pdf-lite 1.3.2 → 1.4.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/acroform/PdfAcroForm.d.ts +63 -0
- package/dist/acroform/PdfAcroForm.js +279 -0
- package/dist/acroform/PdfFontEncodingCache.d.ts +16 -0
- package/dist/acroform/PdfFontEncodingCache.js +75 -0
- package/dist/acroform/acroform.d.ts +7 -449
- package/dist/acroform/acroform.js +5 -1612
- package/dist/acroform/appearance/PdfAppearanceStream.d.ts +15 -0
- package/dist/acroform/appearance/PdfAppearanceStream.js +32 -0
- package/dist/acroform/appearance/PdfButtonAppearanceStream.d.ts +12 -0
- package/dist/acroform/appearance/PdfButtonAppearanceStream.js +54 -0
- package/dist/acroform/appearance/PdfChoiceAppearanceStream.d.ts +15 -0
- package/dist/acroform/appearance/PdfChoiceAppearanceStream.js +48 -0
- package/dist/acroform/appearance/PdfTextAppearanceStream.d.ts +17 -0
- package/dist/acroform/appearance/PdfTextAppearanceStream.js +75 -0
- package/dist/acroform/appearance/index.d.ts +4 -0
- package/dist/acroform/appearance/index.js +4 -0
- package/dist/acroform/fields/PdfButtonFormField.d.ts +9 -0
- package/dist/acroform/fields/PdfButtonFormField.js +35 -0
- package/dist/acroform/fields/PdfChoiceFormField.d.ts +9 -0
- package/dist/acroform/fields/PdfChoiceFormField.js +46 -0
- package/dist/acroform/fields/PdfDefaultAppearance.d.ts +23 -0
- package/dist/acroform/fields/PdfDefaultAppearance.js +68 -0
- package/dist/acroform/fields/PdfFormField.d.ts +119 -0
- package/dist/acroform/fields/PdfFormField.js +499 -0
- package/dist/acroform/fields/PdfFormFieldFlags.d.ts +46 -0
- package/dist/acroform/fields/PdfFormFieldFlags.js +128 -0
- package/dist/acroform/fields/PdfSignatureFormField.d.ts +7 -0
- package/dist/acroform/fields/PdfSignatureFormField.js +12 -0
- package/dist/acroform/fields/PdfTextFormField.d.ts +10 -0
- package/dist/acroform/fields/PdfTextFormField.js +52 -0
- package/dist/acroform/fields/index.d.ts +8 -0
- package/dist/acroform/fields/index.js +8 -0
- package/dist/acroform/fields/types.d.ts +21 -0
- package/dist/acroform/fields/types.js +9 -0
- package/dist/acroform/index.d.ts +5 -1
- package/dist/acroform/index.js +5 -1
- package/dist/acroform/manager.d.ts +7 -0
- package/dist/acroform/manager.js +12 -0
- package/dist/acroform/xfa/PdfXfaData.d.ts +20 -0
- package/dist/acroform/xfa/PdfXfaData.js +68 -0
- package/dist/acroform/xfa/PdfXfaForm.d.ts +12 -0
- package/dist/acroform/xfa/PdfXfaForm.js +64 -0
- package/dist/acroform/xfa/index.d.ts +3 -0
- package/dist/acroform/xfa/index.js +2 -0
- package/dist/annotations/PdfAnnotation.d.ts +40 -0
- package/dist/annotations/PdfAnnotation.js +105 -0
- package/dist/annotations/PdfAnnotationFlags.d.ts +25 -0
- package/dist/annotations/PdfAnnotationFlags.js +94 -0
- package/dist/annotations/PdfAnnotationWriter.d.ts +20 -0
- package/dist/annotations/PdfAnnotationWriter.js +76 -0
- package/dist/annotations/PdfWidgetAnnotation.d.ts +15 -0
- package/dist/annotations/PdfWidgetAnnotation.js +37 -0
- package/dist/annotations/index.d.ts +4 -0
- package/dist/annotations/index.js +4 -0
- package/dist/core/objects/pdf-array.d.ts +1 -1
- package/dist/core/objects/pdf-array.js +3 -2
- package/dist/core/objects/pdf-boolean.d.ts +1 -1
- package/dist/core/objects/pdf-boolean.js +3 -2
- package/dist/core/objects/pdf-comment.d.ts +1 -1
- package/dist/core/objects/pdf-comment.js +1 -1
- package/dist/core/objects/pdf-dictionary.d.ts +1 -1
- package/dist/core/objects/pdf-dictionary.js +3 -2
- package/dist/core/objects/pdf-hexadecimal.d.ts +1 -1
- package/dist/core/objects/pdf-hexadecimal.js +3 -2
- package/dist/core/objects/pdf-indirect-object.d.ts +1 -1
- package/dist/core/objects/pdf-indirect-object.js +1 -1
- package/dist/core/objects/pdf-name.d.ts +1 -1
- package/dist/core/objects/pdf-name.js +3 -2
- package/dist/core/objects/pdf-null.d.ts +1 -1
- package/dist/core/objects/pdf-null.js +3 -2
- package/dist/core/objects/pdf-number.d.ts +1 -1
- package/dist/core/objects/pdf-number.js +3 -2
- package/dist/core/objects/pdf-object-reference.d.ts +1 -1
- package/dist/core/objects/pdf-object-reference.js +3 -2
- package/dist/core/objects/pdf-object.d.ts +3 -1
- package/dist/core/objects/pdf-object.js +6 -0
- package/dist/core/objects/pdf-start-xref.d.ts +1 -1
- package/dist/core/objects/pdf-start-xref.js +3 -2
- package/dist/core/objects/pdf-stream.d.ts +3 -3
- package/dist/core/objects/pdf-stream.js +39 -14
- package/dist/core/objects/pdf-string.d.ts +2 -1
- package/dist/core/objects/pdf-string.js +17 -2
- package/dist/core/objects/pdf-trailer.d.ts +1 -1
- package/dist/core/objects/pdf-trailer.js +3 -2
- package/dist/core/objects/pdf-xref-table.d.ts +3 -3
- package/dist/core/objects/pdf-xref-table.js +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/pdf/pdf-document.d.ts +14 -11
- package/dist/pdf/pdf-document.js +36 -26
- package/dist/pdf/pdf-revision.d.ts +1 -1
- package/dist/pdf/pdf-revision.js +1 -1
- package/dist/pdf/pdf-xref-lookup.d.ts +8 -0
- package/dist/pdf/pdf-xref-lookup.js +12 -0
- package/dist/security/handlers/base.js +3 -0
- package/package.json +1 -1
- package/dist/xfa/index.d.ts +0 -1
- package/dist/xfa/index.js +0 -1
- package/dist/xfa/manager.d.ts +0 -44
- package/dist/xfa/manager.js +0 -136
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { PdfDocument } from '../pdf/pdf-document.js';
|
|
2
|
+
import { PdfDictionary } from '../core/objects/pdf-dictionary.js';
|
|
3
|
+
import { PdfArray } from '../core/objects/pdf-array.js';
|
|
4
|
+
import { PdfString } from '../core/objects/pdf-string.js';
|
|
5
|
+
import { PdfObjectReference } from '../core/objects/pdf-object-reference.js';
|
|
6
|
+
import { PdfIndirectObject } from '../core/objects/pdf-indirect-object.js';
|
|
7
|
+
import { PdfBoolean } from '../core/objects/pdf-boolean.js';
|
|
8
|
+
import { PdfNumber } from '../core/objects/pdf-number.js';
|
|
9
|
+
import { PdfFormField } from './fields/PdfFormField.js';
|
|
10
|
+
import './fields/PdfTextFormField.js';
|
|
11
|
+
import './fields/PdfButtonFormField.js';
|
|
12
|
+
import './fields/PdfChoiceFormField.js';
|
|
13
|
+
import './fields/PdfSignatureFormField.js';
|
|
14
|
+
import type { FormContext } from './fields/types.js';
|
|
15
|
+
export type PdfDefaultResourcesDictionary = PdfDictionary<{
|
|
16
|
+
Font?: PdfDictionary;
|
|
17
|
+
ProcSet?: PdfArray;
|
|
18
|
+
ExtGState?: PdfDictionary;
|
|
19
|
+
ColorSpace?: PdfDictionary;
|
|
20
|
+
Pattern?: PdfDictionary;
|
|
21
|
+
Shading?: PdfDictionary;
|
|
22
|
+
XObject?: PdfDictionary;
|
|
23
|
+
}>;
|
|
24
|
+
export declare class PdfAcroForm<T extends Record<string, string> = Record<string, string>> extends PdfIndirectObject<PdfDictionary<{
|
|
25
|
+
Fields: PdfArray<PdfObjectReference>;
|
|
26
|
+
NeedAppearances?: PdfBoolean;
|
|
27
|
+
SigFlags?: PdfNumber;
|
|
28
|
+
CO?: PdfArray<PdfObjectReference>;
|
|
29
|
+
DR?: PdfDefaultResourcesDictionary;
|
|
30
|
+
DA?: PdfString;
|
|
31
|
+
Q?: PdfNumber;
|
|
32
|
+
XFA?: PdfDictionary;
|
|
33
|
+
}>> implements FormContext<PdfFormField> {
|
|
34
|
+
fields: PdfFormField[];
|
|
35
|
+
private _fontEncodingCache?;
|
|
36
|
+
private document?;
|
|
37
|
+
constructor(options?: {
|
|
38
|
+
other?: PdfIndirectObject;
|
|
39
|
+
fields?: PdfFormField[];
|
|
40
|
+
document?: PdfDocument;
|
|
41
|
+
});
|
|
42
|
+
private get fontEncodingCache();
|
|
43
|
+
get fontEncodingMaps(): Map<string, Map<number, string>>;
|
|
44
|
+
isModified(): boolean;
|
|
45
|
+
get needAppearances(): boolean;
|
|
46
|
+
set needAppearances(value: boolean);
|
|
47
|
+
get signatureFlags(): number;
|
|
48
|
+
set signatureFlags(flags: number);
|
|
49
|
+
get defaultAppearance(): string | null;
|
|
50
|
+
set defaultAppearance(da: string);
|
|
51
|
+
get defaultQuadding(): number;
|
|
52
|
+
set defaultQuadding(q: number);
|
|
53
|
+
get defaultResources(): PdfDefaultResourcesDictionary | null;
|
|
54
|
+
set defaultResources(resources: PdfDefaultResourcesDictionary | null);
|
|
55
|
+
setValues(values: Partial<T>): void;
|
|
56
|
+
importData(fields: T): void;
|
|
57
|
+
exportData(): Partial<T>;
|
|
58
|
+
getFontEncodingMap(fontName: string): Promise<Map<number, string> | null>;
|
|
59
|
+
static fromDocument(document: PdfDocument): Promise<PdfAcroForm | null>;
|
|
60
|
+
private cacheAllFontEncodings;
|
|
61
|
+
private updatePageAnnotations;
|
|
62
|
+
write(document: PdfDocument): Promise<void>;
|
|
63
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { PdfDictionary } from '../core/objects/pdf-dictionary.js';
|
|
2
|
+
import { PdfArray } from '../core/objects/pdf-array.js';
|
|
3
|
+
import { PdfString } from '../core/objects/pdf-string.js';
|
|
4
|
+
import { PdfObjectReference } from '../core/objects/pdf-object-reference.js';
|
|
5
|
+
import { PdfIndirectObject } from '../core/objects/pdf-indirect-object.js';
|
|
6
|
+
import { PdfBoolean } from '../core/objects/pdf-boolean.js';
|
|
7
|
+
import { PdfNumber } from '../core/objects/pdf-number.js';
|
|
8
|
+
import { PdfFontEncodingCache } from './PdfFontEncodingCache.js';
|
|
9
|
+
import { PdfAnnotationWriter } from '../annotations/PdfAnnotationWriter.js';
|
|
10
|
+
import { PdfXfaForm } from './xfa/PdfXfaForm.js';
|
|
11
|
+
import { PdfFormField } from './fields/PdfFormField.js';
|
|
12
|
+
// Import subclasses to trigger static registration blocks
|
|
13
|
+
import './fields/PdfTextFormField.js';
|
|
14
|
+
import './fields/PdfButtonFormField.js';
|
|
15
|
+
import './fields/PdfChoiceFormField.js';
|
|
16
|
+
import './fields/PdfSignatureFormField.js';
|
|
17
|
+
export class PdfAcroForm extends PdfIndirectObject {
|
|
18
|
+
fields;
|
|
19
|
+
_fontEncodingCache;
|
|
20
|
+
document;
|
|
21
|
+
constructor(options) {
|
|
22
|
+
super(options?.other ??
|
|
23
|
+
new PdfIndirectObject({
|
|
24
|
+
content: new PdfDictionary(),
|
|
25
|
+
}));
|
|
26
|
+
this.fields = options?.fields ?? [];
|
|
27
|
+
this.document = options?.document;
|
|
28
|
+
}
|
|
29
|
+
get fontEncodingCache() {
|
|
30
|
+
if (!this._fontEncodingCache) {
|
|
31
|
+
this._fontEncodingCache = new PdfFontEncodingCache(this.document, this.defaultResources);
|
|
32
|
+
}
|
|
33
|
+
return this._fontEncodingCache;
|
|
34
|
+
}
|
|
35
|
+
get fontEncodingMaps() {
|
|
36
|
+
return this.fontEncodingCache.fontEncodingMaps;
|
|
37
|
+
}
|
|
38
|
+
isModified() {
|
|
39
|
+
return this.content.isModified();
|
|
40
|
+
}
|
|
41
|
+
get needAppearances() {
|
|
42
|
+
return (this.content.get('NeedAppearances')?.as(PdfBoolean)?.value ?? false);
|
|
43
|
+
}
|
|
44
|
+
set needAppearances(value) {
|
|
45
|
+
this.content.set('NeedAppearances', new PdfBoolean(value));
|
|
46
|
+
}
|
|
47
|
+
get signatureFlags() {
|
|
48
|
+
return this.content.get('SigFlags')?.as(PdfNumber)?.value ?? 0;
|
|
49
|
+
}
|
|
50
|
+
set signatureFlags(flags) {
|
|
51
|
+
this.content.set('SigFlags', new PdfNumber(flags));
|
|
52
|
+
}
|
|
53
|
+
get defaultAppearance() {
|
|
54
|
+
return this.content.get('DA')?.as(PdfString)?.value ?? null;
|
|
55
|
+
}
|
|
56
|
+
set defaultAppearance(da) {
|
|
57
|
+
this.content.set('DA', new PdfString(da));
|
|
58
|
+
}
|
|
59
|
+
get defaultQuadding() {
|
|
60
|
+
return this.content.get('Q')?.as(PdfNumber)?.value ?? 0;
|
|
61
|
+
}
|
|
62
|
+
set defaultQuadding(q) {
|
|
63
|
+
this.content.set('Q', new PdfNumber(q));
|
|
64
|
+
}
|
|
65
|
+
get defaultResources() {
|
|
66
|
+
return this.content.get('DR')?.as(PdfDictionary) ?? null;
|
|
67
|
+
}
|
|
68
|
+
set defaultResources(resources) {
|
|
69
|
+
if (resources === null) {
|
|
70
|
+
this.content.delete('DR');
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.content.set('DR', resources);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
setValues(values) {
|
|
77
|
+
for (const field of this.fields) {
|
|
78
|
+
const name = field.name;
|
|
79
|
+
if (name in values && values[name] !== undefined) {
|
|
80
|
+
field.value = values[name];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
importData(fields) {
|
|
85
|
+
for (const field of this.fields) {
|
|
86
|
+
const name = field.name;
|
|
87
|
+
if (name && name in fields) {
|
|
88
|
+
field.value = fields[name];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exportData() {
|
|
93
|
+
const result = {};
|
|
94
|
+
for (const field of this.fields) {
|
|
95
|
+
const name = field.name;
|
|
96
|
+
if (name) {
|
|
97
|
+
result[name] = field.value;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
async getFontEncodingMap(fontName) {
|
|
103
|
+
return this.fontEncodingCache.getFontEncodingMap(fontName);
|
|
104
|
+
}
|
|
105
|
+
static async fromDocument(document) {
|
|
106
|
+
const catalog = document.root;
|
|
107
|
+
if (!catalog)
|
|
108
|
+
return null;
|
|
109
|
+
const acroFormRef = catalog.content.get('AcroForm');
|
|
110
|
+
if (!acroFormRef)
|
|
111
|
+
return null;
|
|
112
|
+
let acroFormDict;
|
|
113
|
+
let acroFormContainer;
|
|
114
|
+
if (acroFormRef instanceof PdfObjectReference) {
|
|
115
|
+
const acroFormObject = await document.readObject({
|
|
116
|
+
objectNumber: acroFormRef.objectNumber,
|
|
117
|
+
generationNumber: acroFormRef.generationNumber,
|
|
118
|
+
});
|
|
119
|
+
if (!acroFormObject)
|
|
120
|
+
return null;
|
|
121
|
+
if (!(acroFormObject.content instanceof PdfDictionary))
|
|
122
|
+
throw new Error('AcroForm content must be a dictionary');
|
|
123
|
+
acroFormDict = acroFormObject.content;
|
|
124
|
+
acroFormContainer = acroFormObject;
|
|
125
|
+
}
|
|
126
|
+
else if (acroFormRef instanceof PdfDictionary) {
|
|
127
|
+
acroFormDict = acroFormRef;
|
|
128
|
+
acroFormContainer = new PdfIndirectObject({ content: acroFormDict });
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
const acroForm = new PdfAcroForm({ other: acroFormContainer, document });
|
|
134
|
+
// Pre-cache font encoding maps for all fonts used in fields
|
|
135
|
+
await acroForm.cacheAllFontEncodings();
|
|
136
|
+
const fields = new Map();
|
|
137
|
+
const getFields = async (fieldRefs, parent) => {
|
|
138
|
+
for (const fieldRef of fieldRefs) {
|
|
139
|
+
const refKey = fieldRef.toString().trim();
|
|
140
|
+
if (fields.has(refKey)) {
|
|
141
|
+
fields.get(refKey).parent = parent;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const fieldObject = await document.readObject({
|
|
145
|
+
objectNumber: fieldRef.objectNumber,
|
|
146
|
+
generationNumber: fieldRef.generationNumber,
|
|
147
|
+
});
|
|
148
|
+
if (!fieldObject)
|
|
149
|
+
continue;
|
|
150
|
+
if (!(fieldObject.content instanceof PdfDictionary))
|
|
151
|
+
continue;
|
|
152
|
+
const field = PdfFormField.create({
|
|
153
|
+
other: fieldObject,
|
|
154
|
+
form: acroForm,
|
|
155
|
+
parent,
|
|
156
|
+
});
|
|
157
|
+
const kids = field.kids;
|
|
158
|
+
if (kids.length > 0) {
|
|
159
|
+
await getFields(kids, field);
|
|
160
|
+
}
|
|
161
|
+
acroForm.fields.push(field);
|
|
162
|
+
fields.set(refKey, field);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const fieldsArray = new PdfArray();
|
|
166
|
+
if (acroForm.content.get('Fields') instanceof PdfArray) {
|
|
167
|
+
fieldsArray.items.push(...acroForm.content
|
|
168
|
+
.get('Fields')
|
|
169
|
+
.as((PdfArray)).items);
|
|
170
|
+
}
|
|
171
|
+
else if (acroForm.content.get('Fields') instanceof PdfObjectReference) {
|
|
172
|
+
const fieldsObj = await document.readObject({
|
|
173
|
+
objectNumber: acroForm.content
|
|
174
|
+
.get('Fields')
|
|
175
|
+
.as(PdfObjectReference).objectNumber,
|
|
176
|
+
generationNumber: acroForm.content
|
|
177
|
+
.get('Fields')
|
|
178
|
+
.as(PdfObjectReference).generationNumber,
|
|
179
|
+
});
|
|
180
|
+
if (fieldsObj && fieldsObj.content instanceof PdfArray) {
|
|
181
|
+
fieldsArray.items.push(...fieldsObj.content.as((PdfArray)).items);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
await getFields(fieldsArray.items);
|
|
185
|
+
// Reset field-level modified flag so only explicitly changed fields are detected
|
|
186
|
+
for (const field of acroForm.fields) {
|
|
187
|
+
field.setModified(false);
|
|
188
|
+
}
|
|
189
|
+
return acroForm;
|
|
190
|
+
}
|
|
191
|
+
async cacheAllFontEncodings() {
|
|
192
|
+
await this.fontEncodingCache.cacheAllFontEncodings(this.fields);
|
|
193
|
+
}
|
|
194
|
+
async updatePageAnnotations(document, fieldsByPage) {
|
|
195
|
+
await PdfAnnotationWriter.updatePageAnnotations(document, fieldsByPage);
|
|
196
|
+
}
|
|
197
|
+
async write(document) {
|
|
198
|
+
const catalog = document.root;
|
|
199
|
+
const isIncremental = document.isIncremental();
|
|
200
|
+
document.setIncremental(true);
|
|
201
|
+
const xfaForm = await PdfXfaForm.fromDocument(document);
|
|
202
|
+
if (xfaForm) {
|
|
203
|
+
// Only send fields whose value was explicitly changed (field.isModified())
|
|
204
|
+
const xfaFields = this.fields
|
|
205
|
+
.filter((f) => f.isModified() && f.fieldType !== 'Signature' && f.name)
|
|
206
|
+
.map((f) => ({ name: f.name, value: f.value }));
|
|
207
|
+
if (xfaFields.length > 0) {
|
|
208
|
+
xfaForm.datasets?.updateFields(xfaFields);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const fieldsArray = new PdfArray();
|
|
212
|
+
this.content.set('Fields', fieldsArray);
|
|
213
|
+
const fieldsByPage = new Map();
|
|
214
|
+
// Phase 1: add appearance streams standalone (PdfStream — cannot go in ObjStm)
|
|
215
|
+
// and collect field dicts for ObjStm batching.
|
|
216
|
+
const compressibleFields = [];
|
|
217
|
+
for (const field of this.fields) {
|
|
218
|
+
if (field.content.isModified()) {
|
|
219
|
+
const appearances = field.getAppearanceStreamsForWriting();
|
|
220
|
+
if (appearances) {
|
|
221
|
+
document.add(appearances.primary);
|
|
222
|
+
if (appearances.secondary) {
|
|
223
|
+
document.add(appearances.secondary);
|
|
224
|
+
}
|
|
225
|
+
field.setAppearanceReference(appearances.primary.reference, appearances.secondary?.reference);
|
|
226
|
+
if (!field.print) {
|
|
227
|
+
field.print = true;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
compressibleFields.push(field);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// Phase 2: pack field dicts into ObjStm — pre-assigns their object numbers.
|
|
234
|
+
document.addObjectsAsStream(compressibleFields);
|
|
235
|
+
// Phase 3: build fieldsArray now that field object numbers are stable.
|
|
236
|
+
for (const field of this.fields) {
|
|
237
|
+
let fieldReference;
|
|
238
|
+
if (field.content.isModified()) {
|
|
239
|
+
fieldReference = new PdfObjectReference(field.objectNumber, field.generationNumber);
|
|
240
|
+
const parentRef = field.parentRef;
|
|
241
|
+
const isWidget = field.isWidget;
|
|
242
|
+
if (parentRef && isWidget) {
|
|
243
|
+
const pageKey = `${parentRef.objectNumber}_${parentRef.generationNumber}`;
|
|
244
|
+
if (!fieldsByPage.has(pageKey)) {
|
|
245
|
+
fieldsByPage.set(pageKey, {
|
|
246
|
+
pageRef: parentRef,
|
|
247
|
+
fieldRefs: [],
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
fieldsByPage.get(pageKey).fieldRefs.push(fieldReference);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
fieldReference = field.reference;
|
|
255
|
+
}
|
|
256
|
+
fieldsArray.push(fieldReference);
|
|
257
|
+
}
|
|
258
|
+
await this.updatePageAnnotations(document, fieldsByPage);
|
|
259
|
+
// Phase 4: pack AcroForm dict into ObjStm AFTER fieldsArray is populated,
|
|
260
|
+
// so the dict is serialized with the correct Fields array.
|
|
261
|
+
if (this.isModified()) {
|
|
262
|
+
document.addObjectsAsStream([this]);
|
|
263
|
+
if (!catalog.content.has('AcroForm')) {
|
|
264
|
+
let updatableCatalog = catalog;
|
|
265
|
+
if (catalog.isImmutable()) {
|
|
266
|
+
updatableCatalog = catalog.clone();
|
|
267
|
+
document.add(updatableCatalog);
|
|
268
|
+
}
|
|
269
|
+
updatableCatalog.content.set('AcroForm', this.reference);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// XFA datasets stream — PdfXfaData extends PdfIndirectObject<PdfStream>, must stay standalone
|
|
273
|
+
if (xfaForm) {
|
|
274
|
+
xfaForm.write(document);
|
|
275
|
+
}
|
|
276
|
+
await document.commit();
|
|
277
|
+
document.setIncremental(isIncremental);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { PdfDocument } from '../pdf/pdf-document.js';
|
|
2
|
+
import { PdfDictionary } from '../core/objects/pdf-dictionary.js';
|
|
3
|
+
import type { PdfDefaultResourcesDictionary } from './acroform.js';
|
|
4
|
+
/**
|
|
5
|
+
* Resolves and caches font encoding maps from the form's default resources.
|
|
6
|
+
*/
|
|
7
|
+
export declare class PdfFontEncodingCache {
|
|
8
|
+
readonly fontEncodingMaps: Map<string, Map<number, string>>;
|
|
9
|
+
private document?;
|
|
10
|
+
private defaultResources;
|
|
11
|
+
constructor(document: PdfDocument | undefined, defaultResources: PdfDefaultResourcesDictionary | null);
|
|
12
|
+
getFontEncodingMap(fontName: string): Promise<Map<number, string> | null>;
|
|
13
|
+
cacheAllFontEncodings(fields: Array<{
|
|
14
|
+
content: PdfDictionary;
|
|
15
|
+
}>): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { PdfDictionary } from '../core/objects/pdf-dictionary.js';
|
|
2
|
+
import { PdfArray } from '../core/objects/pdf-array.js';
|
|
3
|
+
import { PdfString } from '../core/objects/pdf-string.js';
|
|
4
|
+
import { PdfObjectReference } from '../core/objects/pdf-object-reference.js';
|
|
5
|
+
import { buildEncodingMap } from '../utils/decodeWithFontEncoding.js';
|
|
6
|
+
/**
|
|
7
|
+
* Resolves and caches font encoding maps from the form's default resources.
|
|
8
|
+
*/
|
|
9
|
+
export class PdfFontEncodingCache {
|
|
10
|
+
fontEncodingMaps = new Map();
|
|
11
|
+
document;
|
|
12
|
+
defaultResources;
|
|
13
|
+
constructor(document, defaultResources) {
|
|
14
|
+
this.document = document;
|
|
15
|
+
this.defaultResources = defaultResources;
|
|
16
|
+
}
|
|
17
|
+
async getFontEncodingMap(fontName) {
|
|
18
|
+
if (this.fontEncodingMaps.has(fontName)) {
|
|
19
|
+
return this.fontEncodingMaps.get(fontName);
|
|
20
|
+
}
|
|
21
|
+
const dr = this.defaultResources;
|
|
22
|
+
if (!dr)
|
|
23
|
+
return null;
|
|
24
|
+
const fonts = dr.get('Font')?.as(PdfDictionary);
|
|
25
|
+
if (!fonts)
|
|
26
|
+
return null;
|
|
27
|
+
const fontRef = fonts.get(fontName)?.as(PdfObjectReference);
|
|
28
|
+
if (!fontRef || !this.document)
|
|
29
|
+
return null;
|
|
30
|
+
const fontObj = await this.document.readObject({
|
|
31
|
+
objectNumber: fontRef.objectNumber,
|
|
32
|
+
generationNumber: fontRef.generationNumber,
|
|
33
|
+
});
|
|
34
|
+
if (!fontObj)
|
|
35
|
+
return null;
|
|
36
|
+
const fontDict = fontObj.content.as(PdfDictionary);
|
|
37
|
+
const encoding = fontDict.get('Encoding');
|
|
38
|
+
let encodingDict = null;
|
|
39
|
+
if (encoding instanceof PdfObjectReference) {
|
|
40
|
+
const encodingObj = await this.document.readObject({
|
|
41
|
+
objectNumber: encoding.objectNumber,
|
|
42
|
+
generationNumber: encoding.generationNumber,
|
|
43
|
+
});
|
|
44
|
+
encodingDict = encodingObj?.content.as(PdfDictionary) ?? null;
|
|
45
|
+
}
|
|
46
|
+
else if (encoding instanceof PdfDictionary) {
|
|
47
|
+
encodingDict = encoding;
|
|
48
|
+
}
|
|
49
|
+
if (!encodingDict)
|
|
50
|
+
return null;
|
|
51
|
+
const differences = encodingDict.get('Differences')?.as(PdfArray);
|
|
52
|
+
if (!differences)
|
|
53
|
+
return null;
|
|
54
|
+
const encodingMap = buildEncodingMap(differences);
|
|
55
|
+
if (!encodingMap)
|
|
56
|
+
return null;
|
|
57
|
+
this.fontEncodingMaps.set(fontName, encodingMap);
|
|
58
|
+
return encodingMap;
|
|
59
|
+
}
|
|
60
|
+
async cacheAllFontEncodings(fields) {
|
|
61
|
+
const fontNames = new Set();
|
|
62
|
+
for (const field of fields) {
|
|
63
|
+
const da = field.content.get('DA')?.as(PdfString)?.value;
|
|
64
|
+
if (da) {
|
|
65
|
+
const fontMatch = da.match(/\/(\w+)\s+[\d.]+\s+Tf/);
|
|
66
|
+
if (fontMatch) {
|
|
67
|
+
fontNames.add(fontMatch[1]);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
for (const fontName of fontNames) {
|
|
72
|
+
await this.getFontEncodingMap(fontName);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|