Leaked source code of windows server 2003
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.

1845 lines
56 KiB

  1. #include "lsmem.h"
  2. #include "lstxtnti.h"
  3. #include "lstxtmod.h"
  4. #include "lstxtmap.h"
  5. #include "lstxtbrs.h"
  6. #include "lsdnset.h"
  7. #include "lsdntext.h"
  8. #include "lschp.h"
  9. #include "lstxtffi.h"
  10. #include "tnti.h"
  11. #include "txtils.h"
  12. #include "txtln.h"
  13. #include "txtobj.h"
  14. #include "lschnke.h"
  15. #include "lsems.h"
  16. #include "objdim.h"
  17. #define max(a,b) ((a) < (b) ? (b) : (a))
  18. #define maskAllCharBasedArrays (fTntiModWidthOnRun | fTntiModWidthSpace | fTntiModWidthPairs | \
  19. fTntiCompressOnRun | fTntiCompressSpace | fTntiCompressTable | \
  20. fTntiExpandOnRun | fTntiExpandSpace | fTntiExpandTable)
  21. #define maskModWidth (fTntiModWidthOnRun | fTntiModWidthSpace | fTntiModWidthPairs)
  22. #define FModWidthSomeDobj(n) (rglschnk[(n)].plschp->fModWidthOnRun || \
  23. rglschnk[(n)].plschp->fModWidthSpace || \
  24. rglschnk[(n)].plschp->fModWidthPairs)
  25. static LSERR PrepareAllArraysGetModWidth(DWORD grpfTnti, DWORD cchnk, const LSCHNKE* rglschnk);
  26. static LSERR ApplyKern(LSTFLOW lstflow, DWORD cchnk, const LSCHNKE* rglschnk);
  27. static LSERR CheckApplyKernBetweenRuns(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjPrev, long itxtobjCur);
  28. static LSERR ApplyKernToRun(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjCur);
  29. static BOOL GetPrevImportantRun(const LSCHNKE* rglschnk, long itxtobj, long* pitxtobjPrev);
  30. static BOOL GetNextImportantRun(DWORD cchnk, const LSCHNKE* rglschnk, long itxtobj, long* pitxtobjNext);
  31. static LSERR GetModWidthClasses(DWORD cchnk, const LSCHNKE* rglschnk);
  32. static LSERR ApplyModWidth(LSTFLOW lstflow, BOOL fFirstOnLine, BOOL fAutoNumberPresent, DWORD cchnk, const LSCHNKE* rglschnk);
  33. static LSERR ApplySnapGrid(DWORD cchnk, const LSCHNKE* rglschnk);
  34. static LSERR ApplyModWidthToRun(LSTFLOW lstflow, BOOL fFirstOnLine, BOOL fAutoNumberPresent, DWORD cchnk, const LSCHNKE* rglschnk, long itxtobjCur);
  35. static LSERR CheckApplyModWidthBetweenRuns(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjPrev, long itxtobjCur);
  36. static LSERR CheckApplyPunctStartLine(PILSOBJ pilsobj, PLSRUN plsrun, LSEMS* plsems, long iwch,
  37. long* pddurChange);
  38. static LSERR CheckApplyModWidthSpace(PILSOBJ pilsobj, PLSRUN plsrunPrev, PLSRUN plsrunCur, PLSRUN plsrunNext,
  39. LSEMS* plsems, long iwchPrev, long iwchCur, long iwchNext, long* pddurChange);
  40. static LSERR CheckApplyModWidthOnRun(PILSOBJ pilsobj, PTXTOBJ ptxtobjPrev, PLSRUN plsrunPrev, PLSRUN plsrunCur,
  41. LSEMS* plsems, long iwchFirst, long iwchSecond, long* pddurChange);
  42. static LSERR ApplySnapChanges(PILSOBJ pilsobj, const LSCHNKE* rglschnk, long iwchFirstSnapped,
  43. long itxtobjFirstSnapped, long iwchPrev, long itxtobjPrev, long durTotal);
  44. static LSERR UndoAppliedModWidth(PILSOBJ pilsobj, const LSCHNKE* rglschnk,
  45. long itxtobj, long iwch, BYTE side, long* pdurUndo);
  46. static LSERR CleanUpGrid(PILSOBJ pilsobj, PLSRUN* rgplsrun, LSCP* rgcp, BOOL* rgfSnapped,
  47. LSERR lserr);
  48. static long CalcSnapped(long urPen, long urColumnMax, long cGrid, long durGridWhole, long durGridRem);
  49. static LSERR ApplyGlyphs(LSTFLOW lstflow, DWORD cchnk, const LSCHNKE* rglschnk);
  50. static LSERR ApplyGlyphsToRange(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjFirst, long itxtobjLast);
  51. static LSERR CheckReallocGlyphs(PLNOBJ plnobj, long cglyphs);
  52. static LSERR FixGlyphSpaces(LSTFLOW lstflow, const LSCHNKE* rglschnk,
  53. long itxtobjFirst, long igindVeryFirst, long itxtobjLast);
  54. static LSERR FixTxtobjs(const LSCHNKE* rglschnk, long itxtobjFirst, long igindFirst, long itxtobjLast);
  55. static LSERR Realloc(PILSOBJ pols, void** pInOut, long cbytes);
  56. static void CopyGindices(PLNOBJ plnobj, GINDEX* pgindex, PGPROP pgprop, long cgind, long* pigindFirst);
  57. #define CheckApplyModWidthTwoChars(pilsobj, plsemsFirst, plsemsSecond,\
  58. iwchFirst, iwchSecond, pddurChangeFirst, pddurChangeSecond) \
  59. {\
  60. LSPAIRACT lspairact;\
  61. MWCLS mwclsCur;\
  62. MWCLS mwclsNext;\
  63. BYTE side;\
  64. \
  65. *(pddurChangeFirst) = 0;\
  66. *(pddurChangeSecond) = 0;\
  67. mwclsCur = (BYTE)(pilsobj)->ptxtinf[((iwchFirst))].mwcls;\
  68. mwclsNext = (BYTE)(pilsobj)->ptxtinf[(iwchSecond)].mwcls;\
  69. Assert(mwclsCur < (pilsobj)->cModWidthClasses);\
  70. Assert(mwclsNext < (pilsobj)->cModWidthClasses);\
  71. lspairact = \
  72. (pilsobj)->plspairact[(pilsobj)->pilspairact[(pilsobj)->cModWidthClasses * mwclsCur + mwclsNext]];\
  73. \
  74. if (lspairact.lsactFirst.side != sideNone)\
  75. {\
  76. GetChanges(lspairact.lsactFirst, (plsemsFirst), (pilsobj)->pdur[((iwchFirst))], fFalse, &side, (pddurChangeFirst));\
  77. ApplyChanges((pilsobj), ((iwchFirst)), side, *(pddurChangeFirst));\
  78. /* (pilsobj)->ptxtinf[((iwchFirst))].fModWidthPair = fTrue;*/\
  79. }\
  80. \
  81. if (lspairact.lsactSecond.side != sideNone)\
  82. {\
  83. GetChanges(lspairact.lsactSecond, (plsemsSecond), (pilsobj)->pdur[(iwchSecond)], fFalse, &side, (pddurChangeSecond));\
  84. ApplyChanges((pilsobj), (iwchSecond), side, *(pddurChangeSecond));\
  85. /* (pilsobj)->ptxtinf[(iwchSecond)].fModWidthPair = fTrue;*/\
  86. }\
  87. \
  88. }
  89. LSERR NominalToIdealText(DWORD grpfTnti, LSTFLOW lstflow, BOOL fFirstOnLine, BOOL fAutoNumberPresent, DWORD cchnk, const LSCHNKE* rglschnk)
  90. {
  91. LSERR lserr;
  92. PILSOBJ pilsobj;
  93. Assert(cchnk > 0);
  94. pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
  95. lserr = PrepareAllArraysGetModWidth(grpfTnti, cchnk, rglschnk);
  96. if (lserr != lserrNone) return lserr;
  97. if (grpfTnti & fTntiGlyphBased)
  98. {
  99. lserr = ApplyGlyphs(lstflow, cchnk, rglschnk);
  100. if (lserr != lserrNone) return lserr;
  101. }
  102. if (grpfTnti & fTntiKern)
  103. {
  104. lserr = ApplyKern(lstflow, cchnk, rglschnk);
  105. if (lserr != lserrNone) return lserr;
  106. }
  107. if ((grpfTnti & maskModWidth) || (pilsobj->grpf & fTxtPunctStartLine))
  108. {
  109. lserr = ApplyModWidth(lstflow, fFirstOnLine, fAutoNumberPresent, cchnk, rglschnk);
  110. if (lserr != lserrNone) return lserr;
  111. }
  112. if (pilsobj->fSnapGrid)
  113. {
  114. #ifdef DEBUG
  115. {
  116. BOOL fInChildList;
  117. lserr = LsdnFInChildList(pilsobj->plsc, ((PTXTOBJ)rglschnk[0].pdobj)->plsdnUpNode, &fInChildList);
  118. Assert(lserr == lserrNone);
  119. Assert(!(grpfTnti & fTntiGlyphBased) || fInChildList);
  120. }
  121. #endif
  122. lserr = ApplySnapGrid(cchnk, rglschnk);
  123. if (lserr != lserrNone) return lserr;
  124. }
  125. return lserr;
  126. }
  127. /* G E T F I R S T C H A R I N C H U N K */
  128. /*----------------------------------------------------------------------------
  129. %%Function: GetFirstCharInChunk
  130. %%Contact: sergeyge
  131. Prepares information about first visible char in chunk
  132. ----------------------------------------------------------------------------*/
  133. LSERR GetFirstCharInChunk(DWORD cchnk, const LSCHNKE* rglschnk, BOOL* pfSuccessful,
  134. WCHAR* pwch, PLSRUN* pplsrun, PHEIGHTS pheights, MWCLS* pmwcls)
  135. {
  136. LSERR lserr;
  137. PILSOBJ pilsobj;
  138. long itxtobj;
  139. long iwch;
  140. PTXTOBJ ptxtobj;
  141. OBJDIM objdim;
  142. Assert(cchnk > 0);
  143. pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
  144. *pfSuccessful = fFalse;
  145. if (GetNextImportantRun(cchnk, rglschnk, 0, &itxtobj))
  146. {
  147. ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
  148. if (ptxtobj->txtf & txtfModWidthClassed)
  149. {
  150. Assert(!(ptxtobj->txtf & txtfGlyphBased));
  151. *pfSuccessful = fTrue;
  152. iwch = ptxtobj->iwchFirst;
  153. *pwch = pilsobj->pwchOrig[iwch];
  154. *pplsrun = rglschnk[itxtobj].plsrun;
  155. *pmwcls = (MWCLS)pilsobj->ptxtinf[iwch].mwcls;
  156. lserr = LsdnGetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, &objdim);
  157. if (lserr != lserrNone) return lserr;
  158. *pheights = objdim.heightsRef;
  159. }
  160. }
  161. return lserrNone;
  162. }
  163. /* G E T L A S T C H A R I N C H U N K */
  164. /*----------------------------------------------------------------------------
  165. %%Function: GetLastCharInChunk
  166. %%Contact: sergeyge
  167. Prepares information about first visible char in chunk
  168. ----------------------------------------------------------------------------*/
  169. LSERR GetLastCharInChunk(DWORD cchnk, const LSCHNKE* rglschnk, BOOL* pfSuccessful,
  170. WCHAR* pwch, PLSRUN* pplsrun, PHEIGHTS pheights, MWCLS* pmwcls)
  171. {
  172. LSERR lserr;
  173. PILSOBJ pilsobj;
  174. long itxtobj;
  175. long iwch;
  176. PTXTOBJ ptxtobj;
  177. OBJDIM objdim;
  178. Assert(cchnk > 0);
  179. pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
  180. *pfSuccessful = fFalse;
  181. if ( GetPrevImportantRun(rglschnk, cchnk - 1, &itxtobj))
  182. {
  183. ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
  184. if (ptxtobj->txtf & txtfModWidthClassed)
  185. {
  186. Assert(!(ptxtobj->txtf & txtfGlyphBased));
  187. *pfSuccessful = fTrue;
  188. iwch = ptxtobj->iwchLim - 1;
  189. *pwch = pilsobj->pwchOrig[iwch];
  190. *pplsrun = rglschnk[itxtobj].plsrun;
  191. *pmwcls = (MWCLS)pilsobj->ptxtinf[iwch].mwcls;
  192. lserr = LsdnGetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, &objdim);
  193. if (lserr != lserrNone) return lserr;
  194. *pheights = objdim.heightsRef;
  195. }
  196. }
  197. return lserrNone;
  198. }
  199. /* M O D I F Y F I R S T C H A R I N C H U N K */
  200. /*----------------------------------------------------------------------------
  201. %%Function: ModifyFirstCharInChunk
  202. %%Contact: sergeyge
  203. Prepares information about first visible char in chunk
  204. ----------------------------------------------------------------------------*/
  205. LSERR ModifyFirstCharInChunk(DWORD cchnk, const LSCHNKE* rglschnk, long durChange)
  206. {
  207. LSERR lserr;
  208. PILSOBJ pilsobj;
  209. long itxtobj;
  210. long iwch;
  211. PTXTOBJ ptxtobj;
  212. BOOL fFound;
  213. Assert(cchnk > 0);
  214. pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
  215. fFound = GetNextImportantRun(cchnk, rglschnk, 0, &itxtobj);
  216. Assert(fFound);
  217. Assert(pilsobj->pdurLeft != NULL);
  218. ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
  219. Assert(!(ptxtobj->txtf & txtfGlyphBased));
  220. Assert(ptxtobj->txtf & txtfModWidthClassed);
  221. iwch = ptxtobj->iwchFirst;
  222. ApplyChanges(pilsobj, iwch, sideLeft, durChange);
  223. lserr = LsdnModifySimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, durChange);
  224. return lserrNone;
  225. }
  226. /* M O D I F Y L A S T C H A R I N C H U N K */
  227. /*----------------------------------------------------------------------------
  228. %%Function: ModifyLastCharInChunk
  229. %%Contact: sergeyge
  230. Prepares information about first visible char in chunk
  231. ----------------------------------------------------------------------------*/
  232. LSERR ModifyLastCharInChunk(DWORD cchnk, const LSCHNKE* rglschnk, long durChange)
  233. {
  234. LSERR lserr;
  235. PILSOBJ pilsobj;
  236. long itxtobj;
  237. long iwch;
  238. PTXTOBJ ptxtobj;
  239. BOOL fFound;
  240. Assert(cchnk > 0);
  241. pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
  242. fFound = GetPrevImportantRun(rglschnk, cchnk-1, &itxtobj);
  243. Assert(fFound);
  244. Assert(pilsobj->pdurRight != NULL);
  245. ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
  246. Assert(!(ptxtobj->txtf & txtfGlyphBased));
  247. Assert(ptxtobj->txtf & txtfModWidthClassed);
  248. iwch = ptxtobj->iwchLim - 1;
  249. ApplyChanges(pilsobj, iwch, sideRight, durChange);
  250. lserr = LsdnModifySimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, durChange);
  251. return lserrNone;
  252. }
  253. /* C U T T E X T D O B J */
  254. /*----------------------------------------------------------------------------
  255. %%Function: CutTextDobj
  256. %%Contact: sergeyge
  257. Cuts characters according to dcpMaxContext
  258. ----------------------------------------------------------------------------*/
  259. LSERR CutTextDobj(DWORD cchnk, const LSCHNKE* rglschnk)
  260. {
  261. LSERR lserr;
  262. PILSOBJ pilsobj;
  263. PTXTOBJ ptxtobj;
  264. long itxtobjLast;
  265. long dcp;
  266. long dur;
  267. long iwchLim;
  268. long igindLim;
  269. long iwSpacesFirst;
  270. long iwSpacesLim;
  271. BOOL fNonSpaceBeforeFound;
  272. long itxtobjBefore;
  273. long iwchBefore;
  274. OBJDIM objdim;
  275. long itxtobj;
  276. BOOL fFixSpaces = fTrue;
  277. Assert(cchnk > 0);
  278. pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
  279. iwchLim = ((PTXTOBJ)rglschnk[cchnk - 1].pdobj)->iwchLim - rglschnk[cchnk-1].plschp->dcpMaxContext + 1;
  280. itxtobjLast = cchnk - 1;
  281. while (itxtobjLast >= 0 && iwchLim <= ((PTXTOBJ)rglschnk[itxtobjLast].pdobj)->iwchFirst)
  282. itxtobjLast--;
  283. if (itxtobjLast >= 0)
  284. {
  285. ptxtobj = (PTXTOBJ)rglschnk[itxtobjLast].pdobj;
  286. fNonSpaceBeforeFound = FindNonSpaceBefore(rglschnk, itxtobjLast, iwchLim - 1, &itxtobjBefore, &iwchBefore);
  287. if (fNonSpaceBeforeFound)
  288. {
  289. if (iwchBefore != iwchLim - 1)
  290. {
  291. Assert(itxtobjBefore >= 0);
  292. itxtobjLast = itxtobjBefore;
  293. iwchLim = iwchBefore + 1;
  294. ptxtobj = (PTXTOBJ)rglschnk[itxtobjLast].pdobj;
  295. }
  296. dcp = iwchLim - ptxtobj->iwchFirst;
  297. lserr = LsdnGetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, &objdim);
  298. Assert(lserr == lserrNone);
  299. dur = objdim.dur;
  300. Assert(ptxtobj->iwchFirst + (long)dcp <= ptxtobj->iwchLim);
  301. if (ptxtobj->txtf & txtfGlyphBased)
  302. {
  303. long igind;
  304. Assert(iwchLim >= ptxtobj->iwchFirst);
  305. /* REVIEW sergeyge: We should take IwchLastFromIwch instead and get rid of fFixSpaces---
  306. right?
  307. */
  308. if (iwchLim > ptxtobj->iwchFirst)
  309. iwchLim = IwchPrevLastFromIwch(ptxtobj, iwchLim) + 1;
  310. /* if part of Dnode is to be left, calculate this part
  311. else delete the whole Dnode
  312. */
  313. if (iwchLim > ptxtobj->iwchFirst)
  314. {
  315. igindLim = IgindLastFromIwch(ptxtobj, iwchLim - 1) + 1;
  316. for (igind = igindLim; igind < ptxtobj->igindLim; igind++)
  317. dur -= pilsobj->pdurGind[igind];
  318. ptxtobj->iwchLim = iwchLim;
  319. ptxtobj->igindLim = igindLim;
  320. lserr = LsdnSetSimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, dur);
  321. Assert (lserr == lserrNone);
  322. lserr = LsdnResetDcp(pilsobj->plsc,
  323. ptxtobj->plsdnUpNode, iwchLim - ptxtobj->iwchFirst);
  324. Assert (lserr == lserrNone);
  325. }
  326. else
  327. {
  328. itxtobjLast--;
  329. fFixSpaces = fFalse;
  330. }
  331. }
  332. else
  333. {
  334. long iwch;
  335. for (iwch = iwchLim; iwch < ptxtobj->iwchLim; iwch++)
  336. dur -= pilsobj->pdur[iwch];
  337. ptxtobj->iwchLim = iwchLim;
  338. lserr = LsdnSetSimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, dur);
  339. Assert (lserr == lserrNone);
  340. lserr = LsdnResetDcp(pilsobj->plsc, ptxtobj->plsdnUpNode, dcp);
  341. Assert (lserr == lserrNone);
  342. }
  343. if (fFixSpaces)
  344. {
  345. Assert(ptxtobj == (PTXTOBJ)rglschnk[itxtobjLast].pdobj);
  346. iwSpacesFirst = ptxtobj->u.reg.iwSpacesFirst;
  347. iwSpacesLim = ptxtobj->u.reg.iwSpacesLim;
  348. while (iwSpacesLim > iwSpacesFirst && pilsobj->pwSpaces[iwSpacesLim - 1] > iwchLim - 1)
  349. {
  350. iwSpacesLim--;
  351. }
  352. ptxtobj->u.reg.iwSpacesLim = iwSpacesLim;
  353. Assert(iwchLim == ptxtobj->iwchLim);
  354. if (iwSpacesLim - iwSpacesFirst == iwchLim - ptxtobj->iwchFirst &&
  355. !(pilsobj->grpf & fTxtSpacesInfluenceHeight) &&
  356. objdim.heightsRef.dvMultiLineHeight != dvHeightIgnore)
  357. {
  358. objdim.dur = dur;
  359. objdim.heightsRef.dvMultiLineHeight = dvHeightIgnore;
  360. objdim.heightsPres.dvMultiLineHeight = dvHeightIgnore;
  361. lserr = LsdnResetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, &objdim);
  362. Assert (lserr == lserrNone);
  363. }
  364. }
  365. }
  366. else
  367. {
  368. /* dirty triangle: in the case of fNonSpaceFound==fFalse, correct itxtobjLast */
  369. itxtobjLast = -1;
  370. }
  371. }
  372. for (itxtobj = itxtobjLast + 1; itxtobj < (long)cchnk; itxtobj++)
  373. {
  374. lserr = LsdnSetSimpleWidth(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobj].pdobj)->plsdnUpNode, 0);
  375. Assert (lserr == lserrNone);
  376. lserr = LsdnResetDcp(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobj].pdobj)->plsdnUpNode, 0);
  377. Assert (lserr == lserrNone);
  378. }
  379. return lserrNone;
  380. }
  381. /* Internal functions implementation */
  382. static LSERR PrepareAllArraysGetModWidth(DWORD grpfTnti, DWORD cchnk, const LSCHNKE* rglschnk)
  383. {
  384. LSERR lserr;
  385. PLNOBJ plnobj;
  386. PILSOBJ pilsobj;
  387. plnobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj;
  388. pilsobj = plnobj->pilsobj;
  389. Assert ((grpfTnti & maskAllCharBasedArrays) || (pilsobj->grpf & fTxtPunctStartLine) ||
  390. (pilsobj->grpf & fTxtHangingPunct) || (grpfTnti & fTntiGlyphBased) ||
  391. (grpfTnti & fTntiKern) || pilsobj->fSnapGrid);
  392. /* if we got to nti some adjustment is needed and we must allocate pdurAdjust */
  393. if (pilsobj->pduAdjust == NULL)
  394. {
  395. pilsobj->pduAdjust = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->wchMax );
  396. if (pilsobj->pduAdjust == NULL)
  397. {
  398. return lserrOutOfMemory;
  399. }
  400. }
  401. if ( (grpfTnti & maskAllCharBasedArrays) || (pilsobj->grpf & fTxtPunctStartLine) ||
  402. (pilsobj->grpf & fTxtHangingPunct) || pilsobj->fSnapGrid || (grpfTnti & fTntiGlyphBased))
  403. {
  404. Assert(pilsobj->pduAdjust != NULL);
  405. if (pilsobj->pdurRight == NULL)
  406. {
  407. Assert (pilsobj->pdurLeft == NULL);
  408. Assert(pilsobj->ptxtinf == NULL);
  409. pilsobj->pdurRight = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->wchMax );
  410. pilsobj->pdurLeft = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->wchMax );
  411. pilsobj->ptxtinf = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(TXTINF) * pilsobj->wchMax );
  412. if (pilsobj->pdurRight == NULL || pilsobj->pdurLeft == NULL || pilsobj->ptxtinf == NULL)
  413. {
  414. return lserrOutOfMemory;
  415. }
  416. memset(pilsobj->pdurRight, 0, sizeof(long) * pilsobj->wchMax );
  417. memset(pilsobj->pdurLeft, 0, sizeof(long) * pilsobj->wchMax );
  418. memset(pilsobj->ptxtinf, 0, sizeof(TXTINF) * pilsobj->wchMax);
  419. }
  420. pilsobj->fNotSimpleText = fTrue;
  421. }
  422. if (grpfTnti & fTntiGlyphBased)
  423. {
  424. lserr = CheckReallocGlyphs(plnobj, pilsobj->wchMax - 2);
  425. if (lserr != lserrNone) return lserr;
  426. }
  427. if ( (grpfTnti & maskAllCharBasedArrays) || (pilsobj->grpf & fTxtPunctStartLine) ||
  428. (pilsobj->grpf & fTxtHangingPunct) || pilsobj->fSnapGrid)
  429. {
  430. lserr = GetModWidthClasses(cchnk, rglschnk);
  431. if (lserr != lserrNone) return lserr;
  432. }
  433. return lserrNone;
  434. }
  435. static LSERR ApplyKern(LSTFLOW lstflow, DWORD cchnk, const LSCHNKE* rglschnk)
  436. {
  437. LSERR lserr;
  438. PILSOBJ pilsobj;
  439. PLNOBJ plnobj;
  440. long itxtobjPrev = 0;
  441. long itxtobjCur;
  442. BOOL fFoundNextRun;
  443. BOOL fFoundKernedPrevRun;
  444. plnobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj;
  445. pilsobj = plnobj->pilsobj;
  446. fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, 0, &itxtobjCur);
  447. fFoundKernedPrevRun = fFalse;
  448. while (fFoundNextRun)
  449. {
  450. if (fFoundKernedPrevRun && rglschnk[itxtobjCur].plschp->fApplyKern)
  451. {
  452. lserr = CheckApplyKernBetweenRuns(lstflow, rglschnk, itxtobjPrev, itxtobjCur);
  453. if (lserr != lserrNone) return lserr;
  454. }
  455. if (rglschnk[itxtobjCur].plschp->fApplyKern)
  456. {
  457. lserr = ApplyKernToRun(lstflow, rglschnk, itxtobjCur);
  458. if (lserr != lserrNone) return lserr;
  459. fFoundKernedPrevRun = fTrue;
  460. itxtobjPrev = itxtobjCur;
  461. }
  462. else
  463. {
  464. fFoundKernedPrevRun = fFalse;
  465. }
  466. fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, itxtobjCur + 1, &itxtobjCur);
  467. }
  468. return lserrNone;
  469. }
  470. static LSERR CheckApplyKernBetweenRuns(LSTFLOW lstflow, const LSCHNKE* rglschnk,
  471. long itxtobjPrev, long itxtobjCur)
  472. {
  473. LSERR lserr;
  474. PTXTOBJ ptxtobj;
  475. PLNOBJ plnobj;
  476. PILSOBJ pilsobj;
  477. long iwchLim;
  478. BOOL fKernPrevRun;
  479. long dduKern;
  480. WCHAR* pwch = NULL;
  481. WCHAR rgwchTwo[2];
  482. long dduAdjust;
  483. ptxtobj = (PTXTOBJ)rglschnk[itxtobjPrev].pdobj;
  484. plnobj = ptxtobj->plnobj;
  485. pilsobj = plnobj->pilsobj;
  486. Assert(!(ptxtobj->txtf & txtfGlyphBased));
  487. lserr = (*pilsobj->plscbk->pfnCheckRunKernability)(pilsobj->pols, rglschnk[itxtobjPrev].plsrun,
  488. rglschnk[itxtobjCur].plsrun, &fKernPrevRun);
  489. if (lserr != lserrNone) return lserr;
  490. if (fKernPrevRun)
  491. {
  492. iwchLim = ptxtobj->iwchLim;
  493. if (iwchLim == ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchFirst)
  494. {
  495. pwch = &pilsobj->pwchOrig[iwchLim - 1];
  496. }
  497. else
  498. {
  499. rgwchTwo[0] = pilsobj->pwchOrig[iwchLim - 1];
  500. rgwchTwo[1] = pilsobj->pwchOrig[((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchFirst];
  501. pwch = rgwchTwo;
  502. }
  503. lserr = (*pilsobj->plscbk->pfnGetRunCharKerning)(pilsobj->pols, rglschnk[itxtobjPrev].plsrun,
  504. lsdevReference, pwch, 2, lstflow, (int*)&dduKern);
  505. if (lserr != lserrNone) return lserr;
  506. dduAdjust = max(-pilsobj->pdur[iwchLim - 1], dduKern);
  507. pilsobj->pdur[iwchLim - 1] += dduAdjust;
  508. lserr = LsdnModifySimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, dduAdjust);
  509. if (lserr != lserrNone) return lserr;
  510. if (pilsobj->fDisplay)
  511. {
  512. if (!pilsobj->fPresEqualRef)
  513. {
  514. lserr = (*pilsobj->plscbk->pfnGetRunCharKerning)(pilsobj->pols, rglschnk[itxtobjPrev].plsrun,
  515. lsdevPres, pwch, 2, lstflow, (int*)&dduKern);
  516. if (lserr != lserrNone) return lserr;
  517. dduAdjust = max(-plnobj->pdup[iwchLim - 1], dduKern);
  518. plnobj->pdup[iwchLim - 1] += dduAdjust;
  519. }
  520. else
  521. {
  522. plnobj->pdup[iwchLim - 1] = pilsobj->pdur[iwchLim-1];
  523. }
  524. }
  525. }
  526. return lserrNone;
  527. }
  528. static LSERR ApplyKernToRun(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjCur)
  529. {
  530. LSERR lserr;
  531. PTXTOBJ ptxtobj;
  532. PLNOBJ plnobj;
  533. PILSOBJ pilsobj;
  534. long iwchFirst;
  535. long iwchLim;
  536. long iwch;
  537. long dduAdjust;
  538. long ddurChange;
  539. ptxtobj = (PTXTOBJ)rglschnk[itxtobjCur].pdobj;
  540. plnobj = ptxtobj->plnobj;
  541. pilsobj = plnobj->pilsobj;
  542. Assert(!(ptxtobj->txtf & txtfGlyphBased));
  543. Assert(pilsobj->pduAdjust != NULL);
  544. iwchFirst = ptxtobj->iwchFirst;
  545. iwchLim = ptxtobj->iwchLim;
  546. Assert (iwchLim > iwchFirst);
  547. if (iwchLim == iwchFirst + 1)
  548. return lserrNone;
  549. lserr = (*pilsobj->plscbk->pfnGetRunCharKerning)(pilsobj->pols, rglschnk[itxtobjCur].plsrun, lsdevReference,
  550. &pilsobj->pwchOrig[iwchFirst], iwchLim - iwchFirst, lstflow, (int*)&pilsobj->pduAdjust[iwchFirst]);
  551. if (lserr != lserrNone) return lserr;
  552. ddurChange = 0;
  553. for (iwch = iwchFirst; iwch < iwchLim - 1; iwch++)
  554. {
  555. dduAdjust = max(-pilsobj->pdur[iwch], pilsobj->pduAdjust[iwch]);
  556. pilsobj->pdur[iwch] += dduAdjust;
  557. ddurChange += dduAdjust;
  558. }
  559. if (ddurChange != 0)
  560. {
  561. lserr = LsdnModifySimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, ddurChange);
  562. if (lserr != lserrNone) return lserr;
  563. }
  564. if (pilsobj->fDisplay)
  565. {
  566. if (!pilsobj->fPresEqualRef)
  567. {
  568. lserr = (*pilsobj->plscbk->pfnGetRunCharKerning)(pilsobj->pols, rglschnk[itxtobjCur].plsrun, lsdevPres,
  569. &plnobj->pwch[iwchFirst], iwchLim - iwchFirst, lstflow, (int*)&pilsobj->pduAdjust[iwchFirst]);
  570. if (lserr != lserrNone) return lserr;
  571. for (iwch = iwchFirst; iwch < iwchLim - 1; iwch++)
  572. {
  573. dduAdjust = max(-plnobj->pdup[iwch], pilsobj->pduAdjust[iwch]);
  574. plnobj->pdup[iwch] += dduAdjust;
  575. }
  576. }
  577. else
  578. {
  579. memcpy(&plnobj->pdup[iwchFirst], &pilsobj->pdur[iwchFirst], sizeof(long) * (iwchLim - iwchFirst) );
  580. }
  581. }
  582. return lserrNone;
  583. }
  584. static BOOL GetPrevImportantRun(const LSCHNKE* rglschnk, long itxtobj, long* pitxtobjPrev)
  585. {
  586. PTXTOBJ ptxtobj;
  587. while (itxtobj >= 0 /*&& !fFound (fFound logic changed to break)*/)
  588. {
  589. ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
  590. if (!(ptxtobj->txtf & txtfSkipAtNti))
  591. {
  592. /*fFound = fTrue;*/
  593. break;
  594. }
  595. else
  596. {
  597. itxtobj--;
  598. }
  599. }
  600. *pitxtobjPrev = itxtobj;
  601. return (itxtobj >= 0);
  602. }
  603. static BOOL GetNextImportantRun(DWORD cchnk, const LSCHNKE* rglschnk, long itxtobj, long* pitxtobjNext)
  604. {
  605. PTXTOBJ ptxtobj;
  606. while (itxtobj < (long)cchnk /*&& !fFound (fFound logic changed to break)*/)
  607. {
  608. ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
  609. if (!(ptxtobj->txtf & txtfSkipAtNti))
  610. {
  611. /*fFound = fTrue;*/
  612. break;
  613. }
  614. else
  615. {
  616. itxtobj++;
  617. }
  618. }
  619. *pitxtobjNext = itxtobj;
  620. return (itxtobj < (long)cchnk);
  621. }
  622. static LSERR ApplyModWidth(LSTFLOW lstflow, BOOL fFirstOnLine, BOOL fAutoNumberPresent, DWORD cchnk, const LSCHNKE* rglschnk)
  623. {
  624. LSERR lserr;
  625. PILSOBJ pilsobj;
  626. PLNOBJ plnobj;
  627. long itxtobjPrev=0;
  628. long itxtobjCur;
  629. BOOL fFoundNextRun;
  630. BOOL fFoundModWidthPrevRun;
  631. plnobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj;
  632. pilsobj = plnobj->pilsobj;
  633. fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, 0, &itxtobjCur);
  634. fFoundModWidthPrevRun = fFalse;
  635. while (fFoundNextRun)
  636. {
  637. if (fFoundModWidthPrevRun && FModWidthSomeDobj(itxtobjCur))
  638. {
  639. lserr = CheckApplyModWidthBetweenRuns(lstflow, rglschnk, itxtobjPrev, itxtobjCur);
  640. if (lserr != lserrNone) return lserr;
  641. }
  642. lserr = ApplyModWidthToRun(lstflow, fFirstOnLine, fAutoNumberPresent,cchnk, rglschnk, itxtobjCur);
  643. if (lserr != lserrNone) return lserr;
  644. fFoundModWidthPrevRun = FModWidthSomeDobj(itxtobjCur);
  645. itxtobjPrev = itxtobjCur;
  646. fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, itxtobjCur + 1, &itxtobjCur);
  647. }
  648. return lserrNone;
  649. }
  650. static LSERR ApplyModWidthToRun(LSTFLOW lstflow, BOOL fFirstOnLine, BOOL fAutoNumberPresent, DWORD cchnk, const LSCHNKE* rglschnk, long itxtobjCur)
  651. {
  652. LSERR lserr;
  653. PTXTOBJ ptxtobj;
  654. PLNOBJ plnobj;
  655. PILSOBJ pilsobj;
  656. long iwchVeryFirst;
  657. long iwchVeryLim;
  658. long iwchFirst;
  659. long iwchLim;
  660. long iwch;
  661. long iwchPrev;
  662. long iwchNext;
  663. LSEMS lsems;
  664. PLSRUN plsrun;
  665. PLSRUN plsrunPrev;
  666. PLSRUN plsrunNext;
  667. long itxtobjPrev;
  668. long itxtobjNext;
  669. BOOL fFoundPrevRun;
  670. BOOL fFoundNextRun;
  671. long ddurChangeFirst;
  672. long ddurChangeSecond;
  673. long ddurChange;
  674. WCHAR* pwchOrig;
  675. ptxtobj = (PTXTOBJ)rglschnk[itxtobjCur].pdobj;
  676. plnobj = ptxtobj->plnobj;
  677. pilsobj = plnobj->pilsobj;
  678. plsrun = rglschnk[itxtobjCur].plsrun;
  679. lserr = (*pilsobj->plscbk->pfnGetEms)(pilsobj->pols, plsrun, lstflow, &lsems);
  680. if (lserr != lserrNone) return lserr;
  681. Assert(ptxtobj->iwchLim > ptxtobj->iwchFirst);
  682. ddurChange = 0;
  683. /* all changes to the last char which depend on the next run will be applied in the next
  684. call to ApplyModWidthBetween runs
  685. */
  686. iwchLim = ptxtobj->iwchLim;
  687. iwchFirst = ptxtobj->iwchFirst;
  688. if ( (pilsobj->grpf & fTxtPunctStartLine) && fFirstOnLine && itxtobjCur == 0 &&
  689. !(fAutoNumberPresent && (pilsobj->grpf & fTxtNoPunctAfterAutoNumber )) &&
  690. !(ptxtobj->txtf & txtfGlyphBased)
  691. )
  692. {
  693. CheckApplyPunctStartLine(pilsobj, plsrun, &lsems, iwchFirst, &ddurChangeFirst);
  694. ddurChange += ddurChangeFirst;
  695. }
  696. if (rglschnk[itxtobjCur].plschp->fModWidthPairs)
  697. {
  698. Assert(pilsobj->ptxtinf != NULL);
  699. Assert(pilsobj->plspairact != NULL);
  700. Assert(pilsobj->pilspairact != NULL);
  701. Assert(!(ptxtobj->txtf & txtfGlyphBased));
  702. Assert(pilsobj->pilspairact != NULL);
  703. if(pilsobj->pilspairact == NULL)
  704. return lserrModWidthPairsNotSet;
  705. for (iwch = iwchFirst; iwch < iwchLim - 1; iwch++)
  706. {
  707. CheckApplyModWidthTwoChars(pilsobj, &lsems, &lsems, iwch, iwch+1, &ddurChangeFirst, &ddurChangeSecond);
  708. ddurChange += (ddurChangeFirst + ddurChangeSecond);
  709. }
  710. }
  711. /* REVIEW sergeyge(elik): should we try to avoid second loop through characters? */
  712. if (rglschnk[itxtobjCur].plschp->fModWidthSpace)
  713. {
  714. Assert(!(ptxtobj->txtf & txtfGlyphBased));
  715. iwchVeryFirst = ((PTXTOBJ)rglschnk[0].pdobj)->iwchFirst;
  716. iwchVeryLim = ((PTXTOBJ)rglschnk[cchnk-1].pdobj)->iwchLim;
  717. pwchOrig = pilsobj->pwchOrig;
  718. for (iwch = iwchFirst; iwch < iwchLim; iwch++)
  719. {
  720. if (pwchOrig[iwch] == pilsobj->wchSpace)
  721. {
  722. plsrunPrev = NULL;
  723. iwchPrev = 0;
  724. if (iwch > iwchFirst)
  725. {
  726. plsrunPrev = plsrun;
  727. iwchPrev = iwch - 1;
  728. }
  729. else if (iwch > iwchVeryFirst)
  730. {
  731. Assert(itxtobjCur > 0);
  732. fFoundPrevRun = GetPrevImportantRun(rglschnk, itxtobjCur-1, &itxtobjPrev);
  733. if (fFoundPrevRun)
  734. {
  735. Assert(itxtobjPrev >= 0);
  736. plsrunPrev = rglschnk[itxtobjPrev].plsrun;
  737. iwchPrev = ((PTXTOBJ)rglschnk[itxtobjPrev].pdobj)->iwchLim - 1;
  738. }
  739. }
  740. plsrunNext = NULL;
  741. iwchNext = 0;
  742. if (iwch < iwchLim - 1)
  743. {
  744. plsrunNext = plsrun;
  745. iwchNext = iwch + 1;
  746. }
  747. else if (iwch < iwchVeryLim - 1)
  748. {
  749. Assert(itxtobjCur < (long)cchnk - 1);
  750. fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, itxtobjCur+1, &itxtobjNext);
  751. if (fFoundNextRun)
  752. {
  753. Assert(itxtobjNext < (long)cchnk);
  754. plsrunNext = rglschnk[itxtobjNext].plsrun;
  755. iwchNext = ((PTXTOBJ)rglschnk[itxtobjNext].pdobj)->iwchFirst;
  756. }
  757. }
  758. lserr = CheckApplyModWidthSpace(pilsobj, plsrunPrev, plsrun, plsrunNext, &lsems,
  759. iwchPrev, iwch, iwchNext, &ddurChangeFirst);
  760. if (lserr != lserrNone) return lserr;
  761. ddurChange += ddurChangeFirst;
  762. }
  763. }
  764. }
  765. if (ddurChange != 0)
  766. {
  767. lserr = LsdnModifySimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, ddurChange);
  768. if (lserr != lserrNone) return lserr;
  769. }
  770. return lserrNone;
  771. }
  772. static LSERR CheckApplyModWidthBetweenRuns(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjPrev, long itxtobjCur)
  773. {
  774. LSERR lserr;
  775. PTXTOBJ ptxtobjPrev;
  776. PLNOBJ plnobj;
  777. PILSOBJ pilsobj;
  778. long iwchNext;
  779. long iwch;
  780. LSEMS lsemsPrev;
  781. LSEMS lsemsCur;
  782. PLSRUN plsrunPrev;
  783. PLSRUN plsrunCur;
  784. long ddurChangeFirst;
  785. long ddurChangeSecond;
  786. long ddurChangePrev;
  787. long ddurChangeCur;
  788. ddurChangePrev = 0;
  789. ddurChangeCur = 0;
  790. ptxtobjPrev = (PTXTOBJ)rglschnk[itxtobjPrev].pdobj;
  791. plnobj = ptxtobjPrev->plnobj;
  792. pilsobj = plnobj->pilsobj;
  793. plsrunPrev = rglschnk[itxtobjPrev].plsrun;
  794. plsrunCur = rglschnk[itxtobjCur].plsrun;
  795. iwchNext = ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchFirst;
  796. lserr = (*pilsobj->plscbk->pfnGetEms)(pilsobj->pols, plsrunPrev, lstflow, &lsemsPrev);
  797. if (lserr != lserrNone) return lserr;
  798. lserr = (*pilsobj->plscbk->pfnGetEms)(pilsobj->pols, plsrunCur, lstflow, &lsemsCur);
  799. if (lserr != lserrNone) return lserr;
  800. iwch = ptxtobjPrev->iwchLim - 1;
  801. if (rglschnk[itxtobjPrev].plschp->fModWidthOnRun && rglschnk[itxtobjCur].plschp->fModWidthOnRun)
  802. {
  803. lserr = CheckApplyModWidthOnRun(pilsobj, ptxtobjPrev,
  804. plsrunPrev, plsrunCur, &lsemsPrev, iwch, iwchNext, &ddurChangeFirst);
  805. if (lserr != lserrNone) return lserr;
  806. ddurChangePrev += ddurChangeFirst;
  807. }
  808. if (rglschnk[itxtobjPrev].plschp->fModWidthPairs && rglschnk[itxtobjCur].plschp->fModWidthPairs)
  809. {
  810. Assert ((!(ptxtobjPrev->txtf & txtfGlyphBased)) &&
  811. !(((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->txtf & txtfGlyphBased));
  812. CheckApplyModWidthTwoChars(pilsobj, &lsemsPrev, &lsemsCur, iwch, iwchNext, &ddurChangeFirst, &ddurChangeSecond);
  813. ddurChangePrev += ddurChangeFirst;
  814. ddurChangeCur += ddurChangeSecond;
  815. }
  816. if (ddurChangePrev != 0)
  817. {
  818. lserr = LsdnModifySimpleWidth(pilsobj->plsc, ptxtobjPrev->plsdnUpNode, ddurChangePrev);
  819. if (lserr != lserrNone) return lserr;
  820. }
  821. if (ddurChangeCur != 0)
  822. {
  823. lserr = LsdnModifySimpleWidth(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->plsdnUpNode,
  824. ddurChangeCur);
  825. if (lserr != lserrNone) return lserr;
  826. }
  827. return lserrNone;
  828. }
  829. static LSERR GetModWidthClasses(DWORD cchnk, const LSCHNKE* rglschnk)
  830. {
  831. LSERR lserr;
  832. PILSOBJ pilsobj;
  833. PTXTOBJ ptxtobj;
  834. long itxtobj;
  835. long iwchFirst;
  836. long iwchLim;
  837. long iwch;
  838. long i;
  839. MWCLS* pmwcls;
  840. WCHAR* pwchOrig;
  841. TXTINF* ptxtinf;
  842. pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
  843. pwchOrig = pilsobj->pwchOrig;
  844. ptxtinf = pilsobj->ptxtinf;
  845. for (itxtobj = 0; itxtobj < (long)cchnk; itxtobj++)
  846. {
  847. ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
  848. if (!(ptxtobj->txtf & txtfGlyphBased))
  849. {
  850. iwchFirst = ptxtobj->iwchFirst;
  851. iwchLim = ptxtobj->iwchLim;
  852. if (iwchLim > iwchFirst)
  853. {
  854. Assert(pilsobj->pduAdjust != NULL);
  855. /* I use pdurAdjust as temporary buffer to read MWCLS info */
  856. pmwcls = (MWCLS*)(&pilsobj->pduAdjust[iwchFirst]);
  857. lserr =(*pilsobj->plscbk->pfnGetModWidthClasses)(pilsobj->pols, rglschnk[itxtobj].plsrun,
  858. &pwchOrig[iwchFirst], (DWORD)(iwchLim - iwchFirst), pmwcls);
  859. if (lserr != lserrNone) return lserr;
  860. for (i=0, iwch = iwchFirst; iwch < iwchLim; i++, iwch++)
  861. {
  862. Assert(pmwcls[i] < pilsobj->cModWidthClasses);
  863. if (pmwcls[i] >= pilsobj->cModWidthClasses)
  864. return lserrInvalidModWidthClass;
  865. ptxtinf[iwch].mwcls = pmwcls[i];
  866. }
  867. }
  868. ptxtobj->txtf |= txtfModWidthClassed;
  869. }
  870. }
  871. return lserrNone;
  872. }
  873. static LSERR CheckApplyPunctStartLine(PILSOBJ pilsobj, PLSRUN plsrun, LSEMS* plsems, long iwch,
  874. long* pddurChange)
  875. {
  876. LSERR lserr;
  877. LSACT lsact;
  878. MWCLS mwcls;
  879. BYTE side;
  880. *pddurChange = 0;
  881. mwcls = (BYTE)pilsobj->ptxtinf[iwch].mwcls;
  882. Assert(mwcls < pilsobj->cModWidthClasses);
  883. lserr = (*pilsobj->plscbk->pfnPunctStartLine)(pilsobj->pols, plsrun, mwcls, pilsobj->pwchOrig[iwch], &lsact);
  884. if (lserr != lserrNone) return lserr;
  885. if (lsact.side != sideNone)
  886. {
  887. GetChanges(lsact, plsems, pilsobj->pdur[iwch], fFalse, &side, pddurChange);
  888. ApplyChanges(pilsobj, iwch, side, *pddurChange);
  889. /* pilsobj->ptxtinf[iwch].fStartLinePunct = fTrue;*/
  890. }
  891. return lserrNone;
  892. }
  893. static LSERR CheckApplyModWidthSpace(PILSOBJ pilsobj, PLSRUN plsrunPrev, PLSRUN plsrunCur, PLSRUN plsrunNext,
  894. LSEMS* plsems, long iwchPrev, long iwchCur, long iwchNext, long* pddurChange)
  895. {
  896. LSERR lserr;
  897. WCHAR wchPrev;
  898. WCHAR wchNext;
  899. LSACT lsact;
  900. BYTE side;
  901. *pddurChange = 0;
  902. wchPrev = 0;
  903. if (plsrunPrev != NULL)
  904. wchPrev = pilsobj->pwchOrig[iwchPrev];
  905. wchNext = 0;
  906. if (plsrunNext != NULL)
  907. wchNext = pilsobj->pwchOrig[iwchNext];
  908. lserr = (*pilsobj->plscbk->pfnModWidthSpace)(pilsobj->pols, plsrunCur, plsrunPrev, wchPrev, plsrunNext, wchNext,
  909. &lsact);
  910. if (lserr != lserrNone) return lserr;
  911. if (lsact.side != sideNone)
  912. {
  913. GetChanges(lsact, plsems, pilsobj->pdur[iwchCur], fTrue, &side, pddurChange);
  914. Assert(side == sideRight);
  915. ApplyChanges(pilsobj, iwchCur, side, *pddurChange);
  916. pilsobj->ptxtinf[iwchCur].fModWidthSpace = fTrue;
  917. }
  918. return lserrNone;
  919. }
  920. static LSERR CheckApplyModWidthOnRun(PILSOBJ pilsobj, PTXTOBJ ptxtobjPrev, PLSRUN plsrunPrev, PLSRUN plsrunCur,
  921. LSEMS* plsems, long iwchFirst, long iwchSecond, long* pddurChange)
  922. {
  923. LSERR lserr;
  924. LSACT lsact;
  925. BYTE side;
  926. long igindLast;
  927. long igind;
  928. *pddurChange = 0;
  929. lserr = (*pilsobj->plscbk->pfnModWidthOnRun)(pilsobj->pols, plsrunPrev, pilsobj->pwchOrig[iwchFirst],
  930. plsrunCur, pilsobj->pwchOrig[iwchSecond], &lsact);
  931. if (lserr != lserrNone) return lserr;
  932. if (lsact.side != sideNone)
  933. {
  934. if (ptxtobjPrev->txtf & txtfGlyphBased)
  935. {
  936. igindLast = IgindLastFromIwch(ptxtobjPrev, iwchFirst);
  937. igind = IgindBaseFromIgind(pilsobj, igindLast);
  938. GetChanges(lsact, plsems, pilsobj->pdurGind[igind], fTrue, &side, pddurChange);
  939. Assert(side == sideRight);
  940. ApplyGlyphChanges(pilsobj, igind, *pddurChange);
  941. }
  942. else
  943. {
  944. GetChanges(lsact, plsems, pilsobj->pdur[iwchFirst], fTrue, &side, pddurChange);
  945. Assert(side == sideRight);
  946. ApplyChanges(pilsobj, iwchFirst, side, *pddurChange);
  947. }
  948. pilsobj->ptxtinf[iwchFirst].fModWidthOnRun = fTrue;
  949. }
  950. return lserrNone;
  951. }
  952. static LSERR ApplySnapGrid(DWORD cchnk, const LSCHNKE* rglschnk)
  953. {
  954. LSERR lserr;
  955. PILSOBJ pilsobj;
  956. long iwchVeryFirst;
  957. long iwchVeryLim;
  958. long iwchFirstInDobj;
  959. long iwchLimInDobj;
  960. long iwch;
  961. long iwchFirstSnapped;
  962. long iwchPrev;
  963. long itxtobj;
  964. long itxtobjCur;
  965. long itxtobjFirstSnapped;
  966. long itxtobjPrev;
  967. PLSRUN* rgplsrun = NULL;
  968. LSCP* rgcp = NULL;
  969. BOOL* rgfSnapped = NULL;
  970. long irg;
  971. PLSRUN plsrunCur;
  972. LSCP cpCur;
  973. long cGrid;
  974. BOOL fFoundNextRun;
  975. long urColumnMax;
  976. long urPen;
  977. long durPen;
  978. long urPenSnapped;
  979. long urPenFirstSnapped;
  980. long durUndo;
  981. long durGridWhole;
  982. long durGridRem;
  983. BOOL fInChildList;
  984. pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
  985. lserr = LsdnFInChildList(pilsobj->plsc, ((PTXTOBJ)rglschnk[0].pdobj)->plsdnUpNode, &fInChildList);
  986. Assert(lserr == lserrNone);
  987. if (fInChildList)
  988. return lserrNone;
  989. iwchVeryFirst = ((PTXTOBJ)rglschnk[0].pdobj)->iwchFirst;
  990. iwchVeryLim = ((PTXTOBJ)rglschnk[cchnk - 1].pdobj)->iwchLim;
  991. if (iwchVeryLim <= iwchVeryFirst)
  992. return lserrNone;
  993. rgcp = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, (iwchVeryLim - iwchVeryFirst) * sizeof (LSCP));
  994. if (rgcp == NULL)
  995. return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserrOutOfMemory);
  996. rgplsrun = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, (iwchVeryLim - iwchVeryFirst) * sizeof (PLSRUN));
  997. if (rgplsrun == NULL)
  998. return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserrOutOfMemory);
  999. rgfSnapped = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, (iwchVeryLim - iwchVeryFirst) * sizeof (BOOL));
  1000. if (rgfSnapped == NULL)
  1001. return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserrOutOfMemory);
  1002. irg = 0;
  1003. for (itxtobj = 0; itxtobj < (long)cchnk; itxtobj++)
  1004. {
  1005. iwchFirstInDobj = ((PTXTOBJ)rglschnk[itxtobj].pdobj)->iwchFirst;
  1006. iwchLimInDobj = ((PTXTOBJ)rglschnk[itxtobj].pdobj)->iwchLim;
  1007. plsrunCur = rglschnk[itxtobj].plsrun;
  1008. cpCur = rglschnk[itxtobj].cpFirst;
  1009. for (iwch = iwchFirstInDobj; iwch < iwchLimInDobj; iwch++)
  1010. {
  1011. rgcp[irg] = cpCur;
  1012. rgplsrun[irg] = plsrunCur;
  1013. irg++;
  1014. cpCur++;
  1015. }
  1016. }
  1017. lserr = (*pilsobj->plscbk->pfnGetSnapGrid)(pilsobj->pols, &pilsobj->pwchOrig[iwchVeryFirst], rgplsrun, rgcp, irg, rgfSnapped, (DWORD*)&cGrid);
  1018. if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
  1019. Assert(cGrid > 0);
  1020. if (cGrid <= 0) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserrNone);
  1021. rgfSnapped[0] = fTrue; /* First character of each lock chunk must be snapped */
  1022. fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, 0, &itxtobjCur);
  1023. if (fFoundNextRun && rgfSnapped[((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchFirst - iwchVeryFirst])
  1024. {
  1025. iwchFirstInDobj = ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchFirst;
  1026. /* fix for the case when ModWidth was applied before snapping to grid.
  1027. Changes to the left of the first character should be undone.
  1028. */
  1029. lserr = UndoAppliedModWidth(pilsobj, rglschnk, itxtobjCur, iwchFirstInDobj, sideLeft, &durUndo);
  1030. if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
  1031. lserr = LsdnGetUrPenAtBeginningOfChunk(pilsobj->plsc, ((PTXTOBJ)rglschnk[0].pdobj)->plsdnUpNode,
  1032. &urPen, &urColumnMax);
  1033. if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
  1034. if (urColumnMax <= 0) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserrNone);
  1035. durGridWhole = urColumnMax / cGrid;
  1036. durGridRem = urColumnMax - durGridWhole * cGrid;
  1037. urPenSnapped = CalcSnapped(urPen, urColumnMax, cGrid, durGridWhole, durGridRem);
  1038. Assert(urPenSnapped >= urPen);
  1039. if (urPenSnapped > urPen)
  1040. {
  1041. ApplyChanges(pilsobj, iwchFirstInDobj, sideLeft, urPenSnapped - urPen);
  1042. lserr = LsdnModifySimpleWidth(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->plsdnUpNode,
  1043. urPenSnapped - urPen);
  1044. if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
  1045. }
  1046. /* Dangerous fix to the bug 594. Width of first character was just changed. First iteration of the
  1047. following for loop assumes that it was not. So I initialize variables in such way that
  1048. first iteration will work correctly---2 errors compensate each other
  1049. before fix initialization was:
  1050. durPen = 0;
  1051. urPen = urPenSnapped
  1052. */
  1053. durPen = urPen - urPenSnapped;
  1054. /* urPen = urPenSnapped;*/
  1055. urPenFirstSnapped = urPenSnapped;
  1056. iwchFirstSnapped = iwchFirstInDobj;
  1057. itxtobjFirstSnapped = itxtobjCur;
  1058. iwchPrev = iwchFirstInDobj;
  1059. itxtobjPrev = itxtobjCur;
  1060. while (fFoundNextRun)
  1061. {
  1062. iwchFirstInDobj = ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchFirst;
  1063. iwchLimInDobj = ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchLim;
  1064. for (iwch = iwchFirstInDobj; iwch < iwchLimInDobj; iwch++)
  1065. {
  1066. if (rgfSnapped[iwch - iwchVeryFirst] && iwch > iwchFirstSnapped)
  1067. {
  1068. /* fix for the case when ModWidth was applied before snapping to grid.
  1069. Changes to the right of the last character should be undone.
  1070. */
  1071. lserr = UndoAppliedModWidth(pilsobj, rglschnk, itxtobjPrev, iwchPrev, sideRight, &durUndo);
  1072. if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
  1073. if (durUndo != 0)
  1074. {
  1075. urPen += durUndo;
  1076. durPen += durUndo;
  1077. }
  1078. /* end of the fix due to ModWidth */
  1079. urPenSnapped = CalcSnapped(urPen, urColumnMax, cGrid, durGridWhole, durGridRem);
  1080. Assert(urPenSnapped - urPenFirstSnapped - durPen >= 0);
  1081. lserr = ApplySnapChanges(pilsobj, rglschnk, iwchFirstSnapped, itxtobjFirstSnapped,
  1082. iwchPrev, itxtobjPrev, urPenSnapped - urPenFirstSnapped - durPen);
  1083. if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
  1084. durPen = 0;
  1085. urPen = urPenSnapped;
  1086. urPenFirstSnapped = urPenSnapped;
  1087. iwchFirstSnapped = iwch;
  1088. itxtobjFirstSnapped = itxtobjCur;
  1089. /* fix for the case when ModWidth was applied before snapping to grid.
  1090. Changes to the left of the first character should be undone.
  1091. */
  1092. lserr = UndoAppliedModWidth(pilsobj, rglschnk, itxtobjCur, iwch, sideLeft, &durUndo);
  1093. if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
  1094. }
  1095. urPen += pilsobj->pdur[iwch];
  1096. durPen += pilsobj->pdur[iwch];
  1097. iwchPrev = iwch;
  1098. itxtobjPrev = itxtobjCur;
  1099. }
  1100. fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, itxtobjCur + 1, &itxtobjCur);
  1101. }
  1102. /* fix for the case when ModWidth was applied before snapping to grid.
  1103. Changes to the right of the last character should be undone.
  1104. */
  1105. UndoAppliedModWidth(pilsobj, rglschnk, itxtobjPrev, iwchPrev, sideRight, &durUndo);
  1106. if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
  1107. if (durUndo != 0)
  1108. {
  1109. urPen += durUndo;
  1110. durPen += durUndo;
  1111. }
  1112. /* end of the fix due to ModWidth */
  1113. urPenSnapped = CalcSnapped(urPen, urColumnMax, cGrid, durGridWhole, durGridRem);
  1114. Assert(urPenSnapped - urPenFirstSnapped - durPen >= 0);
  1115. lserr = ApplySnapChanges(pilsobj, rglschnk, iwchFirstSnapped, itxtobjFirstSnapped,
  1116. iwchPrev, itxtobjPrev, urPenSnapped - urPenFirstSnapped - durPen);
  1117. if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
  1118. }
  1119. return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserrNone);
  1120. }
  1121. static LSERR UndoAppliedModWidth(PILSOBJ pilsobj, const LSCHNKE* rglschnk,
  1122. long itxtobj, long iwch, BYTE side, long* pdurUndo)
  1123. {
  1124. LSERR lserr;
  1125. UndoAppliedChanges(pilsobj, iwch, side, pdurUndo);
  1126. if (*pdurUndo != 0)
  1127. {
  1128. lserr = LsdnModifySimpleWidth(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobj].pdobj)->plsdnUpNode,
  1129. *pdurUndo);
  1130. if (lserr != lserrNone) return lserr;
  1131. pilsobj->ptxtinf[iwch].fModWidthOnRun = fFalse;
  1132. pilsobj->ptxtinf[iwch].fModWidthSpace = fTrue;
  1133. }
  1134. return lserrNone;
  1135. }
  1136. static LSERR ApplySnapChanges(PILSOBJ pilsobj, const LSCHNKE* rglschnk, long iwchFirstSnapped,
  1137. long itxtobjFirstSnapped, long iwchLastSnapped, long itxtobjLastSnapped, long durTotal)
  1138. {
  1139. LSERR lserr;
  1140. long durSnapRight;
  1141. long durSnapLeft;
  1142. durSnapRight = durTotal >> 1;
  1143. durSnapLeft = durTotal - durSnapRight;
  1144. ApplyChanges(pilsobj, iwchFirstSnapped, sideLeft, durSnapLeft);
  1145. lserr = LsdnModifySimpleWidth(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobjFirstSnapped].pdobj)->plsdnUpNode,
  1146. durSnapLeft);
  1147. if (lserr != lserrNone) return lserr;
  1148. ApplyChanges(pilsobj, iwchLastSnapped, sideRight, durSnapRight);
  1149. lserr = LsdnModifySimpleWidth(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobjLastSnapped].pdobj)->plsdnUpNode,
  1150. durSnapRight);
  1151. if (lserr != lserrNone) return lserr;
  1152. return lserrNone;
  1153. }
  1154. static LSERR CleanUpGrid(PILSOBJ pilsobj, PLSRUN* rgplsrun, LSCP* rgcp, BOOL* rgfSnapped,
  1155. LSERR lserr)
  1156. {
  1157. if (rgplsrun != NULL)
  1158. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, rgplsrun);
  1159. if (rgcp != NULL)
  1160. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, rgcp);
  1161. if (rgfSnapped != NULL)
  1162. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, rgfSnapped);
  1163. return lserr;
  1164. }
  1165. static long CalcSnapped(long urPen, long urColumnMax, long cGrid, long durGridWhole, long durGridRem)
  1166. {
  1167. long idGrid;
  1168. /* It is important to prove that idGrid-->urPenSnapped-->idGrid produces the same idGrid we started with.
  1169. Here is the proof:
  1170. idGrid-->urPenSnapped: (idGrid * durGridWhole + durGridRem*idGrid/cGrid)---it is urPenSnapped
  1171. urPenSnapped-->idGrid:
  1172. (urPenSnapped * cGrid + urColumnMax - 1 ) / urColumnMax =
  1173. ((idGrid * durGridWhole + durGridRem*idGrid/cGrid) * cGrid + urColumnMax - 1) / urColumnMax =
  1174. (idGrid * (urColumnMax - durGridRem) + durGridRem * idGrid + urColumnMax - 1) / urColumnMax =
  1175. (idGrid * urColumnMax + urColumnMax - 1) / urColumnMax = idGrid
  1176. It shows also that if one takes urPenSnapped + 1, result will be idGrid + 1 which is exactly correct
  1177. */
  1178. if (urPen >= 0)
  1179. idGrid = (urPen * cGrid + urColumnMax - 1 ) / urColumnMax;
  1180. else
  1181. idGrid = - ((-urPen * cGrid) / urColumnMax);
  1182. return idGrid * durGridWhole + durGridRem * idGrid / cGrid;
  1183. }
  1184. #define cwchShapedTogetherMax 0x7FFF
  1185. /* Glyph-related activities */
  1186. static LSERR ApplyGlyphs(LSTFLOW lstflow, DWORD cchnk, const LSCHNKE* rglschnk)
  1187. {
  1188. LSERR lserr;
  1189. PILSOBJ pilsobj;
  1190. long itxtobj;
  1191. long itxtobjFirst;
  1192. long itxtobjLast;
  1193. BOOL fInterruptShaping;
  1194. long iwchFirstGlobal;
  1195. long iwchLimGlobal;
  1196. pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
  1197. itxtobj = 0;
  1198. while (itxtobj < (long)cchnk && !(((PTXTOBJ)rglschnk[itxtobj].pdobj)->txtf & txtfGlyphBased))
  1199. itxtobj++;
  1200. /* Following Assert is surprisingly wrong, counterexample: glyph-based EOP and nothing else on the line */
  1201. /* Assert(itxtobj < (long)cchnk); */
  1202. while (itxtobj < (long)cchnk)
  1203. {
  1204. itxtobjFirst = itxtobj;
  1205. iwchFirstGlobal = ((PTXTOBJ)rglschnk[itxtobjFirst].pdobj)->iwchFirst;
  1206. iwchLimGlobal = ((PTXTOBJ)rglschnk[itxtobj].pdobj)->iwchLim;
  1207. Assert(iwchLimGlobal - iwchFirstGlobal < cwchShapedTogetherMax);
  1208. itxtobj++;
  1209. fInterruptShaping = fFalse;
  1210. if (itxtobj < (long)cchnk)
  1211. iwchLimGlobal = ((PTXTOBJ)rglschnk[itxtobj].pdobj)->iwchLim;
  1212. while (iwchLimGlobal - iwchFirstGlobal < cwchShapedTogetherMax &&
  1213. !fInterruptShaping && itxtobj < (long)cchnk &&
  1214. (((PTXTOBJ)rglschnk[itxtobj].pdobj)->txtf & txtfGlyphBased))
  1215. {
  1216. lserr = (*pilsobj->plscbk->pfnFInterruptShaping)(pilsobj->pols, lstflow,
  1217. rglschnk[itxtobj-1].plsrun, rglschnk[itxtobj].plsrun, &fInterruptShaping);
  1218. if (lserr != lserrNone) return lserr;
  1219. if (!fInterruptShaping)
  1220. itxtobj++;
  1221. if (itxtobj < (long)cchnk)
  1222. iwchLimGlobal = ((PTXTOBJ)rglschnk[itxtobj].pdobj)->iwchLim;
  1223. }
  1224. itxtobjLast = itxtobj - 1;
  1225. lserr = ApplyGlyphsToRange(lstflow, rglschnk, itxtobjFirst, itxtobjLast);
  1226. if (lserr != lserrNone) return lserr;
  1227. while (itxtobj < (long)cchnk && !(((PTXTOBJ)rglschnk[itxtobj].pdobj)->txtf & txtfGlyphBased))
  1228. itxtobj++;
  1229. }
  1230. return lserrNone;
  1231. }
  1232. static LSERR ApplyGlyphsToRange(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjFirst, long itxtobjLast)
  1233. {
  1234. LSERR lserr;
  1235. PILSOBJ pilsobj;
  1236. PLNOBJ plnobj;
  1237. PTXTOBJ ptxtobjFirst;
  1238. PTXTOBJ ptxtobjLast;
  1239. PLSRUN plsrun;
  1240. long iwchFirstGlobal;
  1241. long iwchLimGlobal;
  1242. GINDEX* pgindex;
  1243. PGPROP pgprop;
  1244. DWORD cgind;
  1245. long igindFirst;
  1246. ptxtobjFirst = (PTXTOBJ)rglschnk[itxtobjFirst].pdobj;
  1247. ptxtobjLast = (PTXTOBJ)rglschnk[itxtobjLast].pdobj;
  1248. plnobj = ptxtobjFirst->plnobj;
  1249. pilsobj = plnobj->pilsobj;
  1250. iwchFirstGlobal = ptxtobjFirst->iwchFirst;
  1251. iwchLimGlobal = ptxtobjLast->iwchLim;
  1252. plsrun = rglschnk[itxtobjFirst].plsrun;
  1253. lserr = (*pilsobj->plscbk->pfnGetGlyphs)(pilsobj->pols, plsrun, &pilsobj->pwchOrig[iwchFirstGlobal],
  1254. iwchLimGlobal - iwchFirstGlobal, lstflow,
  1255. &plnobj->pgmap[iwchFirstGlobal], &pgindex, &pgprop, &cgind);
  1256. if (lserr != lserrNone) return lserr;
  1257. lserr = CheckReallocGlyphs(plnobj, cgind);
  1258. if (lserr != lserrNone) return lserr;
  1259. CopyGindices(plnobj, pgindex, pgprop, cgind, &igindFirst);
  1260. lserr = (*pilsobj->plscbk->pfnGetGlyphPositions)(pilsobj->pols, plsrun, lsdevReference, &pilsobj->pwchOrig[iwchFirstGlobal],
  1261. &plnobj->pgmap[iwchFirstGlobal], iwchLimGlobal - iwchFirstGlobal,
  1262. &plnobj->pgind[igindFirst], &plnobj->pgprop[igindFirst], cgind, lstflow,
  1263. (int*)&pilsobj->pdurGind[igindFirst], &plnobj->pgoffs[igindFirst]);
  1264. if (lserr != lserrNone) return lserr;
  1265. if (pilsobj->fDisplay)
  1266. {
  1267. if (!pilsobj->fPresEqualRef)
  1268. {
  1269. lserr = (*pilsobj->plscbk->pfnGetGlyphPositions)(pilsobj->pols, plsrun, lsdevPres, &pilsobj->pwchOrig[iwchFirstGlobal],
  1270. &plnobj->pgmap[iwchFirstGlobal], iwchLimGlobal - iwchFirstGlobal,
  1271. &plnobj->pgind[igindFirst], &plnobj->pgprop[igindFirst], cgind, lstflow,
  1272. (int*)&plnobj->pdupGind[igindFirst], &plnobj->pgoffs[igindFirst]);
  1273. if (lserr != lserrNone) return lserr;
  1274. }
  1275. /* ScaleSides will take care of the following memcpy */
  1276. // else
  1277. // memcpy (&plnobj->pdupGind[igindFirst], &pilsobj->pdurGind[igindFirst], sizeof(long)*cgind);
  1278. }
  1279. InterpretMap(plnobj, iwchFirstGlobal, iwchLimGlobal - iwchFirstGlobal, igindFirst, cgind);
  1280. Assert(plnobj->pgmap[iwchFirstGlobal] == 0);
  1281. if (pilsobj->fDisplay && (pilsobj->grpf & fTxtVisiSpaces) && rglschnk[itxtobjFirst].cpFirst >= 0)
  1282. {
  1283. FixGlyphSpaces(lstflow, rglschnk, itxtobjFirst, igindFirst, itxtobjLast);
  1284. }
  1285. lserr = FixTxtobjs(rglschnk, itxtobjFirst, igindFirst, itxtobjLast);
  1286. if (lserr != lserrNone) return lserr;
  1287. ptxtobjFirst->txtf |= txtfFirstShaping;
  1288. while (ptxtobjLast->iwchLim == ptxtobjLast->iwchFirst)
  1289. {
  1290. itxtobjLast--;
  1291. Assert (itxtobjLast >= itxtobjFirst);
  1292. ptxtobjLast = (PTXTOBJ)rglschnk[itxtobjLast].pdobj;
  1293. }
  1294. ptxtobjLast->txtf |= txtfLastShaping;
  1295. return lserrNone;
  1296. }
  1297. static LSERR FixTxtobjs(const LSCHNKE* rglschnk, long itxtobjFirst, long igindVeryFirst, long itxtobjLast)
  1298. {
  1299. LSERR lserr;
  1300. PILSOBJ pilsobj;
  1301. PTXTOBJ ptxtobj;
  1302. long itxtobj;
  1303. long iwchFirst;
  1304. long iwchLast;
  1305. long dcpFirst;
  1306. long durTotal;
  1307. long iwSpacesVeryLim;
  1308. long iwSpacesFirst;
  1309. long iwSpacesLim;
  1310. int igind;
  1311. pilsobj = ((PTXTOBJ)rglschnk[itxtobjFirst].pdobj)->plnobj->pilsobj;
  1312. iwchFirst = ((PTXTOBJ)rglschnk[itxtobjFirst].pdobj)->iwchFirst;
  1313. iwSpacesVeryLim = ((PTXTOBJ)rglschnk[itxtobjLast].pdobj)->u.reg.iwSpacesLim;
  1314. for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
  1315. {
  1316. ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
  1317. Assert(ptxtobj->txtkind == txtkindRegular);
  1318. Assert((long)rglschnk[itxtobj].dcp == ptxtobj->iwchLim - ptxtobj->iwchFirst);
  1319. dcpFirst = iwchFirst - ptxtobj->iwchFirst;
  1320. Assert(dcpFirst >= 0);
  1321. ptxtobj->iwchFirst = iwchFirst;
  1322. iwchLast = ptxtobj->iwchLim - 1;
  1323. if (iwchLast < iwchFirst)
  1324. {
  1325. ptxtobj->iwchLim = iwchFirst;
  1326. ptxtobj->u.reg.iwSpacesLim = ptxtobj->u.reg.iwSpacesFirst;
  1327. Assert(itxtobj > itxtobjFirst);
  1328. ptxtobj->igindFirst = ((PTXTOBJ)rglschnk[itxtobj-1].pdobj)->iwchLim;
  1329. ptxtobj->igindLim = ptxtobj->igindFirst;
  1330. lserr = LsdnSetSimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, 0);
  1331. if (lserr != lserrNone) return lserr;
  1332. lserr = LsdnResetDcpMerge(pilsobj->plsc,
  1333. ptxtobj->plsdnUpNode, rglschnk[itxtobj].cpFirst + dcpFirst, 0);
  1334. if (lserr != lserrNone) return lserr;
  1335. /* It would be cleaner to mark these dobj's by another flag, but is it
  1336. worth to introduce one?
  1337. */
  1338. ptxtobj->txtf |= txtfSkipAtNti;
  1339. }
  1340. else
  1341. {
  1342. while (!pilsobj->ptxtinf[iwchLast].fLastInContext)
  1343. iwchLast++;
  1344. Assert(iwchLast < (long)pilsobj->wchMac);
  1345. ptxtobj->iwchLim = iwchLast + 1;
  1346. lserr = LsdnResetDcpMerge(pilsobj->plsc, ptxtobj->plsdnUpNode, rglschnk[itxtobj].cpFirst + dcpFirst, iwchLast + 1 - iwchFirst);
  1347. if (lserr != lserrNone) return lserr;
  1348. Assert (iwchFirst == ptxtobj->iwchFirst);
  1349. Assert (FIwchFirstInContext (pilsobj, iwchFirst));
  1350. Assert (FIwchLastInContext (pilsobj, iwchLast));
  1351. ptxtobj->igindFirst = IgindFirstFromIwchVeryFirst (ptxtobj, igindVeryFirst, iwchFirst);
  1352. ptxtobj->igindLim = IgindLastFromIwchVeryFirst (ptxtobj, igindVeryFirst, iwchLast) + 1;
  1353. durTotal = 0;
  1354. for (igind = ptxtobj->igindFirst; igind < ptxtobj->igindLim; igind++)
  1355. durTotal += pilsobj->pdurGind[igind];
  1356. lserr = LsdnSetSimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, durTotal);
  1357. if (lserr != lserrNone) return lserr;
  1358. iwSpacesFirst = ptxtobj->u.reg.iwSpacesFirst;
  1359. iwSpacesLim = ptxtobj->u.reg.iwSpacesLim;
  1360. while (iwSpacesLim < iwSpacesVeryLim && pilsobj->pwSpaces[iwSpacesLim] < ptxtobj->iwchLim)
  1361. {
  1362. iwSpacesLim++;
  1363. }
  1364. while (iwSpacesFirst < iwSpacesLim && pilsobj->pwSpaces[iwSpacesFirst] < ptxtobj->iwchFirst)
  1365. {
  1366. iwSpacesFirst++;
  1367. }
  1368. ptxtobj->u.reg.iwSpacesFirst = iwSpacesFirst;
  1369. ptxtobj->u.reg.iwSpacesLim = iwSpacesLim;
  1370. iwchFirst = ptxtobj->iwchLim;
  1371. }
  1372. }
  1373. return lserrNone;
  1374. }
  1375. static LSERR CheckReallocGlyphs(PLNOBJ plnobj, long cglyphs)
  1376. {
  1377. LSERR lserr;
  1378. PILSOBJ pilsobj;
  1379. long igindLocalStart;
  1380. long cNew;
  1381. void* pTemp;
  1382. pilsobj = plnobj->pilsobj;
  1383. igindLocalStart = pilsobj->gindMac;
  1384. if (plnobj->pgmap == NULL)
  1385. {
  1386. pTemp = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(GMAP) * pilsobj->wchMax );
  1387. if (pTemp == NULL) return lserrOutOfMemory;
  1388. plnobj->pgmap = pTemp;
  1389. }
  1390. if ( igindLocalStart + cglyphs <= (long)pilsobj->gindMax - 2)
  1391. {
  1392. return lserrNone;
  1393. }
  1394. else
  1395. {
  1396. cNew = gindAddM + pilsobj->gindMax;
  1397. if (cNew - 2 < igindLocalStart + cglyphs)
  1398. {
  1399. cNew = igindLocalStart + cglyphs + 2;
  1400. }
  1401. lserr = Realloc(pilsobj, &pilsobj->pdurGind, sizeof(long) * cNew);
  1402. if (lserr != lserrNone) return lserr;
  1403. lserr = Realloc(pilsobj, &pilsobj->pginf, sizeof(TXTGINF) * cNew);
  1404. if (lserr != lserrNone) return lserr;
  1405. lserr = Realloc(pilsobj, &pilsobj->pduGright, sizeof(long) * cNew);
  1406. if (lserr != lserrNone) return lserr;
  1407. lserr = Realloc(pilsobj, &pilsobj->plsexpinf, sizeof(LSEXPINFO) * cNew);
  1408. if (lserr != lserrNone) return lserr;
  1409. lserr = Realloc(pilsobj, &plnobj->pgind, sizeof(GINDEX) * cNew);
  1410. if (lserr != lserrNone) return lserr;
  1411. lserr = Realloc(pilsobj, &plnobj->pdupGind, sizeof(long) * cNew);
  1412. if (lserr != lserrNone) return lserr;
  1413. lserr = Realloc(pilsobj, &plnobj->pgoffs, sizeof(GOFFSET) * cNew);
  1414. if (lserr != lserrNone) return lserr;
  1415. lserr = Realloc(pilsobj, &plnobj->pexpt, sizeof(EXPTYPE) * cNew);
  1416. if (lserr != lserrNone) return lserr;
  1417. lserr = Realloc(pilsobj, &plnobj->pdupBeforeJust, sizeof(long) * cNew);
  1418. if (lserr != lserrNone) return lserr;
  1419. lserr = Realloc(pilsobj, &plnobj->pgprop, sizeof(GPROP) * cNew);
  1420. if (lserr != lserrNone) return lserr;
  1421. memset(&pilsobj->plsexpinf[pilsobj->gindMax], 0, sizeof(LSEXPINFO) * (cNew - pilsobj->gindMax) );
  1422. memset(&pilsobj->pduGright[pilsobj->gindMax], 0, sizeof(long) * (cNew - pilsobj->gindMax) );
  1423. memset(&plnobj->pexpt[pilsobj->gindMax], 0, sizeof(EXPTYPE) * (cNew - pilsobj->gindMax) );
  1424. pilsobj->gindMax = cNew;
  1425. plnobj->gindMax = cNew;
  1426. }
  1427. return lserrNone;
  1428. }
  1429. static LSERR Realloc(PILSOBJ pilsobj, void** pInOut, long cbytes)
  1430. {
  1431. void* pTemp;
  1432. if (*pInOut == NULL)
  1433. pTemp = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, cbytes );
  1434. else
  1435. pTemp = (*pilsobj->plscbk->pfnReallocPtr)(pilsobj->pols, *pInOut, cbytes );
  1436. if (pTemp == NULL)
  1437. {
  1438. return lserrOutOfMemory;
  1439. }
  1440. *pInOut = pTemp;
  1441. return lserrNone;
  1442. }
  1443. static void CopyGindices(PLNOBJ plnobj, GINDEX* pgindex, PGPROP pgprop, long cgind, long* pigindFirst)
  1444. {
  1445. *pigindFirst = plnobj->pilsobj->gindMac;
  1446. memcpy(&plnobj->pgind[*pigindFirst], pgindex, sizeof(GINDEX) * cgind);
  1447. memcpy(&plnobj->pgprop[*pigindFirst], pgprop, sizeof(GPROP) * cgind);
  1448. plnobj->pilsobj->gindMac += cgind;
  1449. }
  1450. /* F I X G L Y P H S P A C E S */
  1451. /*----------------------------------------------------------------------------
  1452. %%Function: FixGlyphSpaces
  1453. %%Contact: sergeyge
  1454. Fixes space glyph index for the Visi Spaces situation
  1455. ----------------------------------------------------------------------------*/
  1456. static LSERR FixGlyphSpaces(LSTFLOW lstflow, const LSCHNKE* rglschnk,
  1457. long itxtobjFirst, long igindVeryFirst, long itxtobjLast)
  1458. {
  1459. LSERR lserr;
  1460. PILSOBJ pilsobj;
  1461. PLNOBJ plnobj;
  1462. PTXTOBJ ptxtobj;
  1463. long itxtobj;
  1464. long iwSpace;
  1465. long iwch;
  1466. GMAP gmapTemp;
  1467. GINDEX* pgindTemp;
  1468. GPROP* pgpropTemp;
  1469. DWORD cgind;
  1470. plnobj = ((PTXTOBJ)rglschnk[itxtobjFirst].pdobj)->plnobj;
  1471. pilsobj = plnobj->pilsobj;
  1472. lserr = (*pilsobj->plscbk->pfnGetGlyphs)(pilsobj->pols, rglschnk[itxtobjFirst].plsrun,
  1473. &pilsobj->wchVisiSpace, 1, lstflow, &gmapTemp, &pgindTemp, &pgpropTemp, &cgind);
  1474. if (lserr != lserrNone) return lserr;
  1475. if (cgind != 1)
  1476. {
  1477. return lserrNone;
  1478. }
  1479. for (itxtobj=itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
  1480. {
  1481. ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
  1482. Assert(ptxtobj->txtkind == txtkindRegular);
  1483. for (iwSpace = ptxtobj->u.reg.iwSpacesFirst; iwSpace < ptxtobj->u.reg.iwSpacesLim; iwSpace++)
  1484. {
  1485. iwch = pilsobj->pwSpaces[iwSpace];
  1486. if ( FIwchOneToOne(pilsobj, iwch) )
  1487. plnobj->pgind[IgindFirstFromIwchVeryFirst (ptxtobj, igindVeryFirst, iwch)] = *pgindTemp;
  1488. }
  1489. }
  1490. return lserrNone;
  1491. }