postext-pdf 1.29.2 → 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__/canvasShaping.test.d.ts +2 -0
- package/dist/__tests__/canvasShaping.test.d.ts.map +1 -0
- package/dist/__tests__/canvasShaping.test.js +258 -0
- package/dist/__tests__/canvasShaping.test.js.map +1 -0
- package/dist/__tests__/canvasWords.test.d.ts +2 -0
- package/dist/__tests__/canvasWords.test.d.ts.map +1 -0
- package/dist/__tests__/canvasWords.test.js +66 -0
- package/dist/__tests__/canvasWords.test.js.map +1 -0
- package/dist/__tests__/declaredFiles.test.d.ts +2 -0
- package/dist/__tests__/declaredFiles.test.d.ts.map +1 -0
- package/dist/__tests__/declaredFiles.test.js +435 -0
- package/dist/__tests__/declaredFiles.test.js.map +1 -0
- package/dist/__tests__/designTextRtl.test.js +17 -6
- package/dist/__tests__/designTextRtl.test.js.map +1 -1
- package/dist/__tests__/glyphPositions.d.ts +25 -0
- package/dist/__tests__/glyphPositions.d.ts.map +1 -0
- package/dist/__tests__/glyphPositions.js +288 -0
- package/dist/__tests__/glyphPositions.js.map +1 -0
- package/dist/__tests__/japaneseShaping.test.js +3 -3
- package/dist/__tests__/japaneseShaping.test.js.map +1 -1
- package/dist/__tests__/listMarkerShaping.test.d.ts +2 -0
- package/dist/__tests__/listMarkerShaping.test.d.ts.map +1 -0
- package/dist/__tests__/listMarkerShaping.test.js +64 -0
- package/dist/__tests__/listMarkerShaping.test.js.map +1 -0
- package/dist/__tests__/pdfWorker.test.js +27 -0
- package/dist/__tests__/pdfWorker.test.js.map +1 -1
- package/dist/__tests__/scriptContextHan.test.js +3 -3
- package/dist/__tests__/scriptContextHan.test.js.map +1 -1
- package/dist/__tests__/shapingLanguageDocument.test.js +1 -1
- package/dist/__tests__/shapingLanguageDocument.test.js.map +1 -1
- package/dist/__tests__/shapingLanguageRunsDocument.test.js +158 -8
- package/dist/__tests__/shapingLanguageRunsDocument.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 +77 -0
- package/dist/__tests__/trackedLetters.test.js.map +1 -0
- package/dist/canvasWords.d.ts +55 -0
- package/dist/canvasWords.d.ts.map +1 -0
- package/dist/canvasWords.js +160 -0
- package/dist/canvasWords.js.map +1 -0
- package/dist/faceFiles.d.ts +93 -5
- package/dist/faceFiles.d.ts.map +1 -1
- package/dist/faceFiles.js +256 -10
- package/dist/faceFiles.js.map +1 -1
- package/dist/fontCache.d.ts +92 -11
- package/dist/fontCache.d.ts.map +1 -1
- package/dist/fontCache.js +82 -17
- package/dist/fontCache.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pdf-backend/blockRender.d.ts.map +1 -1
- package/dist/pdf-backend/blockRender.js +63 -23
- package/dist/pdf-backend/blockRender.js.map +1 -1
- package/dist/pdf-backend/index.d.ts +3 -2
- package/dist/pdf-backend/index.d.ts.map +1 -1
- package/dist/pdf-backend/index.js +9 -3
- package/dist/pdf-backend/index.js.map +1 -1
- package/dist/pdf-backend/primitives.d.ts +55 -5
- package/dist/pdf-backend/primitives.d.ts.map +1 -1
- package/dist/pdf-backend/primitives.js +206 -25
- package/dist/pdf-backend/primitives.js.map +1 -1
- package/dist/pdf-backend/renderResourceBlock.d.ts.map +1 -1
- package/dist/pdf-backend/renderResourceBlock.js +27 -7
- package/dist/pdf-backend/renderResourceBlock.js.map +1 -1
- package/dist/pdf-backend/shapedText.d.ts +4 -0
- package/dist/pdf-backend/shapedText.d.ts.map +1 -1
- package/dist/pdf-backend/shapedText.js +15 -4
- package/dist/pdf-backend/shapedText.js.map +1 -1
- package/dist/pdf-backend/svgVector.js +1 -1
- package/dist/pdf-backend/svgVector.js.map +1 -1
- package/dist/pdf-backend/verticalText.d.ts.map +1 -1
- package/dist/pdf-backend/verticalText.js +7 -4
- package/dist/pdf-backend/verticalText.js.map +1 -1
- package/dist/pdf-backend/wordPieces.d.ts +22 -41
- package/dist/pdf-backend/wordPieces.d.ts.map +1 -1
- package/dist/pdf-backend/wordPieces.js +75 -62
- package/dist/pdf-backend/wordPieces.js.map +1 -1
- package/dist/shapingLanguage.d.ts +16 -0
- package/dist/shapingLanguage.d.ts.map +1 -1
- package/dist/shapingLanguage.js +50 -20
- package/dist/shapingLanguage.js.map +1 -1
- package/dist/unicodeRange.d.ts +19 -0
- package/dist/unicodeRange.d.ts.map +1 -0
- package/dist/unicodeRange.js +68 -0
- package/dist/unicodeRange.js.map +1 -0
- package/dist/worker/client.d.ts +1 -1
- package/dist/worker/client.d.ts.map +1 -1
- package/dist/worker/client.js +5 -2
- package/dist/worker/client.js.map +1 -1
- package/dist/worker/pdf.worker.js +7 -0
- package/dist/worker/pdf.worker.js.map +1 -1
- package/dist/worker/protocol.d.ts +6 -0
- package/dist/worker/protocol.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvasShaping.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/canvasShaping.test.ts"],"names":[],"mappings":"AAWA,OAAO,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import fontkit from '@pdf-lib/fontkit';
|
|
4
|
+
import { PDFDocument, rgb } from 'pdf-lib';
|
|
5
|
+
import { buildDocument } from 'postext';
|
|
6
|
+
import { renderToPdf } from '../pdf-backend';
|
|
7
|
+
import { loadComplexShaper } from '../complexShaping';
|
|
8
|
+
import { parseFontString } from '../fontString';
|
|
9
|
+
import { shapeInCurrentLanguage, withDocumentLanguage } from '../shapingLanguage';
|
|
10
|
+
import { cellPieces, drawTextPx, textAdvancePx, textShows } from '../pdf-backend/primitives';
|
|
11
|
+
import '../pdf-backend/shapedText';
|
|
12
|
+
import { paintedGlyphs } from './glyphPositions';
|
|
13
|
+
// #770: a document shaped in its own language is shaped word by word, as
|
|
14
|
+
// the canvas shaped it (`canvasWords.ts`), and the characters a line of the
|
|
15
|
+
// CJK composer measured one by one are painted one by one. The widths below
|
|
16
|
+
// are the ones Chrome 154 gives these very font files on a canvas
|
|
17
|
+
// (`measureText` at 1000 px with `ctx.lang` set): thousandths of the em.
|
|
18
|
+
//
|
|
19
|
+
// Chrome cuts a string at its spaces and around each CJK character and
|
|
20
|
+
// shapes every word alone: nothing is kerned across a cut, and a word takes
|
|
21
|
+
// the script of its own letters, none when it has no letter (a space, a
|
|
22
|
+
// quote, a row of digits) unless the whole string has no character above
|
|
23
|
+
// U+00FF. A shaper handed the whole string kerns `ノン` in Noto Serif JP
|
|
24
|
+
// (0.04 em), a comma against a space in Alegreya (0.02 em), sets the dash
|
|
25
|
+
// of `2026—2026` in its Chinese form beside a Latin word, the quotes of
|
|
26
|
+
// `私は“本当”` in their Japanese form, and the space between two Arabic
|
|
27
|
+
// words of Aref Ruqaa 0.146 em wide, as inside Arabic text, for 0.333 em.
|
|
28
|
+
const fixture = (name) => new Uint8Array(fs.readFileSync(new URL(`./fixtures/${name}`, import.meta.url)));
|
|
29
|
+
const FILES = {
|
|
30
|
+
serifJP: fixture('cjk/noto-serif-jp-vertical.ttf'),
|
|
31
|
+
sansSC: fixture('cjk/noto-sans-sc-language.ttf'),
|
|
32
|
+
alegreya: fixture('latin/alegreya-language.ttf'),
|
|
33
|
+
aref: fixture('fontsource/aref-ruqaa-arabic.ttf'),
|
|
34
|
+
};
|
|
35
|
+
/** Kana and the marks after them, in Japanese. */
|
|
36
|
+
const KANA = [['\u30CE\u30F3\u30D5\u30EB', 4000], ['\u30AF\u30EA\u30C3\u30AF', 4000], ['\u30A2\u30A4', 2000], ['\u30EA\u30F3\u30AF\u3068\u306F', 5000], ['\u30AF\u30EA\u30C3\u30AF\u3059\u308B\u3002', 7000], ['\u3059\u3002', 1920], ['\u308C\u3001', 2060], ['\u30FC\u3001', 1960], ['\u30E9\u30FC', 2000], ['\u3059\u3002\u3059\u3002', 3840], ['\u30CE\u30F3 \u30CE\u30F3', 4256], ['\u30CE\u30F3\u30D5\u30EB\u306F\u4EBA', 6000]];
|
|
37
|
+
/** The quotes of Japanese text: alone, beside a kana or a Han character,
|
|
38
|
+
* in a Latin word. */
|
|
39
|
+
const QUOTES = [['\u201C', 426], ['\u201D', 425], ['"', 392], ['\'', 205], ['\u306F\u201C', 1426], ['\u306F"', 1376], ['\u306F"\u306F', 2376], ['\u201C\u672C\u5F53\u201D', 2851], ['\u79C1\u306F\u201C\u672C\u5F53\u201D\u3068\u66F8\u304F\u3002', 8831], ['\u201Cyes\u201D', 2484], ['said \u201Cyes\u201D', 4730], ['yes \u201C\u306F\u201D', 3661], ['"hi"', 1779]];
|
|
40
|
+
/** A running head in Chinese, with Latin words and a dash between digits. */
|
|
41
|
+
const HEAD_ZH = [['\u672C 2026\u20142026 abn', 8573], ['2026\u20142026', 5334], ['n\u2014n', 2220], ['\u672C \u00B7 n', 3058], ['\u4E00 2026', 3444], ['\u4E00 \u2014', 2118]];
|
|
42
|
+
const HEAD_EN = [['\u672C 2026\u20142026 abn', 8573], ['2026\u20142026', 5334], ['n\u2014n', 2114], ['\u672C \u00B7 n', 3058], ['\u4E00 2026', 3444], ['\u4E00 \u2014', 2118]];
|
|
43
|
+
/** Alegreya kerns a comma, a full stop and an interpunct against a space. */
|
|
44
|
+
const SPACED = [['a, e', 1406], ['e \u00B7 a', 1548], ['a. e', 1417], ['a,', 760]];
|
|
45
|
+
/** A title in Aref Ruqaa, with a space and with a no-break space. */
|
|
46
|
+
const TITLE = [['\u0623\u0644\u0641 \u0644\u064A\u0644\u0629 \u0648\u0644\u064A\u0644\u0629', 4176], ['\u0623\u0644\u0641 \u0644\u064A\u0644\u0629', 2622], ['\u0623\u0644\u0641\u00A0\u0644\u064A\u0644\u0629', 2435], ['\u0623\u0644\u0641', 1315], ['\u0644\u064A\u0644\u0629', 974]];
|
|
47
|
+
const fonts = {};
|
|
48
|
+
let pdf;
|
|
49
|
+
beforeAll(async () => {
|
|
50
|
+
await loadComplexShaper();
|
|
51
|
+
pdf = await PDFDocument.create();
|
|
52
|
+
pdf.registerFontkit(fontkit);
|
|
53
|
+
for (const face of Object.keys(FILES)) {
|
|
54
|
+
fonts[face] = await pdf.embedFont(FILES[face], { subset: true });
|
|
55
|
+
shapeInCurrentLanguage(fonts[face]);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
/** In a document shaped in the language `tag`. */
|
|
59
|
+
const inDocument = (tag, fn) => withDocumentLanguage(tag, tag, fn);
|
|
60
|
+
/** In a document that keeps the host's language, declared in `tag`. */
|
|
61
|
+
const inHost = (tag, fn) => withDocumentLanguage(undefined, tag, fn);
|
|
62
|
+
/** The advance the PDF gives `text` set as plain text. */
|
|
63
|
+
const advance = (face, text) => textAdvancePx(fonts[face], text, 1000).advance;
|
|
64
|
+
const near = (got, chrome, what) => expect(Math.abs(got - chrome), `${what}: ${got.toFixed(1)}, Chrome ${chrome}`).toBeLessThan(0.75);
|
|
65
|
+
/** `text` painted at 20 pt from x = 50 on a page of its own, in a document
|
|
66
|
+
* shaped in `tag` (in one that keeps the host's language with `host`):
|
|
67
|
+
* the glyphs the page shows. */
|
|
68
|
+
async function painted(face, text, tag, host = false) {
|
|
69
|
+
const doc = await PDFDocument.create();
|
|
70
|
+
doc.registerFontkit(fontkit);
|
|
71
|
+
const font = await doc.embedFont(FILES[face], { subset: true });
|
|
72
|
+
shapeInCurrentLanguage(font);
|
|
73
|
+
const page = doc.addPage([600, 100]);
|
|
74
|
+
const ctx = { page, pageHeightPt: 100, scale: 1, colorSpace: 'rgb' };
|
|
75
|
+
const paint = () => drawTextPx(ctx, text, 50, 60, font, 20, rgb(0, 0, 0));
|
|
76
|
+
if (host)
|
|
77
|
+
inHost(tag, paint);
|
|
78
|
+
else
|
|
79
|
+
inDocument(tag, paint);
|
|
80
|
+
return (await paintedGlyphs(await doc.save()))[0];
|
|
81
|
+
}
|
|
82
|
+
describe('a string shaped word by word, as on the canvas (#770)', () => {
|
|
83
|
+
it('Noto Serif JP: kana are not kerned against each other, and a kana is against the mark after it', () => {
|
|
84
|
+
inDocument('ja', () => KANA.forEach(([text, chrome]) => near(advance('serifJP', text), chrome, text)));
|
|
85
|
+
});
|
|
86
|
+
it('Noto Serif JP: a quote is Japanese in a Latin word and alone in eight bits, the default one beside a kana', () => {
|
|
87
|
+
inDocument('ja', () => QUOTES.forEach(([text, chrome]) => near(advance('serifJP', text), chrome, text)));
|
|
88
|
+
});
|
|
89
|
+
it('Noto Sans SC: the dash between two numbers is the default one, whatever stands in the words beside it', () => {
|
|
90
|
+
inDocument('zh-Hans', () => HEAD_ZH.forEach(([text, chrome]) => near(advance('sansSC', text), chrome, text)));
|
|
91
|
+
inDocument('en', () => HEAD_EN.forEach(([text, chrome]) => near(advance('sansSC', text), chrome, text)));
|
|
92
|
+
});
|
|
93
|
+
it('Alegreya: nothing is kerned against a space', () => {
|
|
94
|
+
inDocument('en', () => SPACED.forEach(([text, chrome]) => near(advance('alegreya', text), chrome, text)));
|
|
95
|
+
});
|
|
96
|
+
it('a document that keeps the host\u2019s language is shaped string by string, as before', () => {
|
|
97
|
+
inHost('ja', () => {
|
|
98
|
+
// The pair kerned, and the quotes of the whole run Japanese.
|
|
99
|
+
near(advance('serifJP', '\u30CE\u30F3\u30D5\u30EB'), 3920, 'kana');
|
|
100
|
+
near(advance('serifJP', '\u79C1\u306F\u201C\u672C\u5F53\u201D\u3068\u66F8\u304F\u3002'), 8000 + 465 + 465 - 20, 'quotes');
|
|
101
|
+
});
|
|
102
|
+
inHost('en', () => near(advance('alegreya', 'a, e'), 1386, 'a, e'));
|
|
103
|
+
// And so is text with no language in force at all.
|
|
104
|
+
near(advance('alegreya', 'a, e'), 1386, 'a, e');
|
|
105
|
+
near(advance('serifJP', '\u30CE\u30F3\u30D5\u30EB'), 3920, 'kana');
|
|
106
|
+
});
|
|
107
|
+
it('the words that follow each other in one file are one operator, with no number between two kana', () => {
|
|
108
|
+
const shows = (text) => textShows(fonts.serifJP, text).map((show) => show.op.toString());
|
|
109
|
+
inDocument('ja', () => {
|
|
110
|
+
const ops = shows('\u30CE\u30F3\u30D5');
|
|
111
|
+
expect(ops).toHaveLength(1);
|
|
112
|
+
expect(ops[0]).toMatch(/^<[0-9A-F]{12}> Tj$/i);
|
|
113
|
+
// The kana and its full stop are one word: kerned.
|
|
114
|
+
expect(shows('\u3059\u3002')[0]).toMatch(/TJ$/);
|
|
115
|
+
});
|
|
116
|
+
inHost('ja', () => expect(shows('\u30CE\u30F3\u30D5')[0]).toMatch(/TJ$/));
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe('the glyphs of a string painted word by word (#770)', () => {
|
|
120
|
+
it('Noto Serif JP: each kana an em after the one before', async () => {
|
|
121
|
+
const glyphs = await painted('serifJP', '\u30CE\u30F3\u30D5\u30EB\u306F\u4EBA', 'ja');
|
|
122
|
+
expect(glyphs.map((g) => g.text).join('')).toBe('\u30CE\u30F3\u30D5\u30EB\u306F\u4EBA');
|
|
123
|
+
glyphs.forEach((g, i) => expect(g.x, g.text).toBeCloseTo(50 + 20 * i, 2));
|
|
124
|
+
// Shaped as one string, the ones after a kerned pair stand left of their places.
|
|
125
|
+
const whole = await painted('serifJP', '\u30CE\u30F3\u30D5\u30EB\u306F\u4EBA', 'ja', true);
|
|
126
|
+
expect(whole.filter((g, i) => Math.abs(g.x - (50 + 20 * i)) > 0.1).length).toBeGreaterThan(0);
|
|
127
|
+
});
|
|
128
|
+
it('Noto Serif JP: the quotes beside a Han character are the default ones, the ones of a Latin word Japanese', async () => {
|
|
129
|
+
const face = fontkit.create(Buffer.from(FILES.serifJP));
|
|
130
|
+
const k = 1000 / face.unitsPerEm;
|
|
131
|
+
const layout = face.layout;
|
|
132
|
+
const boxOf = (text, at, script, language) => {
|
|
133
|
+
const b = layout.call(face, text, [], script, language).glyphs[at].bbox;
|
|
134
|
+
return [b.minX, b.maxX, b.minY, b.maxY].map((v) => Math.round(v * k)).join(' ');
|
|
135
|
+
};
|
|
136
|
+
const plain = { open: boxOf('\u201C', 0, 'DFLT'), close: boxOf('\u201D', 0, 'DFLT'), ascii: boxOf('"', 0, 'DFLT') };
|
|
137
|
+
const japanese = { open: boxOf('n\u201C', 1, 'latn', 'JAN'), close: boxOf('n\u201D', 1, 'latn', 'JAN'), ascii: boxOf('n"', 1, 'latn', 'JAN') };
|
|
138
|
+
expect(plain.open).not.toBe(japanese.open);
|
|
139
|
+
expect(plain.ascii).not.toBe(japanese.ascii);
|
|
140
|
+
const boxes = async (text, host = false) => {
|
|
141
|
+
const out = {};
|
|
142
|
+
for (const g of await painted('serifJP', text, 'ja', host))
|
|
143
|
+
(out[g.text] ??= []).push(g.box);
|
|
144
|
+
return out;
|
|
145
|
+
};
|
|
146
|
+
const sentence = await boxes('\u79C1\u306F\u201C\u672C\u5F53\u201D\u3068\u66F8\u304F\u3002');
|
|
147
|
+
expect(sentence['\u201C']).toEqual([plain.open]);
|
|
148
|
+
expect(sentence['\u201D']).toEqual([plain.close]);
|
|
149
|
+
expect((await boxes('\u306F"\u306F'))['"']).toEqual([plain.ascii]);
|
|
150
|
+
const word = await boxes('said \u201Cyes\u201D');
|
|
151
|
+
expect(word['\u201C']).toEqual([japanese.open]);
|
|
152
|
+
expect(word['\u201D']).toEqual([japanese.close]);
|
|
153
|
+
expect((await boxes('"'))['"']).toEqual([japanese.ascii]);
|
|
154
|
+
expect((await boxes('"hi"'))['"']).toEqual([japanese.ascii, japanese.ascii]);
|
|
155
|
+
// A document that keeps the host's language prints the Japanese ones everywhere (#427).
|
|
156
|
+
const host = await boxes('\u79C1\u306F\u201C\u672C\u5F53\u201D\u3068\u66F8\u304F\u3002', true);
|
|
157
|
+
expect(host['\u201C']).toEqual([japanese.open]);
|
|
158
|
+
expect(host['\u201D']).toEqual([japanese.close]);
|
|
159
|
+
});
|
|
160
|
+
it('Aref Ruqaa: the space between two Arabic words is a word of its own, 0.333 em wide', async () => {
|
|
161
|
+
/** How wide the glyphs of a painted text stand, thousandths of the em. */
|
|
162
|
+
const width = (glyphs) => ((Math.max(...glyphs.map((g) => g.end)) - Math.min(...glyphs.map((g) => g.x))) / 20) * 1000;
|
|
163
|
+
for (const [text, chrome] of TITLE)
|
|
164
|
+
near(width(await painted('aref', text, 'ar')), chrome, text);
|
|
165
|
+
const space = (glyphs) => glyphs.find((g) => g.text === ' ').advance / 20;
|
|
166
|
+
expect(space(await painted('aref', '\u0623\u0644\u0641 \u0644\u064A\u0644\u0629', 'ar'))).toBeCloseTo(0.333, 3);
|
|
167
|
+
// Shaped as one string, the space is the one of Arabic text, and the two words stand 0.187 em closer.
|
|
168
|
+
const whole = await painted('aref', '\u0623\u0644\u0641 \u0644\u064A\u0644\u0629', 'ar', true);
|
|
169
|
+
expect(space(whole)).toBeCloseTo(0.146, 3);
|
|
170
|
+
near(width(whole), 2435, 'host');
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
// The layout of the documents below: a canvas that measures with the
|
|
174
|
+
// font's own advances, each string as fontkit sets it alone. The composer
|
|
175
|
+
// measures a CJK character by itself, so every kana and every mark is one
|
|
176
|
+
// em in its line.
|
|
177
|
+
const jp = fontkit.create(Buffer.from(FILES.serifJP));
|
|
178
|
+
class StubCtx {
|
|
179
|
+
font = '';
|
|
180
|
+
letterSpacing = '0px';
|
|
181
|
+
measureText(s) {
|
|
182
|
+
const size = parseFontString(this.font)?.sizePx ?? 16;
|
|
183
|
+
let w = 0;
|
|
184
|
+
for (const p of jp.layout(s).positions)
|
|
185
|
+
w += p.xAdvance;
|
|
186
|
+
const width = (w / jp.unitsPerEm) * size;
|
|
187
|
+
return { width, actualBoundingBoxAscent: 0.88 * size, actualBoundingBoxDescent: 0.12 * size, actualBoundingBoxLeft: 0, actualBoundingBoxRight: width };
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
globalThis.OffscreenCanvas = class {
|
|
191
|
+
getContext() {
|
|
192
|
+
return new StubCtx();
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
const pt = (value) => ({ value, unit: 'pt' });
|
|
196
|
+
const japaneseConfig = (shapingLanguage) => ({
|
|
197
|
+
locale: 'ja',
|
|
198
|
+
page: { width: pt(300), height: pt(420), dpi: 72, margins: { top: pt(40), bottom: pt(40), left: pt(30), right: pt(30) } },
|
|
199
|
+
layout: { layoutType: 'single' },
|
|
200
|
+
bodyText: { fontFamily: 'Noto Serif JP', fontSize: pt(16), lineHeight: pt(24), firstLineIndent: pt(0), textAlign: 'left', hyphenation: { enabled: false }, shapingLanguage },
|
|
201
|
+
headings: { fontFamily: 'Noto Serif JP' },
|
|
202
|
+
header: { elements: [] },
|
|
203
|
+
footer: { elements: [] },
|
|
204
|
+
});
|
|
205
|
+
/** The glyphs of the first page of `markdown` laid out and printed. */
|
|
206
|
+
async function printed(markdown, shapingLanguage) {
|
|
207
|
+
const doc = buildDocument({ markdown }, japaneseConfig(shapingLanguage));
|
|
208
|
+
return (await paintedGlyphs(await renderToPdf(doc, { fontProvider: async () => FILES.serifJP })))[0];
|
|
209
|
+
}
|
|
210
|
+
/** How far each `。` that follows a `す` stands from it, pt. */
|
|
211
|
+
function stops(glyphs) {
|
|
212
|
+
const out = [];
|
|
213
|
+
glyphs.forEach((g, i) => {
|
|
214
|
+
if (g.text === '\u3002' && glyphs[i - 1]?.text === '\u3059')
|
|
215
|
+
out.push(g.x - glyphs[i - 1].x);
|
|
216
|
+
});
|
|
217
|
+
return out;
|
|
218
|
+
}
|
|
219
|
+
describe('the characters a line of the CJK composer measured one by one (#770)', () => {
|
|
220
|
+
it('are painted one by one where a face kerns them together, and a Western run whole', () => {
|
|
221
|
+
inDocument('ja', () => {
|
|
222
|
+
// Six ems as the layout measured them; as one string the stop stands 0.08 em closer.
|
|
223
|
+
expect(advance('serifJP', '\u30AF\u30EA\u30C3\u30AF\u3059\u3002')).toBeCloseTo(5920, 0);
|
|
224
|
+
const cells = cellPieces(fonts.serifJP, '\u30AF\u30EA\u30C3\u30AF\u3059\u3002', 6 * 16, 16);
|
|
225
|
+
expect(cells?.map((cell) => cell.text).join('|')).toBe([...'\u30AF\u30EA\u30C3\u30AF\u3059\u3002'].join('|'));
|
|
226
|
+
cells.forEach((cell) => expect(cell.width).toBeCloseTo(16, 6));
|
|
227
|
+
// Chrome's em at 15.625 px is 15.62 px: the same characters.
|
|
228
|
+
expect(cellPieces(fonts.serifJP, '\u30AF\u30EA\u30C3\u30AF\u3059\u3002', 6 * 15.6199951171875, 15.625)).toHaveLength(6);
|
|
229
|
+
// With the line's character spacing in every cell.
|
|
230
|
+
expect(cellPieces(fonts.serifJP, '\u30AF\u30EA\u30C3\u30AF\u3059\u3002', 6 * 17, 16, 1)?.map((cell) => cell.width)).toEqual([17, 17, 17, 17, 17, 17]);
|
|
231
|
+
// Nothing kerns in these: painted as they are.
|
|
232
|
+
expect(cellPieces(fonts.serifJP, '\u30AF\u30EA\u30C3\u30AF', 4 * 16, 16)).toBeUndefined();
|
|
233
|
+
expect(cellPieces(fonts.serifJP, 'said', (1990 / 1000) * 16, 16)).toBeUndefined();
|
|
234
|
+
// A segment of another width is not these characters one by one.
|
|
235
|
+
expect(cellPieces(fonts.serifJP, '\u30AF\u30EA\u30C3\u30AF\u3059\u3002', 6 * 16 + 4, 16)).toBeUndefined();
|
|
236
|
+
});
|
|
237
|
+
// A document that keeps the host's language prints its segments as it did.
|
|
238
|
+
inHost('ja', () => expect(cellPieces(fonts.serifJP, '\u30AF\u30EA\u30C3\u30AF\u3059\u3002', 6 * 16, 16)).toBeUndefined());
|
|
239
|
+
expect(cellPieces(fonts.serifJP, '\u30AF\u30EA\u30C3\u30AF\u3059\u3002', 6 * 16, 16)).toBeUndefined();
|
|
240
|
+
});
|
|
241
|
+
it('a line painted as one text: every stop an em after its kana', async () => {
|
|
242
|
+
const document = stops(await printed('\u30EA\u30F3\u30AF\u3068\u306F\u4F55\u304B\u3002\u30AF\u30EA\u30C3\u30AF\u3059\u3002\u79C1\u306F\u898B\u305F\u3002', 'document'));
|
|
243
|
+
expect(document.length).toBeGreaterThan(0);
|
|
244
|
+
document.forEach((d) => expect(d).toBeCloseTo(16, 2));
|
|
245
|
+
// Shaped in one string, as a document that keeps the host's language is: 0.08 em closer.
|
|
246
|
+
const host = stops(await printed('\u30EA\u30F3\u30AF\u3068\u306F\u4F55\u304B\u3002\u30AF\u30EA\u30C3\u30AF\u3059\u3002\u79C1\u306F\u898B\u305F\u3002', 'host'));
|
|
247
|
+
expect(host.length).toBe(document.length);
|
|
248
|
+
host.forEach((d) => expect(d).toBeCloseTo(16 - 0.08 * 16, 2));
|
|
249
|
+
});
|
|
250
|
+
it('a line painted segment by segment: the same', async () => {
|
|
251
|
+
const document = stops(await printed('**\u30AF\u30EA\u30C3\u30AF\u3059\u3002**\u30EA\u30F3\u30AF\u3068\u306F\u4F55\u304B', 'document'));
|
|
252
|
+
expect(document).toHaveLength(1);
|
|
253
|
+
expect(document[0]).toBeCloseTo(16, 2);
|
|
254
|
+
const host = stops(await printed('**\u30AF\u30EA\u30C3\u30AF\u3059\u3002**\u30EA\u30F3\u30AF\u3068\u306F\u4F55\u304B', 'host'));
|
|
255
|
+
expect(host[0]).toBeCloseTo(16 - 0.08 * 16, 2);
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
//# sourceMappingURL=canvasShaping.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvasShaping.test.js","sourceRoot":"","sources":["../../src/__tests__/canvasShaping.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvasWords.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/canvasWords.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { canvasWords } from '../canvasWords';
|
|
3
|
+
// #770: the words Chrome's canvas shapes a string in. Each cut below was
|
|
4
|
+
// measured in Chrome 154: the width of the string against the sum of its
|
|
5
|
+
// parts, in a face that kerns across the cut (Noto Sans JP and Noto Serif
|
|
6
|
+
// JP kern a kana against the mark after it and against the next kana,
|
|
7
|
+
// Alegreya a comma against a space) or draws a mark otherwise by script
|
|
8
|
+
// (the dash of Noto Serif SC, the quotes of Noto Serif JP).
|
|
9
|
+
describe('the words of a string on the canvas (#770)', () => {
|
|
10
|
+
it('a string of one word is itself', () => {
|
|
11
|
+
for (const text of ['', 'a', 'word', 'l\u00B7l', '\u201Cyes\u201D', '\u672C', '\u2014\u2014', '\u0643\u062A\u0627\u0628.'])
|
|
12
|
+
expect(canvasWords(text)).toEqual([text]);
|
|
13
|
+
});
|
|
14
|
+
it('cuts at a space and at a tab, each a word of its own, and at no other space', () => {
|
|
15
|
+
// A space is a word of its own.
|
|
16
|
+
expect(canvasWords('Li Bai')).toEqual(['Li', ' ', 'Bai']);
|
|
17
|
+
// Two spaces, two words.
|
|
18
|
+
expect(canvasWords('a b')).toEqual(['a', ' ', ' ', 'b']);
|
|
19
|
+
// A tab cuts.
|
|
20
|
+
expect(canvasWords('a\tb')).toEqual(['a', '\t', 'b']);
|
|
21
|
+
// A no-break space does not.
|
|
22
|
+
expect(canvasWords('a\u00A0b')).toEqual(['a\u00A0b']);
|
|
23
|
+
// Nor a thin space or an ideographic one inside Latin text.
|
|
24
|
+
expect(canvasWords('a\u2009b')).toEqual(['a\u2009b']);
|
|
25
|
+
// A dash between digits stays in their word.
|
|
26
|
+
expect(canvasWords('9704\u20142012 \u00B7')).toEqual(['9704\u20142012', ' ', '\u00B7']);
|
|
27
|
+
// Arabic words.
|
|
28
|
+
expect(canvasWords('\u0623\u0644\u0641 \u0644\u064A\u0644\u0629')).toEqual(['\u0623\u0644\u0641', ' ', '\u0644\u064A\u0644\u0629']);
|
|
29
|
+
});
|
|
30
|
+
it('cuts around each CJK character, which keeps the marks after it', () => {
|
|
31
|
+
// Kana beside kana: two words.
|
|
32
|
+
expect(canvasWords('\u3048\u308B')).toEqual(['\u3048', '\u308B']);
|
|
33
|
+
// A kana and the mark after it: one word.
|
|
34
|
+
expect(canvasWords('\u304C\u3001\u30D7')).toEqual(['\u304C\u3001', '\u30D7']);
|
|
35
|
+
// A full stop, then a Latin letter.
|
|
36
|
+
expect(canvasWords('\u3059\u3002a')).toEqual(['\u3059\u3002', 'a']);
|
|
37
|
+
// A Latin word, a space, a kana with its comma.
|
|
38
|
+
expect(canvasWords('a \u304C\u3001')).toEqual(['a', ' ', '\u304C\u3001']);
|
|
39
|
+
// The prolonged sound mark stays with the kana before it.
|
|
40
|
+
expect(canvasWords('\u30E9\u30FC\u30E0')).toEqual(['\u30E9\u30FC', '\u30E0']);
|
|
41
|
+
// A word that opens with marks takes the first character with a script.
|
|
42
|
+
expect(canvasWords('\u3002\u300C\u6D3B\u5B57')).toEqual(['\u3002\u300C\u6D3B', '\u5B57']);
|
|
43
|
+
// A line of kana and Han.
|
|
44
|
+
expect(canvasWords('\u79C1\u306F\u201C\u672C\u5F53\u201D\u3068\u66F8\u304F\u3002')).toEqual(['\u79C1', '\u306F', '\u201C', '\u672C', '\u5F53', '\u201D', '\u3068', '\u66F8', '\u304F\u3002']);
|
|
45
|
+
// A quote beside a kana is a word of its own.
|
|
46
|
+
expect(canvasWords('\u306F"\u306F')).toEqual(['\u306F', '"', '\u306F']);
|
|
47
|
+
// An iteration mark and a voicing mark.
|
|
48
|
+
expect(canvasWords('\u4EBA\u3005\u304C\u304B\u309B')).toEqual(['\u4EBA\u3005', '\u304C', '\u304B\u309B']);
|
|
49
|
+
// An enclosed number has no script: it stays with the character before it.
|
|
50
|
+
expect(canvasWords('\uFF21\u2460b\u2460')).toEqual(['\uFF21\u2460', 'b', '\u2460']);
|
|
51
|
+
// A full-width hyphen-minus is not CJK to the canvas.
|
|
52
|
+
expect(canvasWords('a\uFF0Db')).toEqual(['a\uFF0Db']);
|
|
53
|
+
// Hangul is cut at its spaces only.
|
|
54
|
+
expect(canvasWords('\uD55C\uAD6D \uC5B4')).toEqual(['\uD55C\uAD6D', ' ', '\uC5B4']);
|
|
55
|
+
// A Han character of the upper planes.
|
|
56
|
+
expect(canvasWords('\u{20BB7}\u91CE')).toEqual(['\u{20BB7}', '\u91CE']);
|
|
57
|
+
});
|
|
58
|
+
it('a string with no character above U+00FF is cut at its spaces only', () => {
|
|
59
|
+
expect(canvasWords('caf\u00E9 \u00ABau lait\u00BB')).toEqual(['caf\u00E9', ' ', '\u00ABau', ' ', 'lait\u00BB']);
|
|
60
|
+
});
|
|
61
|
+
it('the words put together are the string', () => {
|
|
62
|
+
for (const text of ['\u3048\u308B', '\u304C\u3001\u30D7', '\u3059\u3002a', 'a \u304C\u3001', '\u30E9\u30FC\u30E0', '\u3002\u300C\u6D3B\u5B57', '\u79C1\u306F\u201C\u672C\u5F53\u201D\u3068\u66F8\u304F\u3002', '\u306F"\u306F', '\u4EBA\u3005\u304C\u304B\u309B', '\uFF21\u2460b', 'a\uFF0Db', '\uD55C\uAD6D \uC5B4', '\u{20BB7}\u91CE', 'Li Bai', 'a b', 'a\tb', 'a\u00A0b', 'a\u2009b', '9704\u20142012 \u00B7', '\u0623\u0644\u0641 \u0644\u064A\u0644\u0629'])
|
|
63
|
+
expect(canvasWords(text).join('')).toBe(text);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=canvasWords.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvasWords.test.js","sourceRoot":"","sources":["../../src/__tests__/canvasWords.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declaredFiles.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/declaredFiles.test.ts"],"names":[],"mappings":""}
|