pdf-parser.js 5.2.26 → 5.2.28
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/{afm-widths-BYiX2L9D.cjs → afm-widths-BHD2HZIL.cjs} +553 -642
- package/dist/{afm-widths-blUDDjlI.js → afm-widths-B_IGbGky.js} +553 -642
- package/dist/afm-widths.cjs +1 -1
- package/dist/afm-widths.js +1 -1
- package/dist/annotations.cjs +5 -3
- package/dist/annotations.d.cts +2 -2
- package/dist/annotations.d.ts +2 -2
- package/dist/annotations.js +5 -3
- package/dist/attachments.d.cts +2 -2
- package/dist/attachments.d.ts +2 -2
- package/dist/builtin-encoding.cjs +17 -6
- package/dist/builtin-encoding.js +17 -6
- package/dist/bytes/crc32.cjs +5 -3
- package/dist/bytes/crc32.js +5 -3
- package/dist/bytes/flate.cjs +0 -1
- package/dist/bytes/flate.js +0 -1
- package/dist/cff-bounds.cjs +73 -45
- package/dist/cff-bounds.js +73 -45
- package/dist/cff.cjs +13 -6
- package/dist/cff.js +13 -6
- package/dist/cmap-table.cjs +54 -26
- package/dist/cmap-table.js +54 -26
- package/dist/cmap.cjs +5 -3
- package/dist/cmap.js +5 -3
- package/dist/content-read.d.cts +1 -1
- package/dist/content-read.d.ts +1 -1
- package/dist/content-write.cjs +21 -14
- package/dist/content-write.d.cts +2 -2
- package/dist/content-write.d.ts +2 -2
- package/dist/content-write.js +21 -14
- package/dist/crypto/aes.cjs +76 -55
- package/dist/crypto/aes.js +76 -55
- package/dist/crypto/md5.cjs +345 -149
- package/dist/crypto/md5.js +345 -149
- package/dist/crypto/rc4.cjs +5 -4
- package/dist/crypto/rc4.js +5 -4
- package/dist/crypto/sha2.cjs +92 -43
- package/dist/crypto/sha2.js +92 -43
- package/dist/document.cjs +17 -11
- package/dist/document.d.cts +1 -1
- package/dist/document.d.ts +1 -1
- package/dist/document.js +17 -11
- package/dist/{embedded-font-Bnhh4juV.d.ts → embedded-font-ByD7ZiQS.d.ts} +1 -1
- package/dist/{embedded-font-CEf-zBCA.d.cts → embedded-font-DgVBedw6.d.cts} +1 -1
- package/dist/embedded-font-write.d.cts +2 -2
- package/dist/embedded-font-write.d.ts +2 -2
- package/dist/embedded-font.cjs +4 -2
- package/dist/embedded-font.d.cts +1 -1
- package/dist/embedded-font.d.ts +1 -1
- package/dist/embedded-font.js +4 -2
- package/dist/encoding.cjs +1 -1
- package/dist/encoding.js +1 -1
- package/dist/encrypt-write.cjs +25 -21
- package/dist/encrypt-write.d.cts +1 -1
- package/dist/encrypt-write.d.ts +1 -1
- package/dist/encrypt-write.js +25 -21
- package/dist/encrypt.cjs +43 -64
- package/dist/encrypt.d.cts +1 -1
- package/dist/encrypt.d.ts +1 -1
- package/dist/encrypt.js +43 -64
- package/dist/filters.cjs +46 -26
- package/dist/filters.d.cts +1 -1
- package/dist/filters.d.ts +1 -1
- package/dist/filters.js +46 -26
- package/dist/font-face.cjs +2 -1
- package/dist/font-face.js +2 -1
- package/dist/font-read.cjs +12 -6
- package/dist/font-read.d.cts +1 -1
- package/dist/font-read.d.ts +1 -1
- package/dist/font-read.js +12 -6
- package/dist/font-registry.d.cts +3 -3
- package/dist/font-registry.d.ts +3 -3
- package/dist/font-tables.cjs +55 -28
- package/dist/font-tables.js +55 -28
- package/dist/form.cjs +13 -8
- package/dist/form.d.cts +2 -2
- package/dist/form.d.ts +2 -2
- package/dist/form.js +13 -8
- package/dist/gdef-table.cjs +6 -3
- package/dist/gdef-table.js +6 -3
- package/dist/{glyf-contours-C0epBNqP.d.ts → glyf-contours-B1PsI9oA.d.ts} +1 -1
- package/dist/{glyf-contours-BRpvd0rt.d.cts → glyf-contours-NHBpgks-.d.cts} +1 -1
- package/dist/glyf-contours.cjs +3 -1
- package/dist/glyf-contours.d.cts +1 -1
- package/dist/glyf-contours.d.ts +1 -1
- package/dist/glyf-contours.js +3 -1
- package/dist/glyf.cjs +22 -11
- package/dist/glyf.js +22 -11
- package/dist/gpos-table.cjs +37 -19
- package/dist/gpos-table.js +37 -19
- package/dist/gsub-table.cjs +40 -25
- package/dist/gsub-table.js +40 -25
- package/dist/hmtx-table.cjs +5 -3
- package/dist/hmtx-table.js +5 -3
- package/dist/image/ccitt-encode.cjs +8 -5
- package/dist/image/ccitt-encode.js +8 -5
- package/dist/image/ccitt.cjs +801 -209
- package/dist/image/ccitt.js +801 -209
- package/dist/image/jbig2-arith.cjs +340 -306
- package/dist/image/jbig2-arith.js +340 -306
- package/dist/image/jbig2-bitmap.cjs +8 -5
- package/dist/image/jbig2-bitmap.js +8 -5
- package/dist/image/jbig2-generic.cjs +240 -69
- package/dist/image/jbig2-generic.js +240 -69
- package/dist/image/jbig2-text.cjs +4 -2
- package/dist/image/jbig2-text.js +4 -2
- package/dist/image/jbig2.cjs +69 -31
- package/dist/image/jbig2.js +69 -31
- package/dist/image/jp2-boxes.cjs +52 -27
- package/dist/image/jp2-boxes.js +52 -27
- package/dist/image/jpeg-info.cjs +29 -24
- package/dist/image/jpeg-info.js +29 -24
- package/dist/image/jpeg2000-codestream.cjs +61 -32
- package/dist/image/jpeg2000-codestream.js +61 -32
- package/dist/image/jpeg2000-dwt.cjs +2 -1
- package/dist/image/jpeg2000-dwt.js +2 -1
- package/dist/image/jpeg2000-t1.cjs +21 -11
- package/dist/image/jpeg2000-t1.js +21 -11
- package/dist/image/jpeg2000-t2.cjs +12 -5
- package/dist/image/jpeg2000-t2.js +12 -5
- package/dist/image/jpeg2000-tagtree.cjs +8 -4
- package/dist/image/jpeg2000-tagtree.js +8 -4
- package/dist/image/jpeg2000.cjs +11 -6
- package/dist/image/jpeg2000.js +11 -6
- package/dist/image/png-decode.cjs +62 -39
- package/dist/image/png-decode.d.cts +3 -2
- package/dist/image/png-decode.d.ts +3 -2
- package/dist/image/png-decode.js +62 -39
- package/dist/image/png-filter.cjs +23 -15
- package/dist/image/png-filter.js +23 -15
- package/dist/images-read.cjs +41 -36
- package/dist/images-read.d.cts +2 -2
- package/dist/images-read.d.ts +2 -2
- package/dist/images-read.js +41 -36
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/interpret.cjs +68 -40
- package/dist/interpret.d.cts +1 -1
- package/dist/interpret.d.ts +1 -1
- package/dist/interpret.js +68 -40
- package/dist/lexer.cjs +86 -51
- package/dist/lexer.js +86 -51
- package/dist/math-content-write.cjs +9 -5
- package/dist/math-content-write.js +9 -5
- package/dist/math-font-write.cjs +2 -1
- package/dist/math-font-write.d.cts +1 -1
- package/dist/math-font-write.d.ts +1 -1
- package/dist/math-font-write.js +2 -1
- package/dist/math-font.cjs +16 -7
- package/dist/math-font.js +16 -7
- package/dist/math-table.cjs +25 -13
- package/dist/math-table.js +25 -13
- package/dist/matrix.cjs +3 -2
- package/dist/matrix.js +3 -2
- package/dist/measure.cjs +1 -1
- package/dist/measure.js +1 -1
- package/dist/names.cjs +7 -7
- package/dist/names.d.cts +2 -2
- package/dist/names.d.ts +2 -2
- package/dist/names.js +7 -7
- package/dist/navigation.cjs +16 -12
- package/dist/navigation.d.cts +4 -4
- package/dist/navigation.d.ts +4 -4
- package/dist/navigation.js +16 -12
- package/dist/{objects-B7HdMeWS.d.cts → objects-e2RS3-yT.d.cts} +3 -3
- package/dist/{objects-B7HdMeWS.d.ts → objects-e2RS3-yT.d.ts} +3 -3
- package/dist/objects.d.cts +1 -1
- package/dist/objects.d.ts +1 -1
- package/dist/optional-content.d.cts +2 -2
- package/dist/optional-content.d.ts +2 -2
- package/dist/ot-layout-common.cjs +22 -15
- package/dist/ot-layout-common.js +22 -15
- package/dist/parse.cjs +7 -5
- package/dist/parse.d.cts +1 -1
- package/dist/parse.d.ts +1 -1
- package/dist/parse.js +7 -5
- package/dist/pdf-text.cjs +5 -2
- package/dist/pdf-text.js +5 -2
- package/dist/predictors.cjs +14 -9
- package/dist/predictors.d.cts +1 -1
- package/dist/predictors.d.ts +1 -1
- package/dist/predictors.js +14 -9
- package/dist/raster.cjs +30 -19
- package/dist/raster.d.cts +8 -8
- package/dist/raster.d.ts +8 -8
- package/dist/raster.js +30 -19
- package/dist/read.cjs +29 -16
- package/dist/read.js +29 -16
- package/dist/serialize.cjs +6 -2
- package/dist/serialize.d.cts +1 -1
- package/dist/serialize.d.ts +1 -1
- package/dist/serialize.js +6 -2
- package/dist/sfnt-subset.cjs +25 -13
- package/dist/sfnt-subset.d.cts +1 -1
- package/dist/sfnt-subset.d.ts +1 -1
- package/dist/sfnt-subset.js +25 -13
- package/dist/sfnt.cjs +20 -10
- package/dist/sfnt.js +20 -10
- package/dist/structure.d.cts +2 -2
- package/dist/structure.d.ts +2 -2
- package/dist/text-group.cjs +0 -1
- package/dist/text-group.js +0 -1
- package/dist/text-layout.d.cts +1 -1
- package/dist/text-layout.d.ts +1 -1
- package/dist/tounicode.cjs +4 -2
- package/dist/tounicode.d.cts +1 -1
- package/dist/tounicode.d.ts +1 -1
- package/dist/tounicode.js +4 -2
- package/dist/winansi.cjs +1 -1
- package/dist/winansi.js +1 -1
- package/dist/write.cjs +20 -12
- package/dist/write.d.cts +1 -1
- package/dist/write.d.ts +1 -1
- package/dist/write.js +20 -12
- package/dist/xref.cjs +5 -2
- package/dist/xref.d.cts +1 -1
- package/dist/xref.d.ts +1 -1
- package/dist/xref.js +5 -2
- package/package.json +1 -1
package/dist/parse.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.cjs";
|
|
2
|
-
import { r as PdfObject } from "./objects-
|
|
2
|
+
import { r as PdfObject } from "./objects-e2RS3-yT.cjs";
|
|
3
3
|
import { ByteReader } from "./bytes/reader.cjs";
|
|
4
4
|
//#region src/parse.d.ts
|
|
5
5
|
declare function parseValue(reader: ByteReader, sink: PdfDiagnosticSink): PdfObject | undefined;
|
package/dist/parse.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.js";
|
|
2
|
-
import { r as PdfObject } from "./objects-
|
|
2
|
+
import { r as PdfObject } from "./objects-e2RS3-yT.js";
|
|
3
3
|
import { ByteReader } from "./bytes/reader.js";
|
|
4
4
|
//#region src/parse.d.ts
|
|
5
5
|
declare function parseValue(reader: ByteReader, sink: PdfDiagnosticSink): PdfObject | undefined;
|
package/dist/parse.js
CHANGED
|
@@ -109,10 +109,12 @@ function parseDictOrStreamBody(reader, sink) {
|
|
|
109
109
|
reader.reset(afterDictMark);
|
|
110
110
|
return dict;
|
|
111
111
|
}
|
|
112
|
+
const CARRIAGE_RETURN = 13;
|
|
113
|
+
const LINE_FEED = 10;
|
|
112
114
|
function skipStreamDataStart(reader, sink) {
|
|
113
|
-
if (reader.peek() ===
|
|
115
|
+
if (reader.peek() === CARRIAGE_RETURN) {
|
|
114
116
|
reader.next();
|
|
115
|
-
if (reader.peek() ===
|
|
117
|
+
if (reader.peek() === LINE_FEED) reader.next();
|
|
116
118
|
else sink({
|
|
117
119
|
code: "pdf/stream-bad-eol",
|
|
118
120
|
severity: "warning",
|
|
@@ -120,7 +122,7 @@ function skipStreamDataStart(reader, sink) {
|
|
|
120
122
|
});
|
|
121
123
|
return;
|
|
122
124
|
}
|
|
123
|
-
if (reader.peek() ===
|
|
125
|
+
if (reader.peek() === LINE_FEED) {
|
|
124
126
|
reader.next();
|
|
125
127
|
return;
|
|
126
128
|
}
|
|
@@ -186,8 +188,8 @@ function findEndstreamOffset(reader, fromOffset) {
|
|
|
186
188
|
}
|
|
187
189
|
function trimTrailingStreamEol(reader, dataStart, endstreamOffset) {
|
|
188
190
|
const precedingTwo = reader.slice(Math.max(dataStart, endstreamOffset - 2), endstreamOffset);
|
|
189
|
-
if (precedingTwo.length >= 2 && precedingTwo[precedingTwo.length - 2] ===
|
|
190
|
-
if (precedingTwo.length >= 1 && (precedingTwo[precedingTwo.length - 1] ===
|
|
191
|
+
if (precedingTwo.length >= 2 && precedingTwo[precedingTwo.length - 2] === CARRIAGE_RETURN && precedingTwo[precedingTwo.length - 1] === LINE_FEED) return endstreamOffset - 2;
|
|
192
|
+
if (precedingTwo.length >= 1 && (precedingTwo[precedingTwo.length - 1] === LINE_FEED || precedingTwo[precedingTwo.length - 1] === CARRIAGE_RETURN)) return endstreamOffset - 1;
|
|
191
193
|
return endstreamOffset;
|
|
192
194
|
}
|
|
193
195
|
function parseIndirectObject(reader, sink) {
|
package/dist/pdf-text.cjs
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
//#region src/pdf-text.ts
|
|
3
|
+
const UTF16BE_BOM_BYTE_0 = 254;
|
|
4
|
+
const UTF16BE_BOM_BYTE_1 = 255;
|
|
5
|
+
const BITS_PER_BYTE = 8;
|
|
3
6
|
function decodePdfString(bytes) {
|
|
4
|
-
if (bytes.length >= 2 && bytes[0] ===
|
|
7
|
+
if (bytes.length >= 2 && bytes[0] === UTF16BE_BOM_BYTE_0 && bytes[1] === UTF16BE_BOM_BYTE_1) {
|
|
5
8
|
let out = "";
|
|
6
|
-
for (let i = 2; i + 1 < bytes.length; i += 2) out += String.fromCharCode((bytes[i] ?? 0) <<
|
|
9
|
+
for (let i = 2; i + 1 < bytes.length; i += 2) out += String.fromCharCode((bytes[i] ?? 0) << BITS_PER_BYTE | (bytes[i + 1] ?? 0));
|
|
7
10
|
return out;
|
|
8
11
|
}
|
|
9
12
|
return Array.from(bytes, (b) => String.fromCharCode(b)).join("");
|
package/dist/pdf-text.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
//#region src/pdf-text.ts
|
|
2
|
+
const UTF16BE_BOM_BYTE_0 = 254;
|
|
3
|
+
const UTF16BE_BOM_BYTE_1 = 255;
|
|
4
|
+
const BITS_PER_BYTE = 8;
|
|
2
5
|
function decodePdfString(bytes) {
|
|
3
|
-
if (bytes.length >= 2 && bytes[0] ===
|
|
6
|
+
if (bytes.length >= 2 && bytes[0] === UTF16BE_BOM_BYTE_0 && bytes[1] === UTF16BE_BOM_BYTE_1) {
|
|
4
7
|
let out = "";
|
|
5
|
-
for (let i = 2; i + 1 < bytes.length; i += 2) out += String.fromCharCode((bytes[i] ?? 0) <<
|
|
8
|
+
for (let i = 2; i + 1 < bytes.length; i += 2) out += String.fromCharCode((bytes[i] ?? 0) << BITS_PER_BYTE | (bytes[i + 1] ?? 0));
|
|
6
9
|
return out;
|
|
7
10
|
}
|
|
8
11
|
return Array.from(bytes, (b) => String.fromCharCode(b)).join("");
|
package/dist/predictors.cjs
CHANGED
|
@@ -6,6 +6,11 @@ const DEFAULT_PREDICTOR = 1;
|
|
|
6
6
|
const DEFAULT_COLORS = 1;
|
|
7
7
|
const DEFAULT_BITS_PER_COMPONENT = 8;
|
|
8
8
|
const DEFAULT_COLUMNS = 1;
|
|
9
|
+
const BITS_PER_BYTE = 8;
|
|
10
|
+
const BYTE_MASK = 255;
|
|
11
|
+
const PNG_PREDICTOR_CODE_MIN = 10;
|
|
12
|
+
const SIXTEEN_BIT_COMPONENT = 16;
|
|
13
|
+
const SIXTEEN_BIT_SAMPLE_MASK = 65535;
|
|
9
14
|
function readPredictorParams(parms) {
|
|
10
15
|
return {
|
|
11
16
|
predictor: require_objects.asNumber(parms ? require_objects.dictGet(parms, "Predictor") : void 0) ?? DEFAULT_PREDICTOR,
|
|
@@ -16,10 +21,10 @@ function readPredictorParams(parms) {
|
|
|
16
21
|
}
|
|
17
22
|
function applyPredictor(data, params, sink) {
|
|
18
23
|
if (params.predictor <= 1) return data;
|
|
19
|
-
const bpp = Math.max(1, Math.ceil(params.colors * params.bitsPerComponent /
|
|
20
|
-
const bytesPerRow = Math.ceil(params.colors * params.bitsPerComponent * params.columns /
|
|
24
|
+
const bpp = Math.max(1, Math.ceil(params.colors * params.bitsPerComponent / BITS_PER_BYTE));
|
|
25
|
+
const bytesPerRow = Math.ceil(params.colors * params.bitsPerComponent * params.columns / BITS_PER_BYTE);
|
|
21
26
|
if (params.predictor === 2) return applyTiffPredictor(data, params, bytesPerRow, sink);
|
|
22
|
-
if (params.predictor >=
|
|
27
|
+
if (params.predictor >= PNG_PREDICTOR_CODE_MIN) {
|
|
23
28
|
const height = bytesPerRow > 0 ? Math.floor(data.length / (bytesPerRow + 1)) : 0;
|
|
24
29
|
return require_image_png_filter.unfilterScanlines(data, height, bytesPerRow, bpp);
|
|
25
30
|
}
|
|
@@ -31,7 +36,7 @@ function applyPredictor(data, params, sink) {
|
|
|
31
36
|
return data;
|
|
32
37
|
}
|
|
33
38
|
function applyTiffPredictor(data, params, bytesPerRow, sink) {
|
|
34
|
-
if (params.bitsPerComponent !==
|
|
39
|
+
if (params.bitsPerComponent !== BITS_PER_BYTE && params.bitsPerComponent !== SIXTEEN_BIT_COMPONENT) {
|
|
35
40
|
sink({
|
|
36
41
|
code: "pdf/unsupported-predictor",
|
|
37
42
|
severity: "warning",
|
|
@@ -42,18 +47,18 @@ function applyTiffPredictor(data, params, bytesPerRow, sink) {
|
|
|
42
47
|
const out = new Uint8Array(data.length);
|
|
43
48
|
out.set(data);
|
|
44
49
|
const rowCount = bytesPerRow > 0 ? Math.floor(out.length / bytesPerRow) : 0;
|
|
45
|
-
const componentStride = params.bitsPerComponent ===
|
|
50
|
+
const componentStride = params.bitsPerComponent === SIXTEEN_BIT_COMPONENT ? 2 : 1;
|
|
46
51
|
const componentsPerPixel = params.colors;
|
|
47
52
|
for (let row = 0; row < rowCount; row++) {
|
|
48
53
|
const rowStart = row * bytesPerRow;
|
|
49
54
|
for (let component = componentsPerPixel; component * componentStride < bytesPerRow; component++) {
|
|
50
55
|
const i = rowStart + component * componentStride;
|
|
51
56
|
const prevI = i - componentsPerPixel * componentStride;
|
|
52
|
-
if (componentStride === 1) out[i] = (out[i] ?? 0) + (out[prevI] ?? 0) &
|
|
57
|
+
if (componentStride === 1) out[i] = (out[i] ?? 0) + (out[prevI] ?? 0) & BYTE_MASK;
|
|
53
58
|
else {
|
|
54
|
-
const sum = ((out[i] ?? 0) <<
|
|
55
|
-
out[i] = sum >>
|
|
56
|
-
out[i + 1] = sum &
|
|
59
|
+
const sum = ((out[i] ?? 0) << BITS_PER_BYTE | (out[i + 1] ?? 0)) + ((out[prevI] ?? 0) << BITS_PER_BYTE | (out[prevI + 1] ?? 0)) & SIXTEEN_BIT_SAMPLE_MASK;
|
|
60
|
+
out[i] = sum >> BITS_PER_BYTE & BYTE_MASK;
|
|
61
|
+
out[i + 1] = sum & BYTE_MASK;
|
|
57
62
|
}
|
|
58
63
|
}
|
|
59
64
|
}
|
package/dist/predictors.d.cts
CHANGED
package/dist/predictors.d.ts
CHANGED
package/dist/predictors.js
CHANGED
|
@@ -5,6 +5,11 @@ const DEFAULT_PREDICTOR = 1;
|
|
|
5
5
|
const DEFAULT_COLORS = 1;
|
|
6
6
|
const DEFAULT_BITS_PER_COMPONENT = 8;
|
|
7
7
|
const DEFAULT_COLUMNS = 1;
|
|
8
|
+
const BITS_PER_BYTE = 8;
|
|
9
|
+
const BYTE_MASK = 255;
|
|
10
|
+
const PNG_PREDICTOR_CODE_MIN = 10;
|
|
11
|
+
const SIXTEEN_BIT_COMPONENT = 16;
|
|
12
|
+
const SIXTEEN_BIT_SAMPLE_MASK = 65535;
|
|
8
13
|
function readPredictorParams(parms) {
|
|
9
14
|
return {
|
|
10
15
|
predictor: asNumber(parms ? dictGet(parms, "Predictor") : void 0) ?? DEFAULT_PREDICTOR,
|
|
@@ -15,10 +20,10 @@ function readPredictorParams(parms) {
|
|
|
15
20
|
}
|
|
16
21
|
function applyPredictor(data, params, sink) {
|
|
17
22
|
if (params.predictor <= 1) return data;
|
|
18
|
-
const bpp = Math.max(1, Math.ceil(params.colors * params.bitsPerComponent /
|
|
19
|
-
const bytesPerRow = Math.ceil(params.colors * params.bitsPerComponent * params.columns /
|
|
23
|
+
const bpp = Math.max(1, Math.ceil(params.colors * params.bitsPerComponent / BITS_PER_BYTE));
|
|
24
|
+
const bytesPerRow = Math.ceil(params.colors * params.bitsPerComponent * params.columns / BITS_PER_BYTE);
|
|
20
25
|
if (params.predictor === 2) return applyTiffPredictor(data, params, bytesPerRow, sink);
|
|
21
|
-
if (params.predictor >=
|
|
26
|
+
if (params.predictor >= PNG_PREDICTOR_CODE_MIN) {
|
|
22
27
|
const height = bytesPerRow > 0 ? Math.floor(data.length / (bytesPerRow + 1)) : 0;
|
|
23
28
|
return unfilterScanlines(data, height, bytesPerRow, bpp);
|
|
24
29
|
}
|
|
@@ -30,7 +35,7 @@ function applyPredictor(data, params, sink) {
|
|
|
30
35
|
return data;
|
|
31
36
|
}
|
|
32
37
|
function applyTiffPredictor(data, params, bytesPerRow, sink) {
|
|
33
|
-
if (params.bitsPerComponent !==
|
|
38
|
+
if (params.bitsPerComponent !== BITS_PER_BYTE && params.bitsPerComponent !== SIXTEEN_BIT_COMPONENT) {
|
|
34
39
|
sink({
|
|
35
40
|
code: "pdf/unsupported-predictor",
|
|
36
41
|
severity: "warning",
|
|
@@ -41,18 +46,18 @@ function applyTiffPredictor(data, params, bytesPerRow, sink) {
|
|
|
41
46
|
const out = new Uint8Array(data.length);
|
|
42
47
|
out.set(data);
|
|
43
48
|
const rowCount = bytesPerRow > 0 ? Math.floor(out.length / bytesPerRow) : 0;
|
|
44
|
-
const componentStride = params.bitsPerComponent ===
|
|
49
|
+
const componentStride = params.bitsPerComponent === SIXTEEN_BIT_COMPONENT ? 2 : 1;
|
|
45
50
|
const componentsPerPixel = params.colors;
|
|
46
51
|
for (let row = 0; row < rowCount; row++) {
|
|
47
52
|
const rowStart = row * bytesPerRow;
|
|
48
53
|
for (let component = componentsPerPixel; component * componentStride < bytesPerRow; component++) {
|
|
49
54
|
const i = rowStart + component * componentStride;
|
|
50
55
|
const prevI = i - componentsPerPixel * componentStride;
|
|
51
|
-
if (componentStride === 1) out[i] = (out[i] ?? 0) + (out[prevI] ?? 0) &
|
|
56
|
+
if (componentStride === 1) out[i] = (out[i] ?? 0) + (out[prevI] ?? 0) & BYTE_MASK;
|
|
52
57
|
else {
|
|
53
|
-
const sum = ((out[i] ?? 0) <<
|
|
54
|
-
out[i] = sum >>
|
|
55
|
-
out[i + 1] = sum &
|
|
58
|
+
const sum = ((out[i] ?? 0) << BITS_PER_BYTE | (out[i + 1] ?? 0)) + ((out[prevI] ?? 0) << BITS_PER_BYTE | (out[prevI + 1] ?? 0)) & SIXTEEN_BIT_SAMPLE_MASK;
|
|
59
|
+
out[i] = sum >> BITS_PER_BYTE & BYTE_MASK;
|
|
60
|
+
out[i + 1] = sum & BYTE_MASK;
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
63
|
}
|
package/dist/raster.cjs
CHANGED
|
@@ -17,13 +17,16 @@ const require_read = require("./read.cjs");
|
|
|
17
17
|
const require_glyf = require("./glyf.cjs");
|
|
18
18
|
const require_glyf_contours = require("./glyf-contours.cjs");
|
|
19
19
|
//#region src/raster.ts
|
|
20
|
+
const PIXEL_ROUNDING_EPSILON = 1e-9;
|
|
21
|
+
const POINTS_PER_INCH = 72;
|
|
22
|
+
const EXTENT_ZERO_EPSILON = 1e-9;
|
|
20
23
|
function regionPixels(extentPt, scale) {
|
|
21
|
-
return Math.max(1, Math.ceil(extentPt * scale -
|
|
24
|
+
return Math.max(1, Math.ceil(extentPt * scale - PIXEL_ROUNDING_EPSILON));
|
|
22
25
|
}
|
|
23
26
|
function renderPdfPage(pdfBytes, pageIndex, options, rasteriser) {
|
|
24
27
|
const sink = options.sink ?? require_diagnostics.NOOP_DIAGNOSTIC_SINK;
|
|
25
28
|
if (options.scale !== void 0 && options.dpi !== void 0) throw new Error("renderPdfPage accepts at most one of scale and dpi; they name the same factor in different units (dpi = 72 x scale)");
|
|
26
|
-
const scale = options.dpi !== void 0 ? options.dpi /
|
|
29
|
+
const scale = options.dpi !== void 0 ? options.dpi / POINTS_PER_INCH : options.scale;
|
|
27
30
|
if (scale !== void 0 && !(scale > 0)) throw new Error(`renderPdfPage requires a positive scale factor (received scale ${options.scale}, dpi ${options.dpi})`);
|
|
28
31
|
const pixelsPerPt = scale ?? 1;
|
|
29
32
|
if (options.clipPt !== void 0 && (!(options.clipPt.widthPt > 0) || !(options.clipPt.heightPt > 0))) throw new Error("renderPdfPage clipPt must carry positive widthPt and heightPt; a zero-extent region has no pixels to render");
|
|
@@ -195,6 +198,7 @@ function drawRect(item, matrix, pixelsPerPt, rasteriser) {
|
|
|
195
198
|
stroke: strokeSpec(item.stroke, void 0, pixelsPerPt)
|
|
196
199
|
});
|
|
197
200
|
}
|
|
201
|
+
const ELLIPSE_QUADRANT_COUNT = 4;
|
|
198
202
|
function drawEllipse(item, matrix, pixelsPerPt, rasteriser) {
|
|
199
203
|
const cx = item.xPt + item.widthPt / 2;
|
|
200
204
|
const cy = item.yPt + item.heightPt / 2;
|
|
@@ -224,8 +228,8 @@ function drawEllipse(item, matrix, pixelsPerPt, rasteriser) {
|
|
|
224
228
|
});
|
|
225
229
|
const start = transformed(cardinalPoints[0]);
|
|
226
230
|
const segments = [];
|
|
227
|
-
for (let i = 0; i <
|
|
228
|
-
const end = transformed(cardinalPoints[(i + 1) %
|
|
231
|
+
for (let i = 0; i < ELLIPSE_QUADRANT_COUNT; i++) {
|
|
232
|
+
const end = transformed(cardinalPoints[(i + 1) % ELLIPSE_QUADRANT_COUNT]);
|
|
229
233
|
const c1 = transformed(controls[i * 2]);
|
|
230
234
|
const c2 = transformed(controls[i * 2 + 1]);
|
|
231
235
|
segments.push({
|
|
@@ -402,12 +406,13 @@ function drawImage(image, ctm, interpretToDeviceMatrix, rasteriser) {
|
|
|
402
406
|
matrix
|
|
403
407
|
});
|
|
404
408
|
}
|
|
409
|
+
const DASHED_STROKE_WIDTH_MULTIPLE = 3;
|
|
405
410
|
function strokeSpec(stroke, style, pixelsPerPt) {
|
|
406
411
|
const widthPx = stroke.widthPt * pixelsPerPt;
|
|
407
412
|
if (style === "dashed") return {
|
|
408
413
|
color: stroke.color,
|
|
409
414
|
widthPx,
|
|
410
|
-
dashPx: [widthPx *
|
|
415
|
+
dashPx: [widthPx * DASHED_STROKE_WIDTH_MULTIPLE, widthPx * DASHED_STROKE_WIDTH_MULTIPLE]
|
|
411
416
|
};
|
|
412
417
|
return {
|
|
413
418
|
color: stroke.color,
|
|
@@ -475,6 +480,7 @@ function flattenCubic(p0, c1, c2, p1) {
|
|
|
475
480
|
flatten(p0, c1, c2, p1, 0);
|
|
476
481
|
return points;
|
|
477
482
|
}
|
|
483
|
+
const CFF_HEADER_SIZE = 4;
|
|
478
484
|
function openEmbeddedProgram(descriptorOwner, resolver) {
|
|
479
485
|
const descriptor = resolver.resolveDict(require_objects.dictGet(descriptorOwner, "FontDescriptor"));
|
|
480
486
|
if (descriptor === void 0) return { kind: "absent" };
|
|
@@ -482,7 +488,7 @@ function openEmbeddedProgram(descriptorOwner, resolver) {
|
|
|
482
488
|
const stream = resolver.resolve(require_objects.dictGet(descriptor, key));
|
|
483
489
|
if (stream?.kind !== "stream") continue;
|
|
484
490
|
const bytes = require_filters.decodeStream(stream.raw, stream.dict, require_diagnostics.NOOP_DIAGNOSTIC_SINK).bytes;
|
|
485
|
-
if (bytes[0] === 1 && bytes[1] === 0 && bytes[2] ===
|
|
491
|
+
if (bytes[0] === 1 && bytes[1] === 0 && bytes[2] === CFF_HEADER_SIZE) return { kind: "cff" };
|
|
486
492
|
const sfnt = require_sfnt.parseSfnt(bytes);
|
|
487
493
|
if (sfnt === void 0) continue;
|
|
488
494
|
if (sfnt.tables.has("CFF ")) return { kind: "cff" };
|
|
@@ -514,6 +520,7 @@ function resolveTextOutlineFace(fontResourceName, resources, resolver, fontResol
|
|
|
514
520
|
outlineFaces.set(fontDict, face);
|
|
515
521
|
return face;
|
|
516
522
|
}
|
|
523
|
+
const BITS_PER_BYTE = 8;
|
|
517
524
|
function buildTextOutlineFace(fontDict, resolver, fontResolver, fontResourceName, resources, sink) {
|
|
518
525
|
const faceName = require_objects.asName(require_objects.dictGet(fontDict, "BaseFont")) ?? require_objects.asName(require_objects.dictGet(fontDict, "Subtype")) ?? "font";
|
|
519
526
|
const unavailable = (reason) => {
|
|
@@ -548,12 +555,12 @@ function buildTextOutlineFace(fontDict, resolver, fontResolver, fontResourceName
|
|
|
548
555
|
if (cidToGidMap?.kind === "stream") {
|
|
549
556
|
const decodedBytes = require_filters.decodeStream(cidToGidMap.raw, cidToGidMap.dict, require_diagnostics.NOOP_DIAGNOSTIC_SINK).bytes;
|
|
550
557
|
const entries = [];
|
|
551
|
-
for (let i = 0; i + 1 < decodedBytes.length; i += 2) entries.push(decodedBytes[i] <<
|
|
558
|
+
for (let i = 0; i + 1 < decodedBytes.length; i += 2) entries.push(decodedBytes[i] << BITS_PER_BYTE | decodedBytes[i + 1]);
|
|
552
559
|
return {
|
|
553
560
|
glyf: program.face.glyf,
|
|
554
561
|
unitsPerEm: program.face.unitsPerEm,
|
|
555
562
|
glyphIdOf: (codes, offset) => {
|
|
556
|
-
const cid = codes[offset] <<
|
|
563
|
+
const cid = codes[offset] << BITS_PER_BYTE | codes[offset + 1];
|
|
557
564
|
return entries[cid];
|
|
558
565
|
}
|
|
559
566
|
};
|
|
@@ -561,7 +568,7 @@ function buildTextOutlineFace(fontDict, resolver, fontResolver, fontResourceName
|
|
|
561
568
|
return {
|
|
562
569
|
glyf: program.face.glyf,
|
|
563
570
|
unitsPerEm: program.face.unitsPerEm,
|
|
564
|
-
glyphIdOf: (codes, offset) => codes[offset] <<
|
|
571
|
+
glyphIdOf: (codes, offset) => codes[offset] << BITS_PER_BYTE | codes[offset + 1]
|
|
565
572
|
};
|
|
566
573
|
}
|
|
567
574
|
if (subtype === "TrueType") {
|
|
@@ -585,6 +592,7 @@ function buildTextOutlineFace(fontDict, resolver, fontResolver, fontResourceName
|
|
|
585
592
|
}
|
|
586
593
|
return unavailable(`a font of subtype ${subtype ?? "(none)"} (a Type3 glyph-procedure font has no static outline at all)`);
|
|
587
594
|
}
|
|
595
|
+
const METRICS_PER_1000_SCALE = 1e3;
|
|
588
596
|
function drawTextRun(item, fontResolver, resolver, outlineFaces, interpretToDeviceMatrix, rasteriser, sink) {
|
|
589
597
|
const face = resolveTextOutlineFace(item.fontResourceName, item.resources, resolver, fontResolver, outlineFaces, sink);
|
|
590
598
|
if (face === void 0) return;
|
|
@@ -597,10 +605,10 @@ function drawTextRun(item, fontResolver, resolver, outlineFaces, interpretToDevi
|
|
|
597
605
|
placements.push({
|
|
598
606
|
glyphId: face.glyphIdOf(item.codes, offset),
|
|
599
607
|
advance: cumulative,
|
|
600
|
-
positionX: (advance.vertical?.positionXPer1000 ?? 0) /
|
|
601
|
-
positionY: (advance.vertical?.positionYPer1000 ?? 0) /
|
|
608
|
+
positionX: (advance.vertical?.positionXPer1000 ?? 0) / METRICS_PER_1000_SCALE,
|
|
609
|
+
positionY: (advance.vertical?.positionYPer1000 ?? 0) / METRICS_PER_1000_SCALE
|
|
602
610
|
});
|
|
603
|
-
cumulative += (advance.vertical?.displacementPer1000 ?? advance.widthPer1000) /
|
|
611
|
+
cumulative += (advance.vertical?.displacementPer1000 ?? advance.widthPer1000) / METRICS_PER_1000_SCALE * item.sizePt;
|
|
604
612
|
offset += byteLength;
|
|
605
613
|
}
|
|
606
614
|
const startDeviceMatrix = require_matrix.multiplyMatrices(item.startMatrix, interpretToDeviceMatrix);
|
|
@@ -623,7 +631,7 @@ function drawTextRun(item, fontResolver, resolver, outlineFaces, interpretToDevi
|
|
|
623
631
|
});
|
|
624
632
|
const rawExtent = Math.hypot(rawEndPoint.x - startPoint.x, rawEndPoint.y - startPoint.y);
|
|
625
633
|
const actualExtent = Math.hypot(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
|
|
626
|
-
const correction = rawExtent >
|
|
634
|
+
const correction = rawExtent > EXTENT_ZERO_EPSILON ? actualExtent / rawExtent : 1;
|
|
627
635
|
const firstPlacement = placements[0];
|
|
628
636
|
const glyphScale = require_matrix.scaleMatrix(1 / face.unitsPerEm, 1 / face.unitsPerEm);
|
|
629
637
|
for (const placement of placements) {
|
|
@@ -646,10 +654,12 @@ function drawGlyphOutline(outline, glyphMatrix, color, rasteriser) {
|
|
|
646
654
|
}
|
|
647
655
|
});
|
|
648
656
|
}
|
|
657
|
+
const MIN_CONTOUR_POINTS = 3;
|
|
658
|
+
const QUADRATIC_TO_CUBIC_CONTROL_FRACTION = 2 / 3;
|
|
649
659
|
function glyphOutlineSubpaths(outline, matrix) {
|
|
650
660
|
const subpaths = [];
|
|
651
661
|
for (const contour of outline.contours) {
|
|
652
|
-
if (contour.length <
|
|
662
|
+
if (contour.length < MIN_CONTOUR_POINTS) continue;
|
|
653
663
|
const firstOn = contour.findIndex((point) => point.onCurve);
|
|
654
664
|
const contourPoints = contour.map((point) => ({
|
|
655
665
|
x: point.x,
|
|
@@ -674,10 +684,10 @@ function glyphOutlineSubpaths(outline, matrix) {
|
|
|
674
684
|
const p1 = require_matrix.applyMatrix(matrix, to);
|
|
675
685
|
segments.push({
|
|
676
686
|
kind: "cubic",
|
|
677
|
-
c1xPx: p0.x +
|
|
678
|
-
c1yPx: p0.y +
|
|
679
|
-
c2xPx: p1.x +
|
|
680
|
-
c2yPx: p1.y +
|
|
687
|
+
c1xPx: p0.x + QUADRATIC_TO_CUBIC_CONTROL_FRACTION * (q.x - p0.x),
|
|
688
|
+
c1yPx: p0.y + QUADRATIC_TO_CUBIC_CONTROL_FRACTION * (q.y - p0.y),
|
|
689
|
+
c2xPx: p1.x + QUADRATIC_TO_CUBIC_CONTROL_FRACTION * (q.x - p1.x),
|
|
690
|
+
c2yPx: p1.y + QUADRATIC_TO_CUBIC_CONTROL_FRACTION * (q.y - p1.y),
|
|
681
691
|
xPx: p1.x,
|
|
682
692
|
yPx: p1.y
|
|
683
693
|
});
|
|
@@ -765,6 +775,7 @@ function rotatedRectBounds(rect, matrix) {
|
|
|
765
775
|
maxY: Math.max(...ys)
|
|
766
776
|
};
|
|
767
777
|
}
|
|
778
|
+
const NEWLINE_BYTE = 10;
|
|
768
779
|
function readPageContentBytes(page, resolver, sink) {
|
|
769
780
|
const contentsObj = resolver.resolve(require_objects.dictGet(page, "Contents"));
|
|
770
781
|
if (contentsObj?.kind === "stream") return require_filters.decodeStream(contentsObj.raw, contentsObj.dict, sink).bytes;
|
|
@@ -772,7 +783,7 @@ function readPageContentBytes(page, resolver, sink) {
|
|
|
772
783
|
const chunks = [];
|
|
773
784
|
for (const entry of contentsObj.items) {
|
|
774
785
|
const streamObj = resolver.resolve(entry);
|
|
775
|
-
if (streamObj?.kind === "stream") chunks.push(require_filters.decodeStream(streamObj.raw, streamObj.dict, sink).bytes, new Uint8Array([
|
|
786
|
+
if (streamObj?.kind === "stream") chunks.push(require_filters.decodeStream(streamObj.raw, streamObj.dict, sink).bytes, new Uint8Array([NEWLINE_BYTE]));
|
|
776
787
|
}
|
|
777
788
|
return require_bytes_writer.concatBytes(chunks);
|
|
778
789
|
}
|
package/dist/raster.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.cjs";
|
|
2
2
|
import { r as Matrix } from "./matrix-B7_SBKQ5.cjs";
|
|
3
|
-
import { n as GlyphOutline } from "./glyf-contours-
|
|
3
|
+
import { n as GlyphOutline } from "./glyf-contours-NHBpgks-.cjs";
|
|
4
4
|
import { Color } from "document-schema.js";
|
|
5
5
|
//#region src/raster.d.ts
|
|
6
6
|
type RasterMatrix = readonly [number, number, number, number, number, number];
|
|
@@ -80,24 +80,24 @@ interface RenderPdfPageOptions {
|
|
|
80
80
|
readonly sink?: PdfDiagnosticSink;
|
|
81
81
|
readonly signal?: AbortSignal;
|
|
82
82
|
}
|
|
83
|
-
declare function renderPdfPage(pdfBytes: Uint8Array<ArrayBuffer>, pageIndex: number, options: RenderPdfPageOptions, rasteriser: PageRasteriser): Uint8Array<ArrayBuffer> | Promise<Uint8Array<ArrayBuffer>>;
|
|
84
|
-
declare function flattenCubic(p0: {
|
|
83
|
+
declare function renderPdfPage(pdfBytes: Uint8Array<ArrayBuffer>, pageIndex: number, options: RenderPdfPageOptions, rasteriser: Readonly<PageRasteriser>): Uint8Array<ArrayBuffer> | Promise<Uint8Array<ArrayBuffer>>;
|
|
84
|
+
declare function flattenCubic(p0: Readonly<{
|
|
85
85
|
x: number;
|
|
86
86
|
y: number;
|
|
87
|
-
}
|
|
87
|
+
}>, c1: Readonly<{
|
|
88
88
|
x: number;
|
|
89
89
|
y: number;
|
|
90
|
-
}
|
|
90
|
+
}>, c2: Readonly<{
|
|
91
91
|
x: number;
|
|
92
92
|
y: number;
|
|
93
|
-
}
|
|
93
|
+
}>, p1: Readonly<{
|
|
94
94
|
x: number;
|
|
95
95
|
y: number;
|
|
96
|
-
}): readonly {
|
|
96
|
+
}>): readonly {
|
|
97
97
|
x: number;
|
|
98
98
|
y: number;
|
|
99
99
|
}[];
|
|
100
|
-
declare function drawGlyphOutline(outline: GlyphOutline, glyphMatrix: Matrix, color: Color
|
|
100
|
+
declare function drawGlyphOutline(outline: GlyphOutline, glyphMatrix: Matrix, color: Readonly<Color>, rasteriser: Readonly<PageRasteriser>): void;
|
|
101
101
|
declare function glyphOutlineSubpaths(outline: GlyphOutline, matrix: Matrix): readonly RasterSubpath[];
|
|
102
102
|
//#endregion
|
|
103
103
|
export { PageRasteriser, RasterDrawOp, RasterFillRectOp, RasterFillSpec, RasterImageOp, RasterMatrix, RasterPageGeometry, RasterPathOp, RasterPathSegment, RasterRegionPt, RasterStrokeSpec, RasterSubpath, RenderPdfPageOptions, drawGlyphOutline, flattenCubic, glyphOutlineSubpaths, renderPdfPage };
|
package/dist/raster.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.js";
|
|
2
2
|
import { r as Matrix } from "./matrix-B7_SBKQ5.js";
|
|
3
|
-
import { n as GlyphOutline } from "./glyf-contours-
|
|
3
|
+
import { n as GlyphOutline } from "./glyf-contours-B1PsI9oA.js";
|
|
4
4
|
import { Color } from "document-schema.js";
|
|
5
5
|
//#region src/raster.d.ts
|
|
6
6
|
type RasterMatrix = readonly [number, number, number, number, number, number];
|
|
@@ -80,24 +80,24 @@ interface RenderPdfPageOptions {
|
|
|
80
80
|
readonly sink?: PdfDiagnosticSink;
|
|
81
81
|
readonly signal?: AbortSignal;
|
|
82
82
|
}
|
|
83
|
-
declare function renderPdfPage(pdfBytes: Uint8Array<ArrayBuffer>, pageIndex: number, options: RenderPdfPageOptions, rasteriser: PageRasteriser): Uint8Array<ArrayBuffer> | Promise<Uint8Array<ArrayBuffer>>;
|
|
84
|
-
declare function flattenCubic(p0: {
|
|
83
|
+
declare function renderPdfPage(pdfBytes: Uint8Array<ArrayBuffer>, pageIndex: number, options: RenderPdfPageOptions, rasteriser: Readonly<PageRasteriser>): Uint8Array<ArrayBuffer> | Promise<Uint8Array<ArrayBuffer>>;
|
|
84
|
+
declare function flattenCubic(p0: Readonly<{
|
|
85
85
|
x: number;
|
|
86
86
|
y: number;
|
|
87
|
-
}
|
|
87
|
+
}>, c1: Readonly<{
|
|
88
88
|
x: number;
|
|
89
89
|
y: number;
|
|
90
|
-
}
|
|
90
|
+
}>, c2: Readonly<{
|
|
91
91
|
x: number;
|
|
92
92
|
y: number;
|
|
93
|
-
}
|
|
93
|
+
}>, p1: Readonly<{
|
|
94
94
|
x: number;
|
|
95
95
|
y: number;
|
|
96
|
-
}): readonly {
|
|
96
|
+
}>): readonly {
|
|
97
97
|
x: number;
|
|
98
98
|
y: number;
|
|
99
99
|
}[];
|
|
100
|
-
declare function drawGlyphOutline(outline: GlyphOutline, glyphMatrix: Matrix, color: Color
|
|
100
|
+
declare function drawGlyphOutline(outline: GlyphOutline, glyphMatrix: Matrix, color: Readonly<Color>, rasteriser: Readonly<PageRasteriser>): void;
|
|
101
101
|
declare function glyphOutlineSubpaths(outline: GlyphOutline, matrix: Matrix): readonly RasterSubpath[];
|
|
102
102
|
//#endregion
|
|
103
103
|
export { PageRasteriser, RasterDrawOp, RasterFillRectOp, RasterFillSpec, RasterImageOp, RasterMatrix, RasterPageGeometry, RasterPathOp, RasterPathSegment, RasterRegionPt, RasterStrokeSpec, RasterSubpath, RenderPdfPageOptions, drawGlyphOutline, flattenCubic, glyphOutlineSubpaths, renderPdfPage };
|
package/dist/raster.js
CHANGED
|
@@ -16,13 +16,16 @@ import { normalizeRotation, pageRotationTransform } from "./read.js";
|
|
|
16
16
|
import { parseGlyf } from "./glyf.js";
|
|
17
17
|
import { decodeGlyphOutline } from "./glyf-contours.js";
|
|
18
18
|
//#region src/raster.ts
|
|
19
|
+
const PIXEL_ROUNDING_EPSILON = 1e-9;
|
|
20
|
+
const POINTS_PER_INCH = 72;
|
|
21
|
+
const EXTENT_ZERO_EPSILON = 1e-9;
|
|
19
22
|
function regionPixels(extentPt, scale) {
|
|
20
|
-
return Math.max(1, Math.ceil(extentPt * scale -
|
|
23
|
+
return Math.max(1, Math.ceil(extentPt * scale - PIXEL_ROUNDING_EPSILON));
|
|
21
24
|
}
|
|
22
25
|
function renderPdfPage(pdfBytes, pageIndex, options, rasteriser) {
|
|
23
26
|
const sink = options.sink ?? NOOP_DIAGNOSTIC_SINK;
|
|
24
27
|
if (options.scale !== void 0 && options.dpi !== void 0) throw new Error("renderPdfPage accepts at most one of scale and dpi; they name the same factor in different units (dpi = 72 x scale)");
|
|
25
|
-
const scale = options.dpi !== void 0 ? options.dpi /
|
|
28
|
+
const scale = options.dpi !== void 0 ? options.dpi / POINTS_PER_INCH : options.scale;
|
|
26
29
|
if (scale !== void 0 && !(scale > 0)) throw new Error(`renderPdfPage requires a positive scale factor (received scale ${options.scale}, dpi ${options.dpi})`);
|
|
27
30
|
const pixelsPerPt = scale ?? 1;
|
|
28
31
|
if (options.clipPt !== void 0 && (!(options.clipPt.widthPt > 0) || !(options.clipPt.heightPt > 0))) throw new Error("renderPdfPage clipPt must carry positive widthPt and heightPt; a zero-extent region has no pixels to render");
|
|
@@ -194,6 +197,7 @@ function drawRect(item, matrix, pixelsPerPt, rasteriser) {
|
|
|
194
197
|
stroke: strokeSpec(item.stroke, void 0, pixelsPerPt)
|
|
195
198
|
});
|
|
196
199
|
}
|
|
200
|
+
const ELLIPSE_QUADRANT_COUNT = 4;
|
|
197
201
|
function drawEllipse(item, matrix, pixelsPerPt, rasteriser) {
|
|
198
202
|
const cx = item.xPt + item.widthPt / 2;
|
|
199
203
|
const cy = item.yPt + item.heightPt / 2;
|
|
@@ -223,8 +227,8 @@ function drawEllipse(item, matrix, pixelsPerPt, rasteriser) {
|
|
|
223
227
|
});
|
|
224
228
|
const start = transformed(cardinalPoints[0]);
|
|
225
229
|
const segments = [];
|
|
226
|
-
for (let i = 0; i <
|
|
227
|
-
const end = transformed(cardinalPoints[(i + 1) %
|
|
230
|
+
for (let i = 0; i < ELLIPSE_QUADRANT_COUNT; i++) {
|
|
231
|
+
const end = transformed(cardinalPoints[(i + 1) % ELLIPSE_QUADRANT_COUNT]);
|
|
228
232
|
const c1 = transformed(controls[i * 2]);
|
|
229
233
|
const c2 = transformed(controls[i * 2 + 1]);
|
|
230
234
|
segments.push({
|
|
@@ -401,12 +405,13 @@ function drawImage(image, ctm, interpretToDeviceMatrix, rasteriser) {
|
|
|
401
405
|
matrix
|
|
402
406
|
});
|
|
403
407
|
}
|
|
408
|
+
const DASHED_STROKE_WIDTH_MULTIPLE = 3;
|
|
404
409
|
function strokeSpec(stroke, style, pixelsPerPt) {
|
|
405
410
|
const widthPx = stroke.widthPt * pixelsPerPt;
|
|
406
411
|
if (style === "dashed") return {
|
|
407
412
|
color: stroke.color,
|
|
408
413
|
widthPx,
|
|
409
|
-
dashPx: [widthPx *
|
|
414
|
+
dashPx: [widthPx * DASHED_STROKE_WIDTH_MULTIPLE, widthPx * DASHED_STROKE_WIDTH_MULTIPLE]
|
|
410
415
|
};
|
|
411
416
|
return {
|
|
412
417
|
color: stroke.color,
|
|
@@ -474,6 +479,7 @@ function flattenCubic(p0, c1, c2, p1) {
|
|
|
474
479
|
flatten(p0, c1, c2, p1, 0);
|
|
475
480
|
return points;
|
|
476
481
|
}
|
|
482
|
+
const CFF_HEADER_SIZE = 4;
|
|
477
483
|
function openEmbeddedProgram(descriptorOwner, resolver) {
|
|
478
484
|
const descriptor = resolver.resolveDict(dictGet(descriptorOwner, "FontDescriptor"));
|
|
479
485
|
if (descriptor === void 0) return { kind: "absent" };
|
|
@@ -481,7 +487,7 @@ function openEmbeddedProgram(descriptorOwner, resolver) {
|
|
|
481
487
|
const stream = resolver.resolve(dictGet(descriptor, key));
|
|
482
488
|
if (stream?.kind !== "stream") continue;
|
|
483
489
|
const bytes = decodeStream(stream.raw, stream.dict, NOOP_DIAGNOSTIC_SINK).bytes;
|
|
484
|
-
if (bytes[0] === 1 && bytes[1] === 0 && bytes[2] ===
|
|
490
|
+
if (bytes[0] === 1 && bytes[1] === 0 && bytes[2] === CFF_HEADER_SIZE) return { kind: "cff" };
|
|
485
491
|
const sfnt = parseSfnt(bytes);
|
|
486
492
|
if (sfnt === void 0) continue;
|
|
487
493
|
if (sfnt.tables.has("CFF ")) return { kind: "cff" };
|
|
@@ -513,6 +519,7 @@ function resolveTextOutlineFace(fontResourceName, resources, resolver, fontResol
|
|
|
513
519
|
outlineFaces.set(fontDict, face);
|
|
514
520
|
return face;
|
|
515
521
|
}
|
|
522
|
+
const BITS_PER_BYTE = 8;
|
|
516
523
|
function buildTextOutlineFace(fontDict, resolver, fontResolver, fontResourceName, resources, sink) {
|
|
517
524
|
const faceName = asName(dictGet(fontDict, "BaseFont")) ?? asName(dictGet(fontDict, "Subtype")) ?? "font";
|
|
518
525
|
const unavailable = (reason) => {
|
|
@@ -547,12 +554,12 @@ function buildTextOutlineFace(fontDict, resolver, fontResolver, fontResourceName
|
|
|
547
554
|
if (cidToGidMap?.kind === "stream") {
|
|
548
555
|
const decodedBytes = decodeStream(cidToGidMap.raw, cidToGidMap.dict, NOOP_DIAGNOSTIC_SINK).bytes;
|
|
549
556
|
const entries = [];
|
|
550
|
-
for (let i = 0; i + 1 < decodedBytes.length; i += 2) entries.push(decodedBytes[i] <<
|
|
557
|
+
for (let i = 0; i + 1 < decodedBytes.length; i += 2) entries.push(decodedBytes[i] << BITS_PER_BYTE | decodedBytes[i + 1]);
|
|
551
558
|
return {
|
|
552
559
|
glyf: program.face.glyf,
|
|
553
560
|
unitsPerEm: program.face.unitsPerEm,
|
|
554
561
|
glyphIdOf: (codes, offset) => {
|
|
555
|
-
const cid = codes[offset] <<
|
|
562
|
+
const cid = codes[offset] << BITS_PER_BYTE | codes[offset + 1];
|
|
556
563
|
return entries[cid];
|
|
557
564
|
}
|
|
558
565
|
};
|
|
@@ -560,7 +567,7 @@ function buildTextOutlineFace(fontDict, resolver, fontResolver, fontResourceName
|
|
|
560
567
|
return {
|
|
561
568
|
glyf: program.face.glyf,
|
|
562
569
|
unitsPerEm: program.face.unitsPerEm,
|
|
563
|
-
glyphIdOf: (codes, offset) => codes[offset] <<
|
|
570
|
+
glyphIdOf: (codes, offset) => codes[offset] << BITS_PER_BYTE | codes[offset + 1]
|
|
564
571
|
};
|
|
565
572
|
}
|
|
566
573
|
if (subtype === "TrueType") {
|
|
@@ -584,6 +591,7 @@ function buildTextOutlineFace(fontDict, resolver, fontResolver, fontResourceName
|
|
|
584
591
|
}
|
|
585
592
|
return unavailable(`a font of subtype ${subtype ?? "(none)"} (a Type3 glyph-procedure font has no static outline at all)`);
|
|
586
593
|
}
|
|
594
|
+
const METRICS_PER_1000_SCALE = 1e3;
|
|
587
595
|
function drawTextRun(item, fontResolver, resolver, outlineFaces, interpretToDeviceMatrix, rasteriser, sink) {
|
|
588
596
|
const face = resolveTextOutlineFace(item.fontResourceName, item.resources, resolver, fontResolver, outlineFaces, sink);
|
|
589
597
|
if (face === void 0) return;
|
|
@@ -596,10 +604,10 @@ function drawTextRun(item, fontResolver, resolver, outlineFaces, interpretToDevi
|
|
|
596
604
|
placements.push({
|
|
597
605
|
glyphId: face.glyphIdOf(item.codes, offset),
|
|
598
606
|
advance: cumulative,
|
|
599
|
-
positionX: (advance.vertical?.positionXPer1000 ?? 0) /
|
|
600
|
-
positionY: (advance.vertical?.positionYPer1000 ?? 0) /
|
|
607
|
+
positionX: (advance.vertical?.positionXPer1000 ?? 0) / METRICS_PER_1000_SCALE,
|
|
608
|
+
positionY: (advance.vertical?.positionYPer1000 ?? 0) / METRICS_PER_1000_SCALE
|
|
601
609
|
});
|
|
602
|
-
cumulative += (advance.vertical?.displacementPer1000 ?? advance.widthPer1000) /
|
|
610
|
+
cumulative += (advance.vertical?.displacementPer1000 ?? advance.widthPer1000) / METRICS_PER_1000_SCALE * item.sizePt;
|
|
603
611
|
offset += byteLength;
|
|
604
612
|
}
|
|
605
613
|
const startDeviceMatrix = multiplyMatrices(item.startMatrix, interpretToDeviceMatrix);
|
|
@@ -622,7 +630,7 @@ function drawTextRun(item, fontResolver, resolver, outlineFaces, interpretToDevi
|
|
|
622
630
|
});
|
|
623
631
|
const rawExtent = Math.hypot(rawEndPoint.x - startPoint.x, rawEndPoint.y - startPoint.y);
|
|
624
632
|
const actualExtent = Math.hypot(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
|
|
625
|
-
const correction = rawExtent >
|
|
633
|
+
const correction = rawExtent > EXTENT_ZERO_EPSILON ? actualExtent / rawExtent : 1;
|
|
626
634
|
const firstPlacement = placements[0];
|
|
627
635
|
const glyphScale = scaleMatrix(1 / face.unitsPerEm, 1 / face.unitsPerEm);
|
|
628
636
|
for (const placement of placements) {
|
|
@@ -645,10 +653,12 @@ function drawGlyphOutline(outline, glyphMatrix, color, rasteriser) {
|
|
|
645
653
|
}
|
|
646
654
|
});
|
|
647
655
|
}
|
|
656
|
+
const MIN_CONTOUR_POINTS = 3;
|
|
657
|
+
const QUADRATIC_TO_CUBIC_CONTROL_FRACTION = 2 / 3;
|
|
648
658
|
function glyphOutlineSubpaths(outline, matrix) {
|
|
649
659
|
const subpaths = [];
|
|
650
660
|
for (const contour of outline.contours) {
|
|
651
|
-
if (contour.length <
|
|
661
|
+
if (contour.length < MIN_CONTOUR_POINTS) continue;
|
|
652
662
|
const firstOn = contour.findIndex((point) => point.onCurve);
|
|
653
663
|
const contourPoints = contour.map((point) => ({
|
|
654
664
|
x: point.x,
|
|
@@ -673,10 +683,10 @@ function glyphOutlineSubpaths(outline, matrix) {
|
|
|
673
683
|
const p1 = applyMatrix(matrix, to);
|
|
674
684
|
segments.push({
|
|
675
685
|
kind: "cubic",
|
|
676
|
-
c1xPx: p0.x +
|
|
677
|
-
c1yPx: p0.y +
|
|
678
|
-
c2xPx: p1.x +
|
|
679
|
-
c2yPx: p1.y +
|
|
686
|
+
c1xPx: p0.x + QUADRATIC_TO_CUBIC_CONTROL_FRACTION * (q.x - p0.x),
|
|
687
|
+
c1yPx: p0.y + QUADRATIC_TO_CUBIC_CONTROL_FRACTION * (q.y - p0.y),
|
|
688
|
+
c2xPx: p1.x + QUADRATIC_TO_CUBIC_CONTROL_FRACTION * (q.x - p1.x),
|
|
689
|
+
c2yPx: p1.y + QUADRATIC_TO_CUBIC_CONTROL_FRACTION * (q.y - p1.y),
|
|
680
690
|
xPx: p1.x,
|
|
681
691
|
yPx: p1.y
|
|
682
692
|
});
|
|
@@ -764,6 +774,7 @@ function rotatedRectBounds(rect, matrix) {
|
|
|
764
774
|
maxY: Math.max(...ys)
|
|
765
775
|
};
|
|
766
776
|
}
|
|
777
|
+
const NEWLINE_BYTE = 10;
|
|
767
778
|
function readPageContentBytes(page, resolver, sink) {
|
|
768
779
|
const contentsObj = resolver.resolve(dictGet(page, "Contents"));
|
|
769
780
|
if (contentsObj?.kind === "stream") return decodeStream(contentsObj.raw, contentsObj.dict, sink).bytes;
|
|
@@ -771,7 +782,7 @@ function readPageContentBytes(page, resolver, sink) {
|
|
|
771
782
|
const chunks = [];
|
|
772
783
|
for (const entry of contentsObj.items) {
|
|
773
784
|
const streamObj = resolver.resolve(entry);
|
|
774
|
-
if (streamObj?.kind === "stream") chunks.push(decodeStream(streamObj.raw, streamObj.dict, sink).bytes, new Uint8Array([
|
|
785
|
+
if (streamObj?.kind === "stream") chunks.push(decodeStream(streamObj.raw, streamObj.dict, sink).bytes, new Uint8Array([NEWLINE_BYTE]));
|
|
775
786
|
}
|
|
776
787
|
return concatBytes(chunks);
|
|
777
788
|
}
|