|
|
#include "lstxtwrd.h"
#include "lstxtmap.h"
#include "txtils.h"
#include "txtln.h"
#include "txtobj.h"
#define min(a,b) ((a) > (b) ? (b) : (a))
#define max(a,b) ((a) < (b) ? (b) : (a))
#define SqueezingFactorShift 2
static long GetNumberOfSpaces(const LSGRCHNK* plsgrchnk, long itxtobjAfterStartSpaces, long iwchAfterStartSpaces, long itxtobjLast, long iwchLast);
static void DistributeInDobjsSpaces(const LSGRCHNK* plsgrchnk, long itxtobjAfterStartSpaces, long iwchAfterStartSpaces, long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind, long duAdd, long wDuBound);
static void GetSqueezingInfo(const LSGRCHNK* plsgrchnk, long itxtobjAfterStartSpaces, long iwchAfterStartSpaces, long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind, long* pNumOfSpaces, long* pduForSqueezing);
static void SqueezeInDobjs(const LSGRCHNK* plsgrchnk, long itxtobjAfterStartSpaces, long iwchAfterStartSpaces, long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind, long duSubstr, long wDuBound);
/* F U L L P O S I T I V E J U S T I F I C A T I O N */ /*----------------------------------------------------------------------------
%%Function: FullPositiveJustification %%Contact: sergeyge
Performs positive distribution in spaces.
Since amount to distribute is not nesessary divisible by number of spaces, additional pixels (wDupBound, wDurBound) are distributed among first wDupBound/wDurBound spaces.
Leading spaces do not participate. ----------------------------------------------------------------------------*/ void FullPositiveSpaceJustification(const LSGRCHNK* plsgrchnk, long itxtobjAfterStartSpaces, long iwchAfterStartSpaces, long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind, long duToDistribute, BOOL* pfSpacesFound) { long NumOfSpaces; long duAdd; long wDuBound;
Assert(duToDistribute > 0); NumOfSpaces = GetNumberOfSpaces(plsgrchnk, itxtobjAfterStartSpaces, iwchAfterStartSpaces, itxtobjLast, iwchLast); if (NumOfSpaces > 0) {
duAdd = duToDistribute / NumOfSpaces;
wDuBound = duToDistribute - (duAdd * NumOfSpaces);
DistributeInDobjsSpaces(plsgrchnk, itxtobjAfterStartSpaces, iwchAfterStartSpaces, itxtobjLast, iwchLast, rgdu, rgduGind, duAdd, wDuBound); }
*pfSpacesFound = (NumOfSpaces > 0); }
/* N E G A T I V E S P A C E J U S T I F I C A T I O N */ /*----------------------------------------------------------------------------
%%Function: NegativeSpaceJustification %%Contact: sergeyge
Performs squeezing into spaces if it is possible. If it is impossible squeezes in as much as it can ----------------------------------------------------------------------------*/ void NegativeSpaceJustification(const LSGRCHNK* plsgrchnk, long itxtobjAfterStartSpaces, long iwchAfterStartSpaces, long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind, long duToSqueeze) { long NumOfSpaces; long duForSqueezing; long duSubstr; long wDuBound;
Assert(duToSqueeze > 0);
GetSqueezingInfo(plsgrchnk, itxtobjAfterStartSpaces, iwchAfterStartSpaces, itxtobjLast, iwchLast, rgdu, rgduGind, &NumOfSpaces, &duForSqueezing);
/* We cannot squeeze more tha we can */ if (duForSqueezing < duToSqueeze) duToSqueeze = duForSqueezing;
/* dupSubstr shows how much should be subtracted from maximum squeezing
each space provides. wDupBound--from how many spaces additional pixel should be subtracted */ if (NumOfSpaces > 0) { duSubstr = (duForSqueezing - duToSqueeze) / NumOfSpaces; wDuBound = (duForSqueezing - duToSqueeze) - duSubstr * NumOfSpaces;
Assert(duSubstr >= 0); Assert(wDuBound >= 0); SqueezeInDobjs(plsgrchnk, itxtobjAfterStartSpaces, iwchAfterStartSpaces, itxtobjLast, iwchLast, rgdu, rgduGind, duSubstr, wDuBound); }
return; }
/* Internal Functions Implementation */
/* G E T N U M B E R O F S P A C E S */ /*----------------------------------------------------------------------------
%%Function: GetNumberOfSpaces %%Contact: sergeyge
Reports amount of spaces for distribution. ----------------------------------------------------------------------------*/ static long GetNumberOfSpaces(const LSGRCHNK* plsgrchnk, long itxtobjAfterStartSpaces, long iwchAfterStartSpaces, long itxtobjLast, long iwchLast) { long NumOfSpaces; PTXTOBJ ptxtobj; PILSOBJ pilsobj; long* rgwSpaces; long iwSpacesFirst; long iwSpacesLim; long iwSpaces; long iwchFirst; long iwchLim; long itxtobj;
ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[0].pdobj; pilsobj = ptxtobj->plnobj->pilsobj; rgwSpaces = pilsobj->pwSpaces;
NumOfSpaces = 0;
for (itxtobj = itxtobjAfterStartSpaces; itxtobj <= itxtobjLast; itxtobj++) { ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[itxtobj].pdobj;
if (ptxtobj->txtkind == txtkindRegular) { iwSpacesFirst = ptxtobj->u.reg.iwSpacesFirst; iwSpacesLim = ptxtobj->u.reg.iwSpacesLim;
iwchFirst = iwchAfterStartSpaces; if (itxtobj > itxtobjAfterStartSpaces) iwchFirst = ptxtobj->iwchFirst;
iwchLim = iwchLast + 1; if (itxtobj < itxtobjLast) iwchLim = ptxtobj->iwchLim;
while (iwSpacesFirst < iwSpacesLim && rgwSpaces[iwSpacesFirst] < iwchFirst) { iwSpacesFirst++; }
while (iwSpacesLim > iwSpacesFirst && rgwSpaces[iwSpacesLim-1] >= iwchLim) { iwSpacesLim--; } if (ptxtobj->txtf & txtfGlyphBased) { for (iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++) if (FIwchOneToOne(pilsobj, rgwSpaces[iwSpaces])) NumOfSpaces++; } else NumOfSpaces += (iwSpacesLim - iwSpacesFirst); } }
return NumOfSpaces; }
/* D I S T R I B U T E I N D O B J S */ /*----------------------------------------------------------------------------
%%Function: DistributeInDobjs %%Contact: sergeyge
Performs distribution in dobjs, based on precalculated information. ----------------------------------------------------------------------------*/ static void DistributeInDobjsSpaces(const LSGRCHNK* plsgrchnk, long itxtobjAfterStartSpaces, long iwchAfterStartSpaces, long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind, long duAdd, long wDuBound) { PTXTOBJ ptxtobj; PILSOBJ pilsobj; PLNOBJ plnobj; long* rgwSpaces; long iwSpacesFirst; long iwSpacesLim; long iwchFirst; long iwchLim; long CurSpace; long itxtobj; long iwSpaces; long igind; long CurSpaceForSecondLoop;
plnobj = ((PTXTOBJ)(plsgrchnk->plschnk[0].pdobj))->plnobj; pilsobj = plnobj->pilsobj; rgwSpaces = pilsobj->pwSpaces; CurSpace = 0; for (itxtobj = itxtobjAfterStartSpaces; itxtobj <= itxtobjLast ; itxtobj++) { ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[itxtobj].pdobj;
if (ptxtobj->txtkind == txtkindRegular) { iwSpacesFirst = ptxtobj->u.reg.iwSpacesFirst; iwSpacesLim = ptxtobj->u.reg.iwSpacesLim;
iwchFirst = iwchAfterStartSpaces; if (itxtobj > itxtobjAfterStartSpaces) iwchFirst = ptxtobj->iwchFirst;
iwchLim = iwchLast + 1; if (itxtobj < itxtobjLast) iwchLim = ptxtobj->iwchLim;
while (iwSpacesFirst < iwSpacesLim && rgwSpaces[iwSpacesFirst] < iwchFirst) { iwSpacesFirst++; }
while (iwSpacesLim > iwSpacesFirst && rgwSpaces[iwSpacesLim-1] >= iwchLim) { iwSpacesLim--; }
if (ptxtobj->txtf & txtfGlyphBased) { Assert(rgduGind != NULL); for(iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++) { if (FIwchOneToOne(pilsobj, rgwSpaces[iwSpaces])) { igind = IgindFirstFromIwch(ptxtobj, rgwSpaces[iwSpaces]); if (CurSpace < wDuBound) { rgduGind[igind] += (duAdd + 1); pilsobj->pduGright[igind] += (duAdd + 1); } else { rgduGind[igind] += duAdd; pilsobj->pduGright[igind] += duAdd; }
CurSpace++; }
} } else { CurSpaceForSecondLoop = CurSpace;
for(iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++) { if (CurSpace < wDuBound) { rgdu[rgwSpaces[iwSpaces]] += (duAdd + 1); } else { rgdu[rgwSpaces[iwSpaces]] += duAdd; }
CurSpace++; } if (pilsobj->fNotSimpleText) { for(iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++) { if (CurSpaceForSecondLoop < wDuBound) { pilsobj->pdurRight[rgwSpaces[iwSpaces]] += (duAdd + 1); } else { pilsobj->pdurRight[rgwSpaces[iwSpaces]] += duAdd; }
CurSpaceForSecondLoop++; } } } } }
}
/* G E T S Q U E E Z I N G I N F O */ /*----------------------------------------------------------------------------
%%Function: GetSqueezingInfo %%Contact: sergeyge
Calculates maximum amount of pixels to squeeze into spaces. Leading spaces are used for squeezing. ----------------------------------------------------------------------------*/ static void GetSqueezingInfo(const LSGRCHNK* plsgrchnk, long itxtobjAfterStartSpaces, long iwchAfterStartSpaces, long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind, long* pNumOfSpaces, long* pduForSqueezing) { PTXTOBJ ptxtobj; PLNOBJ plnobj; PILSOBJ pilsobj; long* rgwSpaces; long iwSpacesFirst; long iwSpacesLim; long iwchFirst; long iwchLim; long itxtobj; long iwSpaces;
ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[0].pdobj; plnobj = ptxtobj->plnobj; pilsobj = plnobj->pilsobj; rgwSpaces = pilsobj->pwSpaces;
*pNumOfSpaces = 0; *pduForSqueezing = 0;
for (itxtobj = itxtobjAfterStartSpaces; itxtobj <= itxtobjLast ; itxtobj++) {
ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[itxtobj].pdobj;
if (! (ptxtobj->txtf & txtfMonospaced) ) {
if (ptxtobj->txtkind == txtkindRegular) { iwSpacesFirst = ptxtobj->u.reg.iwSpacesFirst; iwSpacesLim = ptxtobj->u.reg.iwSpacesLim;
iwchFirst = iwchAfterStartSpaces; if (itxtobj > itxtobjAfterStartSpaces) iwchFirst = ptxtobj->iwchFirst;
iwchLim = iwchLast + 1; if (itxtobj < itxtobjLast) iwchLim = ptxtobj->iwchLim;
while (iwSpacesFirst < iwSpacesLim && rgwSpaces[iwSpacesFirst] < iwchFirst) { iwSpacesFirst++; }
while (iwSpacesLim > iwSpacesFirst && rgwSpaces[iwSpacesLim-1] >= iwchLim) { iwSpacesLim--; }
if (ptxtobj->txtf & txtfGlyphBased) { for (iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++) { if (FIwchOneToOne(pilsobj, rgwSpaces[iwSpaces])) { (*pduForSqueezing) += rgduGind[IgindFirstFromIwch(ptxtobj,rgwSpaces[iwSpaces])] >> SqueezingFactorShift; (*pNumOfSpaces)++; } } } else { for (iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++) { (*pduForSqueezing) += rgdu[rgwSpaces[iwSpaces]] >> SqueezingFactorShift; } (*pNumOfSpaces) += (iwSpacesLim - iwSpacesFirst); } } }
} }
/* S Q U E E Z E I N D O B J S */ /*----------------------------------------------------------------------------
%%Function: SqueezeInDobjs %%Contact: sergeyge
Performs squeezing in dobjs, based on precalculated information ----------------------------------------------------------------------------*/ static void SqueezeInDobjs(const LSGRCHNK* plsgrchnk, long itxtobjAfterStartSpaces, long iwchAfterStartSpaces, long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind, long duSubstr, long wDuBound) { PTXTOBJ ptxtobj; PLNOBJ plnobj; PILSOBJ pilsobj; long* rgwSpaces; long iwSpacesFirst; long iwSpacesLim; long iwchFirst; long iwchLim; long duChange; long CurSpace; long itxtobj; long iwSpaces; long igind; long CurSpaceForSecondLoop;
ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[0].pdobj; plnobj = ptxtobj->plnobj; pilsobj = plnobj->pilsobj; rgwSpaces = pilsobj->pwSpaces; CurSpace = 0;
for (itxtobj = itxtobjAfterStartSpaces; itxtobj <= itxtobjLast; itxtobj++) {
ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[itxtobj].pdobj;
if (! (ptxtobj->txtf & txtfMonospaced) ) {
if (ptxtobj->txtkind == txtkindRegular) { iwSpacesFirst = ptxtobj->u.reg.iwSpacesFirst; iwSpacesLim = ptxtobj->u.reg.iwSpacesLim;
iwchFirst = iwchAfterStartSpaces; if (itxtobj > itxtobjAfterStartSpaces) iwchFirst = ptxtobj->iwchFirst;
iwchLim = iwchLast + 1; if (itxtobj < itxtobjLast) iwchLim = ptxtobj->iwchLim;
while (iwSpacesFirst < iwSpacesLim && rgwSpaces[iwSpacesFirst] < iwchFirst) { iwSpacesFirst++; }
while (iwSpacesLim > iwSpacesFirst && rgwSpaces[iwSpacesLim-1] >= iwchLim) { iwSpacesLim--; }
if (ptxtobj->txtf & txtfGlyphBased) { for(iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++) { if (FIwchOneToOne(pilsobj, rgwSpaces[iwSpaces])) { igind = IgindFirstFromIwch(ptxtobj, rgwSpaces[iwSpaces]); duChange = -(rgduGind[igind] >> SqueezingFactorShift) + duSubstr; if (CurSpace < wDuBound) { duChange += 1; }
rgduGind[igind] += duChange; pilsobj->pduGright[igind] += duChange;
CurSpace++;
} } } else { CurSpaceForSecondLoop = CurSpace; for(iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++) { duChange = -(rgdu[rgwSpaces[iwSpaces]] >> SqueezingFactorShift) + duSubstr; if (CurSpace < wDuBound) { duChange += 1; }
rgdu[rgwSpaces[iwSpaces]] += duChange;
CurSpace++;
} if (pilsobj->fNotSimpleText) {
for(iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++) { duChange = -(rgdu[rgwSpaces[iwSpaces]] >> SqueezingFactorShift) + duSubstr; if (CurSpaceForSecondLoop < wDuBound) { duChange += 1; }
pilsobj->pdurRight[rgwSpaces[iwSpaces]] += duChange;
CurSpaceForSecondLoop++;
} } } } }
}
}
|