postext 1.29.1 → 1.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/dist/__tests__/arabicLocale.test.js +5 -5
  2. package/dist/__tests__/arabicLocale.test.js.map +1 -1
  3. package/dist/__tests__/bundle/balloonPlacementPin.test.js +5 -4
  4. package/dist/__tests__/bundle/balloonPlacementPin.test.js.map +1 -1
  5. package/dist/__tests__/bundle/cjkRulesPin.test.js +8 -6
  6. package/dist/__tests__/bundle/cjkRulesPin.test.js.map +1 -1
  7. package/dist/__tests__/bundle/designOverflowPin.test.js +1 -1
  8. package/dist/__tests__/bundle/flowColumnsPin.test.js +4 -3
  9. package/dist/__tests__/bundle/flowColumnsPin.test.js.map +1 -1
  10. package/dist/__tests__/bundle/gridBalancingPin.test.js +5 -4
  11. package/dist/__tests__/bundle/gridBalancingPin.test.js.map +1 -1
  12. package/dist/__tests__/bundle/gridBreakRulesPin.test.js +14 -10
  13. package/dist/__tests__/bundle/gridBreakRulesPin.test.js.map +1 -1
  14. package/dist/__tests__/bundle/indexGroupSplitPin.test.js +4 -3
  15. package/dist/__tests__/bundle/indexGroupSplitPin.test.js.map +1 -1
  16. package/dist/__tests__/bundle/looseOrderPin.test.js +5 -4
  17. package/dist/__tests__/bundle/looseOrderPin.test.js.map +1 -1
  18. package/dist/__tests__/bundle/refLabelBreaksPin.test.js +5 -4
  19. package/dist/__tests__/bundle/refLabelBreaksPin.test.js.map +1 -1
  20. package/dist/__tests__/bundle/scriptContextPin.test.js +6 -5
  21. package/dist/__tests__/bundle/scriptContextPin.test.js.map +1 -1
  22. package/dist/__tests__/bundle/shapingLanguagePin.test.js +142 -46
  23. package/dist/__tests__/bundle/shapingLanguagePin.test.js.map +1 -1
  24. package/dist/__tests__/bundle/taskBoxPin.test.js +1 -1
  25. package/dist/__tests__/bundle/trailingStepPin.test.js +4 -3
  26. package/dist/__tests__/bundle/trailingStepPin.test.js.map +1 -1
  27. package/dist/__tests__/bundle/wideFloatStretchPin.test.js +4 -3
  28. package/dist/__tests__/bundle/wideFloatStretchPin.test.js.map +1 -1
  29. package/dist/__tests__/bundle.test.js +1 -1
  30. package/dist/__tests__/cellText.test.d.ts +2 -0
  31. package/dist/__tests__/cellText.test.d.ts.map +1 -0
  32. package/dist/__tests__/cellText.test.js +281 -0
  33. package/dist/__tests__/cellText.test.js.map +1 -0
  34. package/dist/__tests__/chineseLocale.test.js +24 -7
  35. package/dist/__tests__/chineseLocale.test.js.map +1 -1
  36. package/dist/__tests__/cjk/japaneseHtml.test.js +3 -3
  37. package/dist/__tests__/cjk/japaneseHtml.test.js.map +1 -1
  38. package/dist/__tests__/cjk/japaneseRuby.test.js +1 -1
  39. package/dist/__tests__/cjk/japaneseRuby.test.js.map +1 -1
  40. package/dist/__tests__/cjk/japaneseSegmentLanguage.test.js +3 -3
  41. package/dist/__tests__/cjk/japaneseSegmentLanguage.test.js.map +1 -1
  42. package/dist/__tests__/codeBlocks.test.js +1 -1
  43. package/dist/__tests__/contextState.test.d.ts +2 -0
  44. package/dist/__tests__/contextState.test.d.ts.map +1 -0
  45. package/dist/__tests__/contextState.test.js +478 -0
  46. package/dist/__tests__/contextState.test.js.map +1 -0
  47. package/dist/__tests__/contextText.test.d.ts +2 -0
  48. package/dist/__tests__/contextText.test.d.ts.map +1 -0
  49. package/dist/__tests__/contextText.test.js +371 -0
  50. package/dist/__tests__/contextText.test.js.map +1 -0
  51. package/dist/__tests__/design/designTextRender.test.js +8 -1
  52. package/dist/__tests__/design/designTextRender.test.js.map +1 -1
  53. package/dist/__tests__/exports.test.js +6 -0
  54. package/dist/__tests__/exports.test.js.map +1 -1
  55. package/dist/__tests__/fontUsage.test.js +40 -0
  56. package/dist/__tests__/fontUsage.test.js.map +1 -1
  57. package/dist/__tests__/hardBreaks.test.js +1 -1
  58. package/dist/__tests__/headingInlineMarks.test.js +1 -1
  59. package/dist/__tests__/html-backend.test.js +6 -2
  60. package/dist/__tests__/html-backend.test.js.map +1 -1
  61. package/dist/__tests__/japaneseNotes.test.js +4 -2
  62. package/dist/__tests__/japaneseNotes.test.js.map +1 -1
  63. package/dist/__tests__/lineEndPieces.test.d.ts +2 -0
  64. package/dist/__tests__/lineEndPieces.test.d.ts.map +1 -0
  65. package/dist/__tests__/lineEndPieces.test.js +374 -0
  66. package/dist/__tests__/lineEndPieces.test.js.map +1 -0
  67. package/dist/__tests__/mathSizeMigration.test.js +2 -2
  68. package/dist/__tests__/pipeline/calloutInlineResourceGap.test.js +1 -1
  69. package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.js +1 -1
  70. package/dist/__tests__/pipeline/colonListRoom.test.js +1 -1
  71. package/dist/__tests__/pipeline/compoundBreaks.test.js +1 -1
  72. package/dist/__tests__/pipeline/dashBreaks.test.js +1 -1
  73. package/dist/__tests__/pipeline/headingSplitOrphans.test.js +1 -1
  74. package/dist/__tests__/pipeline/inlineFigureSpace.test.js +1 -1
  75. package/dist/__tests__/pipeline/paragraphContainerTail.test.js +1 -1
  76. package/dist/__tests__/pipeline/raggedOptimal.test.js +1 -1
  77. package/dist/__tests__/plainGeminateHead.test.d.ts +2 -0
  78. package/dist/__tests__/plainGeminateHead.test.d.ts.map +1 -0
  79. package/dist/__tests__/plainGeminateHead.test.js +92 -0
  80. package/dist/__tests__/plainGeminateHead.test.js.map +1 -0
  81. package/dist/__tests__/presets/showcaseShapingLanguage.test.d.ts +2 -0
  82. package/dist/__tests__/presets/showcaseShapingLanguage.test.d.ts.map +1 -0
  83. package/dist/__tests__/presets/showcaseShapingLanguage.test.js +52 -0
  84. package/dist/__tests__/presets/showcaseShapingLanguage.test.js.map +1 -0
  85. package/dist/__tests__/reshapedTracking.test.d.ts +2 -0
  86. package/dist/__tests__/reshapedTracking.test.d.ts.map +1 -0
  87. package/dist/__tests__/reshapedTracking.test.js +358 -0
  88. package/dist/__tests__/reshapedTracking.test.js.map +1 -0
  89. package/dist/__tests__/rtl/designRunsPainted.test.d.ts +2 -0
  90. package/dist/__tests__/rtl/designRunsPainted.test.d.ts.map +1 -0
  91. package/dist/__tests__/rtl/designRunsPainted.test.js +184 -0
  92. package/dist/__tests__/rtl/designRunsPainted.test.js.map +1 -0
  93. package/dist/__tests__/rtl/designTextPaint.test.js +5 -1
  94. package/dist/__tests__/rtl/designTextPaint.test.js.map +1 -1
  95. package/dist/__tests__/rtl/htmlRtl.test.js +3 -3
  96. package/dist/__tests__/rtl/htmlRtl.test.js.map +1 -1
  97. package/dist/__tests__/rtl/listMarkerDirection.test.js +28 -28
  98. package/dist/__tests__/rtl/listMarkerDirection.test.js.map +1 -1
  99. package/dist/__tests__/rtl/tocNumberPainted.test.d.ts +2 -0
  100. package/dist/__tests__/rtl/tocNumberPainted.test.d.ts.map +1 -0
  101. package/dist/__tests__/rtl/tocNumberPainted.test.js +113 -0
  102. package/dist/__tests__/rtl/tocNumberPainted.test.js.map +1 -0
  103. package/dist/__tests__/scriptContext.test.js +141 -1
  104. package/dist/__tests__/scriptContext.test.js.map +1 -1
  105. package/dist/__tests__/shapingLanguage.test.js +60 -43
  106. package/dist/__tests__/shapingLanguage.test.js.map +1 -1
  107. package/dist/__tests__/trackedLetters.test.d.ts +2 -0
  108. package/dist/__tests__/trackedLetters.test.d.ts.map +1 -0
  109. package/dist/__tests__/trackedLetters.test.js +380 -0
  110. package/dist/__tests__/trackedLetters.test.js.map +1 -0
  111. package/dist/__tests__/trackedLigatures.test.js +23 -10
  112. package/dist/__tests__/trackedLigatures.test.js.map +1 -1
  113. package/dist/__tests__/verseLines.test.js +1 -1
  114. package/dist/__tests__/wordCacheOrder.test.d.ts +2 -0
  115. package/dist/__tests__/wordCacheOrder.test.d.ts.map +1 -0
  116. package/dist/__tests__/wordCacheOrder.test.js +352 -0
  117. package/dist/__tests__/wordCacheOrder.test.js.map +1 -0
  118. package/dist/__tests__/wordPieces.test.d.ts +2 -0
  119. package/dist/__tests__/wordPieces.test.d.ts.map +1 -0
  120. package/dist/__tests__/wordPieces.test.js +762 -0
  121. package/dist/__tests__/wordPieces.test.js.map +1 -0
  122. package/dist/bidi.d.ts +12 -0
  123. package/dist/bidi.d.ts.map +1 -1
  124. package/dist/bidi.js +23 -0
  125. package/dist/bidi.js.map +1 -1
  126. package/dist/bundle/configVersion.d.ts +49 -23
  127. package/dist/bundle/configVersion.d.ts.map +1 -1
  128. package/dist/bundle/configVersion.js +54 -25
  129. package/dist/bundle/configVersion.js.map +1 -1
  130. package/dist/canvas-backend/annotations.d.ts.map +1 -1
  131. package/dist/canvas-backend/annotations.js +8 -7
  132. package/dist/canvas-backend/annotations.js.map +1 -1
  133. package/dist/canvas-backend/blockRender.d.ts.map +1 -1
  134. package/dist/canvas-backend/blockRender.js +81 -47
  135. package/dist/canvas-backend/blockRender.js.map +1 -1
  136. package/dist/canvas-backend/cellText.d.ts +12 -0
  137. package/dist/canvas-backend/cellText.d.ts.map +1 -0
  138. package/dist/canvas-backend/cellText.js +114 -0
  139. package/dist/canvas-backend/cellText.js.map +1 -0
  140. package/dist/canvas-backend/chip.d.ts.map +1 -1
  141. package/dist/canvas-backend/chip.js +12 -9
  142. package/dist/canvas-backend/chip.js.map +1 -1
  143. package/dist/canvas-backend/comic.d.ts.map +1 -1
  144. package/dist/canvas-backend/comic.js +9 -8
  145. package/dist/canvas-backend/comic.js.map +1 -1
  146. package/dist/canvas-backend/contextState.d.ts +69 -0
  147. package/dist/canvas-backend/contextState.d.ts.map +1 -0
  148. package/dist/canvas-backend/contextState.js +96 -0
  149. package/dist/canvas-backend/contextState.js.map +1 -0
  150. package/dist/canvas-backend/contextText.d.ts +76 -0
  151. package/dist/canvas-backend/contextText.d.ts.map +1 -0
  152. package/dist/canvas-backend/contextText.js +102 -0
  153. package/dist/canvas-backend/contextText.js.map +1 -0
  154. package/dist/canvas-backend/decorations.d.ts.map +1 -1
  155. package/dist/canvas-backend/decorations.js +11 -10
  156. package/dist/canvas-backend/decorations.js.map +1 -1
  157. package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
  158. package/dist/canvas-backend/headerFooter.js +23 -15
  159. package/dist/canvas-backend/headerFooter.js.map +1 -1
  160. package/dist/canvas-backend/index.d.ts.map +1 -1
  161. package/dist/canvas-backend/index.js +41 -17
  162. package/dist/canvas-backend/index.js.map +1 -1
  163. package/dist/canvas-backend/mirrorFrame.d.ts.map +1 -1
  164. package/dist/canvas-backend/mirrorFrame.js +5 -4
  165. package/dist/canvas-backend/mirrorFrame.js.map +1 -1
  166. package/dist/canvas-backend/renderResourceBlock.d.ts.map +1 -1
  167. package/dist/canvas-backend/renderResourceBlock.js +36 -29
  168. package/dist/canvas-backend/renderResourceBlock.js.map +1 -1
  169. package/dist/canvas-backend/runDirection.d.ts.map +1 -1
  170. package/dist/canvas-backend/runDirection.js +9 -5
  171. package/dist/canvas-backend/runDirection.js.map +1 -1
  172. package/dist/canvas-backend/scriptText.d.ts.map +1 -1
  173. package/dist/canvas-backend/scriptText.js +11 -9
  174. package/dist/canvas-backend/scriptText.js.map +1 -1
  175. package/dist/canvas-backend/segmentText.d.ts.map +1 -1
  176. package/dist/canvas-backend/segmentText.js +18 -5
  177. package/dist/canvas-backend/segmentText.js.map +1 -1
  178. package/dist/canvas-backend/swatch.d.ts.map +1 -1
  179. package/dist/canvas-backend/swatch.js +3 -2
  180. package/dist/canvas-backend/swatch.js.map +1 -1
  181. package/dist/canvas-backend/trackedText.d.ts +75 -1
  182. package/dist/canvas-backend/trackedText.d.ts.map +1 -1
  183. package/dist/canvas-backend/trackedText.js +192 -28
  184. package/dist/canvas-backend/trackedText.js.map +1 -1
  185. package/dist/canvas-backend/verticalText.d.ts +12 -2
  186. package/dist/canvas-backend/verticalText.d.ts.map +1 -1
  187. package/dist/canvas-backend/verticalText.js +64 -38
  188. package/dist/canvas-backend/verticalText.js.map +1 -1
  189. package/dist/canvas-backend/wordPieces.d.ts +31 -0
  190. package/dist/canvas-backend/wordPieces.d.ts.map +1 -0
  191. package/dist/canvas-backend/wordPieces.js +132 -0
  192. package/dist/canvas-backend/wordPieces.js.map +1 -0
  193. package/dist/canvas-backend/wordRuns.d.ts +13 -1
  194. package/dist/canvas-backend/wordRuns.d.ts.map +1 -1
  195. package/dist/canvas-backend/wordRuns.js +38 -23
  196. package/dist/canvas-backend/wordRuns.js.map +1 -1
  197. package/dist/comics/lettering/__tests__/fitAsPainted.test.d.ts +2 -0
  198. package/dist/comics/lettering/__tests__/fitAsPainted.test.d.ts.map +1 -0
  199. package/dist/comics/lettering/__tests__/fitAsPainted.test.js +97 -0
  200. package/dist/comics/lettering/__tests__/fitAsPainted.test.js.map +1 -0
  201. package/dist/comics/lettering/shape-text.d.ts.map +1 -1
  202. package/dist/comics/lettering/shape-text.js +39 -11
  203. package/dist/comics/lettering/shape-text.js.map +1 -1
  204. package/dist/defaults/bodyText.d.ts.map +1 -1
  205. package/dist/defaults/bodyText.js +6 -5
  206. package/dist/defaults/bodyText.js.map +1 -1
  207. package/dist/design/bidiText.d.ts +45 -6
  208. package/dist/design/bidiText.d.ts.map +1 -1
  209. package/dist/design/bidiText.js +78 -10
  210. package/dist/design/bidiText.js.map +1 -1
  211. package/dist/design/cjkText.d.ts +3 -0
  212. package/dist/design/cjkText.d.ts.map +1 -1
  213. package/dist/design/cjkText.js +1 -1
  214. package/dist/design/cjkText.js.map +1 -1
  215. package/dist/design/layout.d.ts.map +1 -1
  216. package/dist/design/layout.js +36 -5
  217. package/dist/design/layout.js.map +1 -1
  218. package/dist/design/richText.d.ts +9 -1
  219. package/dist/design/richText.d.ts.map +1 -1
  220. package/dist/design/richText.js +8 -2
  221. package/dist/design/richText.js.map +1 -1
  222. package/dist/fonts/usage.d.ts +2 -0
  223. package/dist/fonts/usage.d.ts.map +1 -1
  224. package/dist/fonts/usage.js +18 -0
  225. package/dist/fonts/usage.js.map +1 -1
  226. package/dist/html-backend.d.ts.map +1 -1
  227. package/dist/html-backend.js +664 -84
  228. package/dist/html-backend.js.map +1 -1
  229. package/dist/index.d.ts +3 -1
  230. package/dist/index.d.ts.map +1 -1
  231. package/dist/index.js +4 -1
  232. package/dist/index.js.map +1 -1
  233. package/dist/knuthPlass/breakpoints.d.ts.map +1 -1
  234. package/dist/knuthPlass/breakpoints.js +4 -2
  235. package/dist/knuthPlass/breakpoints.js.map +1 -1
  236. package/dist/knuthPlass/pretextAdapter.d.ts +6 -3
  237. package/dist/knuthPlass/pretextAdapter.d.ts.map +1 -1
  238. package/dist/knuthPlass/pretextAdapter.js +11 -3
  239. package/dist/knuthPlass/pretextAdapter.js.map +1 -1
  240. package/dist/knuthPlass/richAdapter.d.ts +13 -1
  241. package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
  242. package/dist/knuthPlass/richAdapter.js +53 -5
  243. package/dist/knuthPlass/richAdapter.js.map +1 -1
  244. package/dist/knuthPlass/tracking.d.ts.map +1 -1
  245. package/dist/knuthPlass/tracking.js +3 -2
  246. package/dist/knuthPlass/tracking.js.map +1 -1
  247. package/dist/knuthPlass/types.d.ts +6 -0
  248. package/dist/knuthPlass/types.d.ts.map +1 -1
  249. package/dist/locale.d.ts +25 -18
  250. package/dist/locale.d.ts.map +1 -1
  251. package/dist/locale.js +27 -20
  252. package/dist/locale.js.map +1 -1
  253. package/dist/looseLines.d.ts.map +1 -1
  254. package/dist/looseLines.js +3 -2
  255. package/dist/looseLines.js.map +1 -1
  256. package/dist/measure/canvas.d.ts +21 -0
  257. package/dist/measure/canvas.d.ts.map +1 -1
  258. package/dist/measure/canvas.js +165 -85
  259. package/dist/measure/canvas.js.map +1 -1
  260. package/dist/measure/cjkCompose.d.ts.map +1 -1
  261. package/dist/measure/cjkCompose.js +31 -5
  262. package/dist/measure/cjkCompose.js.map +1 -1
  263. package/dist/measure/plain.d.ts.map +1 -1
  264. package/dist/measure/plain.js +31 -6
  265. package/dist/measure/plain.js.map +1 -1
  266. package/dist/measure/pretextLanguage.d.ts.map +1 -1
  267. package/dist/measure/pretextLanguage.js +49 -7
  268. package/dist/measure/pretextLanguage.js.map +1 -1
  269. package/dist/measure/rich.d.ts +18 -1
  270. package/dist/measure/rich.d.ts.map +1 -1
  271. package/dist/measure/rich.js +200 -29
  272. package/dist/measure/rich.js.map +1 -1
  273. package/dist/measure/script.d.ts +17 -1
  274. package/dist/measure/script.d.ts.map +1 -1
  275. package/dist/measure/script.js +17 -1
  276. package/dist/measure/script.js.map +1 -1
  277. package/dist/measure/trackedLigatures.d.ts +59 -0
  278. package/dist/measure/trackedLigatures.d.ts.map +1 -0
  279. package/dist/measure/trackedLigatures.js +144 -0
  280. package/dist/measure/trackedLigatures.js.map +1 -0
  281. package/dist/pipeline/build.d.ts.map +1 -1
  282. package/dist/pipeline/build.js +4 -3
  283. package/dist/pipeline/build.js.map +1 -1
  284. package/dist/pipeline/calloutLayout.d.ts.map +1 -1
  285. package/dist/pipeline/calloutLayout.js +26 -7
  286. package/dist/pipeline/calloutLayout.js.map +1 -1
  287. package/dist/pipeline/lists.d.ts +13 -4
  288. package/dist/pipeline/lists.d.ts.map +1 -1
  289. package/dist/pipeline/lists.js +49 -12
  290. package/dist/pipeline/lists.js.map +1 -1
  291. package/dist/pipeline/toc.d.ts.map +1 -1
  292. package/dist/pipeline/toc.js +33 -9
  293. package/dist/pipeline/toc.js.map +1 -1
  294. package/dist/types.d.ts +35 -22
  295. package/dist/types.d.ts.map +1 -1
  296. package/dist/wordPieces.d.ts +120 -0
  297. package/dist/wordPieces.d.ts.map +1 -0
  298. package/dist/wordPieces.js +319 -0
  299. package/dist/wordPieces.js.map +1 -0
  300. package/package.json +1 -1
@@ -0,0 +1,358 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { renderBlock } from '../canvas-backend/blockRender';
3
+ import { fillTrackedWord, setLetterTracking } from '../canvas-backend/trackedText';
4
+ import { setSegmentLanguages } from '../canvas-backend/wordRuns';
5
+ import { setLetterSpacing } from '../canvas-backend/contextState';
6
+ import { setVerticalPaint } from '../canvas-backend/verticalText';
7
+ import { renderToHtml } from '../html-backend';
8
+ import { buildDocument } from '../pipeline';
9
+ // #770: what a letter-spacing takes away besides ligatures. Chrome sets no
10
+ // contextual alternate under a letter-spacing, and the canvas cannot ask
11
+ // for one: a tracked word of a face with such forms was measured with them
12
+ // and painted without. In a document shaped in its own language a word
13
+ // whose pieces do not end where it was measured to end, or that the
14
+ // letter-spacing reshapes with no ligature to keep, is set whole at the
15
+ // letter-spacing that ends it there, on the canvas and in the HTML. And two
16
+ // more texts painted as measured: the pieces of a sideways word down a
17
+ // vertical line on the canvas, and the runs of a design line in the HTML.
18
+ // A face as a browser measures it. With no letter-spacing: ligatures (ff,
19
+ // fi, fl, ffi) narrower than their letters; a hyphen between two capitals
20
+ // 0.1 em wider (a form by its two neighbours: no pair of letters tells);
21
+ // an N after a U 0.05 em wider (a form by one neighbour, which reads as a
22
+ // ligature of the pair), and a Hebrew bet after an alef; a T after NI 0.1
23
+ // em wider (so `IT`, set alone
24
+ // after `UN`, is not as wide as its part of `UNIT`); a Han character
25
+ // between two others 0.2 em narrower (a face that draws its cells by their
26
+ // neighbours). Under a letter-spacing none of them, and the spacing after
27
+ // every letter. A zero width non-joiner advances nothing and takes no
28
+ // spacing; no ligature forms across it, and the forms by the neighbours
29
+ // stand across it.
30
+ const ZWNJ = '\u200C';
31
+ const ADVANCE = (ch) => {
32
+ if (ch === ' ')
33
+ return 0.25;
34
+ if ('ilf-'.includes(ch))
35
+ return 0.3;
36
+ if (/[A-Z]/.test(ch))
37
+ return 0.6;
38
+ if (ch.codePointAt(0) >= 0x2e80)
39
+ return 1;
40
+ return 0.5;
41
+ };
42
+ const LIGATURES = [['ffi', 0.75], ['ff', 0.5], ['fi', 0.5], ['fl', 0.5]];
43
+ function naturalWidth(raw, size, shaped) {
44
+ // The letters, and whether a non-joiner stands before each.
45
+ const text = raw.replaceAll(ZWNJ, '');
46
+ const apart = [];
47
+ for (let i = 0; i < raw.length; i++)
48
+ if (raw[i] !== ZWNJ)
49
+ apart.push(raw[i - 1] === ZWNJ);
50
+ let w = 0;
51
+ for (let i = 0; i < text.length;) {
52
+ const lig = shaped ? LIGATURES.find(([l]) => text.startsWith(l, i) && !apart.slice(i + 1, i + l.length).includes(true)) : undefined;
53
+ if (lig) {
54
+ w += lig[1] * size;
55
+ i += lig[0].length;
56
+ continue;
57
+ }
58
+ w += ADVANCE(text[i]) * size;
59
+ if (shaped) {
60
+ if (text[i] === '-' && /[A-Z]/.test(text[i - 1] ?? '') && /[A-Z]/.test(text[i + 1] ?? ''))
61
+ w += 0.1 * size;
62
+ if (text[i] === 'N' && text[i - 1] === 'U')
63
+ w += 0.05 * size;
64
+ if (text[i] === '\u05D1' && text[i - 1] === '\u05D0')
65
+ w += 0.05 * size;
66
+ if (text[i] === 'T' && text.slice(i - 2, i) === 'NI')
67
+ w += 0.1 * size;
68
+ if (text[i] === '\u5B57' && text[i - 1] === '\u6F22' && text[i + 1] === '\u4F53')
69
+ w -= 0.2 * size;
70
+ }
71
+ i++;
72
+ }
73
+ return w;
74
+ }
75
+ const lettersOf = (text) => text.replaceAll(ZWNJ, '').length;
76
+ const sizeOf = (font) => parseFloat(/(\d*\.?\d+)px/.exec(font)?.[1] ?? '10');
77
+ class BrowserCtx {
78
+ font = '10px Body';
79
+ letterSpacing = '0px';
80
+ lang = 'inherit';
81
+ measureText(s) {
82
+ const spacing = parseFloat(this.letterSpacing) || 0;
83
+ return { width: naturalWidth(s, sizeOf(this.font), spacing === 0) + spacing * lettersOf(s) };
84
+ }
85
+ }
86
+ function paintingCtx() {
87
+ const seen = [];
88
+ const ctx = Object.assign(new BrowserCtx(), {
89
+ fillStyle: '', textBaseline: 'alphabetic', textAlign: 'left',
90
+ fillText(text, x, y) {
91
+ seen.push({ text, x, y, spacing: parseFloat(this.letterSpacing) || 0, width: this.measureText(text).width });
92
+ },
93
+ save() { }, restore() { }, beginPath() { }, rect() { }, clip() { }, fillRect() { }, moveTo() { }, lineTo() { }, stroke() { },
94
+ });
95
+ return { ctx: ctx, seen };
96
+ }
97
+ globalThis.OffscreenCanvas = class {
98
+ getContext() {
99
+ return new BrowserCtx();
100
+ }
101
+ };
102
+ /** `text` painted as a tracked word at 20 px, 2 px a letter, from x = 100,
103
+ * in a document shaped in its own language (`own`) or its host's. */
104
+ function tracked(text, own) {
105
+ const { ctx, seen } = paintingCtx();
106
+ ctx.font = '20px Body';
107
+ setLetterSpacing(ctx, 2);
108
+ setLetterTracking(own);
109
+ const advance = fillTrackedWord(ctx, text, 100, 50, 2, (piece, x, y) => ctx.fillText(piece, x, y));
110
+ setLetterTracking(false);
111
+ return { seen, advance, left: ctx.letterSpacing };
112
+ }
113
+ /** The width `text` was measured at: its natural width and 2 px a letter. */
114
+ const measured = (text) => naturalWidth(text, 20, true) + 2 * text.length;
115
+ describe('a tracked word the letter-spacing reshapes, on canvas (#770)', () => {
116
+ it('with no ligature to keep: whole, at the letter-spacing that ends it where it was measured', () => {
117
+ const own = tracked('TEA-PARTY', true);
118
+ expect(own.seen.map((p) => p.text)).toEqual(['TEA-PARTY']);
119
+ const [p] = own.seen;
120
+ expect(p.x).toBe(100);
121
+ // The hyphen is 2 px narrower under a letter-spacing: shared among nine letters.
122
+ expect(p.spacing).toBeCloseTo(2 + 2 / 9, 9);
123
+ expect(p.width).toBeCloseTo(measured('TEA-PARTY'), 9);
124
+ expect(own.advance).toBeCloseTo(measured('TEA-PARTY'), 9);
125
+ expect(own.left).toBe('2px');
126
+ // Keeping its host's language: at the tracking, 2 px short of its box, as it was.
127
+ const host = tracked('TEA-PARTY', false);
128
+ expect(host.seen.map((p) => [p.text, p.spacing])).toEqual([['TEA-PARTY', 2]]);
129
+ expect(host.seen[0].width).toBeCloseTo(measured('TEA-PARTY') - 2, 9);
130
+ expect(host.advance).toBeUndefined();
131
+ });
132
+ it('whose pieces do not end where it was measured to end: whole, the same way', () => {
133
+ const own = tracked('UNIT', true);
134
+ expect(own.seen.map((p) => p.text)).toEqual(['UNIT']);
135
+ // 1 px for the N and 2 px for the T, shared among four letters.
136
+ expect(own.seen[0].spacing).toBeCloseTo(2 + 3 / 4, 9);
137
+ expect(own.seen[0].x + own.seen[0].width).toBeCloseTo(100 + measured('UNIT'), 9);
138
+ // Keeping its host's language: the pieces it had, which end 2 px short.
139
+ const host = tracked('UNIT', false);
140
+ expect(host.seen.map((p) => [p.text, p.spacing])).toEqual([['UN', 0], ['IT', 2]]);
141
+ });
142
+ it('letters in a form by their neighbour are no ligature: tracked as the rest of the line', () => {
143
+ // `UN`: the N is 1 px wider after a U, a form the non-joiner leaves
144
+ // and the letter-spacing takes away. Read as a ligature, the word was
145
+ // painted with no tracking inside and 4 px of it after.
146
+ const own = tracked('UN', true);
147
+ expect(own.seen.map((p) => p.text)).toEqual(['UN']);
148
+ const [p] = own.seen;
149
+ expect(p.x).toBe(100);
150
+ // 2 px a letter, and the 1 px of the N's form shared between the two.
151
+ expect(p.spacing).toBeCloseTo(2 + 1 / 2, 9);
152
+ expect(p.x + p.width).toBeCloseTo(100 + measured('UN'), 9);
153
+ expect(own.advance).toBeCloseTo(measured('UN'), 9);
154
+ expect(own.left).toBe('2px');
155
+ // In a line of several words it is spaced as they are.
156
+ const line = tracked('UN MAD TEA-PARTY', true);
157
+ expect(line.seen.map((q) => q.text)).toEqual(['UN', ' ', 'MAD', ' ', 'TEA-PARTY']);
158
+ expect(line.seen[0].spacing).toBeCloseTo(2.5, 9);
159
+ expect(line.seen[2].x).toBeCloseTo(100 + measured('UN '), 9);
160
+ // A ligature, which the non-joiner dissolves, keeps its piece.
161
+ expect(tracked('fi', true).seen.map((q) => [q.text, q.spacing])).toEqual([['fi', 0]]);
162
+ // Keeping its host's language: the pair is painted as the ligature it
163
+ // was read as.
164
+ const host = tracked('UN', false);
165
+ expect(host.seen.map((q) => [q.text, q.spacing])).toEqual([['UN', 0]]);
166
+ });
167
+ it('a right-to-left word is painted as it was, forms by the neighbours and all', () => {
168
+ // Alef and bet, the bet in a form by its neighbour: never painted at a
169
+ // letter-spacing of its own, so it keeps the piece it had.
170
+ const WORD = '\u05D0\u05D1';
171
+ const painted = (own) => {
172
+ const { ctx, seen } = paintingCtx();
173
+ ctx.font = '20px Body';
174
+ ctx.direction = 'rtl';
175
+ setLetterSpacing(ctx, 2);
176
+ setLetterTracking(own);
177
+ fillTrackedWord(ctx, WORD, 100, 50, 2, (piece, x, y) => ctx.fillText(piece, x, y));
178
+ setLetterTracking(false);
179
+ return seen.map((p) => [p.text, p.spacing]);
180
+ };
181
+ expect(painted(true)).toEqual([[WORD, 0]]);
182
+ expect(painted(true)).toEqual(painted(false));
183
+ });
184
+ it('a word whose ligature pieces fit keeps them', () => {
185
+ for (const own of [true, false]) {
186
+ const { seen, advance } = tracked('first', own);
187
+ expect(seen.map((p) => [p.text, p.spacing])).toEqual([['fi', 0], ['rst', 2]]);
188
+ expect(advance).toBeCloseTo(measured('first'), 9);
189
+ }
190
+ // Every letter tracked: the piece after the ligature ends on the box.
191
+ const last = tracked('first', true).seen[1];
192
+ expect(last.x + last.width).toBeCloseTo(100 + measured('first'), 9);
193
+ });
194
+ it('a text of several words: word by word, each where the natural shaping puts it', () => {
195
+ const { seen, advance } = tracked('first A MAD TEA-PARTY', true);
196
+ expect(seen.map((p) => p.text)).toEqual(['fi', 'rst', ' ', 'A', ' ', 'MAD', ' ', 'TEA-PARTY']);
197
+ // Each word starts at the natural width of what stands before it and
198
+ // the tracking of every letter before it.
199
+ const at = (before) => 100 + measured(before);
200
+ expect(seen[3].x).toBeCloseTo(at('first '), 9);
201
+ expect(seen[5].x).toBeCloseTo(at('first A '), 9);
202
+ expect(seen[7].x).toBeCloseTo(at('first A MAD '), 9);
203
+ expect(seen.slice(1, 7).every((p) => p.spacing === 2)).toBe(true);
204
+ expect(seen[7].spacing).toBeCloseTo(2 + 2 / 9, 9);
205
+ expect(seen[7].x + seen[7].width).toBeCloseTo(at('first A MAD TEA-PARTY'), 9);
206
+ expect(advance).toBeCloseTo(measured('first A MAD TEA-PARTY'), 9);
207
+ // A text the letter-spacing leaves as it is: one text, as before.
208
+ expect(tracked('A MAD DAY', true).seen.map((p) => p.text)).toEqual(['A MAD DAY']);
209
+ });
210
+ it('a text with a CJK character is left at the tracking: its cells are not measured at a natural width', () => {
211
+ const { seen, advance } = tracked(CJK, true);
212
+ expect(seen.map((p) => [p.text, p.spacing])).toEqual([[CJK, 2]]);
213
+ expect(advance).toBeUndefined();
214
+ });
215
+ });
216
+ // Three Han characters the face draws 0.2 em narrower together.
217
+ const CJK = '\u6F22\u5B57\u4F53';
218
+ const pt = (value) => ({ value, unit: 'pt' });
219
+ // 72 dpi: 1 pt = 1 px.
220
+ const OWN = {
221
+ page: { width: pt(400), height: pt(900), dpi: 72, margins: { top: pt(40), bottom: pt(10), left: pt(10), right: pt(10) } },
222
+ layout: { layoutType: 'single' },
223
+ header: { elements: [] },
224
+ footer: { elements: [] },
225
+ bodyText: { fontSize: pt(10), lineHeight: pt(14), firstLineIndent: pt(0), hyphenation: { enabled: false }, shapingLanguage: 'document' },
226
+ };
227
+ const HOST = { ...OWN, bodyText: { ...OWN.bodyText, shapingLanguage: 'host' } };
228
+ const head = (config, element) => ({
229
+ ...config,
230
+ header: { elements: [{ kind: 'text', id: 'rh', fontSize: pt(10), placement: { anchor: { to: 'container', edge: 'top-left' }, size: { width: 'auto' } }, ...element }] },
231
+ });
232
+ const headOf = (doc) => doc.pages[0].header.blocks.find((b) => b.kind === 'text');
233
+ describe('a tracked design text the letter-spacing reshapes, in HTML (#770)', () => {
234
+ const TEXT = 'first TEA-PARTY UNIT';
235
+ it('shaped in its own language: each such word in a box at its own letter-spacing', () => {
236
+ const doc = buildDocument({ markdown: 'Text.' }, head(OWN, { content: TEXT, letterSpacing: pt(0.2) }));
237
+ // Measured at its natural width and the tracking of each letter.
238
+ expect(headOf(doc).lines[0].width).toBeCloseTo(naturalWidth(TEXT, 10, true) + 0.2 * TEXT.length, 6);
239
+ const html = renderToHtml(doc);
240
+ // 1 px over nine letters; 0.5 px and 1 px over four.
241
+ expect(html).toContain('<span style="letter-spacing:0.3111px;">TEA-PARTY</span>');
242
+ expect(html).toContain('<span style="letter-spacing:0.5750px;">UNIT</span>');
243
+ // A ligature whose pieces fit stays a box of its own.
244
+ expect(html).toMatch(/<span style="letter-spacing:0;margin-inline-end:0\.400px;">fi<\/span>rst/);
245
+ });
246
+ it('letters in a form by their neighbour are no ligature: the word in a box at its own letter-spacing', () => {
247
+ const doc = buildDocument({ markdown: 'Text.' }, head(OWN, { content: 'UN first', letterSpacing: pt(0.2) }));
248
+ const html = renderToHtml(doc);
249
+ // 0.2 px a letter, and the 0.5 px of the N's form shared between the two.
250
+ expect(html).toContain('<span style="letter-spacing:0.4500px;">UN</span>');
251
+ expect(html).not.toMatch(/<span style="letter-spacing:0;[^"]*">UN<\/span>/);
252
+ expect(html).toMatch(/<span style="letter-spacing:0;margin-inline-end:0\.400px;">fi<\/span>rst/);
253
+ });
254
+ it('keeping its host\'s language: as it was', () => {
255
+ const html = renderToHtml(buildDocument({ markdown: 'Text.' }, head(HOST, { content: TEXT, letterSpacing: pt(0.2) })));
256
+ expect(html).not.toContain('letter-spacing:0.3111px');
257
+ expect(html).not.toContain('letter-spacing:0.5750px');
258
+ expect(html).toContain('TEA-PARTY');
259
+ });
260
+ });
261
+ describe('a tracked line down a vertical page, in HTML (#770)', () => {
262
+ it('its CJK text takes no letter-spacing of its own', () => {
263
+ const config = { ...OWN, layout: { writingMode: 'vertical-rl', layoutType: 'single' }, headings: { levels: [{ level: 2, letterSpacing: pt(0.5) }] } };
264
+ const html = renderToHtml(buildDocument({ markdown: `## ${CJK}` }, config));
265
+ expect(html).toContain(CJK);
266
+ expect(html).not.toMatch(new RegExp(`<span style="letter-spacing:[-\\d.]+px;">${CJK}</span>`));
267
+ });
268
+ });
269
+ describe('a design line of several runs, in HTML (#770)', () => {
270
+ const CONTENT = 'Ada Lovelace^1^, Alan Turing^2^, Grace Hopper';
271
+ it('shaped in its own language: a box per run, each where the widths before it end', () => {
272
+ const doc = buildDocument({ markdown: 'Text.' }, head(OWN, { content: CONTENT, inlineMarks: true }));
273
+ const line = headOf(doc).lines[0];
274
+ expect(line.runs.map((r) => r.text)).toEqual(['Ada Lovelace', '1', ', Alan Turing', '2', ', Grace Hopper']);
275
+ const html = renderToHtml(doc);
276
+ let x = 0;
277
+ for (const run of line.runs) {
278
+ expect(html).toContain(`<span dir="ltr" style="position:absolute;left:${x.toFixed(3)}px;`);
279
+ x += run.width;
280
+ }
281
+ // The text reads as written.
282
+ expect(html.replace(/<[^>]+>/g, '')).toContain('Ada Lovelace1, Alan Turing2, Grace Hopper');
283
+ });
284
+ it('keeping its host\'s language: the runs inline, as they were', () => {
285
+ const html = renderToHtml(buildDocument({ markdown: 'Text.' }, head(HOST, { content: CONTENT, inlineMarks: true })));
286
+ expect(html).not.toContain('<span dir="ltr" style="position:absolute;left:');
287
+ expect(html.replace(/<[^>]+>/g, '')).toContain('Ada Lovelace1, Alan Turing2, Grace Hopper');
288
+ });
289
+ });
290
+ describe('a sideways word down a vertical line, on canvas (#770)', () => {
291
+ const paragraph = (doc) => doc.blocks.find((b) => b.type === 'paragraph');
292
+ // Soft hyphens: the word in the pieces of its syllables. The italic word
293
+ // makes the line one painted segment by segment.
294
+ const MD = 'of­fice *x* of­ficer';
295
+ const painted = (config) => {
296
+ const doc = buildDocument({ markdown: MD }, { ...config, layout: { writingMode: 'vertical-rl', layoutType: 'single' }, bodyText: { ...config.bodyText, textAlign: 'left' } });
297
+ const block = paragraph(doc);
298
+ // The layout holds the word in its pieces, the ligature across a cut:
299
+ // the second piece is what the word grew by.
300
+ expect(block.lines[0].segments.map((s) => s.text).join('|')).toContain('of|fice');
301
+ const { ctx, seen } = paintingCtx();
302
+ const outer = setVerticalPaint({ region: 'mainland' });
303
+ setSegmentLanguages(config === OWN);
304
+ renderBlock(ctx, block, block.bbox.width, block.bbox.x);
305
+ setSegmentLanguages(false);
306
+ setVerticalPaint(outer);
307
+ return seen.map((p) => p.text);
308
+ };
309
+ it('its pieces are one text where the word was measured whole', () => {
310
+ for (const config of [OWN, HOST]) {
311
+ const texts = painted(config);
312
+ expect(texts).toContain('office');
313
+ expect(texts).toContain('officer');
314
+ expect(texts).not.toContain('of');
315
+ }
316
+ });
317
+ // The Chinese guide's contents page opens on `**《Postext指南》**是Sandbox…`:
318
+ // bold marks and a bold word beside plain text, down the column. Asking
319
+ // which pieces to join sets the context's font to each style it measures
320
+ // in and leaves it there; a text is painted in the font of its own
321
+ // segment all the same, and pieces are joined inside one style only.
322
+ it('every text in the font of its own segment, a bold one beside a plain one', () => {
323
+ // The last pieces measured are bold and the first text painted is
324
+ // plain; then bold marks around a plain word, and a word half bold.
325
+ const STYLED = 'of­fice 是 **《**of­ficer**》** **of­**fice **of­ficer**';
326
+ for (const config of [OWN, HOST]) {
327
+ const doc = buildDocument({ markdown: STYLED }, { ...config, layout: { writingMode: 'vertical-rl', layoutType: 'single' }, bodyText: { ...config.bodyText, textAlign: 'left' } });
328
+ const block = paragraph(doc);
329
+ const line = block.lines[0];
330
+ expect(line.cjkComposed).toBeFalsy();
331
+ expect(line.segments.filter((s) => s.kind === 'text').map((s) => (s.bold ? `[${s.text}]` : s.text)).join('|'))
332
+ .toBe('of|fice|是|[《]|of|ficer|[》]|[of]|fice|[of]|[ficer]');
333
+ const { ctx, seen } = paintingCtx();
334
+ const fonts = [];
335
+ const fill = ctx.fillText.bind(ctx);
336
+ Object.assign(ctx, {
337
+ translate() { }, rotate() { }, scale() { },
338
+ fillText(text, x, y) {
339
+ fonts.push([text, ctx.font]);
340
+ fill(text, x, y);
341
+ },
342
+ });
343
+ const outer = setVerticalPaint({ region: 'mainland' });
344
+ setSegmentLanguages(config === OWN);
345
+ renderBlock(ctx, block, block.bbox.width, block.bbox.x);
346
+ setSegmentLanguages(false);
347
+ setVerticalPaint(outer);
348
+ expect(seen.map((p) => p.text)).toEqual(['office', '是', '《', 'officer', '》', 'of', 'fice', 'officer']);
349
+ const plain = fonts[0][1];
350
+ const bold = fonts[2][1];
351
+ expect(bold).not.toBe(plain);
352
+ expect(bold).toMatch(/bold|[6-9]00/);
353
+ expect(fonts.map(([, font]) => (font === bold ? 'bold' : font === plain ? 'plain' : font)))
354
+ .toEqual(['plain', 'plain', 'bold', 'plain', 'bold', 'bold', 'plain', 'bold']);
355
+ }
356
+ });
357
+ });
358
+ //# sourceMappingURL=reshapedTracking.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reshapedTracking.test.js","sourceRoot":"","sources":["../../src/__tests__/reshapedTracking.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=designRunsPainted.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"designRunsPainted.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/rtl/designRunsPainted.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,184 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { directDesignTextBlock, directedTextWidth, measuresRunsAsPainted } from '../../design/bidiText';
3
+ import { resolveDesignSlot } from '../../defaults/headerFooter';
4
+ import { layoutSlotToVdt } from '../../pipeline/headerFooter';
5
+ import { clearMeasurementCache } from '../../measure';
6
+ import { setMeasureLanguage } from '../../measure/canvas';
7
+ import { chipToken } from '../../measure/rich';
8
+ import { createBoundingBox } from '../../vdt';
9
+ // #770, round 2: the runs of a design text (a running head, an opener, a
10
+ // callout's title) and of a chip. A renderer paints a right-to-left run
11
+ // with its context set right to left; the layout measured the line left to
12
+ // right, whole, and each run but the last left to right too. A document
13
+ // shaped in its own language measures each run as it is painted.
14
+ const isArabicLetter = (ch) => /[ء-يـ]/.test(ch);
15
+ const isBracket = (ch) => ch === '(' || ch === ')';
16
+ /**
17
+ * The advance of `text` at 10 px in a face that draws its marks by the
18
+ * run they stand in, as Markazi Text and Amiri do. Left to right, the
19
+ * marks beside an Arabic word are runs apart: a guillemet is 4.7 px and a
20
+ * stop 3 px; right to left they are one run with the word, 4.1 px and
21
+ * 2 px. A bracket is 4.5 px in a text measured left to right that holds
22
+ * an Arabic letter, and 2.5 px alone or in a right-to-left run.
23
+ */
24
+ function faceWidth(text, rtl) {
25
+ const chars = Array.from(text);
26
+ const arabic = chars.some(isArabicLetter);
27
+ let px = 0;
28
+ for (const ch of chars) {
29
+ if (ch === ' ')
30
+ px += 2.5;
31
+ else if (ch === '«' || ch === '»')
32
+ px += rtl ? 4.1 : 4.7;
33
+ else if (ch === '.')
34
+ px += rtl ? 2 : 3;
35
+ else if (isBracket(ch))
36
+ px += !rtl && arabic ? 4.5 : 2.5;
37
+ else
38
+ px += 5;
39
+ }
40
+ return px;
41
+ }
42
+ class MeasureContext {
43
+ font = '10px Kitab';
44
+ lang = 'inherit';
45
+ direction = 'ltr';
46
+ measureText(s) {
47
+ return { width: faceWidth(s, this.direction === 'rtl') };
48
+ }
49
+ }
50
+ const globals = globalThis;
51
+ globals.OffscreenCanvasRenderingContext2D = MeasureContext;
52
+ globals.OffscreenCanvas = class {
53
+ getContext() {
54
+ return new MeasureContext();
55
+ }
56
+ };
57
+ const FONT = '10px Kitab';
58
+ const DPI = 72;
59
+ const pt = (value) => ({ value, unit: 'pt' });
60
+ const stubPage = { index: 0, pageLabel: '1' };
61
+ const placeholders = { kind: 'header', page: stubPage, allPages: [stubPage], metadata: {}, chapterTitleByPageIndex: [] };
62
+ const round = (n) => Math.round(n * 1000) / 1000;
63
+ const OPENER = '«الحرف العربي.»';
64
+ const DATE = '(٧٣٢–٨٠٨هـ)';
65
+ /** A one-element slot of a right-to-left document laid out to its line. */
66
+ function slotLine(content, extra = {}) {
67
+ const el = {
68
+ kind: 'text', id: 't', content, fontFamily: 'Kitab', fontSize: pt(10), overflow: 'wrap', align: 'start',
69
+ placement: { anchor: { to: 'container', edge: 'top-left' }, size: { width: pt(300) } },
70
+ ...extra,
71
+ };
72
+ const slot = layoutSlotToVdt(resolveDesignSlot({ elements: [el] }), { x: 0, y: 0, width: 400, height: 100 }, 0, placeholders, DPI, { direction: 'rtl' });
73
+ return slot.blocks[0].lines[0];
74
+ }
75
+ /** What a renderer sets for each run of a line: its text in a context of
76
+ * its direction. */
77
+ const painted = (line) => line.runs.map((r) => faceWidth(r.text, r.rtl === true));
78
+ const widths = (line) => line.runs.map((r) => round(r.width));
79
+ beforeEach(() => clearMeasurementCache());
80
+ afterEach(() => setMeasureLanguage(undefined));
81
+ describe('the runs of a design text, measured as they are painted (#770)', () => {
82
+ it('only in a document shaped in its own language', () => {
83
+ expect(measuresRunsAsPainted()).toBe(false);
84
+ setMeasureLanguage('ar');
85
+ expect(measuresRunsAsPainted()).toBe(true);
86
+ });
87
+ it('a right-to-left line is as wide as the one run it is painted as', () => {
88
+ // Left to right the guillemets and the stop are runs apart: 9.4 px and
89
+ // 3 px for the 8.2 px and 2 px of the run painted.
90
+ setMeasureLanguage('ar');
91
+ const line = slotLine(OPENER);
92
+ expect(line.runs.map((r) => [r.text, r.rtl])).toEqual([[OPENER, true]]);
93
+ expect(widths(line)).toEqual(painted(line).map(round));
94
+ expect(round(line.width)).toBe(round(faceWidth(OPENER, true)));
95
+ expect(round(faceWidth(OPENER, false) - faceWidth(OPENER, true))).toBe(2.2);
96
+ // Flush with the right edge of its box, at the width painted.
97
+ expect(line.xOffset + line.width).toBeCloseTo(300, 6);
98
+ });
99
+ it('a document in its host\'s language keeps the width measured left to right', () => {
100
+ const line = slotLine(OPENER);
101
+ expect(round(line.width)).toBe(round(faceWidth(OPENER, false)));
102
+ expect(widths(line)).toEqual([round(faceWidth(OPENER, false))]);
103
+ });
104
+ it('a bracket that is a run of its own: every run its own width, the line their sum', () => {
105
+ setMeasureLanguage('ar');
106
+ const line = slotLine(DATE);
107
+ expect(line.runs.map((r) => [r.text, r.rtl ?? false])).toEqual([
108
+ ['(', true], ['٧٣٢', false], ['–', true], ['٨٠٨', false], ['هـ)', true],
109
+ ]);
110
+ expect(widths(line)).toEqual(painted(line).map(round));
111
+ expect(widths(line)).toEqual([2.5, 15, 5, 15, 12.5]);
112
+ expect(round(line.width)).toBe(50);
113
+ });
114
+ it('in its host\'s language the last run keeps what the line measured whole left over', () => {
115
+ const line = slotLine(DATE);
116
+ // 54 px whole (both brackets 4.5 px beside the Arabic letters); the
117
+ // first four runs alone are 37.5 px, and the last takes 16.5 px for
118
+ // the 12.5 px it is painted in.
119
+ expect(round(line.width)).toBe(54);
120
+ expect(widths(line)).toEqual([2.5, 15, 5, 15, 16.5]);
121
+ });
122
+ it('a justified line still ends on its edge, its runs as wide as painted and their spaces', () => {
123
+ setMeasureLanguage('ar');
124
+ const words = ['الحرف.', 'العربي.', 'الحرف.', 'العربي.', 'الحرف.'];
125
+ const el = {
126
+ kind: 'text', id: 't', content: words.join(' '), fontFamily: 'Kitab', fontSize: pt(10), overflow: 'wrap', align: 'justify',
127
+ placement: { anchor: { to: 'container', edge: 'top-left' }, size: { width: pt(70) } },
128
+ };
129
+ const slot = layoutSlotToVdt(resolveDesignSlot({ elements: [el] }), { x: 0, y: 0, width: 400, height: 100 }, 0, placeholders, DPI, { direction: 'rtl' });
130
+ const lines = slot.blocks[0].lines;
131
+ expect(lines.length).toBeGreaterThan(1);
132
+ const first = lines[0];
133
+ expect(first.runs.reduce((s, r) => s + r.width, 0)).toBeCloseTo(70, 6);
134
+ const spacing = first.wordSpacingPx ?? 0;
135
+ for (const r of first.runs) {
136
+ const spaces = r.text.split(' ').length - 1;
137
+ expect(r.width).toBeCloseTo(faceWidth(r.text, r.rtl === true) + spacing * spaces, 6);
138
+ }
139
+ });
140
+ it('a text built by hand (a callout\'s title): its runs as painted, the line their sum', () => {
141
+ const block = () => ({
142
+ kind: 'text',
143
+ bbox: createBoundingBox(0, 0, 200, 14),
144
+ fontString: FONT,
145
+ color: '#000',
146
+ lines: [{ text: DATE, xOffset: 0, baselineY: 10, width: 54 }],
147
+ clip: false,
148
+ });
149
+ setMeasureLanguage('ar');
150
+ const own = block();
151
+ directDesignTextBlock(own, 'rtl', true);
152
+ expect(widths(own.lines[0])).toEqual([2.5, 15, 5, 15, 12.5]);
153
+ expect(own.lines[0].width).toBe(50);
154
+ setMeasureLanguage(undefined);
155
+ const host = block();
156
+ directDesignTextBlock(host, 'rtl', true);
157
+ expect(widths(host.lines[0])).toEqual([2.5, 15, 5, 15, 16.5]);
158
+ expect(host.lines[0].width).toBe(54);
159
+ });
160
+ it('a text measured for wrapping is the sum of its runs as painted', () => {
161
+ setMeasureLanguage('ar');
162
+ expect(directedTextWidth(OPENER, FONT, 'rtl')).toBe(faceWidth(OPENER, true));
163
+ expect(directedTextWidth(DATE, FONT, 'rtl')).toBe(50);
164
+ // A left-to-right text with no right-to-left character: whole.
165
+ expect(directedTextWidth('Alpha (beta).', FONT, 'ltr')).toBe(faceWidth('Alpha (beta).', false));
166
+ });
167
+ });
168
+ describe('the runs of a chip', () => {
169
+ const chip = (text) => {
170
+ const span = { text: '', bold: false, italic: false, chip: { spans: [{ text, bold: false, italic: false }] } };
171
+ return chipToken(span, FONT, FONT, FONT, FONT, 0).chip;
172
+ };
173
+ it('are as wide as painted, and the chip as wide as its runs, in a document shaped in its own language', () => {
174
+ setMeasureLanguage('ar');
175
+ const own = chip(OPENER);
176
+ expect(own.runs.map((r) => [r.rtl, round(r.width)])).toEqual([[true, round(faceWidth(OPENER, true))]]);
177
+ expect(round(own.boxWidth)).toBe(round(faceWidth(OPENER, true)));
178
+ setMeasureLanguage(undefined);
179
+ const host = chip(OPENER);
180
+ expect(round(host.boxWidth)).toBe(round(faceWidth(OPENER, false)));
181
+ expect(round(host.runs[0].width)).toBe(round(faceWidth(OPENER, false)));
182
+ });
183
+ });
184
+ //# sourceMappingURL=designRunsPainted.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"designRunsPainted.test.js","sourceRoot":"","sources":["../../../src/__tests__/rtl/designRunsPainted.test.ts"],"names":[],"mappings":"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"}
@@ -123,7 +123,11 @@ describe('HTML: design text and chips right to left', () => {
123
123
  // The document root runs right to left (#379); a right-to-left running
124
124
  // head inherits that direction, a Latin run of the chip declares its own.
125
125
  expect(html).toMatch(/^<div class="pt-doc" lang="ar" dir="rtl"/);
126
- expect(html).toMatch(/<span style="position:absolute;left:[\d.]+px;top:[-\d.]+px;line-height:1;white-space:pre;">/);
126
+ // Its line box holds a box per run, each in its direction and at the
127
+ // place the layout gave it, as the canvas paints it run by run (#770);
128
+ // a run of several words is as wide as the layout made it and holds a
129
+ // box per word, from its right.
130
+ expect(html).toMatch(/<span style="position:absolute;left:[\d.]+px;top:[-\d.]+px;line-height:1;"><span dir="rtl" style="position:absolute;left:[\d.]+px;top:0;white-space:pre;width:[\d.]+px;"><span style="position:absolute;right:0\.000px;top:0;">/);
127
131
  expect(html).toContain(`<span dir="ltr" style="position:absolute;`);
128
132
  });
129
133
  it('in a left-to-right document, a right-to-left chip run declares rtl', () => {