|
|
#include "lsmem.h"
#include "lstxtqry.h"
#include "txtils.h"
#include "txtln.h"
#include "txtobj.h"
#include "lsqin.h"
#include "lsqout.h"
typedef struct celldimensions { long iwchFirst, iwchLim; long igindFirst, igindLim; long dup; long dcp; // number of cps in cell - different from iwchLim - iwchFirst
// if hyphenation added a character
// filled just before calling AddHyphenationToCell
} CELL;
typedef CELL* PCELL;
static const POINTUV ptZero = {0,0};
// %%Function: GetCellDimensions
// %%Contact: victork
//
// Input: iwchFirst and igindFirst in CELL structure
// Output: the rest of the structure
static void GetCellDimensions(PTXTOBJ ptxtobj, PCELL pcell)
{ PLNOBJ plnobj = ptxtobj->plnobj; long* rgdup = plnobj->pdupGind; // widths of glyphs
GMAP* pgmap = plnobj->pgmap; // first glyph in a cell with given character
// 0 <= i <= wchMax (wchMax in lnobj)
// 0 <= pgmap[i] <= "glyphs in a shape" (not igindMax)
long i, dupCell; GMAP iShapeGindFirstInCell; // iShape means index from gmap, not index to rgdup
// Assert that pcell->iwchFirst is really the cell boundary
// Notice that ptxtinf (and everything in ilsobj) is not valid in query time)
Assert(pcell->iwchFirst == ptxtobj->iwchFirst || pgmap[pcell->iwchFirst] != pgmap[pcell->iwchFirst-1]); // Assert that pcell->igindFirst corresponds to pcell->iwchFirst
Assert(ptxtobj->igindFirst + pgmap[pcell->iwchFirst] - pgmap [ptxtobj->iwchFirst] == pcell->igindFirst);
// find out dimentions of the cell - all characters have the same gmap value
iShapeGindFirstInCell = pgmap[pcell->iwchFirst];
// "infinite" loop will stop when pcell->iwchLim is found
Assert(pcell->iwchFirst < ptxtobj->iwchLim); // ensure loop ends
for (i = pcell->iwchFirst + 1; ; i++) { if (i == ptxtobj->iwchLim) { pcell->iwchLim = ptxtobj->iwchLim; pcell->igindLim = ptxtobj->igindLim; break; } else if (pgmap[i] != iShapeGindFirstInCell) { pcell->iwchLim = i; pcell->igindLim = pcell->igindFirst + pgmap[i] - iShapeGindFirstInCell; break; } } for (i = pcell->igindFirst, dupCell = 0; i < pcell->igindLim; i++) { dupCell += rgdup[i]; }
pcell->dup = dupCell; }
// %%Function: AddHyphenationToCell
// %%Contact: victork
//
static void AddHyphenationToCell(PTXTOBJ ptxtobj, PCELL pcell) { long* rgdup; long i; long dwch = ptxtobj->plnobj->dwchYsr - 1; /* number of chars to add */
if (ptxtobj->txtf&txtfGlyphBased) { rgdup = ptxtobj->plnobj->pdupGind; i = pcell->igindLim;
while (dwch > 0) { pcell->dup += rgdup[i]; pcell->iwchLim ++; pcell->igindLim ++; // there are no ligatures amongst added characters
dwch--; i++; } } else { rgdup = ptxtobj->plnobj->pdup; i = pcell->iwchLim; while (dwch > 0) { pcell->dup += rgdup[i]; pcell->iwchLim ++; dwch--; i++; } }
Assert(pcell->iwchLim == (long) ptxtobj->iwchLim); }
// %%Function: QueryDcpPcell
// %%Contact: victork
//
static void QueryDcpPcell(PTXTOBJ ptxtobj, LSDCP dcp, PCELL pcell, long* pupStartCell) { PLNOBJ plnobj = ptxtobj->plnobj; long iwchLim = (long) ptxtobj->iwchLim; long* rgdup; long i;
CELL cell = {0,0,0,0,0,0}; long iwchQuery; long upStartCell;
BOOL fHyphenationPresent = fFalse;
if (ptxtobj == plnobj->pdobjHyphen) { fHyphenationPresent = fTrue; iwchLim -= (plnobj->dwchYsr - 1); /* exclude additional Ysr characters */ } iwchQuery = ptxtobj->iwchFirst + dcp;
Assert(iwchQuery < iwchLim);
if (ptxtobj->txtf&txtfGlyphBased) { // initialize loop variables to describe non-existent previous cell
upStartCell = 0; cell.iwchLim = ptxtobj->iwchFirst; cell.igindLim = ptxtobj->igindFirst; cell.dup = 0; // loop does cell after cell until the cell containing iwchQuery is found
while (cell.iwchLim <= iwchQuery) { // start filling info about current cell
upStartCell += cell.dup; cell.iwchFirst = cell.iwchLim; cell.igindFirst = cell.igindLim;
// get the rest
GetCellDimensions(ptxtobj, &cell); } } else { rgdup = plnobj->pdup;
i = ptxtobj->iwchFirst; upStartCell = 0;
while (dcp > 0) { upStartCell += rgdup[i]; dcp--; i++; } Assert(i < iwchLim); /* I'm given dcp inside */ // put the info into cell structure
cell.dup = rgdup[i]; cell.iwchFirst = i; cell.iwchLim = i+1; // these two are irrelevant, but for the sake of convenience...
cell.igindFirst = i; cell.igindLim = i; }
cell.dcp = cell.iwchLim - cell.iwchFirst; // hyphenation can change that
// YSR can extend the last cell
if (fHyphenationPresent && cell.iwchLim == iwchLim) { // the cell is up to the YSR sequence - let's include it
AddHyphenationToCell(ptxtobj, &cell); } *pcell = cell; *pupStartCell = upStartCell; }
// %%Function: QueryCpPpointText
// %%Contact: victork
//
/* Input is dcp and dnode dimensions
* Output is point where character begins (on baseline of dnode, so v is always zero), * dimensions of the character - only width is calculated */
LSERR WINAPI QueryCpPpointText(PDOBJ pdobj, LSDCP dcp, PCLSQIN plsqin, PLSQOUT plsqout) {
PTXTOBJ ptxtobj = (PTXTOBJ)pdobj; CELL cell; long upStartCell;
plsqout->pointUvStartObj = ptZero; plsqout->heightsPresObj = plsqin->heightsPresRun; plsqout->dupObj = plsqin->dupRun; plsqout->plssubl = NULL; plsqout->pointUvStartSubline = ptZero; plsqout->lstextcell.pointUvStartCell = ptZero; // u can be changed later
if (ptxtobj->txtkind == txtkindTab) { // A tab is always in a separate dnode and is treated differently
Assert(dcp == 0); plsqout->lstextcell.cpStartCell = plsqin->cpFirstRun; plsqout->lstextcell.cpEndCell = plsqin->cpFirstRun; plsqout->lstextcell.dupCell = plsqin->dupRun; plsqout->lstextcell.cCharsInCell = 1; plsqout->lstextcell.cGlyphsInCell = 0; return lserrNone; } if (ptxtobj->iwchFirst == ptxtobj->iwchLim) { // empty dobj (for NonReqHyphen, OptBreak, or NonBreak characters)
Assert(dcp == 0); Assert(plsqin->dupRun == 0); Assert(ptxtobj->txtkind == txtkindNonReqHyphen || ptxtobj->txtkind == txtkindOptBreak || ptxtobj->txtkind == txtkindOptNonBreak);
plsqout->lstextcell.cpStartCell = plsqin->cpFirstRun; plsqout->lstextcell.cpEndCell = plsqin->cpFirstRun; plsqout->lstextcell.dupCell = 0; plsqout->lstextcell.cCharsInCell = 0; plsqout->lstextcell.cGlyphsInCell = 0; return lserrNone; }
// Find the cell - common with QueryTextCellDetails
QueryDcpPcell(ptxtobj, dcp, &cell, &upStartCell); plsqout->lstextcell.cpStartCell = plsqin->cpFirstRun + cell.iwchFirst - ptxtobj->iwchFirst; plsqout->lstextcell.cpEndCell = plsqout->lstextcell.cpStartCell + cell.dcp - 1; plsqout->lstextcell.pointUvStartCell.u = upStartCell; plsqout->lstextcell.dupCell = cell.dup; plsqout->lstextcell.cCharsInCell = cell.iwchLim - cell.iwchFirst; plsqout->lstextcell.cGlyphsInCell = cell.igindLim - cell.igindFirst;
return lserrNone; }
// %%Function: QueryPointPcpText
// %%Contact: victork
//
LSERR WINAPI QueryPointPcpText(PDOBJ pdobj, PCPOINTUV pptIn, PCLSQIN plsqin, PLSQOUT plsqout)
{ PTXTOBJ ptxtobj = (PTXTOBJ)pdobj; PLNOBJ plnobj = ptxtobj->plnobj; long iwchLim = (long) ptxtobj->iwchLim; BOOL fHyphenationPresent = fFalse; long* rgdup; long i; long upQuery, upStartCell, upLimCell; CELL cell = {0,0,0,0,0,0}; // init'ed to get rid of assert
plsqout->pointUvStartObj = ptZero; plsqout->heightsPresObj = plsqin->heightsPresRun; plsqout->dupObj = plsqin->dupRun; plsqout->plssubl = NULL; plsqout->pointUvStartSubline = ptZero; plsqout->lstextcell.pointUvStartCell = ptZero; // u can change later
if (ptxtobj->txtkind == txtkindTab) { // A tab is always in a separate dnode and is treated differently
plsqout->lstextcell.cpStartCell = plsqin->cpFirstRun; plsqout->lstextcell.cpEndCell = plsqin->cpFirstRun; plsqout->lstextcell.dupCell = plsqin->dupRun; plsqout->lstextcell.cCharsInCell = 1; plsqout->lstextcell.cGlyphsInCell = 0; return lserrNone; }
if (ptxtobj == plnobj->pdobjHyphen) { fHyphenationPresent = fTrue; iwchLim -= (plnobj->dwchYsr - 1); /* exclude additional Ysr characters */ } upQuery = pptIn->u; if (upQuery < 0) { upQuery = 0; // return leftmost when clicked outside left
} upStartCell = 0;
if (ptxtobj->txtf&txtfGlyphBased) { // initialize loop variables to describe non-existent previous cell
upLimCell = 0; cell.iwchLim = ptxtobj->iwchFirst; cell.igindLim = ptxtobj->igindFirst; cell.dup = 0; // loop does cell after cell until the last cell or the cell containing upQuery
while (cell.iwchLim < iwchLim && upLimCell <= upQuery) { // start filling info about current cell
upStartCell = upLimCell; cell.iwchFirst = cell.iwchLim; cell.igindFirst = cell.igindLim;
// get the rest
GetCellDimensions(ptxtobj, &cell); upLimCell = upStartCell + cell.dup; } } else { rgdup = plnobj->pdup;
i = ptxtobj->iwchFirst; upLimCell = 0; while (upLimCell <= upQuery && i < iwchLim) { upStartCell = upLimCell; upLimCell += rgdup[i]; i++; } // put the info into cell structure
cell.dup = rgdup[i - 1]; cell.iwchFirst = i - 1; cell.iwchLim = i; // these two are irrelevant, but for the sake of convenience...
cell.igindFirst = i - 1; cell.igindLim = i - 1; }
cell.dcp = cell.iwchLim - cell.iwchFirst; // hyphenation can change that
// YSR can extend the last cell
if (fHyphenationPresent && cell.iwchLim == iwchLim) { // the cell is up to the YSR sequence - let's include it
AddHyphenationToCell(ptxtobj, &cell); } plsqout->lstextcell.cpStartCell = plsqin->cpFirstRun + cell.iwchFirst - ptxtobj->iwchFirst; plsqout->lstextcell.cpEndCell = plsqout->lstextcell.cpStartCell + cell.dcp - 1; plsqout->lstextcell.pointUvStartCell.u = upStartCell; plsqout->lstextcell.dupCell = cell.dup; plsqout->lstextcell.cCharsInCell = cell.iwchLim - cell.iwchFirst; plsqout->lstextcell.cGlyphsInCell = cell.igindLim - cell.igindFirst;
return lserrNone; }
// %%Function: QueryTextCellDetails
// %%Contact: victork
//
LSERR WINAPI QueryTextCellDetails( PDOBJ pdobj, LSDCP dcp, /* IN: dcpStartCell */ DWORD cChars, /* IN: cCharsInCell */ DWORD cGlyphs, /* IN: cGlyphsInCell */ LPWSTR pwchOut, /* OUT: pointer array[cChars] of char codes */ PGINDEX pgindex, /* OUT: pointer array[cGlyphs] of glyph indices */ long* pdup, /* OUT: pointer array[cGlyphs] of glyph widths */ PGOFFSET pgoffset, /* OUT: pointer array[cGlyphs] of glyph offsets */ PGPROP pgprop) /* OUT: pointer array[cGlyphs] of glyph handles */ { PTXTOBJ ptxtobj = (PTXTOBJ)pdobj; PLNOBJ plnobj = ptxtobj->plnobj;
CELL cell; long upDummy; Unreferenced(cGlyphs); Unreferenced(cChars); // used only in an assert
if (ptxtobj->txtkind == txtkindTab) { // Tab is in a separate dnode always and is treated differently
Assert(dcp == 0); Assert(cChars == 1); *pwchOut = ptxtobj->u.tab.wch; *pdup = (ptxtobj->plnobj->pdup)[ptxtobj->iwchFirst]; return lserrNone; } if (ptxtobj->iwchFirst == ptxtobj->iwchLim) { // empty dobj (for NonReqHyphen, OptBreak, or NonBreak characters)
Assert(dcp == 0); Assert(cChars == 0); Assert(cGlyphs == 0); return lserrNone; }
// Find the cell - common with QueryCpPpointText
QueryDcpPcell(ptxtobj, dcp, &cell, &upDummy); Assert(cell.iwchLim - cell.iwchFirst == (long) cChars);
memcpy(pwchOut, &plnobj->pwch[cell.iwchFirst], sizeof(long) * cChars);
if (ptxtobj->txtf&txtfGlyphBased) { Assert(cell.igindLim - cell.igindFirst == (long) cGlyphs); memcpy(pdup, &plnobj->pdupGind[cell.igindFirst], sizeof(long) * cGlyphs); memcpy(pgindex, &plnobj->pgind[cell.igindFirst], sizeof(long) * cGlyphs); memcpy(pgoffset, &plnobj->pgoffs[cell.igindFirst], sizeof(long) * cGlyphs); memcpy(pgprop, &plnobj->pgprop[cell.igindFirst], sizeof(long) * cGlyphs); } else { memcpy(pdup, &plnobj->pdup[cell.iwchFirst], sizeof(long) * cChars); } return lserrNone; }
|