reamkit 1.27.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 +6 -5
- 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.js +114 -1
- package/dist/esm/pdf-reader/annots.d.ts +0 -14
- package/dist/esm/pdf-reader/annots.js +13 -1
- package/dist/esm/pdf-reader/ccitt.d.ts +2 -3
- package/dist/esm/pdf-reader/ccitt.js +32 -4
- 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/cmap.js +5 -2
- package/dist/esm/pdf-reader/content.d.ts +76 -0
- package/dist/esm/pdf-reader/content.js +142 -59
- 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.js +41 -1
- package/dist/esm/pdf-reader/document.js +26 -9
- package/dist/esm/pdf-reader/embedded-fonts.d.ts +11 -0
- package/dist/esm/pdf-reader/embedded-fonts.js +14 -1
- 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 +9 -3
- package/dist/esm/pdf-reader/flow-build.js +13 -7
- package/dist/esm/pdf-reader/font.js +329 -8
- 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 +4 -3
- package/dist/esm/pdf-reader/image-decode.js +85 -64
- package/dist/esm/pdf-reader/images.d.ts +6 -0
- package/dist/esm/pdf-reader/images.js +50 -7
- package/dist/esm/pdf-reader/jbig2.js +104 -19
- package/dist/esm/pdf-reader/layout.js +1148 -45
- 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/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 -9
- package/dist/esm/pdf-reader/reader.js +34 -21
- package/dist/esm/pdf-reader/shading.d.ts +81 -2
- package/dist/esm/pdf-reader/shading.js +191 -25
- 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/text-rules.js +83 -10
- package/dist/esm/pdf-reader/text.js +82 -3
- 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.js +43 -4
- package/dist/esm/word/document-parser.js +4 -1
- package/dist/esm/word/docx-writer.js +1 -0
- package/package.json +1 -1
|
@@ -2,7 +2,9 @@ import { PDF_NULL, PdfHexString, PdfName, PdfStream } from "../pdf/objects.js";
|
|
|
2
2
|
import { encodePng } from "../core/png-encode.js";
|
|
3
3
|
import { lzwDecodeMsb } from "../core/lzw.js";
|
|
4
4
|
import { reversePredictor } from "./predictor.js";
|
|
5
|
+
import { ascii85Decode, asciiHexDecode, runLengthDecode } from "./stream-filters.js";
|
|
5
6
|
import { labToSrgb } from "./cie-color.js";
|
|
7
|
+
import { readFunction } from "./function.js";
|
|
6
8
|
import { decodeCcitt } from "./ccitt.js";
|
|
7
9
|
import { decodeJbig2 } from "./jbig2.js";
|
|
8
10
|
import { decodeJpeg } from "./jpeg.js";
|
|
@@ -18,9 +20,10 @@ var MAX_PIXELS = 4e7;
|
|
|
18
20
|
* colour spaces; Flate, LZW (EP12), RunLength, ASCII85, ASCIIHex and CCITT
|
|
19
21
|
* Group 4 / Group 3 1-D fax (EP15) filters; PNG/TIFF predictors; bit depths
|
|
20
22
|
* 1/2/4/8/16; an `/SMask` folded in as the PNG alpha channel; and a stencil
|
|
21
|
-
* `/ImageMask` (§8.9.6.2) given back as RGBA in `fillHex
|
|
22
|
-
*
|
|
23
|
-
*
|
|
23
|
+
* `/ImageMask` (§8.9.6.2) given back as RGBA in `fillHex`; `Lab` (§8.6.5.8) and
|
|
24
|
+
* a `Separation`/`DeviceN` through its own tint transform (§8.6.6.4).
|
|
25
|
+
* Unsupported inputs (CCITT Group 3 2-D) return a typed failure so the caller
|
|
26
|
+
* records a loss.
|
|
24
27
|
*
|
|
25
28
|
* @param file The owning file.
|
|
26
29
|
* @param stream The image XObject, or an inline image wrapped as one.
|
|
@@ -300,6 +303,21 @@ function resolveColorSpace(file, csVal) {
|
|
|
300
303
|
}
|
|
301
304
|
};
|
|
302
305
|
}
|
|
306
|
+
if (tag === "Separation" || tag === "DeviceN" || tag === "I") {
|
|
307
|
+
const names = file.resolve(cs[1] ?? PDF_NULL);
|
|
308
|
+
const components = tag === "Separation" ? 1 : Array.isArray(names) ? names.length : 0;
|
|
309
|
+
const alternate = resolveColorSpace(file, cs[2]);
|
|
310
|
+
const transform = readFunction(file, cs[3]);
|
|
311
|
+
if (components < 1 || !alternate || alternate.kind === "tint" || !transform) return void 0;
|
|
312
|
+
return {
|
|
313
|
+
kind: "tint",
|
|
314
|
+
components,
|
|
315
|
+
tint: {
|
|
316
|
+
transform,
|
|
317
|
+
alternate
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
}
|
|
303
321
|
}
|
|
304
322
|
function namedColorSpace(name) {
|
|
305
323
|
if (name === "DeviceGray" || name === "G" || name === "CalGray") return {
|
|
@@ -363,6 +381,29 @@ function toColor(cs, s, px, bpc, decode) {
|
|
|
363
381
|
samples: out
|
|
364
382
|
};
|
|
365
383
|
}
|
|
384
|
+
if (cs.kind === "tint" && cs.tint) {
|
|
385
|
+
const { transform, alternate } = cs.tint;
|
|
386
|
+
const n = cs.components;
|
|
387
|
+
const cache = /* @__PURE__ */ new Map();
|
|
388
|
+
const out = new Uint8Array(px * 3);
|
|
389
|
+
for (let i = 0; i < px; i++) {
|
|
390
|
+
const comps = [];
|
|
391
|
+
for (let k = 0; k < n; k++) comps.push(c01(s[i * n + k], k));
|
|
392
|
+
const key = comps.join(",");
|
|
393
|
+
let rgb = cache.get(key);
|
|
394
|
+
if (!rgb) {
|
|
395
|
+
rgb = alternateRgb(alternate, transform(comps));
|
|
396
|
+
if (cache.size < MAX_TINT_CACHE) cache.set(key, rgb);
|
|
397
|
+
}
|
|
398
|
+
out[i * 3] = rgb[0];
|
|
399
|
+
out[i * 3 + 1] = rgb[1];
|
|
400
|
+
out[i * 3 + 2] = rgb[2];
|
|
401
|
+
}
|
|
402
|
+
return {
|
|
403
|
+
color: "rgb",
|
|
404
|
+
samples: out
|
|
405
|
+
};
|
|
406
|
+
}
|
|
366
407
|
if (cs.kind === "lab") {
|
|
367
408
|
const lab = cs.lab;
|
|
368
409
|
const out = new Uint8Array(px * 3);
|
|
@@ -422,6 +463,47 @@ function toColor(cs, s, px, bpc, decode) {
|
|
|
422
463
|
samples: out
|
|
423
464
|
};
|
|
424
465
|
}
|
|
466
|
+
/** How many distinct tint tuples are remembered before the cache stops growing. */
|
|
467
|
+
var MAX_TINT_CACHE = 65536;
|
|
468
|
+
/** §8.6.6.4 — what the alternate space makes of the transform's output. */
|
|
469
|
+
function alternateRgb(alternate, out) {
|
|
470
|
+
const at = (i) => Math.min(1, Math.max(0, out[i] ?? 0));
|
|
471
|
+
const to255 = (v) => Math.round(v * 255);
|
|
472
|
+
if (alternate.kind === "cmyk") {
|
|
473
|
+
const k = at(3);
|
|
474
|
+
return [
|
|
475
|
+
to255((1 - at(0)) * (1 - k)),
|
|
476
|
+
to255((1 - at(1)) * (1 - k)),
|
|
477
|
+
to255((1 - at(2)) * (1 - k))
|
|
478
|
+
];
|
|
479
|
+
}
|
|
480
|
+
if (alternate.kind === "lab" && alternate.lab) {
|
|
481
|
+
const r = alternate.lab.range;
|
|
482
|
+
const [sr, sg, sb] = labToSrgb(alternate.lab.white, [
|
|
483
|
+
at(0) * 100,
|
|
484
|
+
r[0] + at(1) * (r[1] - r[0]),
|
|
485
|
+
r[2] + at(2) * (r[3] - r[2])
|
|
486
|
+
]);
|
|
487
|
+
return [
|
|
488
|
+
to255(sr),
|
|
489
|
+
to255(sg),
|
|
490
|
+
to255(sb)
|
|
491
|
+
];
|
|
492
|
+
}
|
|
493
|
+
if (alternate.kind === "gray") {
|
|
494
|
+
const g = to255(at(0));
|
|
495
|
+
return [
|
|
496
|
+
g,
|
|
497
|
+
g,
|
|
498
|
+
g
|
|
499
|
+
];
|
|
500
|
+
}
|
|
501
|
+
return [
|
|
502
|
+
to255(at(0)),
|
|
503
|
+
to255(at(1)),
|
|
504
|
+
to255(at(2))
|
|
505
|
+
];
|
|
506
|
+
}
|
|
425
507
|
function paletteRgb(base, lookup, off) {
|
|
426
508
|
if (base.kind === "rgb") return [
|
|
427
509
|
lookup[off] ?? 0,
|
|
@@ -651,61 +733,6 @@ function lzwEarlyChange(file, d) {
|
|
|
651
733
|
const ec = decodeParmsOf(file, d)?.get("EarlyChange");
|
|
652
734
|
return ec !== void 0 && file.resolve(ec) === 0 ? 0 : 1;
|
|
653
735
|
}
|
|
654
|
-
function runLengthDecode(data) {
|
|
655
|
-
const out = [];
|
|
656
|
-
let i = 0;
|
|
657
|
-
while (i < data.length) {
|
|
658
|
-
const len = data[i++];
|
|
659
|
-
if (len === 128) break;
|
|
660
|
-
if (len < 128) for (let j = 0; j <= len && i < data.length; j++) out.push(data[i++]);
|
|
661
|
-
else {
|
|
662
|
-
const b = data[i++] ?? 0;
|
|
663
|
-
for (let j = 0; j < 257 - len; j++) out.push(b);
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
return Uint8Array.from(out);
|
|
667
|
-
}
|
|
668
|
-
function ascii85Decode(data) {
|
|
669
|
-
const out = [];
|
|
670
|
-
let tuple = 0;
|
|
671
|
-
let count = 0;
|
|
672
|
-
for (const c of data) {
|
|
673
|
-
if (c === 126) break;
|
|
674
|
-
if (c <= 32) continue;
|
|
675
|
-
if (c === 122 && count === 0) {
|
|
676
|
-
out.push(0, 0, 0, 0);
|
|
677
|
-
continue;
|
|
678
|
-
}
|
|
679
|
-
if (c < 33 || c > 117) continue;
|
|
680
|
-
tuple = tuple * 85 + (c - 33);
|
|
681
|
-
if (++count === 5) {
|
|
682
|
-
out.push(tuple >>> 24 & 255, tuple >>> 16 & 255, tuple >>> 8 & 255, tuple & 255);
|
|
683
|
-
tuple = 0;
|
|
684
|
-
count = 0;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
if (count > 0) {
|
|
688
|
-
for (let i = count; i < 5; i++) tuple = tuple * 85 + 84;
|
|
689
|
-
for (let i = 0; i < count - 1; i++) out.push(tuple >>> 24 - i * 8 & 255);
|
|
690
|
-
}
|
|
691
|
-
return Uint8Array.from(out);
|
|
692
|
-
}
|
|
693
|
-
function asciiHexDecode(data) {
|
|
694
|
-
const out = [];
|
|
695
|
-
let hi = -1;
|
|
696
|
-
for (const c of data) {
|
|
697
|
-
if (c === 62) break;
|
|
698
|
-
const v = hexVal(c);
|
|
699
|
-
if (v < 0) continue;
|
|
700
|
-
if (hi < 0) hi = v;
|
|
701
|
-
else {
|
|
702
|
-
out.push(hi << 4 | v);
|
|
703
|
-
hi = -1;
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
if (hi >= 0) out.push(hi << 4);
|
|
707
|
-
return Uint8Array.from(out);
|
|
708
|
-
}
|
|
709
736
|
function decodeParmsOf(file, d) {
|
|
710
737
|
const p = file.resolve(d.get("DecodeParms") ?? d.get("DP") ?? PDF_NULL);
|
|
711
738
|
if (p instanceof Map) return p;
|
|
@@ -742,12 +769,6 @@ function boolOf(v) {
|
|
|
742
769
|
function clamp01(x) {
|
|
743
770
|
return x < 0 ? 0 : x > 1 ? 1 : x;
|
|
744
771
|
}
|
|
745
|
-
function hexVal(c) {
|
|
746
|
-
if (c >= 48 && c <= 57) return c - 48;
|
|
747
|
-
if (c >= 65 && c <= 70) return c - 65 + 10;
|
|
748
|
-
if (c >= 97 && c <= 102) return c - 97 + 10;
|
|
749
|
-
return -1;
|
|
750
|
-
}
|
|
751
772
|
function fail(severity, detail) {
|
|
752
773
|
return {
|
|
753
774
|
ok: false,
|
|
@@ -29,6 +29,12 @@ export interface PdfImage {
|
|
|
29
29
|
readonly crop?: ImageCrop;
|
|
30
30
|
/** Enclosing marked-content id, if the placement was inside a `/Figure`. */
|
|
31
31
|
readonly mcid?: number;
|
|
32
|
+
/**
|
|
33
|
+
* §11.6.4.4 `/ca` — how opaque the picture is drawn, `0..1`. Absent is
|
|
34
|
+
* opaque. alphatrans.pdf lays a photograph in at half strength over three
|
|
35
|
+
* coloured squares, and drawn full-strength it hid all three.
|
|
36
|
+
*/
|
|
37
|
+
readonly alpha?: number;
|
|
32
38
|
/**
|
|
33
39
|
* §8.5.3 — where this was painted, as the chain of positions leading to it.
|
|
34
40
|
* The same key a lifted path carries, so the two can be ordered against each
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { PDF_NULL, PdfName, PdfStream } from "../pdf/objects.js";
|
|
2
2
|
import { FEATURES } from "../core/ir/features.js";
|
|
3
|
+
import { encodePng } from "../core/png-encode.js";
|
|
4
|
+
import { buildAlphaMap, sampledShading } from "./shading.js";
|
|
3
5
|
import { interpretContent, multiply } from "./content.js";
|
|
4
|
-
import { buildAlphaMap } from "./shading.js";
|
|
5
6
|
import { collectPageAppearances } from "./annots.js";
|
|
6
7
|
import { hiddenProperties, hiddenXObject } from "./optional-content.js";
|
|
8
|
+
import { buildFonts } from "./text.js";
|
|
7
9
|
import { decodePdfImage } from "./image-decode.js";
|
|
8
10
|
//#region src/pdf-reader/images.ts
|
|
9
|
-
var NO_FONTS = /* @__PURE__ */ new Map();
|
|
10
11
|
var MAX_FORM_DEPTH = 12;
|
|
11
12
|
var MAX_IMAGES = 4096;
|
|
12
13
|
/**
|
|
@@ -23,6 +24,14 @@ function collectPageImages(file, page) {
|
|
|
23
24
|
const lossByDetail = /* @__PURE__ */ new Map();
|
|
24
25
|
const visiting = /* @__PURE__ */ new Set();
|
|
25
26
|
const alphaCache = /* @__PURE__ */ new Map();
|
|
27
|
+
const fontCache = /* @__PURE__ */ new Map();
|
|
28
|
+
const fontsOf = (resources) => {
|
|
29
|
+
const had = fontCache.get(resources);
|
|
30
|
+
if (had) return had;
|
|
31
|
+
const made = buildFonts(file, resources);
|
|
32
|
+
fontCache.set(resources, made);
|
|
33
|
+
return made;
|
|
34
|
+
};
|
|
26
35
|
const addLoss = (severity, detail) => {
|
|
27
36
|
if (!lossByDetail.has(detail)) lossByDetail.set(detail, {
|
|
28
37
|
severity,
|
|
@@ -38,7 +47,7 @@ function collectPageImages(file, page) {
|
|
|
38
47
|
paints = buildAlphaMap(file, resources);
|
|
39
48
|
alphaCache.set(resources, paints);
|
|
40
49
|
}
|
|
41
|
-
const result = interpretContent(content,
|
|
50
|
+
const result = interpretContent(content, fontsOf(resources), baseCtm, void 0, paints, void 0, hiddenProperties(file, resources));
|
|
42
51
|
const patterns = resources ? file.get(resources, "Pattern") : PDF_NULL;
|
|
43
52
|
const patternDict = patterns instanceof Map ? patterns : void 0;
|
|
44
53
|
for (const vector of result.vectors) {
|
|
@@ -51,13 +60,46 @@ function collectPageImages(file, page) {
|
|
|
51
60
|
walk(patternRes instanceof Map ? patternRes : resources, file.streamData(stream), multiply(matrixOf(file, stream.dict), baseCtm), depth + 1, inheritedMcid, [...prefix, vector.order]);
|
|
52
61
|
visiting.delete(stream);
|
|
53
62
|
}
|
|
63
|
+
for (const call of result.glyphs) {
|
|
64
|
+
if (depth >= MAX_FORM_DEPTH || visiting.has(call.stream)) continue;
|
|
65
|
+
visiting.add(call.stream);
|
|
66
|
+
walk(call.resources ?? resources, file.streamData(call.stream), call.ctm, depth + 1, inheritedMcid, [...prefix, call.order]);
|
|
67
|
+
visiting.delete(call.stream);
|
|
68
|
+
}
|
|
69
|
+
for (const paint of result.shadings) {
|
|
70
|
+
if (images.length >= MAX_IMAGES) return;
|
|
71
|
+
const dict = resources ? file.get(resources, "Shading") : PDF_NULL;
|
|
72
|
+
const shading = dict instanceof Map ? file.resolve(dict.get(paint.name) ?? PDF_NULL) : PDF_NULL;
|
|
73
|
+
const sh = shading instanceof PdfStream ? shading.dict : shading instanceof Map ? shading : void 0;
|
|
74
|
+
if (!sh) continue;
|
|
75
|
+
if (paint.masked) continue;
|
|
76
|
+
const sampled = sampledShading(file, sh);
|
|
77
|
+
if (!sampled) continue;
|
|
78
|
+
const placed = multiply(matrixOf(file, sh), paint.ctm);
|
|
79
|
+
const [dx0, dx1, dy0, dy1] = sampled.domain;
|
|
80
|
+
const unit = [
|
|
81
|
+
dx1 - dx0,
|
|
82
|
+
0,
|
|
83
|
+
0,
|
|
84
|
+
dy1 - dy0,
|
|
85
|
+
dx0,
|
|
86
|
+
dy0
|
|
87
|
+
];
|
|
88
|
+
images.push({
|
|
89
|
+
...geometry(multiply(unit, placed), {
|
|
90
|
+
bytes: encodePng(sampled.size, sampled.size, "rgb", sampled.rgb),
|
|
91
|
+
format: "png"
|
|
92
|
+
}, inheritedMcid, paint.clip),
|
|
93
|
+
orderKey: [...prefix, paint.order]
|
|
94
|
+
});
|
|
95
|
+
}
|
|
54
96
|
for (const placement of result.images) {
|
|
55
97
|
if (images.length >= MAX_IMAGES) return;
|
|
56
98
|
if (placement.inline) {
|
|
57
99
|
const decoded = decodePdfImage(file, new PdfStream(placement.inline.dict, placement.inline.data), placement.fillHex);
|
|
58
100
|
if (decoded.ok) {
|
|
59
101
|
images.push({
|
|
60
|
-
...geometry(placement.ctm, decoded, placement.mcid ?? inheritedMcid, placement.clip),
|
|
102
|
+
...geometry(placement.ctm, decoded, placement.mcid ?? inheritedMcid, placement.clip, placement.alpha),
|
|
61
103
|
orderKey: [...prefix, placement.order]
|
|
62
104
|
});
|
|
63
105
|
if (decoded.degraded) addLoss("degraded", decoded.degraded);
|
|
@@ -73,7 +115,7 @@ function collectPageImages(file, page) {
|
|
|
73
115
|
const decoded = decodePdfImage(file, stream, placement.fillHex);
|
|
74
116
|
if (decoded.ok) {
|
|
75
117
|
images.push({
|
|
76
|
-
...geometry(placement.ctm, decoded, mcid, placement.clip),
|
|
118
|
+
...geometry(placement.ctm, decoded, mcid, placement.clip, placement.alpha),
|
|
77
119
|
orderKey: [...prefix, placement.order]
|
|
78
120
|
});
|
|
79
121
|
if (decoded.degraded) addLoss("degraded", decoded.degraded);
|
|
@@ -104,7 +146,7 @@ function collectPageImages(file, page) {
|
|
|
104
146
|
losses: [...lossByDetail.values()]
|
|
105
147
|
};
|
|
106
148
|
}
|
|
107
|
-
function geometry(ctm, decoded, mcid, clip) {
|
|
149
|
+
function geometry(ctm, decoded, mcid, clip, alpha) {
|
|
108
150
|
const widthPt = Math.hypot(ctm[0], ctm[1]) || 1;
|
|
109
151
|
const heightPt = Math.hypot(ctm[2], ctm[3]) || 1;
|
|
110
152
|
const angle = Math.atan2(ctm[1], ctm[0]) * 180 / Math.PI;
|
|
@@ -130,7 +172,8 @@ function geometry(ctm, decoded, mcid, clip) {
|
|
|
130
172
|
y: cy - shownH / 2,
|
|
131
173
|
...crop ? { crop } : {},
|
|
132
174
|
...Math.abs(angle) > .5 ? { rotationDeg: angle } : {},
|
|
133
|
-
...mcid !== void 0 ? { mcid } : {}
|
|
175
|
+
...mcid !== void 0 ? { mcid } : {},
|
|
176
|
+
...alpha !== void 0 ? { alpha } : {}
|
|
134
177
|
};
|
|
135
178
|
}
|
|
136
179
|
/** Below this the clip took a sliver off an edge and is not worth a crop. */
|
|
@@ -1809,21 +1809,21 @@ var Corner = /* @__PURE__ */ function(Corner) {
|
|
|
1809
1809
|
function symbolCodeLength(symbols) {
|
|
1810
1810
|
return Math.ceil(Math.log2(Math.max(symbols, 1)));
|
|
1811
1811
|
}
|
|
1812
|
-
function decodeTextRegion(mq, symbols, p, stripsLog) {
|
|
1812
|
+
function decodeTextRegion(mq, symbols, p, stripsLog, lent) {
|
|
1813
1813
|
const bmp = makeBitmap(p.width, p.height, p.defPixel);
|
|
1814
1814
|
const strips = 1 << stripsLog;
|
|
1815
|
-
const codeLen = symbolCodeLength(symbols.length);
|
|
1816
|
-
const iadt = new IntDecoder(mq);
|
|
1817
|
-
const iafs = new IntDecoder(mq);
|
|
1818
|
-
const iads = new IntDecoder(mq);
|
|
1819
|
-
const iait = new IntDecoder(mq);
|
|
1820
|
-
const iari = new IntDecoder(mq);
|
|
1821
|
-
const iardw = new IntDecoder(mq);
|
|
1822
|
-
const iardh = new IntDecoder(mq);
|
|
1823
|
-
const iardx = new IntDecoder(mq);
|
|
1824
|
-
const iardy = new IntDecoder(mq);
|
|
1825
|
-
const iaid = new IdDecoder(mq, codeLen);
|
|
1826
|
-
const refineCx = newContexts(8192);
|
|
1815
|
+
const codeLen = lent?.codeLen ?? symbolCodeLength(symbols.length);
|
|
1816
|
+
const iadt = lent?.iadt ?? new IntDecoder(mq);
|
|
1817
|
+
const iafs = lent?.iafs ?? new IntDecoder(mq);
|
|
1818
|
+
const iads = lent?.iads ?? new IntDecoder(mq);
|
|
1819
|
+
const iait = lent?.iait ?? new IntDecoder(mq);
|
|
1820
|
+
const iari = lent?.iari ?? new IntDecoder(mq);
|
|
1821
|
+
const iardw = lent?.iardw ?? new IntDecoder(mq);
|
|
1822
|
+
const iardh = lent?.iardh ?? new IntDecoder(mq);
|
|
1823
|
+
const iardx = lent?.iardx ?? new IntDecoder(mq);
|
|
1824
|
+
const iardy = lent?.iardy ?? new IntDecoder(mq);
|
|
1825
|
+
const iaid = lent?.iaid ?? new IdDecoder(mq, codeLen);
|
|
1826
|
+
const refineCx = lent?.refineCx ?? newContexts(8192);
|
|
1827
1827
|
const num = (v) => v === OOB ? 0 : v;
|
|
1828
1828
|
let stripT = -num(iadt.decode()) * strips;
|
|
1829
1829
|
let firstS = 0;
|
|
@@ -1862,10 +1862,10 @@ function decodeTextRegion(mq, symbols, p, stripsLog) {
|
|
|
1862
1862
|
compose(bmp, sym, x, y, p.combOp);
|
|
1863
1863
|
curS += (p.transposed ? sh : sw) - 1;
|
|
1864
1864
|
placed++;
|
|
1865
|
-
if (placed >= p.instances) break;
|
|
1866
1865
|
const ids = iads.decode();
|
|
1867
1866
|
if (ids === OOB) break;
|
|
1868
1867
|
curS += ids + p.dsOffset;
|
|
1868
|
+
if (placed > p.instances * 2 + 16) break;
|
|
1869
1869
|
}
|
|
1870
1870
|
}
|
|
1871
1871
|
return bmp;
|
|
@@ -1890,6 +1890,22 @@ function decodeSymbolDictionary(mq, input, newCount, exportCount, template, at,
|
|
|
1890
1890
|
const refineCx = newContexts(8192);
|
|
1891
1891
|
const newSymbols = [];
|
|
1892
1892
|
const num = (v) => v === OOB ? 0 : v;
|
|
1893
|
+
const codeLen = symbolCodeLength(input.length + newCount);
|
|
1894
|
+
const iaid = new IdDecoder(mq, codeLen);
|
|
1895
|
+
const lent = {
|
|
1896
|
+
codeLen,
|
|
1897
|
+
iadt: new IntDecoder(mq),
|
|
1898
|
+
iafs: new IntDecoder(mq),
|
|
1899
|
+
iads: new IntDecoder(mq),
|
|
1900
|
+
iait: new IntDecoder(mq),
|
|
1901
|
+
iari: new IntDecoder(mq),
|
|
1902
|
+
iardw: new IntDecoder(mq),
|
|
1903
|
+
iardh: new IntDecoder(mq),
|
|
1904
|
+
iardx,
|
|
1905
|
+
iardy,
|
|
1906
|
+
iaid,
|
|
1907
|
+
refineCx
|
|
1908
|
+
};
|
|
1893
1909
|
let height = 0;
|
|
1894
1910
|
let guard = 0;
|
|
1895
1911
|
while (newSymbols.length < newCount && guard++ < 1e4) {
|
|
@@ -1909,7 +1925,7 @@ function decodeSymbolDictionary(mq, input, newCount, exportCount, template, at,
|
|
|
1909
1925
|
const instances = num(iaai.decode());
|
|
1910
1926
|
if (instances === 1) {
|
|
1911
1927
|
const all = [...input, ...newSymbols];
|
|
1912
|
-
const id =
|
|
1928
|
+
const id = iaid.decode();
|
|
1913
1929
|
const rdx = num(iardx.decode());
|
|
1914
1930
|
const rdy = num(iardy.decode());
|
|
1915
1931
|
newSymbols.push(decodeRefinement(mq, refineCx, width, height, rTemplate, all[id] ?? makeBitmap(1, 1), rdx, rdy, rAt, false));
|
|
@@ -1928,7 +1944,7 @@ function decodeSymbolDictionary(mq, input, newCount, exportCount, template, at,
|
|
|
1928
1944
|
refine: true,
|
|
1929
1945
|
rTemplate,
|
|
1930
1946
|
rAt
|
|
1931
|
-
}, 0));
|
|
1947
|
+
}, 0, lent));
|
|
1932
1948
|
}
|
|
1933
1949
|
}
|
|
1934
1950
|
}
|
|
@@ -2039,15 +2055,73 @@ function decodeTextRegionHuff(bits, data, symbols, p, stripsLog, t) {
|
|
|
2039
2055
|
compose(bmp, sym, x, y, p.combOp);
|
|
2040
2056
|
curS += (p.transposed ? sh : sw) - 1;
|
|
2041
2057
|
placed++;
|
|
2042
|
-
if (placed >= p.instances) break;
|
|
2043
2058
|
const ids = huffDecode(bits, t.ds);
|
|
2044
2059
|
if (ids === OOB) break;
|
|
2045
2060
|
curS += ids + p.dsOffset;
|
|
2061
|
+
if (placed > p.instances * 2 + 16) break;
|
|
2046
2062
|
}
|
|
2047
2063
|
}
|
|
2048
2064
|
return bmp;
|
|
2049
2065
|
}
|
|
2050
2066
|
/**
|
|
2067
|
+
* §6.5.8.2 — one shape of a REFINING Huffman dictionary.
|
|
2068
|
+
*
|
|
2069
|
+
* The dictionary states how many instances the shape is made of. One is a
|
|
2070
|
+
* refinement of a symbol it already holds — the id in as many bits as the
|
|
2071
|
+
* dictionary will end with, the offsets through table B.15, and the
|
|
2072
|
+
* refinement's own length through B.1, so the reader steps over exactly that.
|
|
2073
|
+
* Several is a text region of its own, read with the standard tables §6.5.8.2.1
|
|
2074
|
+
* names and with the symbol ids in plain fixed-width codes.
|
|
2075
|
+
*
|
|
2076
|
+
* @returns The shape, which is `width` by `height` whatever it took to make.
|
|
2077
|
+
*/
|
|
2078
|
+
function aggregateSymbolHuff(bits, data, symbols, width, height, codeLen, refineCx, agg) {
|
|
2079
|
+
const num = (v) => v === OOB ? 0 : v;
|
|
2080
|
+
const instances = num(huffDecode(bits, agg.inst));
|
|
2081
|
+
const b15 = standardTable(15);
|
|
2082
|
+
const b1 = standardTable(1);
|
|
2083
|
+
if (instances !== 1) {
|
|
2084
|
+
const ids = buildHuffTable(Array.from({ length: 1 << codeLen }, (_, i) => ({
|
|
2085
|
+
prefLen: codeLen,
|
|
2086
|
+
rangeLen: 0,
|
|
2087
|
+
rangeLow: i
|
|
2088
|
+
})));
|
|
2089
|
+
return decodeTextRegionHuff(bits, data, symbols, {
|
|
2090
|
+
width,
|
|
2091
|
+
height,
|
|
2092
|
+
instances: Math.max(1, instances),
|
|
2093
|
+
stripT: 0,
|
|
2094
|
+
refCorner: Corner.TopLeft,
|
|
2095
|
+
transposed: false,
|
|
2096
|
+
combOp: 0,
|
|
2097
|
+
defPixel: 0,
|
|
2098
|
+
dsOffset: 0,
|
|
2099
|
+
refine: true,
|
|
2100
|
+
rTemplate: agg.rTemplate,
|
|
2101
|
+
rAt: agg.rAt
|
|
2102
|
+
}, 0, {
|
|
2103
|
+
fs: standardTable(6),
|
|
2104
|
+
ds: standardTable(8),
|
|
2105
|
+
dt: standardTable(11),
|
|
2106
|
+
rdw: b15,
|
|
2107
|
+
rdh: b15,
|
|
2108
|
+
rdx: b15,
|
|
2109
|
+
rdy: b15,
|
|
2110
|
+
rsize: b1,
|
|
2111
|
+
symbolIds: ids
|
|
2112
|
+
});
|
|
2113
|
+
}
|
|
2114
|
+
const id = bits.readBits(codeLen);
|
|
2115
|
+
const rdx = num(huffDecode(bits, b15));
|
|
2116
|
+
const rdy = num(huffDecode(bits, b15));
|
|
2117
|
+
const size = num(huffDecode(bits, b1));
|
|
2118
|
+
bits.align();
|
|
2119
|
+
const start = bits.bytePos;
|
|
2120
|
+
const bmp = decodeRefinement(new MQDecoder(data.subarray(start)), refineCx, width, height, agg.rTemplate, symbols[id] ?? makeBitmap(1, 1), rdx, rdy, agg.rAt, false);
|
|
2121
|
+
bits.skipTo(start + size);
|
|
2122
|
+
return bmp;
|
|
2123
|
+
}
|
|
2124
|
+
/**
|
|
2051
2125
|
* §6.5.9 — a Huffman-coded symbol dictionary.
|
|
2052
2126
|
*
|
|
2053
2127
|
* The shapes of a height class are not coded one by one: their widths are read
|
|
@@ -2055,9 +2129,11 @@ function decodeTextRegionHuff(bits, data, symbols, p, stripsLog, t) {
|
|
|
2055
2129
|
* apart by those widths. That is why a Huffman dictionary needs a size field
|
|
2056
2130
|
* the arithmetic one does not.
|
|
2057
2131
|
*/
|
|
2058
|
-
function decodeSymbolDictionaryHuff(bits, data, input, newCount, exportCount, dh, dw, bmSize) {
|
|
2132
|
+
function decodeSymbolDictionaryHuff(bits, data, input, newCount, exportCount, dh, dw, bmSize, agg) {
|
|
2059
2133
|
const newSymbols = [];
|
|
2060
2134
|
const num = (v) => v === OOB ? 0 : v;
|
|
2135
|
+
const codeLen = symbolCodeLength(input.length + newCount);
|
|
2136
|
+
const refineCx = newContexts(8192);
|
|
2061
2137
|
let height = 0;
|
|
2062
2138
|
let guard = 0;
|
|
2063
2139
|
while (newSymbols.length < newCount && guard++ < 1e4) {
|
|
@@ -2071,9 +2147,14 @@ function decodeSymbolDictionaryHuff(bits, data, input, newCount, exportCount, dh
|
|
|
2071
2147
|
if (d === OOB) break;
|
|
2072
2148
|
width += d;
|
|
2073
2149
|
if (width <= 0 || width > 16384 || newSymbols.length + widths.length >= newCount + 1) break;
|
|
2150
|
+
if (agg) {
|
|
2151
|
+
newSymbols.push(aggregateSymbolHuff(bits, data, [...input, ...newSymbols], width, height, codeLen, refineCx, agg));
|
|
2152
|
+
continue;
|
|
2153
|
+
}
|
|
2074
2154
|
widths.push(width);
|
|
2075
2155
|
totalWidth += width;
|
|
2076
2156
|
}
|
|
2157
|
+
if (agg) continue;
|
|
2077
2158
|
if (widths.length === 0) continue;
|
|
2078
2159
|
const size = num(huffDecode(bits, bmSize));
|
|
2079
2160
|
bits.align();
|
|
@@ -2441,7 +2522,11 @@ function decodeJbig2(data, globals, width, height) {
|
|
|
2441
2522
|
const dwSel = flags >> 4 & 3;
|
|
2442
2523
|
const bmSel = flags >> 6 & 1;
|
|
2443
2524
|
const bits = new BitReader(bytes.subarray(seg.start + r.pos, seg.end));
|
|
2444
|
-
symbolsBySegment.set(seg.number, decodeSymbolDictionaryHuff(bits, bytes.subarray(seg.start + r.pos, seg.end), inherited, newCount, exportCount, pick(dhSel, [4, 5]), pick(dwSel, [2, 3]), bmSel === 1 ? custom[ci++] ?? standardTable(1) : standardTable(1)
|
|
2525
|
+
symbolsBySegment.set(seg.number, decodeSymbolDictionaryHuff(bits, bytes.subarray(seg.start + r.pos, seg.end), inherited, newCount, exportCount, pick(dhSel, [4, 5]), pick(dwSel, [2, 3]), bmSel === 1 ? custom[ci++] ?? standardTable(1) : standardTable(1), refAgg ? {
|
|
2526
|
+
inst: (flags >> 7 & 1) === 1 ? custom[ci++] ?? standardTable(1) : standardTable(1),
|
|
2527
|
+
rTemplate,
|
|
2528
|
+
rAt: rAt.length > 0 ? rAt : NOMINAL_AT_REFINE
|
|
2529
|
+
} : void 0));
|
|
2445
2530
|
continue;
|
|
2446
2531
|
}
|
|
2447
2532
|
symbolsBySegment.set(seg.number, decodeSymbolDictionary(new MQDecoder(bytes.subarray(seg.start + r.pos, seg.end)), inherited, newCount, exportCount, template, at.length > 0 ? at : NOMINAL_AT[template] ?? [], refAgg, rTemplate, rAt.length > 0 ? rAt : NOMINAL_AT_REFINE));
|