Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

527 lines
14 KiB

  1. #include "lstxtwrd.h"
  2. #include "lstxtmap.h"
  3. #include "txtils.h"
  4. #include "txtln.h"
  5. #include "txtobj.h"
  6. #define min(a,b) ((a) > (b) ? (b) : (a))
  7. #define max(a,b) ((a) < (b) ? (b) : (a))
  8. #define SqueezingFactorShift 2
  9. static long GetNumberOfSpaces(const LSGRCHNK* plsgrchnk,
  10. long itxtobjAfterStartSpaces, long iwchAfterStartSpaces,
  11. long itxtobjLast, long iwchLast);
  12. static void DistributeInDobjsSpaces(const LSGRCHNK* plsgrchnk,
  13. long itxtobjAfterStartSpaces, long iwchAfterStartSpaces,
  14. long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind, long duAdd, long wDuBound);
  15. static void GetSqueezingInfo(const LSGRCHNK* plsgrchnk,
  16. long itxtobjAfterStartSpaces, long iwchAfterStartSpaces,
  17. long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind,
  18. long* pNumOfSpaces, long* pduForSqueezing);
  19. static void SqueezeInDobjs(const LSGRCHNK* plsgrchnk,
  20. long itxtobjAfterStartSpaces, long iwchAfterStartSpaces,
  21. long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind,
  22. long duSubstr, long wDuBound);
  23. /* F U L L P O S I T I V E J U S T I F I C A T I O N */
  24. /*----------------------------------------------------------------------------
  25. %%Function: FullPositiveJustification
  26. %%Contact: sergeyge
  27. Performs positive distribution in spaces.
  28. Since amount to distribute is not nesessary divisible by number of spaces,
  29. additional pixels (wDupBound, wDurBound) are distributed among first
  30. wDupBound/wDurBound spaces.
  31. Leading spaces do not participate.
  32. ----------------------------------------------------------------------------*/
  33. void FullPositiveSpaceJustification(const LSGRCHNK* plsgrchnk,
  34. long itxtobjAfterStartSpaces, long iwchAfterStartSpaces,
  35. long itxtobjLast, long iwchLast,
  36. long* rgdu, long* rgduGind, long duToDistribute, BOOL* pfSpacesFound)
  37. {
  38. long NumOfSpaces;
  39. long duAdd;
  40. long wDuBound;
  41. Assert(duToDistribute > 0);
  42. NumOfSpaces = GetNumberOfSpaces(plsgrchnk, itxtobjAfterStartSpaces, iwchAfterStartSpaces,
  43. itxtobjLast, iwchLast);
  44. if (NumOfSpaces > 0)
  45. {
  46. duAdd = duToDistribute / NumOfSpaces;
  47. wDuBound = duToDistribute - (duAdd * NumOfSpaces);
  48. DistributeInDobjsSpaces(plsgrchnk, itxtobjAfterStartSpaces, iwchAfterStartSpaces,
  49. itxtobjLast, iwchLast, rgdu, rgduGind, duAdd, wDuBound);
  50. }
  51. *pfSpacesFound = (NumOfSpaces > 0);
  52. }
  53. /* N E G A T I V E S P A C E J U S T I F I C A T I O N */
  54. /*----------------------------------------------------------------------------
  55. %%Function: NegativeSpaceJustification
  56. %%Contact: sergeyge
  57. Performs squeezing into spaces if it is possible.
  58. If it is impossible squeezes in as much as it can
  59. ----------------------------------------------------------------------------*/
  60. void NegativeSpaceJustification(const LSGRCHNK* plsgrchnk,
  61. long itxtobjAfterStartSpaces, long iwchAfterStartSpaces,
  62. long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind, long duToSqueeze)
  63. {
  64. long NumOfSpaces;
  65. long duForSqueezing;
  66. long duSubstr;
  67. long wDuBound;
  68. Assert(duToSqueeze > 0);
  69. GetSqueezingInfo(plsgrchnk, itxtobjAfterStartSpaces, iwchAfterStartSpaces,
  70. itxtobjLast, iwchLast, rgdu, rgduGind, &NumOfSpaces, &duForSqueezing);
  71. /* We cannot squeeze more tha we can */
  72. if (duForSqueezing < duToSqueeze)
  73. duToSqueeze = duForSqueezing;
  74. /* dupSubstr shows how much should be subtracted from maximum squeezing
  75. each space provides.
  76. wDupBound--from how many spaces additional pixel should be subtracted */
  77. if (NumOfSpaces > 0)
  78. {
  79. duSubstr = (duForSqueezing - duToSqueeze) / NumOfSpaces;
  80. wDuBound = (duForSqueezing - duToSqueeze) - duSubstr * NumOfSpaces;
  81. Assert(duSubstr >= 0);
  82. Assert(wDuBound >= 0);
  83. SqueezeInDobjs(plsgrchnk, itxtobjAfterStartSpaces, iwchAfterStartSpaces,
  84. itxtobjLast, iwchLast, rgdu, rgduGind, duSubstr, wDuBound);
  85. }
  86. return;
  87. }
  88. /* Internal Functions Implementation */
  89. /* G E T N U M B E R O F S P A C E S */
  90. /*----------------------------------------------------------------------------
  91. %%Function: GetNumberOfSpaces
  92. %%Contact: sergeyge
  93. Reports amount of spaces for distribution.
  94. ----------------------------------------------------------------------------*/
  95. static long GetNumberOfSpaces(const LSGRCHNK* plsgrchnk,
  96. long itxtobjAfterStartSpaces, long iwchAfterStartSpaces,
  97. long itxtobjLast, long iwchLast)
  98. {
  99. long NumOfSpaces;
  100. PTXTOBJ ptxtobj;
  101. PILSOBJ pilsobj;
  102. long* rgwSpaces;
  103. long iwSpacesFirst;
  104. long iwSpacesLim;
  105. long iwSpaces;
  106. long iwchFirst;
  107. long iwchLim;
  108. long itxtobj;
  109. ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[0].pdobj;
  110. pilsobj = ptxtobj->plnobj->pilsobj;
  111. rgwSpaces = pilsobj->pwSpaces;
  112. NumOfSpaces = 0;
  113. for (itxtobj = itxtobjAfterStartSpaces; itxtobj <= itxtobjLast; itxtobj++)
  114. {
  115. ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[itxtobj].pdobj;
  116. if (ptxtobj->txtkind == txtkindRegular)
  117. {
  118. iwSpacesFirst = ptxtobj->u.reg.iwSpacesFirst;
  119. iwSpacesLim = ptxtobj->u.reg.iwSpacesLim;
  120. iwchFirst = iwchAfterStartSpaces;
  121. if (itxtobj > itxtobjAfterStartSpaces)
  122. iwchFirst = ptxtobj->iwchFirst;
  123. iwchLim = iwchLast + 1;
  124. if (itxtobj < itxtobjLast)
  125. iwchLim = ptxtobj->iwchLim;
  126. while (iwSpacesFirst < iwSpacesLim && rgwSpaces[iwSpacesFirst] < iwchFirst)
  127. {
  128. iwSpacesFirst++;
  129. }
  130. while (iwSpacesLim > iwSpacesFirst && rgwSpaces[iwSpacesLim-1] >= iwchLim)
  131. {
  132. iwSpacesLim--;
  133. }
  134. if (ptxtobj->txtf & txtfGlyphBased)
  135. {
  136. for (iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++)
  137. if (FIwchOneToOne(pilsobj, rgwSpaces[iwSpaces]))
  138. NumOfSpaces++;
  139. }
  140. else
  141. NumOfSpaces += (iwSpacesLim - iwSpacesFirst);
  142. }
  143. }
  144. return NumOfSpaces;
  145. }
  146. /* D I S T R I B U T E I N D O B J S */
  147. /*----------------------------------------------------------------------------
  148. %%Function: DistributeInDobjs
  149. %%Contact: sergeyge
  150. Performs distribution in dobjs, based on precalculated information.
  151. ----------------------------------------------------------------------------*/
  152. static void DistributeInDobjsSpaces(const LSGRCHNK* plsgrchnk,
  153. long itxtobjAfterStartSpaces, long iwchAfterStartSpaces,
  154. long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind, long duAdd, long wDuBound)
  155. {
  156. PTXTOBJ ptxtobj;
  157. PILSOBJ pilsobj;
  158. PLNOBJ plnobj;
  159. long* rgwSpaces;
  160. long iwSpacesFirst;
  161. long iwSpacesLim;
  162. long iwchFirst;
  163. long iwchLim;
  164. long CurSpace;
  165. long itxtobj;
  166. long iwSpaces;
  167. long igind;
  168. long CurSpaceForSecondLoop;
  169. plnobj = ((PTXTOBJ)(plsgrchnk->plschnk[0].pdobj))->plnobj;
  170. pilsobj = plnobj->pilsobj;
  171. rgwSpaces = pilsobj->pwSpaces;
  172. CurSpace = 0;
  173. for (itxtobj = itxtobjAfterStartSpaces; itxtobj <= itxtobjLast ; itxtobj++)
  174. {
  175. ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[itxtobj].pdobj;
  176. if (ptxtobj->txtkind == txtkindRegular)
  177. {
  178. iwSpacesFirst = ptxtobj->u.reg.iwSpacesFirst;
  179. iwSpacesLim = ptxtobj->u.reg.iwSpacesLim;
  180. iwchFirst = iwchAfterStartSpaces;
  181. if (itxtobj > itxtobjAfterStartSpaces)
  182. iwchFirst = ptxtobj->iwchFirst;
  183. iwchLim = iwchLast + 1;
  184. if (itxtobj < itxtobjLast)
  185. iwchLim = ptxtobj->iwchLim;
  186. while (iwSpacesFirst < iwSpacesLim && rgwSpaces[iwSpacesFirst] < iwchFirst)
  187. {
  188. iwSpacesFirst++;
  189. }
  190. while (iwSpacesLim > iwSpacesFirst && rgwSpaces[iwSpacesLim-1] >= iwchLim)
  191. {
  192. iwSpacesLim--;
  193. }
  194. if (ptxtobj->txtf & txtfGlyphBased)
  195. {
  196. Assert(rgduGind != NULL);
  197. for(iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++)
  198. {
  199. if (FIwchOneToOne(pilsobj, rgwSpaces[iwSpaces]))
  200. {
  201. igind = IgindFirstFromIwch(ptxtobj, rgwSpaces[iwSpaces]);
  202. if (CurSpace < wDuBound)
  203. {
  204. rgduGind[igind] += (duAdd + 1);
  205. pilsobj->pduGright[igind] += (duAdd + 1);
  206. }
  207. else
  208. {
  209. rgduGind[igind] += duAdd;
  210. pilsobj->pduGright[igind] += duAdd;
  211. }
  212. CurSpace++;
  213. }
  214. }
  215. }
  216. else
  217. {
  218. CurSpaceForSecondLoop = CurSpace;
  219. for(iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++)
  220. {
  221. if (CurSpace < wDuBound)
  222. {
  223. rgdu[rgwSpaces[iwSpaces]] += (duAdd + 1);
  224. }
  225. else
  226. {
  227. rgdu[rgwSpaces[iwSpaces]] += duAdd;
  228. }
  229. CurSpace++;
  230. }
  231. if (pilsobj->fNotSimpleText)
  232. {
  233. for(iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++)
  234. {
  235. if (CurSpaceForSecondLoop < wDuBound)
  236. {
  237. pilsobj->pdurRight[rgwSpaces[iwSpaces]] += (duAdd + 1);
  238. }
  239. else
  240. {
  241. pilsobj->pdurRight[rgwSpaces[iwSpaces]] += duAdd;
  242. }
  243. CurSpaceForSecondLoop++;
  244. }
  245. }
  246. }
  247. }
  248. }
  249. }
  250. /* G E T S Q U E E Z I N G I N F O */
  251. /*----------------------------------------------------------------------------
  252. %%Function: GetSqueezingInfo
  253. %%Contact: sergeyge
  254. Calculates maximum amount of pixels to squeeze into spaces.
  255. Leading spaces are used for squeezing.
  256. ----------------------------------------------------------------------------*/
  257. static void GetSqueezingInfo(const LSGRCHNK* plsgrchnk,
  258. long itxtobjAfterStartSpaces, long iwchAfterStartSpaces,
  259. long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind,
  260. long* pNumOfSpaces, long* pduForSqueezing)
  261. {
  262. PTXTOBJ ptxtobj;
  263. PLNOBJ plnobj;
  264. PILSOBJ pilsobj;
  265. long* rgwSpaces;
  266. long iwSpacesFirst;
  267. long iwSpacesLim;
  268. long iwchFirst;
  269. long iwchLim;
  270. long itxtobj;
  271. long iwSpaces;
  272. ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[0].pdobj;
  273. plnobj = ptxtobj->plnobj;
  274. pilsobj = plnobj->pilsobj;
  275. rgwSpaces = pilsobj->pwSpaces;
  276. *pNumOfSpaces = 0;
  277. *pduForSqueezing = 0;
  278. for (itxtobj = itxtobjAfterStartSpaces; itxtobj <= itxtobjLast ; itxtobj++)
  279. {
  280. ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[itxtobj].pdobj;
  281. if (! (ptxtobj->txtf & txtfMonospaced) )
  282. {
  283. if (ptxtobj->txtkind == txtkindRegular)
  284. {
  285. iwSpacesFirst = ptxtobj->u.reg.iwSpacesFirst;
  286. iwSpacesLim = ptxtobj->u.reg.iwSpacesLim;
  287. iwchFirst = iwchAfterStartSpaces;
  288. if (itxtobj > itxtobjAfterStartSpaces)
  289. iwchFirst = ptxtobj->iwchFirst;
  290. iwchLim = iwchLast + 1;
  291. if (itxtobj < itxtobjLast)
  292. iwchLim = ptxtobj->iwchLim;
  293. while (iwSpacesFirst < iwSpacesLim && rgwSpaces[iwSpacesFirst] < iwchFirst)
  294. {
  295. iwSpacesFirst++;
  296. }
  297. while (iwSpacesLim > iwSpacesFirst && rgwSpaces[iwSpacesLim-1] >= iwchLim)
  298. {
  299. iwSpacesLim--;
  300. }
  301. if (ptxtobj->txtf & txtfGlyphBased)
  302. {
  303. for (iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++)
  304. {
  305. if (FIwchOneToOne(pilsobj, rgwSpaces[iwSpaces]))
  306. {
  307. (*pduForSqueezing) += rgduGind[IgindFirstFromIwch(ptxtobj,rgwSpaces[iwSpaces])] >>
  308. SqueezingFactorShift;
  309. (*pNumOfSpaces)++;
  310. }
  311. }
  312. }
  313. else
  314. {
  315. for (iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++)
  316. {
  317. (*pduForSqueezing) += rgdu[rgwSpaces[iwSpaces]] >> SqueezingFactorShift;
  318. }
  319. (*pNumOfSpaces) += (iwSpacesLim - iwSpacesFirst);
  320. }
  321. }
  322. }
  323. }
  324. }
  325. /* S Q U E E Z E I N D O B J S */
  326. /*----------------------------------------------------------------------------
  327. %%Function: SqueezeInDobjs
  328. %%Contact: sergeyge
  329. Performs squeezing in dobjs, based on precalculated information
  330. ----------------------------------------------------------------------------*/
  331. static void SqueezeInDobjs(const LSGRCHNK* plsgrchnk,
  332. long itxtobjAfterStartSpaces, long iwchAfterStartSpaces,
  333. long itxtobjLast, long iwchLast, long* rgdu, long* rgduGind,
  334. long duSubstr, long wDuBound)
  335. {
  336. PTXTOBJ ptxtobj;
  337. PLNOBJ plnobj;
  338. PILSOBJ pilsobj;
  339. long* rgwSpaces;
  340. long iwSpacesFirst;
  341. long iwSpacesLim;
  342. long iwchFirst;
  343. long iwchLim;
  344. long duChange;
  345. long CurSpace;
  346. long itxtobj;
  347. long iwSpaces;
  348. long igind;
  349. long CurSpaceForSecondLoop;
  350. ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[0].pdobj;
  351. plnobj = ptxtobj->plnobj;
  352. pilsobj = plnobj->pilsobj;
  353. rgwSpaces = pilsobj->pwSpaces;
  354. CurSpace = 0;
  355. for (itxtobj = itxtobjAfterStartSpaces; itxtobj <= itxtobjLast; itxtobj++)
  356. {
  357. ptxtobj = (PTXTOBJ) plsgrchnk->plschnk[itxtobj].pdobj;
  358. if (! (ptxtobj->txtf & txtfMonospaced) )
  359. {
  360. if (ptxtobj->txtkind == txtkindRegular)
  361. {
  362. iwSpacesFirst = ptxtobj->u.reg.iwSpacesFirst;
  363. iwSpacesLim = ptxtobj->u.reg.iwSpacesLim;
  364. iwchFirst = iwchAfterStartSpaces;
  365. if (itxtobj > itxtobjAfterStartSpaces)
  366. iwchFirst = ptxtobj->iwchFirst;
  367. iwchLim = iwchLast + 1;
  368. if (itxtobj < itxtobjLast)
  369. iwchLim = ptxtobj->iwchLim;
  370. while (iwSpacesFirst < iwSpacesLim && rgwSpaces[iwSpacesFirst] < iwchFirst)
  371. {
  372. iwSpacesFirst++;
  373. }
  374. while (iwSpacesLim > iwSpacesFirst && rgwSpaces[iwSpacesLim-1] >= iwchLim)
  375. {
  376. iwSpacesLim--;
  377. }
  378. if (ptxtobj->txtf & txtfGlyphBased)
  379. {
  380. for(iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++)
  381. {
  382. if (FIwchOneToOne(pilsobj, rgwSpaces[iwSpaces]))
  383. {
  384. igind = IgindFirstFromIwch(ptxtobj, rgwSpaces[iwSpaces]);
  385. duChange = -(rgduGind[igind] >> SqueezingFactorShift) + duSubstr;
  386. if (CurSpace < wDuBound)
  387. {
  388. duChange += 1;
  389. }
  390. rgduGind[igind] += duChange;
  391. pilsobj->pduGright[igind] += duChange;
  392. CurSpace++;
  393. }
  394. }
  395. }
  396. else
  397. {
  398. CurSpaceForSecondLoop = CurSpace;
  399. for(iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++)
  400. {
  401. duChange = -(rgdu[rgwSpaces[iwSpaces]] >> SqueezingFactorShift) + duSubstr;
  402. if (CurSpace < wDuBound)
  403. {
  404. duChange += 1;
  405. }
  406. rgdu[rgwSpaces[iwSpaces]] += duChange;
  407. CurSpace++;
  408. }
  409. if (pilsobj->fNotSimpleText)
  410. {
  411. for(iwSpaces = iwSpacesFirst; iwSpaces < iwSpacesLim; iwSpaces++)
  412. {
  413. duChange = -(rgdu[rgwSpaces[iwSpaces]] >> SqueezingFactorShift) + duSubstr;
  414. if (CurSpaceForSecondLoop < wDuBound)
  415. {
  416. duChange += 1;
  417. }
  418. pilsobj->pdurRight[rgwSpaces[iwSpaces]] += duChange;
  419. CurSpaceForSecondLoop++;
  420. }
  421. }
  422. }
  423. }
  424. }
  425. }
  426. }