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.

1297 lines
38 KiB

  1. #include "lsmem.h"
  2. #include "lstxtcmp.h"
  3. #include "lstxtmod.h"
  4. #include "lstxtmap.h"
  5. #include "lschp.h"
  6. #include "lspract.h"
  7. #include "lsems.h"
  8. #include "txtils.h"
  9. #include "txtln.h"
  10. #include "txtobj.h"
  11. #define min(a,b) ((a) > (b) ? (b) : (a))
  12. #define max(a,b) ((a) < (b) ? (b) : (a))
  13. typedef struct
  14. {
  15. long rgdurPrior[2];
  16. long rgcExpPrior[2];
  17. long cExpOppr;
  18. } EXPINFO;
  19. typedef struct
  20. {
  21. long durComp;
  22. long cCompOppr;
  23. } COMPINFO;
  24. static LSERR GetExpandInfo(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, BOOL fScaled,
  25. long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLim, EXPINFO* pexpinfo);
  26. static void GetCompressInfo(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
  27. long itxtobjLast, long iwchLim, COMPINFO* pcompinfo);
  28. static LSERR CheckExpandSpace(PILSOBJ pilsobj, LSEMS* plsems, long iwchPrev, long iwch, long iwchNext,
  29. PTXTOBJ ptxtobjCur, PLSRUN plsrunPrev, PLSRUN plsrunCur, PLSRUN plsrunNext,
  30. BOOL* pfExpandOpp, long* pdurChange);
  31. static LSERR CheckExpandOnRun(PILSOBJ pilsobj, LSEMS* plsems, long iwch, long iwchNext, PTXTOBJ ptxtobjCur,
  32. PLSRUN plsrunCur, PLSRUN plsrunNext, BOOL* pfExpandOpp, long* pdurChange);
  33. static void ApplyPriorCompression(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
  34. long itxtobjLast, long iwchLim, BYTE prior,
  35. long durToCompress, long durAvailable, long cExpOppr);
  36. static void ApplyPriorExpansion(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
  37. long txtobjLast, long iwchLim, BYTE prior, long durToExpand, long durAvailable, long cExpOppr);
  38. static void ApplyFullExpansion(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
  39. long itxtobjLast, long iwchLim, long durToExpand, long cExpOppr, long cNonText, long* pdurNonText);
  40. static LSERR CheckCompSpace(PILSOBJ pilsobj, LSEMS* plsems, long iwchPrev, long iwch, long iwchNext,
  41. PTXTOBJ ptxtobjCur, PLSRUN plsrunPrev, PLSRUN plsrunCur, PLSRUN plsrunNext, long* pdurChange);
  42. static LSERR CheckCompOnRun(PILSOBJ pilsobj, LSEMS* plsems, long iwch, long iwchNext, PTXTOBJ ptxtobjCur,
  43. PLSRUN plsrunCur, PLSRUN plsrunNext, long* pdurChange);
  44. static void SetComp(PILSOBJ pilsobj, long iwch, BYTE prior, BYTE side, long durChange);
  45. static BOOL GetNextRun(const LSGRCHNK* plsgrchnk, long itxtobj, long* pitxtobjNext);
  46. static void GetPrevCharRun(const LSGRCHNK* plsgrchnk, long itxtobj, long iwch, long* piwchPrev, PLSRUN* pplsrunPrev);
  47. /* F E T C H C O M P R E S S I N F O */
  48. /*----------------------------------------------------------------------------
  49. %%Function: FetchCompressInfo
  50. %%Contact: sergeyge
  51. Fetches compression information until durCompressMaxStop exceeded
  52. ---------------------------------------------------------------------------*/
  53. LSERR FetchCompressInfo(const LSGRCHNK* plsgrchnk, BOOL fFirstOnLine, LSTFLOW lstflow,
  54. long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLim,
  55. long durCompressMaxStop, long* pdurCompressTotal)
  56. {
  57. LSERR lserr;
  58. PILSOBJ pilsobj;
  59. TXTINF* rgtxtinf;
  60. WCHAR* rgwchOrig;
  61. PTXTOBJ ptxtobj;
  62. PLSRUN plsrunCur;
  63. PLSRUN plsrunPrev;
  64. PLSRUN plsrunNext = NULL;
  65. PCLSCHP plschp;
  66. LSPRACT lspract;
  67. BYTE side;
  68. BYTE sideFinal;
  69. long durChange;
  70. long durTemp;
  71. LSEMS lsems;
  72. BOOL fNextAdjacentFound;
  73. long itxtobj;
  74. long itxtobjNext;
  75. long itxtobjLastProcessed;
  76. long itxtobjCompressFetchedLim;
  77. long iwchCompressFetchedLim;
  78. long iwchLimDobj;
  79. long iwch;
  80. long iwchPrev;
  81. long iwchNext;
  82. BOOL fGlyphBased;
  83. *pdurCompressTotal = 0;
  84. pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  85. rgtxtinf = pilsobj->ptxtinf;
  86. /* rgtxtinf == NULL means that there were no runs which possibly could introduce compress opportunity */
  87. if (rgtxtinf == NULL)
  88. return lserrNone;
  89. iwch = iwchFirst;
  90. rgwchOrig = pilsobj->pwchOrig;
  91. itxtobjCompressFetchedLim = 0;
  92. iwchCompressFetchedLim = 0;
  93. if (pilsobj->iwchCompressFetchedFirst == iwchFirst)
  94. {
  95. itxtobjCompressFetchedLim = pilsobj->itxtobjCompressFetchedLim;
  96. iwchCompressFetchedLim = pilsobj->iwchCompressFetchedLim;
  97. }
  98. itxtobj = itxtobjFirst;
  99. itxtobjLastProcessed = itxtobj-1;
  100. if (itxtobj < (long)plsgrchnk->clsgrchnk)
  101. GetNextRun(plsgrchnk, itxtobj, &itxtobj);
  102. Assert( itxtobj == (long)plsgrchnk->clsgrchnk ||
  103. ((PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj)->iwchLim >
  104. ((PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj)->iwchFirst);
  105. while(itxtobj <= itxtobjLast && *pdurCompressTotal < durCompressMaxStop)
  106. {
  107. itxtobjLastProcessed = itxtobj;
  108. fNextAdjacentFound = GetNextRun(plsgrchnk, itxtobj + 1, &itxtobjNext);
  109. ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
  110. plsrunCur = plsgrchnk->plschnk[itxtobj].plsrun;
  111. plschp = plsgrchnk->plschnk[itxtobj].plschp;
  112. iwchLimDobj = iwchLim;
  113. if (itxtobj < itxtobjLast)
  114. iwchLimDobj = ptxtobj->iwchLim;
  115. if (itxtobj > itxtobjCompressFetchedLim - 1 ||
  116. itxtobj == itxtobjCompressFetchedLim - 1 && iwchLimDobj > iwchCompressFetchedLim)
  117. {
  118. lserr = (*pilsobj->plscbk->pfnGetEms)(pilsobj->pols, plsrunCur, lstflow, &lsems);
  119. if (lserr != lserrNone) return lserr;
  120. }
  121. iwch = iwchFirst;
  122. if (itxtobj > itxtobjFirst)
  123. iwch = ptxtobj->iwchFirst;
  124. for (; iwch < iwchLimDobj && *pdurCompressTotal < durCompressMaxStop; iwch++)
  125. {
  126. if (itxtobj < itxtobjCompressFetchedLim - 1 ||
  127. itxtobj == itxtobjCompressFetchedLim - 1 && iwch < iwchCompressFetchedLim)
  128. {
  129. if (rgtxtinf[iwch].prior != prior0)
  130. *pdurCompressTotal -= pilsobj->pduAdjust[iwch];
  131. }
  132. else
  133. {
  134. fGlyphBased = (ptxtobj->txtf & txtfGlyphBased);
  135. rgtxtinf[iwch].prior = prior0;
  136. if (!fGlyphBased && plschp->fCompressTable && !rgtxtinf[iwch].fModWidthOnRun &&
  137. !rgtxtinf[iwch].fModWidthSpace)
  138. {
  139. lspract = pilsobj->plspract[pilsobj->pilspract[rgtxtinf[iwch].mwcls]];
  140. Assert(lspract.prior <= pilsobj->cCompPrior);
  141. if (lspract.prior != prior0)
  142. {
  143. GetChanges(lspract.lsact, &lsems, pilsobj->pdur[iwch] - pilsobj->pdurRight[iwch] - pilsobj->pdurLeft[iwch],
  144. fFalse, &side, &durTemp);
  145. TranslateChanges(side, durTemp, pilsobj->pdur[iwch], pilsobj->pdurRight[iwch], pilsobj->pdurLeft[iwch],
  146. &sideFinal, &durChange);
  147. if (sideFinal != sideNone && durChange < 0)
  148. {
  149. if (itxtobj > itxtobjFirst || itxtobj == itxtobjFirst && iwch > iwchFirst ||
  150. !fFirstOnLine || sideFinal != sideLeft)
  151. {
  152. SetComp(pilsobj, iwch, lspract.prior, sideFinal, durChange);
  153. *pdurCompressTotal -= durChange;
  154. }
  155. }
  156. }
  157. }
  158. if (rgwchOrig[iwch] == pilsobj->wchSpace && plschp->fCompressSpace &&
  159. rgtxtinf[iwch].prior == prior0 && (!fGlyphBased || FIwchOneToOne(pilsobj, iwch)))
  160. {
  161. plsrunNext = NULL;
  162. iwchNext = 0;
  163. /* we take ptxtobj->iwchLim instead of iwchLimDobj because iwchLimDobj char(last char
  164. before spaces on the line must be used for context considerations
  165. */
  166. if (iwch < ptxtobj->iwchLim - 1)
  167. {
  168. plsrunNext = plsrunCur;
  169. iwchNext = iwch + 1;
  170. }
  171. else if (fNextAdjacentFound)
  172. {
  173. plsrunNext = plsgrchnk->plschnk[itxtobjNext].plsrun;
  174. iwchNext = ((PTXTOBJ)plsgrchnk->plschnk[itxtobjNext].pdobj)->iwchFirst;
  175. }
  176. GetPrevCharRun(plsgrchnk, itxtobj, iwch, &iwchPrev, &plsrunPrev);
  177. lserr = CheckCompSpace(pilsobj, &lsems, iwchPrev, iwch, iwchNext, ptxtobj,
  178. plsrunPrev, plsrunCur, plsrunNext, &durChange);
  179. if (lserr != lserrNone) return lserr;
  180. *pdurCompressTotal -= durChange;
  181. }
  182. if (iwch == ptxtobj->iwchLim - 1 && plschp->fCompressOnRun && fNextAdjacentFound &&
  183. rgtxtinf[iwch].prior == prior0)
  184. {
  185. plsrunNext = plsgrchnk->plschnk[itxtobjNext].plsrun;
  186. iwchNext = ((PTXTOBJ)plsgrchnk->plschnk[itxtobjNext].pdobj)->iwchFirst;
  187. lserr = CheckCompOnRun(pilsobj, &lsems, iwch, iwchNext, ptxtobj, plsrunCur, plsrunNext, &durChange);
  188. if (lserr != lserrNone) return lserr;
  189. *pdurCompressTotal -= durChange;
  190. }
  191. }
  192. }
  193. itxtobj = itxtobjNext;
  194. }
  195. pilsobj->iwchCompressFetchedFirst = iwchFirst;
  196. pilsobj->itxtobjCompressFetchedLim = itxtobjLastProcessed + 1;
  197. pilsobj->iwchCompressFetchedLim = min(iwch, iwchLim);
  198. return lserrNone;
  199. }
  200. /* G E T C O M P L A S T C H A R I N F O */
  201. /*----------------------------------------------------------------------------
  202. %%Function: GetCompLastCharInfo
  203. %%Contact: sergeyge
  204. ---------------------------------------------------------------------------*/
  205. void GetCompLastCharInfo(PILSOBJ pilsobj, long iwchLast, MWCLS* pmwcls,
  206. long* pdurCompRight, long* pdurCompLeft)
  207. {
  208. /* Strong assumption for this function is that it is not called on GlyphBased run */
  209. TXTINF txtinf;
  210. *pdurCompRight = 0;
  211. *pdurCompLeft = 0;
  212. /* ptxtinf == NULL means that there were no runs which possibly can introduce compress opportunity */
  213. if (pilsobj->ptxtinf == NULL)
  214. return;
  215. txtinf = pilsobj->ptxtinf[iwchLast];
  216. *pmwcls = (MWCLS)txtinf.mwcls;
  217. if (txtinf.prior != prior0)
  218. {
  219. InterpretChanges(pilsobj, iwchLast, (BYTE)txtinf.side, pilsobj->pduAdjust[iwchLast], pdurCompLeft, pdurCompRight);
  220. Assert(pilsobj->pduAdjust[iwchLast] == *pdurCompLeft + *pdurCompRight);
  221. }
  222. *pdurCompLeft = - *pdurCompLeft;
  223. *pdurCompRight = - *pdurCompRight;
  224. }
  225. /* C O M P R E S S L A S T C H A R R I G H T */
  226. /*----------------------------------------------------------------------------
  227. %%Function: CompressLastCharRight
  228. %%Contact: sergeyge
  229. ---------------------------------------------------------------------------*/
  230. void CompressLastCharRight(PILSOBJ pilsobj, long iwchLast, long durToAdjustRight)
  231. {
  232. /* Strong assumption for this function is that it is not called on GlyphBased run */
  233. pilsobj->pdur[iwchLast] -= durToAdjustRight;
  234. Assert(pilsobj->pdurRight != NULL);
  235. Assert(pilsobj->pdurLeft != NULL);
  236. Assert(pilsobj->ptxtinf != NULL);
  237. pilsobj->pdurRight[iwchLast] -= durToAdjustRight;
  238. if (durToAdjustRight > 0 && pilsobj->ptxtinf[iwchLast].prior != prior0)
  239. {
  240. if (pilsobj->ptxtinf[iwchLast].side == sideRight)
  241. {
  242. pilsobj->ptxtinf[iwchLast].prior = prior0;
  243. pilsobj->pduAdjust[iwchLast] = 0;
  244. }
  245. else if (pilsobj->ptxtinf[iwchLast].side == sideLeftRight)
  246. {
  247. pilsobj->ptxtinf[iwchLast].side = sideLeft;
  248. pilsobj->pduAdjust[iwchLast] += durToAdjustRight;
  249. }
  250. else
  251. {
  252. Assert(fFalse);
  253. }
  254. }
  255. }
  256. /* A P P L Y C O M P R E S S */
  257. /*----------------------------------------------------------------------------
  258. %%Function: ApplyCompress
  259. %%Contact: sergeyge
  260. Applies prioratized compression
  261. ---------------------------------------------------------------------------*/
  262. LSERR ApplyCompress(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow,
  263. long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLim, long durToCompress)
  264. {
  265. PILSOBJ pilsobj;
  266. COMPINFO rgcompinfo[5];
  267. COMPINFO* pcompinfo;
  268. BOOL fReleasePcompinfo;
  269. long i;
  270. Unreferenced(lstflow);
  271. pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  272. fReleasePcompinfo = fFalse;
  273. pcompinfo = rgcompinfo;
  274. if (pilsobj->cCompPrior > 5)
  275. {
  276. pcompinfo = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(COMPINFO) * pilsobj->cCompPrior);
  277. if (pcompinfo == NULL)
  278. return lserrOutOfMemory;
  279. else
  280. fReleasePcompinfo = fTrue;
  281. }
  282. GetCompressInfo(plsgrchnk, itxtobjFirst, iwchFirst, itxtobjLast, iwchLim, pcompinfo);
  283. for (i = 0; i < (long)pilsobj->cCompPrior && durToCompress > 0; i++)
  284. {
  285. if (pcompinfo[i].cCompOppr > 0)
  286. {
  287. ApplyPriorCompression(plsgrchnk, itxtobjFirst, iwchFirst, itxtobjLast, iwchLim, (BYTE)(i+1), durToCompress,
  288. pcompinfo[i].durComp, pcompinfo[i].cCompOppr);
  289. durToCompress -= pcompinfo[i].durComp;
  290. }
  291. }
  292. /* Following Assert is not compatible with the squeezing mode */
  293. /*Assert(durToCompress <= 0);*/
  294. if (fReleasePcompinfo)
  295. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pcompinfo);
  296. return lserrNone;
  297. }
  298. /* A P P L Y E X P A N D */
  299. /*----------------------------------------------------------------------------
  300. %%Function: ApplyExpand
  301. %%Contact: sergeyge
  302. Applies prioratized expansion
  303. ---------------------------------------------------------------------------*/
  304. LSERR ApplyExpand(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, BOOL fScaled, long itxtobjFirst, long iwchFirst,
  305. long itxtobjLast, long iwchLim, DWORD cNonTextObjects, long durToExpand,
  306. long* pdurExtNonText, BOOL* pfFinalAdjustNeeded)
  307. {
  308. LSERR lserr;
  309. PILSOBJ pilsobj;
  310. EXPINFO expinfo;
  311. long i;
  312. pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  313. *pdurExtNonText = 0;
  314. lserr = GetExpandInfo(plsgrchnk, lstflow, fScaled, itxtobjFirst, iwchFirst, itxtobjLast, iwchLim, &expinfo);
  315. if (lserr != lserrNone) return lserr;
  316. for (i = 0; i < 2 && durToExpand > 0; i++)
  317. {
  318. if (expinfo.rgcExpPrior[i])
  319. {
  320. ApplyPriorExpansion(plsgrchnk, itxtobjFirst, iwchFirst, itxtobjLast, iwchLim, (BYTE)(i+1), durToExpand,
  321. expinfo.rgdurPrior[i], expinfo.rgcExpPrior[i]);
  322. durToExpand -= expinfo.rgdurPrior[i];
  323. }
  324. }
  325. if (durToExpand > 0)
  326. {
  327. ApplyFullExpansion(plsgrchnk, itxtobjFirst, iwchFirst, itxtobjLast, iwchLim, durToExpand,
  328. expinfo.cExpOppr, cNonTextObjects, pdurExtNonText);
  329. }
  330. *pfFinalAdjustNeeded = (expinfo.cExpOppr + cNonTextObjects > 0);
  331. return lserrNone;
  332. }
  333. /* A P P L Y D I S T R I B U T I O N */
  334. /*----------------------------------------------------------------------------
  335. %%Function: ApplyDistribution
  336. %%Contact: sergeyge
  337. Applies equal distribution to text chunk
  338. ---------------------------------------------------------------------------*/
  339. void ApplyDistribution(const LSGRCHNK* plsgrchnk, DWORD cNonText,
  340. long durToDistribute, long* pdurNonTextObjects)
  341. {
  342. PILSOBJ pilsobj;
  343. long clschnk;
  344. PTXTOBJ ptxtobj;
  345. long itxtobj;
  346. long iwchFirst;
  347. long iwchLim;
  348. long iwch;
  349. long igind;
  350. long durToAdd;
  351. long cwchToDistribute;
  352. long cwchToDistributeAll;
  353. long wdurBound;
  354. long iwchUsed;
  355. clschnk = (long)plsgrchnk->clsgrchnk;
  356. Assert(clschnk > 0);
  357. pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  358. cwchToDistribute = 0;
  359. for (itxtobj = 0; itxtobj < clschnk; itxtobj++)
  360. {
  361. ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
  362. iwchFirst = ptxtobj->iwchFirst;
  363. iwchLim = iwchFirst + plsgrchnk->plschnk[itxtobj].dcp;
  364. if (itxtobj == clschnk - 1)
  365. iwchLim--;
  366. if (ptxtobj->txtf & txtfGlyphBased)
  367. {
  368. for (iwch = iwchFirst; iwch < iwchLim; iwch++)
  369. {
  370. if (FIwchLastInContext(pilsobj, iwch))
  371. cwchToDistribute++;
  372. }
  373. }
  374. else
  375. cwchToDistribute += (iwchLim - iwchFirst);
  376. }
  377. cwchToDistributeAll = cwchToDistribute + cNonText;
  378. *pdurNonTextObjects = 0;
  379. if (cwchToDistributeAll == 0)
  380. return;
  381. *pdurNonTextObjects = durToDistribute * cNonText / cwchToDistributeAll;
  382. durToDistribute -= *pdurNonTextObjects;
  383. if (cwchToDistribute == 0)
  384. return;
  385. durToAdd = durToDistribute / cwchToDistribute;
  386. wdurBound = durToDistribute - durToAdd * cwchToDistribute;
  387. iwchUsed = 0;
  388. for (itxtobj = 0; itxtobj < clschnk; itxtobj++)
  389. {
  390. ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
  391. iwchFirst = ptxtobj->iwchFirst;
  392. iwchLim = iwchFirst + plsgrchnk->plschnk[itxtobj].dcp;
  393. if (itxtobj == clschnk - 1)
  394. iwchLim--;
  395. if (ptxtobj->txtf & txtfGlyphBased)
  396. {
  397. for (iwch = iwchFirst; iwch < iwchLim; iwch++)
  398. {
  399. if (FIwchLastInContext(pilsobj, iwch))
  400. {
  401. igind = IgindLastFromIwch(ptxtobj, iwch);
  402. igind = IgindBaseFromIgind(pilsobj, igind);
  403. if (iwchUsed < wdurBound)
  404. {
  405. ApplyGlyphChanges(pilsobj, igind, durToAdd + 1);
  406. }
  407. else
  408. {
  409. ApplyGlyphChanges(pilsobj, igind, durToAdd);
  410. }
  411. iwchUsed++;
  412. }
  413. }
  414. }
  415. else
  416. {
  417. for (iwch = iwchFirst; iwch < iwchLim; iwch++)
  418. {
  419. if (iwchUsed < wdurBound)
  420. {
  421. ApplyChanges(pilsobj, iwch, sideRight, durToAdd + 1);
  422. }
  423. else
  424. {
  425. ApplyChanges(pilsobj, iwch, sideRight, durToAdd);
  426. }
  427. iwchUsed++;
  428. }
  429. }
  430. }
  431. }
  432. /* Internal functions implementation */
  433. /* G E T E X P A N D I N F O */
  434. /*----------------------------------------------------------------------------
  435. %%Function: GetExpandInfo
  436. %%Contact: sergeyge
  437. Collects expansion information
  438. ---------------------------------------------------------------------------*/
  439. static LSERR GetExpandInfo(const LSGRCHNK* plsgrchnk, LSTFLOW lstflow, BOOL fScaled,
  440. long itxtobjFirst, long iwchFirst, long itxtobjLast, long iwchLim, EXPINFO* pexpinfo)
  441. {
  442. LSERR lserr;
  443. PILSOBJ pilsobj;
  444. TXTINF* rgtxtinf;
  445. WCHAR* rgwchOrig;
  446. PTXTOBJ ptxtobj;
  447. PLSRUN plsrunCur;
  448. PLSRUN plsrunPrev;
  449. PLSRUN plsrunNext;
  450. PCLSCHP plschp;
  451. long durChange;
  452. LSEMS lsems;
  453. BOOL fNextAdjacentFound;
  454. long itxtobj;
  455. long itxtobjNext;
  456. long iwchLimDobj;
  457. LSEXPAN lsexpan;
  458. long iwch;
  459. long iwchPrev;
  460. long iwchNext;
  461. BOOL fExpandOpp;
  462. BOOL fGlyphBased;
  463. memset(pexpinfo, 0, sizeof(EXPINFO));
  464. pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  465. rgtxtinf = pilsobj->ptxtinf;
  466. /* rgtxtinf == NULL means that there were no runs which possibly can introduce expansion opportunity */
  467. if (rgtxtinf == NULL)
  468. return lserrNone;
  469. rgwchOrig = pilsobj->pwchOrig;
  470. itxtobj = itxtobjFirst;
  471. if (itxtobj < (long)plsgrchnk->clsgrchnk)
  472. GetNextRun(plsgrchnk, itxtobj, &itxtobj);
  473. Assert(itxtobj == (long)plsgrchnk->clsgrchnk ||
  474. ((PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj)->iwchLim >
  475. ((PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj)->iwchFirst);
  476. while(itxtobj <= itxtobjLast)
  477. {
  478. fNextAdjacentFound = GetNextRun(plsgrchnk, itxtobj + 1, &itxtobjNext);
  479. ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
  480. fGlyphBased = (ptxtobj->txtf & txtfGlyphBased);
  481. plsrunCur = plsgrchnk->plschnk[itxtobj].plsrun;
  482. plschp = plsgrchnk->plschnk[itxtobj].plschp;
  483. lserr = (*pilsobj->plscbk->pfnGetEms)(pilsobj->pols, plsrunCur, lstflow, &lsems);
  484. if (lserr != lserrNone) return lserr;
  485. iwchLimDobj = iwchLim;
  486. if (itxtobj < itxtobjLast)
  487. iwchLimDobj = ptxtobj->iwchLim;
  488. iwch = iwchFirst;
  489. if (itxtobj > itxtobjFirst)
  490. iwch = ptxtobj->iwchFirst;
  491. for (; iwch < iwchLimDobj; iwch++)
  492. {
  493. rgtxtinf[iwch].prior = prior0;
  494. if (rgwchOrig[iwch] == pilsobj->wchSpace && plschp->fExpandSpace &&
  495. (!fGlyphBased || FIwchOneToOne(pilsobj, iwch)))
  496. {
  497. plsrunNext = NULL;
  498. iwchNext = 0;
  499. /* we take ptxtobj->iwchLim instead of iwchLimDobj because iwchLimInDobj char(last char
  500. before spaces on the line must be used for context considerations
  501. */
  502. if (iwch < ptxtobj->iwchLim - 1)
  503. {
  504. plsrunNext = plsrunCur;
  505. iwchNext = iwch + 1;
  506. }
  507. else if (fNextAdjacentFound)
  508. {
  509. plsrunNext = plsgrchnk->plschnk[itxtobjNext].plsrun;
  510. iwchNext = ((PTXTOBJ)plsgrchnk->plschnk[itxtobjNext].pdobj)->iwchFirst;
  511. }
  512. GetPrevCharRun(plsgrchnk, itxtobj, iwch, &iwchPrev, &plsrunPrev);
  513. lserr = CheckExpandSpace(pilsobj, &lsems, iwchPrev, iwch, iwchNext, ptxtobj,
  514. plsrunPrev, plsrunCur, plsrunNext, &fExpandOpp, &durChange);
  515. if (lserr != lserrNone) return lserr;
  516. if (fExpandOpp)
  517. {
  518. pexpinfo->cExpOppr++;
  519. rgtxtinf[iwch].fExpand = fTrue;
  520. if (durChange > 0)
  521. {
  522. pexpinfo->rgdurPrior[0] += durChange;
  523. pexpinfo->rgcExpPrior[0]++;
  524. rgtxtinf[iwch].prior = 1;
  525. pilsobj->pduAdjust[iwch] = durChange;
  526. }
  527. }
  528. }
  529. if (!rgtxtinf[iwch].fExpand && iwch == ptxtobj->iwchLim - 1 && plschp->fExpandOnRun &&
  530. fNextAdjacentFound)
  531. {
  532. plsrunNext = plsgrchnk->plschnk[itxtobjNext].plsrun;
  533. iwchNext = ((PTXTOBJ)plsgrchnk->plschnk[itxtobjNext].pdobj)->iwchFirst;
  534. lserr = CheckExpandOnRun(pilsobj, &lsems, iwch, iwchNext, ptxtobj, plsrunCur, plsrunNext,
  535. &fExpandOpp, &durChange);
  536. if (lserr != lserrNone) return lserr;
  537. if (fExpandOpp)
  538. {
  539. pexpinfo->cExpOppr++;
  540. rgtxtinf[iwch].fExpand = fTrue;
  541. if (durChange > 0)
  542. {
  543. pexpinfo->rgdurPrior[1] += durChange;
  544. pexpinfo->rgcExpPrior[1]++;
  545. rgtxtinf[iwch].prior = 2;
  546. pilsobj->pduAdjust[iwch] = durChange;
  547. }
  548. }
  549. }
  550. else if (!rgtxtinf[iwch].fExpand && iwch == ptxtobj->iwchLim - 1 && !fNextAdjacentFound &&
  551. (plsgrchnk->pcont[itxtobj] & fcontExpandAfter))
  552. {
  553. /* Character before foreign object */
  554. pexpinfo->cExpOppr++;
  555. rgtxtinf[iwch].fExpand = fTrue;
  556. }
  557. if (!rgtxtinf[iwch].fExpand && plschp->fExpandTable)
  558. {
  559. Assert(!fGlyphBased);
  560. if (iwch < ptxtobj->iwchLim - 1)
  561. {
  562. lsexpan = pilsobj->plsexpan[pilsobj->pilsexpan[
  563. pilsobj->cModWidthClasses * rgtxtinf[iwch].mwcls + rgtxtinf[iwch+1].mwcls
  564. ]
  565. ];
  566. if (fScaled && lsexpan.fFullScaled || !fScaled && lsexpan.fFullInterletter)
  567. {
  568. pexpinfo->cExpOppr++;
  569. rgtxtinf[iwch].fExpand = fTrue;
  570. }
  571. }
  572. else if (fNextAdjacentFound && plsgrchnk->plschnk[itxtobjNext].plschp->fExpandTable)
  573. {
  574. Assert(!(((PTXTOBJ)plsgrchnk->plschnk[itxtobjNext].pdobj)->txtf & txtfGlyphBased));
  575. iwchNext = ((PTXTOBJ)plsgrchnk->plschnk[itxtobjNext].pdobj)->iwchFirst;
  576. lsexpan = pilsobj->plsexpan[pilsobj->pilsexpan[
  577. pilsobj->cModWidthClasses * rgtxtinf[iwch].mwcls + rgtxtinf[iwchNext].mwcls
  578. ]
  579. ];
  580. if (fScaled && lsexpan.fFullScaled || !fScaled && lsexpan.fFullInterletter)
  581. {
  582. pexpinfo->cExpOppr++;
  583. rgtxtinf[iwch].fExpand = fTrue;
  584. }
  585. }
  586. }
  587. }
  588. itxtobj = itxtobjNext;
  589. }
  590. return lserrNone;
  591. }
  592. /* C H E C K E X P A N D S P A C E */
  593. /*----------------------------------------------------------------------------
  594. %%Function: CheckExpandSpace
  595. %%Contact: sergeyge
  596. Reports if there is expansion opportunity on space and amount of expansion
  597. ---------------------------------------------------------------------------*/
  598. static LSERR CheckExpandSpace(PILSOBJ pilsobj, LSEMS* plsems, long iwchPrev, long iwch, long iwchNext,
  599. PTXTOBJ ptxtobjCur, PLSRUN plsrunPrev, PLSRUN plsrunCur, PLSRUN plsrunNext,
  600. BOOL* pfExpandOpp, long* pdurChange)
  601. {
  602. LSERR lserr;
  603. BYTE side;
  604. LSACT lsact;
  605. long igind;
  606. *pfExpandOpp = fFalse;
  607. *pdurChange = 0;
  608. lserr = (*pilsobj->plscbk->pfnExpWidthSpace)(pilsobj->pols, plsrunCur,
  609. plsrunPrev, pilsobj->pwchOrig[iwchPrev], plsrunNext, pilsobj->pwchOrig[iwchNext], &lsact);
  610. if (lserr != lserrNone) return lserr;
  611. if (lsact.side != sideNone)
  612. {
  613. *pfExpandOpp = fTrue;
  614. if (ptxtobjCur->txtf & txtfGlyphBased)
  615. {
  616. igind = IgindLastFromIwch(ptxtobjCur, iwch);
  617. GetChanges(lsact, plsems, pilsobj->pdurGind[igind], fTrue, &side, pdurChange);
  618. }
  619. else
  620. {
  621. GetChanges(lsact, plsems, pilsobj->pdur[iwch], fTrue, &side, pdurChange);
  622. }
  623. Assert(side == sideRight);
  624. if (*pdurChange < 0)
  625. *pdurChange = 0;
  626. }
  627. return lserrNone;
  628. }
  629. /* C H E C K E X P A N D O N R U N */
  630. /*----------------------------------------------------------------------------
  631. %%Function: CheckExpandOnRun
  632. %%Contact: sergeyge
  633. Reports if there is expansion opportunity between runs and amount of expansion
  634. ---------------------------------------------------------------------------*/
  635. static LSERR CheckExpandOnRun(PILSOBJ pilsobj, LSEMS* plsems, long iwch, long iwchNext, PTXTOBJ ptxtobjCur,
  636. PLSRUN plsrunCur, PLSRUN plsrunNext, BOOL* pfExpandOpp, long* pdurChange)
  637. {
  638. LSERR lserr;
  639. BYTE side;
  640. LSACT lsact;
  641. long igind;
  642. *pfExpandOpp = fFalse;
  643. *pdurChange = 0;
  644. lserr = (*pilsobj->plscbk->pfnExpOnRun)(pilsobj->pols, plsrunCur, pilsobj->pwchOrig[iwch],
  645. plsrunNext, pilsobj->pwchOrig[iwchNext], &lsact);
  646. if (lserr != lserrNone) return lserr;
  647. if (lsact.side != sideNone)
  648. {
  649. *pfExpandOpp = fTrue;
  650. if (ptxtobjCur->txtf & txtfGlyphBased)
  651. {
  652. igind = IgindLastFromIwch(ptxtobjCur, iwch);
  653. igind = IgindBaseFromIgind(pilsobj, igind);
  654. GetChanges(lsact, plsems, pilsobj->pdurGind[igind], fTrue, &side, pdurChange);
  655. }
  656. else
  657. {
  658. GetChanges(lsact, plsems, pilsobj->pdur[iwch], fTrue, &side, pdurChange);
  659. }
  660. Assert(side == sideRight);
  661. if (*pdurChange < 0)
  662. *pdurChange = 0;
  663. }
  664. return lserrNone;
  665. }
  666. /* C H E C K C O M P S P A C E */
  667. /*----------------------------------------------------------------------------
  668. %%Function: CheckCompSpace
  669. %%Contact: sergeyge
  670. Reports if there is compression opportunity on space and amount of compression
  671. ---------------------------------------------------------------------------*/
  672. static LSERR CheckCompSpace(PILSOBJ pilsobj, LSEMS* plsems, long iwchPrev, long iwch, long iwchNext,
  673. PTXTOBJ ptxtobjCur, PLSRUN plsrunPrev, PLSRUN plsrunCur, PLSRUN plsrunNext, long* pdurChange)
  674. {
  675. LSERR lserr;
  676. BYTE side;
  677. LSPRACT lspract;
  678. long igind;
  679. *pdurChange = 0;
  680. lserr = (*pilsobj->plscbk->pfnCompWidthSpace)(pilsobj->pols, plsrunCur,
  681. plsrunPrev, pilsobj->pwchOrig[iwchPrev], plsrunNext, pilsobj->pwchOrig[iwchNext], &lspract);
  682. if (lserr != lserrNone) return lserr;
  683. if (lspract.prior != prior0)
  684. {
  685. if (ptxtobjCur->txtf & txtfGlyphBased)
  686. {
  687. igind = IgindLastFromIwch(ptxtobjCur, iwch);
  688. GetChanges(lspract.lsact, plsems, pilsobj->pdurGind[igind], fFalse, &side, pdurChange);
  689. }
  690. else
  691. {
  692. GetChanges(lspract.lsact, plsems, pilsobj->pdur[iwch], fFalse, &side, pdurChange);
  693. }
  694. Assert(side == sideRight);
  695. if (*pdurChange < 0)
  696. SetComp(pilsobj, iwch, lspract.prior, side, *pdurChange);
  697. else
  698. *pdurChange = 0;
  699. }
  700. return lserrNone;
  701. }
  702. /* C H E C K C O M P O N R U N */
  703. /*----------------------------------------------------------------------------
  704. %%Function: CheckCompOnRun
  705. %%Contact: sergeyge
  706. Reports if there is compression opportunity between runs and amount of compression
  707. ---------------------------------------------------------------------------*/
  708. static LSERR CheckCompOnRun(PILSOBJ pilsobj, LSEMS* plsems, long iwch, long iwchNext,
  709. PTXTOBJ ptxtobjCur, PLSRUN plsrunCur, PLSRUN plsrunNext, long* pdurChange)
  710. {
  711. LSERR lserr;
  712. BYTE side;
  713. LSPRACT lspract;
  714. long igind;
  715. *pdurChange = 0;
  716. lserr = (*pilsobj->plscbk->pfnCompOnRun)(pilsobj->pols, plsrunCur, pilsobj->pwchOrig[iwch],
  717. plsrunNext, pilsobj->pwchOrig[iwchNext], &lspract);
  718. if (lserr != lserrNone) return lserr;
  719. if (lspract.prior != prior0)
  720. {
  721. if (ptxtobjCur->txtf & txtfGlyphBased)
  722. {
  723. igind = IgindLastFromIwch(ptxtobjCur, iwch);
  724. igind = IgindBaseFromIgind(pilsobj, igind);
  725. GetChanges(lspract.lsact, plsems, pilsobj->pdurGind[igind], fFalse, &side, pdurChange);
  726. }
  727. else
  728. {
  729. GetChanges(lspract.lsact, plsems, pilsobj->pdur[iwch], fFalse, &side, pdurChange);
  730. }
  731. Assert(side == sideRight);
  732. if (*pdurChange < 0)
  733. SetComp(pilsobj, iwch, lspract.prior, side, *pdurChange);
  734. else
  735. *pdurChange = 0;
  736. }
  737. return lserrNone;
  738. }
  739. /* S E T C O M P */
  740. /*----------------------------------------------------------------------------
  741. %%Function: SetComp
  742. %%Contact: sergeyge
  743. ---------------------------------------------------------------------------*/
  744. static void SetComp(PILSOBJ pilsobj, long iwch, BYTE prior, BYTE side, long durChange)
  745. {
  746. pilsobj->ptxtinf[iwch].prior = prior;
  747. pilsobj->ptxtinf[iwch].side = side;
  748. pilsobj->pduAdjust[iwch] = durChange;
  749. }
  750. /* G E T N E X T R U N */
  751. /*----------------------------------------------------------------------------
  752. %%Function: GetNextRun
  753. %%Contact: sergeyge
  754. ---------------------------------------------------------------------------*/
  755. static BOOL GetNextRun(const LSGRCHNK* plsgrchnk, long itxtobj, long* pitxtobjNext)
  756. {
  757. long clschnk;
  758. PTXTOBJ ptxtobj;
  759. BOOL fFound;
  760. BOOL fContiguous;
  761. clschnk = (long)plsgrchnk->clsgrchnk;
  762. *pitxtobjNext = clschnk;
  763. fFound = fFalse;
  764. fContiguous = fTrue;
  765. while (!fFound && itxtobj < clschnk)
  766. {
  767. ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
  768. fFound = !(ptxtobj->txtf & txtfSkipAtNti);
  769. fContiguous = fContiguous && !(plsgrchnk->pcont[itxtobj] & fcontNonTextBefore);
  770. itxtobj++;
  771. }
  772. if (fFound)
  773. *pitxtobjNext = itxtobj - 1;
  774. return fFound && fContiguous;
  775. }
  776. /* G E T P R E V C H A R R U N */
  777. /*----------------------------------------------------------------------------
  778. %%Function: GetPrevCharRun
  779. %%Contact: sergeyge
  780. ---------------------------------------------------------------------------*/
  781. static void GetPrevCharRun(const LSGRCHNK* plsgrchnk, long itxtobj, long iwch, long* piwchPrev,
  782. PLSRUN* pplsrunPrev)
  783. {
  784. BOOL fFound;
  785. PTXTOBJ ptxtobj;
  786. fFound = fFalse;
  787. Assert(itxtobj < (long)plsgrchnk->clsgrchnk);
  788. ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
  789. Assert(iwch >= ptxtobj->iwchFirst && iwch < ptxtobj->iwchLim);
  790. *piwchPrev = 0;
  791. *pplsrunPrev = NULL;
  792. if (iwch > ptxtobj->iwchFirst)
  793. {
  794. fFound = fTrue;
  795. *piwchPrev = iwch - 1;
  796. *pplsrunPrev = plsgrchnk->plschnk[itxtobj].plsrun;
  797. }
  798. else
  799. {
  800. while (!fFound && itxtobj > 0 && !(plsgrchnk->pcont[itxtobj] & fcontNonTextBefore))
  801. {
  802. itxtobj--;
  803. Assert(itxtobj >= 0);
  804. ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
  805. fFound = !(ptxtobj->txtf & txtfSkipAtNti);
  806. if (fFound)
  807. {
  808. *piwchPrev = ((PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj)->iwchLim - 1;
  809. *pplsrunPrev = plsgrchnk->plschnk[itxtobj].plsrun;
  810. }
  811. }
  812. }
  813. }
  814. /* A P P L Y P R I O R E X P A N S I O N */
  815. /*----------------------------------------------------------------------------
  816. %%Function: ApplyPriorExpansion
  817. %%Contact: sergeyge
  818. Applies expansion on one priority level
  819. ---------------------------------------------------------------------------*/
  820. static void ApplyPriorExpansion(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
  821. long itxtobjLast, long iwchLim, BYTE prior, long durToExpand, long durAvailable, long cExpOppr)
  822. {
  823. PILSOBJ pilsobj;
  824. PTXTOBJ ptxtobj;
  825. TXTINF* rgtxtinf;
  826. long* rgdurAdjust;
  827. long durSubstr;
  828. long durChange;
  829. long cBound;
  830. long cOpprCur;
  831. long itxtobj;
  832. long iwch;
  833. long iwchFirstInDobj;
  834. long iwchLimInDobj;
  835. long igind;
  836. BOOL fGlyphBased;
  837. pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  838. rgtxtinf = pilsobj->ptxtinf;
  839. rgdurAdjust = pilsobj->pduAdjust;
  840. Assert(durToExpand > 0);
  841. if (durAvailable == 0)
  842. return;
  843. if (durAvailable < durToExpand)
  844. durToExpand = durAvailable;
  845. Assert(cExpOppr > 0);
  846. durSubstr = (durAvailable - durToExpand) / cExpOppr;
  847. cBound = (durAvailable - durToExpand) - durSubstr * cExpOppr;
  848. cOpprCur = 0;
  849. for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
  850. {
  851. ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
  852. fGlyphBased = (ptxtobj->txtf & txtfGlyphBased);
  853. iwchFirstInDobj = iwchFirst;
  854. if (itxtobj > itxtobjFirst)
  855. iwchFirstInDobj = ptxtobj->iwchFirst;
  856. iwchLimInDobj = iwchLim;
  857. if (itxtobj < itxtobjLast)
  858. iwchLimInDobj = ptxtobj->iwchLim;
  859. for (iwch = iwchFirstInDobj; iwch < iwchLimInDobj; iwch++)
  860. {
  861. if (rgtxtinf[iwch].prior == prior)
  862. {
  863. cOpprCur++;
  864. durChange = rgdurAdjust[iwch] - durSubstr;
  865. if (cOpprCur <= cBound)
  866. durChange--;
  867. if (durChange >= 0)
  868. {
  869. if (fGlyphBased)
  870. {
  871. igind = IgindLastFromIwch(ptxtobj, iwch);
  872. igind = IgindBaseFromIgind(pilsobj, igind);
  873. ApplyGlyphChanges(pilsobj, igind, durChange);
  874. }
  875. else
  876. ApplyChanges(pilsobj, iwch, sideRight, durChange);
  877. }
  878. }
  879. }
  880. }
  881. }
  882. /* A P P L Y F U L L E X P A N S I O N */
  883. /*----------------------------------------------------------------------------
  884. %%Function: ApplyFullExpansion
  885. %%Contact: sergeyge
  886. Applies risidual unlimited expansion
  887. ---------------------------------------------------------------------------*/
  888. static void ApplyFullExpansion(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
  889. long itxtobjLast, long iwchLim, long durToExpand, long cExpOppr, long cNonText, long* pdurNonText)
  890. {
  891. PILSOBJ pilsobj;
  892. PTXTOBJ ptxtobj;
  893. TXTINF* rgtxtinf;
  894. long* rgdurAdjust;
  895. long cBound;
  896. long cOpprCur;
  897. long cExpOpprTotal;
  898. long durChange;
  899. long durAdd;
  900. long itxtobj;
  901. long iwch;
  902. long iwchFirstInDobj;
  903. long iwchLimInDobj;
  904. long igind;
  905. BOOL fGlyphBased;
  906. pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  907. rgtxtinf = pilsobj->ptxtinf;
  908. rgdurAdjust = pilsobj->pduAdjust;
  909. *pdurNonText = 0;
  910. cExpOpprTotal = cExpOppr + cNonText;
  911. if (cExpOpprTotal > 0)
  912. {
  913. *pdurNonText = durToExpand * cNonText / cExpOpprTotal;
  914. durToExpand -= *pdurNonText;
  915. if (cExpOppr > 0)
  916. {
  917. durAdd = durToExpand / cExpOppr;
  918. cBound = durToExpand - durAdd * cExpOppr;
  919. cOpprCur = 0;
  920. for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
  921. {
  922. ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
  923. fGlyphBased = (ptxtobj->txtf & txtfGlyphBased);
  924. iwchFirstInDobj = iwchFirst;
  925. if (itxtobj > itxtobjFirst)
  926. iwchFirstInDobj = ptxtobj->iwchFirst;
  927. iwchLimInDobj = iwchLim;
  928. if (itxtobj < itxtobjLast)
  929. iwchLimInDobj = ptxtobj->iwchLim;
  930. for (iwch = iwchFirstInDobj; iwch < iwchLimInDobj; iwch++)
  931. {
  932. if (rgtxtinf[iwch].fExpand)
  933. {
  934. cOpprCur++;
  935. durChange = durAdd;
  936. if (cOpprCur <= cBound)
  937. durChange++;
  938. if (fGlyphBased)
  939. {
  940. igind = IgindLastFromIwch(ptxtobj, iwch);
  941. igind = IgindBaseFromIgind(pilsobj, igind);
  942. ApplyGlyphChanges(pilsobj, igind, durChange);
  943. }
  944. else
  945. ApplyChanges(pilsobj, iwch, sideRight, durChange);
  946. }
  947. }
  948. }
  949. }
  950. }
  951. }
  952. /* G E T C O M P R E S S I N F O */
  953. /*----------------------------------------------------------------------------
  954. %%Function: GetCompressInfo
  955. %%Contact: sergeyge
  956. Agregates compression information accross for priorities
  957. ---------------------------------------------------------------------------*/
  958. static void GetCompressInfo(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
  959. long itxtobjLast, long iwchLim, COMPINFO* pcompinfo)
  960. {
  961. PILSOBJ pilsobj;
  962. PTXTOBJ ptxtobj;
  963. TXTINF* rgtxtinf;
  964. long* rgdurAdjust;
  965. UINT prior;
  966. long cCompPrior;
  967. long itxtobj;
  968. long iwch;
  969. long iwchFirstInDobj;
  970. long iwchLimInDobj;
  971. pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  972. cCompPrior = pilsobj->cCompPrior;
  973. memset(pcompinfo, 0, sizeof(COMPINFO) * cCompPrior);
  974. rgtxtinf = pilsobj->ptxtinf;
  975. rgdurAdjust = pilsobj->pduAdjust;
  976. /* rgtxtinf == NULL means that there were no runs which possibly can introduce compress opportunity */
  977. if (rgtxtinf == NULL)
  978. return;
  979. for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast ; itxtobj++)
  980. {
  981. ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
  982. iwchFirstInDobj = iwchFirst;
  983. if (itxtobj > itxtobjFirst)
  984. iwchFirstInDobj = ptxtobj->iwchFirst;
  985. iwchLimInDobj = iwchLim;
  986. if (itxtobj < itxtobjLast)
  987. iwchLimInDobj = ptxtobj->iwchLim;
  988. for (iwch = iwchFirstInDobj; iwch < iwchLimInDobj; iwch++)
  989. {
  990. prior = rgtxtinf[iwch].prior;
  991. Assert(prior <= (BYTE)cCompPrior);
  992. if (prior > 0)
  993. {
  994. pcompinfo[prior - 1].cCompOppr++;
  995. pcompinfo[prior - 1].durComp -= rgdurAdjust[iwch];
  996. }
  997. }
  998. }
  999. }
  1000. /* A P P L Y P R I O R C O M P R E S S I O N */
  1001. /*----------------------------------------------------------------------------
  1002. %%Function: ApplyPriorCompression
  1003. %%Contact: sergeyge
  1004. Applies compression for one priority level
  1005. ---------------------------------------------------------------------------*/
  1006. static void ApplyPriorCompression(const LSGRCHNK* plsgrchnk, long itxtobjFirst, long iwchFirst,
  1007. long itxtobjLast, long iwchLim, BYTE prior,
  1008. long durToCompress, long durAvailable, long cExpOppr)
  1009. {
  1010. PILSOBJ pilsobj;
  1011. PTXTOBJ ptxtobj;
  1012. TXTINF* rgtxtinf;
  1013. long* rgdurAdjust;
  1014. long durSubstr;
  1015. long cBound;
  1016. long cOpprCur;
  1017. long durChange;
  1018. long iwch;
  1019. long itxtobj;
  1020. long igind;
  1021. BOOL fGlyphBased;
  1022. long iwchFirstInDobj;
  1023. long iwchLimInDobj;
  1024. pilsobj = ((PTXTOBJ)plsgrchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  1025. rgtxtinf = pilsobj->ptxtinf;
  1026. rgdurAdjust = pilsobj->pduAdjust;
  1027. Assert(durToCompress > 0);
  1028. if (durAvailable == 0)
  1029. return;
  1030. if (durAvailable < durToCompress)
  1031. durToCompress = durAvailable;
  1032. Assert(cExpOppr > 0);
  1033. durSubstr = (durAvailable - durToCompress) / cExpOppr;
  1034. cBound = (durAvailable - durToCompress) - durSubstr * cExpOppr;
  1035. cOpprCur = 0;
  1036. for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
  1037. {
  1038. ptxtobj = (PTXTOBJ)plsgrchnk->plschnk[itxtobj].pdobj;
  1039. fGlyphBased = (ptxtobj->txtf & txtfGlyphBased);
  1040. iwchFirstInDobj = iwchFirst;
  1041. if (itxtobj > itxtobjFirst)
  1042. iwchFirstInDobj = ptxtobj->iwchFirst;
  1043. iwchLimInDobj = iwchLim;
  1044. if (itxtobj < itxtobjLast)
  1045. iwchLimInDobj = ptxtobj->iwchLim;
  1046. for (iwch = iwchFirstInDobj; iwch < iwchLimInDobj; iwch++)
  1047. {
  1048. if (rgtxtinf[iwch].prior == prior)
  1049. {
  1050. cOpprCur++;
  1051. durChange = rgdurAdjust[iwch] + durSubstr;
  1052. if (cExpOppr - cBound < cOpprCur)
  1053. durChange++;
  1054. if (durChange < 0)
  1055. {
  1056. if (fGlyphBased)
  1057. {
  1058. igind = IgindLastFromIwch(ptxtobj, iwch);
  1059. igind = IgindBaseFromIgind(pilsobj, igind);
  1060. ApplyGlyphChanges(pilsobj, igind, durChange);
  1061. }
  1062. else
  1063. ApplyChanges(pilsobj, iwch, (BYTE)rgtxtinf[iwch].side, durChange);
  1064. }
  1065. }
  1066. }
  1067. }
  1068. }