pdf-lite 1.7.4-alpha.5 → 1.7.4-alpha.7
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/acroform/appearance/pdf-appearance-stream.d.ts +1 -0
- package/dist/acroform/appearance/pdf-appearance-stream.js +3 -0
- package/dist/acroform/appearance/pdf-choice-appearance-stream.d.ts +1 -0
- package/dist/acroform/appearance/pdf-choice-appearance-stream.js +19 -2
- package/dist/acroform/appearance/pdf-text-appearance-stream.d.ts +1 -0
- package/dist/acroform/appearance/pdf-text-appearance-stream.js +24 -2
- package/dist/acroform/fields/pdf-choice-form-field.js +4 -0
- package/dist/acroform/fields/pdf-text-form-field.js +1 -0
- package/dist/core/decoder.d.ts +3 -0
- package/dist/core/decoder.js +27 -2
- package/dist/core/serializer.js +1 -1
- package/dist/core/tokens/number-token.js +11 -1
- package/dist/pdf/pdf-document.js +9 -2
- package/dist/pdf/pdf-xref-lookup.d.ts +1 -1
- package/dist/pdf/pdf-xref-lookup.js +5 -2
- package/package.json +1 -1
|
@@ -14,6 +14,7 @@ export declare class PdfAppearanceStream extends PdfIndirectObject<PdfStream> {
|
|
|
14
14
|
height?: number;
|
|
15
15
|
contentStream?: string;
|
|
16
16
|
resources?: PdfDictionary;
|
|
17
|
+
matrix?: [number, number, number, number, number, number];
|
|
17
18
|
});
|
|
18
19
|
get contentStream(): string;
|
|
19
20
|
set contentStream(newContent: string);
|
|
@@ -20,6 +20,9 @@ export class PdfAppearanceStream extends PdfIndirectObject {
|
|
|
20
20
|
new PdfNumber(options.width ?? 100),
|
|
21
21
|
new PdfNumber(options.height ?? 100),
|
|
22
22
|
]));
|
|
23
|
+
if (options.matrix) {
|
|
24
|
+
appearanceDict.set('Matrix', new PdfArray(options.matrix.map((v) => new PdfNumber(v))));
|
|
25
|
+
}
|
|
23
26
|
if (options.resources) {
|
|
24
27
|
appearanceDict.set('Resources', options.resources);
|
|
25
28
|
}
|
|
@@ -20,12 +20,29 @@ export class PdfChoiceAppearanceStream extends PdfAppearanceStream {
|
|
|
20
20
|
[x1, x2] = [x2, x1];
|
|
21
21
|
if (y2 < y1)
|
|
22
22
|
[y1, y2] = [y2, y1];
|
|
23
|
-
const
|
|
24
|
-
const
|
|
23
|
+
const rectWidth = x2 - x1;
|
|
24
|
+
const rectHeight = y2 - y1;
|
|
25
|
+
const rotation = ctx.rotation ?? 0;
|
|
26
|
+
const needsSwap = rotation === 90 || rotation === 270;
|
|
27
|
+
const width = needsSwap ? rectHeight : rectWidth;
|
|
28
|
+
const height = needsSwap ? rectWidth : rectHeight;
|
|
29
|
+
// For rotated pages, the BBox uses the displayed (swapped)
|
|
30
|
+
// dimensions and a Matrix entry maps back to annotation space.
|
|
31
|
+
let matrix;
|
|
32
|
+
if (rotation === 90) {
|
|
33
|
+
matrix = [0, 1, -1, 0, rectWidth, 0];
|
|
34
|
+
}
|
|
35
|
+
else if (rotation === 270) {
|
|
36
|
+
matrix = [0, -1, 1, 0, 0, rectHeight];
|
|
37
|
+
}
|
|
38
|
+
else if (rotation === 180) {
|
|
39
|
+
matrix = [-1, 0, 0, -1, rectWidth, rectHeight];
|
|
40
|
+
}
|
|
25
41
|
super({
|
|
26
42
|
width,
|
|
27
43
|
height,
|
|
28
44
|
resources: ctx.fontResources,
|
|
45
|
+
matrix,
|
|
29
46
|
});
|
|
30
47
|
const isUnicode = ctx.isUnicode ?? false;
|
|
31
48
|
const reverseEncodingMap = ctx.reverseEncodingMap;
|
|
@@ -28,8 +28,17 @@ export class PdfTextAppearanceStream extends PdfAppearanceStream {
|
|
|
28
28
|
[x1, x2] = [x2, x1];
|
|
29
29
|
if (y2 < y1)
|
|
30
30
|
[y1, y2] = [y2, y1];
|
|
31
|
-
const
|
|
32
|
-
const
|
|
31
|
+
const rectWidth = x2 - x1;
|
|
32
|
+
const rectHeight = y2 - y1;
|
|
33
|
+
// For rotated pages, the field rect is in the unrotated coordinate
|
|
34
|
+
// space. A 90° or 270° page rotation swaps how the field appears on
|
|
35
|
+
// screen (tall/narrow rect becomes wide/short when viewed). We swap
|
|
36
|
+
// the layout dimensions so text is laid out for the displayed shape,
|
|
37
|
+
// then apply a rotation matrix to map back into the BBox.
|
|
38
|
+
const rotation = ctx.rotation ?? 0;
|
|
39
|
+
const needsSwap = rotation === 90 || rotation === 270;
|
|
40
|
+
const width = needsSwap ? rectHeight : rectWidth;
|
|
41
|
+
const height = needsSwap ? rectWidth : rectHeight;
|
|
33
42
|
const value = ctx.value;
|
|
34
43
|
const isUnicode = ctx.isUnicode ?? false;
|
|
35
44
|
const reverseEncodingMap = ctx.reverseEncodingMap;
|
|
@@ -167,11 +176,24 @@ export class PdfTextAppearanceStream extends PdfAppearanceStream {
|
|
|
167
176
|
}
|
|
168
177
|
g.restore();
|
|
169
178
|
g.endMarkedContent();
|
|
179
|
+
// For rotated pages, the BBox uses the displayed (swapped)
|
|
180
|
+
// dimensions and a Matrix entry maps back to annotation space.
|
|
181
|
+
let matrix;
|
|
182
|
+
if (rotation === 90) {
|
|
183
|
+
matrix = [0, 1, -1, 0, rectWidth, 0];
|
|
184
|
+
}
|
|
185
|
+
else if (rotation === 270) {
|
|
186
|
+
matrix = [0, -1, 1, 0, 0, rectHeight];
|
|
187
|
+
}
|
|
188
|
+
else if (rotation === 180) {
|
|
189
|
+
matrix = [-1, 0, 0, -1, rectWidth, rectHeight];
|
|
190
|
+
}
|
|
170
191
|
super({
|
|
171
192
|
width,
|
|
172
193
|
height,
|
|
173
194
|
contentStream: g.build(),
|
|
174
195
|
resources: ctx.fontResources,
|
|
196
|
+
matrix,
|
|
175
197
|
});
|
|
176
198
|
}
|
|
177
199
|
}
|
|
@@ -97,11 +97,15 @@ export class PdfChoiceFormField extends PdfFormField {
|
|
|
97
97
|
da: parsed,
|
|
98
98
|
flags: this.flags,
|
|
99
99
|
fontResources,
|
|
100
|
+
resolvedFonts: font
|
|
101
|
+
? new Map([[parsed.fontName, font]])
|
|
102
|
+
: undefined,
|
|
100
103
|
isUnicode,
|
|
101
104
|
reverseEncodingMap,
|
|
102
105
|
displayOptions: this.options.map((opt) => opt.label),
|
|
103
106
|
selectedIndex: this.selectedIndex,
|
|
104
107
|
quadding: this.quadding,
|
|
108
|
+
rotation: this.page?.rotate ?? 0,
|
|
105
109
|
});
|
|
106
110
|
if (options?.makeReadOnly) {
|
|
107
111
|
this.readOnly = true;
|
package/dist/core/decoder.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { IncrementalParser } from './parser/incremental-parser.js';
|
|
|
8
8
|
export declare class PdfDecoder extends IncrementalParser<PdfToken, PdfObject> {
|
|
9
9
|
private ignoreWhitespace;
|
|
10
10
|
private maxBufferSizeBytes;
|
|
11
|
+
private _bufferByteSize;
|
|
11
12
|
/**
|
|
12
13
|
* Creates a new PDF decoder.
|
|
13
14
|
*
|
|
@@ -19,6 +20,7 @@ export declare class PdfDecoder extends IncrementalParser<PdfToken, PdfObject> {
|
|
|
19
20
|
ignoreWhitespace?: boolean;
|
|
20
21
|
maxBufferSizeBytes?: number;
|
|
21
22
|
});
|
|
23
|
+
feed(...input: (PdfToken | PdfToken[])[]): void;
|
|
22
24
|
private nextName;
|
|
23
25
|
private nextIndirectObject;
|
|
24
26
|
private nextValue;
|
|
@@ -34,6 +36,7 @@ export declare class PdfDecoder extends IncrementalParser<PdfToken, PdfObject> {
|
|
|
34
36
|
private nextObject;
|
|
35
37
|
private static isPrimitive;
|
|
36
38
|
protected bufferSize(): number;
|
|
39
|
+
protected compact(): void;
|
|
37
40
|
protected canCompact(): boolean;
|
|
38
41
|
protected parse(): PdfObject;
|
|
39
42
|
}
|
package/dist/core/decoder.js
CHANGED
|
@@ -46,6 +46,7 @@ const DEFAULT_MAX_BUFFER_SIZE_BYTES = 10 * 1024 * 1024; // 10 MB
|
|
|
46
46
|
export class PdfDecoder extends IncrementalParser {
|
|
47
47
|
ignoreWhitespace = false;
|
|
48
48
|
maxBufferSizeBytes = DEFAULT_MAX_BUFFER_SIZE_BYTES;
|
|
49
|
+
_bufferByteSize = 0;
|
|
49
50
|
/**
|
|
50
51
|
* Creates a new PDF decoder.
|
|
51
52
|
*
|
|
@@ -59,6 +60,20 @@ export class PdfDecoder extends IncrementalParser {
|
|
|
59
60
|
this.maxBufferSizeBytes =
|
|
60
61
|
options?.maxBufferSizeBytes ?? DEFAULT_MAX_BUFFER_SIZE_BYTES;
|
|
61
62
|
}
|
|
63
|
+
feed(...input) {
|
|
64
|
+
for (const item of input) {
|
|
65
|
+
if (Array.isArray(item)) {
|
|
66
|
+
for (const subItem of item) {
|
|
67
|
+
this._bufferByteSize += subItem.byteLength;
|
|
68
|
+
this.buffer.push(subItem);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
this._bufferByteSize += item.byteLength;
|
|
73
|
+
this.buffer.push(item);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
62
77
|
nextName() {
|
|
63
78
|
const preTokens = this.nextExtraTokens();
|
|
64
79
|
const token = this.expect(PdfNameToken);
|
|
@@ -356,10 +371,20 @@ export class PdfDecoder extends IncrementalParser {
|
|
|
356
371
|
token instanceof PdfStringToken);
|
|
357
372
|
}
|
|
358
373
|
bufferSize() {
|
|
359
|
-
return this.
|
|
374
|
+
return this._bufferByteSize;
|
|
375
|
+
}
|
|
376
|
+
compact() {
|
|
377
|
+
if (this.bufferIndex > 0) {
|
|
378
|
+
for (let i = 0; i < this.bufferIndex; i++) {
|
|
379
|
+
this._bufferByteSize -= this.buffer[i].byteLength;
|
|
380
|
+
}
|
|
381
|
+
this.buffer = this.buffer.slice(this.bufferIndex);
|
|
382
|
+
this.bufferIndex = 0;
|
|
383
|
+
}
|
|
360
384
|
}
|
|
361
385
|
canCompact() {
|
|
362
|
-
return (this.bufferIndex > 50 &&
|
|
386
|
+
return (this.bufferIndex > 50 &&
|
|
387
|
+
this._bufferByteSize > this.maxBufferSizeBytes);
|
|
363
388
|
}
|
|
364
389
|
parse() {
|
|
365
390
|
return this.nextObject(true);
|
package/dist/core/serializer.js
CHANGED
|
@@ -3,6 +3,7 @@ import { Ref } from '../ref.js';
|
|
|
3
3
|
import { PdfToken } from './token.js';
|
|
4
4
|
export class PdfNumberToken extends PdfToken {
|
|
5
5
|
#value;
|
|
6
|
+
#cachedBytes;
|
|
6
7
|
padTo;
|
|
7
8
|
decimalPlaces;
|
|
8
9
|
isByteToken = false;
|
|
@@ -27,19 +28,28 @@ export class PdfNumberToken extends PdfToken {
|
|
|
27
28
|
this.isByteToken = options.isByteToken ?? false;
|
|
28
29
|
}
|
|
29
30
|
toBytes() {
|
|
30
|
-
|
|
31
|
+
if (this.#cachedBytes && !this.isByteToken) {
|
|
32
|
+
return this.#cachedBytes;
|
|
33
|
+
}
|
|
34
|
+
const bytes = PdfNumberToken.toBytes(this.#value, this.padTo, this.decimalPlaces);
|
|
35
|
+
if (!this.isByteToken) {
|
|
36
|
+
this.#cachedBytes = bytes;
|
|
37
|
+
}
|
|
38
|
+
return bytes;
|
|
31
39
|
}
|
|
32
40
|
get ref() {
|
|
33
41
|
return this.#value;
|
|
34
42
|
}
|
|
35
43
|
set ref(newRef) {
|
|
36
44
|
this.#value = newRef;
|
|
45
|
+
this.#cachedBytes = undefined;
|
|
37
46
|
}
|
|
38
47
|
get value() {
|
|
39
48
|
return this.#value.resolve();
|
|
40
49
|
}
|
|
41
50
|
set value(newValue) {
|
|
42
51
|
this.#value.update(newValue);
|
|
52
|
+
this.#cachedBytes = undefined;
|
|
43
53
|
}
|
|
44
54
|
static getValue(bytes) {
|
|
45
55
|
if (bytes instanceof Ref) {
|
package/dist/pdf/pdf-document.js
CHANGED
|
@@ -964,12 +964,17 @@ export class PdfDocument extends PdfObject {
|
|
|
964
964
|
linkRevisions() {
|
|
965
965
|
const xrefLookups = this.revisions.map((rev) => rev.xref);
|
|
966
966
|
const indirectObjects = this.objects.filter((x) => x instanceof PdfIndirectObject);
|
|
967
|
+
// Build offset map once for O(1) lookups across all xrefs
|
|
968
|
+
const offsetMap = new Map();
|
|
969
|
+
for (const obj of indirectObjects) {
|
|
970
|
+
offsetMap.set(obj.offset.resolve(), obj);
|
|
971
|
+
}
|
|
967
972
|
for (const revision of this.revisions) {
|
|
968
973
|
revision.xref.linkPrev(xrefLookups);
|
|
969
974
|
// Walk the entire prev chain to link all xref entries
|
|
970
975
|
let xref = revision.xref;
|
|
971
976
|
while (xref) {
|
|
972
|
-
xref.linkIndirectObjects(indirectObjects);
|
|
977
|
+
xref.linkIndirectObjects(indirectObjects, offsetMap);
|
|
973
978
|
xref = xref.prev;
|
|
974
979
|
}
|
|
975
980
|
}
|
|
@@ -1112,7 +1117,9 @@ export class PdfDocument extends PdfObject {
|
|
|
1112
1117
|
* @returns A cloned PdfDocument instance
|
|
1113
1118
|
*/
|
|
1114
1119
|
cloneImpl() {
|
|
1115
|
-
this.
|
|
1120
|
+
if (this.isModified()) {
|
|
1121
|
+
this.update();
|
|
1122
|
+
}
|
|
1116
1123
|
const clonedRevisions = this.revisions.map((rev) => rev.clone());
|
|
1117
1124
|
const cloned = new PdfDocument({
|
|
1118
1125
|
revisions: clonedRevisions,
|
|
@@ -96,7 +96,7 @@ export declare class PdfXrefLookup {
|
|
|
96
96
|
*
|
|
97
97
|
* @param objects - Array of indirect objects to link
|
|
98
98
|
*/
|
|
99
|
-
linkIndirectObjects(objects: PdfIndirectObject[]): void;
|
|
99
|
+
linkIndirectObjects(objects: PdfIndirectObject[], offsetMap?: Map<number, PdfIndirectObject>): void;
|
|
100
100
|
/**
|
|
101
101
|
* Links this xref to a previous xref lookup based on the Prev trailer entry.
|
|
102
102
|
*
|
|
@@ -240,7 +240,10 @@ export class PdfXrefLookup {
|
|
|
240
240
|
*
|
|
241
241
|
* @param objects - Array of indirect objects to link
|
|
242
242
|
*/
|
|
243
|
-
linkIndirectObjects(objects) {
|
|
243
|
+
linkIndirectObjects(objects, offsetMap) {
|
|
244
|
+
// Use provided map or build one for O(1) lookup
|
|
245
|
+
const byOffset = offsetMap ??
|
|
246
|
+
new Map(objects.map((obj) => [obj.offset.resolve(), obj]));
|
|
244
247
|
for (const entry of this.entriesValues) {
|
|
245
248
|
if (entry instanceof PdfXRefStreamCompressedEntry) {
|
|
246
249
|
continue;
|
|
@@ -248,7 +251,7 @@ export class PdfXrefLookup {
|
|
|
248
251
|
if (!entry.inUse) {
|
|
249
252
|
continue;
|
|
250
253
|
}
|
|
251
|
-
const
|
|
254
|
+
const matchedObject = byOffset.get(entry.byteOffset.value);
|
|
252
255
|
if (!matchedObject ||
|
|
253
256
|
matchedObject.objectNumber !== entry.objectNumber.value) {
|
|
254
257
|
continue;
|