pdf-lite 1.5.0 → 1.6.1
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/EXAMPLES.md +51 -70
- package/README.md +1 -1
- package/dist/acroform/appearance/pdf-button-appearance-stream.d.ts +1 -1
- package/dist/acroform/appearance/pdf-button-appearance-stream.js +6 -2
- package/dist/acroform/fields/pdf-button-form-field.d.ts +0 -9
- package/dist/acroform/fields/pdf-button-form-field.js +7 -39
- package/dist/acroform/fields/pdf-choice-form-field.d.ts +2 -1
- package/dist/acroform/fields/pdf-choice-form-field.js +19 -38
- package/dist/acroform/fields/pdf-default-appearance.js +1 -1
- package/dist/acroform/fields/pdf-form-field.d.ts +27 -32
- package/dist/acroform/fields/pdf-form-field.js +180 -94
- package/dist/acroform/fields/pdf-text-form-field.js +6 -33
- package/dist/acroform/fields/types.d.ts +1 -1
- package/dist/acroform/index.d.ts +0 -2
- package/dist/acroform/index.js +0 -2
- package/dist/acroform/pdf-acro-form.d.ts +12 -36
- package/dist/acroform/pdf-acro-form.js +111 -201
- package/dist/acroform/xfa/pdf-xfa-data.d.ts +4 -3
- package/dist/acroform/xfa/pdf-xfa-data.js +16 -12
- package/dist/acroform/xfa/pdf-xfa-form.d.ts +9 -4
- package/dist/acroform/xfa/pdf-xfa-form.js +17 -39
- package/dist/annotations/index.d.ts +0 -1
- package/dist/annotations/index.js +0 -1
- package/dist/annotations/pdf-annotation.d.ts +7 -2
- package/dist/annotations/pdf-annotation.js +30 -19
- package/dist/annotations/pdf-default-resources.d.ts +11 -0
- package/dist/annotations/pdf-default-resources.js +3 -0
- package/dist/core/decoder.js +1 -1
- package/dist/core/objects/pdf-array.d.ts +8 -1
- package/dist/core/objects/pdf-array.js +31 -0
- package/dist/core/objects/pdf-dictionary.d.ts +2 -0
- package/dist/core/objects/pdf-dictionary.js +14 -7
- package/dist/core/objects/pdf-hexadecimal.d.ts +1 -0
- package/dist/core/objects/pdf-hexadecimal.js +3 -3
- package/dist/core/objects/pdf-indirect-object.d.ts +18 -9
- package/dist/core/objects/pdf-indirect-object.js +75 -16
- package/dist/core/objects/pdf-number.d.ts +1 -0
- package/dist/core/objects/pdf-number.js +5 -4
- package/dist/core/objects/pdf-object-reference.d.ts +8 -1
- package/dist/core/objects/pdf-object-reference.js +14 -0
- package/dist/core/objects/pdf-object.d.ts +14 -0
- package/dist/core/objects/pdf-object.js +36 -0
- package/dist/core/objects/pdf-start-xref.d.ts +1 -0
- package/dist/core/objects/pdf-start-xref.js +4 -0
- package/dist/core/objects/pdf-stream.d.ts +47 -7
- package/dist/core/objects/pdf-stream.js +301 -32
- package/dist/core/objects/pdf-string.d.ts +1 -0
- package/dist/core/objects/pdf-string.js +3 -6
- package/dist/core/objects/pdf-trailer.d.ts +1 -0
- package/dist/core/objects/pdf-trailer.js +6 -3
- package/dist/core/objects/pdf-xref-table.js +1 -1
- package/dist/core/ref.d.ts +3 -1
- package/dist/core/ref.js +8 -5
- package/dist/core/tokens/token.d.ts +2 -1
- package/dist/core/tokens/token.js +3 -0
- package/dist/fonts/index.d.ts +0 -1
- package/dist/fonts/index.js +0 -1
- package/dist/fonts/pdf-font.d.ts +32 -27
- package/dist/fonts/pdf-font.js +115 -77
- package/dist/pdf/index.d.ts +2 -0
- package/dist/pdf/index.js +2 -0
- package/dist/pdf/pdf-document.d.ts +63 -37
- package/dist/pdf/pdf-document.js +351 -135
- package/dist/pdf/pdf-page.d.ts +50 -0
- package/dist/pdf/pdf-page.js +144 -0
- package/dist/pdf/pdf-pages.d.ts +28 -0
- package/dist/pdf/pdf-pages.js +94 -0
- package/dist/pdf/pdf-reader.d.ts +5 -1
- package/dist/pdf/pdf-reader.js +36 -2
- package/dist/pdf/pdf-revision.d.ts +3 -3
- package/dist/pdf/pdf-revision.js +7 -7
- package/dist/pdf/pdf-xref-lookup.js +34 -14
- package/dist/signing/document-security-store.d.ts +14 -17
- package/dist/signing/document-security-store.js +19 -34
- package/dist/signing/signer.d.ts +23 -8
- package/dist/signing/signer.js +51 -17
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
- package/dist/utils/needsCentralWhitespace.d.ts +10 -0
- package/dist/utils/needsCentralWhitespace.js +34 -0
- package/package.json +3 -3
- package/dist/acroform/acroform.d.ts +0 -9
- package/dist/acroform/acroform.js +0 -7
- package/dist/acroform/manager.d.ts +0 -37
- package/dist/acroform/manager.js +0 -57
- package/dist/acroform/pdf-font-encoding-cache.d.ts +0 -27
- package/dist/acroform/pdf-font-encoding-cache.js +0 -188
- package/dist/annotations/pdf-annotation-writer.d.ts +0 -20
- package/dist/annotations/pdf-annotation-writer.js +0 -76
- package/dist/fonts/manager.d.ts +0 -127
- package/dist/fonts/manager.js +0 -378
- package/dist/utils/predictors.d.ts +0 -113
- package/dist/utils/predictors.js +0 -279
|
@@ -9,10 +9,20 @@ export class PdfObject {
|
|
|
9
9
|
modified = true;
|
|
10
10
|
/** Indicates whether the object is immutable (cannot be modified) */
|
|
11
11
|
immutable = false;
|
|
12
|
+
/** Cached byte representation of the object, if available */
|
|
13
|
+
cachedTokens;
|
|
12
14
|
/** The type of this PDF object */
|
|
13
15
|
get objectType() {
|
|
14
16
|
return this.constructor.name;
|
|
15
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Returns true if this object's serialized form ends with a self-delimiting
|
|
20
|
+
* character (e.g., `)`, `>`, `]`, `>>`). Such objects do not require trailing
|
|
21
|
+
* whitespace before the next token.
|
|
22
|
+
*/
|
|
23
|
+
get isTrailingDelimited() {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
16
26
|
/** Indicates whether the object has been modified. Override this method if the modified state is determined differently */
|
|
17
27
|
isModified() {
|
|
18
28
|
return this.modified;
|
|
@@ -27,10 +37,22 @@ export class PdfObject {
|
|
|
27
37
|
}
|
|
28
38
|
/** Sets the immutable state of the object */
|
|
29
39
|
setImmutable(immutable = true) {
|
|
40
|
+
if (immutable === this.immutable) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
30
43
|
this.immutable = immutable;
|
|
44
|
+
if (immutable) {
|
|
45
|
+
this.cachedTokens = this.toTokens();
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
this.cachedTokens = undefined;
|
|
49
|
+
}
|
|
31
50
|
}
|
|
32
51
|
/** Converts the object to an array of PdfTokens, including any pre or post tokens */
|
|
33
52
|
toTokens() {
|
|
53
|
+
if (this.cachedTokens) {
|
|
54
|
+
return this.cachedTokens;
|
|
55
|
+
}
|
|
34
56
|
return [
|
|
35
57
|
...(this.preTokens ?? []),
|
|
36
58
|
...this.tokenize(),
|
|
@@ -90,4 +112,18 @@ export class PdfObject {
|
|
|
90
112
|
}
|
|
91
113
|
return true;
|
|
92
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Serializes the document to a Base64-encoded string.
|
|
117
|
+
*
|
|
118
|
+
* @returns A promise that resolves to the PDF document as a Base64 string
|
|
119
|
+
*/
|
|
120
|
+
toBase64() {
|
|
121
|
+
const bytes = this.toBytes();
|
|
122
|
+
let binary = '';
|
|
123
|
+
const len = bytes.byteLength;
|
|
124
|
+
for (let i = 0; i < len; i++) {
|
|
125
|
+
binary += String.fromCharCode(bytes[i]);
|
|
126
|
+
}
|
|
127
|
+
return btoa(binary);
|
|
128
|
+
}
|
|
93
129
|
}
|
|
@@ -27,6 +27,10 @@ export class PdfStartXRef extends PdfObject {
|
|
|
27
27
|
const cloned = new PdfStartXRef(this.offset.clone());
|
|
28
28
|
return cloned;
|
|
29
29
|
}
|
|
30
|
+
setModified(modified) {
|
|
31
|
+
super.setModified(modified);
|
|
32
|
+
this.offset.setModified(modified);
|
|
33
|
+
}
|
|
30
34
|
isModified() {
|
|
31
35
|
return super.isModified() || this.offset.isModified();
|
|
32
36
|
}
|
|
@@ -1,12 +1,48 @@
|
|
|
1
1
|
import { PdfToken } from '../tokens/token.js';
|
|
2
2
|
import { PdfDictionary } from './pdf-dictionary.js';
|
|
3
3
|
import { PdfObject } from './pdf-object.js';
|
|
4
|
-
import { ByteArray } from '../../types.js';
|
|
4
|
+
import { ByteArray, DecodeParms } from '../../types.js';
|
|
5
5
|
import { PdfNumber } from './pdf-number.js';
|
|
6
6
|
import { PdfIndirectObject } from './pdf-indirect-object.js';
|
|
7
7
|
import { PdfXRefTableEntry } from './pdf-xref-table.js';
|
|
8
8
|
import { PdfFilter, PdfStreamFilterType } from '../../filters/types.js';
|
|
9
|
+
export declare class PdfStreamPredictor extends PdfDictionary<{
|
|
10
|
+
Predictor?: PdfNumber;
|
|
11
|
+
Columns?: PdfNumber;
|
|
12
|
+
Colors?: PdfNumber;
|
|
13
|
+
BitsPerComponent?: PdfNumber;
|
|
14
|
+
}> {
|
|
15
|
+
static NONE: PdfStreamPredictor;
|
|
16
|
+
static TIFF: PdfStreamPredictor;
|
|
17
|
+
static PNG_NONE: PdfStreamPredictor;
|
|
18
|
+
static PNG_SUB: PdfStreamPredictor;
|
|
19
|
+
static PNG_UP: PdfStreamPredictor;
|
|
20
|
+
static PNG_AVERAGE: PdfStreamPredictor;
|
|
21
|
+
static PNG_PAETH: PdfStreamPredictor;
|
|
22
|
+
static PNG_OPTIMUM: PdfStreamPredictor;
|
|
23
|
+
static XREF_STREAM: PdfStreamPredictor;
|
|
24
|
+
get predictor(): number;
|
|
25
|
+
set predictor(value: number);
|
|
26
|
+
get columns(): number;
|
|
27
|
+
set columns(value: number);
|
|
28
|
+
get colors(): number;
|
|
29
|
+
set colors(value: number);
|
|
30
|
+
get bitsPerComponent(): number;
|
|
31
|
+
set bitsPerComponent(value: number);
|
|
32
|
+
toDecodeParms(): DecodeParms;
|
|
33
|
+
cloneImpl(): this;
|
|
34
|
+
static fromDecodeParms(params: DecodeParms): PdfStreamPredictor;
|
|
35
|
+
static fromDictionary(dict?: PdfDictionary): PdfStreamPredictor | undefined;
|
|
36
|
+
encode(data: ByteArray, filterType?: number): ByteArray;
|
|
37
|
+
decode(data: ByteArray): ByteArray;
|
|
38
|
+
private static tiffDecode;
|
|
39
|
+
private static tiffEncode;
|
|
40
|
+
private static pngDecode;
|
|
41
|
+
private static pngEncode;
|
|
42
|
+
private static paethPredictor;
|
|
43
|
+
}
|
|
9
44
|
export declare class PdfStream<T extends PdfDictionary = PdfDictionary> extends PdfObject {
|
|
45
|
+
static PdfStreamPredictor: typeof PdfStreamPredictor;
|
|
10
46
|
header: T;
|
|
11
47
|
original: ByteArray;
|
|
12
48
|
preStreamDataTokens?: PdfToken[];
|
|
@@ -21,14 +57,14 @@ export declare class PdfStream<T extends PdfDictionary = PdfDictionary> extends
|
|
|
21
57
|
get originalAsString(): string;
|
|
22
58
|
get rawAsString(): string;
|
|
23
59
|
set rawAsString(str: string);
|
|
60
|
+
get data(): ByteArray;
|
|
61
|
+
set data(data: ByteArray);
|
|
62
|
+
get dataAsString(): string;
|
|
63
|
+
set dataAsString(str: string);
|
|
24
64
|
getFilters(): PdfStreamFilterType[];
|
|
25
65
|
addFilter(filterName: PdfStreamFilterType): this;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Columns?: number;
|
|
29
|
-
Colors?: number;
|
|
30
|
-
BitsPerComponent?: number;
|
|
31
|
-
}): this;
|
|
66
|
+
get predictor(): PdfStreamPredictor | undefined;
|
|
67
|
+
set predictor(predictor: PdfStreamPredictor);
|
|
32
68
|
removeFilter(filterName: PdfStreamFilterType): this;
|
|
33
69
|
removePredictor(): this;
|
|
34
70
|
removeAllFilters(): this;
|
|
@@ -58,6 +94,9 @@ export declare class PdfStream<T extends PdfDictionary = PdfDictionary> extends
|
|
|
58
94
|
static fromString(data: string): PdfStream;
|
|
59
95
|
}
|
|
60
96
|
export declare class PdfObjStream extends PdfStream {
|
|
97
|
+
private _parsedObjects?;
|
|
98
|
+
set raw(data: ByteArray);
|
|
99
|
+
get raw(): ByteArray;
|
|
61
100
|
constructor(options: {
|
|
62
101
|
header: PdfDictionary;
|
|
63
102
|
original: ByteArray | string;
|
|
@@ -65,6 +104,7 @@ export declare class PdfObjStream extends PdfStream {
|
|
|
65
104
|
});
|
|
66
105
|
static fromObjects(objects: Iterable<PdfIndirectObject>): PdfObjStream;
|
|
67
106
|
getObjectStream(): Generator<PdfIndirectObject>;
|
|
107
|
+
private getParsedObjects;
|
|
68
108
|
getObject(options: {
|
|
69
109
|
objectNumber: number;
|
|
70
110
|
}): PdfIndirectObject | undefined;
|
|
@@ -12,13 +12,244 @@ import { lzw } from '../../filters/lzw.js';
|
|
|
12
12
|
import { runLength } from '../../filters/runlength.js';
|
|
13
13
|
import { passthroughFilter } from '../../filters/pass-through.js';
|
|
14
14
|
import { PdfNumber } from './pdf-number.js';
|
|
15
|
-
import { Predictor } from '../../utils/predictors.js';
|
|
16
15
|
import { bytesToPdfObjects } from '../generators.js';
|
|
17
16
|
import { PdfIndirectObject } from './pdf-indirect-object.js';
|
|
18
17
|
import { PdfXRefTableEntry } from './pdf-xref-table.js';
|
|
19
18
|
import { stringToBytes } from '../../utils/stringToBytes.js';
|
|
20
19
|
import { bytesToString } from '../../utils/bytesToString.js';
|
|
20
|
+
export class PdfStreamPredictor extends PdfDictionary {
|
|
21
|
+
static NONE = new PdfStreamPredictor({ Predictor: new PdfNumber(1) });
|
|
22
|
+
static TIFF = new PdfStreamPredictor({ Predictor: new PdfNumber(2) });
|
|
23
|
+
static PNG_NONE = new PdfStreamPredictor({ Predictor: new PdfNumber(10) });
|
|
24
|
+
static PNG_SUB = new PdfStreamPredictor({ Predictor: new PdfNumber(11) });
|
|
25
|
+
static PNG_UP = new PdfStreamPredictor({ Predictor: new PdfNumber(12) });
|
|
26
|
+
static PNG_AVERAGE = new PdfStreamPredictor({
|
|
27
|
+
Predictor: new PdfNumber(13),
|
|
28
|
+
});
|
|
29
|
+
static PNG_PAETH = new PdfStreamPredictor({ Predictor: new PdfNumber(14) });
|
|
30
|
+
static PNG_OPTIMUM = new PdfStreamPredictor({
|
|
31
|
+
Predictor: new PdfNumber(15),
|
|
32
|
+
});
|
|
33
|
+
static XREF_STREAM = new PdfStreamPredictor({
|
|
34
|
+
Predictor: new PdfNumber(12),
|
|
35
|
+
Columns: new PdfNumber(7),
|
|
36
|
+
});
|
|
37
|
+
get predictor() {
|
|
38
|
+
return this.get('Predictor')?.as(PdfNumber)?.value ?? 1;
|
|
39
|
+
}
|
|
40
|
+
set predictor(value) {
|
|
41
|
+
this.set('Predictor', new PdfNumber(value));
|
|
42
|
+
}
|
|
43
|
+
get columns() {
|
|
44
|
+
return this.get('Columns')?.as(PdfNumber)?.value ?? 1;
|
|
45
|
+
}
|
|
46
|
+
set columns(value) {
|
|
47
|
+
this.set('Columns', new PdfNumber(value));
|
|
48
|
+
}
|
|
49
|
+
get colors() {
|
|
50
|
+
return this.get('Colors')?.as(PdfNumber)?.value ?? 1;
|
|
51
|
+
}
|
|
52
|
+
set colors(value) {
|
|
53
|
+
this.set('Colors', new PdfNumber(value));
|
|
54
|
+
}
|
|
55
|
+
get bitsPerComponent() {
|
|
56
|
+
return this.get('BitsPerComponent')?.as(PdfNumber)?.value ?? 8;
|
|
57
|
+
}
|
|
58
|
+
set bitsPerComponent(value) {
|
|
59
|
+
this.set('BitsPerComponent', new PdfNumber(value));
|
|
60
|
+
}
|
|
61
|
+
toDecodeParms() {
|
|
62
|
+
const params = {};
|
|
63
|
+
const predictor = this.get('Predictor')?.as(PdfNumber);
|
|
64
|
+
if (predictor)
|
|
65
|
+
params.Predictor = predictor.value;
|
|
66
|
+
const columns = this.get('Columns')?.as(PdfNumber);
|
|
67
|
+
if (columns)
|
|
68
|
+
params.Columns = columns.value;
|
|
69
|
+
const colors = this.get('Colors')?.as(PdfNumber);
|
|
70
|
+
if (colors)
|
|
71
|
+
params.Colors = colors.value;
|
|
72
|
+
const bpc = this.get('BitsPerComponent')?.as(PdfNumber);
|
|
73
|
+
if (bpc)
|
|
74
|
+
params.BitsPerComponent = bpc.value;
|
|
75
|
+
return params;
|
|
76
|
+
}
|
|
77
|
+
cloneImpl() {
|
|
78
|
+
return PdfStreamPredictor.fromDecodeParms(this.toDecodeParms());
|
|
79
|
+
}
|
|
80
|
+
static fromDecodeParms(params) {
|
|
81
|
+
const predictor = new PdfStreamPredictor();
|
|
82
|
+
if (params.Predictor !== undefined) {
|
|
83
|
+
predictor.predictor = params.Predictor;
|
|
84
|
+
}
|
|
85
|
+
if (params.Columns !== undefined) {
|
|
86
|
+
predictor.columns = params.Columns;
|
|
87
|
+
}
|
|
88
|
+
if (params.Colors !== undefined) {
|
|
89
|
+
predictor.colors = params.Colors;
|
|
90
|
+
}
|
|
91
|
+
if (params.BitsPerComponent !== undefined) {
|
|
92
|
+
predictor.bitsPerComponent = params.BitsPerComponent;
|
|
93
|
+
}
|
|
94
|
+
return predictor;
|
|
95
|
+
}
|
|
96
|
+
static fromDictionary(dict) {
|
|
97
|
+
if (!dict)
|
|
98
|
+
return undefined;
|
|
99
|
+
const predictor = dict.get('Predictor')?.as(PdfNumber)?.value;
|
|
100
|
+
if (predictor === undefined || predictor <= 1 || predictor > 15) {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
return PdfStreamPredictor.fromDecodeParms({
|
|
104
|
+
Predictor: predictor,
|
|
105
|
+
Columns: dict.get('Columns')?.as(PdfNumber)?.value,
|
|
106
|
+
Colors: dict.get('Colors')?.as(PdfNumber)?.value,
|
|
107
|
+
BitsPerComponent: dict.get('BitsPerComponent')?.as(PdfNumber)
|
|
108
|
+
?.value,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
encode(data, filterType = 0) {
|
|
112
|
+
const bpp = Math.ceil((this.colors * this.bitsPerComponent) / 8);
|
|
113
|
+
if (this.predictor === 2) {
|
|
114
|
+
return PdfStreamPredictor.tiffEncode(data, this.columns, bpp);
|
|
115
|
+
}
|
|
116
|
+
else if (this.predictor >= 10 && this.predictor <= 15) {
|
|
117
|
+
return PdfStreamPredictor.pngEncode(data, this.columns, bpp, filterType);
|
|
118
|
+
}
|
|
119
|
+
return data;
|
|
120
|
+
}
|
|
121
|
+
decode(data) {
|
|
122
|
+
const bpp = Math.ceil((this.colors * this.bitsPerComponent) / 8);
|
|
123
|
+
if (this.predictor === 2) {
|
|
124
|
+
return PdfStreamPredictor.tiffDecode(data, this.columns, bpp);
|
|
125
|
+
}
|
|
126
|
+
else if (this.predictor >= 10 && this.predictor <= 15) {
|
|
127
|
+
return PdfStreamPredictor.pngDecode(data, this.columns, bpp);
|
|
128
|
+
}
|
|
129
|
+
return data;
|
|
130
|
+
}
|
|
131
|
+
static tiffDecode(data, columns, bpp) {
|
|
132
|
+
const rowLength = columns * bpp;
|
|
133
|
+
const output = new Uint8Array(data.length);
|
|
134
|
+
for (let i = 0; i < data.length; i += rowLength) {
|
|
135
|
+
for (let j = 0; j < rowLength; j++) {
|
|
136
|
+
output[i + j] =
|
|
137
|
+
j < bpp
|
|
138
|
+
? data[i + j]
|
|
139
|
+
: (data[i + j] + output[i + j - bpp]) & 0xff;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return output;
|
|
143
|
+
}
|
|
144
|
+
static tiffEncode(data, columns, bpp) {
|
|
145
|
+
const rowLength = columns * bpp;
|
|
146
|
+
const output = new Uint8Array(data.length);
|
|
147
|
+
for (let i = 0; i < data.length; i += rowLength) {
|
|
148
|
+
for (let j = 0; j < rowLength; j++) {
|
|
149
|
+
output[i + j] =
|
|
150
|
+
j < bpp
|
|
151
|
+
? data[i + j]
|
|
152
|
+
: (data[i + j] - data[i + j - bpp] + 256) & 0xff;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return output;
|
|
156
|
+
}
|
|
157
|
+
static pngDecode(data, columns, bpp) {
|
|
158
|
+
const rowLength = columns * bpp;
|
|
159
|
+
const output = [];
|
|
160
|
+
for (let i = 0; i < data.length;) {
|
|
161
|
+
const filter = data[i];
|
|
162
|
+
const row = data.slice(i + 1, i + 1 + rowLength);
|
|
163
|
+
const prior = output.slice(output.length - rowLength, output.length);
|
|
164
|
+
const decodedRow = new Uint8Array(rowLength);
|
|
165
|
+
for (let j = 0; j < rowLength; j++) {
|
|
166
|
+
const left = j >= bpp ? decodedRow[j - bpp] : 0;
|
|
167
|
+
const up = prior[j] ?? 0;
|
|
168
|
+
const upperLeft = j >= bpp ? (prior[j - bpp] ?? 0) : 0;
|
|
169
|
+
switch (filter) {
|
|
170
|
+
case 0:
|
|
171
|
+
decodedRow[j] = row[j];
|
|
172
|
+
break;
|
|
173
|
+
case 1:
|
|
174
|
+
decodedRow[j] = (row[j] + left) & 0xff;
|
|
175
|
+
break;
|
|
176
|
+
case 2:
|
|
177
|
+
decodedRow[j] = (row[j] + up) & 0xff;
|
|
178
|
+
break;
|
|
179
|
+
case 3:
|
|
180
|
+
decodedRow[j] =
|
|
181
|
+
(row[j] + Math.floor((left + up) / 2)) & 0xff;
|
|
182
|
+
break;
|
|
183
|
+
case 4:
|
|
184
|
+
decodedRow[j] =
|
|
185
|
+
(row[j] +
|
|
186
|
+
this.paethPredictor(left, up, upperLeft)) &
|
|
187
|
+
0xff;
|
|
188
|
+
break;
|
|
189
|
+
default:
|
|
190
|
+
throw new Error(`Unsupported PNG filter: ${filter}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
output.push(...decodedRow);
|
|
194
|
+
i += 1 + rowLength;
|
|
195
|
+
}
|
|
196
|
+
return new Uint8Array(output);
|
|
197
|
+
}
|
|
198
|
+
static pngEncode(data, columns, bpp, filterType) {
|
|
199
|
+
const rowLength = columns * bpp;
|
|
200
|
+
const output = [];
|
|
201
|
+
let prior = new Uint8Array(rowLength);
|
|
202
|
+
for (let i = 0; i < data.length; i += rowLength) {
|
|
203
|
+
const row = data.slice(i, i + rowLength);
|
|
204
|
+
const encodedRow = new Uint8Array(rowLength);
|
|
205
|
+
for (let j = 0; j < rowLength; j++) {
|
|
206
|
+
const left = j >= bpp ? row[j - bpp] : 0;
|
|
207
|
+
const up = prior[j] ?? 0;
|
|
208
|
+
const upperLeft = j >= bpp ? (prior[j - bpp] ?? 0) : 0;
|
|
209
|
+
switch (filterType) {
|
|
210
|
+
case 0:
|
|
211
|
+
encodedRow[j] = row[j];
|
|
212
|
+
break;
|
|
213
|
+
case 1:
|
|
214
|
+
encodedRow[j] = (row[j] - left + 256) & 0xff;
|
|
215
|
+
break;
|
|
216
|
+
case 2:
|
|
217
|
+
encodedRow[j] = (row[j] - up + 256) & 0xff;
|
|
218
|
+
break;
|
|
219
|
+
case 3:
|
|
220
|
+
encodedRow[j] =
|
|
221
|
+
(row[j] - Math.floor((left + up) / 2) + 256) & 0xff;
|
|
222
|
+
break;
|
|
223
|
+
case 4:
|
|
224
|
+
encodedRow[j] =
|
|
225
|
+
(row[j] -
|
|
226
|
+
this.paethPredictor(left, up, upperLeft) +
|
|
227
|
+
256) &
|
|
228
|
+
0xff;
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
throw new Error(`Unsupported PNG filter: ${filterType}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
output.push(filterType, ...encodedRow);
|
|
235
|
+
prior = row;
|
|
236
|
+
}
|
|
237
|
+
return new Uint8Array(output);
|
|
238
|
+
}
|
|
239
|
+
static paethPredictor(a, b, c) {
|
|
240
|
+
const p = a + b - c;
|
|
241
|
+
const pa = Math.abs(p - a);
|
|
242
|
+
const pb = Math.abs(p - b);
|
|
243
|
+
const pc = Math.abs(p - c);
|
|
244
|
+
if (pa <= pb && pa <= pc)
|
|
245
|
+
return a;
|
|
246
|
+
if (pb <= pc)
|
|
247
|
+
return b;
|
|
248
|
+
return c;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
21
251
|
export class PdfStream extends PdfObject {
|
|
252
|
+
static PdfStreamPredictor = PdfStreamPredictor;
|
|
22
253
|
header;
|
|
23
254
|
original;
|
|
24
255
|
preStreamDataTokens;
|
|
@@ -45,9 +276,6 @@ export class PdfStream extends PdfObject {
|
|
|
45
276
|
return this.original.slice(0, length);
|
|
46
277
|
}
|
|
47
278
|
set raw(data) {
|
|
48
|
-
if (this.isImmutable()) {
|
|
49
|
-
throw new Error('Cannot modify an immutable PdfStream');
|
|
50
|
-
}
|
|
51
279
|
this.setModified();
|
|
52
280
|
this.original = data;
|
|
53
281
|
this.header.set('Length', new PdfNumber(data.length));
|
|
@@ -61,6 +289,28 @@ export class PdfStream extends PdfObject {
|
|
|
61
289
|
set rawAsString(str) {
|
|
62
290
|
this.raw = stringToBytes(str);
|
|
63
291
|
}
|
|
292
|
+
get data() {
|
|
293
|
+
return this.decode();
|
|
294
|
+
}
|
|
295
|
+
set data(data) {
|
|
296
|
+
const filters = this.getFilters();
|
|
297
|
+
const existingPredictor = this.predictor;
|
|
298
|
+
this.removeAllFilters();
|
|
299
|
+
this.header.delete('DecodeParms');
|
|
300
|
+
this.raw = data;
|
|
301
|
+
if (existingPredictor) {
|
|
302
|
+
this.predictor = existingPredictor;
|
|
303
|
+
}
|
|
304
|
+
for (const filter of filters) {
|
|
305
|
+
this.addFilter(filter);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
get dataAsString() {
|
|
309
|
+
return bytesToString(this.data);
|
|
310
|
+
}
|
|
311
|
+
set dataAsString(str) {
|
|
312
|
+
this.data = stringToBytes(str);
|
|
313
|
+
}
|
|
64
314
|
getFilters() {
|
|
65
315
|
const filters = this.header.get('Filter');
|
|
66
316
|
if (!filters) {
|
|
@@ -94,23 +344,24 @@ export class PdfStream extends PdfObject {
|
|
|
94
344
|
this.raw = filter.encode(this.raw);
|
|
95
345
|
return this;
|
|
96
346
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (!
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
347
|
+
get predictor() {
|
|
348
|
+
const raw = this.header.get('DecodeParms');
|
|
349
|
+
if (!raw)
|
|
350
|
+
return undefined;
|
|
351
|
+
if (raw instanceof PdfStreamPredictor) {
|
|
352
|
+
if (raw.get('Predictor') === undefined)
|
|
353
|
+
return undefined;
|
|
354
|
+
return raw;
|
|
105
355
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
for (const [key, value] of Object.entries(predictorParams)) {
|
|
110
|
-
decodeParms.set(key, new PdfNumber(value));
|
|
356
|
+
if (raw instanceof PdfDictionary) {
|
|
357
|
+
return PdfStreamPredictor.fromDictionary(raw);
|
|
111
358
|
}
|
|
112
|
-
|
|
113
|
-
|
|
359
|
+
return undefined;
|
|
360
|
+
}
|
|
361
|
+
set predictor(predictor) {
|
|
362
|
+
const cloned = predictor.cloneImpl();
|
|
363
|
+
this.header.set('DecodeParms', cloned);
|
|
364
|
+
this.raw = cloned.encode(this.raw);
|
|
114
365
|
}
|
|
115
366
|
removeFilter(filterName) {
|
|
116
367
|
let filters = this.header.get('Filter');
|
|
@@ -159,9 +410,9 @@ export class PdfStream extends PdfObject {
|
|
|
159
410
|
const filter = PdfStream.getFilter(filterName);
|
|
160
411
|
data = filter.decode(data);
|
|
161
412
|
}
|
|
162
|
-
const
|
|
163
|
-
if (
|
|
164
|
-
data =
|
|
413
|
+
const streamPredictor = PdfStreamPredictor.fromDictionary(this.header.get('DecodeParms')?.as(PdfDictionary));
|
|
414
|
+
if (streamPredictor) {
|
|
415
|
+
data = streamPredictor.decode(data);
|
|
165
416
|
}
|
|
166
417
|
return data;
|
|
167
418
|
}
|
|
@@ -235,6 +486,14 @@ export class PdfStream extends PdfObject {
|
|
|
235
486
|
}
|
|
236
487
|
}
|
|
237
488
|
export class PdfObjStream extends PdfStream {
|
|
489
|
+
_parsedObjects;
|
|
490
|
+
set raw(data) {
|
|
491
|
+
super.raw = data;
|
|
492
|
+
this._parsedObjects = undefined;
|
|
493
|
+
}
|
|
494
|
+
get raw() {
|
|
495
|
+
return super.raw;
|
|
496
|
+
}
|
|
238
497
|
constructor(options) {
|
|
239
498
|
super(options);
|
|
240
499
|
if (!this.isType('ObjStm')) {
|
|
@@ -297,8 +556,11 @@ export class PdfObjStream extends PdfStream {
|
|
|
297
556
|
const { value: obj, done } = reader.next();
|
|
298
557
|
if (done)
|
|
299
558
|
break;
|
|
300
|
-
if (obj instanceof PdfNumber
|
|
301
|
-
|
|
559
|
+
if (obj instanceof PdfNumber &&
|
|
560
|
+
(totalObjects === 0 || numbers.length < totalObjects * 2)) {
|
|
561
|
+
// Collect object numbers and byte offsets from the header section.
|
|
562
|
+
// Stop once we have all 2*N pairs so that object values that happen
|
|
563
|
+
// to be plain integers are not mistakenly treated as header entries.
|
|
302
564
|
numbers.push(obj);
|
|
303
565
|
}
|
|
304
566
|
else {
|
|
@@ -307,11 +569,14 @@ export class PdfObjStream extends PdfStream {
|
|
|
307
569
|
// After that come the actual objects
|
|
308
570
|
const objectNumber = numbers[i * 2].value;
|
|
309
571
|
const generationNumber = 0;
|
|
310
|
-
|
|
572
|
+
const decompressedObject = new PdfIndirectObject({
|
|
311
573
|
objectNumber,
|
|
312
574
|
generationNumber,
|
|
313
575
|
content: obj,
|
|
314
|
-
|
|
576
|
+
compressed: true,
|
|
577
|
+
}).clone();
|
|
578
|
+
decompressedObject.setModified(false);
|
|
579
|
+
yield decompressedObject;
|
|
315
580
|
i++;
|
|
316
581
|
// Stop after we've read N objects
|
|
317
582
|
if (totalObjects > 0 && i >= totalObjects) {
|
|
@@ -320,16 +585,20 @@ export class PdfObjStream extends PdfStream {
|
|
|
320
585
|
}
|
|
321
586
|
}
|
|
322
587
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
588
|
+
getParsedObjects() {
|
|
589
|
+
if (!this._parsedObjects) {
|
|
590
|
+
this._parsedObjects = new Map();
|
|
591
|
+
for (const obj of this.getObjectStream()) {
|
|
592
|
+
this._parsedObjects.set(obj.objectNumber, obj);
|
|
327
593
|
}
|
|
328
594
|
}
|
|
329
|
-
return
|
|
595
|
+
return this._parsedObjects;
|
|
596
|
+
}
|
|
597
|
+
getObject(options) {
|
|
598
|
+
return this.getParsedObjects().get(options.objectNumber);
|
|
330
599
|
}
|
|
331
600
|
getObjects() {
|
|
332
|
-
return Array.from(this.
|
|
601
|
+
return Array.from(this.getParsedObjects().values());
|
|
333
602
|
}
|
|
334
603
|
cloneImpl() {
|
|
335
604
|
return new PdfObjStream({
|
|
@@ -37,9 +37,6 @@ export class PdfString extends PdfObject {
|
|
|
37
37
|
return this._raw;
|
|
38
38
|
}
|
|
39
39
|
set raw(raw) {
|
|
40
|
-
if (this.isImmutable()) {
|
|
41
|
-
throw new Error('Cannot modify an immutable PdfString');
|
|
42
|
-
}
|
|
43
40
|
this.setModified();
|
|
44
41
|
this._raw = raw;
|
|
45
42
|
// Clear original bytes when modified
|
|
@@ -53,9 +50,6 @@ export class PdfString extends PdfObject {
|
|
|
53
50
|
return (this.raw.length >= 2 && this.raw[0] === 0xfe && this.raw[1] === 0xff);
|
|
54
51
|
}
|
|
55
52
|
set value(str) {
|
|
56
|
-
if (this.isImmutable()) {
|
|
57
|
-
throw new Error('Cannot modify an immutable PdfString');
|
|
58
|
-
}
|
|
59
53
|
this.setModified();
|
|
60
54
|
if (needsUnicodeEncoding(str)) {
|
|
61
55
|
this._raw = encodeAsUTF16BE(str);
|
|
@@ -74,6 +68,9 @@ export class PdfString extends PdfObject {
|
|
|
74
68
|
// Default: use PDFDocEncoding
|
|
75
69
|
return decodeFromPDFDocEncoding(this.raw);
|
|
76
70
|
}
|
|
71
|
+
get isTrailingDelimited() {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
77
74
|
tokenize() {
|
|
78
75
|
return [new PdfStringToken(this.raw, this._originalBytes)];
|
|
79
76
|
}
|
|
@@ -26,9 +26,12 @@ export class PdfTrailer extends PdfObject {
|
|
|
26
26
|
const cloned = new PdfTrailer(this.dict.clone());
|
|
27
27
|
return cloned;
|
|
28
28
|
}
|
|
29
|
+
setModified(modified) {
|
|
30
|
+
super.setModified(modified);
|
|
31
|
+
this.dict.setModified(modified);
|
|
32
|
+
this.offset.setModified(modified);
|
|
33
|
+
}
|
|
29
34
|
isModified() {
|
|
30
|
-
return (super.isModified() ||
|
|
31
|
-
this.dict.isModified() ||
|
|
32
|
-
this.offset.isModified);
|
|
35
|
+
return (super.isModified() || this.dict.isModified() || this.offset.modified);
|
|
33
36
|
}
|
|
34
37
|
}
|
|
@@ -87,7 +87,7 @@ export class PdfXRefTable extends PdfObject {
|
|
|
87
87
|
return (super.isModified() ||
|
|
88
88
|
this.sections.some((section) => section.isModified()) ||
|
|
89
89
|
this.entries.some((entry) => entry.isModified()) ||
|
|
90
|
-
this.offset.
|
|
90
|
+
this.offset.modified);
|
|
91
91
|
}
|
|
92
92
|
addEntryForObject(obj) {
|
|
93
93
|
const foundEntry = this.entries.find((entry) => entry.objectNumber.value === obj.objectNumber);
|
package/dist/core/ref.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export declare class Ref<T> {
|
|
|
22
22
|
value: T | Ref<T>;
|
|
23
23
|
/** Registered callbacks for update notifications */
|
|
24
24
|
callbacks: Array<RefUpdateCallback<T>>;
|
|
25
|
-
|
|
25
|
+
modified: boolean;
|
|
26
26
|
protected immutable: boolean;
|
|
27
27
|
/**
|
|
28
28
|
* Creates a new Ref with an initial value.
|
|
@@ -31,6 +31,8 @@ export declare class Ref<T> {
|
|
|
31
31
|
* @throws Error if attempting to create a self-referencing Ref
|
|
32
32
|
*/
|
|
33
33
|
constructor(value: T | Ref<T>);
|
|
34
|
+
isModified(): boolean;
|
|
35
|
+
setModified(modified?: boolean): void;
|
|
34
36
|
setImmutable(immutable?: boolean): void;
|
|
35
37
|
isImmutable(): boolean;
|
|
36
38
|
/**
|