postext-pdf 1.14.1 → 1.15.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 (100) hide show
  1. package/README.md +13 -1
  2. package/dist/__bench__/arabicShaping.bench.test.d.ts +2 -0
  3. package/dist/__bench__/arabicShaping.bench.test.d.ts.map +1 -0
  4. package/dist/__bench__/arabicShaping.bench.test.js +53 -0
  5. package/dist/__bench__/arabicShaping.bench.test.js.map +1 -0
  6. package/dist/__tests__/arabicShaping.test.d.ts +2 -0
  7. package/dist/__tests__/arabicShaping.test.d.ts.map +1 -0
  8. package/dist/__tests__/arabicShaping.test.js +261 -0
  9. package/dist/__tests__/arabicShaping.test.js.map +1 -0
  10. package/dist/__tests__/complexShaping.test.d.ts +2 -0
  11. package/dist/__tests__/complexShaping.test.d.ts.map +1 -0
  12. package/dist/__tests__/complexShaping.test.js +145 -0
  13. package/dist/__tests__/complexShaping.test.js.map +1 -0
  14. package/dist/__tests__/designTextRtl.test.d.ts +2 -0
  15. package/dist/__tests__/designTextRtl.test.d.ts.map +1 -0
  16. package/dist/__tests__/designTextRtl.test.js +136 -0
  17. package/dist/__tests__/designTextRtl.test.js.map +1 -0
  18. package/dist/__tests__/harfbuzz.test.d.ts +2 -0
  19. package/dist/__tests__/harfbuzz.test.d.ts.map +1 -0
  20. package/dist/__tests__/harfbuzz.test.js +103 -0
  21. package/dist/__tests__/harfbuzz.test.js.map +1 -0
  22. package/dist/__tests__/measuredLines.test.js +13 -5
  23. package/dist/__tests__/measuredLines.test.js.map +1 -1
  24. package/dist/__tests__/mirroredPdf.test.d.ts +2 -0
  25. package/dist/__tests__/mirroredPdf.test.d.ts.map +1 -0
  26. package/dist/__tests__/mirroredPdf.test.js +104 -0
  27. package/dist/__tests__/mirroredPdf.test.js.map +1 -0
  28. package/dist/__tests__/rtlPdf.test.d.ts +2 -0
  29. package/dist/__tests__/rtlPdf.test.d.ts.map +1 -0
  30. package/dist/__tests__/rtlPdf.test.js +312 -0
  31. package/dist/__tests__/rtlPdf.test.js.map +1 -0
  32. package/dist/__tests__/verticalText.test.js +4 -4
  33. package/dist/__tests__/verticalText.test.js.map +1 -1
  34. package/dist/complexShaping.d.ts +113 -0
  35. package/dist/complexShaping.d.ts.map +1 -0
  36. package/dist/complexShaping.js +188 -0
  37. package/dist/complexShaping.js.map +1 -0
  38. package/dist/faceFiles.d.ts +9 -1
  39. package/dist/faceFiles.d.ts.map +1 -1
  40. package/dist/faceFiles.js +47 -5
  41. package/dist/faceFiles.js.map +1 -1
  42. package/dist/harfbuzz.d.ts +119 -0
  43. package/dist/harfbuzz.d.ts.map +1 -0
  44. package/dist/harfbuzz.js +280 -0
  45. package/dist/harfbuzz.js.map +1 -0
  46. package/dist/harfbuzz.wasm +0 -0
  47. package/dist/index.d.ts +2 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js.map +1 -1
  50. package/dist/pdf-backend/blockRender.d.ts.map +1 -1
  51. package/dist/pdf-backend/blockRender.js +113 -40
  52. package/dist/pdf-backend/blockRender.js.map +1 -1
  53. package/dist/pdf-backend/chip.d.ts.map +1 -1
  54. package/dist/pdf-backend/chip.js +11 -2
  55. package/dist/pdf-backend/chip.js.map +1 -1
  56. package/dist/pdf-backend/directedLine.d.ts +38 -0
  57. package/dist/pdf-backend/directedLine.d.ts.map +1 -0
  58. package/dist/pdf-backend/directedLine.js +103 -0
  59. package/dist/pdf-backend/directedLine.js.map +1 -0
  60. package/dist/pdf-backend/fontHelpers.d.ts.map +1 -1
  61. package/dist/pdf-backend/fontHelpers.js +6 -0
  62. package/dist/pdf-backend/fontHelpers.js.map +1 -1
  63. package/dist/pdf-backend/headerFooter.d.ts.map +1 -1
  64. package/dist/pdf-backend/headerFooter.js +11 -3
  65. package/dist/pdf-backend/headerFooter.js.map +1 -1
  66. package/dist/pdf-backend/index.d.ts +32 -3
  67. package/dist/pdf-backend/index.d.ts.map +1 -1
  68. package/dist/pdf-backend/index.js +40 -6
  69. package/dist/pdf-backend/index.js.map +1 -1
  70. package/dist/pdf-backend/links.d.ts +7 -2
  71. package/dist/pdf-backend/links.d.ts.map +1 -1
  72. package/dist/pdf-backend/links.js +9 -3
  73. package/dist/pdf-backend/links.js.map +1 -1
  74. package/dist/pdf-backend/outlines.js +2 -2
  75. package/dist/pdf-backend/outlines.js.map +1 -1
  76. package/dist/pdf-backend/primitives.d.ts +46 -2
  77. package/dist/pdf-backend/primitives.d.ts.map +1 -1
  78. package/dist/pdf-backend/primitives.js +67 -5
  79. package/dist/pdf-backend/primitives.js.map +1 -1
  80. package/dist/pdf-backend/renderResourceBlock.d.ts.map +1 -1
  81. package/dist/pdf-backend/renderResourceBlock.js +48 -14
  82. package/dist/pdf-backend/renderResourceBlock.js.map +1 -1
  83. package/dist/pdf-backend/rtlRun.d.ts +12 -0
  84. package/dist/pdf-backend/rtlRun.d.ts.map +1 -0
  85. package/dist/pdf-backend/rtlRun.js +31 -0
  86. package/dist/pdf-backend/rtlRun.js.map +1 -0
  87. package/dist/pdf-backend/shapedText.d.ts +122 -0
  88. package/dist/pdf-backend/shapedText.d.ts.map +1 -0
  89. package/dist/pdf-backend/shapedText.js +635 -0
  90. package/dist/pdf-backend/shapedText.js.map +1 -0
  91. package/dist/pdf-backend/svgVector.d.ts +9 -2
  92. package/dist/pdf-backend/svgVector.d.ts.map +1 -1
  93. package/dist/pdf-backend/svgVector.js +42 -18
  94. package/dist/pdf-backend/svgVector.js.map +1 -1
  95. package/dist/worker/client.d.ts.map +1 -1
  96. package/dist/worker/client.js +10 -1
  97. package/dist/worker/client.js.map +1 -1
  98. package/dist/worker/protocol.d.ts +5 -1
  99. package/dist/worker/protocol.d.ts.map +1 -1
  100. package/package.json +6 -5
@@ -0,0 +1,136 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { execFileSync } from 'node:child_process';
6
+ import { PDFArray, PDFDocument, PDFRawStream, decodePDFRawStream } from 'pdf-lib';
7
+ import { buildDocument } from 'postext';
8
+ import { renderToPdf } from '../pdf-backend';
9
+ import { parseFontString } from '../fontString';
10
+ import { complexShaperReady, shapeRun } from '../complexShaping';
11
+ import { resolveParagraph } from 'postext';
12
+ // Issue #377: a running head and a chip of a right-to-left document are
13
+ // painted run by run in the order the engine gives (`order`, `rtl`), the
14
+ // Arabic runs shaped right to left by HarfBuzz.
15
+ const AMIRI = new Uint8Array(fs.readFileSync(new URL('./fixtures/arabic/amiri-subset.ttf', import.meta.url)));
16
+ const fontProvider = async () => AMIRI;
17
+ /** Measures with HarfBuzz once it is loaded, a rough em before. */
18
+ class HarfBuzzCtx {
19
+ font = '';
20
+ measureText(s) {
21
+ const sizePx = parseFontString(this.font)?.sizePx ?? 16;
22
+ const run = complexShaperReady() ? shapeRun(AMIRI, s, { direction: (resolveParagraph(s).paragraphLevel === 1 ? 'rtl' : 'ltr') }) : undefined;
23
+ if (!run)
24
+ return { width: s.length * sizePx * 0.5 };
25
+ return { width: (run.glyphs.reduce((sum, g) => sum + g.xAdvance, 0) / run.upem) * sizePx };
26
+ }
27
+ }
28
+ globalThis.OffscreenCanvas = class {
29
+ getContext() {
30
+ return new HarfBuzzCtx();
31
+ }
32
+ };
33
+ const pt = (value) => ({ value, unit: 'pt' });
34
+ const TITLE = 'السلام عليكم Latin';
35
+ function config() {
36
+ return {
37
+ direction: 'rtl',
38
+ locale: 'ar',
39
+ page: { width: pt(420), height: pt(260), dpi: 72, margins: { top: pt(40), bottom: pt(20), left: pt(20), right: pt(20) } },
40
+ layout: { layoutType: 'single' },
41
+ bodyText: { fontFamily: 'Amiri', fontSize: pt(14), lineHeight: pt(28), firstLineIndent: pt(0), hyphenation: { enabled: false } },
42
+ headings: { levels: [{ level: 1, fontFamily: 'Amiri' }] },
43
+ header: {
44
+ elements: [{
45
+ kind: 'text', id: 'rh', content: '{chapterTitle}', fontFamily: 'Amiri', fontSize: pt(12), overflow: 'wrap', align: 'start',
46
+ placement: { anchor: { to: 'container', edge: 'top-left' }, size: { width: 'fill' } },
47
+ }],
48
+ },
49
+ footer: { elements: [] },
50
+ };
51
+ }
52
+ function pageContent(pdf) {
53
+ const contents = pdf.getPage(0).node.Contents();
54
+ const refs = contents instanceof PDFArray ? contents.asArray() : [contents];
55
+ return refs
56
+ .map((ref) => {
57
+ const s = pdf.context.lookup(ref);
58
+ return s instanceof PDFRawStream ? new TextDecoder('latin1').decode(decodePDFRawStream(s).decode()) : '';
59
+ })
60
+ .join('\n');
61
+ }
62
+ const hasPdftotext = (() => {
63
+ try {
64
+ execFileSync('pdftotext', ['-v'], { stdio: 'ignore' });
65
+ return true;
66
+ }
67
+ catch {
68
+ return false;
69
+ }
70
+ })();
71
+ describe('design text right to left in the PDF', () => {
72
+ it('paints the running head run by run, left to right on the sheet', async () => {
73
+ // Load HarfBuzz for the measurement too: one render first.
74
+ await renderToPdf(buildDocument({ markdown: `# ${TITLE}` }, config()), { fontProvider });
75
+ const doc = buildDocument({ markdown: `# ${TITLE}\n\nكلمة كلمة.` }, config());
76
+ const header = doc.pages[0].header.blocks[0];
77
+ if (header.kind !== 'text')
78
+ throw new Error('no header text');
79
+ const line = header.lines[0];
80
+ expect(header.direction).toBe('rtl');
81
+ expect(line.runs.map((r) => [r.text, r.rtl ?? false])).toEqual([['السلام عليكم ', true], ['Latin', false]]);
82
+ expect(line.order).toEqual([1, 0]);
83
+ const bytes = await renderToPdf(doc, { fontProvider });
84
+ const content = pageContent(await PDFDocument.load(bytes));
85
+ // The header's baseline: two text objects, Latin first (at the left).
86
+ const pageHeightPt = 260;
87
+ const y = Math.round(pageHeightPt - line.baselineY);
88
+ const xs = [...content.matchAll(/^1 0 0 1 (-?[\d.]+) (-?[\d.]+) Tm$/gm)]
89
+ .filter((m) => Math.round(Number(m[2])) === y)
90
+ .map((m) => Number(m[1]));
91
+ expect(xs.length).toBe(2);
92
+ expect(xs[0]).toBeLessThan(xs[1]);
93
+ // The Latin run starts at the header's left edge plus the slack: its
94
+ // start is the box's right edge minus the line width.
95
+ expect(xs[0]).toBeCloseTo((header.bbox.x + line.xOffset) * 1, 0);
96
+ if (hasPdftotext) {
97
+ const file = path.join(os.tmpdir(), `postext-design-rtl-${process.pid}.pdf`);
98
+ fs.writeFileSync(file, bytes);
99
+ const text = execFileSync('pdftotext', ['-enc', 'UTF-8', '-l', '1', file, '-'], { encoding: 'utf8' });
100
+ fs.unlinkSync(file);
101
+ const rows = text.split('\n').map((t) => t.replace(/[\s\f‪-‮]/g, '')).filter(Boolean);
102
+ expect(rows[0]).toBe('السلامعليكمLatin');
103
+ }
104
+ });
105
+ it.skipIf(!hasPdftotext)('places body runs shaped on a mirrored page in their own boxes', async () => {
106
+ const doc = buildDocument({ markdown: 'كلمة السلام عليكم كلمة Latin 2024 كلمة' }, { ...config(), header: { elements: [] } });
107
+ const bytes = await renderToPdf(doc, { fontProvider });
108
+ const file = path.join(os.tmpdir(), `postext-design-rtl-body-${process.pid}.pdf`);
109
+ fs.writeFileSync(file, bytes);
110
+ const xml = execFileSync('pdftotext', ['-bbox', '-l', '1', file, '-'], { encoding: 'utf8' });
111
+ fs.unlinkSync(file);
112
+ const words = [...xml.matchAll(/xMin="([\d.]+)" yMin="[\d.]+" xMax="([\d.]+)"/g)].map((m) => [Number(m[1]), Number(m[2])])
113
+ .sort((a, b) => a[0] - b[0]);
114
+ expect(words.length).toBeGreaterThanOrEqual(6);
115
+ // Up to postext 1.14 each run of a mirrored page was turned back about
116
+ // its left edge and landed one advance off, over its neighbour.
117
+ for (let i = 1; i < words.length; i++)
118
+ expect(words[i][0]).toBeGreaterThanOrEqual(words[i - 1][1] - 0.5);
119
+ });
120
+ });
121
+ describe('a design text in a face with no Arabic letters (#401)', () => {
122
+ it('reports the characters it drew as .notdef', async () => {
123
+ const latin = new Uint8Array(fs.readFileSync(new URL('./fixtures/arabic/amiri-latin-slice.ttf', import.meta.url)));
124
+ const base = config();
125
+ const header = { elements: [{ ...base.header.elements[0], fontFamily: 'Latin Only' }] };
126
+ const doc = buildDocument({ markdown: `# ${TITLE}\n\nكلمة كلمة.` }, { ...base, header });
127
+ const warnings = [];
128
+ await renderToPdf(doc, { fontProvider: async (family) => (family === 'Latin Only' ? latin : AMIRI), onWarning: (w) => warnings.push(w) });
129
+ const missing = warnings.filter((w) => w.kind === 'missingGlyph');
130
+ expect(missing).toHaveLength(1);
131
+ expect(missing[0].family).toBe('Latin Only');
132
+ // The title's Arabic letters, not its Latin word or the space.
133
+ expect(missing[0].characters.join('')).toBe('السمعيك');
134
+ });
135
+ });
136
+ //# sourceMappingURL=designTextRtl.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"designTextRtl.test.js","sourceRoot":"","sources":["../../src/__tests__/designTextRtl.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=harfbuzz.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harfbuzz.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/harfbuzz.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,103 @@
1
+ import { describe, it, expect, vi, afterEach } from 'vitest';
2
+ import { readFileSync } from 'node:fs';
3
+ import fontkit from '@pdf-lib/fontkit';
4
+ import { HARFBUZZ_VERSION, loadHarfBuzz } from '../harfbuzz';
5
+ // Issue #380: HarfBuzz is bound straight to its WebAssembly binary, so it
6
+ // loads the same in Node, a page, a Worker and a bundle; and a PDF whose
7
+ // Arabic was drawn without it says so.
8
+ const AMIRI = new Uint8Array(readFileSync(new URL('./fixtures/arabic/amiri-subset.ttf', import.meta.url)));
9
+ const WASM_URL = new URL('../../node_modules/harfbuzzjs/dist/harfbuzz.wasm', import.meta.url);
10
+ const BASMALA = 'بِسْمِ ٱللَّهِ';
11
+ function glyphs(hb, text, direction, features) {
12
+ const font = hb.openFont(AMIRI, {});
13
+ return hb.shape(font, text, { direction, ...(features ? { features } : {}) });
14
+ }
15
+ describe('HarfBuzz binding', () => {
16
+ it('is written for the harfbuzzjs release installed', () => {
17
+ const pkg = JSON.parse(readFileSync(new URL('../../node_modules/harfbuzzjs/package.json', import.meta.url), 'utf8'));
18
+ expect(pkg.version).toBe(HARFBUZZ_VERSION);
19
+ });
20
+ it('loads from its default place in Node and from bytes alike', async () => {
21
+ const fromFile = await loadHarfBuzz();
22
+ const fromBytes = await loadHarfBuzz(readFileSync(WASM_URL));
23
+ const a = glyphs(fromFile, BASMALA, 'rtl');
24
+ expect(a.length).toBeGreaterThan(5);
25
+ expect(glyphs(fromBytes, BASMALA, 'rtl')).toEqual(a);
26
+ // Right to left: the clusters come out descending, the marks offset.
27
+ const clusters = a.map((g) => g.cluster);
28
+ expect([...clusters].sort((x, y) => y - x)).toEqual(clusters);
29
+ expect(a.some((g) => g.yOffset !== 0)).toBe(true);
30
+ });
31
+ it('loads from a URL string', async () => {
32
+ const hb = await loadHarfBuzz(WASM_URL.href);
33
+ expect(glyphs(hb, 'AB', 'ltr').map((g) => g.cluster)).toEqual([0, 1]);
34
+ });
35
+ it('applies features and agrees with fontkit on glyph ids', async () => {
36
+ const hb = await loadHarfBuzz();
37
+ const face = fontkit.create(Buffer.from(AMIRI));
38
+ const run = glyphs(hb, 'AB', 'ltr');
39
+ expect(run.map((g) => g.gid)).toEqual(face.layout('AB').glyphs.map((g) => g.id));
40
+ // Turning kerning off cannot lengthen the run.
41
+ expect(glyphs(hb, 'AB', 'ltr', [['kern', 0]]).length).toBe(run.length);
42
+ });
43
+ it('shapes long text and many fonts (the heap grows)', async () => {
44
+ const hb = await loadHarfBuzz();
45
+ const long = `${BASMALA} `.repeat(20_000);
46
+ const run = glyphs(hb, long, 'rtl');
47
+ expect(run.length).toBeGreaterThan(100_000);
48
+ for (let i = 0; i < 50; i++)
49
+ hb.openFont(AMIRI, {});
50
+ expect(glyphs(hb, BASMALA, 'rtl')).toEqual(glyphs(hb, BASMALA, 'rtl'));
51
+ });
52
+ it('names every place it looked when the binary is nowhere', async () => {
53
+ await expect(loadHarfBuzz('file:///nowhere/harfbuzz.wasm')).rejects.toThrow(/nowhere\/harfbuzz\.wasm/);
54
+ // A file that is not WebAssembly (a server's error page) is refused
55
+ // before it reaches the compiler.
56
+ const font = new URL('./fixtures/arabic/amiri-subset.ttf', import.meta.url).href;
57
+ await expect(loadHarfBuzz(font)).rejects.toThrow(/not a WebAssembly file/);
58
+ });
59
+ });
60
+ describe('Arabic drawn without HarfBuzz', () => {
61
+ afterEach(() => {
62
+ vi.doUnmock('../harfbuzz');
63
+ vi.resetModules();
64
+ });
65
+ it('is reported as a complexShapingUnavailable warning, and the PDF still builds', async () => {
66
+ vi.resetModules();
67
+ vi.doMock('../harfbuzz', async (importOriginal) => ({
68
+ ...(await importOriginal()),
69
+ loadHarfBuzz: () => Promise.reject(new Error('https://example.test/harfbuzz.wasm: HTTP 404')),
70
+ }));
71
+ const face = fontkit.create(Buffer.from(AMIRI));
72
+ globalThis.OffscreenCanvas = class {
73
+ getContext() {
74
+ return { font: '', measureText: (s) => ({ width: (face.layout(s).advanceWidth / face.unitsPerEm) * 16 }) };
75
+ }
76
+ };
77
+ const { buildDocument } = await import('postext');
78
+ const { renderToPdf } = await import('../pdf-backend');
79
+ const { complexShaperReady } = await import('../complexShaping');
80
+ const pt = (value) => ({ value, unit: 'pt' });
81
+ const doc = buildDocument({ markdown: `${BASMALA} Latin 2024` }, {
82
+ page: { width: pt(300), height: pt(200), dpi: 72, margins: { top: pt(20), bottom: pt(20), left: pt(20), right: pt(20) } },
83
+ locale: 'ar',
84
+ layout: { layoutType: 'single' },
85
+ header: { elements: [] },
86
+ footer: { elements: [] },
87
+ bodyText: { fontFamily: 'Amiri', fontSize: pt(16), lineHeight: pt(30) },
88
+ });
89
+ const warnings = [];
90
+ const bytes = await renderToPdf(doc, { fontProvider: async () => AMIRI, onWarning: (w) => warnings.push(w) });
91
+ expect(bytes.length).toBeGreaterThan(1000);
92
+ expect(complexShaperReady()).toBe(false);
93
+ const shaping = warnings.filter((w) => w.kind === 'complexShapingUnavailable');
94
+ expect(shaping).toHaveLength(1);
95
+ expect(shaping[0].reason).toContain('HTTP 404');
96
+ expect(shaping[0].message).toMatch(/^postext-pdf: HarfBuzz did not load/);
97
+ // A Latin document never looks for HarfBuzz, so it never warns.
98
+ warnings.length = 0;
99
+ await renderToPdf(buildDocument({ markdown: 'Latin only, 2024.' }, doc.config), { fontProvider: async () => AMIRI, onWarning: (w) => warnings.push(w) });
100
+ expect(warnings.filter((w) => w.kind === 'complexShapingUnavailable')).toHaveLength(0);
101
+ }, 60_000);
102
+ });
103
+ //# sourceMappingURL=harfbuzz.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harfbuzz.test.js","sourceRoot":"","sources":["../../src/__tests__/harfbuzz.test.ts"],"names":[],"mappings":"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"}
@@ -195,12 +195,18 @@ describe('a plain ragged line keeps its measured word positions (EF-137)', () =>
195
195
  });
196
196
  });
197
197
  describe('a line with right-to-left letters', () => {
198
- it('stays one run, which the shaper sets right to left', async () => {
198
+ it('stays one run, which HarfBuzz sets right to left', async () => {
199
199
  // Lora has no Hebrew: the browser measured the letters in another font
200
200
  // (0.8 em each), the PDF paints notdef glyphs. Word by word, the pieces
201
- // would be set left to right in logical order, reversing the words.
201
+ // would be set left to right in logical order, reversing the words; a
202
+ // line with no directions in its VDT is cut into bidi runs instead
203
+ // (#380), here one.
202
204
  const doc = buildDocument({ markdown: 'שלום עולם' }, config);
203
205
  const line = doc.pages[0].columns[0].blocks[0].lines[0];
206
+ // As a VDT from before the engine resolved directions (#369).
207
+ delete line.order;
208
+ for (const seg of line.segments ?? [])
209
+ delete seg.rtl;
204
210
  expect(line.segments.length).toBeGreaterThan(1);
205
211
  const pdf = await PDFDocument.load(await renderToPdf(doc, { fontProvider, accessible: false }));
206
212
  const page = pdf.getPage(0);
@@ -209,10 +215,12 @@ describe('a line with right-to-left letters', () => {
209
215
  let content = '';
210
216
  for (const ref of refs)
211
217
  content += new TextDecoder('latin1').decode(decodePDFRawStream(pdf.context.lookup(ref)).decode());
218
+ // One text object, its glyphs at HarfBuzz's advances (each notdef
219
+ // under a span that reads as its letter).
220
+ expect(content.split('\n').filter((l) => l === 'BT')).toHaveLength(1);
212
221
  const shows = content.split('\n').filter((l) => /T[jJ]$/.test(l));
213
- expect(shows).toHaveLength(1);
214
- // One run of glyphs, no pen adjustments between the words.
215
- expect(shows[0]).toMatch(/^<[0-9A-Fa-f]+> Tj$/);
222
+ for (const show of shows)
223
+ expect(show).toMatch(/^\[ .* \] TJ$/);
216
224
  });
217
225
  });
218
226
  describe('measuredTextOperator', () => {
@@ -1 +1 @@
1
- {"version":3,"file":"measuredLines.test.js","sourceRoot":"","sources":["../../src/__tests__/measuredLines.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EACL,QAAQ,EACR,OAAO,EACP,WAAW,EAEX,OAAO,EACP,SAAS,EAGT,kBAAkB,GACnB,MAAM,SAAS,CAAC;AACjB,OAAO,OAAO,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,0EAA0E;AAC1E,yEAAyE;AACzE,uEAAuE;AACvE,wEAAwE;AACxE,0EAA0E;AAC1E,gEAAgE;AAEhE,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,oDAAoD,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7G,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAI/B,CAAC;AAEF;;;oCAGoC;AACpC,MAAM,aAAa;IACjB,IAAI,GAAG,EAAE,CAAC;IACV,WAAW,CAAC,CAAS;QACnB,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,IAAI,EAAE,CAAC;QACtD,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,GAAG,GAAG,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,GAAG,EAAE;YACjB,IAAI,GAAG;gBAAE,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;YAC3E,GAAG,GAAG,EAAE,CAAC;QACX,CAAC,CAAC;QACF,KAAK,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;YACnB,MAAM,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC;YAC9B,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;gBAAC,KAAK,EAAE,CAAC;gBAAC,SAAS;YAAC,CAAC;YACzC,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;gBAAC,KAAK,EAAE,CAAC;gBAAC,KAAK,IAAI,IAAI,CAAC;gBAAC,SAAS;YAAC,CAAC;YACxD,IAAI,EAAE,GAAG,IAAI,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC,EAAE,CAAC;gBAAC,KAAK,EAAE,CAAC;gBAAC,KAAK,IAAI,IAAI,GAAG,GAAG,CAAC;gBAAC,SAAS;YAAC,CAAC;YAC3G,GAAG,IAAI,EAAE,CAAC;QACZ,CAAC;QACD,KAAK,EAAE,CAAC;QACR,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC;CACF;AACA,UAAsD,CAAC,eAAe,GAAG;IACxE,UAAU;QACR,OAAO,IAAI,aAAa,EAAE,CAAC;IAC7B,CAAC;CACF,CAAC;AAEF,MAAM,EAAE,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAa,EAAE,CAAC,CAAC;AAC/D,MAAM,MAAM,GAAkB;IAC5B,yCAAyC;IACzC,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACzH,MAAM,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE;IAChC,QAAQ,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE;IACjH,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;IACxB,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;CACzB,CAAC;AACF,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;AAItD;;;4DAG4D;AAC5D,SAAS,aAAa,CAAC,GAAgB,EAAE,SAAiB;IACxD,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAG,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkD,CAAC;IAC3E,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAa,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACtG,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC;QAC1D,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;QACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,MAAM,KAAK,GAAI,CAAC,CAAC,CAAC,CAAe,CAAC,QAAQ,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAE,EAAE,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC;YAC/D,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,EAAG,CAAe,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QACrC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,YAAY,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAClG,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAG,CAAC;IACvC,MAAM,IAAI,GAAG,QAAQ,YAAY,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC5E,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,MAAM,GAAG,IAAI,IAAI;QAAE,OAAO,IAAI,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAiB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1I,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,IAAI,MAAM,GAAG,EAAE,CAAC,EAAE,IAAI,GAAG,EAAkB,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACxD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,EAAE;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9C,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YACxB,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;QAC7D,CAAC;IACH,CAAC,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,IAAI,CAAyB,CAAC;QAC9B,IAAI,CAAC,CAAC,GAAG,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAAC,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAE,CAAE,CAAC;YAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;aAChG,IAAI,CAAC,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAC1D,IAAI,CAAC,CAAC,GAAG,oCAAoC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAC5E,IAAI,CAAC,CAAC,GAAG,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC;aAC1D,IAAI,CAAC,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAC5C,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;;oBAC7C,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,2EAA2E;AAC3E,SAAS,cAAc,CAAC,IAAa;IACnC,MAAM,GAAG,GAAsD,EAAE,CAAC;IAClE,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACpB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACtC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAChE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC;QACf,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAChC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,QAAgB,EAAE,UAAmB;IACzD,MAAM,GAAG,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;IAC5D,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;IACzF,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;AACjD,CAAC;AAED,QAAQ,CAAC,gEAAgE,EAAE,GAAG,EAAE;IAC9E,KAAK,MAAM,UAAU,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;QACvC,EAAE,CAAC,mFAAmF,UAAU,GAAG,EAAE,KAAK,IAAI,EAAE;YAC9G,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,mCAAmC,EAAE,UAAU,CAAC,CAAC;YACvF,MAAM,CAAC,IAAI,CAAC,QAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnG,yEAAyE;YACzE,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,GAAG,IAAI,CAAC,QAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACpF,KAAK,MAAM,KAAK,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAE,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACrE,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,EAAE,CAAC,kFAAkF,EAAE,KAAK,IAAI,EAAE;QAChG,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5E,wEAAwE;QACxE,mEAAmE;QACnE,sEAAsE;QACtE,MAAM,GAAG,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAC/G,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC;QACzD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACxC,uEAAuE;QACvE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,QAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClF,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC/F,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/E,uDAAuD;QACvD,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,KAAK,MAAM,KAAK,IAAI,cAAc,CAAC,IAAI,CAAC;gBAAE,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAE,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACtH,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;QAClC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wFAAwF,EAAE,KAAK,IAAI,EAAE;QACtG,wEAAwE;QACxE,sCAAsC;QACtC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;QAC5E,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAE,CAAC;QACxE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;QACnD,mEAAmE;QACnE,6DAA6D;QAC7D,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,uEAAuE;QACvE,wEAAwE;QACxE,oEAAoE;QACpE,MAAM,GAAG,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;QAC5D,MAAM,CAAC,IAAI,CAAC,QAAS,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QAChG,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAG,CAAC;QACvC,MAAM,IAAI,GAAG,QAAQ,YAAY,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC5E,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,KAAK,MAAM,GAAG,IAAI,IAAI;YAAE,OAAO,IAAI,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAiB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1I,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9B,2DAA2D;QAC3D,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,CAAC;QACvC,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG;YACb,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;YAC1B,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE;YACvB,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;SAC7B,CAAC;QACF,MAAM,IAAI,GAAG,EAAE,CAAC;QAChB,MAAM,QAAQ,GAAG,GAAG,CAAC;QACrB,MAAM,EAAE,GAAG,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAE,CAAC;QAC/D,MAAM,GAAG,GAAI,EAAsC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5D,gEAAgE;QAChE,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAsG,CAAC;QACvI,MAAM,MAAM,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;QAChH,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;YACjC,IAAI,IAAI,YAAY,SAAS,EAAE,CAAC;gBAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;gBAAC,SAAS;YAAC,CAAC;YAClF,MAAM,GAAG,GAAI,IAAqB,CAAC,QAAQ,EAAE,CAAC;YAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACf,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAE,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,QAAQ,CAAC;YAC/C,CAAC;QACH,CAAC;QACD,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY;QAClD,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"measuredLines.test.js","sourceRoot":"","sources":["../../src/__tests__/measuredLines.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mirroredPdf.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirroredPdf.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/mirroredPdf.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,104 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { execFileSync } from 'node:child_process';
6
+ import { PDFArray, PDFDocument, PDFRawStream, decodePDFRawStream } from 'pdf-lib';
7
+ import { buildDocument } from 'postext';
8
+ import fontkit from '@pdf-lib/fontkit';
9
+ import { renderToPdf } from '../pdf-backend';
10
+ import { parseFontString } from '../fontString';
11
+ // Issue #370: a right-to-left page paints its flow through the mirror of
12
+ // its frame, each text object turned back about its own box, so the text
13
+ // reads (and extracts) as written where the mirrored layout put it.
14
+ const fontBytes = fs.readFileSync(new URL('../../../../apps/web/public/fonts/Lora-Regular.ttf', import.meta.url));
15
+ const fontProvider = async () => new Uint8Array(fontBytes);
16
+ const face = fontkit.create(Buffer.from(fontBytes));
17
+ /** Measures with the face the PDF embeds, so pdftotext sees the words
18
+ * where the layout set them. */
19
+ class StubCtx {
20
+ font = '';
21
+ letterSpacing = '0px';
22
+ measureText(s) {
23
+ const sizePx = parseFontString(this.font)?.sizePx ?? 16;
24
+ return { width: (face.layout(s).advanceWidth / face.unitsPerEm) * sizePx };
25
+ }
26
+ }
27
+ globalThis.OffscreenCanvas = class {
28
+ getContext() {
29
+ return new StubCtx();
30
+ }
31
+ };
32
+ const pt = (value) => ({ value, unit: 'pt' });
33
+ // No full stops: in a right-to-left paragraph a final stop after Latin
34
+ // words is a neutral at the paragraph's level and stands at the line's
35
+ // left end (UAX #9); these tests look at the frame.
36
+ const MD = ['# Heading', 'First paragraph alpha beta gamma delta epsilon zeta eta theta', 'Second paragraph iota kappa lambda mu nu xi omicron pi rho sigma'].join('\n\n');
37
+ function config(direction) {
38
+ return {
39
+ direction,
40
+ locale: 'en',
41
+ page: {
42
+ width: pt(300), height: pt(420), dpi: 72,
43
+ margins: { top: pt(40), bottom: pt(40), left: pt(40), right: pt(20), mirror: true },
44
+ ...(direction === 'ltr' ? { binding: 'left' } : {}),
45
+ },
46
+ header: { elements: [] },
47
+ footer: { elements: [] },
48
+ bodyText: { fontFamily: 'Lora', fontSize: pt(12), lineHeight: pt(18), textAlign: 'left', hyphenation: { enabled: false } },
49
+ };
50
+ }
51
+ async function content(doc) {
52
+ const bytes = await renderToPdf(doc, { fontProvider });
53
+ const pdf = await PDFDocument.load(bytes);
54
+ const contents = pdf.getPage(0).node.Contents();
55
+ const refs = contents instanceof PDFArray ? contents.asArray() : [contents];
56
+ const ops = refs.map((ref) => {
57
+ const s = pdf.context.lookup(ref);
58
+ return s instanceof PDFRawStream ? new TextDecoder('latin1').decode(decodePDFRawStream(s).decode()) : '';
59
+ }).join('\n');
60
+ return { bytes, ops };
61
+ }
62
+ const textMatrices = (ops, a) => [...ops.matchAll(new RegExp(`^${a} 0 0 1 (-?[\\d.]+) (-?[\\d.]+) Tm$`, 'gm'))].map((m) => ({ x: Number(m[1]), y: Number(m[2]) }));
63
+ const hasPdftotext = (() => {
64
+ try {
65
+ execFileSync('pdftotext', ['-v'], { stdio: 'ignore' });
66
+ return true;
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ })();
72
+ describe('a right-to-left page in the PDF', () => {
73
+ it('paints the flow through the mirror, text objects turned back', async () => {
74
+ const ltr = await content(buildDocument({ markdown: MD }, config('ltr')));
75
+ const rtl = await content(buildDocument({ markdown: MD }, config('rtl')));
76
+ expect(ltr.ops).not.toMatch(/^-1 0 0 1 300 0 cm$/m);
77
+ expect(rtl.ops).toMatch(/^-1 0 0 1 300 0 cm$/m);
78
+ const a = textMatrices(ltr.ops, '1');
79
+ const b = textMatrices(rtl.ops, '-1');
80
+ expect(a.length).toBeGreaterThan(2);
81
+ expect(b.length).toBeGreaterThanOrEqual(a.length);
82
+ expect(textMatrices(rtl.ops, '1')).toEqual([]);
83
+ // The same baselines, and every text object inside the flow's width.
84
+ expect(new Set(b.map((m) => Math.round(m.y)))).toEqual(new Set(a.map((m) => Math.round(m.y))));
85
+ for (const m of b)
86
+ expect(m.x).toBeGreaterThan(0);
87
+ });
88
+ it.skipIf(!hasPdftotext)('reads back as written (pdftotext)', async () => {
89
+ const read = async (direction) => {
90
+ const { bytes } = await content(buildDocument({ markdown: MD }, config(direction)));
91
+ const file = path.join(os.tmpdir(), `postext-mirrored-${process.pid}-${direction}.pdf`);
92
+ fs.writeFileSync(file, bytes);
93
+ const text = execFileSync('pdftotext', ['-enc', 'UTF-8', file, '-'], { encoding: 'utf8' });
94
+ fs.unlinkSync(file);
95
+ return text.split('\n').map((l) => l.replace(/\s+/g, ' ').trim()).filter(Boolean);
96
+ };
97
+ const ltr = await read('ltr');
98
+ expect(ltr.join(' ')).toContain('First paragraph alpha');
99
+ // Every line reads as written. (Poppler takes the sheet's left column
100
+ // first: the second one of a right-to-left page.)
101
+ expect([...await read('rtl')].sort()).toEqual([...ltr].sort());
102
+ });
103
+ });
104
+ //# sourceMappingURL=mirroredPdf.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirroredPdf.test.js","sourceRoot":"","sources":["../../src/__tests__/mirroredPdf.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rtlPdf.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rtlPdf.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/rtlPdf.test.ts"],"names":[],"mappings":""}