1072 lines
33 KiB
C
1072 lines
33 KiB
C
|
#include "lsmem.h"
|
||
|
|
||
|
#include "lstxtglf.h"
|
||
|
|
||
|
#include "lstxtmap.h"
|
||
|
#include "txtils.h"
|
||
|
#include "txtln.h"
|
||
|
#include "txtobj.h"
|
||
|
|
||
|
#include "zqfromza.h"
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
long cWhite;
|
||
|
long duMaxWhite;
|
||
|
long duTotalWhite;
|
||
|
long cContinuous;
|
||
|
long duMaxContinuous;
|
||
|
long duMinContinuous;
|
||
|
long cDiscrete;
|
||
|
long duMaxDiscrete;
|
||
|
} EXPG;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
long cExpginfo;
|
||
|
EXPG* pexpg;
|
||
|
long cResidual;
|
||
|
} EXPGINFO;
|
||
|
|
||
|
#define priorSpace 1
|
||
|
#define priorMax 8
|
||
|
#define cDiscreteMax 25
|
||
|
|
||
|
#define min(a,b) ((a) > (b) ? (b) : (a))
|
||
|
#define max(a,b) ((a) < (b) ? (b) : (a))
|
||
|
|
||
|
static LSERR CollectGlyphExpInfo(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, LSDEVICE lsdev,
|
||
|
long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLast,
|
||
|
long* rgdu, long* rgduGind, EXPGINFO* pexpginfo);
|
||
|
static LSERR ApplyPriorGlyphExp(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, LSDEVICE lsdev,
|
||
|
long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLast,
|
||
|
long prior, long duToDistribute, EXPG* pexpg, long* rgdu, long* rgduGind,
|
||
|
long* rgduRight, long* rgduGright, long* pduDistributed);
|
||
|
LSERR static ApplyDiscrete(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, LSDEVICE lsdev,
|
||
|
long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLast,
|
||
|
long prior, long duToDistribute, long cDiscrete,
|
||
|
long* rgduGind, long* rgduGright, long* pduDistributed);
|
||
|
static void ApplyOneEachContinuous(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
|
||
|
long itxtobjLast, long iwchLast, long prior, long duToDistribute, long cContinuous,
|
||
|
long* rgduGind, long* rgduGright, long* pduDistributed);
|
||
|
static void ApplyFullWhiteContinuous(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLast,
|
||
|
long prior,
|
||
|
long* rgdu, long* rgduGind, long* rgduRight, long* rgduGright, long* pduDistributed);
|
||
|
static void ApplyPropWhiteContinuous(const LSGRCHNK* plsgrchnk, BOOL fWhiteOnly,
|
||
|
long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLast, long prior,
|
||
|
long duToDistribute, long duTotalMin,
|
||
|
long* rgdu, long* rgduGind, long* rgduRight, long* rgduGright, long* pduDistributed);
|
||
|
static void ApplyResidualGlyphExp(const LSGRCHNK* plsgrchnk, long itxtobjFirst,
|
||
|
long iwchFirst, long itxtobjLast, long iwchLim, long duToDistribute,
|
||
|
long cResidual, long* rgduGind, long* rgduGright, long* pduDistributed);
|
||
|
static void FixExpt(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchVeryFirst,
|
||
|
long itxtobjLast, long iwchLast, long* rgduGright);
|
||
|
static void CalcExpandChanges(long cWhole, long duDenom, long duRest, long duLocal, long duMax,
|
||
|
long* pduChange, long* pduAddCurrent);
|
||
|
static void ApplyGlyphExpandChanges(long ind, long* rgduGind, long* rgduGright, long* pduDistributed, long duChange);
|
||
|
|
||
|
|
||
|
/* A P P L Y G L Y P H E X P A N D */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyGlyphExpand
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Applies glyph expansion
|
||
|
First collects information about expansion opportunities
|
||
|
Then applies expansion according to priorities
|
||
|
If it is not sufficient, applies risidual expansion
|
||
|
----------------------------------------------------------------------------*/
|
||
|
LSERR ApplyGlyphExpand(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, LSDEVICE lsdev,
|
||
|
long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLast,
|
||
|
long duToDistribute, long* rgdu, long* rgduGind, long* rgduRight, long* rgduGright,
|
||
|
BOOL* pfFullyJustified)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
PILSOBJ pilsobj;
|
||
|
EXPGINFO expginfo;
|
||
|
EXPG rgexpg[priorMax];
|
||
|
long duDistributed;
|
||
|
long i;
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
|
||
|
expginfo.pexpg = rgexpg;
|
||
|
expginfo.cExpginfo = priorMax;
|
||
|
|
||
|
lserr = CollectGlyphExpInfo(plsgrchnk, lstflow, lsdev,
|
||
|
itxtobjFirst, iwchFirst, itxtobjLast, iwchLast, rgdu, rgduGind, &expginfo);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
for (i = 0; i < priorMax && duToDistribute > 0; i++)
|
||
|
{
|
||
|
lserr = ApplyPriorGlyphExp(plsgrchnk, lstflow, lsdev, itxtobjFirst, iwchFirst, itxtobjLast, iwchLast,
|
||
|
i + 1, duToDistribute, &expginfo.pexpg[i], rgdu, rgduGind, rgduRight, rgduGright,
|
||
|
&duDistributed);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
Assert(duDistributed <= duToDistribute);
|
||
|
duToDistribute -= duDistributed;
|
||
|
}
|
||
|
|
||
|
FixExpt(plsgrchnk, itxtobjFirst, iwchFirst, itxtobjLast, iwchLast, rgduGright);
|
||
|
|
||
|
if (duToDistribute > 0 && expginfo.cResidual > 0)
|
||
|
{
|
||
|
ApplyResidualGlyphExp(plsgrchnk, itxtobjFirst, iwchFirst, itxtobjLast, iwchLast, duToDistribute,
|
||
|
expginfo.cResidual, rgduGind, rgduGright, &duDistributed);
|
||
|
Assert(duDistributed == duToDistribute);
|
||
|
duToDistribute = 0;
|
||
|
}
|
||
|
|
||
|
*pfFullyJustified = (duToDistribute == 0);
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* C O L L E C T G L Y P H E X P I N F O */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: CollectGlyphExpInfo
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Collects expansion information and agreagated values for
|
||
|
the expansion algorithm.
|
||
|
Spaces from character-based runs contribute as expansion opportunities
|
||
|
of exptAddWhiteSpace type with prior==priorSpace and duMax==lsexpinfInfinity
|
||
|
----------------------------------------------------------------------------*/
|
||
|
static LSERR CollectGlyphExpInfo(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, LSDEVICE lsdev,
|
||
|
long itxtobjFirst, long iwchVeryFirst, long itxtobjLast, long iwchLast,
|
||
|
long* rgdu, long* rgduGind, EXPGINFO* pexpginfo)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
PILSOBJ pilsobj;
|
||
|
PLNOBJ plnobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
PTXTOBJ ptxtobjLast;
|
||
|
PLSRUN plsrun;
|
||
|
LSEXPINFO* plsexpinf;
|
||
|
EXPTYPE* pexpt;
|
||
|
long itxtobj;
|
||
|
long iwchFirst;
|
||
|
long iwchLim;
|
||
|
long igindFirst;
|
||
|
long igindLim;
|
||
|
long igind;
|
||
|
long iwSpace;
|
||
|
|
||
|
memset(pexpginfo->pexpg, 0, sizeof(EXPG) * pexpginfo->cExpginfo);
|
||
|
pexpginfo->cResidual = 0;
|
||
|
|
||
|
ptxtobjLast = (PTXTOBJ)plsgrchnk->plschnk[max(0, itxtobjLast)].pdobj;
|
||
|
plnobj = ptxtobjLast->plnobj;
|
||
|
pilsobj = plnobj->pilsobj;
|
||
|
|
||
|
itxtobj = itxtobjFirst;
|
||
|
|
||
|
plsexpinf = pilsobj->plsexpinf;
|
||
|
pexpt = plnobj->pexpt;
|
||
|
|
||
|
while (itxtobj <= itxtobjLast)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
if (ptxtobj->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
iwchFirst = iwchVeryFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
Assert(iwchFirst < ptxtobj->iwchLim);
|
||
|
|
||
|
igindFirst = IgindFirstFromIwch(ptxtobj, iwchFirst);
|
||
|
plsrun = plsgrchnk->plschnk[itxtobj].plsrun;
|
||
|
while ((!(ptxtobj->txtf & txtfLastShaping)) && itxtobj < itxtobjLast )
|
||
|
{
|
||
|
itxtobj++;
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
Assert (ptxtobj->txtf & txtfGlyphBased);
|
||
|
Assert(ptxtobj->igindFirst == ((PTXTOBJ)plsgrchnk->plschnk[itxtobj-1].pdobj)->igindLim);
|
||
|
Assert(ptxtobj->iwchFirst == ((PTXTOBJ)plsgrchnk->plschnk[itxtobj-1].pdobj)->iwchLim);
|
||
|
}
|
||
|
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
igindLim = ptxtobj->igindLim;
|
||
|
Assert(itxtobj <= itxtobjLast);
|
||
|
if (itxtobj == itxtobjLast)
|
||
|
{
|
||
|
iwchLim = iwchLast + 1;
|
||
|
Assert(IgindLastFromIwch(ptxtobjLast, iwchLast) + 1 <= igindLim);
|
||
|
igindLim = IgindLastFromIwch(ptxtobjLast, iwchLast);
|
||
|
|
||
|
while (!FIgindFirstInContext(pilsobj, igindLim) && rgduGind[igindLim] == 0)
|
||
|
igindLim--;
|
||
|
|
||
|
Assert(igindLim >= ptxtobj->igindFirst);
|
||
|
|
||
|
igindLim++;
|
||
|
}
|
||
|
|
||
|
lserr = (*pilsobj->plscbk->pfnGetGlyphExpansionInfo)(pilsobj->pols, plsrun, lsdev,
|
||
|
&pilsobj->pwchOrig[iwchFirst], &plnobj->pgmap[iwchFirst], iwchLim - iwchFirst,
|
||
|
&plnobj->pgind[igindFirst], &plnobj->pgprop[igindFirst], igindLim - igindFirst,
|
||
|
lstflow, itxtobj == itxtobjLast, &pexpt[igindFirst], &plsexpinf[igindFirst]);
|
||
|
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
for (igind = igindFirst; igind < igindLim; igind++)
|
||
|
{
|
||
|
Assert(plsexpinf[igind].prior < priorMax);
|
||
|
if (plsexpinf[igind].prior > 0)
|
||
|
{
|
||
|
switch (pexpt[igind])
|
||
|
{
|
||
|
case exptAddWhiteSpace:
|
||
|
Assert(plsexpinf[igind].duMax > 0);
|
||
|
if (rgduGind[igind] > 0)
|
||
|
{
|
||
|
pexpginfo->pexpg[plsexpinf[igind].prior - 1].duMaxWhite += plsexpinf[igind].duMax;
|
||
|
pexpginfo->pexpg[plsexpinf[igind].prior - 1].duTotalWhite += rgduGind[igind];
|
||
|
pexpginfo->pexpg[plsexpinf[igind].prior - 1].cWhite++;
|
||
|
}
|
||
|
break;
|
||
|
case exptAddInkContinuous:
|
||
|
Assert(plsexpinf[igind].duMax > 0);
|
||
|
Assert(plsexpinf[igind].u.AddInkContinuous.duMin > 0);
|
||
|
pexpginfo->pexpg[plsexpinf[igind].prior - 1].duMaxContinuous += plsexpinf[igind].duMax;
|
||
|
pexpginfo->pexpg[plsexpinf[igind].prior - 1].duMinContinuous +=
|
||
|
plsexpinf[igind].u.AddInkContinuous.duMin;
|
||
|
pexpginfo->pexpg[plsexpinf[igind].prior - 1].cContinuous++;
|
||
|
break;
|
||
|
case exptAddInkDiscrete:
|
||
|
Assert(plsexpinf[igind].duMax > 0);
|
||
|
pexpginfo->pexpg[plsexpinf[igind].prior - 1].duMaxDiscrete += plsexpinf[igind].duMax;
|
||
|
pexpginfo->pexpg[plsexpinf[igind].prior - 1].cDiscrete++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (plsexpinf[igind].fCanBeUsedForResidual)
|
||
|
pexpginfo->cResidual++;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (ptxtobj->txtkind == txtkindRegular)
|
||
|
{
|
||
|
iwchFirst = iwchVeryFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
iwchLim = iwchLast + 1;
|
||
|
if (itxtobj < itxtobjLast)
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
|
||
|
for (iwSpace = ptxtobj->u.reg.iwSpacesFirst; iwSpace < ptxtobj->u.reg.iwSpacesLim &&
|
||
|
pilsobj->pwSpaces[iwSpace] < iwchFirst; iwSpace++);
|
||
|
for (; iwSpace < ptxtobj->u.reg.iwSpacesLim &&
|
||
|
pilsobj->pwSpaces[iwSpace] < iwchLim; iwSpace++)
|
||
|
{
|
||
|
pexpginfo->pexpg[priorSpace - 1].duMaxWhite += lsexpinfInfinity;
|
||
|
pexpginfo->pexpg[priorSpace - 1].duTotalWhite += rgdu[pilsobj->pwSpaces[iwSpace]];
|
||
|
pexpginfo->pexpg[priorSpace - 1].cWhite++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
itxtobj++;
|
||
|
|
||
|
}
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* A P P L Y P R I O R G L Y P H E X P A N D */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyPriorGlyphExpand
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Applies glyph expansion for particular priority
|
||
|
|
||
|
Startegy:
|
||
|
1. Apply Discrete expansion
|
||
|
2. If the rest to distribute is bigger than the sum of maximus for other distribution types
|
||
|
use these maximums for distribution
|
||
|
else if sum of mimimums is less than the rest to distribute
|
||
|
distribute proportionally to this minimums (width of character for AddWhiteSpace type)
|
||
|
else
|
||
|
increase AddContinuous opportrunities by minimum one by one while possible,
|
||
|
distribute the rest in White opportunities proportionally
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static LSERR ApplyPriorGlyphExp(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, LSDEVICE lsdev,
|
||
|
long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLast,
|
||
|
long prior, long duToDistribute, EXPG* pexpg, long* rgdu, long* rgduGind,
|
||
|
long* rgduRight, long* rgduGright, long* pduDistributed)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
PILSOBJ pilsobj;
|
||
|
long duCovered;
|
||
|
const BOOL fWhiteOnly = fTrue;
|
||
|
|
||
|
*pduDistributed = 0;
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
|
||
|
Assert(duToDistribute > 0);
|
||
|
|
||
|
if (pexpg->cDiscrete > 0)
|
||
|
{
|
||
|
lserr = ApplyDiscrete(plsgrchnk, lstflow, lsdev, itxtobjFirst, iwchFirst, itxtobjLast, iwchLast,
|
||
|
prior, duToDistribute, pexpg->cDiscrete,
|
||
|
rgduGind, rgduGright, &duCovered);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
Assert(duCovered <= duToDistribute);
|
||
|
|
||
|
duToDistribute -= duCovered;
|
||
|
*pduDistributed += duCovered;
|
||
|
}
|
||
|
|
||
|
if (duToDistribute > 0 && pexpg->cWhite + pexpg->cContinuous > 0 )
|
||
|
{
|
||
|
if (pexpg->duMaxWhite + pexpg->duMaxContinuous <= duToDistribute)
|
||
|
{
|
||
|
ApplyFullWhiteContinuous(plsgrchnk, itxtobjFirst, iwchFirst, itxtobjLast, iwchLast,
|
||
|
prior, rgdu, rgduGind, rgduRight, rgduGright, &duCovered);
|
||
|
|
||
|
Assert(duCovered == pexpg->duMaxWhite + pexpg->duMaxContinuous);
|
||
|
|
||
|
duToDistribute -= duCovered;
|
||
|
*pduDistributed += duCovered;
|
||
|
}
|
||
|
else if (pexpg->duTotalWhite + pexpg->duMinContinuous <= duToDistribute)
|
||
|
{
|
||
|
Assert(pexpg->duMaxWhite + pexpg->duMaxContinuous > duToDistribute);
|
||
|
ApplyPropWhiteContinuous(plsgrchnk, !fWhiteOnly,
|
||
|
itxtobjFirst, iwchFirst, itxtobjLast, iwchLast,
|
||
|
prior, duToDistribute, pexpg->duTotalWhite + pexpg->duMinContinuous,
|
||
|
rgdu, rgduGind, rgduRight, rgduGright, &duCovered);
|
||
|
|
||
|
duToDistribute -= duCovered;
|
||
|
*pduDistributed += duCovered;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Assert(pexpg->duTotalWhite + pexpg->duMinContinuous > duToDistribute);
|
||
|
if (pexpg->cContinuous > 0)
|
||
|
{
|
||
|
ApplyOneEachContinuous(plsgrchnk, itxtobjFirst, iwchFirst, itxtobjLast, iwchLast,
|
||
|
prior, duToDistribute, pexpg->cContinuous,
|
||
|
rgduGind, rgduGright, &duCovered);
|
||
|
duToDistribute -= duCovered;
|
||
|
*pduDistributed += duCovered;
|
||
|
}
|
||
|
if (pexpg->cWhite > 0 && duToDistribute > 0)
|
||
|
{
|
||
|
ApplyPropWhiteContinuous(plsgrchnk, fWhiteOnly,
|
||
|
itxtobjFirst, iwchFirst, itxtobjLast, iwchLast,
|
||
|
prior, duToDistribute, pexpg->duTotalWhite,
|
||
|
rgdu, rgduGind, rgduRight, rgduGright, &duCovered);
|
||
|
duToDistribute -= duCovered;
|
||
|
*pduDistributed += duCovered;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* A P P L Y D I S C R E T E */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyDiscrete
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Applies disctrete glyph expansion for particular priority
|
||
|
|
||
|
Goes ones from first to last glyph on this priority level, and chooses maximum
|
||
|
discrete opportunity which still fits.
|
||
|
---------------------------------------------------------------------------*/
|
||
|
LSERR static ApplyDiscrete(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, LSDEVICE lsdev,
|
||
|
long itxtobjFirst, long iwchVeryFirst, long itxtobjLast, long iwchLast,
|
||
|
long prior, long duToDistribute, long cDiscrete,
|
||
|
long* rgduGind, long* rgduGright, long* pduDistributed)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
PILSOBJ pilsobj;
|
||
|
PLNOBJ plnobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
PTXTOBJ ptxtobjLast;
|
||
|
PLSRUN plsrun;
|
||
|
LSEXPINFO* plsexpinf;
|
||
|
EXPTYPE* pexpt;
|
||
|
long itxtobj;
|
||
|
long iwchFirst;
|
||
|
long iwchLim;
|
||
|
long igindFirst;
|
||
|
long igindLim;
|
||
|
long igind;
|
||
|
long rgduDiscrete[cDiscreteMax];
|
||
|
long* pduDiscrete;
|
||
|
long cwidths;
|
||
|
int i;
|
||
|
|
||
|
*pduDistributed = 0;
|
||
|
|
||
|
ptxtobjLast = (PTXTOBJ)plsgrchnk->plschnk[max(0, itxtobjLast)].pdobj;
|
||
|
plnobj = ptxtobjLast->plnobj;
|
||
|
pilsobj = plnobj->pilsobj;
|
||
|
|
||
|
itxtobj = itxtobjFirst;
|
||
|
|
||
|
plsexpinf = pilsobj->plsexpinf;
|
||
|
pexpt = plnobj->pexpt;
|
||
|
|
||
|
for (itxtobj = itxtobjLast; itxtobj >= itxtobjFirst && cDiscrete > 0 && duToDistribute > 0; itxtobj--)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
if (ptxtobj->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
iwchFirst = iwchVeryFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
Assert(iwchFirst < ptxtobj->iwchLim);
|
||
|
|
||
|
igindFirst = IgindFirstFromIwch(ptxtobj, iwchFirst);
|
||
|
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
igindLim = ptxtobj->igindLim;
|
||
|
Assert(itxtobj <= itxtobjLast);
|
||
|
if (itxtobj == itxtobjLast)
|
||
|
{
|
||
|
iwchLim = iwchLast + 1;
|
||
|
Assert(IgindLastFromIwch(ptxtobjLast, iwchLast) + 1 <= igindLim);
|
||
|
igindLim = IgindLastFromIwch(ptxtobjLast, iwchLast) + 1;
|
||
|
}
|
||
|
|
||
|
plsrun = plsgrchnk->plschnk[itxtobj].plsrun;
|
||
|
|
||
|
for (igind = igindLim - 1; igind >= igindFirst && cDiscrete > 0 && duToDistribute > 0; igind--)
|
||
|
{
|
||
|
if (pexpt[igind] == exptAddInkDiscrete && plsexpinf[igind].prior == prior)
|
||
|
{
|
||
|
cDiscrete--;
|
||
|
if (duToDistribute > plsexpinf[igind].duMax)
|
||
|
{
|
||
|
ApplyGlyphExpandChanges(igind, rgduGind, rgduGright, pduDistributed, plsexpinf[igind].duMax);
|
||
|
duToDistribute -= plsexpinf[igind].duMax;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pduDiscrete = rgduDiscrete;
|
||
|
cwidths = plsexpinf[igind].u.AddInkDiscrete.cwidths - 1;
|
||
|
if (cwidths > cDiscreteMax)
|
||
|
{
|
||
|
pduDiscrete = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * cwidths);
|
||
|
if (pduDiscrete == NULL) return lserrOutOfMemory;
|
||
|
}
|
||
|
lserr = (pilsobj->plscbk->pfnGetGlyphExpansionInkInfo)(pilsobj->pols, plsrun, lsdev,
|
||
|
plnobj->pgind[igind], plnobj->pgprop[igind], lstflow, cwidths, pduDiscrete);
|
||
|
if (lserr != lserrNone)
|
||
|
{
|
||
|
if (pduDiscrete != rgduDiscrete)
|
||
|
(*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pduDiscrete);
|
||
|
return lserr;
|
||
|
}
|
||
|
#ifdef DEBUG
|
||
|
for (i = 0; i < cwidths - 1; i++)
|
||
|
Assert(pduDiscrete[i] <= pduDiscrete[i+1]);
|
||
|
#endif
|
||
|
for (i = cwidths - 1; i >= 0 && pduDiscrete[i] > duToDistribute; i--);
|
||
|
if (i >= 0)
|
||
|
{
|
||
|
Assert(pduDiscrete[i] <= duToDistribute);
|
||
|
ApplyGlyphExpandChanges(igind, rgduGind, rgduGright, pduDistributed, pduDiscrete[i]);
|
||
|
duToDistribute -= pduDiscrete[i];
|
||
|
}
|
||
|
if (pduDiscrete != rgduDiscrete)
|
||
|
(*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pduDiscrete);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* A P P L Y O N E E A C H C O N T I N U O U S */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyOneEachContinuous
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Applies glyph expansion for particular priority
|
||
|
|
||
|
Goes ones from first to last glyph on this priority level, and adds minimum
|
||
|
to each glyph with AddIncContinuous exapnsion type, if this minimum still fits
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void ApplyOneEachContinuous(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchVeryFirst,
|
||
|
long itxtobjLast, long iwchLast, long prior, long duToDistribute, long cContinuous,
|
||
|
long* rgduGind, long* rgduGright, long* pduDistributed)
|
||
|
{
|
||
|
PILSOBJ pilsobj;
|
||
|
PLNOBJ plnobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
PTXTOBJ ptxtobjLast;
|
||
|
LSEXPINFO* plsexpinf;
|
||
|
EXPTYPE* pexpt;
|
||
|
long itxtobj;
|
||
|
long iwchFirst;
|
||
|
long iwchLim;
|
||
|
long igindFirst;
|
||
|
long igindLim;
|
||
|
long igind;
|
||
|
|
||
|
*pduDistributed = 0;
|
||
|
|
||
|
ptxtobjLast = (PTXTOBJ)plsgrchnk->plschnk[max(0, itxtobjLast)].pdobj;
|
||
|
plnobj = ptxtobjLast->plnobj;
|
||
|
pilsobj = plnobj->pilsobj;
|
||
|
|
||
|
itxtobj = itxtobjFirst;
|
||
|
|
||
|
plsexpinf = pilsobj->plsexpinf;
|
||
|
pexpt = plnobj->pexpt;
|
||
|
|
||
|
for (itxtobj = itxtobjLast; itxtobj >= itxtobjFirst && cContinuous > 0 && duToDistribute > 0; itxtobj--)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
if (ptxtobj->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
iwchFirst = iwchVeryFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
Assert(iwchFirst < ptxtobj->iwchLim);
|
||
|
igindFirst = IgindFirstFromIwch(ptxtobj, iwchFirst);
|
||
|
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
igindLim = ptxtobj->igindLim;
|
||
|
Assert(itxtobj <= itxtobjLast);
|
||
|
if (itxtobj == itxtobjLast)
|
||
|
{
|
||
|
iwchLim = iwchLast + 1;
|
||
|
Assert(IgindLastFromIwch(ptxtobjLast, iwchLast) + 1 <= igindLim);
|
||
|
igindLim = IgindLastFromIwch(ptxtobjLast, iwchLast) + 1;
|
||
|
}
|
||
|
|
||
|
for (igind = igindLim - 1; igind >= igindFirst && cContinuous> 0 && duToDistribute > 0; igind--)
|
||
|
{
|
||
|
if (pexpt[igind] == exptAddInkContinuous && plsexpinf[igind].prior == prior)
|
||
|
{
|
||
|
cContinuous--;
|
||
|
if (duToDistribute > plsexpinf[igind].u.AddInkContinuous.duMin)
|
||
|
{
|
||
|
ApplyGlyphExpandChanges(igind, rgduGind, rgduGright, pduDistributed, plsexpinf[igind].u.AddInkContinuous.duMin);
|
||
|
duToDistribute -= plsexpinf[igind].u.AddInkContinuous.duMin;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/* A P P L Y F U L L W H I T E C O N T I N U O U S */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyFullWhiteContinuous
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Applies glyph expansion for particular priority
|
||
|
|
||
|
Goes ones from first to last glyph on this priority level, and adds maximum
|
||
|
to each glyph with AddIncContinuous or AddWhiteSpace exapnsion type
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void ApplyFullWhiteContinuous(const LSGRCHNK* plsgrchnk,
|
||
|
long itxtobjFirst, long iwchVeryFirst, long itxtobjLast, long iwchLast,
|
||
|
long prior,
|
||
|
long* rgdu, long* rgduGind, long* rgduRight, long* rgduGright, long* pduDistributed)
|
||
|
{
|
||
|
PILSOBJ pilsobj;
|
||
|
PLNOBJ plnobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
PTXTOBJ ptxtobjLast;
|
||
|
LSEXPINFO* plsexpinf;
|
||
|
EXPTYPE* pexpt;
|
||
|
long itxtobj;
|
||
|
long iwchFirst;
|
||
|
long iwchLim;
|
||
|
long igindFirst;
|
||
|
long igindLim;
|
||
|
long igind;
|
||
|
long iwSpace;
|
||
|
|
||
|
*pduDistributed = 0;
|
||
|
|
||
|
ptxtobjLast = (PTXTOBJ)plsgrchnk->plschnk[max(0, itxtobjLast)].pdobj;
|
||
|
plnobj = ptxtobjLast->plnobj;
|
||
|
pilsobj = plnobj->pilsobj;
|
||
|
|
||
|
itxtobj = itxtobjFirst;
|
||
|
|
||
|
plsexpinf = pilsobj->plsexpinf;
|
||
|
pexpt = plnobj->pexpt;
|
||
|
|
||
|
for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
if (ptxtobj->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
iwchFirst = iwchVeryFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
Assert(iwchFirst < ptxtobj->iwchLim);
|
||
|
|
||
|
igindFirst = IgindFirstFromIwch(ptxtobj, iwchFirst);
|
||
|
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
igindLim = ptxtobj->igindLim;
|
||
|
Assert(itxtobj <= itxtobjLast);
|
||
|
if (itxtobj == itxtobjLast)
|
||
|
{
|
||
|
iwchLim = iwchLast + 1;
|
||
|
Assert(IgindLastFromIwch(ptxtobjLast, iwchLast) + 1 <= igindLim);
|
||
|
igindLim = IgindLastFromIwch(ptxtobjLast, iwchLast) + 1;
|
||
|
}
|
||
|
|
||
|
for (igind = igindFirst; igind < igindLim; igind++)
|
||
|
{
|
||
|
if (plsexpinf[igind].prior == prior &&
|
||
|
(pexpt[igind] == exptAddWhiteSpace || pexpt[igind] == exptAddInkContinuous))
|
||
|
{
|
||
|
ApplyGlyphExpandChanges(igind, rgduGind, rgduGright, pduDistributed, plsexpinf[igind].duMax);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (ptxtobj->txtkind == txtkindRegular && prior == priorSpace)
|
||
|
{
|
||
|
iwchFirst = iwchVeryFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
iwchLim = iwchLast + 1;
|
||
|
if (itxtobj < itxtobjLast)
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
|
||
|
for (iwSpace = ptxtobj->u.reg.iwSpacesFirst; iwSpace < ptxtobj->u.reg.iwSpacesLim &&
|
||
|
pilsobj->pwSpaces[iwSpace] < iwchFirst; iwSpace++);
|
||
|
for (; iwSpace < ptxtobj->u.reg.iwSpacesLim &&
|
||
|
pilsobj->pwSpaces[iwSpace] < iwchLim; iwSpace++)
|
||
|
{
|
||
|
Assert(fFalse);
|
||
|
ApplyGlyphExpandChanges(pilsobj->pwSpaces[iwSpace], rgdu, rgduRight, pduDistributed, lsexpinfInfinity);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* A P P L Y P R O P W H I T E C O N T I N U O U S */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyPropWhiteContinuous
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Applies glyph expansion for particular priority
|
||
|
|
||
|
Goes ones from first to last glyph on this priority level, and increases width
|
||
|
for each glyph with AddIncContinuous or AddWhiteSpace exapnsion type
|
||
|
proportionally to its minimum (for InkCont) or width of character (for WhiteSpace).
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void ApplyPropWhiteContinuous(const LSGRCHNK* plsgrchnk, BOOL fWhiteOnly,
|
||
|
long itxtobjFirst, long iwchVeryFirst, long itxtobjLast, long iwchLast, long prior,
|
||
|
long duToDistribute, long duDenom,
|
||
|
long* rgdu, long* rgduGind, long* rgduRight, long* rgduGright, long* pduDistributed)
|
||
|
{
|
||
|
PILSOBJ pilsobj;
|
||
|
PLNOBJ plnobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
PTXTOBJ ptxtobjLast;
|
||
|
LSEXPINFO* plsexpinf;
|
||
|
EXPTYPE* pexpt;
|
||
|
long itxtobj;
|
||
|
long iwchFirst;
|
||
|
long iwchLim;
|
||
|
long igindFirst;
|
||
|
long igindLim;
|
||
|
long igind;
|
||
|
long cWhole;
|
||
|
long duAddCurrent;
|
||
|
long duDebt;
|
||
|
long duRest;
|
||
|
long duChange;
|
||
|
long iwch;
|
||
|
long iwSpace;
|
||
|
long duDebtSaved;
|
||
|
|
||
|
*pduDistributed = 0;
|
||
|
|
||
|
ptxtobjLast = (PTXTOBJ)plsgrchnk->plschnk[max(0, itxtobjLast)].pdobj;
|
||
|
plnobj = ptxtobjLast->plnobj;
|
||
|
pilsobj = plnobj->pilsobj;
|
||
|
|
||
|
plsexpinf = pilsobj->plsexpinf;
|
||
|
pexpt = plnobj->pexpt;
|
||
|
|
||
|
cWhole = duToDistribute / duDenom;
|
||
|
|
||
|
duRest = duToDistribute - cWhole * duDenom;
|
||
|
|
||
|
duAddCurrent = 0;
|
||
|
|
||
|
duDebt = 0;
|
||
|
|
||
|
for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
if (ptxtobj->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
iwchFirst = iwchVeryFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
Assert(iwchFirst < ptxtobj->iwchLim);
|
||
|
|
||
|
igindFirst = IgindFirstFromIwch(ptxtobj, iwchFirst);
|
||
|
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
igindLim = ptxtobj->igindLim;
|
||
|
Assert(itxtobj <= itxtobjLast);
|
||
|
if (itxtobj == itxtobjLast)
|
||
|
{
|
||
|
iwchLim = iwchLast + 1;
|
||
|
Assert(IgindLastFromIwch(ptxtobjLast, iwchLast) + 1 <= igindLim);
|
||
|
igindLim = IgindLastFromIwch(ptxtobjLast, iwchLast) + 1;
|
||
|
}
|
||
|
|
||
|
for (igind = igindFirst; igind < igindLim; igind++)
|
||
|
{
|
||
|
if (plsexpinf[igind].prior == prior)
|
||
|
{
|
||
|
if (pexpt[igind] == exptAddWhiteSpace)
|
||
|
{
|
||
|
Assert(rgduGright[igind] == 0 || pexpt[igind] == exptAddInkDiscrete);
|
||
|
CalcExpandChanges(cWhole, duDenom, duRest,
|
||
|
rgduGind[igind], plsexpinf[igind].duMax, &duChange, &duAddCurrent);
|
||
|
if (duChange > 0)
|
||
|
ApplyGlyphExpandChanges(igind, rgduGind, rgduGright, pduDistributed, duChange);
|
||
|
}
|
||
|
|
||
|
else if (pexpt[igind] == exptAddInkContinuous && !fWhiteOnly)
|
||
|
{
|
||
|
Assert(rgduGright[igind] == 0 || pexpt[igind] == exptAddInkDiscrete);
|
||
|
CalcExpandChanges(cWhole, duDenom, duRest, plsexpinf[igind].u.AddInkContinuous.duMin,
|
||
|
plsexpinf[igind].duMax, &duChange, &duAddCurrent);
|
||
|
if (duChange > 0)
|
||
|
ApplyGlyphExpandChanges(igind, rgduGind, rgduGright, pduDistributed, duChange);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (ptxtobj->txtkind == txtkindRegular && prior == priorSpace)
|
||
|
{
|
||
|
iwchFirst = iwchVeryFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
iwchLim = iwchLast + 1;
|
||
|
if (itxtobj < itxtobjLast)
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
|
||
|
for (iwSpace = ptxtobj->u.reg.iwSpacesFirst; iwSpace < ptxtobj->u.reg.iwSpacesLim &&
|
||
|
pilsobj->pwSpaces[iwSpace] < iwchFirst; iwSpace++);
|
||
|
for (; iwSpace < ptxtobj->u.reg.iwSpacesLim &&
|
||
|
pilsobj->pwSpaces[iwSpace] < iwchLim; iwSpace++)
|
||
|
{
|
||
|
iwch = pilsobj->pwSpaces[iwSpace];
|
||
|
CalcExpandChanges(cWhole, duDenom, duRest, rgdu[iwch], lsexpinfInfinity,
|
||
|
&duChange, &duAddCurrent);
|
||
|
if (duChange > 0)
|
||
|
ApplyGlyphExpandChanges(iwch, rgdu, rgduRight, pduDistributed, duChange);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
duDebt = duToDistribute - *pduDistributed;
|
||
|
Assert(duDebt >= 0);
|
||
|
/* If not everything distributed, distribute it somehow not violating Min/Max boundaries */
|
||
|
duDebtSaved = 0;
|
||
|
while (duDebt > 0 && duDebt != duDebtSaved)
|
||
|
{
|
||
|
duDebtSaved = duDebt;
|
||
|
for (itxtobj = itxtobjLast; itxtobj >= itxtobjFirst && duDebt > 0; itxtobj--)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
if (ptxtobj->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
iwchFirst = iwchVeryFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
Assert(iwchFirst < ptxtobj->iwchLim);
|
||
|
|
||
|
igindFirst = IgindFirstFromIwch(ptxtobj, iwchFirst);
|
||
|
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
igindLim = ptxtobj->igindLim;
|
||
|
Assert(itxtobj <= itxtobjLast);
|
||
|
if (itxtobj == itxtobjLast)
|
||
|
{
|
||
|
iwchLim = iwchLast + 1;
|
||
|
Assert(IgindLastFromIwch(ptxtobjLast, iwchLast) + 1 <= igindLim);
|
||
|
igindLim = IgindLastFromIwch(ptxtobjLast, iwchLast) + 1;
|
||
|
}
|
||
|
|
||
|
for (igind = igindLim - 1; igind >= igindFirst && duDebt > 0; igind--)
|
||
|
{
|
||
|
if (plsexpinf[igind].prior == prior && rgduGright[igind] < plsexpinf[igind].duMax)
|
||
|
{
|
||
|
if (pexpt[igind] == exptAddWhiteSpace)
|
||
|
{
|
||
|
duChange = min(rgduGind[igind] - rgduGright[igind], min(duDebt, plsexpinf[igind].duMax - rgduGright[igind]));
|
||
|
ApplyGlyphExpandChanges(igind, rgduGind, rgduGright, pduDistributed, duChange);
|
||
|
duDebt -= duChange;
|
||
|
}
|
||
|
else if (pexpt[igind] == exptAddInkContinuous && !fWhiteOnly)
|
||
|
{
|
||
|
Assert(rgduGright[igind] > 0);
|
||
|
duChange = min(plsexpinf[igind].u.AddInkContinuous.duMin, min(duDebt, plsexpinf[igind].duMax - rgduGright[igind]));
|
||
|
ApplyGlyphExpandChanges(igind, rgduGind, rgduGright, pduDistributed, duChange);
|
||
|
duDebt -= duChange;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (ptxtobj->txtkind == txtkindRegular && prior == priorSpace)
|
||
|
{
|
||
|
iwchFirst = iwchVeryFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
iwchLim = iwchLast + 1;
|
||
|
if (itxtobj < itxtobjLast)
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
|
||
|
for (iwSpace = ptxtobj->u.reg.iwSpacesLim - 1; iwSpace >= ptxtobj->u.reg.iwSpacesFirst &&
|
||
|
pilsobj->pwSpaces[iwSpace] >= iwchLim; iwSpace--);
|
||
|
for (; iwSpace >= ptxtobj->u.reg.iwSpacesFirst &&
|
||
|
pilsobj->pwSpaces[iwSpace] >= iwchFirst && duDebt > 0; iwSpace--)
|
||
|
{
|
||
|
iwch = pilsobj->pwSpaces[iwSpace];
|
||
|
duChange = min(rgdu[iwch] - rgduRight[iwch], duDebt);
|
||
|
ApplyGlyphExpandChanges(iwch, rgdu, rgduRight, pduDistributed, duChange);
|
||
|
duDebt -= duChange;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
Assert(duDebt == duToDistribute - *pduDistributed);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/* A P P L Y R E S I D U A L G L Y P H E X P */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyResidualGlyphExp
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
|
||
|
Distributes equally between all risidual opportunities
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void ApplyResidualGlyphExp(const LSGRCHNK* plsgrchnk, long itxtobjFirst,
|
||
|
long iwchVeryFirst, long itxtobjLast, long iwchLast, long duToDistribute,
|
||
|
long cResidual, long* rgduGind, long* rgduGright, long* pduDistributed)
|
||
|
{
|
||
|
PILSOBJ pilsobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
PTXTOBJ ptxtobjLast;
|
||
|
LSEXPINFO* plsexpinf;
|
||
|
long itxtobj;
|
||
|
long iwchFirst;
|
||
|
long iwchLim;
|
||
|
long igindFirst;
|
||
|
long igindLim;
|
||
|
long igind;
|
||
|
long cUsed;
|
||
|
long duAdd;
|
||
|
long cBound;
|
||
|
|
||
|
*pduDistributed = 0;
|
||
|
|
||
|
if (cResidual == 0)
|
||
|
return;
|
||
|
|
||
|
ptxtobjLast = (PTXTOBJ)plsgrchnk->plschnk[max(0, itxtobjLast)].pdobj;
|
||
|
pilsobj = ptxtobjLast->plnobj->pilsobj;
|
||
|
|
||
|
itxtobj = itxtobjFirst;
|
||
|
|
||
|
plsexpinf = pilsobj->plsexpinf;
|
||
|
|
||
|
duAdd = duToDistribute / cResidual;
|
||
|
|
||
|
cBound = duToDistribute - duAdd * cResidual;
|
||
|
|
||
|
cUsed = 0;
|
||
|
|
||
|
for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
if (ptxtobj->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
iwchFirst = iwchVeryFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
Assert(iwchFirst < ptxtobj->iwchLim);
|
||
|
igindFirst = IgindFirstFromIwch(ptxtobj, iwchFirst);
|
||
|
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
igindLim = ptxtobj->igindLim;
|
||
|
Assert(itxtobj <= itxtobjLast);
|
||
|
if (itxtobj == itxtobjLast)
|
||
|
{
|
||
|
iwchLim = iwchLast + 1;
|
||
|
Assert(IgindLastFromIwch(ptxtobjLast, iwchLast) + 1 <= igindLim);
|
||
|
igindLim = IgindLastFromIwch(ptxtobjLast, iwchLast) + 1;
|
||
|
}
|
||
|
|
||
|
for (igind = igindFirst; igind < igindLim; igind++)
|
||
|
{
|
||
|
if (plsexpinf[igind].fCanBeUsedForResidual)
|
||
|
{
|
||
|
if (cUsed < cBound)
|
||
|
ApplyGlyphExpandChanges(igind, rgduGind, rgduGright, pduDistributed, duAdd + 1);
|
||
|
else
|
||
|
ApplyGlyphExpandChanges(igind, rgduGind, rgduGright, pduDistributed, duAdd);
|
||
|
cUsed++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Assert(duToDistribute == *pduDistributed);
|
||
|
|
||
|
}
|
||
|
|
||
|
/* F I X E X P T */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: FixExpt
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Zeroes expt for the glyphs which were not changed,
|
||
|
so correct distribution type is passed to client at display time
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void FixExpt(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchVeryFirst,
|
||
|
long itxtobjLast, long iwchLast, long* rgduGright)
|
||
|
{
|
||
|
PTXTOBJ ptxtobj;
|
||
|
PTXTOBJ ptxtobjLast;
|
||
|
EXPTYPE* pexpt;
|
||
|
long itxtobj;
|
||
|
long iwchFirst;
|
||
|
long iwchLim;
|
||
|
long igindFirst;
|
||
|
long igindLim;
|
||
|
long igind;
|
||
|
|
||
|
ptxtobjLast = (PTXTOBJ)plsgrchnk->plschnk[max(0, itxtobjLast)].pdobj;
|
||
|
pexpt = ptxtobjLast->plnobj->pexpt;
|
||
|
|
||
|
itxtobj = itxtobjFirst;
|
||
|
|
||
|
for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
|
||
|
if (ptxtobj->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
iwchFirst = iwchVeryFirst;
|
||
|
if (itxtobj > itxtobjFirst)
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
Assert(iwchFirst < ptxtobj->iwchLim);
|
||
|
igindFirst = IgindFirstFromIwch(ptxtobj, iwchFirst);
|
||
|
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
igindLim = ptxtobj->igindLim;
|
||
|
Assert(itxtobj <= itxtobjLast);
|
||
|
if (itxtobj == itxtobjLast)
|
||
|
{
|
||
|
iwchLim = iwchLast + 1;
|
||
|
Assert(IgindLastFromIwch(ptxtobjLast, iwchLast) + 1 <= igindLim);
|
||
|
igindLim = IgindLastFromIwch(ptxtobjLast, iwchLast) + 1;
|
||
|
}
|
||
|
|
||
|
for (igind = igindFirst; igind < igindLim; igind++)
|
||
|
{
|
||
|
if (rgduGright[igind] == 0)
|
||
|
{
|
||
|
pexpt[igind] = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/* C A L C E X P A N D C H A N G E S */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: CalcExpandChanges
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Arithmetics for proportional distribution
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void CalcExpandChanges(long cWhole, long duDenom, long duRest, long duLocal, long duMax,
|
||
|
long* pduChange, long* pduAddCurrent)
|
||
|
{
|
||
|
/* REVIEW sergeyge: is __int64 necessary to avoid overflow??? */
|
||
|
__int64 temp;
|
||
|
|
||
|
temp = Mul64 (duRest, duLocal) + *pduAddCurrent;
|
||
|
|
||
|
Assert(duDenom > 0);
|
||
|
Assert(Div64 (temp, duDenom) < 0x7FFFFFFF);
|
||
|
|
||
|
*pduChange = (long) Div64 (temp, duDenom);
|
||
|
|
||
|
Assert( temp - Mul64(*pduChange, duDenom) < 0x7FFFFFFF);
|
||
|
*pduAddCurrent = (long)(temp - Mul64(*pduChange, duDenom));
|
||
|
|
||
|
*pduChange += (cWhole * duLocal);
|
||
|
if (*pduChange > duMax)
|
||
|
{
|
||
|
*pduChange = duMax;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/* A P P L Y G L Y P H E X P A N D C H A N G E S */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ApplyGlyphExpandChanges
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
---------------------------------------------------------------------------*/
|
||
|
static void ApplyGlyphExpandChanges(long ind, long* rgduGind, long* rgduGright, long* pduDistributed, long duChange)
|
||
|
{
|
||
|
rgduGind[ind] += duChange;
|
||
|
rgduGright[ind] += duChange;
|
||
|
*pduDistributed += duChange;
|
||
|
}
|
||
|
|