pdfnova 1.0.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/README.md +336 -0
- package/dist/AnnotationReader-ADHPZ3V5.mjs +3 -0
- package/dist/AnnotationReader-ADHPZ3V5.mjs.map +1 -0
- package/dist/AnnotationReader-C5XLXGWS.cjs +12 -0
- package/dist/AnnotationReader-C5XLXGWS.cjs.map +1 -0
- package/dist/AnnotationWriter-N3Y4KTPI.cjs +12 -0
- package/dist/AnnotationWriter-N3Y4KTPI.cjs.map +1 -0
- package/dist/AnnotationWriter-XWY5N6AZ.mjs +3 -0
- package/dist/AnnotationWriter-XWY5N6AZ.mjs.map +1 -0
- package/dist/FormFiller-2O4MOQYV.cjs +12 -0
- package/dist/FormFiller-2O4MOQYV.cjs.map +1 -0
- package/dist/FormFiller-6DLWMRN5.mjs +3 -0
- package/dist/FormFiller-6DLWMRN5.mjs.map +1 -0
- package/dist/FormFlattener-5MWLLH7W.cjs +12 -0
- package/dist/FormFlattener-5MWLLH7W.cjs.map +1 -0
- package/dist/FormFlattener-YQRQ3QOY.mjs +3 -0
- package/dist/FormFlattener-YQRQ3QOY.mjs.map +1 -0
- package/dist/FormReader-QAEDFD77.cjs +13 -0
- package/dist/FormReader-QAEDFD77.cjs.map +1 -0
- package/dist/FormReader-XEF3T5LD.mjs +4 -0
- package/dist/FormReader-XEF3T5LD.mjs.map +1 -0
- package/dist/SignatureVerifier-2IR7UQGU.mjs +3 -0
- package/dist/SignatureVerifier-2IR7UQGU.mjs.map +1 -0
- package/dist/SignatureVerifier-4KWQA7X6.cjs +12 -0
- package/dist/SignatureVerifier-4KWQA7X6.cjs.map +1 -0
- package/dist/WasmMock-2I3GVRQF.mjs +397 -0
- package/dist/WasmMock-2I3GVRQF.mjs.map +1 -0
- package/dist/WasmMock-OYPV4J6B.cjs +399 -0
- package/dist/WasmMock-OYPV4J6B.cjs.map +1 -0
- package/dist/chunk-2OWW5BYD.mjs +1847 -0
- package/dist/chunk-2OWW5BYD.mjs.map +1 -0
- package/dist/chunk-2YFCKMVK.cjs +72 -0
- package/dist/chunk-2YFCKMVK.cjs.map +1 -0
- package/dist/chunk-7FGOUG4Z.cjs +51 -0
- package/dist/chunk-7FGOUG4Z.cjs.map +1 -0
- package/dist/chunk-CPMUWWNS.cjs +44 -0
- package/dist/chunk-CPMUWWNS.cjs.map +1 -0
- package/dist/chunk-DVMAQ62T.cjs +109 -0
- package/dist/chunk-DVMAQ62T.cjs.map +1 -0
- package/dist/chunk-ETSUOY4U.cjs +104 -0
- package/dist/chunk-ETSUOY4U.cjs.map +1 -0
- package/dist/chunk-FD5RTJ5W.mjs +60 -0
- package/dist/chunk-FD5RTJ5W.mjs.map +1 -0
- package/dist/chunk-FO3DQLVB.mjs +42 -0
- package/dist/chunk-FO3DQLVB.mjs.map +1 -0
- package/dist/chunk-G2FA6VKV.cjs +62 -0
- package/dist/chunk-G2FA6VKV.cjs.map +1 -0
- package/dist/chunk-G7575D5X.mjs +67 -0
- package/dist/chunk-G7575D5X.mjs.map +1 -0
- package/dist/chunk-I7OBHZLB.mjs +75 -0
- package/dist/chunk-I7OBHZLB.mjs.map +1 -0
- package/dist/chunk-INA3KRJK.cjs +1863 -0
- package/dist/chunk-INA3KRJK.cjs.map +1 -0
- package/dist/chunk-RZFKZ2CA.cjs +77 -0
- package/dist/chunk-RZFKZ2CA.cjs.map +1 -0
- package/dist/chunk-VRJQZOCH.mjs +107 -0
- package/dist/chunk-VRJQZOCH.mjs.map +1 -0
- package/dist/chunk-X53667JS.mjs +102 -0
- package/dist/chunk-X53667JS.mjs.map +1 -0
- package/dist/chunk-XEHKVFPJ.mjs +49 -0
- package/dist/chunk-XEHKVFPJ.mjs.map +1 -0
- package/dist/index.cjs +112 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +103 -0
- package/dist/index.d.ts +103 -0
- package/dist/index.mjs +14 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lite-CMz-Yosm.d.cts +662 -0
- package/dist/lite-CMz-Yosm.d.ts +662 -0
- package/dist/lite.cjs +70 -0
- package/dist/lite.cjs.map +1 -0
- package/dist/lite.d.cts +1 -0
- package/dist/lite.d.ts +1 -0
- package/dist/lite.mjs +8 -0
- package/dist/lite.mjs.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/annotations/AnnotationReader.ts
|
|
4
|
+
var AnnotationReader = class {
|
|
5
|
+
wasm;
|
|
6
|
+
bridge;
|
|
7
|
+
constructor(wasm, bridge) {
|
|
8
|
+
this.wasm = wasm;
|
|
9
|
+
this.bridge = bridge;
|
|
10
|
+
}
|
|
11
|
+
readAnnotations(pagePtr) {
|
|
12
|
+
if (!this.wasm._FPDFPage_GetAnnotCount) return [];
|
|
13
|
+
const count = this.wasm._FPDFPage_GetAnnotCount(pagePtr);
|
|
14
|
+
const annotations = [];
|
|
15
|
+
for (let i = 0; i < count; i++) {
|
|
16
|
+
const annotPtr = this.wasm._FPDFPage_GetAnnot(pagePtr, i);
|
|
17
|
+
if (annotPtr === 0) continue;
|
|
18
|
+
try {
|
|
19
|
+
const data = this._readAnnotation(annotPtr, i);
|
|
20
|
+
if (data) annotations.push(data);
|
|
21
|
+
} finally {
|
|
22
|
+
this.wasm._FPDFPage_CloseAnnot(annotPtr);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return annotations;
|
|
26
|
+
}
|
|
27
|
+
_readAnnotation(annotPtr, index) {
|
|
28
|
+
const subtype = this.wasm._FPDFAnnot_GetSubtype(annotPtr);
|
|
29
|
+
const type = subtype;
|
|
30
|
+
const rect = this._getRect(annotPtr);
|
|
31
|
+
if (!rect) return null;
|
|
32
|
+
const color = this._getColor(annotPtr);
|
|
33
|
+
const contents = this.bridge.getAnnotStringValue(annotPtr, "Contents");
|
|
34
|
+
const author = this.bridge.getAnnotStringValue(annotPtr, "T");
|
|
35
|
+
const modDate = this.bridge.getAnnotStringValue(annotPtr, "M");
|
|
36
|
+
const attachmentPoints = this._getAttachmentPoints(annotPtr);
|
|
37
|
+
return {
|
|
38
|
+
index,
|
|
39
|
+
type,
|
|
40
|
+
rect,
|
|
41
|
+
color: color ?? void 0,
|
|
42
|
+
contents: contents || void 0,
|
|
43
|
+
author: author || void 0,
|
|
44
|
+
modificationDate: modDate || void 0,
|
|
45
|
+
attachmentPoints: attachmentPoints.length > 0 ? attachmentPoints : void 0
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
_getRect(annotPtr) {
|
|
49
|
+
const rectBuf = this.wasm._malloc(32);
|
|
50
|
+
const ok = this.wasm._FPDFAnnot_GetRect(annotPtr, rectBuf);
|
|
51
|
+
if (!ok) {
|
|
52
|
+
this.wasm._free(rectBuf);
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const rect = {
|
|
56
|
+
left: this.wasm.HEAPF64[rectBuf >> 3],
|
|
57
|
+
bottom: this.wasm.HEAPF64[rectBuf + 8 >> 3],
|
|
58
|
+
right: this.wasm.HEAPF64[rectBuf + 16 >> 3],
|
|
59
|
+
top: this.wasm.HEAPF64[rectBuf + 24 >> 3]
|
|
60
|
+
};
|
|
61
|
+
this.wasm._free(rectBuf);
|
|
62
|
+
return rect;
|
|
63
|
+
}
|
|
64
|
+
_getColor(annotPtr) {
|
|
65
|
+
const rPtr = this.wasm._malloc(4);
|
|
66
|
+
const gPtr = this.wasm._malloc(4);
|
|
67
|
+
const bPtr = this.wasm._malloc(4);
|
|
68
|
+
const aPtr = this.wasm._malloc(4);
|
|
69
|
+
const ok = this.wasm._FPDFAnnot_GetColor(annotPtr, 0, rPtr, gPtr, bPtr, aPtr);
|
|
70
|
+
if (!ok) {
|
|
71
|
+
this.bridge.freeAll(rPtr, gPtr, bPtr, aPtr);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const color = {
|
|
75
|
+
r: this.wasm.HEAPU32[rPtr >> 2],
|
|
76
|
+
g: this.wasm.HEAPU32[gPtr >> 2],
|
|
77
|
+
b: this.wasm.HEAPU32[bPtr >> 2],
|
|
78
|
+
a: this.wasm.HEAPU32[aPtr >> 2]
|
|
79
|
+
};
|
|
80
|
+
this.bridge.freeAll(rPtr, gPtr, bPtr, aPtr);
|
|
81
|
+
return color;
|
|
82
|
+
}
|
|
83
|
+
_getAttachmentPoints(annotPtr) {
|
|
84
|
+
if (!this.wasm._FPDFAnnot_CountAttachmentPoints) return [];
|
|
85
|
+
const count = this.wasm._FPDFAnnot_CountAttachmentPoints(annotPtr);
|
|
86
|
+
if (count <= 0) return [];
|
|
87
|
+
const points = [];
|
|
88
|
+
const buf = this.wasm._malloc(64);
|
|
89
|
+
for (let i = 0; i < count; i++) {
|
|
90
|
+
this.wasm._FPDFAnnot_GetAttachmentPoints(annotPtr, i, buf);
|
|
91
|
+
points.push({
|
|
92
|
+
x1: this.wasm.HEAPF64[buf >> 3],
|
|
93
|
+
y1: this.wasm.HEAPF64[buf + 8 >> 3],
|
|
94
|
+
x2: this.wasm.HEAPF64[buf + 16 >> 3],
|
|
95
|
+
y2: this.wasm.HEAPF64[buf + 24 >> 3],
|
|
96
|
+
x3: this.wasm.HEAPF64[buf + 32 >> 3],
|
|
97
|
+
y3: this.wasm.HEAPF64[buf + 40 >> 3],
|
|
98
|
+
x4: this.wasm.HEAPF64[buf + 48 >> 3],
|
|
99
|
+
y4: this.wasm.HEAPF64[buf + 56 >> 3]
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
this.wasm._free(buf);
|
|
103
|
+
return points;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
exports.AnnotationReader = AnnotationReader;
|
|
108
|
+
//# sourceMappingURL=chunk-DVMAQ62T.cjs.map
|
|
109
|
+
//# sourceMappingURL=chunk-DVMAQ62T.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/annotations/AnnotationReader.ts"],"names":[],"mappings":"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","file":"chunk-DVMAQ62T.cjs","sourcesContent":["import type { WasmModule, AnnotationData, AnnotationColor, AnnotationRect, AttachmentPoint } from '../types';\nimport { AnnotationType } from '../types';\nimport { WasmBridge } from '../core/WasmBridge';\n\n/**\n * Reads annotations from a PDF page using PDFium's FPDFAnnot_* APIs.\n */\nexport class AnnotationReader {\n private wasm: WasmModule;\n private bridge: WasmBridge;\n\n constructor(wasm: WasmModule, bridge: WasmBridge) {\n this.wasm = wasm;\n this.bridge = bridge;\n }\n\n readAnnotations(pagePtr: number): AnnotationData[] {\n if (!this.wasm._FPDFPage_GetAnnotCount) return [];\n\n const count = this.wasm._FPDFPage_GetAnnotCount(pagePtr);\n const annotations: AnnotationData[] = [];\n\n for (let i = 0; i < count; i++) {\n const annotPtr = this.wasm._FPDFPage_GetAnnot!(pagePtr, i);\n if (annotPtr === 0) continue;\n\n try {\n const data = this._readAnnotation(annotPtr, i);\n if (data) annotations.push(data);\n } finally {\n this.wasm._FPDFPage_CloseAnnot!(annotPtr);\n }\n }\n\n return annotations;\n }\n\n private _readAnnotation(annotPtr: number, index: number): AnnotationData | null {\n const subtype = this.wasm._FPDFAnnot_GetSubtype!(annotPtr);\n const type = subtype as AnnotationType;\n\n const rect = this._getRect(annotPtr);\n if (!rect) return null;\n\n const color = this._getColor(annotPtr);\n const contents = this.bridge.getAnnotStringValue(annotPtr, 'Contents');\n const author = this.bridge.getAnnotStringValue(annotPtr, 'T');\n const modDate = this.bridge.getAnnotStringValue(annotPtr, 'M');\n\n const attachmentPoints = this._getAttachmentPoints(annotPtr);\n\n return {\n index,\n type,\n rect,\n color: color ?? undefined,\n contents: contents || undefined,\n author: author || undefined,\n modificationDate: modDate || undefined,\n attachmentPoints: attachmentPoints.length > 0 ? attachmentPoints : undefined,\n };\n }\n\n private _getRect(annotPtr: number): AnnotationRect | null {\n const rectBuf = this.wasm._malloc(32); // 4 doubles\n const ok = this.wasm._FPDFAnnot_GetRect!(annotPtr, rectBuf);\n if (!ok) {\n this.wasm._free(rectBuf);\n return null;\n }\n\n const rect: AnnotationRect = {\n left: this.wasm.HEAPF64[rectBuf >> 3],\n bottom: this.wasm.HEAPF64[(rectBuf + 8) >> 3],\n right: this.wasm.HEAPF64[(rectBuf + 16) >> 3],\n top: this.wasm.HEAPF64[(rectBuf + 24) >> 3],\n };\n\n this.wasm._free(rectBuf);\n return rect;\n }\n\n private _getColor(annotPtr: number): AnnotationColor | null {\n const rPtr = this.wasm._malloc(4);\n const gPtr = this.wasm._malloc(4);\n const bPtr = this.wasm._malloc(4);\n const aPtr = this.wasm._malloc(4);\n\n // type 0 = color, 1 = interior color\n const ok = this.wasm._FPDFAnnot_GetColor!(annotPtr, 0, rPtr, gPtr, bPtr, aPtr);\n\n if (!ok) {\n this.bridge.freeAll(rPtr, gPtr, bPtr, aPtr);\n return null;\n }\n\n const color: AnnotationColor = {\n r: this.wasm.HEAPU32[rPtr >> 2],\n g: this.wasm.HEAPU32[gPtr >> 2],\n b: this.wasm.HEAPU32[bPtr >> 2],\n a: this.wasm.HEAPU32[aPtr >> 2],\n };\n\n this.bridge.freeAll(rPtr, gPtr, bPtr, aPtr);\n return color;\n }\n\n private _getAttachmentPoints(annotPtr: number): AttachmentPoint[] {\n if (!this.wasm._FPDFAnnot_CountAttachmentPoints) return [];\n\n const count = this.wasm._FPDFAnnot_CountAttachmentPoints(annotPtr);\n if (count <= 0) return [];\n\n const points: AttachmentPoint[] = [];\n const buf = this.wasm._malloc(64); // 8 doubles (4 quadrilateral points x 2 coords)\n\n for (let i = 0; i < count; i++) {\n this.wasm._FPDFAnnot_GetAttachmentPoints!(annotPtr, i, buf);\n points.push({\n x1: this.wasm.HEAPF64[buf >> 3],\n y1: this.wasm.HEAPF64[(buf + 8) >> 3],\n x2: this.wasm.HEAPF64[(buf + 16) >> 3],\n y2: this.wasm.HEAPF64[(buf + 24) >> 3],\n x3: this.wasm.HEAPF64[(buf + 32) >> 3],\n y3: this.wasm.HEAPF64[(buf + 40) >> 3],\n x4: this.wasm.HEAPF64[(buf + 48) >> 3],\n y4: this.wasm.HEAPF64[(buf + 56) >> 3],\n });\n }\n\n this.wasm._free(buf);\n return points;\n }\n}\n"]}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/signatures/SignatureVerifier.ts
|
|
4
|
+
var SignatureVerifier = class {
|
|
5
|
+
wasm;
|
|
6
|
+
bridge;
|
|
7
|
+
constructor(wasm, bridge) {
|
|
8
|
+
this.wasm = wasm;
|
|
9
|
+
this.bridge = bridge;
|
|
10
|
+
}
|
|
11
|
+
readSignatures(docPtr) {
|
|
12
|
+
if (!this.wasm._FPDF_GetSignatureCount) return [];
|
|
13
|
+
const count = this.wasm._FPDF_GetSignatureCount(docPtr);
|
|
14
|
+
if (count <= 0) return [];
|
|
15
|
+
const signatures = [];
|
|
16
|
+
for (let i = 0; i < count; i++) {
|
|
17
|
+
const sigPtr = this.wasm._FPDF_GetSignatureObject(docPtr, i);
|
|
18
|
+
if (sigPtr === 0) continue;
|
|
19
|
+
const sig = this._readSignature(sigPtr, i);
|
|
20
|
+
if (sig) signatures.push(sig);
|
|
21
|
+
}
|
|
22
|
+
return signatures;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Verify a signature's integrity.
|
|
26
|
+
* Performs basic byte-range validation and returns extracted metadata.
|
|
27
|
+
* For full PKI verification, use the raw `contents` with a crypto library.
|
|
28
|
+
*/
|
|
29
|
+
async verify(docPtr, sigIndex, documentBytes) {
|
|
30
|
+
const signatures = this.readSignatures(docPtr);
|
|
31
|
+
const sig = signatures[sigIndex];
|
|
32
|
+
if (!sig) {
|
|
33
|
+
throw new Error(`Signature at index ${sigIndex} not found`);
|
|
34
|
+
}
|
|
35
|
+
const byteRangeValid = this._validateByteRange(sig.byteRange, documentBytes);
|
|
36
|
+
return {
|
|
37
|
+
valid: byteRangeValid && sig.contents.length > 0,
|
|
38
|
+
signer: sig.reason || "Unknown",
|
|
39
|
+
reason: sig.reason,
|
|
40
|
+
timestamp: sig.signingTime,
|
|
41
|
+
subFilter: sig.subFilter,
|
|
42
|
+
docMDPPermission: sig.docMDPPermission,
|
|
43
|
+
rawContents: sig.contents
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
_readSignature(sigPtr, index) {
|
|
47
|
+
const contents = this.bridge.getSignatureBinaryField(
|
|
48
|
+
sigPtr,
|
|
49
|
+
(sig, buf, bufLen) => this.wasm._FPDFSignObj_GetContents(sig, buf, bufLen)
|
|
50
|
+
);
|
|
51
|
+
const byteRangeRaw = this.bridge.getSignatureBinaryField(
|
|
52
|
+
sigPtr,
|
|
53
|
+
(sig, buf, bufLen) => this.wasm._FPDFSignObj_GetByteRange(sig, buf, bufLen)
|
|
54
|
+
);
|
|
55
|
+
const byteRange = this._parseByteRange(byteRangeRaw);
|
|
56
|
+
const subFilter = this.bridge.getSignatureStringField(
|
|
57
|
+
sigPtr,
|
|
58
|
+
(sig, buf, bufLen) => this.wasm._FPDFSignObj_GetSubFilter(sig, buf, bufLen)
|
|
59
|
+
);
|
|
60
|
+
const reason = this.bridge.getSignatureStringField(
|
|
61
|
+
sigPtr,
|
|
62
|
+
(sig, buf, bufLen) => this.wasm._FPDFSignObj_GetReason(sig, buf, bufLen)
|
|
63
|
+
);
|
|
64
|
+
const signingTime = this.bridge.getSignatureStringField(
|
|
65
|
+
sigPtr,
|
|
66
|
+
(sig, buf, bufLen) => this.wasm._FPDFSignObj_GetTime(sig, buf, bufLen)
|
|
67
|
+
);
|
|
68
|
+
const docMDPPermission = this.wasm._FPDFSignObj_GetDocMDPPermission(sigPtr);
|
|
69
|
+
return {
|
|
70
|
+
index,
|
|
71
|
+
contents,
|
|
72
|
+
byteRange,
|
|
73
|
+
subFilter,
|
|
74
|
+
reason,
|
|
75
|
+
signingTime,
|
|
76
|
+
docMDPPermission
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
_parseByteRange(raw) {
|
|
80
|
+
if (raw.length === 0) return [];
|
|
81
|
+
const view = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);
|
|
82
|
+
const ints = [];
|
|
83
|
+
for (let i = 0; i + 3 < raw.length; i += 4) {
|
|
84
|
+
ints.push(view.getInt32(i, true));
|
|
85
|
+
}
|
|
86
|
+
return ints;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Validates that the byte ranges cover the expected portions of the document
|
|
90
|
+
* (everything except the signature contents hex string).
|
|
91
|
+
*/
|
|
92
|
+
_validateByteRange(byteRange, documentBytes) {
|
|
93
|
+
if (byteRange.length < 4 || byteRange.length % 2 !== 0) return false;
|
|
94
|
+
if (byteRange[0] !== 0) return false;
|
|
95
|
+
const lastOffset = byteRange[byteRange.length - 2];
|
|
96
|
+
const lastLength = byteRange[byteRange.length - 1];
|
|
97
|
+
if (lastOffset + lastLength !== documentBytes.length) return false;
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
exports.SignatureVerifier = SignatureVerifier;
|
|
103
|
+
//# sourceMappingURL=chunk-ETSUOY4U.cjs.map
|
|
104
|
+
//# sourceMappingURL=chunk-ETSUOY4U.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/signatures/SignatureVerifier.ts"],"names":[],"mappings":"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","file":"chunk-ETSUOY4U.cjs","sourcesContent":["import type { WasmModule, SignatureData, SignatureVerificationResult } from '../types';\nimport { WasmBridge } from '../core/WasmBridge';\n\n/**\n * Reads and verifies digital signatures from a PDF document.\n * Uses PDFium's FPDFSignObj_* APIs to extract signature metadata.\n *\n * Note: Full cryptographic verification (validating the PKCS#7 signature\n * against a certificate chain) requires additional crypto libraries.\n * This class extracts the raw signature data and metadata for verification\n * by external tools (e.g., node-forge, WebCrypto, or OpenSSL).\n */\nexport class SignatureVerifier {\n private wasm: WasmModule;\n private bridge: WasmBridge;\n\n constructor(wasm: WasmModule, bridge: WasmBridge) {\n this.wasm = wasm;\n this.bridge = bridge;\n }\n\n readSignatures(docPtr: number): SignatureData[] {\n if (!this.wasm._FPDF_GetSignatureCount) return [];\n\n const count = this.wasm._FPDF_GetSignatureCount(docPtr);\n if (count <= 0) return [];\n\n const signatures: SignatureData[] = [];\n\n for (let i = 0; i < count; i++) {\n const sigPtr = this.wasm._FPDF_GetSignatureObject!(docPtr, i);\n if (sigPtr === 0) continue;\n\n const sig = this._readSignature(sigPtr, i);\n if (sig) signatures.push(sig);\n }\n\n return signatures;\n }\n\n /**\n * Verify a signature's integrity.\n * Performs basic byte-range validation and returns extracted metadata.\n * For full PKI verification, use the raw `contents` with a crypto library.\n */\n async verify(docPtr: number, sigIndex: number, documentBytes: Uint8Array): Promise<SignatureVerificationResult> {\n const signatures = this.readSignatures(docPtr);\n const sig = signatures[sigIndex];\n\n if (!sig) {\n throw new Error(`Signature at index ${sigIndex} not found`);\n }\n\n // Basic byte-range integrity check\n const byteRangeValid = this._validateByteRange(sig.byteRange, documentBytes);\n\n return {\n valid: byteRangeValid && sig.contents.length > 0,\n signer: sig.reason || 'Unknown',\n reason: sig.reason,\n timestamp: sig.signingTime,\n subFilter: sig.subFilter,\n docMDPPermission: sig.docMDPPermission,\n rawContents: sig.contents,\n };\n }\n\n private _readSignature(sigPtr: number, index: number): SignatureData | null {\n const contents = this.bridge.getSignatureBinaryField(\n sigPtr,\n (sig, buf, bufLen) => this.wasm._FPDFSignObj_GetContents!(sig, buf, bufLen),\n );\n\n const byteRangeRaw = this.bridge.getSignatureBinaryField(\n sigPtr,\n (sig, buf, bufLen) => this.wasm._FPDFSignObj_GetByteRange!(sig, buf, bufLen),\n );\n const byteRange = this._parseByteRange(byteRangeRaw);\n\n const subFilter = this.bridge.getSignatureStringField(\n sigPtr,\n (sig, buf, bufLen) => this.wasm._FPDFSignObj_GetSubFilter!(sig, buf, bufLen),\n );\n\n const reason = this.bridge.getSignatureStringField(\n sigPtr,\n (sig, buf, bufLen) => this.wasm._FPDFSignObj_GetReason!(sig, buf, bufLen),\n );\n\n const signingTime = this.bridge.getSignatureStringField(\n sigPtr,\n (sig, buf, bufLen) => this.wasm._FPDFSignObj_GetTime!(sig, buf, bufLen),\n );\n\n const docMDPPermission = this.wasm._FPDFSignObj_GetDocMDPPermission!(sigPtr);\n\n return {\n index,\n contents,\n byteRange,\n subFilter,\n reason,\n signingTime,\n docMDPPermission,\n };\n }\n\n private _parseByteRange(raw: Uint8Array): number[] {\n if (raw.length === 0) return [];\n\n // Byte range is stored as pairs of (offset, length) as 32-bit integers\n const view = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);\n const ints: number[] = [];\n for (let i = 0; i + 3 < raw.length; i += 4) {\n ints.push(view.getInt32(i, true));\n }\n return ints;\n }\n\n /**\n * Validates that the byte ranges cover the expected portions of the document\n * (everything except the signature contents hex string).\n */\n private _validateByteRange(byteRange: number[], documentBytes: Uint8Array): boolean {\n if (byteRange.length < 4 || byteRange.length % 2 !== 0) return false;\n\n // Byte range should start at 0\n if (byteRange[0] !== 0) return false;\n\n // Last range should end at document length\n const lastOffset = byteRange[byteRange.length - 2];\n const lastLength = byteRange[byteRange.length - 1];\n if (lastOffset + lastLength !== documentBytes.length) return false;\n\n return true;\n }\n}\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// src/forms/FormReader.ts
|
|
2
|
+
var FormReader = class {
|
|
3
|
+
wasm;
|
|
4
|
+
bridge;
|
|
5
|
+
constructor(wasm, bridge) {
|
|
6
|
+
this.wasm = wasm;
|
|
7
|
+
this.bridge = bridge;
|
|
8
|
+
}
|
|
9
|
+
readAllFields(docPtr, formHandle, pageCount) {
|
|
10
|
+
const fields = [];
|
|
11
|
+
for (let pageIdx = 0; pageIdx < pageCount; pageIdx++) {
|
|
12
|
+
const pagePtr = this.wasm._FPDF_LoadPage(docPtr, pageIdx);
|
|
13
|
+
if (pagePtr === 0) continue;
|
|
14
|
+
try {
|
|
15
|
+
const pageFields = this._readPageFields(pagePtr, formHandle, pageIdx);
|
|
16
|
+
fields.push(...pageFields);
|
|
17
|
+
} finally {
|
|
18
|
+
this.wasm._FPDF_ClosePage(pagePtr);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return fields;
|
|
22
|
+
}
|
|
23
|
+
_readPageFields(pagePtr, formHandle, pageIndex) {
|
|
24
|
+
if (!this.wasm._FPDFPage_GetAnnotCount) return [];
|
|
25
|
+
const annotCount = this.wasm._FPDFPage_GetAnnotCount(pagePtr);
|
|
26
|
+
const fields = [];
|
|
27
|
+
for (let i = 0; i < annotCount; i++) {
|
|
28
|
+
const annotPtr = this.wasm._FPDFPage_GetAnnot(pagePtr, i);
|
|
29
|
+
if (annotPtr === 0) continue;
|
|
30
|
+
try {
|
|
31
|
+
const subtype = this.wasm._FPDFAnnot_GetSubtype(annotPtr);
|
|
32
|
+
if (subtype !== 20) continue;
|
|
33
|
+
const fieldType = this.wasm._FPDFAnnot_GetFormFieldType ? this.wasm._FPDFAnnot_GetFormFieldType(formHandle, annotPtr) : -1 /* Unknown */;
|
|
34
|
+
const name = this.bridge.getFormFieldName(formHandle, annotPtr);
|
|
35
|
+
const value = this.bridge.getFormFieldValue(formHandle, annotPtr);
|
|
36
|
+
const flags = this.wasm._FPDFAnnot_GetFormFieldFlags ? this.wasm._FPDFAnnot_GetFormFieldFlags(formHandle, annotPtr) : 0;
|
|
37
|
+
let isChecked;
|
|
38
|
+
if (fieldType === 1 /* CheckBox */ || fieldType === 2 /* RadioButton */) {
|
|
39
|
+
isChecked = this.wasm._FPDFAnnot_IsChecked ? this.wasm._FPDFAnnot_IsChecked(formHandle, annotPtr) !== 0 : void 0;
|
|
40
|
+
}
|
|
41
|
+
fields.push({
|
|
42
|
+
name,
|
|
43
|
+
type: fieldType,
|
|
44
|
+
value,
|
|
45
|
+
flags,
|
|
46
|
+
isChecked,
|
|
47
|
+
pageIndex,
|
|
48
|
+
annotIndex: i
|
|
49
|
+
});
|
|
50
|
+
} finally {
|
|
51
|
+
this.wasm._FPDFPage_CloseAnnot(annotPtr);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return fields;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export { FormReader };
|
|
59
|
+
//# sourceMappingURL=chunk-FD5RTJ5W.mjs.map
|
|
60
|
+
//# sourceMappingURL=chunk-FD5RTJ5W.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/forms/FormReader.ts"],"names":[],"mappings":"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","file":"chunk-FD5RTJ5W.mjs","sourcesContent":["import type { WasmModule, FormFieldData } from '../types';\nimport { FormFieldType } from '../types';\nimport { WasmBridge } from '../core/WasmBridge';\n\n/**\n * Reads form fields from all pages of a PDF document.\n * Iterates through annotations of type Widget to find form fields.\n */\nexport class FormReader {\n private wasm: WasmModule;\n private bridge: WasmBridge;\n\n constructor(wasm: WasmModule, bridge: WasmBridge) {\n this.wasm = wasm;\n this.bridge = bridge;\n }\n\n readAllFields(docPtr: number, formHandle: number, pageCount: number): FormFieldData[] {\n const fields: FormFieldData[] = [];\n\n for (let pageIdx = 0; pageIdx < pageCount; pageIdx++) {\n const pagePtr = this.wasm._FPDF_LoadPage(docPtr, pageIdx);\n if (pagePtr === 0) continue;\n\n try {\n const pageFields = this._readPageFields(pagePtr, formHandle, pageIdx);\n fields.push(...pageFields);\n } finally {\n this.wasm._FPDF_ClosePage(pagePtr);\n }\n }\n\n return fields;\n }\n\n private _readPageFields(pagePtr: number, formHandle: number, pageIndex: number): FormFieldData[] {\n if (!this.wasm._FPDFPage_GetAnnotCount) return [];\n\n const annotCount = this.wasm._FPDFPage_GetAnnotCount(pagePtr);\n const fields: FormFieldData[] = [];\n\n for (let i = 0; i < annotCount; i++) {\n const annotPtr = this.wasm._FPDFPage_GetAnnot!(pagePtr, i);\n if (annotPtr === 0) continue;\n\n try {\n const subtype = this.wasm._FPDFAnnot_GetSubtype!(annotPtr);\n // Widget annotation (subtype 20) = form field\n if (subtype !== 20) continue;\n\n const fieldType = this.wasm._FPDFAnnot_GetFormFieldType\n ? this.wasm._FPDFAnnot_GetFormFieldType(formHandle, annotPtr) as FormFieldType\n : FormFieldType.Unknown;\n\n const name = this.bridge.getFormFieldName(formHandle, annotPtr);\n const value = this.bridge.getFormFieldValue(formHandle, annotPtr);\n const flags = this.wasm._FPDFAnnot_GetFormFieldFlags\n ? this.wasm._FPDFAnnot_GetFormFieldFlags(formHandle, annotPtr)\n : 0;\n\n let isChecked: boolean | undefined;\n if (fieldType === FormFieldType.CheckBox || fieldType === FormFieldType.RadioButton) {\n isChecked = this.wasm._FPDFAnnot_IsChecked\n ? this.wasm._FPDFAnnot_IsChecked(formHandle, annotPtr) !== 0\n : undefined;\n }\n\n fields.push({\n name,\n type: fieldType,\n value,\n flags,\n isChecked,\n pageIndex,\n annotIndex: i,\n });\n } finally {\n this.wasm._FPDFPage_CloseAnnot!(annotPtr);\n }\n }\n\n return fields;\n }\n}\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/forms/FormFlattener.ts
|
|
2
|
+
var FormFlattener = class {
|
|
3
|
+
wasm;
|
|
4
|
+
constructor(wasm) {
|
|
5
|
+
this.wasm = wasm;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Flatten all form fields across all pages.
|
|
9
|
+
* @param usage - 0 for normal display, 1 for print appearance
|
|
10
|
+
* @returns Number of pages successfully flattened
|
|
11
|
+
*/
|
|
12
|
+
flattenAll(docPtr, pageCount, usage = 0) {
|
|
13
|
+
if (!this.wasm._FPDFPage_Flatten) {
|
|
14
|
+
throw new Error("Form flattening requires the full pdfnova build");
|
|
15
|
+
}
|
|
16
|
+
let flattenedCount = 0;
|
|
17
|
+
for (let i = 0; i < pageCount; i++) {
|
|
18
|
+
const pagePtr = this.wasm._FPDF_LoadPage(docPtr, i);
|
|
19
|
+
if (pagePtr === 0) continue;
|
|
20
|
+
try {
|
|
21
|
+
const result = this.wasm._FPDFPage_Flatten(pagePtr, usage);
|
|
22
|
+
if (result === 1) flattenedCount++;
|
|
23
|
+
} finally {
|
|
24
|
+
this.wasm._FPDF_ClosePage(pagePtr);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return flattenedCount;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Flatten form fields on a single page.
|
|
31
|
+
*/
|
|
32
|
+
flattenPage(pagePtr, usage = 0) {
|
|
33
|
+
if (!this.wasm._FPDFPage_Flatten) {
|
|
34
|
+
throw new Error("Form flattening requires the full pdfnova build");
|
|
35
|
+
}
|
|
36
|
+
return this.wasm._FPDFPage_Flatten(pagePtr, usage) === 1;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export { FormFlattener };
|
|
41
|
+
//# sourceMappingURL=chunk-FO3DQLVB.mjs.map
|
|
42
|
+
//# sourceMappingURL=chunk-FO3DQLVB.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/forms/FormFlattener.ts"],"names":[],"mappings":";AAMO,IAAM,gBAAN,MAAoB;AAAA,EACjB,IAAA;AAAA,EAER,YAAY,IAAA,EAAkB;AAC5B,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAA,CAAW,MAAA,EAAgB,SAAA,EAAmB,KAAA,GAAgB,CAAA,EAAW;AACvE,IAAA,IAAI,CAAC,IAAA,CAAK,IAAA,CAAK,iBAAA,EAAmB;AAChC,MAAA,MAAM,IAAI,MAAM,iDAAiD,CAAA;AAAA,IACnE;AAEA,IAAA,IAAI,cAAA,GAAiB,CAAA;AAErB,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,EAAW,CAAA,EAAA,EAAK;AAClC,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,QAAQ,CAAC,CAAA;AAClD,MAAA,IAAI,YAAY,CAAA,EAAG;AAEnB,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,IAAA,CAAK,IAAA,CAAK,iBAAA,CAAkB,SAAS,KAAK,CAAA;AAEzD,QAAA,IAAI,WAAW,CAAA,EAAG,cAAA,EAAA;AAAA,MACpB,CAAA,SAAE;AACA,QAAA,IAAA,CAAK,IAAA,CAAK,gBAAgB,OAAO,CAAA;AAAA,MACnC;AAAA,IACF;AAEA,IAAA,OAAO,cAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,WAAA,CAAY,OAAA,EAAiB,KAAA,GAAgB,CAAA,EAAY;AACvD,IAAA,IAAI,CAAC,IAAA,CAAK,IAAA,CAAK,iBAAA,EAAmB;AAChC,MAAA,MAAM,IAAI,MAAM,iDAAiD,CAAA;AAAA,IACnE;AACA,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,iBAAA,CAAkB,OAAA,EAAS,KAAK,CAAA,KAAM,CAAA;AAAA,EACzD;AACF","file":"chunk-FO3DQLVB.mjs","sourcesContent":["import type { WasmModule } from '../types';\n\n/**\n * Flattens form fields into static page content.\n * After flattening, form fields become non-interactive rendered graphics.\n */\nexport class FormFlattener {\n private wasm: WasmModule;\n\n constructor(wasm: WasmModule) {\n this.wasm = wasm;\n }\n\n /**\n * Flatten all form fields across all pages.\n * @param usage - 0 for normal display, 1 for print appearance\n * @returns Number of pages successfully flattened\n */\n flattenAll(docPtr: number, pageCount: number, usage: number = 0): number {\n if (!this.wasm._FPDFPage_Flatten) {\n throw new Error('Form flattening requires the full pdfnova build');\n }\n\n let flattenedCount = 0;\n\n for (let i = 0; i < pageCount; i++) {\n const pagePtr = this.wasm._FPDF_LoadPage(docPtr, i);\n if (pagePtr === 0) continue;\n\n try {\n const result = this.wasm._FPDFPage_Flatten(pagePtr, usage);\n // 0 = cannot flatten (no forms), 1 = success, 2 = nothing to flatten\n if (result === 1) flattenedCount++;\n } finally {\n this.wasm._FPDF_ClosePage(pagePtr);\n }\n }\n\n return flattenedCount;\n }\n\n /**\n * Flatten form fields on a single page.\n */\n flattenPage(pagePtr: number, usage: number = 0): boolean {\n if (!this.wasm._FPDFPage_Flatten) {\n throw new Error('Form flattening requires the full pdfnova build');\n }\n return this.wasm._FPDFPage_Flatten(pagePtr, usage) === 1;\n }\n}\n"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/forms/FormReader.ts
|
|
4
|
+
var FormReader = class {
|
|
5
|
+
wasm;
|
|
6
|
+
bridge;
|
|
7
|
+
constructor(wasm, bridge) {
|
|
8
|
+
this.wasm = wasm;
|
|
9
|
+
this.bridge = bridge;
|
|
10
|
+
}
|
|
11
|
+
readAllFields(docPtr, formHandle, pageCount) {
|
|
12
|
+
const fields = [];
|
|
13
|
+
for (let pageIdx = 0; pageIdx < pageCount; pageIdx++) {
|
|
14
|
+
const pagePtr = this.wasm._FPDF_LoadPage(docPtr, pageIdx);
|
|
15
|
+
if (pagePtr === 0) continue;
|
|
16
|
+
try {
|
|
17
|
+
const pageFields = this._readPageFields(pagePtr, formHandle, pageIdx);
|
|
18
|
+
fields.push(...pageFields);
|
|
19
|
+
} finally {
|
|
20
|
+
this.wasm._FPDF_ClosePage(pagePtr);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return fields;
|
|
24
|
+
}
|
|
25
|
+
_readPageFields(pagePtr, formHandle, pageIndex) {
|
|
26
|
+
if (!this.wasm._FPDFPage_GetAnnotCount) return [];
|
|
27
|
+
const annotCount = this.wasm._FPDFPage_GetAnnotCount(pagePtr);
|
|
28
|
+
const fields = [];
|
|
29
|
+
for (let i = 0; i < annotCount; i++) {
|
|
30
|
+
const annotPtr = this.wasm._FPDFPage_GetAnnot(pagePtr, i);
|
|
31
|
+
if (annotPtr === 0) continue;
|
|
32
|
+
try {
|
|
33
|
+
const subtype = this.wasm._FPDFAnnot_GetSubtype(annotPtr);
|
|
34
|
+
if (subtype !== 20) continue;
|
|
35
|
+
const fieldType = this.wasm._FPDFAnnot_GetFormFieldType ? this.wasm._FPDFAnnot_GetFormFieldType(formHandle, annotPtr) : -1 /* Unknown */;
|
|
36
|
+
const name = this.bridge.getFormFieldName(formHandle, annotPtr);
|
|
37
|
+
const value = this.bridge.getFormFieldValue(formHandle, annotPtr);
|
|
38
|
+
const flags = this.wasm._FPDFAnnot_GetFormFieldFlags ? this.wasm._FPDFAnnot_GetFormFieldFlags(formHandle, annotPtr) : 0;
|
|
39
|
+
let isChecked;
|
|
40
|
+
if (fieldType === 1 /* CheckBox */ || fieldType === 2 /* RadioButton */) {
|
|
41
|
+
isChecked = this.wasm._FPDFAnnot_IsChecked ? this.wasm._FPDFAnnot_IsChecked(formHandle, annotPtr) !== 0 : void 0;
|
|
42
|
+
}
|
|
43
|
+
fields.push({
|
|
44
|
+
name,
|
|
45
|
+
type: fieldType,
|
|
46
|
+
value,
|
|
47
|
+
flags,
|
|
48
|
+
isChecked,
|
|
49
|
+
pageIndex,
|
|
50
|
+
annotIndex: i
|
|
51
|
+
});
|
|
52
|
+
} finally {
|
|
53
|
+
this.wasm._FPDFPage_CloseAnnot(annotPtr);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return fields;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
exports.FormReader = FormReader;
|
|
61
|
+
//# sourceMappingURL=chunk-G2FA6VKV.cjs.map
|
|
62
|
+
//# sourceMappingURL=chunk-G2FA6VKV.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/forms/FormReader.ts"],"names":[],"mappings":"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","file":"chunk-G2FA6VKV.cjs","sourcesContent":["import type { WasmModule, FormFieldData } from '../types';\nimport { FormFieldType } from '../types';\nimport { WasmBridge } from '../core/WasmBridge';\n\n/**\n * Reads form fields from all pages of a PDF document.\n * Iterates through annotations of type Widget to find form fields.\n */\nexport class FormReader {\n private wasm: WasmModule;\n private bridge: WasmBridge;\n\n constructor(wasm: WasmModule, bridge: WasmBridge) {\n this.wasm = wasm;\n this.bridge = bridge;\n }\n\n readAllFields(docPtr: number, formHandle: number, pageCount: number): FormFieldData[] {\n const fields: FormFieldData[] = [];\n\n for (let pageIdx = 0; pageIdx < pageCount; pageIdx++) {\n const pagePtr = this.wasm._FPDF_LoadPage(docPtr, pageIdx);\n if (pagePtr === 0) continue;\n\n try {\n const pageFields = this._readPageFields(pagePtr, formHandle, pageIdx);\n fields.push(...pageFields);\n } finally {\n this.wasm._FPDF_ClosePage(pagePtr);\n }\n }\n\n return fields;\n }\n\n private _readPageFields(pagePtr: number, formHandle: number, pageIndex: number): FormFieldData[] {\n if (!this.wasm._FPDFPage_GetAnnotCount) return [];\n\n const annotCount = this.wasm._FPDFPage_GetAnnotCount(pagePtr);\n const fields: FormFieldData[] = [];\n\n for (let i = 0; i < annotCount; i++) {\n const annotPtr = this.wasm._FPDFPage_GetAnnot!(pagePtr, i);\n if (annotPtr === 0) continue;\n\n try {\n const subtype = this.wasm._FPDFAnnot_GetSubtype!(annotPtr);\n // Widget annotation (subtype 20) = form field\n if (subtype !== 20) continue;\n\n const fieldType = this.wasm._FPDFAnnot_GetFormFieldType\n ? this.wasm._FPDFAnnot_GetFormFieldType(formHandle, annotPtr) as FormFieldType\n : FormFieldType.Unknown;\n\n const name = this.bridge.getFormFieldName(formHandle, annotPtr);\n const value = this.bridge.getFormFieldValue(formHandle, annotPtr);\n const flags = this.wasm._FPDFAnnot_GetFormFieldFlags\n ? this.wasm._FPDFAnnot_GetFormFieldFlags(formHandle, annotPtr)\n : 0;\n\n let isChecked: boolean | undefined;\n if (fieldType === FormFieldType.CheckBox || fieldType === FormFieldType.RadioButton) {\n isChecked = this.wasm._FPDFAnnot_IsChecked\n ? this.wasm._FPDFAnnot_IsChecked(formHandle, annotPtr) !== 0\n : undefined;\n }\n\n fields.push({\n name,\n type: fieldType,\n value,\n flags,\n isChecked,\n pageIndex,\n annotIndex: i,\n });\n } finally {\n this.wasm._FPDFPage_CloseAnnot!(annotPtr);\n }\n }\n\n return fields;\n }\n}\n"]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var RENDER_FLAG = {
|
|
3
|
+
ANNOT: 1,
|
|
4
|
+
LCD_TEXT: 2,
|
|
5
|
+
NO_NATIVETEXT: 4,
|
|
6
|
+
GRAYSCALE: 8,
|
|
7
|
+
REVERSE_BYTE_ORDER: 16,
|
|
8
|
+
DEBUG_INFO: 128,
|
|
9
|
+
NO_CATCH: 256,
|
|
10
|
+
RENDER_LIMITEDIMAGECACHE: 512,
|
|
11
|
+
RENDER_FORCEHALFTONE: 1024,
|
|
12
|
+
PRINTING: 2048,
|
|
13
|
+
RENDER_NO_SMOOTHTEXT: 4096,
|
|
14
|
+
RENDER_NO_SMOOTHIMAGE: 8192,
|
|
15
|
+
RENDER_NO_SMOOTHPATH: 16384
|
|
16
|
+
};
|
|
17
|
+
var AnnotationType = /* @__PURE__ */ ((AnnotationType2) => {
|
|
18
|
+
AnnotationType2[AnnotationType2["Unknown"] = 0] = "Unknown";
|
|
19
|
+
AnnotationType2[AnnotationType2["Text"] = 1] = "Text";
|
|
20
|
+
AnnotationType2[AnnotationType2["Link"] = 2] = "Link";
|
|
21
|
+
AnnotationType2[AnnotationType2["FreeText"] = 3] = "FreeText";
|
|
22
|
+
AnnotationType2[AnnotationType2["Line"] = 4] = "Line";
|
|
23
|
+
AnnotationType2[AnnotationType2["Square"] = 5] = "Square";
|
|
24
|
+
AnnotationType2[AnnotationType2["Circle"] = 6] = "Circle";
|
|
25
|
+
AnnotationType2[AnnotationType2["Polygon"] = 7] = "Polygon";
|
|
26
|
+
AnnotationType2[AnnotationType2["Polyline"] = 8] = "Polyline";
|
|
27
|
+
AnnotationType2[AnnotationType2["Highlight"] = 9] = "Highlight";
|
|
28
|
+
AnnotationType2[AnnotationType2["Underline"] = 10] = "Underline";
|
|
29
|
+
AnnotationType2[AnnotationType2["Squiggly"] = 11] = "Squiggly";
|
|
30
|
+
AnnotationType2[AnnotationType2["StrikeOut"] = 12] = "StrikeOut";
|
|
31
|
+
AnnotationType2[AnnotationType2["Stamp"] = 13] = "Stamp";
|
|
32
|
+
AnnotationType2[AnnotationType2["Caret"] = 14] = "Caret";
|
|
33
|
+
AnnotationType2[AnnotationType2["Ink"] = 15] = "Ink";
|
|
34
|
+
AnnotationType2[AnnotationType2["Popup"] = 16] = "Popup";
|
|
35
|
+
AnnotationType2[AnnotationType2["FileAttachment"] = 17] = "FileAttachment";
|
|
36
|
+
AnnotationType2[AnnotationType2["Sound"] = 18] = "Sound";
|
|
37
|
+
AnnotationType2[AnnotationType2["Movie"] = 19] = "Movie";
|
|
38
|
+
AnnotationType2[AnnotationType2["Widget"] = 20] = "Widget";
|
|
39
|
+
AnnotationType2[AnnotationType2["Screen"] = 21] = "Screen";
|
|
40
|
+
AnnotationType2[AnnotationType2["PrinterMark"] = 22] = "PrinterMark";
|
|
41
|
+
AnnotationType2[AnnotationType2["TrapNet"] = 23] = "TrapNet";
|
|
42
|
+
AnnotationType2[AnnotationType2["Watermark"] = 24] = "Watermark";
|
|
43
|
+
AnnotationType2[AnnotationType2["ThreeD"] = 25] = "ThreeD";
|
|
44
|
+
AnnotationType2[AnnotationType2["RichMedia"] = 26] = "RichMedia";
|
|
45
|
+
AnnotationType2[AnnotationType2["XFAWidget"] = 27] = "XFAWidget";
|
|
46
|
+
AnnotationType2[AnnotationType2["Redact"] = 28] = "Redact";
|
|
47
|
+
return AnnotationType2;
|
|
48
|
+
})(AnnotationType || {});
|
|
49
|
+
var FormFieldType = /* @__PURE__ */ ((FormFieldType2) => {
|
|
50
|
+
FormFieldType2[FormFieldType2["Unknown"] = -1] = "Unknown";
|
|
51
|
+
FormFieldType2[FormFieldType2["PushButton"] = 0] = "PushButton";
|
|
52
|
+
FormFieldType2[FormFieldType2["CheckBox"] = 1] = "CheckBox";
|
|
53
|
+
FormFieldType2[FormFieldType2["RadioButton"] = 2] = "RadioButton";
|
|
54
|
+
FormFieldType2[FormFieldType2["ComboBox"] = 3] = "ComboBox";
|
|
55
|
+
FormFieldType2[FormFieldType2["ListBox"] = 4] = "ListBox";
|
|
56
|
+
FormFieldType2[FormFieldType2["TextField"] = 5] = "TextField";
|
|
57
|
+
FormFieldType2[FormFieldType2["Signature"] = 6] = "Signature";
|
|
58
|
+
return FormFieldType2;
|
|
59
|
+
})(FormFieldType || {});
|
|
60
|
+
var FLATTEN_USAGE = {
|
|
61
|
+
NORMALONLY: 0,
|
|
62
|
+
PRINT: 1
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export { AnnotationType, FLATTEN_USAGE, FormFieldType, RENDER_FLAG };
|
|
66
|
+
//# sourceMappingURL=chunk-G7575D5X.mjs.map
|
|
67
|
+
//# sourceMappingURL=chunk-G7575D5X.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"names":["AnnotationType","FormFieldType"],"mappings":"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","file":"chunk-G7575D5X.mjs","sourcesContent":["// ─── WASM / Core ────────────────────────────────────────────────\n\nexport type WasmTier = 'lite' | 'full';\n\nexport interface WasmModule {\n HEAPU8: Uint8Array;\n HEAPU32: Uint32Array;\n HEAP32: Int32Array;\n HEAPF32: Float32Array;\n HEAPF64: Float64Array;\n\n _malloc(size: number): number;\n _free(ptr: number): void;\n\n // Document lifecycle\n _FPDF_InitLibraryWithConfig(configPtr: number): void;\n _FPDF_DestroyLibrary(): void;\n _FPDF_LoadMemDocument(buf: number, size: number, password: number): number;\n _FPDF_CloseDocument(doc: number): void;\n _FPDF_GetLastError(): number;\n _FPDF_GetPageCount(doc: number): number;\n\n // Page lifecycle\n _FPDF_LoadPage(doc: number, pageIndex: number): number;\n _FPDF_ClosePage(page: number): void;\n _FPDF_GetPageWidthF(page: number): number;\n _FPDF_GetPageHeightF(page: number): number;\n\n // Rendering\n _FPDFBitmap_Create(width: number, height: number, alpha: number): number;\n _FPDFBitmap_FillRect(bitmap: number, left: number, top: number, width: number, height: number, color: number): void;\n _FPDFBitmap_GetBuffer(bitmap: number): number;\n _FPDFBitmap_GetStride(bitmap: number): number;\n _FPDFBitmap_Destroy(bitmap: number): void;\n _FPDF_RenderPageBitmap(bitmap: number, page: number, startX: number, startY: number, sizeX: number, sizeY: number, rotate: number, flags: number): void;\n\n // Text\n _FPDFText_LoadPage(page: number): number;\n _FPDFText_ClosePage(textPage: number): void;\n _FPDFText_CountChars(textPage: number): number;\n _FPDFText_GetUnicode(textPage: number, index: number): number;\n _FPDFText_GetFontSize(textPage: number, index: number): number;\n _FPDFText_GetCharBox(textPage: number, index: number, left: number, right: number, bottom: number, top: number): number;\n _FPDFText_GetText(textPage: number, startIndex: number, count: number, buf: number): number;\n _FPDFText_FindStart(textPage: number, findWhat: number, flags: number, startIndex: number): number;\n _FPDFText_FindNext(findHandle: number): number;\n _FPDFText_FindClose(findHandle: number): void;\n _FPDFText_GetSchResultIndex(findHandle: number): number;\n _FPDFText_GetSchCount(findHandle: number): number;\n _FPDFText_CountRects(textPage: number, startIndex: number, count: number): number;\n _FPDFText_GetRect(textPage: number, rectIndex: number, left: number, top: number, right: number, bottom: number): number;\n\n // Metadata\n _FPDF_GetMetaText(doc: number, tag: number, buf: number, bufLen: number): number;\n\n // Bookmarks\n _FPDFBookmark_GetFirstChild(doc: number, bookmark: number): number;\n _FPDFBookmark_GetNextSibling(doc: number, bookmark: number): number;\n _FPDFBookmark_GetTitle(bookmark: number, buf: number, bufLen: number): number;\n _FPDFBookmark_GetAction(bookmark: number): number;\n _FPDFBookmark_GetDest(doc: number, bookmark: number): number;\n _FPDFDest_GetDestPageIndex(doc: number, dest: number): number;\n\n // Links\n _FPDFLink_LoadWebLinks(textPage: number): number;\n _FPDFLink_CountWebLinks(linkPage: number): number;\n _FPDFLink_GetURL(linkPage: number, linkIndex: number, buf: number, bufLen: number): number;\n _FPDFLink_CountRects(linkPage: number, linkIndex: number): number;\n _FPDFLink_GetRect(linkPage: number, linkIndex: number, rectIndex: number, left: number, top: number, right: number, bottom: number): void;\n _FPDFLink_CloseWebLinks(linkPage: number): void;\n\n // ─── Full-tier only ───────────────────────────────────────────\n\n // Annotations\n _FPDFPage_GetAnnotCount?(page: number): number;\n _FPDFPage_GetAnnot?(page: number, index: number): number;\n _FPDFPage_CreateAnnot?(page: number, subtype: number): number;\n _FPDFPage_RemoveAnnot?(page: number, index: number): number;\n _FPDFAnnot_GetSubtype?(annot: number): number;\n _FPDFAnnot_GetRect?(annot: number, rect: number): number;\n _FPDFAnnot_SetRect?(annot: number, rect: number): number;\n _FPDFAnnot_GetColor?(annot: number, type: number, r: number, g: number, b: number, a: number): number;\n _FPDFAnnot_SetColor?(annot: number, type: number, r: number, g: number, b: number, a: number): number;\n _FPDFAnnot_GetStringValue?(annot: number, key: number, buf: number, bufLen: number): number;\n _FPDFAnnot_SetStringValue?(annot: number, key: number, value: number): number;\n _FPDFAnnot_AppendAttachmentPoints?(annot: number, points: number): number;\n _FPDFAnnot_CountAttachmentPoints?(annot: number): number;\n _FPDFAnnot_GetAttachmentPoints?(annot: number, index: number, points: number): number;\n _FPDFPage_CloseAnnot?(annot: number): void;\n\n // Forms\n _FPDFDOC_InitFormFillEnvironment?(doc: number, formInfo: number): number;\n _FPDFDOC_ExitFormFillEnvironment?(formHandle: number): void;\n _FPDF_GetFormType?(doc: number): number;\n _FPDFPage_HasFormFieldAtPoint?(formHandle: number, page: number, x: number, y: number): number;\n _FORM_OnMouseMove?(formHandle: number, page: number, modifier: number, x: number, y: number): void;\n\n // Form fields\n _FPDFAnnot_GetFormFieldType?(formHandle: number, annot: number): number;\n _FPDFAnnot_GetFormFieldName?(formHandle: number, annot: number, buf: number, bufLen: number): number;\n _FPDFAnnot_GetFormFieldValue?(formHandle: number, annot: number, buf: number, bufLen: number): number;\n _FPDFAnnot_SetFormFieldValue?(formHandle: number, annot: number, value: number): void;\n _FPDFAnnot_GetFormFieldFlags?(formHandle: number, annot: number): number;\n _FPDFAnnot_IsChecked?(formHandle: number, annot: number): number;\n\n // Form flattening\n _FPDFPage_Flatten?(page: number, usage: number): number;\n\n // Save\n _FPDF_SaveAsCopy?(doc: number, writer: number, flags: number): number;\n _FPDF_SaveWithVersion?(doc: number, writer: number, flags: number, version: number): number;\n\n // Signatures\n _FPDF_GetSignatureCount?(doc: number): number;\n _FPDF_GetSignatureObject?(doc: number, index: number): number;\n _FPDFSignObj_GetContents?(sig: number, buf: number, bufLen: number): number;\n _FPDFSignObj_GetByteRange?(sig: number, buf: number, bufLen: number): number;\n _FPDFSignObj_GetSubFilter?(sig: number, buf: number, bufLen: number): number;\n _FPDFSignObj_GetReason?(sig: number, buf: number, bufLen: number): number;\n _FPDFSignObj_GetTime?(sig: number, buf: number, bufLen: number): number;\n _FPDFSignObj_GetDocMDPPermission?(sig: number): number;\n\n // Emscripten utilities\n UTF8ToString(ptr: number): string;\n UTF16ToString(ptr: number): string;\n stringToUTF8(str: string, outPtr: number, maxBytesToWrite: number): void;\n stringToUTF16(str: string, outPtr: number, maxBytesToWrite: number): void;\n lengthBytesUTF8(str: string): number;\n lengthBytesUTF16(str: string): number;\n}\n\nexport interface PDFNovaConfig {\n wasmUrl?: string;\n worker?: boolean;\n maxWorkers?: number;\n}\n\n// ─── Document ───────────────────────────────────────────────────\n\nexport interface OpenOptions {\n password?: string;\n headers?: Record<string, string>;\n credentials?: RequestCredentials;\n wasmUrl?: string;\n worker?: boolean;\n}\n\nexport interface PDFMetadata {\n title: string;\n author: string;\n subject: string;\n keywords: string;\n creator: string;\n producer: string;\n creationDate: string;\n modDate: string;\n}\n\nexport interface PDFPermissions {\n print: boolean;\n copy: boolean;\n modify: boolean;\n annotate: boolean;\n fillForms: boolean;\n extractForAccessibility: boolean;\n assemble: boolean;\n printHighQuality: boolean;\n}\n\n// ─── Rendering ──────────────────────────────────────────────────\n\nexport interface RenderOptions {\n scale?: number;\n rotation?: 0 | 90 | 180 | 270;\n background?: string;\n flags?: number;\n}\n\nexport const RENDER_FLAG = {\n ANNOT: 0x01,\n LCD_TEXT: 0x02,\n NO_NATIVETEXT: 0x04,\n GRAYSCALE: 0x08,\n REVERSE_BYTE_ORDER: 0x10,\n DEBUG_INFO: 0x80,\n NO_CATCH: 0x100,\n RENDER_LIMITEDIMAGECACHE: 0x200,\n RENDER_FORCEHALFTONE: 0x400,\n PRINTING: 0x800,\n RENDER_NO_SMOOTHTEXT: 0x1000,\n RENDER_NO_SMOOTHIMAGE: 0x2000,\n RENDER_NO_SMOOTHPATH: 0x4000,\n} as const;\n\n// ─── Text ───────────────────────────────────────────────────────\n\nexport interface TextSpan {\n text: string;\n x: number;\n y: number;\n width: number;\n height: number;\n fontSize: number;\n charIndex: number;\n charCount: number;\n}\n\nexport interface CharBox {\n char: string;\n charCode: number;\n left: number;\n right: number;\n top: number;\n bottom: number;\n fontSize: number;\n index: number;\n}\n\nexport interface SearchResult {\n pageIndex: number;\n matchIndex: number;\n charIndex: number;\n charCount: number;\n rects: TextRect[];\n text: string;\n}\n\nexport interface SearchOptions {\n caseSensitive?: boolean;\n wholeWord?: boolean;\n}\n\nexport interface TextRect {\n left: number;\n top: number;\n right: number;\n bottom: number;\n}\n\n// ─── Navigation ─────────────────────────────────────────────────\n\nexport interface OutlineItem {\n title: string;\n pageIndex: number;\n children: OutlineItem[];\n}\n\nexport interface LinkInfo {\n url: string;\n rects: TextRect[];\n pageIndex: number;\n}\n\n// ─── Annotations (full tier) ────────────────────────────────────\n\nexport enum AnnotationType {\n Unknown = 0,\n Text = 1,\n Link = 2,\n FreeText = 3,\n Line = 4,\n Square = 5,\n Circle = 6,\n Polygon = 7,\n Polyline = 8,\n Highlight = 9,\n Underline = 10,\n Squiggly = 11,\n StrikeOut = 12,\n Stamp = 13,\n Caret = 14,\n Ink = 15,\n Popup = 16,\n FileAttachment = 17,\n Sound = 18,\n Movie = 19,\n Widget = 20,\n Screen = 21,\n PrinterMark = 22,\n TrapNet = 23,\n Watermark = 24,\n ThreeD = 25,\n RichMedia = 26,\n XFAWidget = 27,\n Redact = 28,\n}\n\nexport interface AnnotationColor {\n r: number;\n g: number;\n b: number;\n a: number;\n}\n\nexport interface AnnotationRect {\n left: number;\n top: number;\n right: number;\n bottom: number;\n}\n\nexport interface AttachmentPoint {\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n x3: number;\n y3: number;\n x4: number;\n y4: number;\n}\n\nexport interface AnnotationData {\n index: number;\n type: AnnotationType;\n rect: AnnotationRect;\n color?: AnnotationColor;\n contents?: string;\n author?: string;\n modificationDate?: string;\n attachmentPoints?: AttachmentPoint[];\n}\n\nexport interface CreateAnnotationOptions {\n type: AnnotationType;\n rect: AnnotationRect;\n color?: AnnotationColor;\n contents?: string;\n attachmentPoints?: AttachmentPoint[];\n}\n\n// ─── Forms (full tier) ──────────────────────────────────────────\n\nexport enum FormFieldType {\n Unknown = -1,\n PushButton = 0,\n CheckBox = 1,\n RadioButton = 2,\n ComboBox = 3,\n ListBox = 4,\n TextField = 5,\n Signature = 6,\n}\n\nexport interface FormFieldData {\n name: string;\n type: FormFieldType;\n value: string;\n flags: number;\n isChecked?: boolean;\n pageIndex: number;\n annotIndex: number;\n}\n\nexport const FLATTEN_USAGE = {\n NORMALONLY: 0,\n PRINT: 1,\n} as const;\n\n// ─── Signatures (full tier) ────────────────────────────────────\n\nexport interface SignatureData {\n index: number;\n contents: Uint8Array;\n byteRange: number[];\n subFilter: string;\n reason: string;\n signingTime: string;\n docMDPPermission: number;\n}\n\nexport interface SignatureVerificationResult {\n valid: boolean;\n signer: string;\n reason: string;\n timestamp: string;\n subFilter: string;\n docMDPPermission: number;\n rawContents: Uint8Array;\n}\n\n// ─── Virtual Renderer ───────────────────────────────────────────\n\nexport interface VirtualRendererOptions {\n container: HTMLElement;\n overscan?: number;\n cacheSize?: number;\n scale?: number;\n gap?: number;\n}\n\n// ─── Worker ─────────────────────────────────────────────────────\n\nexport type WorkerMessageType =\n | 'init'\n | 'open'\n | 'render'\n | 'getText'\n | 'getTextSpans'\n | 'search'\n | 'close'\n | 'destroy';\n\nexport interface WorkerRequest {\n id: number;\n type: WorkerMessageType;\n payload: unknown;\n}\n\nexport interface WorkerResponse {\n id: number;\n type: 'result' | 'error';\n payload: unknown;\n}\n"]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// src/annotations/AnnotationWriter.ts
|
|
2
|
+
var AnnotationWriter = class {
|
|
3
|
+
wasm;
|
|
4
|
+
bridge;
|
|
5
|
+
constructor(wasm, bridge) {
|
|
6
|
+
this.wasm = wasm;
|
|
7
|
+
this.bridge = bridge;
|
|
8
|
+
}
|
|
9
|
+
addAnnotation(pagePtr, options) {
|
|
10
|
+
if (!this.wasm._FPDFPage_CreateAnnot) {
|
|
11
|
+
throw new Error("Annotation creation requires the full pdfnova build");
|
|
12
|
+
}
|
|
13
|
+
const annotPtr = this.wasm._FPDFPage_CreateAnnot(pagePtr, options.type);
|
|
14
|
+
if (annotPtr === 0) throw new Error("Failed to create annotation");
|
|
15
|
+
try {
|
|
16
|
+
this._setRect(annotPtr, options.rect);
|
|
17
|
+
if (options.color) {
|
|
18
|
+
this._setColor(annotPtr, options.color);
|
|
19
|
+
}
|
|
20
|
+
if (options.contents) {
|
|
21
|
+
const valuePtr = this.bridge.allocateUTF16String(options.contents);
|
|
22
|
+
const keyPtr = this.bridge.allocateString("Contents");
|
|
23
|
+
this.wasm._FPDFAnnot_SetStringValue(annotPtr, keyPtr, valuePtr);
|
|
24
|
+
this.bridge.freeAll(keyPtr, valuePtr);
|
|
25
|
+
}
|
|
26
|
+
if (options.attachmentPoints) {
|
|
27
|
+
for (const point of options.attachmentPoints) {
|
|
28
|
+
const buf = this.wasm._malloc(64);
|
|
29
|
+
this.wasm.HEAPF64[buf >> 3] = point.x1;
|
|
30
|
+
this.wasm.HEAPF64[buf + 8 >> 3] = point.y1;
|
|
31
|
+
this.wasm.HEAPF64[buf + 16 >> 3] = point.x2;
|
|
32
|
+
this.wasm.HEAPF64[buf + 24 >> 3] = point.y2;
|
|
33
|
+
this.wasm.HEAPF64[buf + 32 >> 3] = point.x3;
|
|
34
|
+
this.wasm.HEAPF64[buf + 40 >> 3] = point.y3;
|
|
35
|
+
this.wasm.HEAPF64[buf + 48 >> 3] = point.x4;
|
|
36
|
+
this.wasm.HEAPF64[buf + 56 >> 3] = point.y4;
|
|
37
|
+
this.wasm._FPDFAnnot_AppendAttachmentPoints(annotPtr, buf);
|
|
38
|
+
this.wasm._free(buf);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} finally {
|
|
42
|
+
this.wasm._FPDFPage_CloseAnnot(annotPtr);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
removeAnnotation(pagePtr, index) {
|
|
46
|
+
if (!this.wasm._FPDFPage_RemoveAnnot) {
|
|
47
|
+
throw new Error("Annotation removal requires the full pdfnova build");
|
|
48
|
+
}
|
|
49
|
+
const result = this.wasm._FPDFPage_RemoveAnnot(pagePtr, index);
|
|
50
|
+
if (result === 0) throw new Error(`Failed to remove annotation at index ${index}`);
|
|
51
|
+
}
|
|
52
|
+
_setRect(annotPtr, rect) {
|
|
53
|
+
const buf = this.wasm._malloc(32);
|
|
54
|
+
this.wasm.HEAPF64[buf >> 3] = rect.left;
|
|
55
|
+
this.wasm.HEAPF64[buf + 8 >> 3] = rect.bottom;
|
|
56
|
+
this.wasm.HEAPF64[buf + 16 >> 3] = rect.right;
|
|
57
|
+
this.wasm.HEAPF64[buf + 24 >> 3] = rect.top;
|
|
58
|
+
this.wasm._FPDFAnnot_SetRect(annotPtr, buf);
|
|
59
|
+
this.wasm._free(buf);
|
|
60
|
+
}
|
|
61
|
+
_setColor(annotPtr, color) {
|
|
62
|
+
this.wasm._FPDFAnnot_SetColor(
|
|
63
|
+
annotPtr,
|
|
64
|
+
0,
|
|
65
|
+
color.r,
|
|
66
|
+
color.g,
|
|
67
|
+
color.b,
|
|
68
|
+
color.a
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export { AnnotationWriter };
|
|
74
|
+
//# sourceMappingURL=chunk-I7OBHZLB.mjs.map
|
|
75
|
+
//# sourceMappingURL=chunk-I7OBHZLB.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/annotations/AnnotationWriter.ts"],"names":[],"mappings":"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","file":"chunk-I7OBHZLB.mjs","sourcesContent":["import type { WasmModule, CreateAnnotationOptions, AnnotationColor, AnnotationRect } from '../types';\nimport { WasmBridge } from '../core/WasmBridge';\n\n/**\n * Creates and modifies annotations on PDF pages using PDFium's FPDFAnnot_* APIs.\n */\nexport class AnnotationWriter {\n private wasm: WasmModule;\n private bridge: WasmBridge;\n\n constructor(wasm: WasmModule, bridge: WasmBridge) {\n this.wasm = wasm;\n this.bridge = bridge;\n }\n\n addAnnotation(pagePtr: number, options: CreateAnnotationOptions): void {\n if (!this.wasm._FPDFPage_CreateAnnot) {\n throw new Error('Annotation creation requires the full pdfnova build');\n }\n\n const annotPtr = this.wasm._FPDFPage_CreateAnnot(pagePtr, options.type);\n if (annotPtr === 0) throw new Error('Failed to create annotation');\n\n try {\n this._setRect(annotPtr, options.rect);\n\n if (options.color) {\n this._setColor(annotPtr, options.color);\n }\n\n if (options.contents) {\n const valuePtr = this.bridge.allocateUTF16String(options.contents);\n const keyPtr = this.bridge.allocateString('Contents');\n this.wasm._FPDFAnnot_SetStringValue!(annotPtr, keyPtr, valuePtr);\n this.bridge.freeAll(keyPtr, valuePtr);\n }\n\n if (options.attachmentPoints) {\n for (const point of options.attachmentPoints) {\n const buf = this.wasm._malloc(64);\n this.wasm.HEAPF64[buf >> 3] = point.x1;\n this.wasm.HEAPF64[(buf + 8) >> 3] = point.y1;\n this.wasm.HEAPF64[(buf + 16) >> 3] = point.x2;\n this.wasm.HEAPF64[(buf + 24) >> 3] = point.y2;\n this.wasm.HEAPF64[(buf + 32) >> 3] = point.x3;\n this.wasm.HEAPF64[(buf + 40) >> 3] = point.y3;\n this.wasm.HEAPF64[(buf + 48) >> 3] = point.x4;\n this.wasm.HEAPF64[(buf + 56) >> 3] = point.y4;\n this.wasm._FPDFAnnot_AppendAttachmentPoints!(annotPtr, buf);\n this.wasm._free(buf);\n }\n }\n } finally {\n this.wasm._FPDFPage_CloseAnnot!(annotPtr);\n }\n }\n\n removeAnnotation(pagePtr: number, index: number): void {\n if (!this.wasm._FPDFPage_RemoveAnnot) {\n throw new Error('Annotation removal requires the full pdfnova build');\n }\n\n const result = this.wasm._FPDFPage_RemoveAnnot(pagePtr, index);\n if (result === 0) throw new Error(`Failed to remove annotation at index ${index}`);\n }\n\n private _setRect(annotPtr: number, rect: AnnotationRect): void {\n const buf = this.wasm._malloc(32);\n this.wasm.HEAPF64[buf >> 3] = rect.left;\n this.wasm.HEAPF64[(buf + 8) >> 3] = rect.bottom;\n this.wasm.HEAPF64[(buf + 16) >> 3] = rect.right;\n this.wasm.HEAPF64[(buf + 24) >> 3] = rect.top;\n this.wasm._FPDFAnnot_SetRect!(annotPtr, buf);\n this.wasm._free(buf);\n }\n\n private _setColor(annotPtr: number, color: AnnotationColor): void {\n this.wasm._FPDFAnnot_SetColor!(\n annotPtr, 0,\n color.r, color.g, color.b, color.a,\n );\n }\n}\n"]}
|