reamkit 1.29.0 → 1.30.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/dist/esm/core/document-model/types.d.ts +2 -0
- package/dist/esm/core/drawingml/shape-render.js +13 -1
- package/dist/esm/core/fonts/index.d.ts +1 -1
- package/dist/esm/core/fonts/remote-fonts.d.ts +8 -0
- package/dist/esm/core/fonts/remote-fonts.js +100 -17
- package/dist/esm/core/ir/flow.d.ts +17 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/pdf-reader/annot-draw.js +93 -1
- package/dist/esm/pdf-reader/annots.d.ts +18 -0
- package/dist/esm/pdf-reader/annots.js +86 -9
- package/dist/esm/pdf-reader/cmap.js +5 -2
- package/dist/esm/pdf-reader/content.d.ts +17 -4
- package/dist/esm/pdf-reader/content.js +163 -11
- package/dist/esm/pdf-reader/display.js +16 -0
- package/dist/esm/pdf-reader/embedded-fonts.d.ts +24 -0
- package/dist/esm/pdf-reader/embedded-fonts.js +48 -9
- package/dist/esm/pdf-reader/flow-build.d.ts +96 -5
- package/dist/esm/pdf-reader/flow-build.js +210 -23
- package/dist/esm/pdf-reader/font.d.ts +27 -1
- package/dist/esm/pdf-reader/font.js +313 -29
- package/dist/esm/pdf-reader/glyf-outline.js +13 -2
- package/dist/esm/pdf-reader/glyph-shapes.d.ts +18 -0
- package/dist/esm/pdf-reader/glyph-shapes.js +57 -0
- package/dist/esm/pdf-reader/image-decode.js +70 -4
- package/dist/esm/pdf-reader/images.d.ts +5 -0
- package/dist/esm/pdf-reader/images.js +4 -2
- package/dist/esm/pdf-reader/jbig2.d.ts +40 -1
- package/dist/esm/pdf-reader/jbig2.js +78 -16
- package/dist/esm/pdf-reader/jpeg.d.ts +6 -3
- package/dist/esm/pdf-reader/jpeg.js +21 -1
- package/dist/esm/pdf-reader/layout.d.ts +26 -2
- package/dist/esm/pdf-reader/layout.js +638 -92
- package/dist/esm/pdf-reader/lexer.d.ts +10 -0
- package/dist/esm/pdf-reader/lexer.js +17 -0
- package/dist/esm/pdf-reader/pattern-tint.d.ts +11 -1
- package/dist/esm/pdf-reader/pattern-tint.js +21 -3
- package/dist/esm/pdf-reader/regions.d.ts +25 -0
- package/dist/esm/pdf-reader/regions.js +167 -0
- package/dist/esm/pdf-reader/shading.d.ts +58 -2
- package/dist/esm/pdf-reader/shading.js +181 -11
- package/dist/esm/pdf-reader/struct-tree.js +112 -8
- package/dist/esm/pdf-reader/tagged.js +27 -7
- package/dist/esm/pdf-reader/text-rules.js +1 -1
- package/dist/esm/pdf-reader/text.js +9 -14
- package/dist/esm/pdf-reader/vector.d.ts +8 -2
- package/dist/esm/pdf-reader/vector.js +34 -5
- package/dist/esm/word/docx-writer.js +137 -36
- package/dist/esm/word/drawing-parser.js +7 -2
- package/dist/esm/word/paragraph-properties.js +2 -0
- package/package.json +5 -3
|
@@ -41,6 +41,8 @@ function decodePdfImage(file, stream, fillHex) {
|
|
|
41
41
|
const last = filters[filters.length - 1];
|
|
42
42
|
if (last === "DCTDecode" || last === "DCT") {
|
|
43
43
|
const jpegBytes = applyChainExceptLast(filters, stream.data);
|
|
44
|
+
const inks = cmykJpeg(file, d, jpegBytes, width, height);
|
|
45
|
+
if (inks) return inks;
|
|
44
46
|
const masked = hasSMask(file, d) ? maskedJpeg(file, d, jpegBytes, width, height) : void 0;
|
|
45
47
|
if (masked) return masked;
|
|
46
48
|
const degraded = hasSMask(file, d) ? "image transparency dropped (JPEG could not be decoded to attach its mask)" : void 0;
|
|
@@ -74,7 +76,7 @@ function decodePdfImage(file, stream, fillHex) {
|
|
|
74
76
|
}
|
|
75
77
|
const decoded = last === "CCITTFaxDecode" || last === "CCF" ? decodeCcittImage(file, stream, filters, width, height) : decodeToSamples(file, stream, filters, width, height);
|
|
76
78
|
if (typeof decoded === "string") return fail("dropped", decoded);
|
|
77
|
-
const alpha = decodeSMask(file, d, width, height);
|
|
79
|
+
const alpha = decodeSMask(file, d, width, height) ?? decoded.keyed;
|
|
78
80
|
const { color, samples } = alpha ? combineAlpha(decoded, alpha) : decoded;
|
|
79
81
|
return {
|
|
80
82
|
ok: true,
|
|
@@ -92,7 +94,40 @@ function decodeToSamples(file, stream, filters, width, height) {
|
|
|
92
94
|
if (!cs) return "unsupported image colour space";
|
|
93
95
|
const bpc = intOf(file.get(d, "BitsPerComponent")) || intOf(file.get(d, "BPC")) || 8;
|
|
94
96
|
const decodeArr = decodeArrayOf(file, d);
|
|
95
|
-
|
|
97
|
+
const integers = unpackSamples(raw, width, height, cs.components, bpc);
|
|
98
|
+
const keyed = colorKey(file, d, integers, cs.components, width * height);
|
|
99
|
+
return {
|
|
100
|
+
...toColor(cs, integers, width * height, bpc, decodeArr),
|
|
101
|
+
...keyed ? { keyed } : {}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* §8.9.6.4 — colour key masking: `/Mask` as an array of a range per colour
|
|
106
|
+
* component, and a sample whose every component falls inside its range is
|
|
107
|
+
* not painted. The ranges are in the image's own sample values, before any
|
|
108
|
+
* `/Decode`. colorkeymask.pdf keys out every sample of full red, and painted
|
|
109
|
+
* whole its red bar stood beside the green and blue ones the page shows.
|
|
110
|
+
*
|
|
111
|
+
* @returns The alpha it comes to, or `undefined` where no sample is keyed out.
|
|
112
|
+
*/
|
|
113
|
+
function colorKey(file, d, samples, n, px) {
|
|
114
|
+
const mask = file.resolve(d.get("Mask") ?? PDF_NULL);
|
|
115
|
+
if (!Array.isArray(mask) || mask.length < 2 * n) return void 0;
|
|
116
|
+
const ranges = mask.slice(0, 2 * n).map((v) => file.resolve(v));
|
|
117
|
+
if (!ranges.every((v) => typeof v === "number")) return void 0;
|
|
118
|
+
const data = new Uint8Array(px).fill(255);
|
|
119
|
+
let keyed = false;
|
|
120
|
+
for (let i = 0; i < px; i++) {
|
|
121
|
+
let inside = true;
|
|
122
|
+
for (let c = 0; c < n && inside; c++) {
|
|
123
|
+
const v = samples[i * n + c];
|
|
124
|
+
inside = v >= ranges[2 * c] && v <= ranges[2 * c + 1];
|
|
125
|
+
}
|
|
126
|
+
if (!inside) continue;
|
|
127
|
+
data[i] = 0;
|
|
128
|
+
keyed = true;
|
|
129
|
+
}
|
|
130
|
+
return keyed ? { data } : void 0;
|
|
96
131
|
}
|
|
97
132
|
/**
|
|
98
133
|
* §7.4.7 — a `/JBIG2Decode` image: the stream's own segments, plus the shared
|
|
@@ -579,7 +614,7 @@ function unpackSamples(raw, width, height, ncomp, bpc) {
|
|
|
579
614
|
*/
|
|
580
615
|
function maskedJpeg(file, d, jpegBytes, width, height) {
|
|
581
616
|
const image = decodeJpeg(jpegBytes);
|
|
582
|
-
if (!image) return void 0;
|
|
617
|
+
if (!image || image.components === 4) return void 0;
|
|
583
618
|
const alpha = decodeSMask(file, d, image.width, image.height);
|
|
584
619
|
if (!alpha) return void 0;
|
|
585
620
|
const { color: pngColor, samples } = combineAlpha(image.components === 1 ? {
|
|
@@ -624,7 +659,7 @@ function decodeSMask(file, d, width, height) {
|
|
|
624
659
|
/** A DCT-coded mask decoded to samples, or `undefined` past the baseline decoder. */
|
|
625
660
|
function jpegSamples(bytes) {
|
|
626
661
|
const decoded = decodeJpeg(bytes);
|
|
627
|
-
if (!decoded) return void 0;
|
|
662
|
+
if (!decoded || decoded.components === 4) return void 0;
|
|
628
663
|
return decoded.components === 1 ? {
|
|
629
664
|
color: "gray",
|
|
630
665
|
samples: decoded.samples
|
|
@@ -633,6 +668,37 @@ function jpegSamples(bytes) {
|
|
|
633
668
|
samples: decoded.samples
|
|
634
669
|
};
|
|
635
670
|
}
|
|
671
|
+
/**
|
|
672
|
+
* §8.6.4.4 — a four-ink JPEG taken apart and given back as the colours it
|
|
673
|
+
* paints, through the image's colour space and its `/Decode` (§8.9.5.2) as any
|
|
674
|
+
* other sampled CMYK image is, with an `/SMask` folded in where it has one.
|
|
675
|
+
*
|
|
676
|
+
* @returns The picture as a PNG, or `undefined` where the JPEG is not four
|
|
677
|
+
* inks or is past the baseline decoder — it then travels as it is.
|
|
678
|
+
*/
|
|
679
|
+
function cmykJpeg(file, d, jpegBytes, width, height) {
|
|
680
|
+
const image = decodeJpeg(jpegBytes);
|
|
681
|
+
if (image?.components !== 4) return void 0;
|
|
682
|
+
const cs = resolveColorSpace(file, d.get("ColorSpace") ?? d.get("CS"));
|
|
683
|
+
const inks = cs?.components === 4 ? cs : {
|
|
684
|
+
kind: "cmyk",
|
|
685
|
+
components: 4
|
|
686
|
+
};
|
|
687
|
+
const px = image.width * image.height;
|
|
688
|
+
const color = toColor(inks, Uint16Array.from(image.samples), px, 8, decodeArrayOf(file, d));
|
|
689
|
+
const alpha = hasSMask(file, d) ? decodeSMask(file, d, image.width, image.height) : void 0;
|
|
690
|
+
const { color: pngColor, samples } = alpha ? combineAlpha(color, alpha) : {
|
|
691
|
+
color: color.color,
|
|
692
|
+
samples: color.samples
|
|
693
|
+
};
|
|
694
|
+
return {
|
|
695
|
+
ok: true,
|
|
696
|
+
bytes: encodePng(image.width, image.height, pngColor, samples),
|
|
697
|
+
format: "png",
|
|
698
|
+
widthPx: width,
|
|
699
|
+
heightPx: height
|
|
700
|
+
};
|
|
701
|
+
}
|
|
636
702
|
function combineAlpha(color, alpha) {
|
|
637
703
|
const px = alpha.data.length;
|
|
638
704
|
if (color.color === "gray") {
|
|
@@ -22,6 +22,11 @@ export interface PdfImage {
|
|
|
22
22
|
* centre, which is what every downstream format does with one.
|
|
23
23
|
*/
|
|
24
24
|
readonly rotationDeg?: number;
|
|
25
|
+
/**
|
|
26
|
+
* §8.9.5 — the CTM MIRRORS the picture: its first row stands at the foot of
|
|
27
|
+
* the box. Drawn as a flip top to bottom, and then the turn above.
|
|
28
|
+
*/
|
|
29
|
+
readonly flipV?: boolean;
|
|
25
30
|
/**
|
|
26
31
|
* §8.5.4 — the fraction of each of the picture's OWN edges a clip cut away,
|
|
27
32
|
* where one bounded it: `a:srcRect` in DrawingML terms. Absent is whole.
|
|
@@ -3,7 +3,7 @@ import { FEATURES } from "../core/ir/features.js";
|
|
|
3
3
|
import { encodePng } from "../core/png-encode.js";
|
|
4
4
|
import { buildAlphaMap, sampledShading } from "./shading.js";
|
|
5
5
|
import { interpretContent, multiply } from "./content.js";
|
|
6
|
-
import { collectPageAppearances } from "./annots.js";
|
|
6
|
+
import { appearanceContent, collectPageAppearances } from "./annots.js";
|
|
7
7
|
import { hiddenProperties, hiddenXObject } from "./optional-content.js";
|
|
8
8
|
import { buildFonts } from "./text.js";
|
|
9
9
|
import { decodePdfImage } from "./image-decode.js";
|
|
@@ -139,7 +139,7 @@ function collectPageImages(file, page) {
|
|
|
139
139
|
0
|
|
140
140
|
], 0, void 0, []);
|
|
141
141
|
collectPageAppearances(file, page).forEach((appearance, index) => {
|
|
142
|
-
walk(appearance.resources ?? page.resources, file
|
|
142
|
+
walk(appearance.resources ?? page.resources, appearanceContent(file, appearance), appearance.ctm, 1, void 0, [Number.MAX_SAFE_INTEGER, index]);
|
|
143
143
|
});
|
|
144
144
|
return {
|
|
145
145
|
images,
|
|
@@ -150,6 +150,7 @@ function geometry(ctm, decoded, mcid, clip, alpha) {
|
|
|
150
150
|
const widthPt = Math.hypot(ctm[0], ctm[1]) || 1;
|
|
151
151
|
const heightPt = Math.hypot(ctm[2], ctm[3]) || 1;
|
|
152
152
|
const angle = Math.atan2(ctm[1], ctm[0]) * 180 / Math.PI;
|
|
153
|
+
const mirrored = ctm[0] * ctm[3] - ctm[1] * ctm[2] < 0;
|
|
153
154
|
const box = clippedUnitBox(ctm, clip);
|
|
154
155
|
const u = (box.u0 + box.u1) / 2;
|
|
155
156
|
const v = (box.v0 + box.v1) / 2;
|
|
@@ -172,6 +173,7 @@ function geometry(ctm, decoded, mcid, clip, alpha) {
|
|
|
172
173
|
y: cy - shownH / 2,
|
|
173
174
|
...crop ? { crop } : {},
|
|
174
175
|
...Math.abs(angle) > .5 ? { rotationDeg: angle } : {},
|
|
176
|
+
...mirrored ? { flipV: true } : {},
|
|
175
177
|
...mcid !== void 0 ? { mcid } : {},
|
|
176
178
|
...alpha !== void 0 ? { alpha } : {}
|
|
177
179
|
};
|
|
@@ -5,7 +5,7 @@ export interface Jbig2Bitmap {
|
|
|
5
5
|
readonly data: Uint8Array;
|
|
6
6
|
}
|
|
7
7
|
/** A context's state: the Table E.1 index and which symbol is currently more probable. */
|
|
8
|
-
interface Cx {
|
|
8
|
+
export interface Cx {
|
|
9
9
|
i: Uint8Array;
|
|
10
10
|
mps: Uint8Array;
|
|
11
11
|
}
|
|
@@ -71,6 +71,19 @@ export declare function decodeGenericRegion(mq: MQDecoder, cx: Cx, width: number
|
|
|
71
71
|
* @param dy Likewise, vertically.
|
|
72
72
|
*/
|
|
73
73
|
export declare function decodeRefinement(mq: MQDecoder, cx: Cx, width: number, height: number, template: number, reference: Jbig2Bitmap, dx: number, dy: number, at: ReadonlyArray<At>, tpgron: boolean): Jbig2Bitmap;
|
|
74
|
+
/**
|
|
75
|
+
* §B.5 — the prefix every line of standard table B.`n` is written with, the
|
|
76
|
+
* way the spec prints it: a string of bits beside the values the line covers.
|
|
77
|
+
*
|
|
78
|
+
* @param n The table's number, 1–15.
|
|
79
|
+
* @returns Its lines, shortest prefix first, each with its prefix.
|
|
80
|
+
*/
|
|
81
|
+
export declare function standardTableCodes(n: number): Array<{
|
|
82
|
+
prefix: string;
|
|
83
|
+
rangeLow: number;
|
|
84
|
+
rangeLen: number;
|
|
85
|
+
kind?: 'lower' | 'oob';
|
|
86
|
+
}>;
|
|
74
87
|
/**
|
|
75
88
|
* §6.4.5 — draw a text region: a run of strips, each holding instances of the
|
|
76
89
|
* symbols in `symbols`, placed by running coordinates rather than absolute ones.
|
|
@@ -94,6 +107,32 @@ export declare function decodeRefinement(mq: MQDecoder, cx: Cx, width: number, h
|
|
|
94
107
|
* @returns The number of bits an id takes.
|
|
95
108
|
*/
|
|
96
109
|
export declare function symbolCodeLength(symbols: number): number;
|
|
110
|
+
/**
|
|
111
|
+
* §7.4.3.1.1 — the statistics a symbol dictionary codes its bitmaps with: the
|
|
112
|
+
* generic region's contexts and the refinement's. A dictionary may keep them
|
|
113
|
+
* when it is done (bit 9) and a later one start from them (bit 8) instead of
|
|
114
|
+
* from nothing.
|
|
115
|
+
*/
|
|
116
|
+
export interface BitmapContexts {
|
|
117
|
+
readonly generic: Cx;
|
|
118
|
+
readonly refine: Cx;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* §7.4.3.2 step 3 — the statistics a symbol dictionary starts from.
|
|
122
|
+
*
|
|
123
|
+
* One that says it USES the coding context starts where the LAST dictionary it
|
|
124
|
+
* refers to was left, among those that kept theirs: the bitmaps it codes were
|
|
125
|
+
* coded against those. Started fresh, every shape of
|
|
126
|
+
* bitmap-symbol-context-reuse.pdf decoded to paper and the sheet came back
|
|
127
|
+
* blank. It starts from a copy — two dictionaries may start from the same
|
|
128
|
+
* one, and the second must not start where the first left off.
|
|
129
|
+
*
|
|
130
|
+
* @param used Whether the dictionary's flags say it uses the context (bit 8).
|
|
131
|
+
* @param referred The segments it refers to, in the order it names them.
|
|
132
|
+
* @param kept What each dictionary that retained its context was left with.
|
|
133
|
+
* @returns The contexts to decode with.
|
|
134
|
+
*/
|
|
135
|
+
export declare function startingContexts(used: boolean, referred: ReadonlyArray<number>, kept: ReadonlyMap<number, BitmapContexts>): BitmapContexts;
|
|
97
136
|
/**
|
|
98
137
|
* Decode an embedded JBIG2 image.
|
|
99
138
|
*
|
|
@@ -726,8 +726,11 @@ function huffDecode(r, t) {
|
|
|
726
726
|
* §B.5 Tables B.1–B.15 — the standard tables, as `[prefLen, rangeLen,
|
|
727
727
|
* rangeLow]` with `'lower'` and `'oob'` on the two lines that need them.
|
|
728
728
|
*
|
|
729
|
-
* They are transcribed rather than derived, and
|
|
730
|
-
*
|
|
729
|
+
* They are transcribed rather than derived, and a transcription can lose a
|
|
730
|
+
* line without a sound: B.7 came over four lines short and B.10 with five
|
|
731
|
+
* prefixes a bit or two long, and only the files that read through those two
|
|
732
|
+
* ever noticed. Every table is a complete prefix code — its lengths sum to
|
|
733
|
+
* exactly one, by Kraft — and that is what the tests hold each of them to.
|
|
731
734
|
*/
|
|
732
735
|
var STANDARD_TABLES = [
|
|
733
736
|
[
|
|
@@ -1020,18 +1023,38 @@ var STANDARD_TABLES = [
|
|
|
1020
1023
|
},
|
|
1021
1024
|
{
|
|
1022
1025
|
prefLen: 4,
|
|
1023
|
-
rangeLen:
|
|
1026
|
+
rangeLen: 5,
|
|
1024
1027
|
rangeLow: 0
|
|
1025
1028
|
},
|
|
1026
1029
|
{
|
|
1027
1030
|
prefLen: 5,
|
|
1028
|
-
rangeLen:
|
|
1031
|
+
rangeLen: 5,
|
|
1032
|
+
rangeLow: 32
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
prefLen: 5,
|
|
1036
|
+
rangeLen: 6,
|
|
1037
|
+
rangeLow: 64
|
|
1038
|
+
},
|
|
1039
|
+
{
|
|
1040
|
+
prefLen: 4,
|
|
1041
|
+
rangeLen: 7,
|
|
1042
|
+
rangeLow: 128
|
|
1043
|
+
},
|
|
1044
|
+
{
|
|
1045
|
+
prefLen: 3,
|
|
1046
|
+
rangeLen: 8,
|
|
1047
|
+
rangeLow: 256
|
|
1048
|
+
},
|
|
1049
|
+
{
|
|
1050
|
+
prefLen: 3,
|
|
1051
|
+
rangeLen: 9,
|
|
1029
1052
|
rangeLow: 512
|
|
1030
1053
|
},
|
|
1031
1054
|
{
|
|
1032
1055
|
prefLen: 3,
|
|
1033
1056
|
rangeLen: 10,
|
|
1034
|
-
rangeLow:
|
|
1057
|
+
rangeLow: 1024
|
|
1035
1058
|
},
|
|
1036
1059
|
{
|
|
1037
1060
|
prefLen: 5,
|
|
@@ -1042,7 +1065,7 @@ var STANDARD_TABLES = [
|
|
|
1042
1065
|
{
|
|
1043
1066
|
prefLen: 5,
|
|
1044
1067
|
rangeLen: 32,
|
|
1045
|
-
rangeLow:
|
|
1068
|
+
rangeLow: 2048
|
|
1046
1069
|
}
|
|
1047
1070
|
],
|
|
1048
1071
|
[
|
|
@@ -1330,27 +1353,27 @@ var STANDARD_TABLES = [
|
|
|
1330
1353
|
rangeLow: 102
|
|
1331
1354
|
},
|
|
1332
1355
|
{
|
|
1333
|
-
prefLen:
|
|
1356
|
+
prefLen: 6,
|
|
1334
1357
|
rangeLen: 6,
|
|
1335
1358
|
rangeLow: 134
|
|
1336
1359
|
},
|
|
1337
1360
|
{
|
|
1338
|
-
prefLen:
|
|
1361
|
+
prefLen: 6,
|
|
1339
1362
|
rangeLen: 7,
|
|
1340
1363
|
rangeLow: 198
|
|
1341
1364
|
},
|
|
1342
1365
|
{
|
|
1343
|
-
prefLen:
|
|
1366
|
+
prefLen: 6,
|
|
1344
1367
|
rangeLen: 8,
|
|
1345
1368
|
rangeLow: 326
|
|
1346
1369
|
},
|
|
1347
1370
|
{
|
|
1348
|
-
prefLen:
|
|
1371
|
+
prefLen: 6,
|
|
1349
1372
|
rangeLen: 9,
|
|
1350
1373
|
rangeLow: 582
|
|
1351
1374
|
},
|
|
1352
1375
|
{
|
|
1353
|
-
prefLen:
|
|
1376
|
+
prefLen: 6,
|
|
1354
1377
|
rangeLen: 10,
|
|
1355
1378
|
rangeLow: 1094
|
|
1356
1379
|
},
|
|
@@ -1879,15 +1902,15 @@ function decodeTextRegion(mq, symbols, p, stripsLog, lent) {
|
|
|
1879
1902
|
*
|
|
1880
1903
|
* @param input The symbols this dictionary inherits from the ones it refers to.
|
|
1881
1904
|
*/
|
|
1882
|
-
function decodeSymbolDictionary(mq, input, newCount, exportCount, template, at, refAgg, rTemplate, rAt) {
|
|
1905
|
+
function decodeSymbolDictionary(mq, input, newCount, exportCount, template, at, refAgg, rTemplate, rAt, contexts = freshBitmapContexts()) {
|
|
1883
1906
|
const iadh = new IntDecoder(mq);
|
|
1884
1907
|
const iadw = new IntDecoder(mq);
|
|
1885
1908
|
const iaex = new IntDecoder(mq);
|
|
1886
1909
|
const iaai = new IntDecoder(mq);
|
|
1887
1910
|
const iardx = new IntDecoder(mq);
|
|
1888
1911
|
const iardy = new IntDecoder(mq);
|
|
1889
|
-
const genericCx =
|
|
1890
|
-
const refineCx =
|
|
1912
|
+
const genericCx = contexts.generic;
|
|
1913
|
+
const refineCx = contexts.refine;
|
|
1891
1914
|
const newSymbols = [];
|
|
1892
1915
|
const num = (v) => v === OOB ? 0 : v;
|
|
1893
1916
|
const codeLen = symbolCodeLength(input.length + newCount);
|
|
@@ -2365,6 +2388,41 @@ function compose(dst, src, x0, y0, op) {
|
|
|
2365
2388
|
}
|
|
2366
2389
|
}
|
|
2367
2390
|
}
|
|
2391
|
+
function freshBitmapContexts() {
|
|
2392
|
+
return {
|
|
2393
|
+
generic: newContexts(65536),
|
|
2394
|
+
refine: newContexts(8192)
|
|
2395
|
+
};
|
|
2396
|
+
}
|
|
2397
|
+
/**
|
|
2398
|
+
* §7.4.3.2 step 3 — the statistics a symbol dictionary starts from.
|
|
2399
|
+
*
|
|
2400
|
+
* One that says it USES the coding context starts where the LAST dictionary it
|
|
2401
|
+
* refers to was left, among those that kept theirs: the bitmaps it codes were
|
|
2402
|
+
* coded against those. Started fresh, every shape of
|
|
2403
|
+
* bitmap-symbol-context-reuse.pdf decoded to paper and the sheet came back
|
|
2404
|
+
* blank. It starts from a copy — two dictionaries may start from the same
|
|
2405
|
+
* one, and the second must not start where the first left off.
|
|
2406
|
+
*
|
|
2407
|
+
* @param used Whether the dictionary's flags say it uses the context (bit 8).
|
|
2408
|
+
* @param referred The segments it refers to, in the order it names them.
|
|
2409
|
+
* @param kept What each dictionary that retained its context was left with.
|
|
2410
|
+
* @returns The contexts to decode with.
|
|
2411
|
+
*/
|
|
2412
|
+
function startingContexts(used, referred, kept) {
|
|
2413
|
+
const last = used ? referred.map((n) => kept.get(n)).filter((c) => c !== void 0).at(-1) : void 0;
|
|
2414
|
+
if (last === void 0) return freshBitmapContexts();
|
|
2415
|
+
return {
|
|
2416
|
+
generic: {
|
|
2417
|
+
i: last.generic.i.slice(),
|
|
2418
|
+
mps: last.generic.mps.slice()
|
|
2419
|
+
},
|
|
2420
|
+
refine: {
|
|
2421
|
+
i: last.refine.i.slice(),
|
|
2422
|
+
mps: last.refine.mps.slice()
|
|
2423
|
+
}
|
|
2424
|
+
};
|
|
2425
|
+
}
|
|
2368
2426
|
/**
|
|
2369
2427
|
* Decode an embedded JBIG2 image.
|
|
2370
2428
|
*
|
|
@@ -2391,6 +2449,7 @@ function decodeJbig2(data, globals, width, height) {
|
|
|
2391
2449
|
const symbolsBySegment = /* @__PURE__ */ new Map();
|
|
2392
2450
|
const patternsBySegment = /* @__PURE__ */ new Map();
|
|
2393
2451
|
const tablesBySegment = /* @__PURE__ */ new Map();
|
|
2452
|
+
const contextsBySegment = /* @__PURE__ */ new Map();
|
|
2394
2453
|
const run = (bytes) => {
|
|
2395
2454
|
for (const seg of parseSegments(bytes)) {
|
|
2396
2455
|
const r = new Reader(bytes.subarray(seg.start, seg.end));
|
|
@@ -2496,7 +2555,8 @@ function decodeJbig2(data, globals, width, height) {
|
|
|
2496
2555
|
const refAgg = (flags & 2) !== 0;
|
|
2497
2556
|
const template = flags >> 10 & 3;
|
|
2498
2557
|
const rTemplate = flags >> 12 & 1;
|
|
2499
|
-
flags & 256;
|
|
2558
|
+
const ctxUsed = (flags & 256) !== 0;
|
|
2559
|
+
const ctxRetained = (flags & 512) !== 0;
|
|
2500
2560
|
const at = [];
|
|
2501
2561
|
if (!huff) {
|
|
2502
2562
|
const n = template === 0 ? 4 : 1;
|
|
@@ -2529,7 +2589,9 @@ function decodeJbig2(data, globals, width, height) {
|
|
|
2529
2589
|
} : void 0));
|
|
2530
2590
|
continue;
|
|
2531
2591
|
}
|
|
2532
|
-
|
|
2592
|
+
const contexts = startingContexts(ctxUsed, seg.referred, contextsBySegment);
|
|
2593
|
+
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, contexts));
|
|
2594
|
+
if (ctxRetained) contextsBySegment.set(seg.number, contexts);
|
|
2533
2595
|
continue;
|
|
2534
2596
|
}
|
|
2535
2597
|
if (seg.type === 4 || seg.type === 6 || seg.type === 7) {
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
/** A decoded JPEG: 8-bit interleaved samples, one or
|
|
1
|
+
/** A decoded JPEG: 8-bit interleaved samples, one, three or four components. */
|
|
2
2
|
export interface DecodedJpeg {
|
|
3
3
|
readonly width: number;
|
|
4
4
|
readonly height: number;
|
|
5
|
-
/**
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* 1 = grayscale, 3 = RGB (already converted from YCbCr where it applies),
|
|
7
|
+
* 4 = CMYK as the stream stores it (converted from YCCK where it applies).
|
|
8
|
+
*/
|
|
9
|
+
readonly components: 1 | 3 | 4;
|
|
7
10
|
/** `width * height * components` bytes, row-major. */
|
|
8
11
|
readonly samples: Uint8Array;
|
|
9
12
|
}
|
|
@@ -151,7 +151,7 @@ function readFrame(bytes, p) {
|
|
|
151
151
|
const width = be16(bytes, p + 3);
|
|
152
152
|
const count = bytes[p + 5];
|
|
153
153
|
if (width <= 0 || height <= 0 || width * height > MAX_PIXELS) return void 0;
|
|
154
|
-
if (count !== 1 && count !== 3) return void 0;
|
|
154
|
+
if (count !== 1 && count !== 3 && count !== 4) return void 0;
|
|
155
155
|
const comps = [];
|
|
156
156
|
let maxH = 1;
|
|
157
157
|
let maxV = 1;
|
|
@@ -393,6 +393,15 @@ function assemble(frame, adobeTransform) {
|
|
|
393
393
|
components: 1,
|
|
394
394
|
samples
|
|
395
395
|
};
|
|
396
|
+
if (n === 4) {
|
|
397
|
+
if (adobeTransform === 2) ycckToCmyk(samples);
|
|
398
|
+
return {
|
|
399
|
+
width,
|
|
400
|
+
height,
|
|
401
|
+
components: 4,
|
|
402
|
+
samples
|
|
403
|
+
};
|
|
404
|
+
}
|
|
396
405
|
if (adobeTransform !== 0) ycbcrToRgb(samples);
|
|
397
406
|
return {
|
|
398
407
|
width,
|
|
@@ -401,6 +410,17 @@ function assemble(frame, adobeTransform) {
|
|
|
401
410
|
samples
|
|
402
411
|
};
|
|
403
412
|
}
|
|
413
|
+
/** Adobe's YCCK → CMYK, in place: the YCbCr → RGB conversion, complemented. */
|
|
414
|
+
function ycckToCmyk(s) {
|
|
415
|
+
for (let i = 0; i < s.length; i += 4) {
|
|
416
|
+
const y = s[i];
|
|
417
|
+
const cb = s[i + 1] - 128;
|
|
418
|
+
const cr = s[i + 2] - 128;
|
|
419
|
+
s[i] = 255 - clamp(y + 1.402 * cr);
|
|
420
|
+
s[i + 1] = 255 - clamp(y - .344136 * cb - .714136 * cr);
|
|
421
|
+
s[i + 2] = 255 - clamp(y + 1.772 * cb);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
404
424
|
/** ITU-T T.871 §7 — the JFIF YCbCr → RGB conversion, in place. */
|
|
405
425
|
function ycbcrToRgb(s) {
|
|
406
426
|
for (let i = 0; i < s.length; i += 3) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PdfVector } from './vector.js';
|
|
1
2
|
import { PdfFile } from './document.js';
|
|
2
3
|
import { Reconstruction } from './flow-build.js';
|
|
3
4
|
/** §9.10.2 — a glyph the face maps to no character (see `./font`). */
|
|
@@ -33,8 +34,14 @@ export declare function reconstructByLayout(file: PdfFile, mode?: 'flow' | 'posi
|
|
|
33
34
|
* placed rather than set — a centred title's every line is short of the measure
|
|
34
35
|
* and none of them ends anything.
|
|
35
36
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
37
|
+
* A line of a right-to-left script starts at the RIGHT and ends at the left,
|
|
38
|
+
* and is read the other way round: ArabicCIDTrueType.pdf sets four lines, each
|
|
39
|
+
* flush right and shorter than the one before, and read as a left-to-right
|
|
40
|
+
* setting every pair of them ran together as one paragraph.
|
|
41
|
+
*
|
|
42
|
+
* @param prev The line before: where it starts, how wide it is, its face,
|
|
43
|
+
* and its text when it has any.
|
|
44
|
+
* @param next The line after — where it starts, and how wide it is.
|
|
38
45
|
* @param column The measure both were set in, when it is known.
|
|
39
46
|
* @returns Whether the first line ended a paragraph.
|
|
40
47
|
*/
|
|
@@ -42,9 +49,26 @@ export declare function endedParagraph(prev: {
|
|
|
42
49
|
x: number;
|
|
43
50
|
width: number;
|
|
44
51
|
fontSize: number;
|
|
52
|
+
text?: string;
|
|
45
53
|
}, next: {
|
|
46
54
|
x: number;
|
|
55
|
+
width?: number;
|
|
47
56
|
}, column: {
|
|
48
57
|
left: number;
|
|
49
58
|
right: number;
|
|
50
59
|
} | undefined): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* §9.6.6 — the glyphs a page draws for want of characters, gathered into the
|
|
62
|
+
* WORDS they stand in: a traced glyph that stands against the one before it,
|
|
63
|
+
* on its line and in its colour, is drawn as one shape with it.
|
|
64
|
+
*
|
|
65
|
+
* Every mark kept apart is a shape of its own in the document, anchored to
|
|
66
|
+
* the page — and a paper set in a subset whose glyphs name nothing is nothing
|
|
67
|
+
* but such marks: TAMReview.pdf came back as forty-two thousand shapes, a
|
|
68
|
+
* package no reader would open in under three minutes. The picture is the
|
|
69
|
+
* same either way.
|
|
70
|
+
*
|
|
71
|
+
* @param vectors The page's painted paths, in painting order.
|
|
72
|
+
* @returns The same paths, each run of traced glyphs made one.
|
|
73
|
+
*/
|
|
74
|
+
export declare function drawnWords(vectors: ReadonlyArray<PdfVector>): Array<PdfVector>;
|