1298 lines
36 KiB
C
1298 lines
36 KiB
C
|
#include "lsmem.h"
|
||
|
|
||
|
#include "lstxtcmp.h"
|
||
|
#include "lstxtmod.h"
|
||
|
#include "lstxtmap.h"
|
||
|
|
||
|
#include "lschp.h"
|
||
|
#include "lspract.h"
|
||
|
#include "lsems.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))
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
long rgdurPrior[2];
|
||
|
long rgcExpPrior[2];
|
||
|
long cExpOppr;
|
||
|
} EXPINFO;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
long durComp;
|
||
|
long cCompOppr;
|
||
|
} COMPINFO;
|
||
|
|
||
|
|
||
|
static LSERR GetExpandInfo(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, BOOL fScaled,
|
||
|
long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLim, EXPINFO* pexpinfo);
|
||
|
static void GetCompressInfo(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
|
||
|
long itxtobjLast, long iwchLim, COMPINFO* pcompinfo);
|
||
|
static LSERR CheckExpandSpace(PILSOBJ pilsobj, LSEMS* plsems, long iwchPrev, long iwch, long iwchNext,
|
||
|
PTXTOBJ ptxtobjCur, PLSRUN plsrunPrev, PLSRUN plsrunCur, PLSRUN plsrunNext,
|
||
|
BOOL* pfExpandOpp, long* pdurChange);
|
||
|
static LSERR CheckExpandOnRun(PILSOBJ pilsobj, LSEMS* plsems, long iwch, long iwchNext, PTXTOBJ ptxtobjCur,
|
||
|
PLSRUN plsrunCur, PLSRUN plsrunNext, BOOL* pfExpandOpp, long* pdurChange);
|
||
|
static void ApplyPriorCompression(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
|
||
|
long itxtobjLast, long iwchLim, BYTE prior,
|
||
|
long durToCompress, long durAvailable, long cExpOppr);
|
||
|
static void ApplyPriorExpansion(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
|
||
|
long txtobjLast, long iwchLim, BYTE prior, long durToExpand, long durAvailable, long cExpOppr);
|
||
|
static void ApplyFullExpansion(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
|
||
|
long itxtobjLast, long iwchLim, long durToExpand, long cExpOppr, long cNonText, long* pdurNonText);
|
||
|
static LSERR CheckCompSpace(PILSOBJ pilsobj, LSEMS* plsems, long iwchPrev, long iwch, long iwchNext,
|
||
|
PTXTOBJ ptxtobjCur, PLSRUN plsrunPrev, PLSRUN plsrunCur, PLSRUN plsrunNext, long* pdurChange);
|
||
|
static LSERR CheckCompOnRun(PILSOBJ pilsobj, LSEMS* plsems, long iwch, long iwchNext, PTXTOBJ ptxtobjCur,
|
||
|
PLSRUN plsrunCur, PLSRUN plsrunNext, long* pdurChange);
|
||
|
static void SetComp(PILSOBJ pilsobj, long iwch, BYTE prior, BYTE side, long durChange);
|
||
|
static BOOL GetNextRun(const LSGRCHNK* plsgrchnk, long itxtobj, long* pitxtobjNext);
|
||
|
static void GetPrevCharRun(const LSGRCHNK* plsgrchnk, long itxtobj, long iwch, long* piwchPrev, PLSRUN* pplsrunPrev);
|
||
|
|
||
|
/* F E T C H C O M P R E S S I N F O */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: FetchCompressInfo
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Fetches compression information until durCompressMaxStop exceeded
|
||
|
---------------------------------------------------------------------------*/
|
||
|
LSERR FetchCompressInfo(const LSGRCHNK* plsgrchnk, BOOL fFirstOnLine, LSTFLOW lstflow,
|
||
|
long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLim,
|
||
|
long durCompressMaxStop, long* pdurCompressTotal)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
PILSOBJ pilsobj;
|
||
|
TXTINF* rgtxtinf;
|
||
|
WCHAR* rgwchOrig;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
PLSRUN plsrunCur;
|
||
|
PLSRUN plsrunPrev;
|
||
|
PLSRUN plsrunNext = NULL;
|
||
|
PCLSCHP plschp;
|
||
|
LSPRACT lspract;
|
||
|
BYTE side;
|
||
|
BYTE sideFinal;
|
||
|
long durChange;
|
||
|
long durTemp;
|
||
|
LSEMS lsems;
|
||
|
BOOL fNextAdjacentFound;
|
||
|
long itxtobj;
|
||
|
long itxtobjNext;
|
||
|
long itxtobjLastProcessed;
|
||
|
long itxtobjCompressFetchedLim;
|
||
|
long iwchCompressFetchedLim;
|
||
|
long iwchLimDobj;
|
||
|
long iwch;
|
||
|
long iwchPrev;
|
||
|
long iwchNext;
|
||
|
BOOL fGlyphBased;
|
||
|
|
||
|
*pdurCompressTotal = 0;
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
|
||
|
rgtxtinf = pilsobj->ptxtinf;
|
||
|
/* rgtxtinf == NULL means that there were no runs which possibly could introduce compress opportunity */
|
||
|
if (rgtxtinf == NULL)
|
||
|
return lserrNone;
|
||
|
|
||
|
iwch = iwchFirst;
|
||
|
|
||
|
rgwchOrig = pilsobj->pwchOrig;
|
||
|
|
||
|
itxtobjCompressFetchedLim = 0;
|
||
|
iwchCompressFetchedLim = 0;
|
||
|
|
||
|
if (pilsobj->iwchCompressFetchedFirst == iwchFirst)
|
||
|
{
|
||
|
itxtobjCompressFetchedLim = pilsobj->itxtobjCompressFetchedLim;
|
||
|
iwchCompressFetchedLim = pilsobj->iwchCompressFetchedLim;
|
||
|
}
|
||
|
|
||
|
itxtobj = itxtobjFirst;
|
||
|
itxtobjLastProcessed = itxtobj-1;
|
||
|
|
||
|
if (itxtobj < (long)plsgrchnk->clsgrchnk)
|
||
|
GetNextRun(plsgrchnk, itxtobj, &itxtobj);
|
||
|
|
||
|
Assert( itxtobj == (long)plsgrchnk->clsgrchnk ||
|
||
|
((PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj)->iwchLim >
|
||
|
((PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj)->iwchFirst);
|
||
|
|
||
|
while(itxtobj <= itxtobjLast && *pdurCompressTotal < durCompressMaxStop)
|
||
|
{
|
||
|
itxtobjLastProcessed = itxtobj;
|
||
|
|
||
|
fNextAdjacentFound = GetNextRun(plsgrchnk, itxtobj + 1, &itxtobjNext);
|
||
|
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
plsrunCur = plsgrchnk->plschnk[itxtobj].plsrun;
|
||
|
plschp = plsgrchnk->plschnk[itxtobj].plschp;
|
||
|
|
||
|
iwchLimDobj = iwchLim;
|
||
|
if (itxtobj < itxtobjLast)
|
||
|
iwchLimDobj = ptxtobj->iwchLim;
|
||
|
|
||
|
if (itxtobj > itxtobjCompressFetchedLim - 1 ||
|
||
|
itxtobj == itxtobjCompressFetchedLim - 1 && iwchLimDobj > iwchCompressFetchedLim)
|
||
|
{
|
||
|
lserr = (*pilsobj->plscbk->pfnGetEms)(pilsobj->pols, plsrunCur, lstflow, &lsems);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
}
|
||
|
|
||
|
iwch = iwchFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwch = ptxtobj->iwchFirst;
|
||
|
|
||
|
for (; iwch < iwchLimDobj && *pdurCompressTotal < durCompressMaxStop; iwch++)
|
||
|
{
|
||
|
if (itxtobj < itxtobjCompressFetchedLim - 1 ||
|
||
|
itxtobj == itxtobjCompressFetchedLim - 1 && iwch < iwchCompressFetchedLim)
|
||
|
{
|
||
|
if (rgtxtinf[iwch].prior != prior0)
|
||
|
*pdurCompressTotal -= pilsobj->pduAdjust[iwch];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
fGlyphBased = (ptxtobj->txtf & txtfGlyphBased);
|
||
|
rgtxtinf[iwch].prior = prior0;
|
||
|
|
||
|
if (!fGlyphBased && plschp->fCompressTable && !rgtxtinf[iwch].fModWidthOnRun &&
|
||
|
!rgtxtinf[iwch].fModWidthSpace)
|
||
|
{
|
||
|
lspract = pilsobj->plspract[pilsobj->pilspract[rgtxtinf[iwch].mwcls]];
|
||
|
Assert(lspract.prior <= pilsobj->cCompPrior);
|
||
|
if (lspract.prior != prior0)
|
||
|
{
|
||
|
GetChanges(lspract.lsact, &lsems, pilsobj->pdur[iwch] - pilsobj->pdurRight[iwch] - pilsobj->pdurLeft[iwch],
|
||
|
fFalse, &side, &durTemp);
|
||
|
TranslateChanges(side, durTemp, pilsobj->pdur[iwch], pilsobj->pdurRight[iwch], pilsobj->pdurLeft[iwch],
|
||
|
&sideFinal, &durChange);
|
||
|
if (sideFinal != sideNone && durChange < 0)
|
||
|
{
|
||
|
if (itxtobj > itxtobjFirst || itxtobj == itxtobjFirst && iwch > iwchFirst ||
|
||
|
!fFirstOnLine || sideFinal != sideLeft)
|
||
|
{
|
||
|
SetComp(pilsobj, iwch, lspract.prior, sideFinal, durChange);
|
||
|
*pdurCompressTotal -= durChange;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (rgwchOrig[iwch] == pilsobj->wchSpace && plschp->fCompressSpace &&
|
||
|
rgtxtinf[iwch].prior == prior0 && (!fGlyphBased || FIwchOneToOne(pilsobj, iwch)))
|
||
|
{
|
||
|
plsrunNext = NULL;
|
||
|
iwchNext = 0;
|
||
|
/* we take ptxtobj->iwchLim instead of iwchLimDobj because iwchLimDobj char(last char
|
||
|
before spaces on the line must be used for context considerations
|
||
|
*/
|
||
|
if (iwch < ptxtobj->iwchLim - 1)
|
||
|
{
|
||
|
plsrunNext = plsrunCur;
|
||
|
iwchNext = iwch + 1;
|
||
|
}
|
||
|
else if (fNextAdjacentFound)
|
||
|
{
|
||
|
plsrunNext = plsgrchnk->plschnk[itxtobjNext].plsrun;
|
||
|
iwchNext = ((PTXTOBJ)plsgrchnk->plschnk[itxtobjNext].pdobj)->iwchFirst;
|
||
|
}
|
||
|
|
||
|
GetPrevCharRun(plsgrchnk, itxtobj, iwch, &iwchPrev, &plsrunPrev);
|
||
|
|
||
|
lserr = CheckCompSpace(pilsobj, &lsems, iwchPrev, iwch, iwchNext, ptxtobj,
|
||
|
plsrunPrev, plsrunCur, plsrunNext, &durChange);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
*pdurCompressTotal -= durChange;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (iwch == ptxtobj->iwchLim - 1 && plschp->fCompressOnRun && fNextAdjacentFound &&
|
||
|
rgtxtinf[iwch].prior == prior0)
|
||
|
{
|
||
|
plsrunNext = plsgrchnk->plschnk[itxtobjNext].plsrun;
|
||
|
iwchNext = ((PTXTOBJ)plsgrchnk->plschnk[itxtobjNext].pdobj)->iwchFirst;
|
||
|
lserr = CheckCompOnRun(pilsobj, &lsems, iwch, iwchNext, ptxtobj, plsrunCur, plsrunNext, &durChange);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
*pdurCompressTotal -= durChange;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
itxtobj = itxtobjNext;
|
||
|
|
||
|
}
|
||
|
|
||
|
pilsobj->iwchCompressFetchedFirst = iwchFirst;
|
||
|
pilsobj->itxtobjCompressFetchedLim = itxtobjLastProcessed + 1;
|
||
|
pilsobj->iwchCompressFetchedLim = min(iwch, iwchLim);
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* G E T C O M P L A S T C H A R I N F O */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: GetCompLastCharInfo
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
---------------------------------------------------------------------------*/
|
||
|
void GetCompLastCharInfo(PILSOBJ pilsobj, long iwchLast, MWCLS* pmwcls,
|
||
|
long* pdurCompRight, long* pdurCompLeft)
|
||
|
{
|
||
|
/* Strong assumption for this function is that it is not called on GlyphBased run */
|
||
|
TXTINF txtinf;
|
||
|
|
||
|
*pdurCompRight = 0;
|
||
|
*pdurCompLeft = 0;
|
||
|
|
||
|
/* ptxtinf == NULL means that there were no runs which possibly can introduce compress opportunity */
|
||
|
if (pilsobj->ptxtinf == NULL)
|
||
|
return;
|
||
|
|
||
|
txtinf = pilsobj->ptxtinf[iwchLast];
|
||
|
|
||
|
*pmwcls = (MWCLS)txtinf.mwcls;
|
||
|
|
||
|
if (txtinf.prior != prior0)
|
||
|
{
|
||
|
InterpretChanges(pilsobj, iwchLast, (BYTE)txtinf.side, pilsobj->pduAdjust[iwchLast], pdurCompLeft, pdurCompRight);
|
||
|
Assert(pilsobj->pduAdjust[iwchLast] == *pdurCompLeft + *pdurCompRight);
|
||
|
}
|
||
|
|
||
|
*pdurCompLeft = - *pdurCompLeft;
|
||
|
*pdurCompRight = - *pdurCompRight;
|
||
|
}
|
||
|
|
||
|
/* C O M P R E S S L A S T C H A R R I G H T */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: CompressLastCharRight
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
---------------------------------------------------------------------------*/
|
||
|
void CompressLastCharRight(PILSOBJ pilsobj, long iwchLast, long durToAdjustRight)
|
||
|
{
|
||
|
/* Strong assumption for this function is that it is not called on GlyphBased run */
|
||
|
pilsobj->pdur[iwchLast] -= durToAdjustRight;
|
||
|
|
||
|
Assert(pilsobj->pdurRight != NULL);
|
||
|
Assert(pilsobj->pdurLeft != NULL);
|
||
|
Assert(pilsobj->ptxtinf != NULL);
|
||
|
|
||
|
pilsobj->pdurRight[iwchLast] -= durToAdjustRight;
|
||
|
|
||
|
if (durToAdjustRight > 0 && pilsobj->ptxtinf[iwchLast].prior != prior0)
|
||
|
{
|
||
|
if (pilsobj->ptxtinf[iwchLast].side == sideRight)
|
||
|
{
|
||
|
pilsobj->ptxtinf[iwchLast].prior = prior0;
|
||
|
pilsobj->pduAdjust[iwchLast] = 0;
|
||
|
}
|
||
|
else if (pilsobj->ptxtinf[iwchLast].side == sideLeftRight)
|
||
|
{
|
||
|
pilsobj->ptxtinf[iwchLast].side = sideLeft;
|
||
|
pilsobj->pduAdjust[iwchLast] += durToAdjustRight;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Assert(fFalse);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/* A P P L Y C O M P R E S S */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyCompress
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Applies prioratized compression
|
||
|
---------------------------------------------------------------------------*/
|
||
|
LSERR ApplyCompress(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow,
|
||
|
long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLim, long durToCompress)
|
||
|
{
|
||
|
PILSOBJ pilsobj;
|
||
|
COMPINFO rgcompinfo[5];
|
||
|
COMPINFO* pcompinfo;
|
||
|
BOOL fReleasePcompinfo;
|
||
|
long i;
|
||
|
|
||
|
Unreferenced(lstflow);
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
|
||
|
fReleasePcompinfo = fFalse;
|
||
|
pcompinfo = rgcompinfo;
|
||
|
if (pilsobj->cCompPrior > 5)
|
||
|
{
|
||
|
pcompinfo = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(COMPINFO) * pilsobj->cCompPrior);
|
||
|
if (pcompinfo == NULL)
|
||
|
return lserrOutOfMemory;
|
||
|
else
|
||
|
fReleasePcompinfo = fTrue;
|
||
|
}
|
||
|
|
||
|
GetCompressInfo(plsgrchnk, itxtobjFirst, iwchFirst, itxtobjLast, iwchLim, pcompinfo);
|
||
|
|
||
|
for (i = 0; i < (long)pilsobj->cCompPrior && durToCompress > 0; i++)
|
||
|
{
|
||
|
if (pcompinfo[i].cCompOppr > 0)
|
||
|
{
|
||
|
ApplyPriorCompression(plsgrchnk, itxtobjFirst, iwchFirst, itxtobjLast, iwchLim, (BYTE)(i+1), durToCompress,
|
||
|
pcompinfo[i].durComp, pcompinfo[i].cCompOppr);
|
||
|
durToCompress -= pcompinfo[i].durComp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Following Assert is not compatible with the squeezing mode */
|
||
|
/*Assert(durToCompress <= 0);*/
|
||
|
|
||
|
if (fReleasePcompinfo)
|
||
|
(*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pcompinfo);
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* A P P L Y E X P A N D */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyExpand
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Applies prioratized expansion
|
||
|
---------------------------------------------------------------------------*/
|
||
|
|
||
|
LSERR ApplyExpand(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, BOOL fScaled, long itxtobjFirst, long iwchFirst,
|
||
|
long itxtobjLast, long iwchLim, DWORD cNonTextObjects, long durToExpand,
|
||
|
long* pdurExtNonText, BOOL* pfFinalAdjustNeeded)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
PILSOBJ pilsobj;
|
||
|
EXPINFO expinfo;
|
||
|
long i;
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
|
||
|
*pdurExtNonText = 0;
|
||
|
|
||
|
lserr = GetExpandInfo(plsgrchnk, lstflow, fScaled, itxtobjFirst, iwchFirst, itxtobjLast, iwchLim, &expinfo);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
for (i = 0; i < 2 && durToExpand > 0; i++)
|
||
|
{
|
||
|
if (expinfo.rgcExpPrior[i])
|
||
|
{
|
||
|
ApplyPriorExpansion(plsgrchnk, itxtobjFirst, iwchFirst, itxtobjLast, iwchLim, (BYTE)(i+1), durToExpand,
|
||
|
expinfo.rgdurPrior[i], expinfo.rgcExpPrior[i]);
|
||
|
durToExpand -= expinfo.rgdurPrior[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (durToExpand > 0)
|
||
|
{
|
||
|
ApplyFullExpansion(plsgrchnk, itxtobjFirst, iwchFirst, itxtobjLast, iwchLim, durToExpand,
|
||
|
expinfo.cExpOppr, cNonTextObjects, pdurExtNonText);
|
||
|
|
||
|
}
|
||
|
|
||
|
*pfFinalAdjustNeeded = (expinfo.cExpOppr + cNonTextObjects > 0);
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* A P P L Y D I S T R I B U T I O N */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyDistribution
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Applies equal distribution to text chunk
|
||
|
---------------------------------------------------------------------------*/
|
||
|
void ApplyDistribution(const LSGRCHNK* plsgrchnk, DWORD cNonText,
|
||
|
long durToDistribute, long* pdurNonTextObjects)
|
||
|
{
|
||
|
PILSOBJ pilsobj;
|
||
|
long clschnk;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
long itxtobj;
|
||
|
long iwchFirst;
|
||
|
long iwchLim;
|
||
|
long iwch;
|
||
|
long igind;
|
||
|
long durToAdd;
|
||
|
long cwchToDistribute;
|
||
|
long cwchToDistributeAll;
|
||
|
long wdurBound;
|
||
|
long iwchUsed;
|
||
|
|
||
|
clschnk = (long)plsgrchnk->clsgrchnk;
|
||
|
Assert(clschnk > 0);
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
|
||
|
cwchToDistribute = 0;
|
||
|
|
||
|
|
||
|
for (itxtobj = 0; itxtobj < clschnk; itxtobj++)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
iwchLim = iwchFirst + plsgrchnk->plschnk[itxtobj].dcp;
|
||
|
if (itxtobj == clschnk - 1)
|
||
|
iwchLim--;
|
||
|
if (ptxtobj->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
for (iwch = iwchFirst; iwch < iwchLim; iwch++)
|
||
|
{
|
||
|
if (FIwchLastInContext(pilsobj, iwch))
|
||
|
cwchToDistribute++;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
cwchToDistribute += (iwchLim - iwchFirst);
|
||
|
}
|
||
|
|
||
|
cwchToDistributeAll = cwchToDistribute + cNonText;
|
||
|
|
||
|
*pdurNonTextObjects = 0;
|
||
|
|
||
|
if (cwchToDistributeAll == 0)
|
||
|
return;
|
||
|
|
||
|
*pdurNonTextObjects = durToDistribute * cNonText / cwchToDistributeAll;
|
||
|
|
||
|
durToDistribute -= *pdurNonTextObjects;
|
||
|
|
||
|
if (cwchToDistribute == 0)
|
||
|
return;
|
||
|
|
||
|
durToAdd = durToDistribute / cwchToDistribute;
|
||
|
wdurBound = durToDistribute - durToAdd * cwchToDistribute;
|
||
|
|
||
|
iwchUsed = 0;
|
||
|
|
||
|
for (itxtobj = 0; itxtobj < clschnk; itxtobj++)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
iwchLim = iwchFirst + plsgrchnk->plschnk[itxtobj].dcp;
|
||
|
if (itxtobj == clschnk - 1)
|
||
|
iwchLim--;
|
||
|
|
||
|
if (ptxtobj->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
for (iwch = iwchFirst; iwch < iwchLim; iwch++)
|
||
|
{
|
||
|
if (FIwchLastInContext(pilsobj, iwch))
|
||
|
{
|
||
|
igind = IgindLastFromIwch(ptxtobj, iwch);
|
||
|
igind = IgindBaseFromIgind(pilsobj, igind);
|
||
|
if (iwchUsed < wdurBound)
|
||
|
{
|
||
|
ApplyGlyphChanges(pilsobj, igind, durToAdd + 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ApplyGlyphChanges(pilsobj, igind, durToAdd);
|
||
|
}
|
||
|
iwchUsed++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (iwch = iwchFirst; iwch < iwchLim; iwch++)
|
||
|
{
|
||
|
if (iwchUsed < wdurBound)
|
||
|
{
|
||
|
ApplyChanges(pilsobj, iwch, sideRight, durToAdd + 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ApplyChanges(pilsobj, iwch, sideRight, durToAdd);
|
||
|
}
|
||
|
iwchUsed++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Internal functions implementation */
|
||
|
|
||
|
/* G E T E X P A N D I N F O */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: GetExpandInfo
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Collects expansion information
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static LSERR GetExpandInfo(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, BOOL fScaled,
|
||
|
long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLim, EXPINFO* pexpinfo)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
PILSOBJ pilsobj;
|
||
|
TXTINF* rgtxtinf;
|
||
|
WCHAR* rgwchOrig;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
PLSRUN plsrunCur;
|
||
|
PLSRUN plsrunPrev;
|
||
|
PLSRUN plsrunNext;
|
||
|
PCLSCHP plschp;
|
||
|
long durChange;
|
||
|
LSEMS lsems;
|
||
|
BOOL fNextAdjacentFound;
|
||
|
long itxtobj;
|
||
|
long itxtobjNext;
|
||
|
long iwchLimDobj;
|
||
|
LSEXPAN lsexpan;
|
||
|
long iwch;
|
||
|
long iwchPrev;
|
||
|
long iwchNext;
|
||
|
BOOL fExpandOpp;
|
||
|
BOOL fGlyphBased;
|
||
|
|
||
|
memset(pexpinfo, 0, sizeof(EXPINFO));
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
|
||
|
rgtxtinf = pilsobj->ptxtinf;
|
||
|
/* rgtxtinf == NULL means that there were no runs which possibly can introduce expansion opportunity */
|
||
|
if (rgtxtinf == NULL)
|
||
|
return lserrNone;
|
||
|
|
||
|
rgwchOrig = pilsobj->pwchOrig;
|
||
|
|
||
|
itxtobj = itxtobjFirst;
|
||
|
|
||
|
if (itxtobj < (long)plsgrchnk->clsgrchnk)
|
||
|
GetNextRun(plsgrchnk, itxtobj, &itxtobj);
|
||
|
|
||
|
Assert(itxtobj == (long)plsgrchnk->clsgrchnk ||
|
||
|
((PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj)->iwchLim >
|
||
|
((PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj)->iwchFirst);
|
||
|
|
||
|
while(itxtobj <= itxtobjLast)
|
||
|
{
|
||
|
fNextAdjacentFound = GetNextRun(plsgrchnk, itxtobj + 1, &itxtobjNext);
|
||
|
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
fGlyphBased = (ptxtobj->txtf & txtfGlyphBased);
|
||
|
plsrunCur = plsgrchnk->plschnk[itxtobj].plsrun;
|
||
|
plschp = plsgrchnk->plschnk[itxtobj].plschp;
|
||
|
|
||
|
lserr = (*pilsobj->plscbk->pfnGetEms)(pilsobj->pols, plsrunCur, lstflow, &lsems);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
|
||
|
iwchLimDobj = iwchLim;
|
||
|
if (itxtobj < itxtobjLast)
|
||
|
iwchLimDobj = ptxtobj->iwchLim;
|
||
|
|
||
|
iwch = iwchFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwch = ptxtobj->iwchFirst;
|
||
|
|
||
|
for (; iwch < iwchLimDobj; iwch++)
|
||
|
{
|
||
|
|
||
|
rgtxtinf[iwch].prior = prior0;
|
||
|
|
||
|
if (rgwchOrig[iwch] == pilsobj->wchSpace && plschp->fExpandSpace &&
|
||
|
(!fGlyphBased || FIwchOneToOne(pilsobj, iwch)))
|
||
|
{
|
||
|
plsrunNext = NULL;
|
||
|
iwchNext = 0;
|
||
|
/* we take ptxtobj->iwchLim instead of iwchLimDobj because iwchLimInDobj char(last char
|
||
|
before spaces on the line must be used for context considerations
|
||
|
*/
|
||
|
if (iwch < ptxtobj->iwchLim - 1)
|
||
|
{
|
||
|
plsrunNext = plsrunCur;
|
||
|
iwchNext = iwch + 1;
|
||
|
}
|
||
|
else if (fNextAdjacentFound)
|
||
|
{
|
||
|
plsrunNext = plsgrchnk->plschnk[itxtobjNext].plsrun;
|
||
|
iwchNext = ((PTXTOBJ)plsgrchnk->plschnk[itxtobjNext].pdobj)->iwchFirst;
|
||
|
}
|
||
|
|
||
|
GetPrevCharRun(plsgrchnk, itxtobj, iwch, &iwchPrev, &plsrunPrev);
|
||
|
|
||
|
lserr = CheckExpandSpace(pilsobj, &lsems, iwchPrev, iwch, iwchNext, ptxtobj,
|
||
|
plsrunPrev, plsrunCur, plsrunNext, &fExpandOpp, &durChange);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (fExpandOpp)
|
||
|
{
|
||
|
pexpinfo->cExpOppr++;
|
||
|
rgtxtinf[iwch].fExpand = fTrue;
|
||
|
if (durChange > 0)
|
||
|
{
|
||
|
pexpinfo->rgdurPrior[0] += durChange;
|
||
|
pexpinfo->rgcExpPrior[0]++;
|
||
|
rgtxtinf[iwch].prior = 1;
|
||
|
pilsobj->pduAdjust[iwch] = durChange;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
if (!rgtxtinf[iwch].fExpand && iwch == ptxtobj->iwchLim - 1 && plschp->fExpandOnRun &&
|
||
|
fNextAdjacentFound)
|
||
|
{
|
||
|
plsrunNext = plsgrchnk->plschnk[itxtobjNext].plsrun;
|
||
|
iwchNext = ((PTXTOBJ)plsgrchnk->plschnk[itxtobjNext].pdobj)->iwchFirst;
|
||
|
lserr = CheckExpandOnRun(pilsobj, &lsems, iwch, iwchNext, ptxtobj, plsrunCur, plsrunNext,
|
||
|
&fExpandOpp, &durChange);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (fExpandOpp)
|
||
|
{
|
||
|
pexpinfo->cExpOppr++;
|
||
|
rgtxtinf[iwch].fExpand = fTrue;
|
||
|
if (durChange > 0)
|
||
|
{
|
||
|
pexpinfo->rgdurPrior[1] += durChange;
|
||
|
pexpinfo->rgcExpPrior[1]++;
|
||
|
rgtxtinf[iwch].prior = 2;
|
||
|
pilsobj->pduAdjust[iwch] = durChange;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (!rgtxtinf[iwch].fExpand && iwch == ptxtobj->iwchLim - 1 && !fNextAdjacentFound &&
|
||
|
(plsgrchnk->pcont[itxtobj] & fcontExpandAfter))
|
||
|
{
|
||
|
/* Character before foreign object */
|
||
|
pexpinfo->cExpOppr++;
|
||
|
rgtxtinf[iwch].fExpand = fTrue;
|
||
|
}
|
||
|
|
||
|
if (!rgtxtinf[iwch].fExpand && plschp->fExpandTable)
|
||
|
{
|
||
|
Assert(!fGlyphBased);
|
||
|
if (iwch < ptxtobj->iwchLim - 1)
|
||
|
{
|
||
|
lsexpan = pilsobj->plsexpan[pilsobj->pilsexpan[
|
||
|
pilsobj->cModWidthClasses * rgtxtinf[iwch].mwcls + rgtxtinf[iwch+1].mwcls
|
||
|
]
|
||
|
];
|
||
|
if (fScaled && lsexpan.fFullScaled || !fScaled && lsexpan.fFullInterletter)
|
||
|
{
|
||
|
pexpinfo->cExpOppr++;
|
||
|
rgtxtinf[iwch].fExpand = fTrue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (fNextAdjacentFound && plsgrchnk->plschnk[itxtobjNext].plschp->fExpandTable)
|
||
|
{
|
||
|
Assert(!(((PTXTOBJ)plsgrchnk->plschnk[itxtobjNext].pdobj)->txtf & txtfGlyphBased));
|
||
|
iwchNext = ((PTXTOBJ)plsgrchnk->plschnk[itxtobjNext].pdobj)->iwchFirst;
|
||
|
|
||
|
lsexpan = pilsobj->plsexpan[pilsobj->pilsexpan[
|
||
|
pilsobj->cModWidthClasses * rgtxtinf[iwch].mwcls + rgtxtinf[iwchNext].mwcls
|
||
|
]
|
||
|
];
|
||
|
if (fScaled && lsexpan.fFullScaled || !fScaled && lsexpan.fFullInterletter)
|
||
|
{
|
||
|
pexpinfo->cExpOppr++;
|
||
|
rgtxtinf[iwch].fExpand = fTrue;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
itxtobj = itxtobjNext;
|
||
|
|
||
|
}
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* C H E C K E X P A N D S P A C E */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: CheckExpandSpace
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Reports if there is expansion opportunity on space and amount of expansion
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static LSERR CheckExpandSpace(PILSOBJ pilsobj, LSEMS* plsems, long iwchPrev, long iwch, long iwchNext,
|
||
|
PTXTOBJ ptxtobjCur, PLSRUN plsrunPrev, PLSRUN plsrunCur, PLSRUN plsrunNext,
|
||
|
BOOL* pfExpandOpp, long* pdurChange)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
BYTE side;
|
||
|
LSACT lsact;
|
||
|
long igind;
|
||
|
|
||
|
*pfExpandOpp = fFalse;
|
||
|
*pdurChange = 0;
|
||
|
|
||
|
lserr = (*pilsobj->plscbk->pfnExpWidthSpace)(pilsobj->pols, plsrunCur,
|
||
|
plsrunPrev, pilsobj->pwchOrig[iwchPrev], plsrunNext, pilsobj->pwchOrig[iwchNext], &lsact);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (lsact.side != sideNone)
|
||
|
{
|
||
|
*pfExpandOpp = fTrue;
|
||
|
if (ptxtobjCur->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
igind = IgindLastFromIwch(ptxtobjCur, iwch);
|
||
|
GetChanges(lsact, plsems, pilsobj->pdurGind[igind], fTrue, &side, pdurChange);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GetChanges(lsact, plsems, pilsobj->pdur[iwch], fTrue, &side, pdurChange);
|
||
|
}
|
||
|
|
||
|
Assert(side == sideRight);
|
||
|
|
||
|
if (*pdurChange < 0)
|
||
|
*pdurChange = 0;
|
||
|
}
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* C H E C K E X P A N D O N R U N */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: CheckExpandOnRun
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Reports if there is expansion opportunity between runs and amount of expansion
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static LSERR CheckExpandOnRun(PILSOBJ pilsobj, LSEMS* plsems, long iwch, long iwchNext, PTXTOBJ ptxtobjCur,
|
||
|
PLSRUN plsrunCur, PLSRUN plsrunNext, BOOL* pfExpandOpp, long* pdurChange)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
BYTE side;
|
||
|
LSACT lsact;
|
||
|
long igind;
|
||
|
|
||
|
*pfExpandOpp = fFalse;
|
||
|
*pdurChange = 0;
|
||
|
|
||
|
lserr = (*pilsobj->plscbk->pfnExpOnRun)(pilsobj->pols, plsrunCur, pilsobj->pwchOrig[iwch],
|
||
|
plsrunNext, pilsobj->pwchOrig[iwchNext], &lsact);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (lsact.side != sideNone)
|
||
|
{
|
||
|
*pfExpandOpp = fTrue;
|
||
|
if (ptxtobjCur->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
igind = IgindLastFromIwch(ptxtobjCur, iwch);
|
||
|
igind = IgindBaseFromIgind(pilsobj, igind);
|
||
|
GetChanges(lsact, plsems, pilsobj->pdurGind[igind], fTrue, &side, pdurChange);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GetChanges(lsact, plsems, pilsobj->pdur[iwch], fTrue, &side, pdurChange);
|
||
|
}
|
||
|
Assert(side == sideRight);
|
||
|
if (*pdurChange < 0)
|
||
|
*pdurChange = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* C H E C K C O M P S P A C E */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: CheckCompSpace
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Reports if there is compression opportunity on space and amount of compression
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static LSERR CheckCompSpace(PILSOBJ pilsobj, LSEMS* plsems, long iwchPrev, long iwch, long iwchNext,
|
||
|
PTXTOBJ ptxtobjCur, PLSRUN plsrunPrev, PLSRUN plsrunCur, PLSRUN plsrunNext, long* pdurChange)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
BYTE side;
|
||
|
LSPRACT lspract;
|
||
|
long igind;
|
||
|
|
||
|
*pdurChange = 0;
|
||
|
|
||
|
lserr = (*pilsobj->plscbk->pfnCompWidthSpace)(pilsobj->pols, plsrunCur,
|
||
|
plsrunPrev, pilsobj->pwchOrig[iwchPrev], plsrunNext, pilsobj->pwchOrig[iwchNext], &lspract);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (lspract.prior != prior0)
|
||
|
{
|
||
|
if (ptxtobjCur->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
igind = IgindLastFromIwch(ptxtobjCur, iwch);
|
||
|
GetChanges(lspract.lsact, plsems, pilsobj->pdurGind[igind], fFalse, &side, pdurChange);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GetChanges(lspract.lsact, plsems, pilsobj->pdur[iwch], fFalse, &side, pdurChange);
|
||
|
}
|
||
|
|
||
|
Assert(side == sideRight);
|
||
|
if (*pdurChange < 0)
|
||
|
SetComp(pilsobj, iwch, lspract.prior, side, *pdurChange);
|
||
|
else
|
||
|
*pdurChange = 0;
|
||
|
}
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* C H E C K C O M P O N R U N */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: CheckCompOnRun
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Reports if there is compression opportunity between runs and amount of compression
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static LSERR CheckCompOnRun(PILSOBJ pilsobj, LSEMS* plsems, long iwch, long iwchNext,
|
||
|
PTXTOBJ ptxtobjCur, PLSRUN plsrunCur, PLSRUN plsrunNext, long* pdurChange)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
BYTE side;
|
||
|
LSPRACT lspract;
|
||
|
long igind;
|
||
|
|
||
|
*pdurChange = 0;
|
||
|
|
||
|
lserr = (*pilsobj->plscbk->pfnCompOnRun)(pilsobj->pols, plsrunCur, pilsobj->pwchOrig[iwch],
|
||
|
plsrunNext, pilsobj->pwchOrig[iwchNext], &lspract);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (lspract.prior != prior0)
|
||
|
|
||
|
{
|
||
|
if (ptxtobjCur->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
igind = IgindLastFromIwch(ptxtobjCur, iwch);
|
||
|
igind = IgindBaseFromIgind(pilsobj, igind);
|
||
|
GetChanges(lspract.lsact, plsems, pilsobj->pdurGind[igind], fFalse, &side, pdurChange);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GetChanges(lspract.lsact, plsems, pilsobj->pdur[iwch], fFalse, &side, pdurChange);
|
||
|
}
|
||
|
Assert(side == sideRight);
|
||
|
if (*pdurChange < 0)
|
||
|
SetComp(pilsobj, iwch, lspract.prior, side, *pdurChange);
|
||
|
else
|
||
|
*pdurChange = 0;
|
||
|
}
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* S E T C O M P */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: SetComp
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void SetComp(PILSOBJ pilsobj, long iwch, BYTE prior, BYTE side, long durChange)
|
||
|
{
|
||
|
pilsobj->ptxtinf[iwch].prior = prior;
|
||
|
pilsobj->ptxtinf[iwch].side = side;
|
||
|
pilsobj->pduAdjust[iwch] = durChange;
|
||
|
}
|
||
|
|
||
|
/* G E T N E X T R U N */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: GetNextRun
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static BOOL GetNextRun(const LSGRCHNK* plsgrchnk, long itxtobj, long* pitxtobjNext)
|
||
|
{
|
||
|
long clschnk;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
BOOL fFound;
|
||
|
BOOL fContiguous;
|
||
|
|
||
|
clschnk = (long)plsgrchnk->clsgrchnk;
|
||
|
|
||
|
*pitxtobjNext = clschnk;
|
||
|
|
||
|
fFound = fFalse;
|
||
|
fContiguous = fTrue;
|
||
|
|
||
|
while (!fFound && itxtobj < clschnk)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
fFound = !(ptxtobj->txtf & txtfSkipAtNti);
|
||
|
fContiguous = fContiguous && !(plsgrchnk->pcont[itxtobj] & fcontNonTextBefore);
|
||
|
itxtobj++;
|
||
|
}
|
||
|
|
||
|
if (fFound)
|
||
|
*pitxtobjNext = itxtobj - 1;
|
||
|
|
||
|
return fFound && fContiguous;
|
||
|
}
|
||
|
|
||
|
/* G E T P R E V C H A R R U N */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: GetPrevCharRun
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void GetPrevCharRun(const LSGRCHNK* plsgrchnk, long itxtobj, long iwch, long* piwchPrev,
|
||
|
PLSRUN* pplsrunPrev)
|
||
|
{
|
||
|
BOOL fFound;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
|
||
|
fFound = fFalse;
|
||
|
|
||
|
Assert(itxtobj < (long)plsgrchnk->clsgrchnk);
|
||
|
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
|
||
|
Assert(iwch >= ptxtobj->iwchFirst && iwch < ptxtobj->iwchLim);
|
||
|
|
||
|
*piwchPrev = 0;
|
||
|
*pplsrunPrev = NULL;
|
||
|
if (iwch > ptxtobj->iwchFirst)
|
||
|
{
|
||
|
fFound = fTrue;
|
||
|
*piwchPrev = iwch - 1;
|
||
|
*pplsrunPrev = plsgrchnk->plschnk[itxtobj].plsrun;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (!fFound && itxtobj > 0 && !(plsgrchnk->pcont[itxtobj] & fcontNonTextBefore))
|
||
|
{
|
||
|
itxtobj--;
|
||
|
Assert(itxtobj >= 0);
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
fFound = !(ptxtobj->txtf & txtfSkipAtNti);
|
||
|
if (fFound)
|
||
|
{
|
||
|
*piwchPrev = ((PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj)->iwchLim - 1;
|
||
|
*pplsrunPrev = plsgrchnk->plschnk[itxtobj].plsrun;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* A P P L Y P R I O R E X P A N S I O N */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyPriorExpansion
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Applies expansion on one priority level
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void ApplyPriorExpansion(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
|
||
|
long itxtobjLast, long iwchLim, BYTE prior, long durToExpand, long durAvailable, long cExpOppr)
|
||
|
{
|
||
|
PILSOBJ pilsobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
TXTINF* rgtxtinf;
|
||
|
long* rgdurAdjust;
|
||
|
long durSubstr;
|
||
|
long durChange;
|
||
|
long cBound;
|
||
|
long cOpprCur;
|
||
|
long itxtobj;
|
||
|
long iwch;
|
||
|
long iwchFirstInDobj;
|
||
|
long iwchLimInDobj;
|
||
|
long igind;
|
||
|
BOOL fGlyphBased;
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
rgtxtinf = pilsobj->ptxtinf;
|
||
|
rgdurAdjust = pilsobj->pduAdjust;
|
||
|
|
||
|
Assert(durToExpand > 0);
|
||
|
if (durAvailable == 0)
|
||
|
return;
|
||
|
|
||
|
if (durAvailable < durToExpand)
|
||
|
durToExpand = durAvailable;
|
||
|
|
||
|
Assert(cExpOppr > 0);
|
||
|
|
||
|
durSubstr = (durAvailable - durToExpand) / cExpOppr;
|
||
|
cBound = (durAvailable - durToExpand) - durSubstr * cExpOppr;
|
||
|
|
||
|
cOpprCur = 0;
|
||
|
|
||
|
for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
|
||
|
fGlyphBased = (ptxtobj->txtf & txtfGlyphBased);
|
||
|
|
||
|
|
||
|
iwchFirstInDobj = iwchFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirstInDobj = ptxtobj->iwchFirst;
|
||
|
|
||
|
iwchLimInDobj = iwchLim;
|
||
|
if (itxtobj < itxtobjLast)
|
||
|
iwchLimInDobj = ptxtobj->iwchLim;
|
||
|
|
||
|
for (iwch = iwchFirstInDobj; iwch < iwchLimInDobj; iwch++)
|
||
|
{
|
||
|
if (rgtxtinf[iwch].prior == prior)
|
||
|
{
|
||
|
cOpprCur++;
|
||
|
durChange = rgdurAdjust[iwch] - durSubstr;
|
||
|
if (cOpprCur <= cBound)
|
||
|
durChange--;
|
||
|
if (durChange >= 0)
|
||
|
{
|
||
|
if (fGlyphBased)
|
||
|
{
|
||
|
igind = IgindLastFromIwch(ptxtobj, iwch);
|
||
|
igind = IgindBaseFromIgind(pilsobj, igind);
|
||
|
ApplyGlyphChanges(pilsobj, igind, durChange);
|
||
|
}
|
||
|
else
|
||
|
ApplyChanges(pilsobj, iwch, sideRight, durChange);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/* A P P L Y F U L L E X P A N S I O N */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyFullExpansion
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Applies risidual unlimited expansion
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void ApplyFullExpansion(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
|
||
|
long itxtobjLast, long iwchLim, long durToExpand, long cExpOppr, long cNonText, long* pdurNonText)
|
||
|
{
|
||
|
PILSOBJ pilsobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
TXTINF* rgtxtinf;
|
||
|
long* rgdurAdjust;
|
||
|
long cBound;
|
||
|
long cOpprCur;
|
||
|
long cExpOpprTotal;
|
||
|
long durChange;
|
||
|
long durAdd;
|
||
|
long itxtobj;
|
||
|
long iwch;
|
||
|
long iwchFirstInDobj;
|
||
|
long iwchLimInDobj;
|
||
|
long igind;
|
||
|
BOOL fGlyphBased;
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
rgtxtinf = pilsobj->ptxtinf;
|
||
|
rgdurAdjust = pilsobj->pduAdjust;
|
||
|
|
||
|
*pdurNonText = 0;
|
||
|
|
||
|
cExpOpprTotal = cExpOppr + cNonText;
|
||
|
|
||
|
if (cExpOpprTotal > 0)
|
||
|
{
|
||
|
|
||
|
*pdurNonText = durToExpand * cNonText / cExpOpprTotal;
|
||
|
|
||
|
durToExpand -= *pdurNonText;
|
||
|
|
||
|
if (cExpOppr > 0)
|
||
|
{
|
||
|
|
||
|
durAdd = durToExpand / cExpOppr;
|
||
|
|
||
|
cBound = durToExpand - durAdd * cExpOppr;
|
||
|
|
||
|
cOpprCur = 0;
|
||
|
|
||
|
for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
|
||
|
fGlyphBased = (ptxtobj->txtf & txtfGlyphBased);
|
||
|
|
||
|
iwchFirstInDobj = iwchFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirstInDobj = ptxtobj->iwchFirst;
|
||
|
|
||
|
iwchLimInDobj = iwchLim;
|
||
|
if (itxtobj < itxtobjLast)
|
||
|
iwchLimInDobj = ptxtobj->iwchLim;
|
||
|
|
||
|
for (iwch = iwchFirstInDobj; iwch < iwchLimInDobj; iwch++)
|
||
|
{
|
||
|
if (rgtxtinf[iwch].fExpand)
|
||
|
{
|
||
|
cOpprCur++;
|
||
|
durChange = durAdd;
|
||
|
if (cOpprCur <= cBound)
|
||
|
durChange++;
|
||
|
|
||
|
if (fGlyphBased)
|
||
|
{
|
||
|
igind = IgindLastFromIwch(ptxtobj, iwch);
|
||
|
igind = IgindBaseFromIgind(pilsobj, igind);
|
||
|
ApplyGlyphChanges(pilsobj, igind, durChange);
|
||
|
}
|
||
|
else
|
||
|
ApplyChanges(pilsobj, iwch, sideRight, durChange);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* G E T C O M P R E S S I N F O */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: GetCompressInfo
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Agregates compression information accross for priorities
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void GetCompressInfo(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
|
||
|
long itxtobjLast, long iwchLim, COMPINFO* pcompinfo)
|
||
|
{
|
||
|
PILSOBJ pilsobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
TXTINF* rgtxtinf;
|
||
|
long* rgdurAdjust;
|
||
|
UINT prior;
|
||
|
long cCompPrior;
|
||
|
long itxtobj;
|
||
|
long iwch;
|
||
|
long iwchFirstInDobj;
|
||
|
long iwchLimInDobj;
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
cCompPrior = pilsobj->cCompPrior;
|
||
|
memset(pcompinfo, 0, sizeof(COMPINFO) * cCompPrior);
|
||
|
|
||
|
rgtxtinf = pilsobj->ptxtinf;
|
||
|
rgdurAdjust = pilsobj->pduAdjust;
|
||
|
/* rgtxtinf == NULL means that there were no runs which possibly can introduce compress opportunity */
|
||
|
if (rgtxtinf == NULL)
|
||
|
return;
|
||
|
|
||
|
for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast ; itxtobj++)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
|
||
|
iwchFirstInDobj = iwchFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirstInDobj = ptxtobj->iwchFirst;
|
||
|
|
||
|
iwchLimInDobj = iwchLim;
|
||
|
if (itxtobj < itxtobjLast)
|
||
|
iwchLimInDobj = ptxtobj->iwchLim;
|
||
|
|
||
|
for (iwch = iwchFirstInDobj; iwch < iwchLimInDobj; iwch++)
|
||
|
{
|
||
|
prior = rgtxtinf[iwch].prior;
|
||
|
Assert(prior <= (BYTE)cCompPrior);
|
||
|
if (prior > 0)
|
||
|
{
|
||
|
pcompinfo[prior - 1].cCompOppr++;
|
||
|
pcompinfo[prior - 1].durComp -= rgdurAdjust[iwch];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* A P P L Y P R I O R C O M P R E S S I O N */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyPriorCompression
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Applies compression for one priority level
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void ApplyPriorCompression(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
|
||
|
long itxtobjLast, long iwchLim, BYTE prior,
|
||
|
long durToCompress, long durAvailable, long cExpOppr)
|
||
|
{
|
||
|
PILSOBJ pilsobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
TXTINF* rgtxtinf;
|
||
|
long* rgdurAdjust;
|
||
|
long durSubstr;
|
||
|
long cBound;
|
||
|
long cOpprCur;
|
||
|
long durChange;
|
||
|
long iwch;
|
||
|
long itxtobj;
|
||
|
long igind;
|
||
|
BOOL fGlyphBased;
|
||
|
long iwchFirstInDobj;
|
||
|
long iwchLimInDobj;
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
rgtxtinf = pilsobj->ptxtinf;
|
||
|
rgdurAdjust = pilsobj->pduAdjust;
|
||
|
|
||
|
Assert(durToCompress > 0);
|
||
|
if (durAvailable == 0)
|
||
|
return;
|
||
|
|
||
|
if (durAvailable < durToCompress)
|
||
|
durToCompress = durAvailable;
|
||
|
|
||
|
Assert(cExpOppr > 0);
|
||
|
|
||
|
durSubstr = (durAvailable - durToCompress) / cExpOppr;
|
||
|
cBound = (durAvailable - durToCompress) - durSubstr * cExpOppr;
|
||
|
|
||
|
cOpprCur = 0;
|
||
|
for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
|
||
|
fGlyphBased = (ptxtobj->txtf & txtfGlyphBased);
|
||
|
|
||
|
iwchFirstInDobj = iwchFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirstInDobj = ptxtobj->iwchFirst;
|
||
|
|
||
|
iwchLimInDobj = iwchLim;
|
||
|
if (itxtobj < itxtobjLast)
|
||
|
iwchLimInDobj = ptxtobj->iwchLim;
|
||
|
|
||
|
for (iwch = iwchFirstInDobj; iwch < iwchLimInDobj; iwch++)
|
||
|
{
|
||
|
if (rgtxtinf[iwch].prior == prior)
|
||
|
{
|
||
|
cOpprCur++;
|
||
|
durChange = rgdurAdjust[iwch] + durSubstr;
|
||
|
if (cExpOppr - cBound < cOpprCur)
|
||
|
durChange++;
|
||
|
if (durChange < 0)
|
||
|
{
|
||
|
if (fGlyphBased)
|
||
|
{
|
||
|
igind = IgindLastFromIwch(ptxtobj, iwch);
|
||
|
igind = IgindBaseFromIgind(pilsobj, igind);
|
||
|
ApplyGlyphChanges(pilsobj, igind, durChange);
|
||
|
}
|
||
|
else
|
||
|
ApplyChanges(pilsobj, iwch, (BYTE)rgtxtinf[iwch].side, durChange);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|