pdf-codec 1.3.0 → 1.4.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 +38 -0
- package/dist/afm-widths-BoeTOK2r.cjs +826 -0
- package/dist/afm-widths-Dxucrg7D.js +779 -0
- package/dist/afm-widths-DyDq56Ph.d.cts +19 -0
- package/dist/afm-widths-DyDq56Ph.d.ts +19 -0
- package/dist/afm-widths.cjs +4 -0
- package/dist/afm-widths.d.cts +2 -0
- package/dist/afm-widths.d.ts +2 -0
- package/dist/afm-widths.js +2 -0
- package/dist/assets/stix-two-math-font.cjs +5 -0
- package/dist/assets/stix-two-math-font.d.cts +4 -0
- package/dist/assets/stix-two-math-font.d.ts +4 -0
- package/dist/assets/stix-two-math-font.js +4 -0
- package/dist/bytes/crc32.cjs +21 -0
- package/dist/bytes/crc32.d.cts +4 -0
- package/dist/bytes/crc32.d.ts +4 -0
- package/dist/bytes/crc32.js +20 -0
- package/dist/bytes/flate.cjs +53 -0
- package/dist/bytes/flate.d.cts +12 -0
- package/dist/bytes/flate.d.ts +12 -0
- package/dist/bytes/flate.js +49 -0
- package/dist/bytes/reader.cjs +60 -0
- package/dist/bytes/reader.d.cts +20 -0
- package/dist/bytes/reader.d.ts +20 -0
- package/dist/bytes/reader.js +58 -0
- package/dist/bytes/writer.cjs +37 -0
- package/dist/bytes/writer.d.cts +13 -0
- package/dist/bytes/writer.d.ts +13 -0
- package/dist/bytes/writer.js +35 -0
- package/dist/cmap.cjs +110 -0
- package/dist/cmap.d.cts +8 -0
- package/dist/cmap.d.ts +8 -0
- package/dist/cmap.js +109 -0
- package/dist/codec.cjs +34 -0
- package/dist/codec.d.cts +167 -0
- package/dist/codec.d.ts +167 -0
- package/dist/codec.js +32 -0
- package/dist/content-read.cjs +126 -0
- package/dist/content-read.d.cts +21 -0
- package/dist/content-read.d.ts +21 -0
- package/dist/content-read.js +125 -0
- package/dist/content-write.cjs +138 -0
- package/dist/content-write.d.cts +24 -0
- package/dist/content-write.d.ts +24 -0
- package/dist/content-write.js +137 -0
- package/dist/diagnostics.cjs +21 -0
- package/dist/diagnostics.d.cts +19 -0
- package/dist/diagnostics.d.ts +19 -0
- package/dist/diagnostics.js +18 -0
- package/dist/document.cjs +162 -0
- package/dist/document.d.cts +12 -0
- package/dist/document.d.ts +12 -0
- package/dist/document.js +161 -0
- package/dist/encoding.cjs +5 -0
- package/dist/encoding.d.cts +6 -0
- package/dist/encoding.d.ts +6 -0
- package/dist/encoding.js +2 -0
- package/dist/filters.cjs +223 -0
- package/dist/filters.d.cts +14 -0
- package/dist/filters.d.ts +14 -0
- package/dist/filters.js +218 -0
- package/dist/font-read.cjs +199 -0
- package/dist/font-read.d.cts +23 -0
- package/dist/font-read.d.ts +23 -0
- package/dist/font-read.js +198 -0
- package/dist/font-style.cjs +35 -0
- package/dist/font-style.d.cts +14 -0
- package/dist/font-style.d.ts +14 -0
- package/dist/font-style.js +34 -0
- package/dist/fonts.cjs +124 -0
- package/dist/fonts.d.cts +15 -0
- package/dist/fonts.d.ts +15 -0
- package/dist/fonts.js +122 -0
- package/dist/formula.cjs +0 -0
- package/dist/formula.d.cts +10 -0
- package/dist/formula.d.ts +10 -0
- package/dist/formula.js +0 -0
- package/dist/image/jpeg-info.cjs +71 -0
- package/dist/image/jpeg-info.d.cts +12 -0
- package/dist/image/jpeg-info.d.ts +12 -0
- package/dist/image/jpeg-info.js +70 -0
- package/dist/image/png-decode.cjs +181 -0
- package/dist/image/png-decode.d.cts +14 -0
- package/dist/image/png-decode.d.ts +14 -0
- package/dist/image/png-decode.js +180 -0
- package/dist/image/png-encode.cjs +64 -0
- package/dist/image/png-encode.d.cts +8 -0
- package/dist/image/png-encode.d.ts +8 -0
- package/dist/image/png-encode.js +63 -0
- package/dist/image/png-filter.cjs +95 -0
- package/dist/image/png-filter.d.cts +6 -0
- package/dist/image/png-filter.d.ts +6 -0
- package/dist/image/png-filter.js +93 -0
- package/dist/images-read.cjs +250 -0
- package/dist/images-read.d.cts +13 -0
- package/dist/images-read.d.ts +13 -0
- package/dist/images-read.js +249 -0
- package/dist/index.cjs +45 -5912
- package/dist/index.d.cts +21 -483
- package/dist/index.d.ts +21 -483
- package/dist/index.js +18 -5885
- package/dist/interpret.cjs +587 -0
- package/dist/interpret.d.cts +84 -0
- package/dist/interpret.d.ts +84 -0
- package/dist/interpret.js +586 -0
- package/dist/lexer.cjs +180 -0
- package/dist/lexer.d.cts +29 -0
- package/dist/lexer.d.ts +29 -0
- package/dist/lexer.js +179 -0
- package/dist/math-cmap.cjs +81 -0
- package/dist/math-cmap.d.cts +6 -0
- package/dist/math-cmap.d.ts +6 -0
- package/dist/math-cmap.js +80 -0
- package/dist/math-content-write.cjs +83 -0
- package/dist/math-content-write.d.cts +11 -0
- package/dist/math-content-write.d.ts +11 -0
- package/dist/math-content-write.js +81 -0
- package/dist/math-font-write.cjs +100 -0
- package/dist/math-font-write.d.cts +19 -0
- package/dist/math-font-write.d.ts +19 -0
- package/dist/math-font-write.js +99 -0
- package/dist/math-font.cjs +103 -0
- package/dist/math-font.d.cts +25 -0
- package/dist/math-font.d.ts +25 -0
- package/dist/math-font.js +102 -0
- package/dist/math-hmtx.cjs +17 -0
- package/dist/math-hmtx.d.cts +8 -0
- package/dist/math-hmtx.d.ts +8 -0
- package/dist/math-hmtx.js +16 -0
- package/dist/math-table.cjs +117 -0
- package/dist/math-table.d.cts +45 -0
- package/dist/math-table.d.ts +45 -0
- package/dist/math-table.js +116 -0
- package/dist/math-types-Ba8qAf1p.d.cts +82 -0
- package/dist/math-types-Ba8qAf1p.d.ts +82 -0
- package/dist/math-types.cjs +0 -0
- package/dist/math-types.d.cts +2 -0
- package/dist/math-types.d.ts +2 -0
- package/dist/math-types.js +0 -0
- package/dist/matrix-B3c2_a2f.d.cts +18 -0
- package/dist/matrix-B3c2_a2f.d.ts +18 -0
- package/dist/matrix.cjs +93 -0
- package/dist/matrix.d.cts +2 -0
- package/dist/matrix.d.ts +2 -0
- package/dist/matrix.js +83 -0
- package/dist/measure.cjs +54 -0
- package/dist/measure.d.cts +20 -0
- package/dist/measure.d.ts +20 -0
- package/dist/measure.js +53 -0
- package/dist/objects.cjs +100 -0
- package/dist/objects.d.cts +58 -0
- package/dist/objects.d.ts +58 -0
- package/dist/objects.js +84 -0
- package/dist/parse.cjs +230 -0
- package/dist/parse.d.cts +13 -0
- package/dist/parse.d.ts +13 -0
- package/dist/parse.js +228 -0
- package/dist/predictors.cjs +64 -0
- package/dist/predictors.d.cts +13 -0
- package/dist/predictors.d.ts +13 -0
- package/dist/predictors.js +62 -0
- package/dist/read.cjs +418 -0
- package/dist/read.d.cts +21 -0
- package/dist/read.d.ts +21 -0
- package/dist/read.js +413 -0
- package/dist/serialize.cjs +69 -0
- package/dist/serialize.d.cts +8 -0
- package/dist/serialize.d.ts +8 -0
- package/dist/serialize.js +66 -0
- package/dist/sfnt.cjs +52 -0
- package/dist/sfnt.d.cts +17 -0
- package/dist/sfnt.d.ts +17 -0
- package/dist/sfnt.js +46 -0
- package/dist/text-layout.cjs +224 -0
- package/dist/text-layout.d.cts +37 -0
- package/dist/text-layout.d.ts +37 -0
- package/dist/text-layout.js +222 -0
- package/dist/util/abort.cjs +7 -0
- package/dist/util/abort.d.cts +4 -0
- package/dist/util/abort.d.ts +4 -0
- package/dist/util/abort.js +6 -0
- package/dist/util/base64.cjs +48 -0
- package/dist/util/base64.d.cts +5 -0
- package/dist/util/base64.d.ts +5 -0
- package/dist/util/base64.js +46 -0
- package/dist/winansi.cjs +5 -0
- package/dist/winansi.d.cts +20 -0
- package/dist/winansi.d.ts +20 -0
- package/dist/winansi.js +2 -0
- package/dist/write.cjs +421 -0
- package/dist/write.d.cts +16 -0
- package/dist/write.d.ts +16 -0
- package/dist/write.js +419 -0
- package/dist/xref.cjs +325 -0
- package/dist/xref.d.cts +21 -0
- package/dist/xref.d.ts +21 -0
- package/dist/xref.js +324 -0
- package/package.json +9 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { PdfDiagnosticSink } from "./diagnostics.js";
|
|
2
|
+
import { PdfDict, PdfObject } from "./objects.js";
|
|
3
|
+
import { n as Matrix } from "./matrix-B3c2_a2f.js";
|
|
4
|
+
import { Color } from "document-schema.js";
|
|
5
|
+
//#region src/interpret.d.ts
|
|
6
|
+
interface ExtractedTextRun {
|
|
7
|
+
readonly kind: 'text';
|
|
8
|
+
readonly codes: Uint8Array<ArrayBuffer>;
|
|
9
|
+
readonly fontResourceName: string;
|
|
10
|
+
readonly resources: PdfDict;
|
|
11
|
+
readonly startMatrix: Matrix;
|
|
12
|
+
readonly endMatrix: Matrix;
|
|
13
|
+
readonly sizePt: number;
|
|
14
|
+
readonly color: Color;
|
|
15
|
+
}
|
|
16
|
+
interface ExtractedRect {
|
|
17
|
+
readonly kind: 'rect';
|
|
18
|
+
readonly xPt: number;
|
|
19
|
+
readonly yPt: number;
|
|
20
|
+
readonly widthPt: number;
|
|
21
|
+
readonly heightPt: number;
|
|
22
|
+
readonly color: Color;
|
|
23
|
+
}
|
|
24
|
+
type ExtractedPathSegment = {
|
|
25
|
+
readonly kind: 'line';
|
|
26
|
+
readonly xPt: number;
|
|
27
|
+
readonly yPt: number;
|
|
28
|
+
} | {
|
|
29
|
+
readonly kind: 'cubic';
|
|
30
|
+
readonly c1xPt: number;
|
|
31
|
+
readonly c1yPt: number;
|
|
32
|
+
readonly c2xPt: number;
|
|
33
|
+
readonly c2yPt: number;
|
|
34
|
+
readonly xPt: number;
|
|
35
|
+
readonly yPt: number;
|
|
36
|
+
};
|
|
37
|
+
interface ExtractedSubpath {
|
|
38
|
+
readonly startXPt: number;
|
|
39
|
+
readonly startYPt: number;
|
|
40
|
+
readonly segments: readonly ExtractedPathSegment[];
|
|
41
|
+
readonly closed: boolean;
|
|
42
|
+
}
|
|
43
|
+
interface ExtractedPath {
|
|
44
|
+
readonly kind: 'path';
|
|
45
|
+
readonly subpaths: readonly ExtractedSubpath[];
|
|
46
|
+
readonly fillRule: 'nonzero' | 'evenodd';
|
|
47
|
+
readonly fill: Color | undefined;
|
|
48
|
+
readonly stroke: {
|
|
49
|
+
readonly color: Color;
|
|
50
|
+
readonly widthPt: number;
|
|
51
|
+
} | undefined;
|
|
52
|
+
}
|
|
53
|
+
interface ExtractedImage {
|
|
54
|
+
readonly kind: 'image';
|
|
55
|
+
readonly resourceName: string;
|
|
56
|
+
readonly resources: PdfDict;
|
|
57
|
+
readonly matrix: Matrix;
|
|
58
|
+
}
|
|
59
|
+
interface ExtractedInlineImage {
|
|
60
|
+
readonly kind: 'inlineImage';
|
|
61
|
+
readonly dict: PdfDict;
|
|
62
|
+
readonly data: Uint8Array<ArrayBuffer>;
|
|
63
|
+
readonly matrix: Matrix;
|
|
64
|
+
}
|
|
65
|
+
type ExtractedItem = ExtractedTextRun | ExtractedRect | ExtractedPath | ExtractedImage | ExtractedInlineImage;
|
|
66
|
+
interface GlyphAdvance {
|
|
67
|
+
readonly widthPer1000: number;
|
|
68
|
+
readonly byteLengthConsumed: number;
|
|
69
|
+
}
|
|
70
|
+
interface FontMetricsPort {
|
|
71
|
+
glyphAdvance(fontResourceName: string, resources: PdfDict, codes: Uint8Array<ArrayBuffer>, byteOffset: number): GlyphAdvance | undefined;
|
|
72
|
+
}
|
|
73
|
+
interface PdfObjectResolver {
|
|
74
|
+
resolve(obj: PdfObject | undefined): PdfObject | undefined;
|
|
75
|
+
resolveDict(obj: PdfObject | undefined): PdfDict | undefined;
|
|
76
|
+
}
|
|
77
|
+
interface InterpretContext {
|
|
78
|
+
readonly fontMetrics: FontMetricsPort;
|
|
79
|
+
readonly resolver: PdfObjectResolver;
|
|
80
|
+
readonly sink: PdfDiagnosticSink;
|
|
81
|
+
}
|
|
82
|
+
declare function interpretContentStream(bytes: Uint8Array<ArrayBuffer>, resources: PdfDict, context: InterpretContext): ExtractedItem[];
|
|
83
|
+
//#endregion
|
|
84
|
+
export { ExtractedImage, ExtractedInlineImage, ExtractedItem, ExtractedPath, ExtractedPathSegment, ExtractedRect, ExtractedSubpath, ExtractedTextRun, FontMetricsPort, GlyphAdvance, InterpretContext, PdfObjectResolver, interpretContentStream };
|
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
import { asArray, asName, asNumber, dictGet } from "./objects.js";
|
|
2
|
+
import { decodeStream } from "./filters.js";
|
|
3
|
+
import { IDENTITY_MATRIX, applyMatrix, multiplyMatrices, translationMatrix } from "./matrix.js";
|
|
4
|
+
import { readContentStream } from "./content-read.js";
|
|
5
|
+
import { COLOR_BLACK } from "document-schema.js";
|
|
6
|
+
//#region src/interpret.ts
|
|
7
|
+
const MAX_FORM_XOBJECT_DEPTH = 12;
|
|
8
|
+
const FALLBACK_GLYPH_WIDTH_PER_1000 = 500;
|
|
9
|
+
const DEFAULT_LINE_WIDTH_PT = 1;
|
|
10
|
+
function defaultTextState() {
|
|
11
|
+
return {
|
|
12
|
+
tm: IDENTITY_MATRIX,
|
|
13
|
+
tlm: IDENTITY_MATRIX,
|
|
14
|
+
fontResourceName: void 0,
|
|
15
|
+
fontSizePt: 0,
|
|
16
|
+
charSpace: 0,
|
|
17
|
+
wordSpace: 0,
|
|
18
|
+
horizScale: 1,
|
|
19
|
+
leading: 0,
|
|
20
|
+
rise: 0
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function computeTrm(ctm, ts) {
|
|
24
|
+
const fontMatrix = [
|
|
25
|
+
ts.fontSizePt * ts.horizScale,
|
|
26
|
+
0,
|
|
27
|
+
0,
|
|
28
|
+
ts.fontSizePt,
|
|
29
|
+
0,
|
|
30
|
+
ts.rise
|
|
31
|
+
];
|
|
32
|
+
return multiplyMatrices(multiplyMatrices(fontMatrix, ts.tm), ctm);
|
|
33
|
+
}
|
|
34
|
+
function numAt(operands, index) {
|
|
35
|
+
return asNumber(operands[index]) ?? 0;
|
|
36
|
+
}
|
|
37
|
+
function grayColor(value) {
|
|
38
|
+
return {
|
|
39
|
+
r: value,
|
|
40
|
+
g: value,
|
|
41
|
+
b: value
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function rgbColor(operands) {
|
|
45
|
+
return {
|
|
46
|
+
r: numAt(operands, 0),
|
|
47
|
+
g: numAt(operands, 1),
|
|
48
|
+
b: numAt(operands, 2)
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function cmykColor(operands) {
|
|
52
|
+
const c = numAt(operands, 0);
|
|
53
|
+
const m = numAt(operands, 1);
|
|
54
|
+
const y = numAt(operands, 2);
|
|
55
|
+
const k = numAt(operands, 3);
|
|
56
|
+
return {
|
|
57
|
+
r: (1 - c) * (1 - k),
|
|
58
|
+
g: (1 - m) * (1 - k),
|
|
59
|
+
b: (1 - y) * (1 - k)
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function genericColor(operands) {
|
|
63
|
+
const numericOperands = operands.filter((o) => o.kind === "number");
|
|
64
|
+
if (numericOperands.length === 1) return grayColor(numAt(numericOperands, 0));
|
|
65
|
+
if (numericOperands.length === 3) return rgbColor(numericOperands);
|
|
66
|
+
if (numericOperands.length === 4) return cmykColor(numericOperands);
|
|
67
|
+
}
|
|
68
|
+
function matrixFromOperands(operands) {
|
|
69
|
+
return [
|
|
70
|
+
numAt(operands, 0),
|
|
71
|
+
numAt(operands, 1),
|
|
72
|
+
numAt(operands, 2),
|
|
73
|
+
numAt(operands, 3),
|
|
74
|
+
numAt(operands, 4),
|
|
75
|
+
numAt(operands, 5)
|
|
76
|
+
];
|
|
77
|
+
}
|
|
78
|
+
function isAxisAligned(m) {
|
|
79
|
+
return m[1] === 0 && m[2] === 0;
|
|
80
|
+
}
|
|
81
|
+
function rectFromOperands(operands, ctm) {
|
|
82
|
+
const x = numAt(operands, 0);
|
|
83
|
+
const y = numAt(operands, 1);
|
|
84
|
+
const w = numAt(operands, 2);
|
|
85
|
+
const h = numAt(operands, 3);
|
|
86
|
+
if (!isAxisAligned(ctm)) return;
|
|
87
|
+
const scaledX = x * ctm[0] + ctm[4];
|
|
88
|
+
const scaledY = y * ctm[3] + ctm[5];
|
|
89
|
+
const scaledW = w * ctm[0];
|
|
90
|
+
const scaledH = h * ctm[3];
|
|
91
|
+
return {
|
|
92
|
+
xPt: scaledW >= 0 ? scaledX : scaledX + scaledW,
|
|
93
|
+
yPt: scaledH >= 0 ? scaledY : scaledY + scaledH,
|
|
94
|
+
widthPt: Math.abs(scaledW),
|
|
95
|
+
heightPt: Math.abs(scaledH)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function interpretContentStream(bytes, resources, context) {
|
|
99
|
+
const items = [];
|
|
100
|
+
runContentStream(bytes, resources, {
|
|
101
|
+
ctm: IDENTITY_MATRIX,
|
|
102
|
+
fillColor: COLOR_BLACK,
|
|
103
|
+
strokeColor: COLOR_BLACK,
|
|
104
|
+
lineWidth: DEFAULT_LINE_WIDTH_PT
|
|
105
|
+
}, context, items, 0);
|
|
106
|
+
return items;
|
|
107
|
+
}
|
|
108
|
+
function lastPointOf(subpath) {
|
|
109
|
+
const last = subpath.segments[subpath.segments.length - 1];
|
|
110
|
+
return last === void 0 ? {
|
|
111
|
+
x: subpath.startXPt,
|
|
112
|
+
y: subpath.startYPt
|
|
113
|
+
} : {
|
|
114
|
+
x: last.xPt,
|
|
115
|
+
y: last.yPt
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function runContentStream(bytes, resources, initialState, context, items, depth) {
|
|
119
|
+
const operations = readContentStream(bytes, context.sink);
|
|
120
|
+
const gsStack = [];
|
|
121
|
+
let gs = initialState;
|
|
122
|
+
let ts = defaultTextState();
|
|
123
|
+
let pendingRect;
|
|
124
|
+
let pathSubpaths = [];
|
|
125
|
+
let currentSubpath;
|
|
126
|
+
const finalizeCurrentSubpath = () => {
|
|
127
|
+
if (currentSubpath !== void 0) {
|
|
128
|
+
pathSubpaths.push(currentSubpath);
|
|
129
|
+
currentSubpath = void 0;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const resetPath = () => {
|
|
133
|
+
pendingRect = void 0;
|
|
134
|
+
pathSubpaths = [];
|
|
135
|
+
currentSubpath = void 0;
|
|
136
|
+
};
|
|
137
|
+
const appendRectSubpath = (operands, ctm) => {
|
|
138
|
+
finalizeCurrentSubpath();
|
|
139
|
+
const x = numAt(operands, 0);
|
|
140
|
+
const y = numAt(operands, 1);
|
|
141
|
+
const w = numAt(operands, 2);
|
|
142
|
+
const h = numAt(operands, 3);
|
|
143
|
+
const p1 = applyMatrix(ctm, {
|
|
144
|
+
x,
|
|
145
|
+
y
|
|
146
|
+
});
|
|
147
|
+
const p2 = applyMatrix(ctm, {
|
|
148
|
+
x: x + w,
|
|
149
|
+
y
|
|
150
|
+
});
|
|
151
|
+
const p3 = applyMatrix(ctm, {
|
|
152
|
+
x: x + w,
|
|
153
|
+
y: y + h
|
|
154
|
+
});
|
|
155
|
+
const p4 = applyMatrix(ctm, {
|
|
156
|
+
x,
|
|
157
|
+
y: y + h
|
|
158
|
+
});
|
|
159
|
+
pathSubpaths.push({
|
|
160
|
+
startXPt: p1.x,
|
|
161
|
+
startYPt: p1.y,
|
|
162
|
+
segments: [
|
|
163
|
+
{
|
|
164
|
+
kind: "line",
|
|
165
|
+
xPt: p2.x,
|
|
166
|
+
yPt: p2.y
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
kind: "line",
|
|
170
|
+
xPt: p3.x,
|
|
171
|
+
yPt: p3.y
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
kind: "line",
|
|
175
|
+
xPt: p4.x,
|
|
176
|
+
yPt: p4.y
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
closed: true
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
const paintFillRuleFor = (operator) => operator.endsWith("*") ? "evenodd" : "nonzero";
|
|
183
|
+
const emitPaint = (operator) => {
|
|
184
|
+
if (operator === "n") {
|
|
185
|
+
resetPath();
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if ((operator === "s" || operator === "b" || operator === "b*") && currentSubpath !== void 0) currentSubpath.closed = true;
|
|
189
|
+
if ((operator === "f" || operator === "F" || operator === "f*") && currentSubpath === void 0 && pathSubpaths.length === 1 && pendingRect !== void 0) {
|
|
190
|
+
items.push({
|
|
191
|
+
kind: "rect",
|
|
192
|
+
...pendingRect,
|
|
193
|
+
color: gs.fillColor
|
|
194
|
+
});
|
|
195
|
+
resetPath();
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
finalizeCurrentSubpath();
|
|
199
|
+
if (pathSubpaths.length > 0) {
|
|
200
|
+
const isFillOp = operator === "f" || operator === "F" || operator === "f*" || operator === "B" || operator === "B*" || operator === "b" || operator === "b*";
|
|
201
|
+
const isStrokeOp = operator === "S" || operator === "s" || operator === "B" || operator === "B*" || operator === "b" || operator === "b*";
|
|
202
|
+
items.push({
|
|
203
|
+
kind: "path",
|
|
204
|
+
subpaths: pathSubpaths,
|
|
205
|
+
fillRule: paintFillRuleFor(operator),
|
|
206
|
+
fill: isFillOp ? gs.fillColor : void 0,
|
|
207
|
+
stroke: isStrokeOp ? {
|
|
208
|
+
color: gs.strokeColor,
|
|
209
|
+
widthPt: gs.lineWidth
|
|
210
|
+
} : void 0
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
resetPath();
|
|
214
|
+
};
|
|
215
|
+
const advanceThroughString = (codes) => {
|
|
216
|
+
if (ts.fontResourceName === void 0) return;
|
|
217
|
+
let offset = 0;
|
|
218
|
+
while (offset < codes.length) {
|
|
219
|
+
const glyph = context.fontMetrics.glyphAdvance(ts.fontResourceName, resources, codes, offset);
|
|
220
|
+
if (glyph === void 0) context.sink({
|
|
221
|
+
code: "pdf/font-not-resolved",
|
|
222
|
+
severity: "warning",
|
|
223
|
+
message: `could not resolve font resource /${ts.fontResourceName} to compute a glyph advance; assuming a fallback width`
|
|
224
|
+
});
|
|
225
|
+
const widthPer1000 = glyph?.widthPer1000 ?? FALLBACK_GLYPH_WIDTH_PER_1000;
|
|
226
|
+
const byteLength = glyph?.byteLengthConsumed ?? 1;
|
|
227
|
+
const isSingleByteSpace = byteLength === 1 && codes[offset] === 32;
|
|
228
|
+
const tx = (widthPer1000 / 1e3 * ts.fontSizePt + ts.charSpace + (isSingleByteSpace ? ts.wordSpace : 0)) * ts.horizScale;
|
|
229
|
+
ts.tm = multiplyMatrices(translationMatrix(tx, 0), ts.tm);
|
|
230
|
+
offset += byteLength;
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
const showTextArray = (elements) => {
|
|
234
|
+
if (ts.fontResourceName === void 0) return;
|
|
235
|
+
const startMatrix = computeTrm(gs.ctm, ts);
|
|
236
|
+
const chunks = [];
|
|
237
|
+
let totalLength = 0;
|
|
238
|
+
for (const el of elements) if (el.kind === "string") {
|
|
239
|
+
chunks.push(el.bytes);
|
|
240
|
+
totalLength += el.bytes.length;
|
|
241
|
+
advanceThroughString(el.bytes);
|
|
242
|
+
} else if (el.kind === "number") {
|
|
243
|
+
const adjustment = -(el.value / 1e3) * ts.fontSizePt * ts.horizScale;
|
|
244
|
+
ts.tm = multiplyMatrices(translationMatrix(adjustment, 0), ts.tm);
|
|
245
|
+
}
|
|
246
|
+
if (totalLength === 0) return;
|
|
247
|
+
const combined = new Uint8Array(totalLength);
|
|
248
|
+
let at = 0;
|
|
249
|
+
for (const chunk of chunks) {
|
|
250
|
+
combined.set(chunk, at);
|
|
251
|
+
at += chunk.length;
|
|
252
|
+
}
|
|
253
|
+
const endMatrix = computeTrm(gs.ctm, ts);
|
|
254
|
+
items.push({
|
|
255
|
+
kind: "text",
|
|
256
|
+
codes: combined,
|
|
257
|
+
fontResourceName: ts.fontResourceName,
|
|
258
|
+
resources,
|
|
259
|
+
startMatrix,
|
|
260
|
+
endMatrix,
|
|
261
|
+
sizePt: ts.fontSizePt,
|
|
262
|
+
color: gs.fillColor
|
|
263
|
+
});
|
|
264
|
+
};
|
|
265
|
+
const showText = (bytes) => {
|
|
266
|
+
showTextArray([{
|
|
267
|
+
kind: "string",
|
|
268
|
+
bytes,
|
|
269
|
+
hex: false
|
|
270
|
+
}]);
|
|
271
|
+
};
|
|
272
|
+
const nextLine = () => {
|
|
273
|
+
ts.tlm = multiplyMatrices(translationMatrix(0, -ts.leading), ts.tlm);
|
|
274
|
+
ts.tm = ts.tlm;
|
|
275
|
+
};
|
|
276
|
+
const handleDo = (name) => {
|
|
277
|
+
if (name === void 0) return;
|
|
278
|
+
const xobjects = context.resolver.resolveDict(dictGet(resources, "XObject"));
|
|
279
|
+
const xobj = xobjects !== void 0 ? context.resolver.resolve(dictGet(xobjects, name)) : void 0;
|
|
280
|
+
if (xobj?.kind !== "stream") {
|
|
281
|
+
context.sink({
|
|
282
|
+
code: "pdf/xobject-not-resolved",
|
|
283
|
+
severity: "warning",
|
|
284
|
+
message: `XObject resource /${name} did not resolve to a stream`
|
|
285
|
+
});
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const subtype = asName(dictGet(xobj.dict, "Subtype"));
|
|
289
|
+
if (subtype === "Image") {
|
|
290
|
+
items.push({
|
|
291
|
+
kind: "image",
|
|
292
|
+
resourceName: name,
|
|
293
|
+
resources,
|
|
294
|
+
matrix: gs.ctm
|
|
295
|
+
});
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
if (subtype === "Form") {
|
|
299
|
+
if (depth >= MAX_FORM_XOBJECT_DEPTH) {
|
|
300
|
+
context.sink({
|
|
301
|
+
code: "pdf/form-recursion-limit",
|
|
302
|
+
severity: "warning",
|
|
303
|
+
message: "form XObject recursion exceeded the depth limit; skipping further nesting"
|
|
304
|
+
});
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const formMatrixArr = asArray(dictGet(xobj.dict, "Matrix"));
|
|
308
|
+
const formMatrix = formMatrixArr !== void 0 ? matrixFromOperands(formMatrixArr) : IDENTITY_MATRIX;
|
|
309
|
+
const formResources = context.resolver.resolveDict(dictGet(xobj.dict, "Resources")) ?? resources;
|
|
310
|
+
const decoded = decodeStream(xobj.raw, xobj.dict, context.sink);
|
|
311
|
+
const formState = {
|
|
312
|
+
...gs,
|
|
313
|
+
ctm: multiplyMatrices(formMatrix, gs.ctm)
|
|
314
|
+
};
|
|
315
|
+
runContentStream(decoded.bytes, formResources, formState, context, items, depth + 1);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
for (const token of operations) {
|
|
319
|
+
if (token.kind === "inlineImage") {
|
|
320
|
+
items.push({
|
|
321
|
+
kind: "inlineImage",
|
|
322
|
+
dict: token.image.dict,
|
|
323
|
+
data: token.image.data,
|
|
324
|
+
matrix: gs.ctm
|
|
325
|
+
});
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
const { operands, operator } = token.operation;
|
|
329
|
+
switch (operator) {
|
|
330
|
+
case "q":
|
|
331
|
+
gsStack.push(gs);
|
|
332
|
+
break;
|
|
333
|
+
case "Q":
|
|
334
|
+
gs = gsStack.pop() ?? gs;
|
|
335
|
+
break;
|
|
336
|
+
case "cm":
|
|
337
|
+
gs = {
|
|
338
|
+
...gs,
|
|
339
|
+
ctm: multiplyMatrices(matrixFromOperands(operands), gs.ctm)
|
|
340
|
+
};
|
|
341
|
+
break;
|
|
342
|
+
case "g":
|
|
343
|
+
gs = {
|
|
344
|
+
...gs,
|
|
345
|
+
fillColor: grayColor(numAt(operands, 0))
|
|
346
|
+
};
|
|
347
|
+
break;
|
|
348
|
+
case "G":
|
|
349
|
+
gs = {
|
|
350
|
+
...gs,
|
|
351
|
+
strokeColor: grayColor(numAt(operands, 0))
|
|
352
|
+
};
|
|
353
|
+
break;
|
|
354
|
+
case "rg":
|
|
355
|
+
gs = {
|
|
356
|
+
...gs,
|
|
357
|
+
fillColor: rgbColor(operands)
|
|
358
|
+
};
|
|
359
|
+
break;
|
|
360
|
+
case "RG":
|
|
361
|
+
gs = {
|
|
362
|
+
...gs,
|
|
363
|
+
strokeColor: rgbColor(operands)
|
|
364
|
+
};
|
|
365
|
+
break;
|
|
366
|
+
case "k":
|
|
367
|
+
gs = {
|
|
368
|
+
...gs,
|
|
369
|
+
fillColor: cmykColor(operands)
|
|
370
|
+
};
|
|
371
|
+
break;
|
|
372
|
+
case "K":
|
|
373
|
+
gs = {
|
|
374
|
+
...gs,
|
|
375
|
+
strokeColor: cmykColor(operands)
|
|
376
|
+
};
|
|
377
|
+
break;
|
|
378
|
+
case "sc":
|
|
379
|
+
case "scn": {
|
|
380
|
+
const color = genericColor(operands);
|
|
381
|
+
if (color !== void 0) gs = {
|
|
382
|
+
...gs,
|
|
383
|
+
fillColor: color
|
|
384
|
+
};
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
case "SC":
|
|
388
|
+
case "SCN": {
|
|
389
|
+
const color = genericColor(operands);
|
|
390
|
+
if (color !== void 0) gs = {
|
|
391
|
+
...gs,
|
|
392
|
+
strokeColor: color
|
|
393
|
+
};
|
|
394
|
+
break;
|
|
395
|
+
}
|
|
396
|
+
case "re":
|
|
397
|
+
pendingRect = rectFromOperands(operands, gs.ctm);
|
|
398
|
+
appendRectSubpath(operands, gs.ctm);
|
|
399
|
+
break;
|
|
400
|
+
case "m": {
|
|
401
|
+
finalizeCurrentSubpath();
|
|
402
|
+
const p = applyMatrix(gs.ctm, {
|
|
403
|
+
x: numAt(operands, 0),
|
|
404
|
+
y: numAt(operands, 1)
|
|
405
|
+
});
|
|
406
|
+
currentSubpath = {
|
|
407
|
+
startXPt: p.x,
|
|
408
|
+
startYPt: p.y,
|
|
409
|
+
segments: [],
|
|
410
|
+
closed: false
|
|
411
|
+
};
|
|
412
|
+
pendingRect = void 0;
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
case "l": {
|
|
416
|
+
const p = applyMatrix(gs.ctm, {
|
|
417
|
+
x: numAt(operands, 0),
|
|
418
|
+
y: numAt(operands, 1)
|
|
419
|
+
});
|
|
420
|
+
currentSubpath?.segments.push({
|
|
421
|
+
kind: "line",
|
|
422
|
+
xPt: p.x,
|
|
423
|
+
yPt: p.y
|
|
424
|
+
});
|
|
425
|
+
pendingRect = void 0;
|
|
426
|
+
break;
|
|
427
|
+
}
|
|
428
|
+
case "c": {
|
|
429
|
+
const c1 = applyMatrix(gs.ctm, {
|
|
430
|
+
x: numAt(operands, 0),
|
|
431
|
+
y: numAt(operands, 1)
|
|
432
|
+
});
|
|
433
|
+
const c2 = applyMatrix(gs.ctm, {
|
|
434
|
+
x: numAt(operands, 2),
|
|
435
|
+
y: numAt(operands, 3)
|
|
436
|
+
});
|
|
437
|
+
const p = applyMatrix(gs.ctm, {
|
|
438
|
+
x: numAt(operands, 4),
|
|
439
|
+
y: numAt(operands, 5)
|
|
440
|
+
});
|
|
441
|
+
currentSubpath?.segments.push({
|
|
442
|
+
kind: "cubic",
|
|
443
|
+
c1xPt: c1.x,
|
|
444
|
+
c1yPt: c1.y,
|
|
445
|
+
c2xPt: c2.x,
|
|
446
|
+
c2yPt: c2.y,
|
|
447
|
+
xPt: p.x,
|
|
448
|
+
yPt: p.y
|
|
449
|
+
});
|
|
450
|
+
pendingRect = void 0;
|
|
451
|
+
break;
|
|
452
|
+
}
|
|
453
|
+
case "v":
|
|
454
|
+
if (currentSubpath !== void 0) {
|
|
455
|
+
const cur = lastPointOf(currentSubpath);
|
|
456
|
+
const c2 = applyMatrix(gs.ctm, {
|
|
457
|
+
x: numAt(operands, 0),
|
|
458
|
+
y: numAt(operands, 1)
|
|
459
|
+
});
|
|
460
|
+
const p = applyMatrix(gs.ctm, {
|
|
461
|
+
x: numAt(operands, 2),
|
|
462
|
+
y: numAt(operands, 3)
|
|
463
|
+
});
|
|
464
|
+
currentSubpath.segments.push({
|
|
465
|
+
kind: "cubic",
|
|
466
|
+
c1xPt: cur.x,
|
|
467
|
+
c1yPt: cur.y,
|
|
468
|
+
c2xPt: c2.x,
|
|
469
|
+
c2yPt: c2.y,
|
|
470
|
+
xPt: p.x,
|
|
471
|
+
yPt: p.y
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
pendingRect = void 0;
|
|
475
|
+
break;
|
|
476
|
+
case "y": {
|
|
477
|
+
const c1 = applyMatrix(gs.ctm, {
|
|
478
|
+
x: numAt(operands, 0),
|
|
479
|
+
y: numAt(operands, 1)
|
|
480
|
+
});
|
|
481
|
+
const p = applyMatrix(gs.ctm, {
|
|
482
|
+
x: numAt(operands, 2),
|
|
483
|
+
y: numAt(operands, 3)
|
|
484
|
+
});
|
|
485
|
+
currentSubpath?.segments.push({
|
|
486
|
+
kind: "cubic",
|
|
487
|
+
c1xPt: c1.x,
|
|
488
|
+
c1yPt: c1.y,
|
|
489
|
+
c2xPt: p.x,
|
|
490
|
+
c2yPt: p.y,
|
|
491
|
+
xPt: p.x,
|
|
492
|
+
yPt: p.y
|
|
493
|
+
});
|
|
494
|
+
pendingRect = void 0;
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
case "h":
|
|
498
|
+
if (currentSubpath !== void 0) currentSubpath.closed = true;
|
|
499
|
+
pendingRect = void 0;
|
|
500
|
+
break;
|
|
501
|
+
case "w":
|
|
502
|
+
gs = {
|
|
503
|
+
...gs,
|
|
504
|
+
lineWidth: numAt(operands, 0)
|
|
505
|
+
};
|
|
506
|
+
break;
|
|
507
|
+
case "f":
|
|
508
|
+
case "F":
|
|
509
|
+
case "f*":
|
|
510
|
+
case "S":
|
|
511
|
+
case "s":
|
|
512
|
+
case "B":
|
|
513
|
+
case "B*":
|
|
514
|
+
case "b":
|
|
515
|
+
case "b*":
|
|
516
|
+
case "n":
|
|
517
|
+
emitPaint(operator);
|
|
518
|
+
break;
|
|
519
|
+
case "BT":
|
|
520
|
+
ts = defaultTextState();
|
|
521
|
+
break;
|
|
522
|
+
case "Tf":
|
|
523
|
+
ts.fontResourceName = asName(operands[0]);
|
|
524
|
+
ts.fontSizePt = numAt(operands, 1);
|
|
525
|
+
break;
|
|
526
|
+
case "Tc":
|
|
527
|
+
ts.charSpace = numAt(operands, 0);
|
|
528
|
+
break;
|
|
529
|
+
case "Tw":
|
|
530
|
+
ts.wordSpace = numAt(operands, 0);
|
|
531
|
+
break;
|
|
532
|
+
case "Tz":
|
|
533
|
+
ts.horizScale = numAt(operands, 0) / 100;
|
|
534
|
+
break;
|
|
535
|
+
case "TL":
|
|
536
|
+
ts.leading = numAt(operands, 0);
|
|
537
|
+
break;
|
|
538
|
+
case "Ts":
|
|
539
|
+
ts.rise = numAt(operands, 0);
|
|
540
|
+
break;
|
|
541
|
+
case "Td":
|
|
542
|
+
ts.tlm = multiplyMatrices(translationMatrix(numAt(operands, 0), numAt(operands, 1)), ts.tlm);
|
|
543
|
+
ts.tm = ts.tlm;
|
|
544
|
+
break;
|
|
545
|
+
case "TD":
|
|
546
|
+
ts.leading = -numAt(operands, 1);
|
|
547
|
+
ts.tlm = multiplyMatrices(translationMatrix(numAt(operands, 0), numAt(operands, 1)), ts.tlm);
|
|
548
|
+
ts.tm = ts.tlm;
|
|
549
|
+
break;
|
|
550
|
+
case "Tm":
|
|
551
|
+
ts.tlm = matrixFromOperands(operands);
|
|
552
|
+
ts.tm = ts.tlm;
|
|
553
|
+
break;
|
|
554
|
+
case "T*":
|
|
555
|
+
nextLine();
|
|
556
|
+
break;
|
|
557
|
+
case "Tj": {
|
|
558
|
+
const str = operands[0];
|
|
559
|
+
if (str?.kind === "string") showText(str.bytes);
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
case "'": {
|
|
563
|
+
nextLine();
|
|
564
|
+
const str = operands[0];
|
|
565
|
+
if (str?.kind === "string") showText(str.bytes);
|
|
566
|
+
break;
|
|
567
|
+
}
|
|
568
|
+
case "\"": {
|
|
569
|
+
ts.wordSpace = numAt(operands, 0);
|
|
570
|
+
ts.charSpace = numAt(operands, 1);
|
|
571
|
+
nextLine();
|
|
572
|
+
const str = operands[2];
|
|
573
|
+
if (str?.kind === "string") showText(str.bytes);
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
case "TJ": {
|
|
577
|
+
const array = asArray(operands[0]);
|
|
578
|
+
if (array !== void 0) showTextArray(array);
|
|
579
|
+
break;
|
|
580
|
+
}
|
|
581
|
+
case "Do": handleDo(asName(operands[0]));
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
//#endregion
|
|
586
|
+
export { interpretContentStream };
|