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.

586 lines
23 KiB

  1. #include "dispul.h"
  2. #include "lsc.h"
  3. #include "lsdnode.h"
  4. #include "lstfset.h"
  5. #include "lsulinfo.h"
  6. #include "lsstinfo.h"
  7. #include "dninfo.h"
  8. #include "dispmisc.h"
  9. #include "zqfromza.h"
  10. /* GetULMetric output */
  11. typedef struct {
  12. UINT kul;
  13. DWORD cNumberOfLines;
  14. __int64 dvpUnderlineOriginOffset;
  15. __int64 dvpFirstUnderlineOffset;
  16. __int64 dvpFirstUnderlineSize;
  17. __int64 dvpGapBetweenLines;
  18. __int64 dvpSecondUnderlineSize;
  19. } ULMETRIC;
  20. /* weighted sums for averaging */
  21. typedef struct {
  22. __int64 dupSum; // the sum of weights
  23. __int64 dvpFirstUnderlineOffset; // unnormalized values -
  24. __int64 dvpFirstUnderlineSize;
  25. __int64 dvpGapBetweenLines; // divide them by dupSum
  26. __int64 dvpSecondUnderlineSize; // to get weighted averages
  27. } ULMETRICSUM;
  28. // %%Function: InitULMetricSums
  29. // %%Contact: victork
  30. //
  31. // Neighbouring dnodes with good metrics and same baseline get averaged.
  32. // We use weighted average with dnode width for weights.
  33. // If the first dnode to participate in averaging happens to have zero width (almost never),
  34. // we arbitrarily change width to 1. This hack changes result very slightly and in a very rare case,
  35. // but simplify the logic considerably.
  36. static void InitULMetricSums(long dup, const ULMETRIC* pulm, ULMETRICSUM* pulmSum)
  37. {
  38. Assert(dup >= 0);
  39. if (dup == 0)
  40. {
  41. dup = 1;
  42. }
  43. pulmSum->dvpFirstUnderlineOffset = Mul64 (pulm->dvpFirstUnderlineOffset, dup);
  44. pulmSum->dvpFirstUnderlineSize = Mul64 (pulm->dvpFirstUnderlineSize, dup);
  45. pulmSum->dvpGapBetweenLines = Mul64 (pulm->dvpGapBetweenLines, dup);
  46. pulmSum->dvpSecondUnderlineSize = Mul64 (pulm->dvpSecondUnderlineSize, dup);
  47. pulmSum->dupSum = dup;
  48. }
  49. // %%Function: AddToULMetricSums
  50. // %%Contact: victork
  51. //
  52. static void AddToULMetricSums(long dup, const ULMETRIC* pulm, ULMETRICSUM* pulmSum)
  53. {
  54. Assert(dup >= 0);
  55. /* Add to running sums */
  56. pulmSum->dvpFirstUnderlineOffset += Mul64 (pulm->dvpFirstUnderlineOffset, dup);
  57. pulmSum->dvpFirstUnderlineSize += Mul64 (pulm->dvpFirstUnderlineSize, dup);
  58. pulmSum->dvpGapBetweenLines += Mul64 (pulm->dvpGapBetweenLines, dup);
  59. pulmSum->dvpSecondUnderlineSize += Mul64 (pulm->dvpSecondUnderlineSize, dup);
  60. pulmSum->dupSum += dup;
  61. }
  62. // %%Function: GetAveragedMetrics
  63. // %%Contact: victork
  64. //
  65. static void GetAveragedMetrics(const ULMETRICSUM* pulmSum, LSULMETRIC* pulm)
  66. {
  67. __int64 dupSum = pulmSum->dupSum;
  68. Assert(dupSum > 0);
  69. /* divide by sum of weights */
  70. pulm->dvpFirstUnderlineOffset = (long) Div64 (pulmSum->dvpFirstUnderlineOffset + Div64 (dupSum, 2), dupSum);
  71. pulm->dvpFirstUnderlineSize = (long) Div64 (pulmSum->dvpFirstUnderlineSize + Div64 (dupSum, 2), dupSum);
  72. pulm->dvpGapBetweenLines = (long) Div64 (pulmSum->dvpGapBetweenLines + Div64 (dupSum, 2), dupSum);
  73. pulm->dvpSecondUnderlineSize = (long) Div64 (pulmSum->dvpSecondUnderlineSize + Div64 (dupSum, 2), dupSum);
  74. Assert (pulm->dvpFirstUnderlineOffset == Div64 (pulmSum->dvpFirstUnderlineOffset + Div64 (dupSum, 2), dupSum));
  75. Assert (pulm->dvpFirstUnderlineSize == Div64 (pulmSum->dvpFirstUnderlineSize + Div64 (dupSum, 2), dupSum));
  76. Assert (pulm->dvpGapBetweenLines == Div64 (pulmSum->dvpGapBetweenLines + Div64 (dupSum, 2), dupSum));
  77. Assert (pulm->dvpSecondUnderlineSize == Div64 (pulmSum->dvpSecondUnderlineSize + Div64 (dupSum, 2), dupSum));
  78. }
  79. // %%Function: GetULMetric
  80. // %%Contact: victork
  81. //
  82. /*
  83. * Normally, when underlining goes on the under (negative, descent) side,
  84. * dvpFirstUnderlineOffset >= 0.
  85. * However, underlining on the other side is possible too, (vertical Japanese)
  86. *
  87. * Notice that offsets are from dnode baseline, not from the current baseline, so
  88. * underline can be both above current baseline and on the under side for raised dnodes.
  89. *
  90. * We have to be compatible with Word meaning what's good for him should be good for us (pity).
  91. * For example, Word sometimes allow the lower UL to be below descent.
  92. */
  93. static LSERR GetULMetric(PLSC plsc, PLSDNODE pdn, LSTFLOW lstflow,
  94. BOOL* pfUnderlineFromBelow, ULMETRIC* pulm, BOOL *pfGood)
  95. {
  96. LSULINFO lsulinfo;
  97. LSERR lserr;
  98. long dvpUnderlineLim;
  99. lserr = (*plsc->lscbk.pfnGetRunUnderlineInfo)(plsc->pols, pdn->u.real.plsrun,
  100. &(pdn->u.real.objdim.heightsPres), lstflow,
  101. &lsulinfo);
  102. if (lserr != lserrNone) return lserr;
  103. pulm->kul = lsulinfo.kulbase;
  104. pulm->cNumberOfLines = lsulinfo.cNumberOfLines;
  105. pulm->dvpFirstUnderlineSize = lsulinfo.dvpFirstUnderlineSize;
  106. *pfUnderlineFromBelow = (lsulinfo.dvpFirstUnderlineOffset >= lsulinfo.dvpUnderlineOriginOffset);
  107. if (*pfUnderlineFromBelow)
  108. {
  109. pulm->dvpFirstUnderlineOffset = lsulinfo.dvpFirstUnderlineOffset;
  110. pulm->dvpUnderlineOriginOffset = lsulinfo.dvpUnderlineOriginOffset;
  111. dvpUnderlineLim = pdn->u.real.objdim.heightsPres.dvDescent + pdn->u.real.lschp.dvpPos;
  112. }
  113. else
  114. {
  115. pulm->dvpFirstUnderlineOffset = -lsulinfo.dvpFirstUnderlineOffset;
  116. pulm->dvpUnderlineOriginOffset = -lsulinfo.dvpUnderlineOriginOffset;
  117. dvpUnderlineLim = pdn->u.real.objdim.heightsPres.dvAscent + 1 - pdn->u.real.lschp.dvpPos;
  118. }
  119. *pfGood = pulm->dvpFirstUnderlineSize > 0 &&
  120. (dvpUnderlineLim == 0 || pulm->dvpFirstUnderlineOffset < dvpUnderlineLim);
  121. if (lsulinfo.cNumberOfLines == 2)
  122. {
  123. pulm->dvpGapBetweenLines = lsulinfo.dvpGapBetweenLines;
  124. pulm->dvpSecondUnderlineSize = lsulinfo.dvpSecondUnderlineSize;
  125. *pfGood = *pfGood && pulm->dvpSecondUnderlineSize > 0;
  126. }
  127. else
  128. {
  129. Assert (lsulinfo.cNumberOfLines == 1);
  130. pulm->dvpGapBetweenLines = 0;
  131. pulm->dvpSecondUnderlineSize = 0;
  132. };
  133. if (!*pfGood)
  134. {
  135. pulm->dvpUnderlineOriginOffset = 0; // to provide good input to DrawUnderlineAsText
  136. }
  137. // dvpFirstUnderlineOffset was relative to local baseline until this moment, it is relative
  138. // to the UnderlineOrigin from now on. (because we average runs with the same UnderlineOrigin)
  139. pulm->dvpFirstUnderlineOffset -= pulm->dvpUnderlineOriginOffset;
  140. // The notion of bad metrics was introduced in Word to deal with particular, now obsolete, printers.
  141. // Word doesn't support them any more, other clients never cared about them.
  142. // We drop the support for them now too.
  143. // The assignment below makes a lot of code in dispul.c and dispmain.c unneeded or unreachable.
  144. // Callback pfnDrawUnderlineAsText will never be called now. Input parameter fUnderline to
  145. // pfnDrawTextRun is now always False.
  146. // Now is not the time to make big changes, maybe later.
  147. *pfGood = fTrue;
  148. return lserrNone;
  149. }
  150. // %%Function: GetUnderlineOrigin
  151. // %%Contact: victork
  152. //
  153. /* normal and raised text are in the same group, lowered texts doesn't mix */
  154. // Note: dvpUnderlineOriginOffset is relative to the local baseline, positive means down the page
  155. // in case of fUnderlineFromBelow - bigger means lower.
  156. // dvpUnderlineOrigin is relative to the current baseline, negative means down the page
  157. // in case of fUnderlineFromBelow - bigger means higher (sign changed).
  158. //
  159. static void GetUnderlineOrigin(PLSDNODE pdn, BOOL fUnderlineFromBelow, long dvpUnderlineOriginOffset,
  160. long* pdvpSubscriptOffset, long* pdvpUnderlineOrigin)
  161. {
  162. if (fUnderlineFromBelow)
  163. {
  164. *pdvpSubscriptOffset = pdn->u.real.lschp.dvpPos;
  165. *pdvpUnderlineOrigin = pdn->u.real.lschp.dvpPos - dvpUnderlineOriginOffset;
  166. }
  167. else
  168. {
  169. *pdvpSubscriptOffset = -pdn->u.real.lschp.dvpPos;
  170. *pdvpUnderlineOrigin = -pdn->u.real.lschp.dvpPos - dvpUnderlineOriginOffset;
  171. }
  172. if (*pdvpSubscriptOffset > 0)
  173. {
  174. *pdvpSubscriptOffset = 0; // put all superscripts in the baseline group
  175. }
  176. return;
  177. }
  178. // %%Function: GetUnderlineMergeMetric
  179. // %%Contact: victork
  180. //
  181. /* For aesthetics, we try to underline dnodes (typically text) on the same side of
  182. the baseline (normal text and superscripts are considered to be on the
  183. same side of the baseline, versus subscripts, which are on the other side) with one
  184. continuous underline in even thickness. The underline metric used is the
  185. average from all those dnodes which are at the lowest height in the
  186. merge group. Merge is sometimes not possible because some dnodes may have
  187. bad underline metric. The following rules describe the merge decision
  188. under all possible scenarios. The dnodes in question are all on the same
  189. side of the baseline, i.e, there is never a merge of underline if it involes
  190. crossing the baseline.
  191. Rules for merging underlined dnodes on the same side of the baseline
  192. A. current: good Metric, new dnode: good metric
  193. Merge? Metric Used
  194. new dnode same height : yes average
  195. new dnode lower : yes new dnode
  196. new dnode higher : yes current
  197. B. current: good Metric, new dnode: bad metric
  198. Merge? Metric Used
  199. new dnode same height : no
  200. new dnode lower : no
  201. new dnode higher : yes current
  202. C. current: bad Metric, new dnode: good metric
  203. Merge? Metric Used
  204. new dnode same height : no
  205. new dnode lower : yes new dnode
  206. new dnode higher : no
  207. B. current: bad Metric, new dnode: bad metric
  208. Merge? Metric Used (baseline only)
  209. new dnode same height : no
  210. new dnode lower : yes new dnode
  211. new dnode higher : yes current
  212. */
  213. LSERR GetUnderlineMergeMetric(PLSC plsc, PLSDNODE pdn, POINTUV pt, long upLimUnderline,
  214. LSTFLOW lstflow, LSCP cpLimBreak, LSULMETRIC* pulmMerge, int* pcdnodes, BOOL* pfGoodMerge)
  215. {
  216. LSERR lserr;
  217. long dupNew;
  218. long dvpUnderlineOriginMerge, dvpUnderlineOriginNew;
  219. long dvpSubscriptOffsetNew, dvpSubscriptOffsetMerge;
  220. BOOL fGoodNew;
  221. BOOL fUnderlineFromBelowMerge, fUnderlineFromBelowNew;
  222. ULMETRIC ulm;
  223. ULMETRICSUM ulmSum;
  224. UINT kulMerge;
  225. DWORD cNumberOfLinesMerge;
  226. lserr = GetULMetric(plsc, pdn, lstflow, &fUnderlineFromBelowMerge, &ulm, pfGoodMerge);
  227. if (lserr != lserrNone) return lserr;
  228. *pcdnodes = 1; /* Counter for number of dnodes participationg in UL merge */
  229. kulMerge = ulm.kul;
  230. cNumberOfLinesMerge = ulm.cNumberOfLines;
  231. /* Initialize running sums with current dnode */
  232. dupNew = pdn->u.real.dup;
  233. InitULMetricSums(dupNew, &ulm, &ulmSum);
  234. GetUnderlineOrigin(pdn, fUnderlineFromBelowMerge, (long)ulm.dvpUnderlineOriginOffset,
  235. &dvpSubscriptOffsetMerge, &dvpUnderlineOriginMerge);
  236. /* March down display list to collect merge participants */
  237. pdn = AdvanceToNextDnode(pdn, lstflow, &pt);
  238. /* Iterate till end of list, or end of UL */
  239. while (FDnodeBeforeCpLim(pdn, cpLimBreak)
  240. && pdn->klsdn == klsdnReal
  241. && !pdn->u.real.lschp.fInvisible
  242. && pdn->u.real.lschp.fUnderline && pt.u < upLimUnderline
  243. )
  244. {
  245. /* loop invariance:
  246. * *pcdnodes are merged already, merge ends at pt.u,
  247. * dvpUnderlineOriginMerge reflect lowest dnode in merge group,
  248. * other variables ending with Merge - other Merge info
  249. * ulmSum contains ulm info of Merge, entries in it are not normalized yet.
  250. */
  251. lserr = GetULMetric(plsc, pdn, lstflow, &fUnderlineFromBelowNew, &ulm, &fGoodNew);
  252. if (lserr != lserrNone) return lserr;
  253. /* break if new dnode has different underline type or position */
  254. GetUnderlineOrigin(pdn, fUnderlineFromBelowNew, (long)ulm.dvpUnderlineOriginOffset,
  255. &dvpSubscriptOffsetNew, &dvpUnderlineOriginNew);
  256. if (ulm.kul != kulMerge ||
  257. ulm.cNumberOfLines != cNumberOfLinesMerge ||
  258. dvpSubscriptOffsetNew != dvpSubscriptOffsetMerge ||
  259. fUnderlineFromBelowNew != fUnderlineFromBelowMerge)
  260. {
  261. break;
  262. }
  263. /* Type and position are the same - try to extend merge */
  264. dupNew = pdn->u.real.dup;
  265. if (dvpUnderlineOriginNew < dvpUnderlineOriginMerge)
  266. { /* new dnode lower - previous metrics is irrelevant */
  267. if (*pfGoodMerge && !fGoodNew)
  268. break; /* except we won't change from good to bad */
  269. dvpUnderlineOriginMerge = dvpUnderlineOriginNew;
  270. *pfGoodMerge = fGoodNew;
  271. if (fGoodNew) /* New good metrics - */
  272. { /* restart running sums from this dnode */
  273. InitULMetricSums(dupNew, &ulm, &ulmSum);
  274. }
  275. }
  276. else if (dvpUnderlineOriginNew > dvpUnderlineOriginMerge)
  277. { /* new dnode higher - new metrics is irrelevant */
  278. if (!*pfGoodMerge && fGoodNew)
  279. break; /* except we won't throw away good for bad */
  280. }
  281. /* NB We are not adding contribution of higher dnode to running sums */
  282. else /* new dnode the same height */
  283. if (*pfGoodMerge && fGoodNew)
  284. {
  285. /* Add contribution of current dnode to running sums */
  286. AddToULMetricSums(dupNew, &ulm, &ulmSum);
  287. }
  288. else /* dvpUnderlineOriginNew == dvpUnderlineOriginMerge && */
  289. break; /* !both good */
  290. /* Advance to next dnode */
  291. ++*pcdnodes;
  292. pdn = AdvanceToNextDnode(pdn, lstflow, &pt);
  293. }
  294. pulmMerge->kul = kulMerge;
  295. pulmMerge->cNumberOfLines = cNumberOfLinesMerge;
  296. if (*pfGoodMerge)
  297. {
  298. GetAveragedMetrics(&ulmSum, pulmMerge);
  299. }
  300. if (!fUnderlineFromBelowMerge)
  301. {
  302. pulmMerge->dvpFirstUnderlineOffset = -pulmMerge->dvpFirstUnderlineOffset;
  303. dvpUnderlineOriginMerge = -dvpUnderlineOriginMerge;
  304. }
  305. pulmMerge->vpUnderlineOrigin = pt.v + dvpUnderlineOriginMerge;
  306. return lserrNone;
  307. }
  308. // %%Function: DrawUnderlineMerge
  309. // %%Contact: victork
  310. //
  311. LSERR DrawUnderlineMerge(PLSC plsc, PLSDNODE pdn, const POINT* pptOrg, int cdnodes, long upUnderlineStart,
  312. BOOL fgoodmetric, const LSULMETRIC* pulm, UINT kdispmode,
  313. const RECT* prectclip, long upLimUnderline, LSTFLOW lstflow)
  314. {
  315. /* pdn is the first of cdnodes dnodes, merged and averaged by LSULMetric. Now we cut this merge into
  316. * smaller ones if client wants interruption. Merge here means this smaller merge.
  317. */
  318. LSERR lserr;
  319. POINTUV ptUnderlineStart[2];
  320. long dvpUnderlineSize[2];
  321. long dup = 0;
  322. BOOL fInterruptUnderline;
  323. BOOL fFirstNode = TRUE;
  324. PLSRUN plsrunFirstInMerge, plsrunPrevious, plsrunCurrent = NULL;
  325. LSCP cpLastInPrevious, cpFirstInCurrent = 0;
  326. LSDCP dcpCurrent = 0;
  327. int cLines, i;
  328. POINT ptXY;
  329. POINTUV ptDummy = {0,0};
  330. cLines = (fgoodmetric && pulm->cNumberOfLines == 2) ? 2 : 1;
  331. ptUnderlineStart[0].u = upUnderlineStart;
  332. if (fgoodmetric)
  333. ptUnderlineStart[0].v = pulm->vpUnderlineOrigin - pulm->dvpFirstUnderlineOffset;
  334. else
  335. ptUnderlineStart[0].v = pulm->vpUnderlineOrigin;
  336. dvpUnderlineSize[0] = pulm->dvpFirstUnderlineSize;
  337. if (cLines == 2)
  338. {
  339. ptUnderlineStart[1].u = upUnderlineStart;
  340. ptUnderlineStart[1].v = ptUnderlineStart[0].v - pulm->dvpFirstUnderlineSize -
  341. pulm->dvpGapBetweenLines;
  342. dvpUnderlineSize[1] = pulm->dvpSecondUnderlineSize;
  343. }
  344. plsrunFirstInMerge = pdn->u.real.plsrun;
  345. while (cdnodes >= 0) /* cdnodes is at least 1 coming in */
  346. {
  347. Assert(FIsDnodeReal(pdn));
  348. /* Check to flush out pending UL */
  349. if (fFirstNode)
  350. {
  351. fFirstNode = FALSE;
  352. fInterruptUnderline = FALSE;
  353. plsrunCurrent = pdn->u.real.plsrun;
  354. cpFirstInCurrent = pdn->cpFirst;
  355. dcpCurrent = pdn->dcp;
  356. }
  357. else if (cdnodes != 0)
  358. {
  359. plsrunPrevious = plsrunCurrent;
  360. cpLastInPrevious = cpFirstInCurrent + dcpCurrent - 1;
  361. plsrunCurrent = pdn->u.real.plsrun;
  362. cpFirstInCurrent = pdn->cpFirst;
  363. dcpCurrent = pdn->dcp;
  364. lserr = (*plsc->lscbk.pfnFInterruptUnderline)(plsc->pols, plsrunPrevious, cpLastInPrevious,
  365. plsrunCurrent, cpFirstInCurrent, &fInterruptUnderline);
  366. if (lserr != lserrNone) return lserr;
  367. }
  368. else /* we've come to the last one */
  369. fInterruptUnderline = TRUE;
  370. if (fInterruptUnderline)
  371. {
  372. if (ptUnderlineStart[0].u + dup > upLimUnderline)
  373. {
  374. dup = upLimUnderline - ptUnderlineStart[0].u;
  375. }
  376. Assert(dup >= 0); /* upLimUnderline should not change */
  377. if (fgoodmetric)
  378. for (i = 0; i < cLines; ++i)
  379. {
  380. LsPointXYFromPointUV(pptOrg, lstflow, &ptUnderlineStart[i], &ptXY);
  381. lserr = (*plsc->lscbk.pfnDrawUnderline)(plsc->pols, plsrunFirstInMerge, pulm->kul,
  382. &ptXY, dup, dvpUnderlineSize[i], lstflow, kdispmode, prectclip);
  383. if (lserr != lserrNone) return lserr;
  384. }
  385. else
  386. {
  387. LsPointXYFromPointUV(pptOrg, lstflow, &ptUnderlineStart[0], &ptXY);
  388. lserr = (*plsc->lscbk.pfnDrawUnderlineAsText)(plsc->pols, plsrunFirstInMerge, &ptXY,
  389. dup, kdispmode, lstflow, prectclip);
  390. if (lserr != lserrNone) return lserr;
  391. }
  392. /* reset states to start with current dnode */
  393. ptUnderlineStart[0].u += dup;
  394. if (cLines == 2) ptUnderlineStart[1].u += dup;
  395. dup = 0;
  396. plsrunFirstInMerge = pdn->u.real.plsrun;
  397. }
  398. dup += pdn->u.real.dup;
  399. --cdnodes;
  400. if (cdnodes > 0)
  401. {
  402. pdn = AdvanceToNextDnode(pdn, lstflow, &ptDummy);
  403. }
  404. }
  405. return lserrNone;
  406. }
  407. // %%Function: GetStrikeMetric
  408. // %%Contact: victork
  409. //
  410. LSERR GetStrikeMetric(PLSC plsc, PLSDNODE pdn, LSTFLOW lstflow, LSSTRIKEMETRIC* pstm, BOOL* pfgood)
  411. {
  412. LSSTINFO lsstinfo;
  413. LSERR lserr;
  414. long dvpAscent = pdn->u.real.objdim.heightsPres.dvAscent; // dvpUppermost
  415. long dvpDescent = -pdn->u.real.objdim.heightsPres.dvDescent + 1; // dvpLowest
  416. lserr = (*plsc->lscbk.pfnGetRunStrikethroughInfo)(plsc->pols, pdn->u.real.plsrun,
  417. &(pdn->u.real.objdim.heightsPres), lstflow, &lsstinfo);
  418. if (lserr != lserrNone) return lserr;
  419. pstm->cNumberOfLines = lsstinfo.cNumberOfLines;
  420. pstm->kul = lsstinfo.kstbase;
  421. if (lsstinfo.cNumberOfLines == 2)
  422. {
  423. *pfgood = lsstinfo.dvpLowerStrikethroughOffset >= dvpDescent
  424. && lsstinfo.dvpLowerStrikethroughSize > 0
  425. && lsstinfo.dvpUpperStrikethroughOffset > lsstinfo.dvpLowerStrikethroughOffset + lsstinfo.dvpLowerStrikethroughSize
  426. && lsstinfo.dvpUpperStrikethroughSize > 0
  427. && lsstinfo.dvpUpperStrikethroughOffset + lsstinfo.dvpUpperStrikethroughSize <= dvpAscent;
  428. if (*pfgood)
  429. {
  430. pstm->dvp1stSSSize = lsstinfo.dvpLowerStrikethroughSize;
  431. pstm->dvp1stSSOffset = lsstinfo.dvpLowerStrikethroughOffset;
  432. pstm->dvp2ndSSSize = lsstinfo.dvpUpperStrikethroughSize;
  433. pstm->dvp2ndSSOffset = lsstinfo.dvpUpperStrikethroughOffset;
  434. }
  435. }
  436. else
  437. {
  438. *pfgood = lsstinfo.dvpLowerStrikethroughOffset >= dvpDescent
  439. && lsstinfo.dvpLowerStrikethroughSize > 0
  440. && lsstinfo.dvpLowerStrikethroughOffset + lsstinfo.dvpLowerStrikethroughSize <= dvpAscent;
  441. if (*pfgood)
  442. {
  443. pstm->dvp1stSSSize = lsstinfo.dvpLowerStrikethroughSize;
  444. pstm->dvp1stSSOffset = lsstinfo.dvpLowerStrikethroughOffset;
  445. }
  446. }
  447. return lserrNone;
  448. }
  449. // %%Function: StrikeDnode
  450. // %%Contact: victork
  451. //
  452. LSERR StrikeDnode(PLSC plsc, PLSDNODE pdn, const POINT* pptOrg, POINTUV pt, const LSSTRIKEMETRIC* pstm,
  453. UINT kdispmode, const RECT* prectclip, long upLimUnderline, LSTFLOW lstflow)
  454. {
  455. LSERR lserr = lserrNone;
  456. long dup;
  457. POINT ptXY;
  458. if (pt.u < upLimUnderline)
  459. {
  460. dup = pdn->u.real.dup;
  461. if (pt.u + dup > upLimUnderline) dup = upLimUnderline - pt.u;
  462. pt.v += pdn->u.real.lschp.dvpPos + pstm->dvp1stSSOffset;
  463. LsPointXYFromPointUV(pptOrg, lstflow, &pt, &ptXY);
  464. lserr = (*plsc->lscbk.pfnDrawStrikethrough)(plsc->pols, pdn->u.real.plsrun, pstm->kul,
  465. &ptXY, dup, pstm->dvp1stSSSize, lstflow, kdispmode, prectclip);
  466. if (lserr == lserrNone && pstm->cNumberOfLines == 2)
  467. {
  468. pt.v += pstm->dvp2ndSSOffset - pstm->dvp1stSSOffset;
  469. LsPointXYFromPointUV(pptOrg, lstflow, &pt, &ptXY);
  470. lserr = (*plsc->lscbk.pfnDrawStrikethrough)(plsc->pols, pdn->u.real.plsrun, pstm->kul,
  471. &ptXY, dup, pstm->dvp2ndSSSize, lstflow, kdispmode, prectclip);
  472. }
  473. }
  474. return lserr;
  475. }
  476. // Note: Lstfow and BiDi
  477. // Lstfow used in this file is always lstflow of the main subline.
  478. // It doesn't matter if no sublines are submitted and looks logical for submitted dnodes.