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.
Files changed (198) hide show
  1. package/README.md +38 -0
  2. package/dist/afm-widths-BoeTOK2r.cjs +826 -0
  3. package/dist/afm-widths-Dxucrg7D.js +779 -0
  4. package/dist/afm-widths-DyDq56Ph.d.cts +19 -0
  5. package/dist/afm-widths-DyDq56Ph.d.ts +19 -0
  6. package/dist/afm-widths.cjs +4 -0
  7. package/dist/afm-widths.d.cts +2 -0
  8. package/dist/afm-widths.d.ts +2 -0
  9. package/dist/afm-widths.js +2 -0
  10. package/dist/assets/stix-two-math-font.cjs +5 -0
  11. package/dist/assets/stix-two-math-font.d.cts +4 -0
  12. package/dist/assets/stix-two-math-font.d.ts +4 -0
  13. package/dist/assets/stix-two-math-font.js +4 -0
  14. package/dist/bytes/crc32.cjs +21 -0
  15. package/dist/bytes/crc32.d.cts +4 -0
  16. package/dist/bytes/crc32.d.ts +4 -0
  17. package/dist/bytes/crc32.js +20 -0
  18. package/dist/bytes/flate.cjs +53 -0
  19. package/dist/bytes/flate.d.cts +12 -0
  20. package/dist/bytes/flate.d.ts +12 -0
  21. package/dist/bytes/flate.js +49 -0
  22. package/dist/bytes/reader.cjs +60 -0
  23. package/dist/bytes/reader.d.cts +20 -0
  24. package/dist/bytes/reader.d.ts +20 -0
  25. package/dist/bytes/reader.js +58 -0
  26. package/dist/bytes/writer.cjs +37 -0
  27. package/dist/bytes/writer.d.cts +13 -0
  28. package/dist/bytes/writer.d.ts +13 -0
  29. package/dist/bytes/writer.js +35 -0
  30. package/dist/cmap.cjs +110 -0
  31. package/dist/cmap.d.cts +8 -0
  32. package/dist/cmap.d.ts +8 -0
  33. package/dist/cmap.js +109 -0
  34. package/dist/codec.cjs +34 -0
  35. package/dist/codec.d.cts +167 -0
  36. package/dist/codec.d.ts +167 -0
  37. package/dist/codec.js +32 -0
  38. package/dist/content-read.cjs +126 -0
  39. package/dist/content-read.d.cts +21 -0
  40. package/dist/content-read.d.ts +21 -0
  41. package/dist/content-read.js +125 -0
  42. package/dist/content-write.cjs +138 -0
  43. package/dist/content-write.d.cts +24 -0
  44. package/dist/content-write.d.ts +24 -0
  45. package/dist/content-write.js +137 -0
  46. package/dist/diagnostics.cjs +21 -0
  47. package/dist/diagnostics.d.cts +19 -0
  48. package/dist/diagnostics.d.ts +19 -0
  49. package/dist/diagnostics.js +18 -0
  50. package/dist/document.cjs +162 -0
  51. package/dist/document.d.cts +12 -0
  52. package/dist/document.d.ts +12 -0
  53. package/dist/document.js +161 -0
  54. package/dist/encoding.cjs +5 -0
  55. package/dist/encoding.d.cts +6 -0
  56. package/dist/encoding.d.ts +6 -0
  57. package/dist/encoding.js +2 -0
  58. package/dist/filters.cjs +223 -0
  59. package/dist/filters.d.cts +14 -0
  60. package/dist/filters.d.ts +14 -0
  61. package/dist/filters.js +218 -0
  62. package/dist/font-read.cjs +199 -0
  63. package/dist/font-read.d.cts +23 -0
  64. package/dist/font-read.d.ts +23 -0
  65. package/dist/font-read.js +198 -0
  66. package/dist/font-style.cjs +35 -0
  67. package/dist/font-style.d.cts +14 -0
  68. package/dist/font-style.d.ts +14 -0
  69. package/dist/font-style.js +34 -0
  70. package/dist/fonts.cjs +124 -0
  71. package/dist/fonts.d.cts +15 -0
  72. package/dist/fonts.d.ts +15 -0
  73. package/dist/fonts.js +122 -0
  74. package/dist/formula.cjs +0 -0
  75. package/dist/formula.d.cts +10 -0
  76. package/dist/formula.d.ts +10 -0
  77. package/dist/formula.js +0 -0
  78. package/dist/image/jpeg-info.cjs +71 -0
  79. package/dist/image/jpeg-info.d.cts +12 -0
  80. package/dist/image/jpeg-info.d.ts +12 -0
  81. package/dist/image/jpeg-info.js +70 -0
  82. package/dist/image/png-decode.cjs +181 -0
  83. package/dist/image/png-decode.d.cts +14 -0
  84. package/dist/image/png-decode.d.ts +14 -0
  85. package/dist/image/png-decode.js +180 -0
  86. package/dist/image/png-encode.cjs +64 -0
  87. package/dist/image/png-encode.d.cts +8 -0
  88. package/dist/image/png-encode.d.ts +8 -0
  89. package/dist/image/png-encode.js +63 -0
  90. package/dist/image/png-filter.cjs +95 -0
  91. package/dist/image/png-filter.d.cts +6 -0
  92. package/dist/image/png-filter.d.ts +6 -0
  93. package/dist/image/png-filter.js +93 -0
  94. package/dist/images-read.cjs +250 -0
  95. package/dist/images-read.d.cts +13 -0
  96. package/dist/images-read.d.ts +13 -0
  97. package/dist/images-read.js +249 -0
  98. package/dist/index.cjs +45 -5912
  99. package/dist/index.d.cts +21 -483
  100. package/dist/index.d.ts +21 -483
  101. package/dist/index.js +18 -5885
  102. package/dist/interpret.cjs +587 -0
  103. package/dist/interpret.d.cts +84 -0
  104. package/dist/interpret.d.ts +84 -0
  105. package/dist/interpret.js +586 -0
  106. package/dist/lexer.cjs +180 -0
  107. package/dist/lexer.d.cts +29 -0
  108. package/dist/lexer.d.ts +29 -0
  109. package/dist/lexer.js +179 -0
  110. package/dist/math-cmap.cjs +81 -0
  111. package/dist/math-cmap.d.cts +6 -0
  112. package/dist/math-cmap.d.ts +6 -0
  113. package/dist/math-cmap.js +80 -0
  114. package/dist/math-content-write.cjs +83 -0
  115. package/dist/math-content-write.d.cts +11 -0
  116. package/dist/math-content-write.d.ts +11 -0
  117. package/dist/math-content-write.js +81 -0
  118. package/dist/math-font-write.cjs +100 -0
  119. package/dist/math-font-write.d.cts +19 -0
  120. package/dist/math-font-write.d.ts +19 -0
  121. package/dist/math-font-write.js +99 -0
  122. package/dist/math-font.cjs +103 -0
  123. package/dist/math-font.d.cts +25 -0
  124. package/dist/math-font.d.ts +25 -0
  125. package/dist/math-font.js +102 -0
  126. package/dist/math-hmtx.cjs +17 -0
  127. package/dist/math-hmtx.d.cts +8 -0
  128. package/dist/math-hmtx.d.ts +8 -0
  129. package/dist/math-hmtx.js +16 -0
  130. package/dist/math-table.cjs +117 -0
  131. package/dist/math-table.d.cts +45 -0
  132. package/dist/math-table.d.ts +45 -0
  133. package/dist/math-table.js +116 -0
  134. package/dist/math-types-Ba8qAf1p.d.cts +82 -0
  135. package/dist/math-types-Ba8qAf1p.d.ts +82 -0
  136. package/dist/math-types.cjs +0 -0
  137. package/dist/math-types.d.cts +2 -0
  138. package/dist/math-types.d.ts +2 -0
  139. package/dist/math-types.js +0 -0
  140. package/dist/matrix-B3c2_a2f.d.cts +18 -0
  141. package/dist/matrix-B3c2_a2f.d.ts +18 -0
  142. package/dist/matrix.cjs +93 -0
  143. package/dist/matrix.d.cts +2 -0
  144. package/dist/matrix.d.ts +2 -0
  145. package/dist/matrix.js +83 -0
  146. package/dist/measure.cjs +54 -0
  147. package/dist/measure.d.cts +20 -0
  148. package/dist/measure.d.ts +20 -0
  149. package/dist/measure.js +53 -0
  150. package/dist/objects.cjs +100 -0
  151. package/dist/objects.d.cts +58 -0
  152. package/dist/objects.d.ts +58 -0
  153. package/dist/objects.js +84 -0
  154. package/dist/parse.cjs +230 -0
  155. package/dist/parse.d.cts +13 -0
  156. package/dist/parse.d.ts +13 -0
  157. package/dist/parse.js +228 -0
  158. package/dist/predictors.cjs +64 -0
  159. package/dist/predictors.d.cts +13 -0
  160. package/dist/predictors.d.ts +13 -0
  161. package/dist/predictors.js +62 -0
  162. package/dist/read.cjs +418 -0
  163. package/dist/read.d.cts +21 -0
  164. package/dist/read.d.ts +21 -0
  165. package/dist/read.js +413 -0
  166. package/dist/serialize.cjs +69 -0
  167. package/dist/serialize.d.cts +8 -0
  168. package/dist/serialize.d.ts +8 -0
  169. package/dist/serialize.js +66 -0
  170. package/dist/sfnt.cjs +52 -0
  171. package/dist/sfnt.d.cts +17 -0
  172. package/dist/sfnt.d.ts +17 -0
  173. package/dist/sfnt.js +46 -0
  174. package/dist/text-layout.cjs +224 -0
  175. package/dist/text-layout.d.cts +37 -0
  176. package/dist/text-layout.d.ts +37 -0
  177. package/dist/text-layout.js +222 -0
  178. package/dist/util/abort.cjs +7 -0
  179. package/dist/util/abort.d.cts +4 -0
  180. package/dist/util/abort.d.ts +4 -0
  181. package/dist/util/abort.js +6 -0
  182. package/dist/util/base64.cjs +48 -0
  183. package/dist/util/base64.d.cts +5 -0
  184. package/dist/util/base64.d.ts +5 -0
  185. package/dist/util/base64.js +46 -0
  186. package/dist/winansi.cjs +5 -0
  187. package/dist/winansi.d.cts +20 -0
  188. package/dist/winansi.d.ts +20 -0
  189. package/dist/winansi.js +2 -0
  190. package/dist/write.cjs +421 -0
  191. package/dist/write.d.cts +16 -0
  192. package/dist/write.d.ts +16 -0
  193. package/dist/write.js +419 -0
  194. package/dist/xref.cjs +325 -0
  195. package/dist/xref.d.cts +21 -0
  196. package/dist/xref.d.ts +21 -0
  197. package/dist/xref.js +324 -0
  198. 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 };