reamkit 1.29.0 → 1.31.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 +60 -24
- package/dist/esm/core/converter/project.js +3 -1
- package/dist/esm/core/crypto/offcrypto.js +1 -1
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +65 -0
- package/dist/esm/core/drawingml/shape-render.js +13 -1
- package/dist/esm/core/font/index.d.ts +2 -0
- package/dist/esm/core/font/ttf-build.d.ts +113 -0
- package/dist/esm/core/font/ttf-build.js +1224 -0
- package/dist/esm/core/font/ttf-subset.d.ts +19 -0
- package/dist/esm/core/font/ttf-subset.js +14 -1
- package/dist/esm/core/fonts/index.d.ts +1 -1
- package/dist/esm/core/fonts/provider.d.ts +17 -0
- package/dist/esm/core/fonts/provider.js +27 -2
- package/dist/esm/core/fonts/remote-fonts.d.ts +8 -0
- package/dist/esm/core/fonts/remote-fonts.js +108 -18
- package/dist/esm/core/ir/flow.d.ts +88 -1
- package/dist/esm/core/numbering/index.d.ts +1 -1
- package/dist/esm/core/numbering/state.d.ts +11 -1
- package/dist/esm/core/numbering/state.js +10 -1
- package/dist/esm/core/style-cascade/resolver.js +35 -4
- package/dist/esm/core/style-cascade/types.d.ts +19 -1
- package/dist/esm/core/style-cascade/types.js +3 -0
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/layout/page-doc.d.ts +10 -3
- package/dist/esm/layout/styled-layout.d.ts +48 -7
- package/dist/esm/layout/styled-layout.js +881 -119
- package/dist/esm/layout/turned-section.d.ts +38 -0
- package/dist/esm/layout/turned-section.js +193 -0
- package/dist/esm/pdf/styled-page-emitter.js +78 -2
- package/dist/esm/pdf-reader/annot-draw.js +93 -1
- package/dist/esm/pdf-reader/annots.d.ts +18 -0
- package/dist/esm/pdf-reader/annots.js +86 -9
- package/dist/esm/pdf-reader/cff-outline.d.ts +27 -0
- package/dist/esm/pdf-reader/cff-outline.js +169 -21
- package/dist/esm/pdf-reader/cmap.js +5 -2
- package/dist/esm/pdf-reader/content.d.ts +70 -4
- package/dist/esm/pdf-reader/content.js +172 -12
- package/dist/esm/pdf-reader/display.d.ts +36 -0
- package/dist/esm/pdf-reader/display.js +82 -1
- package/dist/esm/pdf-reader/document.js +5 -1
- package/dist/esm/pdf-reader/embedded-fonts.d.ts +25 -0
- package/dist/esm/pdf-reader/embedded-fonts.js +78 -9
- package/dist/esm/pdf-reader/encodings.d.ts +8 -0
- package/dist/esm/pdf-reader/encodings.js +25 -3
- package/dist/esm/pdf-reader/face-outlines.d.ts +78 -0
- package/dist/esm/pdf-reader/face-outlines.js +362 -0
- package/dist/esm/pdf-reader/figures.d.ts +52 -0
- package/dist/esm/pdf-reader/figures.js +433 -0
- package/dist/esm/pdf-reader/flow-build.d.ts +224 -7
- package/dist/esm/pdf-reader/flow-build.js +545 -39
- package/dist/esm/pdf-reader/font.d.ts +27 -1
- package/dist/esm/pdf-reader/font.js +632 -63
- package/dist/esm/pdf-reader/glyf-outline.d.ts +33 -0
- package/dist/esm/pdf-reader/glyf-outline.js +148 -3
- package/dist/esm/pdf-reader/glyph-names.js +154 -1
- package/dist/esm/pdf-reader/glyph-shapes.d.ts +18 -0
- package/dist/esm/pdf-reader/glyph-shapes.js +57 -0
- package/dist/esm/pdf-reader/image-decode.js +70 -4
- package/dist/esm/pdf-reader/images.d.ts +5 -0
- package/dist/esm/pdf-reader/images.js +4 -2
- package/dist/esm/pdf-reader/jbig2.d.ts +40 -1
- package/dist/esm/pdf-reader/jbig2.js +78 -16
- package/dist/esm/pdf-reader/jpeg.d.ts +6 -3
- package/dist/esm/pdf-reader/jpeg.js +21 -1
- package/dist/esm/pdf-reader/layout.d.ts +119 -2
- package/dist/esm/pdf-reader/layout.js +2219 -184
- package/dist/esm/pdf-reader/lexer.d.ts +10 -0
- package/dist/esm/pdf-reader/lexer.js +17 -0
- package/dist/esm/pdf-reader/page-numbers.d.ts +53 -0
- package/dist/esm/pdf-reader/page-numbers.js +167 -0
- package/dist/esm/pdf-reader/pattern-tint.d.ts +11 -1
- package/dist/esm/pdf-reader/pattern-tint.js +21 -3
- package/dist/esm/pdf-reader/regions.d.ts +25 -0
- package/dist/esm/pdf-reader/regions.js +167 -0
- package/dist/esm/pdf-reader/shading.d.ts +58 -2
- package/dist/esm/pdf-reader/shading.js +181 -11
- package/dist/esm/pdf-reader/struct-tree.js +112 -8
- package/dist/esm/pdf-reader/tagged.js +207 -28
- package/dist/esm/pdf-reader/text-rules.js +1 -1
- package/dist/esm/pdf-reader/text.d.ts +6 -3
- package/dist/esm/pdf-reader/text.js +106 -22
- package/dist/esm/pdf-reader/type1-outline.d.ts +11 -0
- package/dist/esm/pdf-reader/type1-outline.js +63 -8
- package/dist/esm/pdf-reader/vector.d.ts +8 -2
- package/dist/esm/pdf-reader/vector.js +105 -6
- package/dist/esm/word/doc/doc-reader.js +6 -2
- package/dist/esm/word/doc/doc-text.d.ts +6 -0
- package/dist/esm/word/doc/doc-text.js +19 -1
- package/dist/esm/word/document-parser.d.ts +2 -2
- package/dist/esm/word/document-parser.js +11 -1
- package/dist/esm/word/docx-reader.js +5 -3
- package/dist/esm/word/docx-writer.js +341 -54
- package/dist/esm/word/drawing-parser.d.ts +5 -3
- package/dist/esm/word/drawing-parser.js +56 -10
- package/dist/esm/word/font-embed.d.ts +30 -0
- package/dist/esm/word/font-embed.js +173 -0
- package/dist/esm/word/font-table.d.ts +10 -0
- package/dist/esm/word/font-table.js +13 -1
- package/dist/esm/word/index.js +1 -1
- package/dist/esm/word/numbering-parser.d.ts +3 -1
- package/dist/esm/word/numbering-parser.js +2 -1
- package/dist/esm/word/paragraph-properties.d.ts +7 -6
- package/dist/esm/word/paragraph-properties.js +16 -2
- package/dist/esm/word/run-properties.js +26 -0
- package/package.json +12 -5
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { PDF_NULL, PdfHexString, PdfName } from "../pdf/objects.js";
|
|
2
|
+
import { bidiClass } from "../core/bidi/char-types.js";
|
|
3
|
+
import { reorderVisual } from "../core/bidi/algorithm.js";
|
|
4
|
+
import { analyzeString, hasBidiCharacters } from "../core/bidi/index.js";
|
|
2
5
|
import { Lexer } from "./lexer.js";
|
|
3
|
-
import { cmykHex, grayHex, rgbHex, spaceColor } from "./shading.js";
|
|
6
|
+
import { cmykHex, dashLengths, grayHex, rgbHex, spaceColor } from "./shading.js";
|
|
4
7
|
//#region src/pdf-reader/content.ts
|
|
5
8
|
/**
|
|
6
9
|
* A painted path emitted by the path-painting operators (§8.5.3), captured in
|
|
@@ -101,9 +104,13 @@ function initialState() {
|
|
|
101
104
|
fillColor: "000000",
|
|
102
105
|
strokeColor: "000000",
|
|
103
106
|
lineWidth: 1,
|
|
107
|
+
dash: [],
|
|
108
|
+
lineCap: 0,
|
|
104
109
|
fillGradient: void 0,
|
|
105
110
|
fillPattern: void 0,
|
|
111
|
+
fillPatternPaint: void 0,
|
|
106
112
|
fillAlpha: 1,
|
|
113
|
+
strokeAlpha: 1,
|
|
107
114
|
fillDarkens: false,
|
|
108
115
|
blendMode: void 0,
|
|
109
116
|
softMask: false,
|
|
@@ -184,6 +191,7 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
184
191
|
const glyphs = [];
|
|
185
192
|
const painted = [];
|
|
186
193
|
const outlines = [];
|
|
194
|
+
const codesShown = /* @__PURE__ */ new Map();
|
|
187
195
|
const lexer = new Lexer(bytes);
|
|
188
196
|
const stack = [];
|
|
189
197
|
let state = initialState();
|
|
@@ -229,6 +237,25 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
229
237
|
y
|
|
230
238
|
});
|
|
231
239
|
};
|
|
240
|
+
const currentPoint = () => {
|
|
241
|
+
for (let i = path.length - 1; i >= 0; i--) {
|
|
242
|
+
const seg = path[i];
|
|
243
|
+
if (seg.op === "close") {
|
|
244
|
+
for (let k = i - 1; k >= 0; k--) {
|
|
245
|
+
const start = path[k];
|
|
246
|
+
if (start.op === "move") return {
|
|
247
|
+
x: start.x,
|
|
248
|
+
y: start.y
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
x: seg.x,
|
|
255
|
+
y: seg.y
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
};
|
|
232
259
|
const rectTo = (x, y, w, h) => {
|
|
233
260
|
moveTo(x, y);
|
|
234
261
|
lineTo(x + w, y);
|
|
@@ -241,6 +268,11 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
241
268
|
const scale = Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])) || 1;
|
|
242
269
|
return state.lineWidth * scale;
|
|
243
270
|
};
|
|
271
|
+
const ctmDash = () => {
|
|
272
|
+
const m = state.ctm;
|
|
273
|
+
const scale = Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])) || 1;
|
|
274
|
+
return state.dash.map((n) => n * scale);
|
|
275
|
+
};
|
|
244
276
|
const paintPath = (fill, stroke) => {
|
|
245
277
|
if (path.length >= 2 && (fill || stroke) && visible()) {
|
|
246
278
|
const mcid = mcStack.length > 0 ? mcStack[mcStack.length - 1] : void 0;
|
|
@@ -249,6 +281,7 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
249
281
|
segs: path,
|
|
250
282
|
...state.clip ? { clip: state.clip } : {},
|
|
251
283
|
...fill && state.fillPattern !== void 0 ? { patternName: state.fillPattern } : {},
|
|
284
|
+
...fill && state.fillPattern !== void 0 && state.fillPatternPaint !== void 0 ? { patternPaint: state.fillPatternPaint } : {},
|
|
252
285
|
...fill ? { fillHex: state.fillColor } : {},
|
|
253
286
|
...fill && state.fillAlpha < 1 ? { alpha: state.fillAlpha } : {},
|
|
254
287
|
...fill && state.fillDarkens ? { darkens: true } : {},
|
|
@@ -259,6 +292,10 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
259
292
|
strokeHex: state.strokeColor,
|
|
260
293
|
lineWidth: ctmLineWidth()
|
|
261
294
|
} : {},
|
|
295
|
+
...stroke && state.dash.length > 0 ? { dash: ctmDash() } : {},
|
|
296
|
+
...stroke && state.lineCap === 1 ? { cap: "round" } : {},
|
|
297
|
+
...stroke && state.lineCap === 2 ? { cap: "square" } : {},
|
|
298
|
+
...stroke && state.strokeAlpha < 1 ? { strokeAlpha: state.strokeAlpha } : {},
|
|
262
299
|
...mcid !== void 0 ? { mcid } : {}
|
|
263
300
|
});
|
|
264
301
|
}
|
|
@@ -337,6 +374,11 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
337
374
|
const bytes = toBytes(operand);
|
|
338
375
|
const codes = state.font.splitCodes ? state.font.splitCodes(bytes) : splitCodes(bytes, state.font.bytesPerCode);
|
|
339
376
|
for (const code of codes) advanceGlyph(code);
|
|
377
|
+
if (state.font.program && visible() && state.renderMode !== 3 && state.renderMode !== 7) {
|
|
378
|
+
let set = codesShown.get(state.font);
|
|
379
|
+
if (!set) codesShown.set(state.font, set = /* @__PURE__ */ new Set());
|
|
380
|
+
for (const code of codes) set.add(code);
|
|
381
|
+
}
|
|
340
382
|
return state.font.decode(codes);
|
|
341
383
|
};
|
|
342
384
|
const emitAt = (origin, shown, end) => {
|
|
@@ -357,6 +399,7 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
357
399
|
fontSizePt: Math.abs(state.fontSize) * scaleY,
|
|
358
400
|
spaceWidthPt: (state.font.width(32) / 1e3 * state.fontSize + state.charSpacing + state.wordSpacing) * scaleX,
|
|
359
401
|
fontKey: state.fontKey,
|
|
402
|
+
...state.font.fixedPitch === true ? { fixedPitch: true } : {},
|
|
360
403
|
...state.font.name !== void 0 ? { fontName: state.font.name } : {},
|
|
361
404
|
...state.font.type3 ? { type3: true } : {},
|
|
362
405
|
...state.renderMode === 3 || state.renderMode === 7 ? { invisible: true } : {},
|
|
@@ -519,6 +562,8 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
519
562
|
if (named !== void 0) {
|
|
520
563
|
state.fillGradient = shadings.get(named);
|
|
521
564
|
state.fillPattern = state.fillGradient ? void 0 : named;
|
|
565
|
+
const components = operands.filter((o) => typeof o === "number");
|
|
566
|
+
state.fillPatternPaint = components.length > 0 ? spaceColor(components, void 0) : void 0;
|
|
522
567
|
break;
|
|
523
568
|
}
|
|
524
569
|
const hex = colorOfOperands(operands, state.fillSpace);
|
|
@@ -531,7 +576,12 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
531
576
|
}
|
|
532
577
|
case "SCN":
|
|
533
578
|
case "SC": {
|
|
534
|
-
|
|
579
|
+
const last = operands[operands.length - 1];
|
|
580
|
+
if (last instanceof PdfName) {
|
|
581
|
+
const sweep = shadings.get(last.value);
|
|
582
|
+
if (sweep) state.strokeColor = midGradient(sweep);
|
|
583
|
+
break;
|
|
584
|
+
}
|
|
535
585
|
const hex = colorOfOperands(operands, state.strokeSpace);
|
|
536
586
|
if (hex !== void 0) state.strokeColor = hex;
|
|
537
587
|
break;
|
|
@@ -548,6 +598,14 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
548
598
|
case "w":
|
|
549
599
|
state.lineWidth = num(0);
|
|
550
600
|
break;
|
|
601
|
+
case "d":
|
|
602
|
+
state.dash = dashLengths(operands[0]);
|
|
603
|
+
break;
|
|
604
|
+
case "J": {
|
|
605
|
+
const cap = num(0);
|
|
606
|
+
if (cap === 0 || cap === 1 || cap === 2) state.lineCap = cap;
|
|
607
|
+
break;
|
|
608
|
+
}
|
|
551
609
|
case "m":
|
|
552
610
|
moveTo(num(0), num(1));
|
|
553
611
|
break;
|
|
@@ -557,6 +615,26 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
557
615
|
case "c":
|
|
558
616
|
curveTo(num(0), num(1), num(2), num(3), num(4), num(5));
|
|
559
617
|
break;
|
|
618
|
+
case "v": {
|
|
619
|
+
const at = currentPoint();
|
|
620
|
+
if (at) {
|
|
621
|
+
const [x2, y2] = toPage(num(0), num(1));
|
|
622
|
+
const [x, y] = toPage(num(2), num(3));
|
|
623
|
+
path.push({
|
|
624
|
+
op: "cubic",
|
|
625
|
+
x1: at.x,
|
|
626
|
+
y1: at.y,
|
|
627
|
+
x2,
|
|
628
|
+
y2,
|
|
629
|
+
x,
|
|
630
|
+
y
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
break;
|
|
634
|
+
}
|
|
635
|
+
case "y":
|
|
636
|
+
curveTo(num(0), num(1), num(2), num(3), num(2), num(3));
|
|
637
|
+
break;
|
|
560
638
|
case "re":
|
|
561
639
|
rectTo(num(0), num(1), num(2), num(3));
|
|
562
640
|
break;
|
|
@@ -610,6 +688,10 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
610
688
|
state.blendMode = paint.blend;
|
|
611
689
|
}
|
|
612
690
|
if (paint.masked !== void 0) state.softMask = paint.masked;
|
|
691
|
+
if (paint.lineWidth !== void 0) state.lineWidth = paint.lineWidth;
|
|
692
|
+
if (paint.dash !== void 0) state.dash = paint.dash;
|
|
693
|
+
if (paint.lineCap !== void 0) state.lineCap = paint.lineCap;
|
|
694
|
+
if (paint.strokeAlpha !== void 0) state.strokeAlpha = paint.strokeAlpha;
|
|
613
695
|
}
|
|
614
696
|
break;
|
|
615
697
|
}
|
|
@@ -670,7 +752,8 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
670
752
|
vectors,
|
|
671
753
|
glyphs,
|
|
672
754
|
shadings: painted,
|
|
673
|
-
outlines
|
|
755
|
+
outlines,
|
|
756
|
+
shown: codesShown
|
|
674
757
|
};
|
|
675
758
|
}
|
|
676
759
|
/** One path segment through a matrix — the glyph's own space onto the page. */
|
|
@@ -713,12 +796,27 @@ function strokesText(mode) {
|
|
|
713
796
|
* ArabicCIDTrueType.pdf came out mirrored for exactly that reason: the reader
|
|
714
797
|
* passed visual order through and the layout reversed it a second time.
|
|
715
798
|
*
|
|
716
|
-
* A run
|
|
717
|
-
* number inside an Arabic sentence
|
|
718
|
-
*
|
|
799
|
+
* A run wholly right-to-left is simply reversed. A MIXED one — a full stop or
|
|
800
|
+
* a number inside an Arabic sentence — is put through the bidi algorithm's
|
|
801
|
+
* reordering (UAX #9 L2), which for the runs a line holds undoes itself: the
|
|
802
|
+
* painted order reordered is the reading order. Left alone, a note of
|
|
803
|
+
* freetext_no_appearance.pdf came back with every line that held a full stop
|
|
804
|
+
* reading back to front. The direction it is reordered in is the one most of
|
|
805
|
+
* its letters run in — the painted order says nothing about which comes first.
|
|
719
806
|
*/
|
|
720
807
|
function logicalOrder(text) {
|
|
721
|
-
|
|
808
|
+
if (isRightToLeft(text)) return [...text].reverse().join("");
|
|
809
|
+
if (!hasBidiCharacters(text)) return text;
|
|
810
|
+
const chars = [...text];
|
|
811
|
+
let rtl = 0;
|
|
812
|
+
let strong = 0;
|
|
813
|
+
for (const ch of chars) {
|
|
814
|
+
const type = bidiClass(ch.codePointAt(0) ?? 0);
|
|
815
|
+
if (type === "R" || type === "AL") rtl++;
|
|
816
|
+
if (type === "R" || type === "AL" || type === "L") strong++;
|
|
817
|
+
}
|
|
818
|
+
const { levels } = analyzeString(text, rtl * 2 >= strong ? "rtl" : "ltr");
|
|
819
|
+
return reorderVisual(levels).map((i) => chars[i] ?? "").join("");
|
|
722
820
|
}
|
|
723
821
|
/**
|
|
724
822
|
* Whether a string is wholly right-to-left: at least one letter of an RTL
|
|
@@ -837,8 +935,8 @@ function readValue(lexer) {
|
|
|
837
935
|
* The bytes are binary and may hold `EI` themselves, so the end is found by
|
|
838
936
|
* MEASURING where the dictionary says how much there is — an unfiltered image
|
|
839
937
|
* is exactly `ceil(W · BPC · components / 8) · H` bytes — and only searched for
|
|
840
|
-
* where a filter makes the length unknowable
|
|
841
|
-
* two of them and both were skipped over.
|
|
938
|
+
* where a filter makes the length unknowable (see {@link filteredEnd}).
|
|
939
|
+
* images_1bit_grayscale.pdf draws two of them and both were skipped over.
|
|
842
940
|
*/
|
|
843
941
|
function readInlineImage(lexer) {
|
|
844
942
|
const dict = /* @__PURE__ */ new Map();
|
|
@@ -848,24 +946,86 @@ function readInlineImage(lexer) {
|
|
|
848
946
|
if (tok.kind === "keyword" && tok.value === "ID") break;
|
|
849
947
|
if (tok.kind === "name") dict.set(tok.value, readValue(lexer));
|
|
850
948
|
}
|
|
851
|
-
const start = lexer.pos + 1;
|
|
852
949
|
const measured = inlineLength(dict);
|
|
950
|
+
const crlf = lexer.byteAt(lexer.pos) === 13 && lexer.byteAt(lexer.pos + 1) === 10;
|
|
951
|
+
const start = lexer.pos + (crlf && measured === void 0 ? 2 : 1);
|
|
853
952
|
let end = measured !== void 0 ? start + measured : -1;
|
|
854
953
|
if (end < 0 || end > lexer.length) {
|
|
855
|
-
end = lexer
|
|
954
|
+
end = filteredEnd(lexer, start, dict);
|
|
856
955
|
if (end < 0) {
|
|
857
956
|
lexer.pos = lexer.length;
|
|
858
957
|
return;
|
|
859
958
|
}
|
|
860
959
|
}
|
|
861
960
|
const data = lexer.slice(start, Math.min(end, lexer.length));
|
|
862
|
-
const ei = lexer.
|
|
961
|
+
const ei = lexer.indexOfKeyword("EI", end);
|
|
863
962
|
lexer.pos = ei < 0 ? lexer.length : ei + 2;
|
|
864
963
|
return {
|
|
865
964
|
dict,
|
|
866
965
|
data
|
|
867
966
|
};
|
|
868
967
|
}
|
|
968
|
+
/**
|
|
969
|
+
* §8.9.7 — where a FILTERED inline image's bytes end, which the dictionary
|
|
970
|
+
* cannot say.
|
|
971
|
+
*
|
|
972
|
+
* Searched for as the first two bytes `EI`, the end fell inside the picture
|
|
973
|
+
* wherever its own bytes spelled them: a JPEG is dense with them, and
|
|
974
|
+
* bug1065245.pdf's three banners were each cut off a few hundred bytes in,
|
|
975
|
+
* would not decode, and were dropped — a blank sheet. So the data is read to
|
|
976
|
+
* where its OWN encoding ends: a JPEG at its end-of-image marker, hex text at
|
|
977
|
+
* `>`, base-85 at `~>`. Anything else ends at the first `EI` standing as a
|
|
978
|
+
* word of its own.
|
|
979
|
+
*/
|
|
980
|
+
function filteredEnd(lexer, start, dict) {
|
|
981
|
+
const f = dict.get("F") ?? dict.get("Filter");
|
|
982
|
+
const first = Array.isArray(f) ? f[0] : f;
|
|
983
|
+
const filter = first instanceof PdfName ? first.value : "";
|
|
984
|
+
if (filter === "DCT" || filter === "DCTDecode") {
|
|
985
|
+
const eoi = jpegEnd(lexer, start);
|
|
986
|
+
if (eoi !== void 0) return eoi;
|
|
987
|
+
} else if (filter === "AHx" || filter === "ASCIIHexDecode") {
|
|
988
|
+
const gt = lexer.indexOfAscii(">", start);
|
|
989
|
+
if (gt >= 0) return gt + 1;
|
|
990
|
+
} else if (filter === "A85" || filter === "ASCII85Decode") {
|
|
991
|
+
const tilde = lexer.indexOfAscii("~>", start);
|
|
992
|
+
if (tilde >= 0) return tilde + 2;
|
|
993
|
+
}
|
|
994
|
+
return lexer.indexOfKeyword("EI", start);
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Where a JPEG that starts at `start` ends: past its end-of-image marker,
|
|
998
|
+
* found by walking its segments — a length-prefixed marker segment is stepped
|
|
999
|
+
* over whole, and the coded data after a start-of-scan is read to the next
|
|
1000
|
+
* marker, where `FF` stands before anything but a stuffed `00` or a restart.
|
|
1001
|
+
*/
|
|
1002
|
+
function jpegEnd(lexer, start) {
|
|
1003
|
+
if (lexer.byteAt(start) !== 255 || lexer.byteAt(start + 1) !== 216) return void 0;
|
|
1004
|
+
let i = start + 2;
|
|
1005
|
+
for (;;) {
|
|
1006
|
+
if (lexer.byteAt(i) !== 255) return void 0;
|
|
1007
|
+
let marker = lexer.byteAt(i + 1);
|
|
1008
|
+
while (marker === 255) marker = lexer.byteAt(++i + 1);
|
|
1009
|
+
if (marker < 0) return void 0;
|
|
1010
|
+
if (marker === 217) return i + 2;
|
|
1011
|
+
if (marker >= 208 && marker <= 215 || marker === 1) {
|
|
1012
|
+
i += 2;
|
|
1013
|
+
continue;
|
|
1014
|
+
}
|
|
1015
|
+
const hi = lexer.byteAt(i + 2);
|
|
1016
|
+
const lo = lexer.byteAt(i + 3);
|
|
1017
|
+
if (hi < 0 || lo < 0 || (hi << 8) + lo < 2) return void 0;
|
|
1018
|
+
i += 2 + (hi << 8) + lo;
|
|
1019
|
+
if (marker !== 218) continue;
|
|
1020
|
+
for (;;) {
|
|
1021
|
+
const b = lexer.byteAt(i);
|
|
1022
|
+
if (b < 0) return void 0;
|
|
1023
|
+
const next = lexer.byteAt(i + 1);
|
|
1024
|
+
if (b === 255 && next !== 0 && !(next >= 208 && next <= 215)) break;
|
|
1025
|
+
i++;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
869
1029
|
/** How many bytes an UNFILTERED inline image's samples take, if that is known. */
|
|
870
1030
|
function inlineLength(dict) {
|
|
871
1031
|
if (dict.has("F") || dict.has("Filter")) return void 0;
|
|
@@ -15,6 +15,16 @@ export interface Display {
|
|
|
15
15
|
x: number;
|
|
16
16
|
y: number;
|
|
17
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* §17.6.20 — present when the page is READ in a frame turned back from the
|
|
20
|
+
* sheet it is shown on: its words run DOWN the sheet, and they are read in
|
|
21
|
+
* the frame where they stand upright (see {@link textFrameOf}). `width` and
|
|
22
|
+
* `height` above are that frame's; these are the sheet's.
|
|
23
|
+
*/
|
|
24
|
+
readonly sheet?: {
|
|
25
|
+
readonly width: number;
|
|
26
|
+
readonly height: number;
|
|
27
|
+
};
|
|
18
28
|
}
|
|
19
29
|
/**
|
|
20
30
|
* The {@link Display} a page's shown box and `/Rotate` describe.
|
|
@@ -27,6 +37,32 @@ export interface Display {
|
|
|
27
37
|
* @returns Its size, its turn, and the map onto it.
|
|
28
38
|
*/
|
|
29
39
|
export declare function displayOf(page: PdfPage): Display;
|
|
40
|
+
/**
|
|
41
|
+
* The frame a page whose words run DOWN its sheet is read in: the sheet turned
|
|
42
|
+
* back a quarter, so the words stand upright in it and every line, paragraph
|
|
43
|
+
* and margin is found the way it is on any other page.
|
|
44
|
+
*
|
|
45
|
+
* A viewer turns such a page with its words, and so does the document it is
|
|
46
|
+
* read into (§17.6.20 `tbRl`; see {@link wordsTurnOf} for when a page's words
|
|
47
|
+
* run down it): hello_world_rotated.pdf sets "Hello world"
|
|
48
|
+
* upright in a portrait box and turns the page by `/Rotate 90`, and read on
|
|
49
|
+
* the shown sheet the words were set flat across it where every viewer shows
|
|
50
|
+
* them running down.
|
|
51
|
+
*
|
|
52
|
+
* @param shown The page's shown geometry.
|
|
53
|
+
* @returns The frame, which knows the sheet it was turned back from.
|
|
54
|
+
*/
|
|
55
|
+
export declare function textFrameOf(shown: Display): Display;
|
|
56
|
+
/**
|
|
57
|
+
* How a page's words stand on its sheet: the quarter turn, counter-clockwise,
|
|
58
|
+
* whose words outweigh every other on it together, by their letters at their
|
|
59
|
+
* size — or 0 where none does. A label set on its side beside the text does
|
|
60
|
+
* not turn a page; a page of it does.
|
|
61
|
+
*
|
|
62
|
+
* @param runs The page's runs, placed on the shown sheet.
|
|
63
|
+
* @returns 0, 90, 180 or 270; 270 is a page whose words run DOWN it.
|
|
64
|
+
*/
|
|
65
|
+
export declare function wordsTurnOf(runs: ReadonlyArray<TextRun>): 0 | 90 | 180 | 270;
|
|
30
66
|
/**
|
|
31
67
|
* The same runs, placed on the shown page.
|
|
32
68
|
*
|
|
@@ -46,6 +46,71 @@ function displayOf(page) {
|
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
|
+
* The frame a page whose words run DOWN its sheet is read in: the sheet turned
|
|
50
|
+
* back a quarter, so the words stand upright in it and every line, paragraph
|
|
51
|
+
* and margin is found the way it is on any other page.
|
|
52
|
+
*
|
|
53
|
+
* A viewer turns such a page with its words, and so does the document it is
|
|
54
|
+
* read into (§17.6.20 `tbRl`; see {@link wordsTurnOf} for when a page's words
|
|
55
|
+
* run down it): hello_world_rotated.pdf sets "Hello world"
|
|
56
|
+
* upright in a portrait box and turns the page by `/Rotate 90`, and read on
|
|
57
|
+
* the shown sheet the words were set flat across it where every viewer shows
|
|
58
|
+
* them running down.
|
|
59
|
+
*
|
|
60
|
+
* @param shown The page's shown geometry.
|
|
61
|
+
* @returns The frame, which knows the sheet it was turned back from.
|
|
62
|
+
*/
|
|
63
|
+
function textFrameOf(shown) {
|
|
64
|
+
return {
|
|
65
|
+
width: shown.height,
|
|
66
|
+
height: shown.width,
|
|
67
|
+
turnDeg: shown.turnDeg === 270 || shown.turnDeg === -90 ? 0 : shown.turnDeg + 90,
|
|
68
|
+
place: (x, y) => {
|
|
69
|
+
const p = shown.place(x, y);
|
|
70
|
+
return {
|
|
71
|
+
x: shown.height - p.y,
|
|
72
|
+
y: p.x
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
sheet: {
|
|
76
|
+
width: shown.width,
|
|
77
|
+
height: shown.height
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* How a page's words stand on its sheet: the quarter turn, counter-clockwise,
|
|
83
|
+
* whose words outweigh every other on it together, by their letters at their
|
|
84
|
+
* size — or 0 where none does. A label set on its side beside the text does
|
|
85
|
+
* not turn a page; a page of it does.
|
|
86
|
+
*
|
|
87
|
+
* @param runs The page's runs, placed on the shown sheet.
|
|
88
|
+
* @returns 0, 90, 180 or 270; 270 is a page whose words run DOWN it.
|
|
89
|
+
*/
|
|
90
|
+
function wordsTurnOf(runs) {
|
|
91
|
+
const by = [
|
|
92
|
+
0,
|
|
93
|
+
0,
|
|
94
|
+
0,
|
|
95
|
+
0
|
|
96
|
+
];
|
|
97
|
+
let all = 0;
|
|
98
|
+
for (const r of runs) {
|
|
99
|
+
const letters = r.text.trim().length;
|
|
100
|
+
if (letters === 0) continue;
|
|
101
|
+
const weight = letters * (r.fontSizePt || 10);
|
|
102
|
+
all += weight;
|
|
103
|
+
const angle = (Math.round(r.angleDeg ?? 0) % 360 + 360) % 360;
|
|
104
|
+
if (angle % 90 === 0) by[angle / 90] += weight;
|
|
105
|
+
}
|
|
106
|
+
const most = by.findIndex((w) => w * 2 > all);
|
|
107
|
+
return most > 0 ? [
|
|
108
|
+
90,
|
|
109
|
+
180,
|
|
110
|
+
270
|
|
111
|
+
][most - 1] : 0;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
49
114
|
* The same runs, placed on the shown page.
|
|
50
115
|
*
|
|
51
116
|
* @param runs The runs as the content stream drew them.
|
|
@@ -199,12 +264,28 @@ function placeVectors(vectors, d) {
|
|
|
199
264
|
ys.push(s.y);
|
|
200
265
|
if (s.op === "cubic") xs.push(s.x1, s.x2), ys.push(s.y1, s.y2);
|
|
201
266
|
}
|
|
267
|
+
const g = v.gradient;
|
|
268
|
+
const moved = g?.axis !== void 0 ? { gradient: {
|
|
269
|
+
...g,
|
|
270
|
+
axis: ((a) => {
|
|
271
|
+
const p0 = d.place(a.x0, a.y0);
|
|
272
|
+
const p1 = d.place(a.x1, a.y1);
|
|
273
|
+
return {
|
|
274
|
+
x0: p0.x,
|
|
275
|
+
y0: p0.y,
|
|
276
|
+
x1: p1.x,
|
|
277
|
+
y1: p1.y
|
|
278
|
+
};
|
|
279
|
+
})(g.axis)
|
|
280
|
+
} } : {};
|
|
202
281
|
if (xs.length === 0) return {
|
|
203
282
|
...v,
|
|
283
|
+
...moved,
|
|
204
284
|
segs
|
|
205
285
|
};
|
|
206
286
|
return {
|
|
207
287
|
...v,
|
|
288
|
+
...moved,
|
|
208
289
|
segs,
|
|
209
290
|
minX: Math.min(...xs),
|
|
210
291
|
minY: Math.min(...ys),
|
|
@@ -214,4 +295,4 @@ function placeVectors(vectors, d) {
|
|
|
214
295
|
}).filter((v) => shows(d, v.minX, v.minY, v.maxX, v.maxY));
|
|
215
296
|
}
|
|
216
297
|
//#endregion
|
|
217
|
-
export { displayOf, placeImages, placeRuns, placeVectors };
|
|
298
|
+
export { displayOf, placeImages, placeRuns, placeVectors, textFrameOf, wordsTurnOf };
|
|
@@ -183,7 +183,7 @@ var PdfFile = class PdfFile {
|
|
|
183
183
|
}
|
|
184
184
|
return;
|
|
185
185
|
}
|
|
186
|
-
const media = mediaBox
|
|
186
|
+
const media = mediaBox !== void 0 && hasArea(mediaBox) ? mediaBox : DEFAULT_MEDIA_BOX;
|
|
187
187
|
out.push({
|
|
188
188
|
dict: node,
|
|
189
189
|
mediaBox: media,
|
|
@@ -556,6 +556,10 @@ function lastIndexOfAscii(buf, needle) {
|
|
|
556
556
|
* bug1844576.pdf is 612×792 of paper cropped to 181×53.75, and read as its
|
|
557
557
|
* media box the form on it arrived a fifth of the way down a letter page.
|
|
558
558
|
*/
|
|
559
|
+
/** Whether a rectangle bounds anything: a point or a line is no page. */
|
|
560
|
+
function hasArea([x0, y0, x1, y1]) {
|
|
561
|
+
return Math.abs(x1 - x0) > 1 && Math.abs(y1 - y0) > 1;
|
|
562
|
+
}
|
|
559
563
|
function shownBox(media, crop) {
|
|
560
564
|
if (!crop) return media;
|
|
561
565
|
const [mx0, my0, mx1, my1] = media;
|
|
@@ -29,6 +29,16 @@ import { FontRegistry } from '../core/font/index.js';
|
|
|
29
29
|
* @returns Name → a one-face registry holding that program.
|
|
30
30
|
*/
|
|
31
31
|
export declare function collectEmbeddedFonts(file: PdfFile, pages: ReadonlyArray<PdfPage>, losses?: Array<Loss>): Map<string, FontRegistry>;
|
|
32
|
+
/**
|
|
33
|
+
* Every `/Font` dictionary the pages draw with, each once: the page's own
|
|
34
|
+
* resources and those of every form it paints (§8.8 — a drawing keeps most of
|
|
35
|
+
* its lettering inside them).
|
|
36
|
+
*
|
|
37
|
+
* @param file The owning file.
|
|
38
|
+
* @param pages The pages whose fonts are wanted.
|
|
39
|
+
* @param visit Called once per font dictionary.
|
|
40
|
+
*/
|
|
41
|
+
export declare function eachPageFont(file: PdfFile, pages: ReadonlyArray<PdfPage>, visit: (fontDict: PdfDict) => void): void;
|
|
32
42
|
/**
|
|
33
43
|
* The name a run set in `fontDict` will ask for: its `/BaseFont` without the
|
|
34
44
|
* six-capital subset prefix (§9.6.4), lowercased.
|
|
@@ -49,3 +59,18 @@ export declare function embeddedFontName(file: PdfFile, fontDict: PdfDict): stri
|
|
|
49
59
|
* @param fontDict The font dictionary.
|
|
50
60
|
*/
|
|
51
61
|
export declare function hasLiftableProgram(file: PdfFile, fontDict: PdfDict): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* The style a font's embedded program states for itself — the `head` table's
|
|
64
|
+
* macStyle, bit 0 bold and bit 1 italic — where the file carries a TrueType
|
|
65
|
+
* program to read it from, and the weight a Type 1 program names (see
|
|
66
|
+
* {@link typeOneStyle}).
|
|
67
|
+
*
|
|
68
|
+
* @param file The document.
|
|
69
|
+
* @param fontDict The font dictionary.
|
|
70
|
+
* @returns The program's own style, or `undefined` where there is no program
|
|
71
|
+
* or it has no header.
|
|
72
|
+
*/
|
|
73
|
+
export declare function programStyle(file: PdfFile, fontDict: PdfDict): {
|
|
74
|
+
bold: boolean;
|
|
75
|
+
italic: boolean;
|
|
76
|
+
} | undefined;
|
|
@@ -32,11 +32,7 @@ var MAX_FORM_DEPTH = 8;
|
|
|
32
32
|
*/
|
|
33
33
|
function collectEmbeddedFonts(file, pages, losses) {
|
|
34
34
|
const out = /* @__PURE__ */ new Map();
|
|
35
|
-
|
|
36
|
-
const visiting = /* @__PURE__ */ new Set();
|
|
37
|
-
const addFont = (fontDict) => {
|
|
38
|
-
if (seen.has(fontDict)) return;
|
|
39
|
-
seen.add(fontDict);
|
|
35
|
+
eachPageFont(file, pages, (fontDict) => {
|
|
40
36
|
const name = embeddedFontName(file, fontDict);
|
|
41
37
|
if (name === void 0 || out.has(name)) return;
|
|
42
38
|
const program = fontProgram(file, fontDict);
|
|
@@ -53,13 +49,29 @@ function collectEmbeddedFonts(file, pages, losses) {
|
|
|
53
49
|
}
|
|
54
50
|
out.set(name, FontRegistry.fromBytes({ regular: program }));
|
|
55
51
|
} catch {}
|
|
56
|
-
};
|
|
52
|
+
});
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Every `/Font` dictionary the pages draw with, each once: the page's own
|
|
57
|
+
* resources and those of every form it paints (§8.8 — a drawing keeps most of
|
|
58
|
+
* its lettering inside them).
|
|
59
|
+
*
|
|
60
|
+
* @param file The owning file.
|
|
61
|
+
* @param pages The pages whose fonts are wanted.
|
|
62
|
+
* @param visit Called once per font dictionary.
|
|
63
|
+
*/
|
|
64
|
+
function eachPageFont(file, pages, visit) {
|
|
65
|
+
const seen = /* @__PURE__ */ new Set();
|
|
66
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
57
67
|
const walk = (resources, depth) => {
|
|
58
68
|
if (!resources) return;
|
|
59
69
|
const fonts = file.get(resources, "Font");
|
|
60
70
|
if (fonts instanceof Map) for (const value of fonts.values()) {
|
|
61
71
|
const dict = file.resolve(value);
|
|
62
|
-
if (dict instanceof Map)
|
|
72
|
+
if (!(dict instanceof Map) || seen.has(dict)) continue;
|
|
73
|
+
seen.add(dict);
|
|
74
|
+
visit(dict);
|
|
63
75
|
}
|
|
64
76
|
if (depth >= MAX_FORM_DEPTH) return;
|
|
65
77
|
const xobjects = file.get(resources, "XObject");
|
|
@@ -76,7 +88,6 @@ function collectEmbeddedFonts(file, pages, losses) {
|
|
|
76
88
|
}
|
|
77
89
|
};
|
|
78
90
|
for (const page of pages) walk(page.resources, 0);
|
|
79
|
-
return out;
|
|
80
91
|
}
|
|
81
92
|
/**
|
|
82
93
|
* The name a run set in `fontDict` will ask for: its `/BaseFont` without the
|
|
@@ -105,6 +116,64 @@ function embeddedFontName(file, fontDict) {
|
|
|
105
116
|
function hasLiftableProgram(file, fontDict) {
|
|
106
117
|
return fontProgram(file, fontDict) !== void 0;
|
|
107
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* The style a font's embedded program states for itself — the `head` table's
|
|
121
|
+
* macStyle, bit 0 bold and bit 1 italic — where the file carries a TrueType
|
|
122
|
+
* program to read it from, and the weight a Type 1 program names (see
|
|
123
|
+
* {@link typeOneStyle}).
|
|
124
|
+
*
|
|
125
|
+
* @param file The document.
|
|
126
|
+
* @param fontDict The font dictionary.
|
|
127
|
+
* @returns The program's own style, or `undefined` where there is no program
|
|
128
|
+
* or it has no header.
|
|
129
|
+
*/
|
|
130
|
+
function programStyle(file, fontDict) {
|
|
131
|
+
const program = fontProgram(file, fontDict);
|
|
132
|
+
if (!program) return typeOneStyle(file, fontDict);
|
|
133
|
+
if (program.length < 12) return void 0;
|
|
134
|
+
const view = new DataView(program.buffer, program.byteOffset, program.byteLength);
|
|
135
|
+
const tables = view.getUint16(4);
|
|
136
|
+
for (let i = 0; i < tables; i++) {
|
|
137
|
+
const at = 12 + i * 16;
|
|
138
|
+
if (at + 16 > program.length) return void 0;
|
|
139
|
+
if (String.fromCharCode(...program.subarray(at, at + 4)) !== "head") continue;
|
|
140
|
+
const offset = view.getUint32(at + 8);
|
|
141
|
+
if (offset + 46 > program.length) return void 0;
|
|
142
|
+
const macStyle = view.getUint16(offset + 44);
|
|
143
|
+
return {
|
|
144
|
+
bold: (macStyle & 1) !== 0,
|
|
145
|
+
italic: (macStyle & 2) !== 0
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* §9.9 `/FontFile` — the weight a Type 1 program names in its `FontInfo`
|
|
151
|
+
* (`/Weight (Bold)`), read off the cleartext that opens it. pdfTeX states no
|
|
152
|
+
* weight in the descriptor, and names URW's bold Times "NimbusRomNo9L-Medi",
|
|
153
|
+
* which no rule of names reads as bold: comments.pdf's headings and captions
|
|
154
|
+
* came back in the body's weight. Its program says "Bold"; Computer Modern's
|
|
155
|
+
* say "Medium", which is their book weight.
|
|
156
|
+
*
|
|
157
|
+
* @param file The document.
|
|
158
|
+
* @param fontDict The font dictionary.
|
|
159
|
+
* @returns The style, or `undefined` where no program names a weight.
|
|
160
|
+
*/
|
|
161
|
+
function typeOneStyle(file, fontDict) {
|
|
162
|
+
const owner = descendant(file, fontDict) ?? fontDict;
|
|
163
|
+
const descriptor = file.resolve(owner.get("FontDescriptor") ?? PDF_NULL);
|
|
164
|
+
if (!(descriptor instanceof Map)) return void 0;
|
|
165
|
+
const program = file.resolve(descriptor.get("FontFile") ?? PDF_NULL);
|
|
166
|
+
if (!(program instanceof PdfStream)) return void 0;
|
|
167
|
+
const bytes = file.streamData(program);
|
|
168
|
+
const clear = new TextDecoder("latin1").decode(bytes.subarray(0, TYPE_ONE_HEAD));
|
|
169
|
+
const weight = /\/Weight\s*\(([^)]*)\)/u.exec(clear)?.[1];
|
|
170
|
+
return weight === void 0 ? void 0 : {
|
|
171
|
+
bold: /bold|black|heavy|semib|demi/iu.test(weight),
|
|
172
|
+
italic: false
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/** How far into a Type 1 program its `FontInfo` stands, at the most. */
|
|
176
|
+
var TYPE_ONE_HEAD = 8192;
|
|
108
177
|
/** §9.9 `/FontFile2` — the TrueType program, off the font or its descendant. */
|
|
109
178
|
function fontProgram(file, fontDict) {
|
|
110
179
|
const owner = descendant(file, fontDict) ?? fontDict;
|
|
@@ -123,4 +192,4 @@ function descendant(file, fontDict) {
|
|
|
123
192
|
return first instanceof Map ? first : void 0;
|
|
124
193
|
}
|
|
125
194
|
//#endregion
|
|
126
|
-
export { collectEmbeddedFonts, embeddedFontName, hasLiftableProgram };
|
|
195
|
+
export { collectEmbeddedFonts, eachPageFont, embeddedFontName, hasLiftableProgram, programStyle };
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
/** One of the base encodings this reader has a table for (Annex D.2). */
|
|
2
2
|
export type BaseEncodingName = 'StandardEncoding' | 'WinAnsiEncoding' | 'MacRomanEncoding';
|
|
3
|
+
/**
|
|
4
|
+
* The glyph a code of WinAnsiEncoding's Latin-1 half selects, by name (see
|
|
5
|
+
* `WIN_ANSI_LATIN`).
|
|
6
|
+
*
|
|
7
|
+
* @param code A one-byte code.
|
|
8
|
+
* @returns The Annex D.2 glyph name, or `undefined` outside 0xA0–0xFF.
|
|
9
|
+
*/
|
|
10
|
+
export declare function winAnsiLatinName(code: number): string | undefined;
|
|
3
11
|
/**
|
|
4
12
|
* The glyph names of a base encoding, or `undefined` for a name this has no
|
|
5
13
|
* table for — `/MacExpertEncoding`, whose repertory no reader here can set.
|