mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
527 lines
14 KiB
527 lines
14 KiB
#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++;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|