reamkit 1.34.1 → 1.35.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/README.md +2 -1
- package/dist/esm/core/converter/ream.d.ts +15 -0
- package/dist/esm/core/converter/ream.js +35 -2
- package/dist/esm/core/font/index.d.ts +1 -1
- package/dist/esm/core/font/index.js +2 -2
- package/dist/esm/core/font/mark-shaper.d.ts +27 -0
- package/dist/esm/core/font/mark-shaper.js +116 -0
- package/dist/esm/core/font/measure.d.ts +16 -0
- package/dist/esm/core/font/measure.js +34 -2
- package/dist/esm/core/fonts/index.d.ts +2 -2
- package/dist/esm/core/fonts/remote-fonts.d.ts +37 -3
- package/dist/esm/core/fonts/remote-fonts.js +58 -1
- package/dist/esm/core/fonts/scripts.d.ts +21 -1
- package/dist/esm/core/fonts/scripts.js +46 -7
- package/dist/esm/html/html-writer.js +7 -2
- package/dist/esm/layout/line-paint.d.ts +2 -2
- package/dist/esm/layout/line-paint.js +5 -5
- package/dist/esm/layout/page-doc.d.ts +6 -0
- package/dist/esm/layout/styled-layout.js +155 -25
- package/dist/esm/pdf/cid-font.d.ts +6 -0
- package/dist/esm/pdf/cid-font.js +3 -2
- package/dist/esm/pdf/styled-page-emitter.js +4 -3
- package/dist/esm/pdf-reader/glyph-names.js +331 -0
- package/dist/esm/pdf-reader/text.js +65 -1
- package/dist/esm/word/docx-to-pdf.js +45 -2
- package/package.json +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { resolveFamilyStyle } from "../core/fonts/remote-fonts.js";
|
|
1
|
+
import { companionOf, companionScale, resolveFamilyStyle } from "../core/fonts/remote-fonts.js";
|
|
2
2
|
import { fontSlotOf, scriptForCodepoint } from "../core/fonts/scripts.js";
|
|
3
3
|
import { hasSubstitutable, substituteLetters } from "../core/font/ligatures.js";
|
|
4
4
|
import { hasIndic, syllableStarts } from "../core/font/indic-shaper.js";
|
|
5
|
-
import {
|
|
5
|
+
import { hasCombiningMark, isCombiningMark } from "../core/font/mark-shaper.js";
|
|
6
|
+
import { createFontMeasure, shapeGlyphs, sharedGlyphCodes } from "../core/font/measure.js";
|
|
6
7
|
import "../core/font/index.js";
|
|
7
8
|
import { pageItemBounds } from "./page-doc.js";
|
|
8
9
|
import { halfPtToPt, pt } from "../core/ir/units.js";
|
|
@@ -2916,9 +2917,20 @@ function runFontKeyAndParsed(options, ascii, bold, italic) {
|
|
|
2916
2917
|
* @param italic …and whether it is italic.
|
|
2917
2918
|
* @returns The face to draw it with, or `undefined` when nobody has it.
|
|
2918
2919
|
*/
|
|
2919
|
-
function fallbackFaceKey(options, cp, bold, italic) {
|
|
2920
|
+
function fallbackFaceKey(options, cp, bold, italic, own) {
|
|
2920
2921
|
const byFamily = options.registriesByFamily;
|
|
2921
2922
|
if (!byFamily || byFamily.size === 0) return void 0;
|
|
2923
|
+
const companion = own === void 0 ? void 0 : companionOf(own);
|
|
2924
|
+
const borrowed = companion ? byFamily.get(companion.family) : void 0;
|
|
2925
|
+
if (companion && borrowed) {
|
|
2926
|
+
const { variant, parsed } = borrowed.resolveByStyle(bold, italic);
|
|
2927
|
+
const widthScale = companionScale(companion, cp, variant);
|
|
2928
|
+
if (widthScale !== void 0 && parsed.glyphForCodepoint(cp) !== 0) return {
|
|
2929
|
+
fontKey: `${companion.family}:${variant}`,
|
|
2930
|
+
parsed,
|
|
2931
|
+
widthScale
|
|
2932
|
+
};
|
|
2933
|
+
}
|
|
2922
2934
|
const hanFace = byFamily.has("jp") ? "jp" : byFamily.has("kr") ? "kr" : "sc";
|
|
2923
2935
|
const script = scriptForCodepoint(cp, hanFace);
|
|
2924
2936
|
const order = script ? [script] : [];
|
|
@@ -2955,17 +2967,60 @@ function fallbackFaceKey(options, cp, bold, italic) {
|
|
|
2955
2967
|
* @returns The text to set, which is `text` itself unless something was undrawable.
|
|
2956
2968
|
*/
|
|
2957
2969
|
function drawableText(faces, text) {
|
|
2958
|
-
if (!hasSubstitutable(text)) return text;
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2970
|
+
if (!hasSubstitutable(text) && !hasCombiningMark(text)) return text;
|
|
2971
|
+
return drawnPieces(faces, text).join("");
|
|
2972
|
+
}
|
|
2973
|
+
/**
|
|
2974
|
+
* What is drawn for each character of `text` — itself, the letters of a
|
|
2975
|
+
* ligature nobody can draw (see {@link drawableText}), a composed letter in
|
|
2976
|
+
* place of a letter and the marks written apart after it, and nothing for those
|
|
2977
|
+
* marks.
|
|
2978
|
+
*
|
|
2979
|
+
* A letter of the Latin, Greek or Cyrillic alphabets followed by combining
|
|
2980
|
+
* marks is set as the letter that composes them (Unicode canonical
|
|
2981
|
+
* composition, NFC) where the face that would draw it has one: и + U+0306 is
|
|
2982
|
+
* drawn as й, а + U+0306 as Chuvash ӑ, о + U+0308 as Altai ӧ. Set as two
|
|
2983
|
+
* glyphs the mark stood at its own default place, beside the letter and above
|
|
2984
|
+
* it; Word draws the two exactly as it draws the composed letter. What has no
|
|
2985
|
+
* composed form — the stressed а, а and U+0301 — is left to the face's anchors (see
|
|
2986
|
+
* `shapeMarks`).
|
|
2987
|
+
*
|
|
2988
|
+
* @param faces The face each character of the run is drawn with ({@link runFaces}).
|
|
2989
|
+
* @param text The run's text.
|
|
2990
|
+
* @returns One string per code point of `text`, empty where a mark went into its letter.
|
|
2991
|
+
*/
|
|
2992
|
+
function drawnPieces(faces, text) {
|
|
2993
|
+
const cps = [...text].map((ch) => ch.codePointAt(0));
|
|
2994
|
+
const out = cps.map((cp) => String.fromCodePoint(cp));
|
|
2995
|
+
for (let i = 0; i < cps.length; i++) {
|
|
2996
|
+
let end = i + 1;
|
|
2997
|
+
while (end < cps.length && isCombiningMark(cps[end])) end++;
|
|
2998
|
+
if (end > i + 1 && composesInPlace(cps[i])) {
|
|
2999
|
+
const cluster = String.fromCodePoint(...cps.slice(i, end));
|
|
3000
|
+
const composed = cluster.normalize("NFC");
|
|
3001
|
+
const drawable = [...composed].every((ch) => faces(ch.codePointAt(0)).parsed.glyphForCodepoint(ch.codePointAt(0)) !== 0);
|
|
3002
|
+
if (composed !== cluster && drawable) {
|
|
3003
|
+
out[i] = composed;
|
|
3004
|
+
for (let k = i + 1; k < end; k++) out[k] = "";
|
|
3005
|
+
}
|
|
3006
|
+
i = end - 1;
|
|
3007
|
+
continue;
|
|
3008
|
+
}
|
|
3009
|
+
const letters = substituteLetters(cps[i]);
|
|
3010
|
+
if (letters !== void 0 && faces(cps[i]).parsed.glyphForCodepoint(cps[i]) === 0) out[i] = letters;
|
|
2965
3011
|
}
|
|
2966
3012
|
return out;
|
|
2967
3013
|
}
|
|
2968
3014
|
/**
|
|
3015
|
+
* Whether a letter's marks are composed into it by the layout: the Latin,
|
|
3016
|
+
* Greek and Cyrillic alphabets. The scripts of India compose and reorder in
|
|
3017
|
+
* their own shaper, and a CJK compatibility ideograph is not a letter to
|
|
3018
|
+
* recompose at all.
|
|
3019
|
+
*/
|
|
3020
|
+
function composesInPlace(cp) {
|
|
3021
|
+
return cp < 1328 || cp >= 7680 && cp <= 8191;
|
|
3022
|
+
}
|
|
3023
|
+
/**
|
|
2969
3024
|
* §9.2.2 — the face a request had to settle for, and what is left to draw.
|
|
2970
3025
|
*
|
|
2971
3026
|
* A registry may hold one face and be asked for four: `FontBytesByVariant`
|
|
@@ -3082,14 +3137,15 @@ function slotFaces(options, resolved, primary) {
|
|
|
3082
3137
|
* slant: a script face is fetched in the regular weight only, and a bold run in
|
|
3083
3138
|
* it is stroked, which is what F3's synthesis is for.
|
|
3084
3139
|
*/
|
|
3085
|
-
function fallbackFace(options, cp, resolved) {
|
|
3086
|
-
const
|
|
3087
|
-
if (!
|
|
3140
|
+
function fallbackFace(options, cp, resolved, own) {
|
|
3141
|
+
const found = fallbackFaceKey(options, cp, resolved.bold, resolved.italic, own);
|
|
3142
|
+
if (!found) return void 0;
|
|
3143
|
+
const { widthScale, ...face } = found;
|
|
3088
3144
|
const variant = face.fontKey.split(":")[1];
|
|
3089
3145
|
const got = variant === "bold" || variant === "boldItalic" || variant === "italic" ? variant : "regular";
|
|
3090
3146
|
return {
|
|
3091
3147
|
...face,
|
|
3092
|
-
...syntheticFace(got, resolved.bold, resolved.italic)
|
|
3148
|
+
...syntheticFace(got, resolved.bold, resolved.italic, widthScale)
|
|
3093
3149
|
};
|
|
3094
3150
|
}
|
|
3095
3151
|
/**
|
|
@@ -3119,11 +3175,41 @@ function runFaces(options, resolved, primary, text) {
|
|
|
3119
3175
|
const own = slots?.get(fontSlotOf(cp, resolved.rtl)) ?? primary;
|
|
3120
3176
|
if (own.parsed.glyphForCodepoint(cp) !== 0) return own;
|
|
3121
3177
|
if (own !== primary && primary.parsed.glyphForCodepoint(cp) !== 0) return primary;
|
|
3122
|
-
return fallbackFace(options, cp, resolved) ?? own;
|
|
3178
|
+
return fallbackFace(options, cp, resolved, own.fontKey.split(":")[0]) ?? own;
|
|
3123
3179
|
};
|
|
3180
|
+
const marks = markFaces(drawing, text);
|
|
3181
|
+
const withMarks = marks ? (cp) => marks.get(cp) ?? drawing(cp) : drawing;
|
|
3124
3182
|
const indic = indicFace(drawing, text);
|
|
3125
|
-
if (!indic) return
|
|
3126
|
-
return (cp) => INDIC_JOINS.has(cp) && indic.parsed.glyphForCodepoint(cp) !== 0 ? indic :
|
|
3183
|
+
if (!indic) return withMarks;
|
|
3184
|
+
return (cp) => INDIC_JOINS.has(cp) && indic.parsed.glyphForCodepoint(cp) !== 0 ? indic : withMarks(cp);
|
|
3185
|
+
}
|
|
3186
|
+
/**
|
|
3187
|
+
* The face each combining mark of `text` is drawn in, where it is not its
|
|
3188
|
+
* own: the face of the letter it sits on, when that face has it. A mark is
|
|
3189
|
+
* placed on its letter by the anchors of ONE face (see `shapeMarks`), and a
|
|
3190
|
+
* Cambria run sets its Cyrillic in the face Caladea borrows it from while
|
|
3191
|
+
* Caladea has an acute of its own — so the acute of a stressed а was drawn by Caladea
|
|
3192
|
+
* beside a letter drawn by Noto Serif, and missed it. One face per mark per
|
|
3193
|
+
* run: the letter it first sits on decides.
|
|
3194
|
+
*
|
|
3195
|
+
* @param drawing The face each character is drawn in, letter by letter.
|
|
3196
|
+
* @param text The run's text.
|
|
3197
|
+
* @returns The marks to draw in another face, or `undefined` when none.
|
|
3198
|
+
*/
|
|
3199
|
+
function markFaces(drawing, text) {
|
|
3200
|
+
if (!hasCombiningMark(text)) return void 0;
|
|
3201
|
+
let out;
|
|
3202
|
+
let base;
|
|
3203
|
+
for (const ch of text) {
|
|
3204
|
+
const cp = ch.codePointAt(0);
|
|
3205
|
+
if (!isCombiningMark(cp)) {
|
|
3206
|
+
base = drawing(cp);
|
|
3207
|
+
continue;
|
|
3208
|
+
}
|
|
3209
|
+
if (!base || out?.has(cp) === true) continue;
|
|
3210
|
+
if (drawing(cp).fontKey !== base.fontKey && base.parsed.glyphForCodepoint(cp) !== 0) (out ??= /* @__PURE__ */ new Map()).set(cp, base);
|
|
3211
|
+
}
|
|
3212
|
+
return out;
|
|
3127
3213
|
}
|
|
3128
3214
|
/** The face that draws the first letter of the scripts of India in `text`. */
|
|
3129
3215
|
function indicFace(drawing, text) {
|
|
@@ -3225,6 +3311,7 @@ function collectFontResources(body, headersFooters, options, imageResources) {
|
|
|
3225
3311
|
sink.glyphText ??= /* @__PURE__ */ new Map();
|
|
3226
3312
|
if (!sink.glyphText.has(g)) sink.glyphText.set(g, t);
|
|
3227
3313
|
}
|
|
3314
|
+
if (!shaped.glyphText) countSharedGlyphs(sink, span.parsed, shown);
|
|
3228
3315
|
}
|
|
3229
3316
|
if (run.text.includes(" ")) for (const stop of resolveParagraphProperties(para.properties, options.styles).tabs) {
|
|
3230
3317
|
const ch = stop.leader === void 0 ? void 0 : TAB_LEADER_CHARS.get(stop.leader);
|
|
@@ -3390,12 +3477,52 @@ function collectFontResources(body, headersFooters, options, imageResources) {
|
|
|
3390
3477
|
parsed: info.parsed,
|
|
3391
3478
|
measure: createFontMeasure(info.parsed, options.layoutProfile !== "word"),
|
|
3392
3479
|
gids: info.gids,
|
|
3393
|
-
...info.glyphText ? { glyphText: info.glyphText } : {}
|
|
3480
|
+
...info.glyphText ? { glyphText: info.glyphText } : {},
|
|
3481
|
+
...info.drawnAs ? { glyphChars: mostDrawn(info.drawnAs) } : {}
|
|
3394
3482
|
});
|
|
3395
3483
|
}
|
|
3396
3484
|
return out;
|
|
3397
3485
|
}
|
|
3398
3486
|
/**
|
|
3487
|
+
* Count, for each glyph of `text` that several characters share in the face's
|
|
3488
|
+
* `cmap`, which of them drew it (see `sharedGlyphCodes`).
|
|
3489
|
+
*
|
|
3490
|
+
* @param sink The face's collected glyphs, which the counts are kept with.
|
|
3491
|
+
* @param parsed The face.
|
|
3492
|
+
* @param text The text the face draws.
|
|
3493
|
+
*/
|
|
3494
|
+
function countSharedGlyphs(sink, parsed, text) {
|
|
3495
|
+
for (const ch of text) {
|
|
3496
|
+
const cp = ch.codePointAt(0);
|
|
3497
|
+
if (cp < 128) continue;
|
|
3498
|
+
const gid = parsed.glyphForCodepoint(cp);
|
|
3499
|
+
if (gid === 0 || sharedGlyphCodes(parsed, gid) === void 0) continue;
|
|
3500
|
+
sink.drawnAs ??= /* @__PURE__ */ new Map();
|
|
3501
|
+
let counts = sink.drawnAs.get(gid);
|
|
3502
|
+
if (!counts) sink.drawnAs.set(gid, counts = /* @__PURE__ */ new Map());
|
|
3503
|
+
counts.set(cp, (counts.get(cp) ?? 0) + 1);
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
/**
|
|
3507
|
+
* The character each shared glyph was drawn for most often; the first drawn
|
|
3508
|
+
* where two tie. One /ToUnicode entry cannot name both, and a document that
|
|
3509
|
+
* spells the same word in both alphabets with one glyph is rarer than one
|
|
3510
|
+
* that does not.
|
|
3511
|
+
*/
|
|
3512
|
+
function mostDrawn(drawnAs) {
|
|
3513
|
+
const out = /* @__PURE__ */ new Map();
|
|
3514
|
+
for (const [gid, counts] of drawnAs) {
|
|
3515
|
+
let best = -1;
|
|
3516
|
+
let most = 0;
|
|
3517
|
+
for (const [cp, n] of counts) if (n > most) {
|
|
3518
|
+
best = cp;
|
|
3519
|
+
most = n;
|
|
3520
|
+
}
|
|
3521
|
+
out.set(gid, best);
|
|
3522
|
+
}
|
|
3523
|
+
return out;
|
|
3524
|
+
}
|
|
3525
|
+
/**
|
|
3399
3526
|
* The one line an empty paragraph still occupies — no tokens, but as tall as
|
|
3400
3527
|
* the paragraph mark's own font (§17.3.1.31 `w:rPr` on the `w:pPr`, which is
|
|
3401
3528
|
* exactly the run properties Word keeps for a paragraph that holds no runs).
|
|
@@ -3682,17 +3809,18 @@ function mendSplitSyllables(runs) {
|
|
|
3682
3809
|
function charColours(options, paragraph, faces, resolved, run, drawn) {
|
|
3683
3810
|
const from = run.charProperties;
|
|
3684
3811
|
if (!from) return void 0;
|
|
3812
|
+
const pieces = drawn === run.text ? void 0 : drawnPieces(faces, run.text);
|
|
3685
3813
|
const hexOf = /* @__PURE__ */ new Map([[run.properties, resolved.colorHex]]);
|
|
3686
3814
|
const out = [];
|
|
3687
|
-
|
|
3688
|
-
for (
|
|
3689
|
-
const props = from[i
|
|
3815
|
+
const count = [...run.text].length;
|
|
3816
|
+
for (let i = 0; i < count; i++) {
|
|
3817
|
+
const props = from[i] ?? run.properties;
|
|
3690
3818
|
let hex = hexOf.get(props);
|
|
3691
3819
|
if (hex === void 0) {
|
|
3692
3820
|
hex = resolveRunProperties(props, paragraph.properties, options.styles).colorHex;
|
|
3693
3821
|
hexOf.set(props, hex);
|
|
3694
3822
|
}
|
|
3695
|
-
const letters =
|
|
3823
|
+
const letters = pieces ? [...pieces[i]].length : 1;
|
|
3696
3824
|
for (let k = 0; k < letters; k++) out.push(hex);
|
|
3697
3825
|
}
|
|
3698
3826
|
return out.some((hex) => hex !== resolved.colorHex) ? out : void 0;
|
|
@@ -4207,7 +4335,7 @@ function lastCodePoint(s) {
|
|
|
4207
4335
|
const chars = [...s];
|
|
4208
4336
|
return chars.length > 0 ? chars[chars.length - 1].codePointAt(0) : 0;
|
|
4209
4337
|
}
|
|
4210
|
-
function paragraphItemStream(tokens, hyphenator, maxLineWidthPt) {
|
|
4338
|
+
function paragraphItemStream(tokens, hyphenator, maxLineWidthPt, squeeze = true) {
|
|
4211
4339
|
const entries = [];
|
|
4212
4340
|
let prevBoxEndCp = null;
|
|
4213
4341
|
let prevWasImage = false;
|
|
@@ -4254,7 +4382,7 @@ function paragraphItemStream(tokens, hyphenator, maxLineWidthPt) {
|
|
|
4254
4382
|
type: "glue",
|
|
4255
4383
|
width: tok.widthPt,
|
|
4256
4384
|
stretch: tok.widthPt * .6,
|
|
4257
|
-
shrink: tok.widthPt * GLUE_SHRINK_RATIO
|
|
4385
|
+
shrink: squeeze ? tok.widthPt * GLUE_SHRINK_RATIO : 0
|
|
4258
4386
|
} : {
|
|
4259
4387
|
type: "box",
|
|
4260
4388
|
width: tok.widthPt
|
|
@@ -4606,7 +4734,9 @@ function withLeadingTabWidths(tokens, resolved, firstLineWidth) {
|
|
|
4606
4734
|
function wrap(tokens, firstLineWidth, otherWidth, resolved, hyphenator, profile, leading, noExpandShiftReturn, lineWidths) {
|
|
4607
4735
|
if (tokens.length === 0) return [];
|
|
4608
4736
|
const widths = lineWidths ?? [firstLineWidth, otherWidth];
|
|
4609
|
-
const
|
|
4737
|
+
const measured = withLeadingTabWidths(tokens, resolved, widths[0] ?? firstLineWidth);
|
|
4738
|
+
const justified = resolved.alignment === "both" || resolved.alignment === "distribute";
|
|
4739
|
+
const entries = paragraphItemStream(measured, hyphenator, Math.max(0, ...widths), justified);
|
|
4610
4740
|
const items = entries.map((e) => e.item);
|
|
4611
4741
|
const breaks = profile === "ream" ? breakLines(items, widths).breaks : greedyBreakLines(items, widths);
|
|
4612
4742
|
const buildLines = (at) => {
|
|
@@ -15,6 +15,12 @@ export interface EmbedTtfOptions {
|
|
|
15
15
|
* sign's contextual form — so that /ToUnicode names them too.
|
|
16
16
|
*/
|
|
17
17
|
readonly glyphText?: ReadonlyMap<number, string>;
|
|
18
|
+
/**
|
|
19
|
+
* The character each glyph that several characters share was drawn for —
|
|
20
|
+
* the Cyrillic schwa, say, where the face draws the Latin one with the same
|
|
21
|
+
* glyph — so that /ToUnicode names the one the page means.
|
|
22
|
+
*/
|
|
23
|
+
readonly glyphChars?: ReadonlyMap<number, number>;
|
|
18
24
|
}
|
|
19
25
|
/** The result of {@link embedTtfFont}: the Type 0 font reference plus measurement/encoding helpers. */
|
|
20
26
|
export interface EmbeddedFont {
|
package/dist/esm/pdf/cid-font.js
CHANGED
|
@@ -58,7 +58,7 @@ function embedTtfFont(doc, parsed, options = {}) {
|
|
|
58
58
|
W: widthRuns.flatMap(([first, ws]) => [first, ws]),
|
|
59
59
|
CIDToGIDMap: name("Identity")
|
|
60
60
|
}));
|
|
61
|
-
const toUnicodeRef = doc.add(deflatedStream({}, buildToUnicodeCMap(parsed, subsetGids, options.glyphText)));
|
|
61
|
+
const toUnicodeRef = doc.add(deflatedStream({}, buildToUnicodeCMap(parsed, subsetGids, options.glyphText, options.glyphChars)));
|
|
62
62
|
const type0Ref = doc.add(dict({
|
|
63
63
|
Type: name("Font"),
|
|
64
64
|
Subtype: name("Type0"),
|
|
@@ -127,7 +127,7 @@ function codeRank(cp) {
|
|
|
127
127
|
if (cp >= 64256 && cp <= 65023 || cp >= 65136 && cp <= 65279) return 1;
|
|
128
128
|
return 0;
|
|
129
129
|
}
|
|
130
|
-
function buildToUnicodeCMap(parsed, subsetGids, glyphText) {
|
|
130
|
+
function buildToUnicodeCMap(parsed, subsetGids, glyphText, glyphChars) {
|
|
131
131
|
const inSubset = subsetGids ? new Set(subsetGids) : void 0;
|
|
132
132
|
const gidToCps = /* @__PURE__ */ new Map();
|
|
133
133
|
const order = [];
|
|
@@ -143,6 +143,7 @@ function buildToUnicodeCMap(parsed, subsetGids, glyphText) {
|
|
|
143
143
|
gidToCps.set(gid, [cp]);
|
|
144
144
|
order.push(gid);
|
|
145
145
|
}
|
|
146
|
+
for (const [gid, cp] of glyphChars ?? []) if (gidToCps.get(gid)?.length === 1 && parsed.glyphForCodepoint(cp) === gid) gidToCps.set(gid, [cp]);
|
|
146
147
|
for (const [gid, cps] of gidToCps) {
|
|
147
148
|
const letters = cps.length === 1 ? lettersForLigature(cps[0]) : void 0;
|
|
148
149
|
if (letters !== void 0) gidToCps.set(gid, [...letters].map((c) => c.codePointAt(0)));
|
|
@@ -524,7 +524,8 @@ function embedFontResources(doc, laid, pdfaProfile) {
|
|
|
524
524
|
out.set(variant, embedTtfFont(doc, res.parsed, {
|
|
525
525
|
usedGids: res.gids,
|
|
526
526
|
cidSet,
|
|
527
|
-
...res.glyphText ? { glyphText: res.glyphText } : {}
|
|
527
|
+
...res.glyphText ? { glyphText: res.glyphText } : {},
|
|
528
|
+
...res.glyphChars ? { glyphChars: res.glyphChars } : {}
|
|
528
529
|
}));
|
|
529
530
|
}
|
|
530
531
|
return out;
|
|
@@ -682,7 +683,7 @@ function emitPageContent(page, tagging, gradientNames, alphaStateNames, duotoneS
|
|
|
682
683
|
let lastTz = 100;
|
|
683
684
|
/** A run's letter spacing, in the text space `Tz` scales (§9.4.4). */
|
|
684
685
|
const spacingOf = (tok) => {
|
|
685
|
-
const tz = Math.round((tok.synthetic?.widthScale ?? 1) * (tok.resolvedRun.widthScale ?? 1) *
|
|
686
|
+
const tz = Math.round((tok.synthetic?.widthScale ?? 1) * (tok.resolvedRun.widthScale ?? 1) * 1e3) / 10;
|
|
686
687
|
return (tok.resolvedRun.letterSpacingPt ?? 0) / (tz > 0 ? tz / 100 : 1);
|
|
687
688
|
};
|
|
688
689
|
/**
|
|
@@ -744,7 +745,7 @@ function emitPageContent(page, tagging, gradientNames, alphaStateNames, duotoneS
|
|
|
744
745
|
lastStroke = outline.colorHex;
|
|
745
746
|
}
|
|
746
747
|
const scale = (tok.synthetic?.widthScale ?? 1) * (tok.resolvedRun.widthScale ?? 1);
|
|
747
|
-
const tz = Math.round(scale *
|
|
748
|
+
const tz = Math.round(scale * 1e3) / 10;
|
|
748
749
|
if (tz !== lastTz) {
|
|
749
750
|
out.push(`${formatNumber(tz)} Tz`);
|
|
750
751
|
lastTz = tz;
|
|
@@ -547,6 +547,335 @@ var GLYPHS = {
|
|
|
547
547
|
zero: "0",
|
|
548
548
|
zeta: "ζ"
|
|
549
549
|
};
|
|
550
|
+
var CYRILLIC = /* @__PURE__ */ new Map([
|
|
551
|
+
["afii10023", 1025],
|
|
552
|
+
["Iocyrillic", 1025],
|
|
553
|
+
["afii10051", 1026],
|
|
554
|
+
["Djecyrillic", 1026],
|
|
555
|
+
["afii10052", 1027],
|
|
556
|
+
["Gjecyrillic", 1027],
|
|
557
|
+
["afii10053", 1028],
|
|
558
|
+
["Ecyrillic", 1028],
|
|
559
|
+
["afii10054", 1029],
|
|
560
|
+
["Dzecyrillic", 1029],
|
|
561
|
+
["afii10055", 1030],
|
|
562
|
+
["Icyrillic", 1030],
|
|
563
|
+
["afii10056", 1031],
|
|
564
|
+
["Yicyrillic", 1031],
|
|
565
|
+
["afii10057", 1032],
|
|
566
|
+
["Jecyrillic", 1032],
|
|
567
|
+
["afii10058", 1033],
|
|
568
|
+
["Ljecyrillic", 1033],
|
|
569
|
+
["afii10059", 1034],
|
|
570
|
+
["Njecyrillic", 1034],
|
|
571
|
+
["afii10060", 1035],
|
|
572
|
+
["Tshecyrillic", 1035],
|
|
573
|
+
["afii10061", 1036],
|
|
574
|
+
["Kjecyrillic", 1036],
|
|
575
|
+
["afii10062", 1038],
|
|
576
|
+
["Ushortcyrillic", 1038],
|
|
577
|
+
["afii10145", 1039],
|
|
578
|
+
["Dzhecyrillic", 1039],
|
|
579
|
+
["Acyrillic", 1040],
|
|
580
|
+
["afii10017", 1040],
|
|
581
|
+
["afii10018", 1041],
|
|
582
|
+
["Becyrillic", 1041],
|
|
583
|
+
["afii10019", 1042],
|
|
584
|
+
["Vecyrillic", 1042],
|
|
585
|
+
["afii10020", 1043],
|
|
586
|
+
["Gecyrillic", 1043],
|
|
587
|
+
["afii10021", 1044],
|
|
588
|
+
["Decyrillic", 1044],
|
|
589
|
+
["afii10022", 1045],
|
|
590
|
+
["Iecyrillic", 1045],
|
|
591
|
+
["afii10024", 1046],
|
|
592
|
+
["Zhecyrillic", 1046],
|
|
593
|
+
["afii10025", 1047],
|
|
594
|
+
["Zecyrillic", 1047],
|
|
595
|
+
["afii10026", 1048],
|
|
596
|
+
["Iicyrillic", 1048],
|
|
597
|
+
["afii10027", 1049],
|
|
598
|
+
["Iishortcyrillic", 1049],
|
|
599
|
+
["afii10028", 1050],
|
|
600
|
+
["Kacyrillic", 1050],
|
|
601
|
+
["afii10029", 1051],
|
|
602
|
+
["Elcyrillic", 1051],
|
|
603
|
+
["afii10030", 1052],
|
|
604
|
+
["Emcyrillic", 1052],
|
|
605
|
+
["afii10031", 1053],
|
|
606
|
+
["Encyrillic", 1053],
|
|
607
|
+
["afii10032", 1054],
|
|
608
|
+
["Ocyrillic", 1054],
|
|
609
|
+
["afii10033", 1055],
|
|
610
|
+
["Pecyrillic", 1055],
|
|
611
|
+
["afii10034", 1056],
|
|
612
|
+
["Ercyrillic", 1056],
|
|
613
|
+
["afii10035", 1057],
|
|
614
|
+
["Escyrillic", 1057],
|
|
615
|
+
["afii10036", 1058],
|
|
616
|
+
["Tecyrillic", 1058],
|
|
617
|
+
["afii10037", 1059],
|
|
618
|
+
["Ucyrillic", 1059],
|
|
619
|
+
["afii10038", 1060],
|
|
620
|
+
["Efcyrillic", 1060],
|
|
621
|
+
["afii10039", 1061],
|
|
622
|
+
["Khacyrillic", 1061],
|
|
623
|
+
["afii10040", 1062],
|
|
624
|
+
["Tsecyrillic", 1062],
|
|
625
|
+
["afii10041", 1063],
|
|
626
|
+
["Checyrillic", 1063],
|
|
627
|
+
["afii10042", 1064],
|
|
628
|
+
["Shacyrillic", 1064],
|
|
629
|
+
["afii10043", 1065],
|
|
630
|
+
["Shchacyrillic", 1065],
|
|
631
|
+
["afii10044", 1066],
|
|
632
|
+
["Hardsigncyrillic", 1066],
|
|
633
|
+
["afii10045", 1067],
|
|
634
|
+
["Yericyrillic", 1067],
|
|
635
|
+
["afii10046", 1068],
|
|
636
|
+
["Softsigncyrillic", 1068],
|
|
637
|
+
["afii10047", 1069],
|
|
638
|
+
["Ereversedcyrillic", 1069],
|
|
639
|
+
["afii10048", 1070],
|
|
640
|
+
["IUcyrillic", 1070],
|
|
641
|
+
["afii10049", 1071],
|
|
642
|
+
["IAcyrillic", 1071],
|
|
643
|
+
["acyrillic", 1072],
|
|
644
|
+
["afii10065", 1072],
|
|
645
|
+
["afii10066", 1073],
|
|
646
|
+
["becyrillic", 1073],
|
|
647
|
+
["afii10067", 1074],
|
|
648
|
+
["vecyrillic", 1074],
|
|
649
|
+
["afii10068", 1075],
|
|
650
|
+
["gecyrillic", 1075],
|
|
651
|
+
["afii10069", 1076],
|
|
652
|
+
["decyrillic", 1076],
|
|
653
|
+
["afii10070", 1077],
|
|
654
|
+
["iecyrillic", 1077],
|
|
655
|
+
["afii10072", 1078],
|
|
656
|
+
["zhecyrillic", 1078],
|
|
657
|
+
["afii10073", 1079],
|
|
658
|
+
["zecyrillic", 1079],
|
|
659
|
+
["afii10074", 1080],
|
|
660
|
+
["iicyrillic", 1080],
|
|
661
|
+
["afii10075", 1081],
|
|
662
|
+
["iishortcyrillic", 1081],
|
|
663
|
+
["afii10076", 1082],
|
|
664
|
+
["kacyrillic", 1082],
|
|
665
|
+
["afii10077", 1083],
|
|
666
|
+
["elcyrillic", 1083],
|
|
667
|
+
["afii10078", 1084],
|
|
668
|
+
["emcyrillic", 1084],
|
|
669
|
+
["afii10079", 1085],
|
|
670
|
+
["encyrillic", 1085],
|
|
671
|
+
["afii10080", 1086],
|
|
672
|
+
["ocyrillic", 1086],
|
|
673
|
+
["afii10081", 1087],
|
|
674
|
+
["pecyrillic", 1087],
|
|
675
|
+
["afii10082", 1088],
|
|
676
|
+
["ercyrillic", 1088],
|
|
677
|
+
["afii10083", 1089],
|
|
678
|
+
["escyrillic", 1089],
|
|
679
|
+
["afii10084", 1090],
|
|
680
|
+
["tecyrillic", 1090],
|
|
681
|
+
["afii10085", 1091],
|
|
682
|
+
["ucyrillic", 1091],
|
|
683
|
+
["afii10086", 1092],
|
|
684
|
+
["efcyrillic", 1092],
|
|
685
|
+
["afii10087", 1093],
|
|
686
|
+
["khacyrillic", 1093],
|
|
687
|
+
["afii10088", 1094],
|
|
688
|
+
["tsecyrillic", 1094],
|
|
689
|
+
["afii10089", 1095],
|
|
690
|
+
["checyrillic", 1095],
|
|
691
|
+
["afii10090", 1096],
|
|
692
|
+
["shacyrillic", 1096],
|
|
693
|
+
["afii10091", 1097],
|
|
694
|
+
["shchacyrillic", 1097],
|
|
695
|
+
["afii10092", 1098],
|
|
696
|
+
["hardsigncyrillic", 1098],
|
|
697
|
+
["afii10093", 1099],
|
|
698
|
+
["yericyrillic", 1099],
|
|
699
|
+
["afii10094", 1100],
|
|
700
|
+
["softsigncyrillic", 1100],
|
|
701
|
+
["afii10095", 1101],
|
|
702
|
+
["ereversedcyrillic", 1101],
|
|
703
|
+
["afii10096", 1102],
|
|
704
|
+
["iucyrillic", 1102],
|
|
705
|
+
["afii10097", 1103],
|
|
706
|
+
["iacyrillic", 1103],
|
|
707
|
+
["afii10071", 1105],
|
|
708
|
+
["iocyrillic", 1105],
|
|
709
|
+
["afii10099", 1106],
|
|
710
|
+
["djecyrillic", 1106],
|
|
711
|
+
["afii10100", 1107],
|
|
712
|
+
["gjecyrillic", 1107],
|
|
713
|
+
["afii10101", 1108],
|
|
714
|
+
["ecyrillic", 1108],
|
|
715
|
+
["afii10102", 1109],
|
|
716
|
+
["dzecyrillic", 1109],
|
|
717
|
+
["afii10103", 1110],
|
|
718
|
+
["icyrillic", 1110],
|
|
719
|
+
["afii10104", 1111],
|
|
720
|
+
["yicyrillic", 1111],
|
|
721
|
+
["afii10105", 1112],
|
|
722
|
+
["jecyrillic", 1112],
|
|
723
|
+
["afii10106", 1113],
|
|
724
|
+
["ljecyrillic", 1113],
|
|
725
|
+
["afii10107", 1114],
|
|
726
|
+
["njecyrillic", 1114],
|
|
727
|
+
["afii10108", 1115],
|
|
728
|
+
["tshecyrillic", 1115],
|
|
729
|
+
["afii10109", 1116],
|
|
730
|
+
["kjecyrillic", 1116],
|
|
731
|
+
["afii10110", 1118],
|
|
732
|
+
["ushortcyrillic", 1118],
|
|
733
|
+
["afii10193", 1119],
|
|
734
|
+
["dzhecyrillic", 1119],
|
|
735
|
+
["Omegacyrillic", 1120],
|
|
736
|
+
["omegacyrillic", 1121],
|
|
737
|
+
["afii10146", 1122],
|
|
738
|
+
["Yatcyrillic", 1122],
|
|
739
|
+
["afii10194", 1123],
|
|
740
|
+
["yatcyrillic", 1123],
|
|
741
|
+
["Eiotifiedcyrillic", 1124],
|
|
742
|
+
["eiotifiedcyrillic", 1125],
|
|
743
|
+
["Yuslittlecyrillic", 1126],
|
|
744
|
+
["yuslittlecyrillic", 1127],
|
|
745
|
+
["Yuslittleiotifiedcyrillic", 1128],
|
|
746
|
+
["yuslittleiotifiedcyrillic", 1129],
|
|
747
|
+
["Yusbigcyrillic", 1130],
|
|
748
|
+
["yusbigcyrillic", 1131],
|
|
749
|
+
["Yusbigiotifiedcyrillic", 1132],
|
|
750
|
+
["yusbigiotifiedcyrillic", 1133],
|
|
751
|
+
["Ksicyrillic", 1134],
|
|
752
|
+
["ksicyrillic", 1135],
|
|
753
|
+
["Psicyrillic", 1136],
|
|
754
|
+
["psicyrillic", 1137],
|
|
755
|
+
["afii10147", 1138],
|
|
756
|
+
["Fitacyrillic", 1138],
|
|
757
|
+
["afii10195", 1139],
|
|
758
|
+
["fitacyrillic", 1139],
|
|
759
|
+
["afii10148", 1140],
|
|
760
|
+
["Izhitsacyrillic", 1140],
|
|
761
|
+
["afii10196", 1141],
|
|
762
|
+
["izhitsacyrillic", 1141],
|
|
763
|
+
["Izhitsadblgravecyrillic", 1142],
|
|
764
|
+
["izhitsadblgravecyrillic", 1143],
|
|
765
|
+
["Ukcyrillic", 1144],
|
|
766
|
+
["ukcyrillic", 1145],
|
|
767
|
+
["Omegaroundcyrillic", 1146],
|
|
768
|
+
["omegaroundcyrillic", 1147],
|
|
769
|
+
["Omegatitlocyrillic", 1148],
|
|
770
|
+
["omegatitlocyrillic", 1149],
|
|
771
|
+
["Otcyrillic", 1150],
|
|
772
|
+
["otcyrillic", 1151],
|
|
773
|
+
["Koppacyrillic", 1152],
|
|
774
|
+
["koppacyrillic", 1153],
|
|
775
|
+
["thousandcyrillic", 1154],
|
|
776
|
+
["titlocyrilliccmb", 1155],
|
|
777
|
+
["palatalizationcyrilliccmb", 1156],
|
|
778
|
+
["dasiapneumatacyrilliccmb", 1157],
|
|
779
|
+
["psilipneumatacyrilliccmb", 1158],
|
|
780
|
+
["afii10050", 1168],
|
|
781
|
+
["Gheupturncyrillic", 1168],
|
|
782
|
+
["afii10098", 1169],
|
|
783
|
+
["gheupturncyrillic", 1169],
|
|
784
|
+
["Ghestrokecyrillic", 1170],
|
|
785
|
+
["ghestrokecyrillic", 1171],
|
|
786
|
+
["Ghemiddlehookcyrillic", 1172],
|
|
787
|
+
["ghemiddlehookcyrillic", 1173],
|
|
788
|
+
["Zhedescendercyrillic", 1174],
|
|
789
|
+
["zhedescendercyrillic", 1175],
|
|
790
|
+
["Zedescendercyrillic", 1176],
|
|
791
|
+
["zedescendercyrillic", 1177],
|
|
792
|
+
["Kadescendercyrillic", 1178],
|
|
793
|
+
["kadescendercyrillic", 1179],
|
|
794
|
+
["Kaverticalstrokecyrillic", 1180],
|
|
795
|
+
["kaverticalstrokecyrillic", 1181],
|
|
796
|
+
["Kastrokecyrillic", 1182],
|
|
797
|
+
["kastrokecyrillic", 1183],
|
|
798
|
+
["Kabashkircyrillic", 1184],
|
|
799
|
+
["kabashkircyrillic", 1185],
|
|
800
|
+
["Endescendercyrillic", 1186],
|
|
801
|
+
["endescendercyrillic", 1187],
|
|
802
|
+
["Enghecyrillic", 1188],
|
|
803
|
+
["enghecyrillic", 1189],
|
|
804
|
+
["Pemiddlehookcyrillic", 1190],
|
|
805
|
+
["pemiddlehookcyrillic", 1191],
|
|
806
|
+
["Haabkhasiancyrillic", 1192],
|
|
807
|
+
["haabkhasiancyrillic", 1193],
|
|
808
|
+
["Esdescendercyrillic", 1194],
|
|
809
|
+
["esdescendercyrillic", 1195],
|
|
810
|
+
["Tedescendercyrillic", 1196],
|
|
811
|
+
["tedescendercyrillic", 1197],
|
|
812
|
+
["Ustraightcyrillic", 1198],
|
|
813
|
+
["ustraightcyrillic", 1199],
|
|
814
|
+
["Ustraightstrokecyrillic", 1200],
|
|
815
|
+
["ustraightstrokecyrillic", 1201],
|
|
816
|
+
["Hadescendercyrillic", 1202],
|
|
817
|
+
["hadescendercyrillic", 1203],
|
|
818
|
+
["Tetsecyrillic", 1204],
|
|
819
|
+
["tetsecyrillic", 1205],
|
|
820
|
+
["Chedescendercyrillic", 1206],
|
|
821
|
+
["chedescendercyrillic", 1207],
|
|
822
|
+
["Cheverticalstrokecyrillic", 1208],
|
|
823
|
+
["cheverticalstrokecyrillic", 1209],
|
|
824
|
+
["Shhacyrillic", 1210],
|
|
825
|
+
["shhacyrillic", 1211],
|
|
826
|
+
["Cheabkhasiancyrillic", 1212],
|
|
827
|
+
["cheabkhasiancyrillic", 1213],
|
|
828
|
+
["Chedescenderabkhasiancyrillic", 1214],
|
|
829
|
+
["chedescenderabkhasiancyrillic", 1215],
|
|
830
|
+
["palochkacyrillic", 1216],
|
|
831
|
+
["Zhebrevecyrillic", 1217],
|
|
832
|
+
["zhebrevecyrillic", 1218],
|
|
833
|
+
["Kahookcyrillic", 1219],
|
|
834
|
+
["kahookcyrillic", 1220],
|
|
835
|
+
["Enhookcyrillic", 1223],
|
|
836
|
+
["enhookcyrillic", 1224],
|
|
837
|
+
["Chekhakassiancyrillic", 1227],
|
|
838
|
+
["chekhakassiancyrillic", 1228],
|
|
839
|
+
["Abrevecyrillic", 1232],
|
|
840
|
+
["abrevecyrillic", 1233],
|
|
841
|
+
["Adieresiscyrillic", 1234],
|
|
842
|
+
["adieresiscyrillic", 1235],
|
|
843
|
+
["Aiecyrillic", 1236],
|
|
844
|
+
["aiecyrillic", 1237],
|
|
845
|
+
["Iebrevecyrillic", 1238],
|
|
846
|
+
["iebrevecyrillic", 1239],
|
|
847
|
+
["Schwacyrillic", 1240],
|
|
848
|
+
["afii10846", 1241],
|
|
849
|
+
["schwacyrillic", 1241],
|
|
850
|
+
["Schwadieresiscyrillic", 1242],
|
|
851
|
+
["schwadieresiscyrillic", 1243],
|
|
852
|
+
["Zhedieresiscyrillic", 1244],
|
|
853
|
+
["zhedieresiscyrillic", 1245],
|
|
854
|
+
["Zedieresiscyrillic", 1246],
|
|
855
|
+
["zedieresiscyrillic", 1247],
|
|
856
|
+
["Dzeabkhasiancyrillic", 1248],
|
|
857
|
+
["dzeabkhasiancyrillic", 1249],
|
|
858
|
+
["Imacroncyrillic", 1250],
|
|
859
|
+
["imacroncyrillic", 1251],
|
|
860
|
+
["Idieresiscyrillic", 1252],
|
|
861
|
+
["idieresiscyrillic", 1253],
|
|
862
|
+
["Odieresiscyrillic", 1254],
|
|
863
|
+
["odieresiscyrillic", 1255],
|
|
864
|
+
["Obarredcyrillic", 1256],
|
|
865
|
+
["obarredcyrillic", 1257],
|
|
866
|
+
["Obarreddieresiscyrillic", 1258],
|
|
867
|
+
["obarreddieresiscyrillic", 1259],
|
|
868
|
+
["Umacroncyrillic", 1262],
|
|
869
|
+
["umacroncyrillic", 1263],
|
|
870
|
+
["Udieresiscyrillic", 1264],
|
|
871
|
+
["udieresiscyrillic", 1265],
|
|
872
|
+
["Uhungarumlautcyrillic", 1266],
|
|
873
|
+
["uhungarumlautcyrillic", 1267],
|
|
874
|
+
["Chedieresiscyrillic", 1268],
|
|
875
|
+
["chedieresiscyrillic", 1269],
|
|
876
|
+
["Yerudieresiscyrillic", 1272],
|
|
877
|
+
["yerudieresiscyrillic", 1273]
|
|
878
|
+
]);
|
|
550
879
|
/**
|
|
551
880
|
* The text a glyph name stands for, or `undefined` when the name says nothing.
|
|
552
881
|
*
|
|
@@ -561,6 +890,8 @@ function textForGlyphName(name) {
|
|
|
561
890
|
}
|
|
562
891
|
const known = GLYPHS[base];
|
|
563
892
|
if (known !== void 0) return known;
|
|
893
|
+
const cyrillic = CYRILLIC.get(base);
|
|
894
|
+
if (cyrillic !== void 0) return String.fromCodePoint(cyrillic);
|
|
564
895
|
if (base.length === 1) return base;
|
|
565
896
|
const uni = /^uni((?:[0-9A-Fa-f]{4})+)$/u.exec(base);
|
|
566
897
|
if (uni) {
|