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.
- package/dist/__tests__/arabicLocale.test.js +5 -5
- package/dist/__tests__/arabicLocale.test.js.map +1 -1
- package/dist/__tests__/bundle/balloonPlacementPin.test.js +5 -4
- package/dist/__tests__/bundle/balloonPlacementPin.test.js.map +1 -1
- package/dist/__tests__/bundle/cjkRulesPin.test.js +8 -6
- package/dist/__tests__/bundle/cjkRulesPin.test.js.map +1 -1
- package/dist/__tests__/bundle/designOverflowPin.test.js +1 -1
- package/dist/__tests__/bundle/flowColumnsPin.test.js +4 -3
- package/dist/__tests__/bundle/flowColumnsPin.test.js.map +1 -1
- package/dist/__tests__/bundle/gridBalancingPin.test.js +5 -4
- package/dist/__tests__/bundle/gridBalancingPin.test.js.map +1 -1
- package/dist/__tests__/bundle/gridBreakRulesPin.test.js +14 -10
- package/dist/__tests__/bundle/gridBreakRulesPin.test.js.map +1 -1
- package/dist/__tests__/bundle/indexGroupSplitPin.test.js +4 -3
- package/dist/__tests__/bundle/indexGroupSplitPin.test.js.map +1 -1
- package/dist/__tests__/bundle/looseOrderPin.test.js +5 -4
- package/dist/__tests__/bundle/looseOrderPin.test.js.map +1 -1
- package/dist/__tests__/bundle/refLabelBreaksPin.test.js +5 -4
- package/dist/__tests__/bundle/refLabelBreaksPin.test.js.map +1 -1
- package/dist/__tests__/bundle/scriptContextPin.test.js +6 -5
- package/dist/__tests__/bundle/scriptContextPin.test.js.map +1 -1
- package/dist/__tests__/bundle/shapingLanguagePin.test.js +142 -46
- package/dist/__tests__/bundle/shapingLanguagePin.test.js.map +1 -1
- package/dist/__tests__/bundle/taskBoxPin.test.js +1 -1
- package/dist/__tests__/bundle/trailingStepPin.test.js +4 -3
- package/dist/__tests__/bundle/trailingStepPin.test.js.map +1 -1
- package/dist/__tests__/bundle/wideFloatStretchPin.test.js +4 -3
- package/dist/__tests__/bundle/wideFloatStretchPin.test.js.map +1 -1
- package/dist/__tests__/bundle.test.js +1 -1
- package/dist/__tests__/cellText.test.d.ts +2 -0
- package/dist/__tests__/cellText.test.d.ts.map +1 -0
- package/dist/__tests__/cellText.test.js +281 -0
- package/dist/__tests__/cellText.test.js.map +1 -0
- package/dist/__tests__/chineseLocale.test.js +24 -7
- package/dist/__tests__/chineseLocale.test.js.map +1 -1
- package/dist/__tests__/cjk/japaneseHtml.test.js +3 -3
- package/dist/__tests__/cjk/japaneseHtml.test.js.map +1 -1
- package/dist/__tests__/cjk/japaneseRuby.test.js +1 -1
- package/dist/__tests__/cjk/japaneseRuby.test.js.map +1 -1
- package/dist/__tests__/cjk/japaneseSegmentLanguage.test.js +3 -3
- package/dist/__tests__/cjk/japaneseSegmentLanguage.test.js.map +1 -1
- package/dist/__tests__/codeBlocks.test.js +1 -1
- package/dist/__tests__/contextState.test.d.ts +2 -0
- package/dist/__tests__/contextState.test.d.ts.map +1 -0
- package/dist/__tests__/contextState.test.js +478 -0
- package/dist/__tests__/contextState.test.js.map +1 -0
- package/dist/__tests__/contextText.test.d.ts +2 -0
- package/dist/__tests__/contextText.test.d.ts.map +1 -0
- package/dist/__tests__/contextText.test.js +371 -0
- package/dist/__tests__/contextText.test.js.map +1 -0
- package/dist/__tests__/design/designTextRender.test.js +8 -1
- package/dist/__tests__/design/designTextRender.test.js.map +1 -1
- package/dist/__tests__/exports.test.js +6 -0
- package/dist/__tests__/exports.test.js.map +1 -1
- package/dist/__tests__/fontUsage.test.js +40 -0
- package/dist/__tests__/fontUsage.test.js.map +1 -1
- package/dist/__tests__/hardBreaks.test.js +1 -1
- package/dist/__tests__/headingInlineMarks.test.js +1 -1
- package/dist/__tests__/html-backend.test.js +6 -2
- package/dist/__tests__/html-backend.test.js.map +1 -1
- package/dist/__tests__/japaneseNotes.test.js +4 -2
- package/dist/__tests__/japaneseNotes.test.js.map +1 -1
- package/dist/__tests__/lineEndPieces.test.d.ts +2 -0
- package/dist/__tests__/lineEndPieces.test.d.ts.map +1 -0
- package/dist/__tests__/lineEndPieces.test.js +374 -0
- package/dist/__tests__/lineEndPieces.test.js.map +1 -0
- package/dist/__tests__/mathSizeMigration.test.js +2 -2
- package/dist/__tests__/pipeline/calloutInlineResourceGap.test.js +1 -1
- package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.js +1 -1
- package/dist/__tests__/pipeline/colonListRoom.test.js +1 -1
- package/dist/__tests__/pipeline/compoundBreaks.test.js +1 -1
- package/dist/__tests__/pipeline/dashBreaks.test.js +1 -1
- package/dist/__tests__/pipeline/headingSplitOrphans.test.js +1 -1
- package/dist/__tests__/pipeline/inlineFigureSpace.test.js +1 -1
- package/dist/__tests__/pipeline/paragraphContainerTail.test.js +1 -1
- package/dist/__tests__/pipeline/raggedOptimal.test.js +1 -1
- package/dist/__tests__/plainGeminateHead.test.d.ts +2 -0
- package/dist/__tests__/plainGeminateHead.test.d.ts.map +1 -0
- package/dist/__tests__/plainGeminateHead.test.js +92 -0
- package/dist/__tests__/plainGeminateHead.test.js.map +1 -0
- package/dist/__tests__/presets/showcaseShapingLanguage.test.d.ts +2 -0
- package/dist/__tests__/presets/showcaseShapingLanguage.test.d.ts.map +1 -0
- package/dist/__tests__/presets/showcaseShapingLanguage.test.js +52 -0
- package/dist/__tests__/presets/showcaseShapingLanguage.test.js.map +1 -0
- package/dist/__tests__/reshapedTracking.test.d.ts +2 -0
- package/dist/__tests__/reshapedTracking.test.d.ts.map +1 -0
- package/dist/__tests__/reshapedTracking.test.js +358 -0
- package/dist/__tests__/reshapedTracking.test.js.map +1 -0
- package/dist/__tests__/rtl/designRunsPainted.test.d.ts +2 -0
- package/dist/__tests__/rtl/designRunsPainted.test.d.ts.map +1 -0
- package/dist/__tests__/rtl/designRunsPainted.test.js +184 -0
- package/dist/__tests__/rtl/designRunsPainted.test.js.map +1 -0
- package/dist/__tests__/rtl/designTextPaint.test.js +5 -1
- package/dist/__tests__/rtl/designTextPaint.test.js.map +1 -1
- package/dist/__tests__/rtl/htmlRtl.test.js +3 -3
- package/dist/__tests__/rtl/htmlRtl.test.js.map +1 -1
- package/dist/__tests__/rtl/listMarkerDirection.test.js +28 -28
- package/dist/__tests__/rtl/listMarkerDirection.test.js.map +1 -1
- package/dist/__tests__/rtl/tocNumberPainted.test.d.ts +2 -0
- package/dist/__tests__/rtl/tocNumberPainted.test.d.ts.map +1 -0
- package/dist/__tests__/rtl/tocNumberPainted.test.js +113 -0
- package/dist/__tests__/rtl/tocNumberPainted.test.js.map +1 -0
- package/dist/__tests__/scriptContext.test.js +141 -1
- package/dist/__tests__/scriptContext.test.js.map +1 -1
- package/dist/__tests__/shapingLanguage.test.js +60 -43
- package/dist/__tests__/shapingLanguage.test.js.map +1 -1
- package/dist/__tests__/trackedLetters.test.d.ts +2 -0
- package/dist/__tests__/trackedLetters.test.d.ts.map +1 -0
- package/dist/__tests__/trackedLetters.test.js +380 -0
- package/dist/__tests__/trackedLetters.test.js.map +1 -0
- package/dist/__tests__/trackedLigatures.test.js +23 -10
- package/dist/__tests__/trackedLigatures.test.js.map +1 -1
- package/dist/__tests__/verseLines.test.js +1 -1
- package/dist/__tests__/wordCacheOrder.test.d.ts +2 -0
- package/dist/__tests__/wordCacheOrder.test.d.ts.map +1 -0
- package/dist/__tests__/wordCacheOrder.test.js +352 -0
- package/dist/__tests__/wordCacheOrder.test.js.map +1 -0
- package/dist/__tests__/wordPieces.test.d.ts +2 -0
- package/dist/__tests__/wordPieces.test.d.ts.map +1 -0
- package/dist/__tests__/wordPieces.test.js +762 -0
- package/dist/__tests__/wordPieces.test.js.map +1 -0
- package/dist/bidi.d.ts +12 -0
- package/dist/bidi.d.ts.map +1 -1
- package/dist/bidi.js +23 -0
- package/dist/bidi.js.map +1 -1
- package/dist/bundle/configVersion.d.ts +49 -23
- package/dist/bundle/configVersion.d.ts.map +1 -1
- package/dist/bundle/configVersion.js +54 -25
- package/dist/bundle/configVersion.js.map +1 -1
- package/dist/canvas-backend/annotations.d.ts.map +1 -1
- package/dist/canvas-backend/annotations.js +8 -7
- package/dist/canvas-backend/annotations.js.map +1 -1
- package/dist/canvas-backend/blockRender.d.ts.map +1 -1
- package/dist/canvas-backend/blockRender.js +81 -47
- package/dist/canvas-backend/blockRender.js.map +1 -1
- package/dist/canvas-backend/cellText.d.ts +12 -0
- package/dist/canvas-backend/cellText.d.ts.map +1 -0
- package/dist/canvas-backend/cellText.js +114 -0
- package/dist/canvas-backend/cellText.js.map +1 -0
- package/dist/canvas-backend/chip.d.ts.map +1 -1
- package/dist/canvas-backend/chip.js +12 -9
- package/dist/canvas-backend/chip.js.map +1 -1
- package/dist/canvas-backend/comic.d.ts.map +1 -1
- package/dist/canvas-backend/comic.js +9 -8
- package/dist/canvas-backend/comic.js.map +1 -1
- package/dist/canvas-backend/contextState.d.ts +69 -0
- package/dist/canvas-backend/contextState.d.ts.map +1 -0
- package/dist/canvas-backend/contextState.js +96 -0
- package/dist/canvas-backend/contextState.js.map +1 -0
- package/dist/canvas-backend/contextText.d.ts +76 -0
- package/dist/canvas-backend/contextText.d.ts.map +1 -0
- package/dist/canvas-backend/contextText.js +102 -0
- package/dist/canvas-backend/contextText.js.map +1 -0
- package/dist/canvas-backend/decorations.d.ts.map +1 -1
- package/dist/canvas-backend/decorations.js +11 -10
- package/dist/canvas-backend/decorations.js.map +1 -1
- package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
- package/dist/canvas-backend/headerFooter.js +23 -15
- package/dist/canvas-backend/headerFooter.js.map +1 -1
- package/dist/canvas-backend/index.d.ts.map +1 -1
- package/dist/canvas-backend/index.js +41 -17
- package/dist/canvas-backend/index.js.map +1 -1
- package/dist/canvas-backend/mirrorFrame.d.ts.map +1 -1
- package/dist/canvas-backend/mirrorFrame.js +5 -4
- package/dist/canvas-backend/mirrorFrame.js.map +1 -1
- package/dist/canvas-backend/renderResourceBlock.d.ts.map +1 -1
- package/dist/canvas-backend/renderResourceBlock.js +36 -29
- package/dist/canvas-backend/renderResourceBlock.js.map +1 -1
- package/dist/canvas-backend/runDirection.d.ts.map +1 -1
- package/dist/canvas-backend/runDirection.js +9 -5
- package/dist/canvas-backend/runDirection.js.map +1 -1
- package/dist/canvas-backend/scriptText.d.ts.map +1 -1
- package/dist/canvas-backend/scriptText.js +11 -9
- package/dist/canvas-backend/scriptText.js.map +1 -1
- package/dist/canvas-backend/segmentText.d.ts.map +1 -1
- package/dist/canvas-backend/segmentText.js +18 -5
- package/dist/canvas-backend/segmentText.js.map +1 -1
- package/dist/canvas-backend/swatch.d.ts.map +1 -1
- package/dist/canvas-backend/swatch.js +3 -2
- package/dist/canvas-backend/swatch.js.map +1 -1
- package/dist/canvas-backend/trackedText.d.ts +75 -1
- package/dist/canvas-backend/trackedText.d.ts.map +1 -1
- package/dist/canvas-backend/trackedText.js +192 -28
- package/dist/canvas-backend/trackedText.js.map +1 -1
- package/dist/canvas-backend/verticalText.d.ts +12 -2
- package/dist/canvas-backend/verticalText.d.ts.map +1 -1
- package/dist/canvas-backend/verticalText.js +64 -38
- package/dist/canvas-backend/verticalText.js.map +1 -1
- package/dist/canvas-backend/wordPieces.d.ts +31 -0
- package/dist/canvas-backend/wordPieces.d.ts.map +1 -0
- package/dist/canvas-backend/wordPieces.js +132 -0
- package/dist/canvas-backend/wordPieces.js.map +1 -0
- package/dist/canvas-backend/wordRuns.d.ts +13 -1
- package/dist/canvas-backend/wordRuns.d.ts.map +1 -1
- package/dist/canvas-backend/wordRuns.js +38 -23
- package/dist/canvas-backend/wordRuns.js.map +1 -1
- package/dist/comics/lettering/__tests__/fitAsPainted.test.d.ts +2 -0
- package/dist/comics/lettering/__tests__/fitAsPainted.test.d.ts.map +1 -0
- package/dist/comics/lettering/__tests__/fitAsPainted.test.js +97 -0
- package/dist/comics/lettering/__tests__/fitAsPainted.test.js.map +1 -0
- package/dist/comics/lettering/shape-text.d.ts.map +1 -1
- package/dist/comics/lettering/shape-text.js +39 -11
- package/dist/comics/lettering/shape-text.js.map +1 -1
- package/dist/defaults/bodyText.d.ts.map +1 -1
- package/dist/defaults/bodyText.js +6 -5
- package/dist/defaults/bodyText.js.map +1 -1
- package/dist/design/bidiText.d.ts +45 -6
- package/dist/design/bidiText.d.ts.map +1 -1
- package/dist/design/bidiText.js +78 -10
- package/dist/design/bidiText.js.map +1 -1
- package/dist/design/cjkText.d.ts +3 -0
- package/dist/design/cjkText.d.ts.map +1 -1
- package/dist/design/cjkText.js +1 -1
- package/dist/design/cjkText.js.map +1 -1
- package/dist/design/layout.d.ts.map +1 -1
- package/dist/design/layout.js +36 -5
- package/dist/design/layout.js.map +1 -1
- package/dist/design/richText.d.ts +9 -1
- package/dist/design/richText.d.ts.map +1 -1
- package/dist/design/richText.js +8 -2
- package/dist/design/richText.js.map +1 -1
- package/dist/fonts/usage.d.ts +2 -0
- package/dist/fonts/usage.d.ts.map +1 -1
- package/dist/fonts/usage.js +18 -0
- package/dist/fonts/usage.js.map +1 -1
- package/dist/html-backend.d.ts.map +1 -1
- package/dist/html-backend.js +664 -84
- package/dist/html-backend.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/knuthPlass/breakpoints.d.ts.map +1 -1
- package/dist/knuthPlass/breakpoints.js +4 -2
- package/dist/knuthPlass/breakpoints.js.map +1 -1
- package/dist/knuthPlass/pretextAdapter.d.ts +6 -3
- package/dist/knuthPlass/pretextAdapter.d.ts.map +1 -1
- package/dist/knuthPlass/pretextAdapter.js +11 -3
- package/dist/knuthPlass/pretextAdapter.js.map +1 -1
- package/dist/knuthPlass/richAdapter.d.ts +13 -1
- package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
- package/dist/knuthPlass/richAdapter.js +53 -5
- package/dist/knuthPlass/richAdapter.js.map +1 -1
- package/dist/knuthPlass/tracking.d.ts.map +1 -1
- package/dist/knuthPlass/tracking.js +3 -2
- package/dist/knuthPlass/tracking.js.map +1 -1
- package/dist/knuthPlass/types.d.ts +6 -0
- package/dist/knuthPlass/types.d.ts.map +1 -1
- package/dist/locale.d.ts +25 -18
- package/dist/locale.d.ts.map +1 -1
- package/dist/locale.js +27 -20
- package/dist/locale.js.map +1 -1
- package/dist/looseLines.d.ts.map +1 -1
- package/dist/looseLines.js +3 -2
- package/dist/looseLines.js.map +1 -1
- package/dist/measure/canvas.d.ts +21 -0
- package/dist/measure/canvas.d.ts.map +1 -1
- package/dist/measure/canvas.js +165 -85
- package/dist/measure/canvas.js.map +1 -1
- package/dist/measure/cjkCompose.d.ts.map +1 -1
- package/dist/measure/cjkCompose.js +31 -5
- package/dist/measure/cjkCompose.js.map +1 -1
- package/dist/measure/plain.d.ts.map +1 -1
- package/dist/measure/plain.js +31 -6
- package/dist/measure/plain.js.map +1 -1
- package/dist/measure/pretextLanguage.d.ts.map +1 -1
- package/dist/measure/pretextLanguage.js +49 -7
- package/dist/measure/pretextLanguage.js.map +1 -1
- package/dist/measure/rich.d.ts +18 -1
- package/dist/measure/rich.d.ts.map +1 -1
- package/dist/measure/rich.js +200 -29
- package/dist/measure/rich.js.map +1 -1
- package/dist/measure/script.d.ts +17 -1
- package/dist/measure/script.d.ts.map +1 -1
- package/dist/measure/script.js +17 -1
- package/dist/measure/script.js.map +1 -1
- package/dist/measure/trackedLigatures.d.ts +59 -0
- package/dist/measure/trackedLigatures.d.ts.map +1 -0
- package/dist/measure/trackedLigatures.js +144 -0
- package/dist/measure/trackedLigatures.js.map +1 -0
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +4 -3
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/calloutLayout.d.ts.map +1 -1
- package/dist/pipeline/calloutLayout.js +26 -7
- package/dist/pipeline/calloutLayout.js.map +1 -1
- package/dist/pipeline/lists.d.ts +13 -4
- package/dist/pipeline/lists.d.ts.map +1 -1
- package/dist/pipeline/lists.js +49 -12
- package/dist/pipeline/lists.js.map +1 -1
- package/dist/pipeline/toc.d.ts.map +1 -1
- package/dist/pipeline/toc.js +33 -9
- package/dist/pipeline/toc.js.map +1 -1
- package/dist/types.d.ts +35 -22
- package/dist/types.d.ts.map +1 -1
- package/dist/wordPieces.d.ts +120 -0
- package/dist/wordPieces.d.ts.map +1 -0
- package/dist/wordPieces.js +319 -0
- package/dist/wordPieces.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,380 @@
|
|
|
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 { renderToHtml } from '../html-backend';
|
|
7
|
+
import { buildDocument } from '../pipeline';
|
|
8
|
+
import { setMeasureLanguage, measureSpacedWidth, measureTextWidth, clearTextWidthCache } from '../measure/canvas';
|
|
9
|
+
import { trackedLigaturePieces } from '../measure/trackedLigatures';
|
|
10
|
+
// #770: the layout counts the tracking of a tracked word once a letter. A
|
|
11
|
+
// ligature painted alone advanced by one tracking, as one glyph, so a word
|
|
12
|
+
// that held one ended a tracking short of its box for each letter joined
|
|
13
|
+
// (or ran over it, on a tightened line). In a document shaped in its own
|
|
14
|
+
// language the canvas sets the piece after a ligature the tracking of
|
|
15
|
+
// every letter before it further on, and the HTML writes the same pieces.
|
|
16
|
+
// A document that keeps its host's language is painted as it was
|
|
17
|
+
// (`trackedLigatures.test.ts`).
|
|
18
|
+
// A face with ff, fi, fl and ffi ligatures narrower than their letters, as
|
|
19
|
+
// a browser measures it: under a letter-spacing the ligatures are off and
|
|
20
|
+
// the spacing follows every letter. "fir" is kerned 0.2 px closer after the
|
|
21
|
+
// ligature, to tell the kerning across a cut.
|
|
22
|
+
const ADVANCE = (ch) => {
|
|
23
|
+
if (ch === ' ')
|
|
24
|
+
return 0.25;
|
|
25
|
+
if ('ilf.,'.includes(ch))
|
|
26
|
+
return 0.3;
|
|
27
|
+
if (/[A-Z]/.test(ch))
|
|
28
|
+
return 0.66;
|
|
29
|
+
return 0.5;
|
|
30
|
+
};
|
|
31
|
+
const SHALOM = 'שלום';
|
|
32
|
+
const LIGATURES = [['ffi', 0.75], ['ff', 0.5], ['fi', 0.5], ['fl', 0.5]];
|
|
33
|
+
function naturalWidth(text, size, ligatures) {
|
|
34
|
+
let w = 0;
|
|
35
|
+
for (let i = 0; i < text.length;) {
|
|
36
|
+
const lig = ligatures ? LIGATURES.find(([l]) => text.startsWith(l, i)) : undefined;
|
|
37
|
+
if (lig) {
|
|
38
|
+
w += lig[1] * size;
|
|
39
|
+
i += lig[0].length;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
w += ADVANCE(text[i]) * size;
|
|
43
|
+
i++;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return w;
|
|
47
|
+
}
|
|
48
|
+
const sizeOf = (font) => parseFloat(/(\d*\.?\d+)px/.exec(font)?.[1] ?? '10');
|
|
49
|
+
class BrowserCtx {
|
|
50
|
+
font = '10px Body';
|
|
51
|
+
letterSpacing = '0px';
|
|
52
|
+
lang = 'inherit';
|
|
53
|
+
measureText(s) {
|
|
54
|
+
const spacing = parseFloat(this.letterSpacing) || 0;
|
|
55
|
+
return { width: naturalWidth(s, sizeOf(this.font), spacing === 0) + spacing * s.length };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function paintingCtx() {
|
|
59
|
+
const seen = [];
|
|
60
|
+
const ctx = Object.assign(new BrowserCtx(), {
|
|
61
|
+
fillStyle: '', textBaseline: 'alphabetic',
|
|
62
|
+
fillText(text, x, y) {
|
|
63
|
+
seen.push({ text, x, y, spacing: parseFloat(this.letterSpacing) || 0, width: this.measureText(text).width });
|
|
64
|
+
},
|
|
65
|
+
save() { }, restore() { }, beginPath() { }, rect() { }, clip() { }, fillRect() { }, moveTo() { }, lineTo() { }, stroke() { },
|
|
66
|
+
});
|
|
67
|
+
return { ctx: ctx, seen };
|
|
68
|
+
}
|
|
69
|
+
globalThis.OffscreenCanvas = class {
|
|
70
|
+
getContext() {
|
|
71
|
+
return new BrowserCtx();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const pt = (value) => ({ value, unit: 'pt' });
|
|
75
|
+
// 72 dpi: 1 pt = 1 px.
|
|
76
|
+
const OWN = {
|
|
77
|
+
page: { width: pt(160), height: pt(900), dpi: 72, margins: { top: pt(10), bottom: pt(10), left: pt(10), right: pt(10) } },
|
|
78
|
+
layout: { layoutType: 'single' },
|
|
79
|
+
header: { elements: [] },
|
|
80
|
+
footer: { elements: [] },
|
|
81
|
+
bodyText: { fontSize: pt(10), lineHeight: pt(14), firstLineIndent: pt(0), hyphenation: { enabled: false }, shapingLanguage: 'document' },
|
|
82
|
+
};
|
|
83
|
+
const HOST = { ...OWN, bodyText: { ...OWN.bodyText, shapingLanguage: 'host' } };
|
|
84
|
+
// Three lines with 10‰ of negative tracking (`tightenRunts`).
|
|
85
|
+
const JUSTIFIED = 'fire stood the offices first is office within lets stood lets left stood is offices is office first a fire.';
|
|
86
|
+
const paragraph = (doc) => doc.blocks.find((b) => b.type === 'paragraph');
|
|
87
|
+
const LIGA = "font-feature-settings:'liga' 1,'clig' 1;";
|
|
88
|
+
/** Where each word of `line` is painted to end, the tracking its last
|
|
89
|
+
* piece is owed counted (`owed` trackings a ligature), against where its
|
|
90
|
+
* segment ends. */
|
|
91
|
+
function wordEnds(block, line, seen, tracking, owed) {
|
|
92
|
+
const segments = line.segments;
|
|
93
|
+
const justified = block.textAlign === 'justify' && !line.isLastLine;
|
|
94
|
+
const wordWidth = segments.reduce((w, s) => (s.kind === 'space' ? w : w + s.width), 0);
|
|
95
|
+
const spaces = segments.filter((s) => s.kind === 'space').length;
|
|
96
|
+
const out = [];
|
|
97
|
+
let x = line.bbox.x;
|
|
98
|
+
for (const seg of segments) {
|
|
99
|
+
if (seg.kind === 'space') {
|
|
100
|
+
x += justified ? (block.bbox.width - wordWidth) / spaces : seg.width;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const pieces = seen.filter((p) => p.y === line.baseline && (Math.abs(p.x - x) < 1e-6 || (p.x > x && p.x < x + seg.width - 1e-6)));
|
|
104
|
+
expect(pieces.map((p) => p.text).join('')).toBe(seg.text);
|
|
105
|
+
const last = pieces[pieces.length - 1];
|
|
106
|
+
out.push({ text: seg.text, end: last.x + last.width + (last.spacing === 0 ? owed(last.text) * tracking : 0), place: x + seg.width });
|
|
107
|
+
x += seg.width;
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
describe('the ligatures of a tracked text, as the measurer sees them (#770)', () => {
|
|
112
|
+
it('measures under a letter-spacing and leaves the context at none', () => {
|
|
113
|
+
clearTextWidthCache();
|
|
114
|
+
setMeasureLanguage('en');
|
|
115
|
+
try {
|
|
116
|
+
expect(measureSpacedWidth('first', '10px Body', 1)).toBeCloseTo(naturalWidth('first', 10, false) + 5, 9);
|
|
117
|
+
// The measure after it is taken at no spacing.
|
|
118
|
+
expect(measureTextWidth('first', '10px Body')).toBeCloseTo(naturalWidth('first', 10, true), 9);
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
setMeasureLanguage(undefined);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
it('a ligature is a piece of its own with its letters, the rest between them', () => {
|
|
125
|
+
setMeasureLanguage('en');
|
|
126
|
+
try {
|
|
127
|
+
expect(trackedLigaturePieces('first', '20px Body')).toEqual([
|
|
128
|
+
{ text: 'fi', offset: 0, width: 10, letters: 2, ligature: true },
|
|
129
|
+
{ text: 'rst', offset: 10, width: 30, letters: 3, ligature: false },
|
|
130
|
+
]);
|
|
131
|
+
expect(trackedLigaturePieces('offices', '20px Body').map((p) => [p.text, p.offset, p.letters, p.ligature])).toEqual([
|
|
132
|
+
['o', 0, 1, false], ['ffi', 10, 3, true], ['ces', 25, 3, false],
|
|
133
|
+
]);
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
setMeasureLanguage(undefined);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
it('a word the letter-spacing changes nothing of, and a right-to-left one, are set whole', () => {
|
|
140
|
+
expect(trackedLigaturePieces('stood', '20px Body')).toBeNull();
|
|
141
|
+
expect(trackedLigaturePieces(SHALOM, '20px Body')).toBeNull();
|
|
142
|
+
expect(trackedLigaturePieces('a', '20px Body')).toBeNull();
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
describe('a tracked word on canvas, every letter tracked (#770)', () => {
|
|
146
|
+
it('sets the piece after a ligature the tracking of each letter before it further on', () => {
|
|
147
|
+
const at = (on) => {
|
|
148
|
+
const { ctx, seen } = paintingCtx();
|
|
149
|
+
ctx.font = '20px Body';
|
|
150
|
+
setLetterSpacing(ctx, 0.5);
|
|
151
|
+
setLetterTracking(on);
|
|
152
|
+
fillTrackedWord(ctx, 'offices', 100, 50, 0.5, (text, x, y) => ctx.fillText(text, x, y));
|
|
153
|
+
setLetterTracking(false);
|
|
154
|
+
expect(seen.map((p) => p.text)).toEqual(['o', 'ffi', 'ces']);
|
|
155
|
+
return seen.map((p) => p.x);
|
|
156
|
+
};
|
|
157
|
+
// o at 100; ffi after one letter; ces after four letters (o, f, f, i),
|
|
158
|
+
// or after two glyphs where a ligature is one.
|
|
159
|
+
expect(at(true)).toEqual([100, 100 + 10 + 0.5, 100 + 25 + 4 * 0.5]);
|
|
160
|
+
expect(at(false)).toEqual([100, 100 + 10 + 0.5, 100 + 25 + 2 * 0.5]);
|
|
161
|
+
});
|
|
162
|
+
it('a paragraph shaped in its own language: every word ends where its box does', () => {
|
|
163
|
+
const doc = buildDocument({ markdown: JUSTIFIED }, OWN);
|
|
164
|
+
const block = paragraph(doc);
|
|
165
|
+
const t = block.letterSpacing;
|
|
166
|
+
expect(t).toBeCloseTo(-0.1, 5);
|
|
167
|
+
const { ctx, seen } = paintingCtx();
|
|
168
|
+
setSegmentLanguages(true);
|
|
169
|
+
renderBlock(ctx, block, block.bbox.width, block.bbox.x);
|
|
170
|
+
setSegmentLanguages(false);
|
|
171
|
+
expect(seen.filter((p) => p.text === 'fi' || p.text === 'ffi')).toHaveLength(8);
|
|
172
|
+
let withLigature = 0;
|
|
173
|
+
for (const line of block.lines) {
|
|
174
|
+
for (const word of wordEnds(block, line, seen, t, (ligature) => ligature.length)) {
|
|
175
|
+
expect(word.end).toBeCloseTo(word.place, 6);
|
|
176
|
+
if (/fi/.test(word.text))
|
|
177
|
+
withLigature++;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
expect(withLigature).toBe(8);
|
|
181
|
+
});
|
|
182
|
+
it('a paragraph that keeps its host\'s language: a ligature takes one tracking, as it did', () => {
|
|
183
|
+
const doc = buildDocument({ markdown: JUSTIFIED }, HOST);
|
|
184
|
+
const block = paragraph(doc);
|
|
185
|
+
const t = block.letterSpacing;
|
|
186
|
+
const { ctx, seen } = paintingCtx();
|
|
187
|
+
setSegmentLanguages(false);
|
|
188
|
+
renderBlock(ctx, block, block.bbox.width, block.bbox.x);
|
|
189
|
+
const short = [];
|
|
190
|
+
for (const line of block.lines) {
|
|
191
|
+
for (const word of wordEnds(block, line, seen, t, () => 1))
|
|
192
|
+
if (/fi/.test(word.text))
|
|
193
|
+
short.push(word.end - word.place);
|
|
194
|
+
}
|
|
195
|
+
// On a line tightened by 0.1 px a letter the four words with `fi` run
|
|
196
|
+
// 0.1 px over their boxes, the four with `ffi` 0.2 px.
|
|
197
|
+
expect(short.map((d) => Math.round(d * 1e6) / 1e6).sort()).toEqual([0.1, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2]);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
describe('a tracked line in HTML, every letter tracked (#770)', () => {
|
|
201
|
+
it('shaped in its own language: no feature asked for, each ligature in a box with the tracking of its letters', () => {
|
|
202
|
+
const doc = buildDocument({ markdown: JUSTIFIED }, OWN);
|
|
203
|
+
const t = paragraph(doc).letterSpacing;
|
|
204
|
+
const html = renderToHtml(doc);
|
|
205
|
+
expect(html).toContain(`letter-spacing:${t}px;`);
|
|
206
|
+
expect(html).not.toContain("'liga'");
|
|
207
|
+
const box = (letters, text) => `<span style="letter-spacing:0;margin-inline-end:${(letters * t).toFixed(3)}px;">${text}</span>`;
|
|
208
|
+
expect(html).toContain(`>${box(2, 'fi')}re</span>`);
|
|
209
|
+
expect(html).toContain(`>o${box(3, 'ffi')}ces</span>`);
|
|
210
|
+
expect(html).toContain(`>${box(2, 'fi')}rst</span>`);
|
|
211
|
+
expect(html.split('letter-spacing:0;margin-inline-end:').length - 1).toBe(8);
|
|
212
|
+
// A word with no ligature is its text.
|
|
213
|
+
expect(html).toContain('>stood</span>');
|
|
214
|
+
});
|
|
215
|
+
it('a run in another face is cut in its own font', () => {
|
|
216
|
+
const doc = buildDocument({ markdown: JUSTIFIED.replace('first is', '**first** is') }, OWN);
|
|
217
|
+
expect(paragraph(doc).letterSpacing).toBeLessThan(0);
|
|
218
|
+
const html = renderToHtml(doc);
|
|
219
|
+
expect(html).toMatch(/<span style="font:[^;]+;line-height:0;[^"]*"><span style="letter-spacing:0;margin-inline-end:[-\d.]+px;">fi<\/span>rst<\/span>/);
|
|
220
|
+
expect(html).not.toContain("'liga'");
|
|
221
|
+
});
|
|
222
|
+
it('keeping its host\'s language: the ligatures asked for as features, the words whole', () => {
|
|
223
|
+
const doc = buildDocument({ markdown: JUSTIFIED }, HOST);
|
|
224
|
+
const t = paragraph(doc).letterSpacing;
|
|
225
|
+
const html = renderToHtml(doc);
|
|
226
|
+
expect(html).toContain(`letter-spacing:${t}px;${LIGA}`);
|
|
227
|
+
expect(html).not.toContain('margin-inline-end');
|
|
228
|
+
expect(html).toContain('>first</span>');
|
|
229
|
+
});
|
|
230
|
+
it('an untracked line is written as it was, in either', () => {
|
|
231
|
+
for (const config of [OWN, HOST]) {
|
|
232
|
+
const html = renderToHtml(buildDocument({ markdown: 'The first of its offices.' }, config));
|
|
233
|
+
expect(html).not.toContain("'liga'");
|
|
234
|
+
expect(html).not.toContain('margin-inline-end');
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
it('the two documents are laid out alike: the tracking changes no width', () => {
|
|
238
|
+
const own = paragraph(buildDocument({ markdown: JUSTIFIED }, OWN));
|
|
239
|
+
const host = paragraph(buildDocument({ markdown: JUSTIFIED }, HOST));
|
|
240
|
+
expect(own.lines.map((l) => l.segments.map((s) => [s.text, s.width]))).toEqual(host.lines.map((l) => l.segments.map((s) => [s.text, s.width])));
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
describe('a tracked design text in HTML, every letter tracked (#770)', () => {
|
|
244
|
+
const head = (config, content) => ({
|
|
245
|
+
...config,
|
|
246
|
+
page: { ...config.page, width: pt(300), margins: { top: pt(40), bottom: pt(10), left: pt(10), right: pt(10) } },
|
|
247
|
+
header: { elements: [{ kind: 'text', id: 'rh', content, fontSize: pt(10), letterSpacing: pt(0.2), overflow: 'wrap', placement: { anchor: { to: 'container', edge: 'top-left' }, size: { width: 'auto' } } }] },
|
|
248
|
+
});
|
|
249
|
+
it('a running head: a box per word, its ligatures boxes of their own', () => {
|
|
250
|
+
const html = renderToHtml(buildDocument({ markdown: 'Text.' }, head(OWN, 'first office')));
|
|
251
|
+
expect(html).not.toContain("'liga'");
|
|
252
|
+
expect(html).toMatch(/top:0;"><span style="letter-spacing:0;margin-inline-end:0\.400px;">fi<\/span>rst<\/span>/);
|
|
253
|
+
expect(html).toMatch(/top:0;">o<span style="letter-spacing:0;margin-inline-end:0\.600px;">ffi<\/span>ce<\/span>/);
|
|
254
|
+
const hosted = renderToHtml(buildDocument({ markdown: 'Text.' }, head(HOST, 'first office')));
|
|
255
|
+
expect(hosted).toContain(`letter-spacing:0.2px;${LIGA}`);
|
|
256
|
+
expect(hosted).not.toContain('margin-inline-end');
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
describe('a callout title set by the CJK composer (#770)', () => {
|
|
260
|
+
const callout = (config) => ({
|
|
261
|
+
...config,
|
|
262
|
+
locale: 'ja',
|
|
263
|
+
page: { ...config.page, width: pt(400), height: pt(300) },
|
|
264
|
+
calloutStyles: [{ id: 'd' }],
|
|
265
|
+
});
|
|
266
|
+
const MD = 'Text.\n\n:::callout{type="d" title="Sandboxでやってみよう"}\nOne line.\n:::\n';
|
|
267
|
+
const titleOf = (doc) => doc.blocks.find((b) => b.type === 'callout').designOverlay.blocks.find((b) => b.kind === 'text');
|
|
268
|
+
it('shaped in its own language: the line carries the composer\'s runs, the Han–Latin space in a box', () => {
|
|
269
|
+
const line = titleOf(buildDocument({ markdown: MD }, callout(OWN))).lines[0];
|
|
270
|
+
expect(line.text).toBe('Sandboxでやってみよう');
|
|
271
|
+
expect(line.runs).toBeDefined();
|
|
272
|
+
expect(line.runs.map((r) => r.text).join('')).toBe(line.text);
|
|
273
|
+
// The runs are as wide as the line; set at its glyphs' advances the
|
|
274
|
+
// text is narrower by the space between `Sandbox` and `で`.
|
|
275
|
+
const sum = line.runs.reduce((w, r) => w + r.width, 0);
|
|
276
|
+
expect(sum).toBeCloseTo(line.width, 6);
|
|
277
|
+
const glyphs = line.runs.reduce((w, r) => w + naturalWidth(r.text, sizeOf(r.fontString), true), 0);
|
|
278
|
+
expect(line.width - glyphs).toBeGreaterThan(1);
|
|
279
|
+
expect(line.runs.some((r) => r.inkOffset !== undefined)).toBe(true);
|
|
280
|
+
});
|
|
281
|
+
it('keeping its host\'s language: the line as it was, with no runs', () => {
|
|
282
|
+
const own = titleOf(buildDocument({ markdown: MD }, callout(OWN))).lines[0];
|
|
283
|
+
const host = titleOf(buildDocument({ markdown: MD }, callout(HOST))).lines[0];
|
|
284
|
+
expect(host.runs).toBeUndefined();
|
|
285
|
+
expect(host.width).toBeCloseTo(own.width, 6);
|
|
286
|
+
});
|
|
287
|
+
it('a title with nothing spaced by the composer carries no runs', () => {
|
|
288
|
+
const line = titleOf(buildDocument({ markdown: MD.replace('Sandboxでやってみよう', 'やってみよう') }, callout(OWN))).lines[0];
|
|
289
|
+
expect(line.runs).toBeUndefined();
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
describe('other texts the HTML sets as they were measured (#770)', () => {
|
|
293
|
+
const TOC = '# Contents {toc="false"}\n\n:::toc\n\n# The lantern\n\nText.\n\n# The second lantern\n\nText.';
|
|
294
|
+
it('a leader of dots takes its own direction in a document shaped in its own language', () => {
|
|
295
|
+
// The opening tag of each leader box. Its direction is a `dir`: an
|
|
296
|
+
// EPUB's pages may carry no `direction` declaration (EPUBCheck CSS-001).
|
|
297
|
+
const leader = (config) => [...renderToHtml(buildDocument({ markdown: TOC }, { ...config, page: { ...config.page, width: pt(300) } })).matchAll(/<span aria-hidden="true"[^>]*>(?:<span[^>]*>)?[. ]{4,}/g)].map((m) => m[0]);
|
|
298
|
+
const own = leader(OWN);
|
|
299
|
+
expect(own.length).toBeGreaterThan(0);
|
|
300
|
+
for (const tag of own)
|
|
301
|
+
expect(tag).toMatch(/^<span aria-hidden="true" style="position:absolute;[^"]*" dir="ltr">/);
|
|
302
|
+
const host = leader(HOST);
|
|
303
|
+
expect(host).toHaveLength(own.length);
|
|
304
|
+
for (const tag of [...own, ...host])
|
|
305
|
+
expect(tag).not.toContain('direction');
|
|
306
|
+
for (const tag of host)
|
|
307
|
+
expect(tag).not.toContain(' dir=');
|
|
308
|
+
});
|
|
309
|
+
it('a drop cap of a tracked line is set with no tracking, as it was measured', () => {
|
|
310
|
+
const config = { ...OWN, page: { ...OWN.page, width: pt(300) }, headings: { levels: [{ level: 1, dropCap: { lines: 2 } }] } };
|
|
311
|
+
const doc = buildDocument({ markdown: '# One\n\nLong before there were title pages there were readers of the scrolls who kept their place with a finger and a lamp.' }, config);
|
|
312
|
+
const block = paragraph(doc);
|
|
313
|
+
expect(block.dropCap).toBeDefined();
|
|
314
|
+
const cap = (html) => /class="pt-dropcap" style="([^"]*)"/.exec(html)[1];
|
|
315
|
+
expect(cap(renderToHtml(doc))).not.toContain('letter-spacing');
|
|
316
|
+
block.letterSpacing = 0.25;
|
|
317
|
+
expect(cap(renderToHtml(doc))).toContain('white-space:pre;letter-spacing:normal;');
|
|
318
|
+
});
|
|
319
|
+
it('a design line of one run in the block\'s font is a box per word, as a line with no runs', () => {
|
|
320
|
+
const config = {
|
|
321
|
+
...OWN,
|
|
322
|
+
page: { ...OWN.page, width: pt(300), margins: { top: pt(40), bottom: pt(10), left: pt(10), right: pt(10) } },
|
|
323
|
+
header: { elements: [{ kind: 'text', id: 'rh', content: 'Set in stone and so on', fontSize: pt(10), overflow: 'wrap', placement: { anchor: { to: 'container', edge: 'top-left' }, size: { width: 'auto' } } }] },
|
|
324
|
+
};
|
|
325
|
+
const doc = buildDocument({ markdown: 'Text.' }, config);
|
|
326
|
+
const WORDS = /<span style="position:absolute;left:0\.000px;top:0;">Set<\/span><span style="position:absolute;left:[\d.]+px;top:0;"> <\/span><span style="position:absolute;left:[\d.]+px;top:0;">in<\/span>/;
|
|
327
|
+
const plain = renderToHtml(doc);
|
|
328
|
+
expect(plain).toMatch(WORDS);
|
|
329
|
+
// The same line as the composer of a Chinese or Japanese document
|
|
330
|
+
// hands it over: one run, its whole text.
|
|
331
|
+
const block = doc.pages[0].header.blocks.find((b) => b.kind === 'text');
|
|
332
|
+
const line = block.lines[0];
|
|
333
|
+
line.runs = [{ text: line.text, fontString: block.fontString, width: line.width }];
|
|
334
|
+
expect(renderToHtml(doc)).toBe(plain);
|
|
335
|
+
// A run that is not the line in the block's font keeps its own box.
|
|
336
|
+
line.runs = [{ text: line.text, fontString: block.fontString, width: line.width, baselineShift: 1 }];
|
|
337
|
+
expect(renderToHtml(doc)).not.toMatch(WORDS);
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
describe('a right-to-left run of a design line (#770)', () => {
|
|
341
|
+
it('is a box per word from the run\'s right, in a run box as wide as the run', () => {
|
|
342
|
+
const config = {
|
|
343
|
+
...OWN, locale: 'ar',
|
|
344
|
+
page: { ...OWN.page, width: pt(300), margins: { top: pt(40), bottom: pt(10), left: pt(10), right: pt(10) } },
|
|
345
|
+
header: { elements: [{ kind: 'text', id: 'rh', content: '\u0628\u0627\u0628 \u0643\u062A\u0627\u0628 \u0628\u0627\u0628', fontSize: pt(10), overflow: 'wrap', placement: { anchor: { to: 'container', edge: 'top-left' }, size: { width: 'auto' } } }] },
|
|
346
|
+
};
|
|
347
|
+
const doc = buildDocument({ markdown: '\u0628\u0627\u0628.' }, config);
|
|
348
|
+
const block = doc.pages[0].header.blocks.find((b) => b.kind === 'text');
|
|
349
|
+
const run = block.lines[0].runs[0];
|
|
350
|
+
expect(run.rtl).toBe(true);
|
|
351
|
+
const html = renderToHtml(doc);
|
|
352
|
+
// باب 15 px, a space 2.5 px, كتاب 20 px: each word from the right.
|
|
353
|
+
expect(html).toContain(`white-space:pre;width:${run.width.toFixed(3)}px;"><span style="position:absolute;right:0.000px;top:0;">\u0628\u0627\u0628</span><span style="position:absolute;right:15.000px;top:0;"> </span><span style="position:absolute;right:17.500px;top:0;">\u0643\u062A\u0627\u0628</span>`);
|
|
354
|
+
expect(html).not.toContain('display:inline-block;"> </span>\u0643');
|
|
355
|
+
// A run the layout holds at another width than its words set so is
|
|
356
|
+
// written as it was.
|
|
357
|
+
run.width += 1;
|
|
358
|
+
block.lines[0].width += 1;
|
|
359
|
+
expect(renderToHtml(doc)).toContain('display:inline-block;"> </span>\u0643');
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
describe('a sideways word down a vertical line (#770)', () => {
|
|
363
|
+
it('its pieces are one box where the word was measured whole', () => {
|
|
364
|
+
const config = { ...OWN, layout: { writingMode: 'vertical-rl', layoutType: 'single' }, bodyText: { ...OWN.bodyText, textAlign: 'left' } };
|
|
365
|
+
// Soft hyphens: the word in the pieces of its syllables.
|
|
366
|
+
const MD = 'of\u00ADfice *x* of\u00ADficer';
|
|
367
|
+
const doc = buildDocument({ markdown: MD }, config);
|
|
368
|
+
const line = paragraph(doc).lines[0];
|
|
369
|
+
// The layout holds the word in the pieces of its syllables, the
|
|
370
|
+
// ligature across a cut: the second piece is what the word grew by.
|
|
371
|
+
expect(line.segments.map((s) => s.text).join('|')).toContain('of|fice');
|
|
372
|
+
const html = renderToHtml(doc);
|
|
373
|
+
expect(html).toMatch(/white-space:pre;[^"]*">office<\/span>/);
|
|
374
|
+
expect(html).not.toMatch(/">of<\/span>/);
|
|
375
|
+
// Keeping its host's language where no page is known: as it was.
|
|
376
|
+
const hosted = renderToHtml(buildDocument({ markdown: MD }, { ...config, bodyText: { ...config.bodyText, shapingLanguage: 'host' } }));
|
|
377
|
+
expect(hosted).toMatch(/">of<\/span>/);
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
//# sourceMappingURL=trackedLetters.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trackedLetters.test.js","sourceRoot":"","sources":["../../src/__tests__/trackedLetters.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { renderPageToCanvas } from '../canvas-backend';
|
|
|
3
3
|
import { renderBlock } from '../canvas-backend/blockRender';
|
|
4
4
|
import { beginMirroredFlow } from '../canvas-backend/mirrorFrame';
|
|
5
5
|
import { fillTrackedWord, trackedPieces, shapedOtherwise } from '../canvas-backend/trackedText';
|
|
6
|
+
import { setLetterSpacing } from '../canvas-backend/contextState';
|
|
6
7
|
import { renderHeaderFooterSlot, renderTextBlock } from '../canvas-backend/headerFooter';
|
|
7
8
|
import { renderComicBalloon } from '../canvas-backend/comic';
|
|
8
9
|
import { fillFlowText, setVerticalPaint } from '../canvas-backend/verticalText';
|
|
@@ -94,8 +95,8 @@ describe('the pieces of a tracked word (#663)', () => {
|
|
|
94
95
|
const { ctx } = paintingCtx();
|
|
95
96
|
expect(shapedOtherwise(ctx, 'first')).toBe(true);
|
|
96
97
|
expect(trackedPieces(ctx, 'first')).toEqual([
|
|
97
|
-
{ text: 'fi', offset: 0, glyphsBefore: 0, ligature: true },
|
|
98
|
-
{ text: 'rst', offset: 5, glyphsBefore: 1, ligature: false },
|
|
98
|
+
{ text: 'fi', offset: 0, glyphsBefore: 0, lettersBefore: 0, ligature: true },
|
|
99
|
+
{ text: 'rst', offset: 5, glyphsBefore: 1, lettersBefore: 2, ligature: false },
|
|
99
100
|
]);
|
|
100
101
|
// o | ffi | ces: the three letters of one ligature stay together.
|
|
101
102
|
expect(trackedPieces(ctx, 'offices').map((p) => [p.text, p.offset, p.glyphsBefore, p.ligature])).toEqual([
|
|
@@ -106,7 +107,7 @@ describe('the pieces of a tracked word (#663)', () => {
|
|
|
106
107
|
});
|
|
107
108
|
it('leaves the letter-spacing as it found it and measures a word once', () => {
|
|
108
109
|
const { ctx } = paintingCtx();
|
|
109
|
-
ctx
|
|
110
|
+
setLetterSpacing(ctx, -0.2);
|
|
110
111
|
trackedPieces(ctx, 'reflect');
|
|
111
112
|
expect(ctx.letterSpacing).toBe('-0.2px');
|
|
112
113
|
const before = ctx.measured;
|
|
@@ -122,13 +123,17 @@ describe('the pieces of a tracked word (#663)', () => {
|
|
|
122
123
|
});
|
|
123
124
|
});
|
|
124
125
|
const pt = (value) => ({ value, unit: 'pt' });
|
|
125
|
-
// 72 dpi: 1 pt = 1 px.
|
|
126
|
+
// 72 dpi: 1 pt = 1 px. The documents of this file keep their host's
|
|
127
|
+
// language: a ligature takes one tracking, as one glyph, and the HTML asks
|
|
128
|
+
// for the ligatures as features, as up to postext 1.29. A document shaped
|
|
129
|
+
// in its own language gives a ligature the tracking of each letter
|
|
130
|
+
// (`trackedLetters.test.ts`, #770).
|
|
126
131
|
const CONFIG = {
|
|
127
132
|
page: { width: pt(160), height: pt(900), dpi: 72, margins: { top: pt(10), bottom: pt(10), left: pt(10), right: pt(10) } },
|
|
128
133
|
layout: { layoutType: 'single' },
|
|
129
134
|
header: { elements: [] },
|
|
130
135
|
footer: { elements: [] },
|
|
131
|
-
bodyText: { fontSize: pt(10), lineHeight: pt(14), firstLineIndent: pt(0), hyphenation: { enabled: false } },
|
|
136
|
+
bodyText: { fontSize: pt(10), lineHeight: pt(14), firstLineIndent: pt(0), hyphenation: { enabled: false }, shapingLanguage: 'host' },
|
|
132
137
|
};
|
|
133
138
|
// Four lines set naturally, the last a runt; three with 10‰ of negative
|
|
134
139
|
// tracking (`tightenRunts`). Justified, the second line holds no ligature;
|
|
@@ -378,7 +383,7 @@ describe('a word in pieces inside a mirrored frame (#685)', () => {
|
|
|
378
383
|
it('is turned once, about its box: the pieces in reading order from the box\'s left', () => {
|
|
379
384
|
const { ctx, runs } = sheetCanvas();
|
|
380
385
|
const t = -0.1;
|
|
381
|
-
ctx
|
|
386
|
+
setLetterSpacing(ctx, t);
|
|
382
387
|
const end = beginMirroredFlow(ctx, 200);
|
|
383
388
|
const paint = (text, x, y) => ctx.fillText(text, x, y);
|
|
384
389
|
fillTrackedWord(ctx, 'first', 40, 50, t, paint);
|
|
@@ -405,7 +410,7 @@ describe('a word in pieces inside a mirrored frame (#685)', () => {
|
|
|
405
410
|
});
|
|
406
411
|
it('outside a mirrored frame the pieces start at the word\'s left', () => {
|
|
407
412
|
const { ctx, runs } = sheetCanvas();
|
|
408
|
-
ctx
|
|
413
|
+
setLetterSpacing(ctx, -0.1);
|
|
409
414
|
fillTrackedWord(ctx, 'first', 40, 50, -0.1, (text, x, y) => ctx.fillText(text, x, y));
|
|
410
415
|
expect(runs.map((r) => [r.text, +leftOf(r).toFixed(6), r.spacing])).toEqual([['fi', 40, 0], ['rst', 44.9, -0.1]]);
|
|
411
416
|
});
|
|
@@ -469,7 +474,7 @@ describe('right-to-left words on a tracked line (#685)', () => {
|
|
|
469
474
|
// …and it is still painted whole, with one `fillText`.
|
|
470
475
|
expect(trackedPieces(ctx, word)).toBeNull();
|
|
471
476
|
const seen = [];
|
|
472
|
-
ctx
|
|
477
|
+
setLetterSpacing(ctx, 0.5);
|
|
473
478
|
fillTrackedWord(ctx, word, 10, 20, 0.5, (text, x, y) => seen.push([text, x, y]));
|
|
474
479
|
expect(seen).toEqual([[word, 10, 20]]);
|
|
475
480
|
expect(ctx.letterSpacing).toBe('0.5px');
|
|
@@ -599,7 +604,7 @@ describe('a tracked vertical line (#685, #703)', () => {
|
|
|
599
604
|
// where a browser that keeps the ligature puts it.
|
|
600
605
|
const cellAt = (keeps) => {
|
|
601
606
|
const { ctx, runs } = sheetCanvas(keeps);
|
|
602
|
-
ctx
|
|
607
|
+
setLetterSpacing(ctx, 0.5);
|
|
603
608
|
const outer = setVerticalPaint({ region: 'mainland' });
|
|
604
609
|
fillFlowText(ctx, 'first\u697C', 30, 50);
|
|
605
610
|
setVerticalPaint(outer);
|
|
@@ -887,7 +892,15 @@ describe('a tracked design text in HTML (#703)', () => {
|
|
|
887
892
|
it('asks for its ligatures after the letter-spacing', () => {
|
|
888
893
|
const html = renderToHtml(buildDocument({ markdown: 'Text.' }, withHead('first office')));
|
|
889
894
|
expect(html).toContain(`letter-spacing:${T}px;${LIGA}`);
|
|
890
|
-
|
|
895
|
+
// One box, its word space in a box of its own, so nothing kerns across
|
|
896
|
+
// it (#770).
|
|
897
|
+
expect(html).toContain('>first<span style="display:inline-block;"> </span>office</span>');
|
|
898
|
+
// Shaped in its own language: a box per word, and no feature asked
|
|
899
|
+
// for (the ligatures are boxes of their own, `trackedLetters.test.ts`).
|
|
900
|
+
const own = renderToHtml(buildDocument({ markdown: 'Text.' }, withHead('first office', {}, { ...CONFIG, bodyText: { ...CONFIG.bodyText, shapingLanguage: 'document' } })));
|
|
901
|
+
expect(own).toContain(`letter-spacing:${T}px;`);
|
|
902
|
+
expect(own).not.toContain(LIGA);
|
|
903
|
+
expect(own).toMatch(/<span style="position:absolute;left:0\.000px;top:0;"><span [^>]+>fi<\/span>rst<\/span><span style="position:absolute;left:[\d.]+px;top:0;"> <\/span><span style="position:absolute;left:[\d.]+px;top:0;">o<span [^>]+>ffi<\/span>ce<\/span>/);
|
|
891
904
|
});
|
|
892
905
|
it('a run in another face asks again after its own font', () => {
|
|
893
906
|
const html = renderToHtml(buildDocument({ markdown: 'Text.' }, withHead('the **first** office', { inlineMarks: true })));
|