reamkit 1.26.0 → 1.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -8
- package/dist/esm/core/converter/ream.d.ts +0 -9
- package/dist/esm/core/converter/ream.js +0 -1
- package/dist/esm/core/document-model/types.d.ts +5 -3
- package/dist/esm/core/font/index.d.ts +1 -0
- package/dist/esm/core/font/ligatures.d.ts +17 -0
- package/dist/esm/core/font/ligatures.js +49 -0
- package/dist/esm/core/font/ttf-parser.d.ts +2 -1
- package/dist/esm/core/font/ttf-parser.js +11 -2
- package/dist/esm/core/fonts/remote-fonts.d.ts +1 -1
- package/dist/esm/core/fonts/remote-fonts.js +47 -2
- package/dist/esm/core/fonts/scripts.js +10 -5
- package/dist/esm/excel/header-footer.js +53 -8
- package/dist/esm/layout/styled-layout.js +53 -3
- package/dist/esm/pdf/cid-font.js +35 -8
- package/dist/esm/pdf-reader/annot-draw.d.ts +65 -0
- package/dist/esm/pdf-reader/annot-draw.js +487 -0
- package/dist/esm/pdf-reader/annots.d.ts +0 -12
- package/dist/esm/pdf-reader/annots.js +30 -4
- package/dist/esm/pdf-reader/ccitt.d.ts +20 -3
- package/dist/esm/pdf-reader/ccitt.js +102 -6
- package/dist/esm/pdf-reader/cff-outline.d.ts +36 -0
- package/dist/esm/pdf-reader/cff-outline.js +1122 -0
- package/dist/esm/pdf-reader/cie-color.d.ts +33 -0
- package/dist/esm/pdf-reader/cie-color.js +112 -0
- package/dist/esm/pdf-reader/cmap.js +5 -2
- package/dist/esm/pdf-reader/content.d.ts +123 -3
- package/dist/esm/pdf-reader/content.js +232 -54
- package/dist/esm/pdf-reader/dingbats.d.ts +11 -0
- package/dist/esm/pdf-reader/dingbats.js +1033 -0
- package/dist/esm/pdf-reader/display.d.ts +1 -1
- package/dist/esm/pdf-reader/display.js +61 -6
- package/dist/esm/pdf-reader/document.d.ts +6 -0
- package/dist/esm/pdf-reader/document.js +55 -10
- package/dist/esm/pdf-reader/embedded-fonts.d.ts +23 -3
- package/dist/esm/pdf-reader/embedded-fonts.js +36 -4
- package/dist/esm/pdf-reader/encodings.d.ts +25 -0
- package/dist/esm/pdf-reader/encodings.js +110 -0
- package/dist/esm/pdf-reader/flow-build.d.ts +19 -5
- package/dist/esm/pdf-reader/flow-build.js +111 -11
- package/dist/esm/pdf-reader/font.js +403 -21
- package/dist/esm/pdf-reader/function.d.ts +16 -0
- package/dist/esm/pdf-reader/function.js +414 -0
- package/dist/esm/pdf-reader/glyf-outline.d.ts +43 -0
- package/dist/esm/pdf-reader/glyf-outline.js +351 -0
- package/dist/esm/pdf-reader/glyph-names.js +20 -0
- package/dist/esm/pdf-reader/icc.d.ts +10 -0
- package/dist/esm/pdf-reader/icc.js +210 -0
- package/dist/esm/pdf-reader/image-decode.d.ts +9 -4
- package/dist/esm/pdf-reader/image-decode.js +274 -72
- package/dist/esm/pdf-reader/images.d.ts +18 -0
- package/dist/esm/pdf-reader/images.js +154 -11
- package/dist/esm/pdf-reader/jbig2.d.ts +23 -0
- package/dist/esm/pdf-reader/jbig2.js +126 -32
- package/dist/esm/pdf-reader/layout.d.ts +32 -0
- package/dist/esm/pdf-reader/layout.js +1316 -64
- package/dist/esm/pdf-reader/lexer.d.ts +2 -0
- package/dist/esm/pdf-reader/lexer.js +4 -0
- package/dist/esm/pdf-reader/math-rows.d.ts +23 -0
- package/dist/esm/pdf-reader/math-rows.js +198 -0
- package/dist/esm/pdf-reader/optional-content.d.ts +36 -0
- package/dist/esm/pdf-reader/optional-content.js +93 -0
- package/dist/esm/pdf-reader/predefined-cmap.d.ts +21 -0
- package/dist/esm/pdf-reader/predefined-cmap.js +102 -0
- package/dist/esm/pdf-reader/reader.d.ts +6 -6
- package/dist/esm/pdf-reader/reader.js +102 -16
- package/dist/esm/pdf-reader/shading.d.ts +139 -8
- package/dist/esm/pdf-reader/shading.js +309 -39
- package/dist/esm/pdf-reader/standard-metrics.d.ts +8 -0
- package/dist/esm/pdf-reader/standard-metrics.js +18 -0
- package/dist/esm/pdf-reader/standard-widths.d.ts +20 -0
- package/dist/esm/pdf-reader/standard-widths.js +62 -0
- package/dist/esm/pdf-reader/stream-filters.d.ts +6 -0
- package/dist/esm/pdf-reader/stream-filters.js +67 -0
- package/dist/esm/pdf-reader/tagged.js +204 -32
- package/dist/esm/pdf-reader/text-rules.d.ts +16 -0
- package/dist/esm/pdf-reader/text-rules.js +185 -0
- package/dist/esm/pdf-reader/text.js +157 -4
- package/dist/esm/pdf-reader/type1-outline.d.ts +21 -0
- package/dist/esm/pdf-reader/type1-outline.js +576 -0
- package/dist/esm/pdf-reader/vector.d.ts +5 -0
- package/dist/esm/pdf-reader/vector.js +79 -27
- package/dist/esm/word/document-parser.js +4 -1
- package/dist/esm/word/docx-writer.js +74 -11
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PDF_NULL, PdfHexString, PdfName } from "../pdf/objects.js";
|
|
2
2
|
import { Lexer } from "./lexer.js";
|
|
3
|
+
import { cmykHex, grayHex, rgbHex, spaceColor } from "./shading.js";
|
|
3
4
|
//#region src/pdf-reader/content.ts
|
|
4
5
|
/**
|
|
5
6
|
* A painted path emitted by the path-painting operators (§8.5.3), captured in
|
|
@@ -91,6 +92,9 @@ function initialState() {
|
|
|
91
92
|
fillGradient: void 0,
|
|
92
93
|
fillPattern: void 0,
|
|
93
94
|
fillAlpha: 1,
|
|
95
|
+
fillDarkens: false,
|
|
96
|
+
blendMode: void 0,
|
|
97
|
+
softMask: false,
|
|
94
98
|
clip: void 0
|
|
95
99
|
};
|
|
96
100
|
}
|
|
@@ -132,30 +136,42 @@ function spaceOf(operands, spaces) {
|
|
|
132
136
|
}
|
|
133
137
|
}
|
|
134
138
|
/**
|
|
135
|
-
* §8.
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* there is. One number is the ambiguous case — grey in a device space, but the
|
|
140
|
-
* strength of a colorant in a Separation, where 1 is the ink at full and reads
|
|
141
|
-
* dark — so a lone component is only taken where the space said what it means.
|
|
139
|
+
* §8.7.4.5 — one colour for a whole sweep: the stop at its middle, or the mean
|
|
140
|
+
* of the two it falls between. A gradient is a shape a run cannot carry, and
|
|
141
|
+
* the end it starts at is no more the colour of the words than the end it
|
|
142
|
+
* finishes at.
|
|
142
143
|
*/
|
|
143
|
-
function
|
|
144
|
-
const
|
|
145
|
-
if (
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
144
|
+
function midGradient(gradient) {
|
|
145
|
+
const stops = [...gradient.stops].sort((a, b) => a.offset - b.offset);
|
|
146
|
+
if (stops.length === 0) return "000000";
|
|
147
|
+
const exact = stops.find((s) => Math.abs(s.offset - .5) < 1e-6);
|
|
148
|
+
if (exact) return exact.colorHex;
|
|
149
|
+
const before = [...stops].reverse().find((s) => s.offset <= .5) ?? stops[0];
|
|
150
|
+
const after = stops.find((s) => s.offset >= .5) ?? stops[stops.length - 1];
|
|
151
|
+
const span = after.offset - before.offset;
|
|
152
|
+
const t = span > 0 ? (.5 - before.offset) / span : 0;
|
|
153
|
+
const mix = (at) => {
|
|
154
|
+
const a = parseInt(before.colorHex.slice(at, at + 2), 16);
|
|
155
|
+
const b = parseInt(after.colorHex.slice(at, at + 2), 16);
|
|
156
|
+
return Number.isFinite(a) && Number.isFinite(b) ? Math.round(a + (b - a) * t) : 0;
|
|
157
|
+
};
|
|
158
|
+
return [
|
|
159
|
+
mix(0),
|
|
160
|
+
mix(2),
|
|
161
|
+
mix(4)
|
|
162
|
+
].map((c) => Math.max(0, Math.min(255, c)).toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
153
163
|
}
|
|
154
|
-
|
|
164
|
+
/** §8.6.8 — the colour a run of `sc` / `scn` operands comes to (see `spaceColor`). */
|
|
165
|
+
function colorOfOperands(operands, space) {
|
|
166
|
+
return spaceColor(operands.filter((o) => typeof o === "number"), space);
|
|
167
|
+
}
|
|
168
|
+
function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__PURE__ */ new Map(), alphas = /* @__PURE__ */ new Map(), spaces = /* @__PURE__ */ new Map(), hiddenOc = /* @__PURE__ */ new Set()) {
|
|
155
169
|
const runs = [];
|
|
156
170
|
const images = [];
|
|
157
171
|
const vectors = [];
|
|
158
172
|
const glyphs = [];
|
|
173
|
+
const painted = [];
|
|
174
|
+
const outlines = [];
|
|
159
175
|
const lexer = new Lexer(bytes);
|
|
160
176
|
const stack = [];
|
|
161
177
|
let state = initialState();
|
|
@@ -167,6 +183,9 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
167
183
|
let paintOrder = 0;
|
|
168
184
|
let operands = [];
|
|
169
185
|
const mcStack = [];
|
|
186
|
+
const ocStack = [];
|
|
187
|
+
let hiddenDepth = 0;
|
|
188
|
+
const visible = () => hiddenDepth === 0;
|
|
170
189
|
const toPage = (x, y) => [x * state.ctm[0] + y * state.ctm[2] + state.ctm[4], x * state.ctm[1] + y * state.ctm[3] + state.ctm[5]];
|
|
171
190
|
const moveTo = (x, y) => {
|
|
172
191
|
const [px, py] = toPage(x, y);
|
|
@@ -211,7 +230,7 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
211
230
|
return state.lineWidth * scale;
|
|
212
231
|
};
|
|
213
232
|
const paintPath = (fill, stroke) => {
|
|
214
|
-
if (path.length >= 2 && (fill || stroke)) {
|
|
233
|
+
if (path.length >= 2 && (fill || stroke) && visible()) {
|
|
215
234
|
const mcid = mcStack.length > 0 ? mcStack[mcStack.length - 1] : void 0;
|
|
216
235
|
vectors.push({
|
|
217
236
|
order: paintOrder++,
|
|
@@ -220,6 +239,9 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
220
239
|
...fill && state.fillPattern !== void 0 ? { patternName: state.fillPattern } : {},
|
|
221
240
|
...fill ? { fillHex: state.fillColor } : {},
|
|
222
241
|
...fill && state.fillAlpha < 1 ? { alpha: state.fillAlpha } : {},
|
|
242
|
+
...fill && state.fillDarkens ? { darkens: true } : {},
|
|
243
|
+
...state.blendMode !== void 0 ? { blend: state.blendMode } : {},
|
|
244
|
+
...state.softMask ? { masked: true } : {},
|
|
223
245
|
...fill && state.fillGradient ? { gradient: state.fillGradient } : {},
|
|
224
246
|
...stroke ? {
|
|
225
247
|
strokeHex: state.strokeColor,
|
|
@@ -249,7 +271,7 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
249
271
|
const type3 = state.font.type3;
|
|
250
272
|
if (type3) {
|
|
251
273
|
const stream = type3.proc(code);
|
|
252
|
-
if (stream) {
|
|
274
|
+
if (stream && visible()) {
|
|
253
275
|
const scale = [
|
|
254
276
|
state.fontSize * state.hScale,
|
|
255
277
|
0,
|
|
@@ -266,12 +288,41 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
266
288
|
});
|
|
267
289
|
}
|
|
268
290
|
}
|
|
269
|
-
const
|
|
291
|
+
const outline = state.font.outline;
|
|
292
|
+
if (outline && visible() && state.renderMode !== 3 && state.renderMode !== 7) {
|
|
293
|
+
const segs = outline.path(code);
|
|
294
|
+
if (segs) {
|
|
295
|
+
const scale = [
|
|
296
|
+
state.fontSize * state.hScale,
|
|
297
|
+
0,
|
|
298
|
+
0,
|
|
299
|
+
state.fontSize,
|
|
300
|
+
0,
|
|
301
|
+
state.rise
|
|
302
|
+
];
|
|
303
|
+
const place = multiply(outline.matrix, multiply(scale, multiply(tm, state.ctm)));
|
|
304
|
+
outlines.push({
|
|
305
|
+
order: paintOrder++,
|
|
306
|
+
segs: segs.map((seg) => mapSeg(seg, place)),
|
|
307
|
+
...state.clip ? { clip: state.clip } : {},
|
|
308
|
+
fillHex: state.fillColor,
|
|
309
|
+
...state.fillAlpha < 1 ? { alpha: state.fillAlpha } : {},
|
|
310
|
+
glyph: true
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
270
314
|
const isSpace = state.font.bytesPerCode === 1 && code === 32;
|
|
271
|
-
|
|
315
|
+
const spacing = state.charSpacing + (isSpace ? state.wordSpacing : 0);
|
|
316
|
+
const down = state.font.verticalAdvance;
|
|
317
|
+
if (down) {
|
|
318
|
+
tm = multiply(translation(0, down(code) / 1e3 * state.fontSize - spacing), tm);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
tm = multiply(translation((state.font.width(code) / 1e3 * state.fontSize + spacing) * state.hScale, 0), tm);
|
|
272
322
|
};
|
|
273
323
|
const consume = (operand) => {
|
|
274
|
-
const
|
|
324
|
+
const bytes = toBytes(operand);
|
|
325
|
+
const codes = state.font.splitCodes ? state.font.splitCodes(bytes) : splitCodes(bytes, state.font.bytesPerCode);
|
|
275
326
|
for (const code of codes) advanceGlyph(code);
|
|
276
327
|
return state.font.decode(codes);
|
|
277
328
|
};
|
|
@@ -279,8 +330,10 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
279
330
|
const text = logicalOrder(shown);
|
|
280
331
|
if (text.length === 0) return;
|
|
281
332
|
const scaleY = Math.hypot(origin[2], origin[3]) || 1;
|
|
333
|
+
const scaleX = (Math.hypot(origin[0], origin[1]) || 1) * state.hScale;
|
|
282
334
|
const mcid = mcStack.length > 0 ? mcStack[mcStack.length - 1] : void 0;
|
|
283
335
|
const angle = Math.atan2(origin[1], origin[0]) * 180 / Math.PI;
|
|
336
|
+
if (!visible()) return;
|
|
284
337
|
runs.push({
|
|
285
338
|
text,
|
|
286
339
|
x: origin[4],
|
|
@@ -288,19 +341,21 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
288
341
|
endX: end[4],
|
|
289
342
|
endY: end[5],
|
|
290
343
|
...Math.abs(angle) > UPRIGHT_TOLERANCE_DEG ? { angleDeg: angle } : {},
|
|
291
|
-
fontSizePt: state.fontSize * scaleY,
|
|
344
|
+
fontSizePt: Math.abs(state.fontSize) * scaleY,
|
|
345
|
+
spaceWidthPt: (state.font.width(32) / 1e3 * state.fontSize + state.charSpacing + state.wordSpacing) * scaleX,
|
|
292
346
|
fontKey: state.fontKey,
|
|
293
347
|
...state.font.name !== void 0 ? { fontName: state.font.name } : {},
|
|
294
348
|
...state.font.type3 ? { type3: true } : {},
|
|
295
349
|
...state.renderMode === 3 || state.renderMode === 7 ? { invisible: true } : {},
|
|
296
350
|
...state.fillPattern !== void 0 ? { fillPatternName: state.fillPattern } : {},
|
|
351
|
+
...state.fillGradient ? { gradientFill: true } : {},
|
|
297
352
|
...strokesText(state.renderMode) ? {
|
|
298
353
|
outlineHex: state.strokeColor,
|
|
299
354
|
outlineWidthPt: ctmLineWidth()
|
|
300
355
|
} : {},
|
|
301
356
|
...state.font.bold ? { bold: true } : {},
|
|
302
357
|
...state.font.italic ? { italic: true } : {},
|
|
303
|
-
colorHex: state.fillColor,
|
|
358
|
+
colorHex: state.fillGradient ? midGradient(state.fillGradient) : state.fillColor,
|
|
304
359
|
...mcid !== void 0 ? { mcid } : {}
|
|
305
360
|
});
|
|
306
361
|
};
|
|
@@ -392,23 +447,33 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
392
447
|
const props = operands[operands.length - 1];
|
|
393
448
|
const mcidVal = !(tag instanceof PdfName && tag.value === "Artifact") && props instanceof Map ? props.get("MCID") : void 0;
|
|
394
449
|
mcStack.push(typeof mcidVal === "number" ? mcidVal : void 0);
|
|
450
|
+
const isOc = tag instanceof PdfName && tag.value === "OC" && props instanceof PdfName && hiddenOc.has(props.value);
|
|
451
|
+
ocStack.push(isOc);
|
|
452
|
+
if (isOc) hiddenDepth++;
|
|
395
453
|
break;
|
|
396
454
|
}
|
|
397
455
|
case "BMC":
|
|
398
456
|
mcStack.push(void 0);
|
|
457
|
+
ocStack.push(false);
|
|
399
458
|
break;
|
|
400
459
|
case "EMC":
|
|
401
460
|
mcStack.pop();
|
|
461
|
+
if (ocStack.pop() === true) hiddenDepth--;
|
|
402
462
|
break;
|
|
403
463
|
case "Do": {
|
|
404
464
|
const nm = operands[0];
|
|
405
|
-
if (nm instanceof PdfName) {
|
|
465
|
+
if (nm instanceof PdfName && visible()) {
|
|
406
466
|
const mcid = mcStack.length > 0 ? mcStack[mcStack.length - 1] : void 0;
|
|
407
467
|
images.push({
|
|
408
468
|
order: paintOrder++,
|
|
409
469
|
name: nm.value,
|
|
410
470
|
ctm: state.ctm,
|
|
411
|
-
...
|
|
471
|
+
...state.clip ? { clip: state.clip } : {},
|
|
472
|
+
fillHex: state.fillColor,
|
|
473
|
+
...mcid !== void 0 ? { mcid } : {},
|
|
474
|
+
...state.fillAlpha < 1 ? { alpha: state.fillAlpha } : {},
|
|
475
|
+
...state.blendMode !== void 0 ? { blend: state.blendMode } : {},
|
|
476
|
+
...state.softMask ? { masked: true } : {}
|
|
412
477
|
});
|
|
413
478
|
}
|
|
414
479
|
break;
|
|
@@ -443,7 +508,7 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
443
508
|
state.fillPattern = state.fillGradient ? void 0 : named;
|
|
444
509
|
break;
|
|
445
510
|
}
|
|
446
|
-
const hex =
|
|
511
|
+
const hex = colorOfOperands(operands, state.fillSpace);
|
|
447
512
|
if (hex !== void 0) {
|
|
448
513
|
state.fillColor = hex;
|
|
449
514
|
state.fillGradient = void 0;
|
|
@@ -454,7 +519,7 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
454
519
|
case "SCN":
|
|
455
520
|
case "SC": {
|
|
456
521
|
if (operands[operands.length - 1] instanceof PdfName) break;
|
|
457
|
-
const hex =
|
|
522
|
+
const hex = colorOfOperands(operands, state.strokeSpace);
|
|
458
523
|
if (hex !== void 0) state.strokeColor = hex;
|
|
459
524
|
break;
|
|
460
525
|
}
|
|
@@ -506,12 +571,33 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
506
571
|
path.push({ op: "close" });
|
|
507
572
|
paintPath(true, true);
|
|
508
573
|
break;
|
|
574
|
+
case "sh": {
|
|
575
|
+
const nm = operands[0];
|
|
576
|
+
if (nm instanceof PdfName && visible()) painted.push({
|
|
577
|
+
name: nm.value,
|
|
578
|
+
ctm: state.ctm,
|
|
579
|
+
...state.clip ? { clip: state.clip } : {},
|
|
580
|
+
...state.softMask ? { masked: true } : {},
|
|
581
|
+
...state.fillAlpha < 1 ? { alpha: state.fillAlpha } : {},
|
|
582
|
+
...state.fillDarkens ? { darkens: true } : {},
|
|
583
|
+
order: paintOrder++
|
|
584
|
+
});
|
|
585
|
+
break;
|
|
586
|
+
}
|
|
509
587
|
case "n":
|
|
510
588
|
paintPath(false, false);
|
|
511
589
|
break;
|
|
512
590
|
case "gs": {
|
|
513
591
|
const nm = operands[operands.length - 1];
|
|
514
|
-
|
|
592
|
+
const paint = nm instanceof PdfName ? alphas.get(nm.value) : void 0;
|
|
593
|
+
if (paint) {
|
|
594
|
+
if (paint.alpha !== void 0) state.fillAlpha = paint.alpha;
|
|
595
|
+
if (paint.statesBlend === true) {
|
|
596
|
+
state.fillDarkens = paint.darkens ?? false;
|
|
597
|
+
state.blendMode = paint.blend;
|
|
598
|
+
}
|
|
599
|
+
if (paint.masked !== void 0) state.softMask = paint.masked;
|
|
600
|
+
}
|
|
515
601
|
break;
|
|
516
602
|
}
|
|
517
603
|
case "W":
|
|
@@ -545,8 +631,19 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
545
631
|
operands.push(readDict(lexer));
|
|
546
632
|
break;
|
|
547
633
|
case "keyword":
|
|
548
|
-
if (tok.value === "BI")
|
|
549
|
-
|
|
634
|
+
if (tok.value === "BI") {
|
|
635
|
+
const inline = readInlineImage(lexer);
|
|
636
|
+
if (inline && visible()) images.push({
|
|
637
|
+
order: paintOrder++,
|
|
638
|
+
name: "",
|
|
639
|
+
inline,
|
|
640
|
+
ctm: state.ctm,
|
|
641
|
+
...state.clip ? { clip: state.clip } : {},
|
|
642
|
+
fillHex: state.fillColor,
|
|
643
|
+
...mcStack.length > 0 ? { mcid: mcStack[mcStack.length - 1] } : {},
|
|
644
|
+
...state.blendMode !== void 0 ? { blend: state.blendMode } : {}
|
|
645
|
+
});
|
|
646
|
+
} else exec(tok.value);
|
|
550
647
|
operands = [];
|
|
551
648
|
break;
|
|
552
649
|
default:
|
|
@@ -558,7 +655,34 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
558
655
|
texts: runs,
|
|
559
656
|
images,
|
|
560
657
|
vectors,
|
|
561
|
-
glyphs
|
|
658
|
+
glyphs,
|
|
659
|
+
shadings: painted,
|
|
660
|
+
outlines
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
/** One path segment through a matrix — the glyph's own space onto the page. */
|
|
664
|
+
function mapSeg(seg, m) {
|
|
665
|
+
const at = (x, y) => [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
|
|
666
|
+
if (seg.op === "close") return seg;
|
|
667
|
+
if (seg.op === "cubic") {
|
|
668
|
+
const [x1, y1] = at(seg.x1, seg.y1);
|
|
669
|
+
const [x2, y2] = at(seg.x2, seg.y2);
|
|
670
|
+
const [x, y] = at(seg.x, seg.y);
|
|
671
|
+
return {
|
|
672
|
+
op: "cubic",
|
|
673
|
+
x1,
|
|
674
|
+
y1,
|
|
675
|
+
x2,
|
|
676
|
+
y2,
|
|
677
|
+
x,
|
|
678
|
+
y
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
const [x, y] = at(seg.x, seg.y);
|
|
682
|
+
return {
|
|
683
|
+
op: seg.op,
|
|
684
|
+
x,
|
|
685
|
+
y
|
|
562
686
|
};
|
|
563
687
|
}
|
|
564
688
|
/** §9.3.6 — the rendering modes that put a line round the glyphs. */
|
|
@@ -610,21 +734,6 @@ function isRightToLeft(text) {
|
|
|
610
734
|
function isRtl(cp) {
|
|
611
735
|
return cp >= 1424 && cp <= 1535 || cp >= 1536 && cp <= 1791 || cp >= 1792 && cp <= 1871 || cp >= 1920 && cp <= 1983 || cp >= 2208 && cp <= 2303 || cp >= 64285 && cp <= 65023 || cp >= 65136 && cp <= 65279;
|
|
612
736
|
}
|
|
613
|
-
function clamp255(v) {
|
|
614
|
-
return Math.max(0, Math.min(255, Math.round(v * 255)));
|
|
615
|
-
}
|
|
616
|
-
function hex2(v) {
|
|
617
|
-
return clamp255(v).toString(16).padStart(2, "0");
|
|
618
|
-
}
|
|
619
|
-
function rgbHex(r, g, b) {
|
|
620
|
-
return (hex2(r) + hex2(g) + hex2(b)).toUpperCase();
|
|
621
|
-
}
|
|
622
|
-
function grayHex(v) {
|
|
623
|
-
return rgbHex(v, v, v);
|
|
624
|
-
}
|
|
625
|
-
function cmykHex(c, m, y, k) {
|
|
626
|
-
return rgbHex((1 - c) * (1 - k), (1 - m) * (1 - k), (1 - y) * (1 - k));
|
|
627
|
-
}
|
|
628
737
|
function matrixFromOperands(operands) {
|
|
629
738
|
const n = (i) => typeof operands[i] === "number" ? operands[i] : 0;
|
|
630
739
|
return [
|
|
@@ -658,9 +767,30 @@ function readArray(lexer) {
|
|
|
658
767
|
for (;;) {
|
|
659
768
|
const tok = lexer.nextToken();
|
|
660
769
|
if (tok.kind === "arrayClose" || tok.kind === "eof") break;
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
770
|
+
switch (tok.kind) {
|
|
771
|
+
case "num":
|
|
772
|
+
out.push(tok.value);
|
|
773
|
+
break;
|
|
774
|
+
case "str":
|
|
775
|
+
out.push(tok.value);
|
|
776
|
+
break;
|
|
777
|
+
case "hexstr":
|
|
778
|
+
out.push(new PdfHexString(tok.bytes));
|
|
779
|
+
break;
|
|
780
|
+
case "name":
|
|
781
|
+
out.push(new PdfName(tok.value));
|
|
782
|
+
break;
|
|
783
|
+
case "arrayOpen":
|
|
784
|
+
out.push(readArray(lexer));
|
|
785
|
+
break;
|
|
786
|
+
case "dictOpen":
|
|
787
|
+
out.push(readDict(lexer));
|
|
788
|
+
break;
|
|
789
|
+
case "keyword":
|
|
790
|
+
if (tok.value === "true" || tok.value === "false") out.push(tok.value === "true");
|
|
791
|
+
break;
|
|
792
|
+
default: break;
|
|
793
|
+
}
|
|
664
794
|
}
|
|
665
795
|
return out;
|
|
666
796
|
}
|
|
@@ -687,14 +817,62 @@ function readValue(lexer) {
|
|
|
687
817
|
default: return PDF_NULL;
|
|
688
818
|
}
|
|
689
819
|
}
|
|
690
|
-
|
|
820
|
+
/**
|
|
821
|
+
* §8.9.7 — an inline image: its dictionary between `BI` and `ID`, then its
|
|
822
|
+
* bytes up to `EI`.
|
|
823
|
+
*
|
|
824
|
+
* The bytes are binary and may hold `EI` themselves, so the end is found by
|
|
825
|
+
* MEASURING where the dictionary says how much there is — an unfiltered image
|
|
826
|
+
* is exactly `ceil(W · BPC · components / 8) · H` bytes — and only searched for
|
|
827
|
+
* where a filter makes the length unknowable. images_1bit_grayscale.pdf draws
|
|
828
|
+
* two of them and both were skipped over.
|
|
829
|
+
*/
|
|
830
|
+
function readInlineImage(lexer) {
|
|
831
|
+
const dict = /* @__PURE__ */ new Map();
|
|
691
832
|
for (;;) {
|
|
692
833
|
const tok = lexer.nextToken();
|
|
693
|
-
if (tok.kind === "eof") return;
|
|
834
|
+
if (tok.kind === "eof") return void 0;
|
|
694
835
|
if (tok.kind === "keyword" && tok.value === "ID") break;
|
|
836
|
+
if (tok.kind === "name") dict.set(tok.value, readValue(lexer));
|
|
837
|
+
}
|
|
838
|
+
const start = lexer.pos + 1;
|
|
839
|
+
const measured = inlineLength(dict);
|
|
840
|
+
let end = measured !== void 0 ? start + measured : -1;
|
|
841
|
+
if (end < 0 || end > lexer.length) {
|
|
842
|
+
end = lexer.indexOfAscii("EI", start);
|
|
843
|
+
if (end < 0) {
|
|
844
|
+
lexer.pos = lexer.length;
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
695
847
|
}
|
|
696
|
-
const
|
|
848
|
+
const data = lexer.slice(start, Math.min(end, lexer.length));
|
|
849
|
+
const ei = lexer.indexOfAscii("EI", end);
|
|
697
850
|
lexer.pos = ei < 0 ? lexer.length : ei + 2;
|
|
851
|
+
return {
|
|
852
|
+
dict,
|
|
853
|
+
data
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
/** How many bytes an UNFILTERED inline image's samples take, if that is known. */
|
|
857
|
+
function inlineLength(dict) {
|
|
858
|
+
if (dict.has("F") || dict.has("Filter")) return void 0;
|
|
859
|
+
const num = (...keys) => {
|
|
860
|
+
for (const k of keys) {
|
|
861
|
+
const v = dict.get(k);
|
|
862
|
+
if (typeof v === "number") return v;
|
|
863
|
+
}
|
|
864
|
+
return 0;
|
|
865
|
+
};
|
|
866
|
+
const w = num("W", "Width");
|
|
867
|
+
const h = num("H", "Height");
|
|
868
|
+
if (w <= 0 || h <= 0) return void 0;
|
|
869
|
+
const mask = dict.get("IM") === true || dict.get("ImageMask") === true;
|
|
870
|
+
const bpc = mask ? 1 : num("BPC", "BitsPerComponent") || 8;
|
|
871
|
+
const cs = dict.get("CS") ?? dict.get("ColorSpace");
|
|
872
|
+
const name = cs instanceof PdfName ? cs.value : "";
|
|
873
|
+
const comps = mask ? 1 : /^(RGB|DeviceRGB|CalRGB)$/u.test(name) ? 3 : /^(CMYK|DeviceCMYK)$/u.test(name) ? 4 : /^(G|DeviceGray|CalGray|I|Indexed)$/u.test(name) || name === "" ? 1 : 0;
|
|
874
|
+
if (comps === 0) return void 0;
|
|
875
|
+
return ((w * comps * bpc + 7) / 8 | 0) * h;
|
|
698
876
|
}
|
|
699
877
|
//#endregion
|
|
700
878
|
export { IDENTITY, interpretContent, isRightToLeft, multiply };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** The character a ZapfDingbats code stands for, or `undefined` for an unused one. */
|
|
2
|
+
export declare function zapfDingbatsChar(code: number): string | undefined;
|
|
3
|
+
/**
|
|
4
|
+
* The character a dingbat's glyph NAME stands for — `a38` is ✫ — for a font
|
|
5
|
+
* that names its glyphs through `/Differences` (§9.6.6.1).
|
|
6
|
+
*
|
|
7
|
+
* @param name The glyph name.
|
|
8
|
+
*/
|
|
9
|
+
export declare function dingbatChar(name: string): string | undefined;
|
|
10
|
+
/** Whether a base font names the ZapfDingbats face (§9.6.2.2 Table 109). */
|
|
11
|
+
export declare function isZapfDingbats(baseFont: string): boolean;
|