reamkit 1.26.0 → 1.28.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 (85) hide show
  1. package/README.md +14 -8
  2. package/dist/esm/core/converter/ream.d.ts +0 -9
  3. package/dist/esm/core/converter/ream.js +0 -1
  4. package/dist/esm/core/document-model/types.d.ts +5 -3
  5. package/dist/esm/core/font/index.d.ts +1 -0
  6. package/dist/esm/core/font/ligatures.d.ts +17 -0
  7. package/dist/esm/core/font/ligatures.js +49 -0
  8. package/dist/esm/core/font/ttf-parser.d.ts +2 -1
  9. package/dist/esm/core/font/ttf-parser.js +11 -2
  10. package/dist/esm/core/fonts/remote-fonts.d.ts +1 -1
  11. package/dist/esm/core/fonts/remote-fonts.js +47 -2
  12. package/dist/esm/core/fonts/scripts.js +10 -5
  13. package/dist/esm/excel/header-footer.js +53 -8
  14. package/dist/esm/layout/styled-layout.js +53 -3
  15. package/dist/esm/pdf/cid-font.js +35 -8
  16. package/dist/esm/pdf-reader/annot-draw.d.ts +65 -0
  17. package/dist/esm/pdf-reader/annot-draw.js +487 -0
  18. package/dist/esm/pdf-reader/annots.d.ts +0 -12
  19. package/dist/esm/pdf-reader/annots.js +30 -4
  20. package/dist/esm/pdf-reader/ccitt.d.ts +20 -3
  21. package/dist/esm/pdf-reader/ccitt.js +102 -6
  22. package/dist/esm/pdf-reader/cff-outline.d.ts +36 -0
  23. package/dist/esm/pdf-reader/cff-outline.js +1122 -0
  24. package/dist/esm/pdf-reader/cie-color.d.ts +33 -0
  25. package/dist/esm/pdf-reader/cie-color.js +112 -0
  26. package/dist/esm/pdf-reader/cmap.js +5 -2
  27. package/dist/esm/pdf-reader/content.d.ts +123 -3
  28. package/dist/esm/pdf-reader/content.js +232 -54
  29. package/dist/esm/pdf-reader/dingbats.d.ts +11 -0
  30. package/dist/esm/pdf-reader/dingbats.js +1033 -0
  31. package/dist/esm/pdf-reader/display.d.ts +1 -1
  32. package/dist/esm/pdf-reader/display.js +61 -6
  33. package/dist/esm/pdf-reader/document.d.ts +6 -0
  34. package/dist/esm/pdf-reader/document.js +55 -10
  35. package/dist/esm/pdf-reader/embedded-fonts.d.ts +23 -3
  36. package/dist/esm/pdf-reader/embedded-fonts.js +36 -4
  37. package/dist/esm/pdf-reader/encodings.d.ts +25 -0
  38. package/dist/esm/pdf-reader/encodings.js +110 -0
  39. package/dist/esm/pdf-reader/flow-build.d.ts +19 -5
  40. package/dist/esm/pdf-reader/flow-build.js +111 -11
  41. package/dist/esm/pdf-reader/font.js +403 -21
  42. package/dist/esm/pdf-reader/function.d.ts +16 -0
  43. package/dist/esm/pdf-reader/function.js +414 -0
  44. package/dist/esm/pdf-reader/glyf-outline.d.ts +43 -0
  45. package/dist/esm/pdf-reader/glyf-outline.js +351 -0
  46. package/dist/esm/pdf-reader/glyph-names.js +20 -0
  47. package/dist/esm/pdf-reader/icc.d.ts +10 -0
  48. package/dist/esm/pdf-reader/icc.js +210 -0
  49. package/dist/esm/pdf-reader/image-decode.d.ts +9 -4
  50. package/dist/esm/pdf-reader/image-decode.js +274 -72
  51. package/dist/esm/pdf-reader/images.d.ts +18 -0
  52. package/dist/esm/pdf-reader/images.js +154 -11
  53. package/dist/esm/pdf-reader/jbig2.d.ts +23 -0
  54. package/dist/esm/pdf-reader/jbig2.js +126 -32
  55. package/dist/esm/pdf-reader/layout.d.ts +32 -0
  56. package/dist/esm/pdf-reader/layout.js +1316 -64
  57. package/dist/esm/pdf-reader/lexer.d.ts +2 -0
  58. package/dist/esm/pdf-reader/lexer.js +4 -0
  59. package/dist/esm/pdf-reader/math-rows.d.ts +23 -0
  60. package/dist/esm/pdf-reader/math-rows.js +198 -0
  61. package/dist/esm/pdf-reader/optional-content.d.ts +36 -0
  62. package/dist/esm/pdf-reader/optional-content.js +93 -0
  63. package/dist/esm/pdf-reader/predefined-cmap.d.ts +21 -0
  64. package/dist/esm/pdf-reader/predefined-cmap.js +102 -0
  65. package/dist/esm/pdf-reader/reader.d.ts +6 -6
  66. package/dist/esm/pdf-reader/reader.js +102 -16
  67. package/dist/esm/pdf-reader/shading.d.ts +139 -8
  68. package/dist/esm/pdf-reader/shading.js +309 -39
  69. package/dist/esm/pdf-reader/standard-metrics.d.ts +8 -0
  70. package/dist/esm/pdf-reader/standard-metrics.js +18 -0
  71. package/dist/esm/pdf-reader/standard-widths.d.ts +20 -0
  72. package/dist/esm/pdf-reader/standard-widths.js +62 -0
  73. package/dist/esm/pdf-reader/stream-filters.d.ts +6 -0
  74. package/dist/esm/pdf-reader/stream-filters.js +67 -0
  75. package/dist/esm/pdf-reader/tagged.js +204 -32
  76. package/dist/esm/pdf-reader/text-rules.d.ts +16 -0
  77. package/dist/esm/pdf-reader/text-rules.js +185 -0
  78. package/dist/esm/pdf-reader/text.js +157 -4
  79. package/dist/esm/pdf-reader/type1-outline.d.ts +21 -0
  80. package/dist/esm/pdf-reader/type1-outline.js +576 -0
  81. package/dist/esm/pdf-reader/vector.d.ts +5 -0
  82. package/dist/esm/pdf-reader/vector.js +79 -27
  83. package/dist/esm/word/document-parser.js +4 -1
  84. package/dist/esm/word/docx-writer.js +74 -11
  85. package/package.json +1 -1
@@ -0,0 +1,185 @@
1
+ //#region src/pdf-reader/text-rules.ts
2
+ /** A rule no thicker than this is a line under words, not a box. */
3
+ var THICKEST_PT = 2;
4
+ /** …and no thinner than this: below it the page drew a seam, not a mark. */
5
+ var THINNEST_PT = .2;
6
+ /** …or than this fraction of the face it underlines, for a large one. */
7
+ var THICKEST_EM = .09;
8
+ /** How much of a run's advance a rule must cover to be that run's own. */
9
+ var COVERS = .6;
10
+ /**
11
+ * How far past the words it may run, in points, before it is a rule about
12
+ * something else.
13
+ *
14
+ * An underline begins and ends with the words it underlines; a table's cell
15
+ * border begins at the CELL, which is the text's own edge less the padding, and
16
+ * ends at the cell's other edge however short the text stops. TAMReview.pdf's
17
+ * tables are ruled 86.2 to 509.0 across a measure whose text stops well before
18
+ * it, and a proportional allowance let every one of them through.
19
+ */
20
+ var OVERHANG_PT = 2;
21
+ /** An underline sits within this fraction of the size below the baseline. */
22
+ var UNDER_EM = .35;
23
+ /** A strikeout crosses between these fractions of the size ABOVE it. */
24
+ var STRIKE_LOW = .15;
25
+ var STRIKE_HIGH = .5;
26
+ /**
27
+ * Read the underlines and strikeouts a page DREW onto the runs they mark.
28
+ *
29
+ * @param runs The page's runs, placed on the shown page.
30
+ * @param vectors The page's lifted paths, placed the same way.
31
+ * @returns The runs, marked; and the paths that became those marks.
32
+ */
33
+ function markDrawnRules(runs, vectors) {
34
+ const marks = /* @__PURE__ */ new Map();
35
+ const consumed = /* @__PURE__ */ new Set();
36
+ for (const { rule: v, parts } of joinRules(vectors)) {
37
+ const under = coveredRuns(runs, v, "under");
38
+ const through = under.length > 0 ? [] : coveredRuns(runs, v, "through");
39
+ const hit = under.length > 0 ? under : through;
40
+ if (hit.length === 0) continue;
41
+ const left = Math.min(...hit.map((r) => Math.min(r.x, r.endX)));
42
+ const right = Math.max(...hit.map((r) => Math.max(r.x, r.endX)));
43
+ if (!(right - left > 0)) continue;
44
+ if (left - v.minX > OVERHANG_PT || v.maxX - right > OVERHANG_PT) continue;
45
+ for (const run of hit) {
46
+ const had = marks.get(run) ?? {};
47
+ const hex = ruleHex(v);
48
+ marks.set(run, under.length > 0 && hex !== void 0 ? {
49
+ ...had,
50
+ underline: hex
51
+ } : {
52
+ ...had,
53
+ strike: true
54
+ });
55
+ }
56
+ for (const part of parts) consumed.add(part);
57
+ }
58
+ if (marks.size === 0) return {
59
+ runs: [...runs],
60
+ consumed
61
+ };
62
+ return {
63
+ runs: runs.map((run) => {
64
+ const mark = marks.get(run);
65
+ if (!mark) return run;
66
+ return {
67
+ ...run,
68
+ markup: {
69
+ ...run.markup,
70
+ ...mark.underline !== void 0 && run.markup?.underline === void 0 ? {
71
+ underline: "single",
72
+ underlineHex: mark.underline
73
+ } : {},
74
+ ...mark.strike === true ? { strike: true } : {}
75
+ }
76
+ };
77
+ }),
78
+ consumed
79
+ };
80
+ }
81
+ /** Two segments this far apart are still one line: a word space, no more. */
82
+ var JOIN_PT = 6;
83
+ /** Two segments within this of each other sit at the same height. */
84
+ var SAME_HEIGHT_PT = .5;
85
+ /**
86
+ * The rules, with the ones a page drew in PIECES joined back into one.
87
+ *
88
+ * An underline is a mark about a phrase, but a producer may stroke it a word at
89
+ * a time: TAMReview.pdf draws its copyright licence as six segments end to end.
90
+ * Matched one by one none of them covers enough of the long run it belongs to,
91
+ * so each was rejected and the phrase came back unmarked.
92
+ *
93
+ * Joined only along a straight, level line, with no more than a word space
94
+ * between the pieces — which is what a broken underline is and what a row of
95
+ * separate table rules is not.
96
+ */
97
+ function joinRules(vectors) {
98
+ const rules = vectors.filter((v) => isRule(v));
99
+ const byRow = /* @__PURE__ */ new Map();
100
+ for (const v of rules) {
101
+ const mid = (v.minY + v.maxY) / 2;
102
+ const key = `${ruleHex(v) ?? ""}@${String(Math.round(mid / SAME_HEIGHT_PT))}`;
103
+ const row = byRow.get(key);
104
+ if (row) row.push(v);
105
+ else byRow.set(key, [v]);
106
+ }
107
+ const out = [];
108
+ for (const row of byRow.values()) {
109
+ row.sort((a, b) => a.minX - b.minX);
110
+ let run = [];
111
+ const flush = () => {
112
+ if (run.length === 0) return;
113
+ const first = run[0];
114
+ out.push({
115
+ rule: {
116
+ ...first,
117
+ minX: Math.min(...run.map((v) => v.minX)),
118
+ maxX: Math.max(...run.map((v) => v.maxX)),
119
+ minY: Math.min(...run.map((v) => v.minY)),
120
+ maxY: Math.max(...run.map((v) => v.maxY))
121
+ },
122
+ parts: run
123
+ });
124
+ run = [];
125
+ };
126
+ for (const v of row) {
127
+ const last = run[run.length - 1];
128
+ if (last && v.minX - last.maxX > JOIN_PT) flush();
129
+ run.push(v);
130
+ }
131
+ flush();
132
+ }
133
+ return out;
134
+ }
135
+ /**
136
+ * A thin bar under words — filled OR stroked.
137
+ *
138
+ * A page draws an underline either way, and the stroked one is the commoner:
139
+ * TAMReview.pdf strokes its copyright licence with six zero-height segments,
140
+ * one per word. Read as a filled bar only, none of them was a mark at all —
141
+ * they stayed artwork, and when the words re-set the artwork stayed where it
142
+ * was drawn and came back crossing the line it should have sat under.
143
+ */
144
+ function isRule(v) {
145
+ if (v.gradient !== void 0) return false;
146
+ const stroked = v.strokeHex !== void 0 && v.fillHex === void 0;
147
+ const colour = stroked ? v.strokeHex : v.fillHex;
148
+ if (colour === void 0) return false;
149
+ if (colour === "FFFFFF") return false;
150
+ if (v.maxX - v.minX <= 2) return false;
151
+ if (stroked) {
152
+ if (v.maxY - v.minY > THICKEST_PT) return false;
153
+ return (v.lineWidth ?? 1) <= THICKEST_PT;
154
+ }
155
+ const h = v.maxY - v.minY;
156
+ return h >= THINNEST_PT && h <= THICKEST_PT;
157
+ }
158
+ /** The colour a rule marks in, whichever way the page drew it. */
159
+ function ruleHex(v) {
160
+ return v.fillHex ?? v.strokeHex;
161
+ }
162
+ /**
163
+ * The runs a rule marks: on one baseline, covered along their advance, and at
164
+ * the offset from that baseline the mark is drawn at.
165
+ */
166
+ function coveredRuns(runs, v, where) {
167
+ const out = [];
168
+ const mid = (v.minY + v.maxY) / 2;
169
+ for (const run of runs) {
170
+ const size = run.fontSizePt;
171
+ if (!(size > 0) || run.angleDeg !== void 0) continue;
172
+ if (v.maxY - v.minY > Math.max(THICKEST_PT, size * THICKEST_EM)) continue;
173
+ const below = run.y - mid;
174
+ if (!(where === "under" ? below > 0 && below < size * UNDER_EM : below < -size * STRIKE_LOW && below > -size * STRIKE_HIGH)) continue;
175
+ const left = Math.min(run.x, run.endX);
176
+ const right = Math.max(run.x, run.endX);
177
+ const advance = right - left;
178
+ if (!(advance > 0)) continue;
179
+ if (Math.min(right, v.maxX) - Math.max(left, v.minX) < advance * COVERS) continue;
180
+ out.push(run);
181
+ }
182
+ return out;
183
+ }
184
+ //#endregion
185
+ export { markDrawnRules };
@@ -1,6 +1,9 @@
1
1
  import { PDF_NULL, PdfName, PdfStream } from "../pdf/objects.js";
2
+ import { buildColorSpaceMap, buildShadingMap } from "./shading.js";
2
3
  import { IDENTITY, interpretContent, multiply } from "./content.js";
4
+ import { textMarkupOf } from "./annot-draw.js";
3
5
  import { collectPageAppearances } from "./annots.js";
6
+ import { hiddenProperties, hiddenXObject } from "./optional-content.js";
4
7
  import { buildContentFont } from "./font.js";
5
8
  import { patternTint } from "./pattern-tint.js";
6
9
  //#region src/pdf-reader/text.ts
@@ -21,17 +24,166 @@ function extractPageText(file, page) {
21
24
  collectRuns(file, page.resources, file.pageContent(page), IDENTITY, 0, /* @__PURE__ */ new Set(), runs);
22
25
  for (const appearance of collectPageAppearances(file, page)) collectRuns(file, appearance.resources ?? page.resources, file.streamData(appearance.stream), appearance.ctm, 1, new Set([appearance.stream]), runs);
23
26
  const links = collectLinks(file, page);
24
- if (links.length === 0) return runs;
25
- return runs.map((run) => {
27
+ const marks = collectTextMarkup(file, page);
28
+ const shown = withoutRestrikes(runs);
29
+ if (links.length === 0 && marks.length === 0) return shown;
30
+ return shown.flatMap((run) => {
26
31
  const link = links.find((l) => inRect(run.x, run.y, l.rect));
27
- return link ? {
32
+ const linked = link ? {
28
33
  ...run,
29
34
  href: link.href
30
35
  } : run;
36
+ const marked = marks.find((m) => m.quads.some((q) => touches(q, linked)));
37
+ if (!marked) return [linked];
38
+ const quad = marked.quads.find((q) => touches(q, linked));
39
+ return quad ? markedPieces(linked, quad, marked.mark) : [linked];
31
40
  });
32
41
  }
42
+ /**
43
+ * §12.5.6.10 — whether a marked quad reaches this run at all.
44
+ *
45
+ * The quad is a box round a run of text and the run is a baseline with an
46
+ * advance, so the test is the baseline falling inside the box's height while
47
+ * the two overlap horizontally by more than a hair.
48
+ */
49
+ function touches(q, run) {
50
+ if (run.y < q.y0 || run.y > q.y0 + q.h) return false;
51
+ const left = Math.min(run.x, run.endX);
52
+ const right = Math.max(run.x, run.endX);
53
+ return Math.min(right, q.x1) - Math.max(left, q.x0) > .5;
54
+ }
55
+ /**
56
+ * The run cut at the quad's edges, so only what the quad covers is marked.
57
+ *
58
+ * A quad round ONE WORD of a line must not claim the line: highlight_popup.pdf
59
+ * marks "PDF.js" in "Hello PDF.js World", which is one run, and the whole line
60
+ * came back highlighted. The run states its advance and its text and not where
61
+ * each glyph fell inside it, so the cut is made by proportion of the advance —
62
+ * a word off by a fraction of a letter where the face is proportional, against
63
+ * a line marked entirely wrongly.
64
+ */
65
+ function markedPieces(run, q, mark) {
66
+ const left = Math.min(run.x, run.endX);
67
+ const advance = Math.max(run.x, run.endX) - left;
68
+ const chars = [...run.text];
69
+ if (!(advance > 0) || chars.length === 0) return [{
70
+ ...run,
71
+ markup: mark
72
+ }];
73
+ const at = (x) => Math.max(0, Math.min(chars.length, Math.round((x - left) / advance * chars.length)));
74
+ const from = at(q.x0);
75
+ const to = at(q.x1);
76
+ if (from <= 0 && to >= chars.length) return [{
77
+ ...run,
78
+ markup: mark
79
+ }];
80
+ if (to <= from) return [run];
81
+ const per = advance / chars.length;
82
+ const piece = (a, b, marked) => ({
83
+ ...run,
84
+ text: chars.slice(a, b).join(""),
85
+ x: left + a * per,
86
+ endX: left + b * per,
87
+ ...marked ? { markup: mark } : {}
88
+ });
89
+ return [
90
+ ...from > 0 ? [piece(0, from, false)] : [],
91
+ piece(from, to, true),
92
+ ...to < chars.length ? [piece(to, chars.length, false)] : []
93
+ ];
94
+ }
95
+ /** Every text-markup annotation on the page, with the boxes it marks. */
96
+ function collectTextMarkup(file, page) {
97
+ const annots = file.get(page.dict, "Annots");
98
+ if (!Array.isArray(annots)) return [];
99
+ const out = [];
100
+ for (const entry of annots) {
101
+ const annot = file.resolve(entry);
102
+ if (!(annot instanceof Map)) continue;
103
+ const mark = textMarkupOf(file, annot);
104
+ if (mark) out.push(mark);
105
+ }
106
+ return out;
107
+ }
108
+ /**
109
+ * §9.4.3 — the same text struck again in the same place, dropped.
110
+ *
111
+ * A page with no bold face to hand fakes one by drawing its text several times
112
+ * a fraction of a point apart, and every copy is a run of its own.
113
+ * bug900822.pdf draws one line FOUR times — twice 0.16pt apart across, twice
114
+ * 0.32pt apart down — and read as four lines its letters came back interleaved:
115
+ * "TTTTeeeesssstttt" where the page shows "Test test".
116
+ *
117
+ * A copy is a run with the SAME text and size within a small fraction of an em
118
+ * of another. That is well inside the advance of even the narrowest letter, so
119
+ * a word that really does repeat a character is never mistaken for one. The
120
+ * LAST copy is the one kept: it is the one painted on top.
121
+ *
122
+ * The extra strikes are not read as WEIGHT. It is tempting — the offset is
123
+ * exactly how a face with no bold cut is emboldened — but two strikes a tenth
124
+ * of a point apart are a hair of ink and not a bold face:
125
+ * issue11150_reduced.pdf strikes each of its three letters twice and every
126
+ * renderer shows them at the weight of the text around them.
127
+ *
128
+ * @param runs The page's runs, in painting order.
129
+ * @returns The runs a reader sees, each drawn once.
130
+ */
131
+ function withoutRestrikes(runs) {
132
+ const kept = /* @__PURE__ */ new Map();
133
+ const out = [];
134
+ for (const run of runs) {
135
+ if (run.text.length === 0) {
136
+ out.push(run);
137
+ continue;
138
+ }
139
+ const tol = Math.max((run.fontSizePt || 10) * RESTRIKE_EM, .05);
140
+ const cell = (x, y) => `${run.text}|${run.fontSizePt.toFixed(1)}|${String(Math.round(x / tol))}|${String(Math.round(y / tol))}`;
141
+ let at = -1;
142
+ for (const dx of [
143
+ -1,
144
+ 0,
145
+ 1
146
+ ]) for (const dy of [
147
+ -1,
148
+ 0,
149
+ 1
150
+ ]) {
151
+ const had = kept.get(cell(run.x + dx * tol, run.y + dy * tol));
152
+ if (had !== void 0) at = had;
153
+ }
154
+ if (at >= 0) {
155
+ out[at] = run;
156
+ kept.set(cell(run.x, run.y), at);
157
+ continue;
158
+ }
159
+ kept.set(cell(run.x, run.y), out.length);
160
+ out.push(run);
161
+ }
162
+ return out;
163
+ }
164
+ /** How near, in ems, a re-strike of the same text lands to the one it thickens. */
165
+ var RESTRIKE_EM = .08;
166
+ var spaceCache = /* @__PURE__ */ new WeakMap();
167
+ /** The page's shading patterns, read once per resource dictionary. */
168
+ var shadingCache = /* @__PURE__ */ new WeakMap();
169
+ function shadingsOf(file, resources) {
170
+ if (!resources) return /* @__PURE__ */ new Map();
171
+ const had = shadingCache.get(resources);
172
+ if (had) return had;
173
+ const made = buildShadingMap(file, resources);
174
+ shadingCache.set(resources, made);
175
+ return made;
176
+ }
177
+ function spacesOf(file, resources) {
178
+ if (!resources) return /* @__PURE__ */ new Map();
179
+ const had = spaceCache.get(resources);
180
+ if (had) return had;
181
+ const made = buildColorSpaceMap(file, resources);
182
+ spaceCache.set(resources, made);
183
+ return made;
184
+ }
33
185
  function collectRuns(file, resources, content, baseCtm, depth, visiting, out) {
34
- const result = interpretContent(content, buildFonts(file, resources), baseCtm);
186
+ const result = interpretContent(content, buildFonts(file, resources), baseCtm, shadingsOf(file, resources), void 0, spacesOf(file, resources), hiddenProperties(file, resources));
35
187
  out.push(...result.texts.map((r) => withPatternColour(file, resources, r, visiting)));
36
188
  if (depth >= MAX_FORM_DEPTH) return;
37
189
  for (const glyph of result.glyphs) {
@@ -46,6 +198,7 @@ function collectRuns(file, resources, content, baseCtm, depth, visiting, out) {
46
198
  for (const placement of result.images) {
47
199
  const stream = file.resolve(xobjects.get(placement.name) ?? PDF_NULL);
48
200
  if (!(stream instanceof PdfStream) || visiting.has(stream)) continue;
201
+ if (hiddenXObject(file, stream)) continue;
49
202
  const sub = file.get(stream.dict, "Subtype");
50
203
  if (!(sub instanceof PdfName) || sub.value !== "Form") continue;
51
204
  visiting.add(stream);
@@ -0,0 +1,21 @@
1
+ import { PathSeg } from './content.js';
2
+ /** What an embedded Type 1 program says about its glyphs. */
3
+ export interface Type1Font {
4
+ /** The contours of one glyph, by NAME — a Type 1 font indexes by nothing else. */
5
+ readonly path: (name: string) => Array<PathSeg> | undefined;
6
+ /**
7
+ * Whether the program holds a glyph of that name at all. One it holds which
8
+ * draws nothing is a BLANK glyph — a space — and not one it lacks.
9
+ */
10
+ readonly has: (name: string) => boolean;
11
+ /** The program's own `/Encoding`: code → glyph name, where it states one. */
12
+ readonly encoding?: ReadonlyMap<number, string>;
13
+ }
14
+ /**
15
+ * Read an embedded Type 1 program.
16
+ *
17
+ * @param program The raw `/FontFile` bytes — the cleartext header, the
18
+ * `eexec`-encrypted body, and the trailing zeros.
19
+ * @returns A reader, or `undefined` where the program cannot be read.
20
+ */
21
+ export declare function type1Font(program: Uint8Array): Type1Font | undefined;