pdf-codec 1.4.2 → 1.6.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.
Files changed (170) hide show
  1. package/README.md +56 -15
  2. package/dist/assets/caladea-bold.cjs +5 -0
  3. package/dist/assets/caladea-bold.d.cts +4 -0
  4. package/dist/assets/caladea-bold.d.ts +4 -0
  5. package/dist/assets/caladea-bold.js +4 -0
  6. package/dist/assets/caladea-bolditalic.cjs +5 -0
  7. package/dist/assets/caladea-bolditalic.d.cts +4 -0
  8. package/dist/assets/caladea-bolditalic.d.ts +4 -0
  9. package/dist/assets/caladea-bolditalic.js +4 -0
  10. package/dist/assets/caladea-italic.cjs +5 -0
  11. package/dist/assets/caladea-italic.d.cts +4 -0
  12. package/dist/assets/caladea-italic.d.ts +4 -0
  13. package/dist/assets/caladea-italic.js +4 -0
  14. package/dist/assets/caladea-regular.cjs +5 -0
  15. package/dist/assets/caladea-regular.d.cts +4 -0
  16. package/dist/assets/caladea-regular.d.ts +4 -0
  17. package/dist/assets/caladea-regular.js +4 -0
  18. package/dist/assets/carlito-bold.cjs +5 -0
  19. package/dist/assets/carlito-bold.d.cts +4 -0
  20. package/dist/assets/carlito-bold.d.ts +4 -0
  21. package/dist/assets/carlito-bold.js +4 -0
  22. package/dist/assets/carlito-bolditalic.cjs +5 -0
  23. package/dist/assets/carlito-bolditalic.d.cts +4 -0
  24. package/dist/assets/carlito-bolditalic.d.ts +4 -0
  25. package/dist/assets/carlito-bolditalic.js +4 -0
  26. package/dist/assets/carlito-italic.cjs +5 -0
  27. package/dist/assets/carlito-italic.d.cts +4 -0
  28. package/dist/assets/carlito-italic.d.ts +4 -0
  29. package/dist/assets/carlito-italic.js +4 -0
  30. package/dist/assets/carlito-regular.cjs +5 -0
  31. package/dist/assets/carlito-regular.d.cts +4 -0
  32. package/dist/assets/carlito-regular.d.ts +4 -0
  33. package/dist/assets/carlito-regular.js +4 -0
  34. package/dist/cff-probe.cjs +133 -0
  35. package/dist/cff-probe.d.cts +10 -0
  36. package/dist/cff-probe.d.ts +10 -0
  37. package/dist/cff-probe.js +132 -0
  38. package/dist/cmap-table.cjs +108 -0
  39. package/dist/cmap-table.d.cts +6 -0
  40. package/dist/cmap-table.d.ts +6 -0
  41. package/dist/cmap-table.js +107 -0
  42. package/dist/content-write.cjs +36 -17
  43. package/dist/content-write.d.cts +9 -2
  44. package/dist/content-write.d.ts +9 -2
  45. package/dist/content-write.js +35 -16
  46. package/dist/crypto/aes.cjs +166 -0
  47. package/dist/crypto/aes.d.cts +6 -0
  48. package/dist/crypto/aes.d.ts +6 -0
  49. package/dist/crypto/aes.js +163 -0
  50. package/dist/crypto/md5.cjs +215 -0
  51. package/dist/crypto/md5.d.cts +4 -0
  52. package/dist/crypto/md5.d.ts +4 -0
  53. package/dist/crypto/md5.js +214 -0
  54. package/dist/crypto/rc4.cjs +29 -0
  55. package/dist/crypto/rc4.d.cts +4 -0
  56. package/dist/crypto/rc4.d.ts +4 -0
  57. package/dist/crypto/rc4.js +28 -0
  58. package/dist/crypto/sha2.cjs +261 -0
  59. package/dist/crypto/sha2.d.cts +6 -0
  60. package/dist/crypto/sha2.d.ts +6 -0
  61. package/dist/crypto/sha2.js +258 -0
  62. package/dist/diagnostics.cjs +7 -0
  63. package/dist/diagnostics.d.cts +4 -1
  64. package/dist/diagnostics.d.ts +4 -1
  65. package/dist/diagnostics.js +7 -1
  66. package/dist/document.cjs +38 -2
  67. package/dist/document.js +38 -2
  68. package/dist/embedded-font-CLedn-mT.d.cts +42 -0
  69. package/dist/embedded-font-CbqkKgBl.d.ts +42 -0
  70. package/dist/embedded-font-write.cjs +92 -0
  71. package/dist/embedded-font-write.d.cts +22 -0
  72. package/dist/embedded-font-write.d.ts +22 -0
  73. package/dist/embedded-font-write.js +90 -0
  74. package/dist/embedded-font.cjs +142 -0
  75. package/dist/embedded-font.d.cts +2 -0
  76. package/dist/embedded-font.d.ts +2 -0
  77. package/dist/embedded-font.js +138 -0
  78. package/dist/encrypt.cjs +264 -0
  79. package/dist/encrypt.d.cts +11 -0
  80. package/dist/encrypt.d.ts +11 -0
  81. package/dist/encrypt.js +263 -0
  82. package/dist/filters.cjs +19 -1
  83. package/dist/filters.js +19 -1
  84. package/dist/font-registry-Cn7P9lAh.d.ts +38 -0
  85. package/dist/font-registry-yby02snZ.d.cts +38 -0
  86. package/dist/font-registry.cjs +152 -0
  87. package/dist/font-registry.d.cts +2 -0
  88. package/dist/font-registry.d.ts +2 -0
  89. package/dist/font-registry.js +150 -0
  90. package/dist/font-substitutes.cjs +13 -0
  91. package/dist/font-substitutes.d.cts +5 -0
  92. package/dist/font-substitutes.d.ts +5 -0
  93. package/dist/font-substitutes.js +12 -0
  94. package/dist/font-tables.cjs +127 -0
  95. package/dist/font-tables.d.cts +43 -0
  96. package/dist/font-tables.d.ts +43 -0
  97. package/dist/font-tables.js +122 -0
  98. package/dist/fonts.cjs +1 -0
  99. package/dist/fonts.d.cts +2 -1
  100. package/dist/fonts.d.ts +2 -1
  101. package/dist/fonts.js +1 -1
  102. package/dist/glyf.cjs +127 -0
  103. package/dist/glyf.d.cts +31 -0
  104. package/dist/glyf.d.ts +31 -0
  105. package/dist/glyf.js +125 -0
  106. package/dist/{math-hmtx.cjs → hmtx-table.cjs} +3 -3
  107. package/dist/{math-hmtx.d.ts → hmtx-table.d.cts} +2 -2
  108. package/dist/{math-hmtx.d.cts → hmtx-table.d.ts} +2 -2
  109. package/dist/{math-hmtx.js → hmtx-table.js} +3 -3
  110. package/dist/image/ccitt.cjs +488 -0
  111. package/dist/image/ccitt.d.cts +17 -0
  112. package/dist/image/ccitt.d.ts +17 -0
  113. package/dist/image/ccitt.js +487 -0
  114. package/dist/images-read.cjs +1 -4
  115. package/dist/images-read.js +2 -5
  116. package/dist/index.cjs +8 -0
  117. package/dist/index.d.cts +7 -4
  118. package/dist/index.d.ts +7 -4
  119. package/dist/index.js +5 -3
  120. package/dist/interpret.cjs +173 -38
  121. package/dist/interpret.d.cts +27 -10
  122. package/dist/interpret.d.ts +27 -10
  123. package/dist/interpret.js +174 -39
  124. package/dist/math-font-write.cjs +3 -32
  125. package/dist/math-font-write.js +2 -31
  126. package/dist/math-font.cjs +7 -5
  127. package/dist/math-font.js +5 -3
  128. package/dist/math-table.d.cts +1 -1
  129. package/dist/math-table.d.ts +1 -1
  130. package/dist/{matrix-B3c2_a2f.d.cts → matrix-BHzJESll.d.cts} +2 -1
  131. package/dist/{matrix-B3c2_a2f.d.ts → matrix-BHzJESll.d.ts} +2 -1
  132. package/dist/matrix.cjs +2 -0
  133. package/dist/matrix.d.cts +2 -2
  134. package/dist/matrix.d.ts +2 -2
  135. package/dist/matrix.js +2 -1
  136. package/dist/measure.cjs +65 -14
  137. package/dist/measure.d.cts +8 -1
  138. package/dist/measure.d.ts +8 -1
  139. package/dist/measure.js +64 -15
  140. package/dist/objects.cjs +4 -0
  141. package/dist/objects.d.cts +2 -1
  142. package/dist/objects.d.ts +2 -1
  143. package/dist/objects.js +4 -1
  144. package/dist/read.cjs +43 -4
  145. package/dist/read.d.cts +1 -1
  146. package/dist/read.d.ts +1 -1
  147. package/dist/read.js +43 -4
  148. package/dist/sfnt-V08bb5ut.d.cts +21 -0
  149. package/dist/sfnt-V08bb5ut.d.ts +21 -0
  150. package/dist/sfnt-subset.cjs +250 -0
  151. package/dist/sfnt-subset.d.cts +11 -0
  152. package/dist/sfnt-subset.d.ts +11 -0
  153. package/dist/sfnt-subset.js +249 -0
  154. package/dist/sfnt.cjs +50 -4
  155. package/dist/sfnt.d.cts +2 -17
  156. package/dist/sfnt.d.ts +2 -17
  157. package/dist/sfnt.js +47 -5
  158. package/dist/tounicode.cjs +34 -0
  159. package/dist/tounicode.d.cts +5 -0
  160. package/dist/tounicode.d.ts +5 -0
  161. package/dist/tounicode.js +33 -0
  162. package/dist/write.cjs +81 -11
  163. package/dist/write.d.cts +6 -0
  164. package/dist/write.d.ts +6 -0
  165. package/dist/write.js +82 -12
  166. package/package.json +1 -1
  167. package/dist/math-cmap.cjs +0 -81
  168. package/dist/math-cmap.d.cts +0 -6
  169. package/dist/math-cmap.d.ts +0 -6
  170. package/dist/math-cmap.js +0 -80
@@ -0,0 +1,263 @@
1
+ import { concatBytes } from "./bytes/writer.js";
2
+ import { PdfEncryptedError, PdfPasswordRequiredError } from "./diagnostics.js";
3
+ import { aesCbcDecrypt, aesCbcEncrypt } from "./crypto/aes.js";
4
+ import { md5 } from "./crypto/md5.js";
5
+ import { rc4 } from "./crypto/rc4.js";
6
+ import { sha256, sha384, sha512 } from "./crypto/sha2.js";
7
+ import { asDict, asName, asNumber, dictGet } from "./objects.js";
8
+ //#region src/encrypt.ts
9
+ const PASSWORD_PADDING = new Uint8Array([
10
+ 40,
11
+ 191,
12
+ 78,
13
+ 94,
14
+ 78,
15
+ 117,
16
+ 138,
17
+ 65,
18
+ 100,
19
+ 0,
20
+ 78,
21
+ 86,
22
+ 255,
23
+ 250,
24
+ 1,
25
+ 8,
26
+ 46,
27
+ 46,
28
+ 0,
29
+ 182,
30
+ 208,
31
+ 104,
32
+ 62,
33
+ 128,
34
+ 47,
35
+ 12,
36
+ 169,
37
+ 254,
38
+ 100,
39
+ 83,
40
+ 105,
41
+ 122
42
+ ]);
43
+ const AES_OBJECT_KEY_SALT = new Uint8Array([
44
+ 115,
45
+ 65,
46
+ 108,
47
+ 84
48
+ ]);
49
+ const MD5_DIGEST_BYTES = 16;
50
+ const OBJECT_KEY_EXTRA_BYTES = 5;
51
+ const LEGACY_KEY_ITERATIONS = 50;
52
+ const ALGORITHM_5_ITERATIONS = 19;
53
+ const R6_MINIMUM_ROUNDS = 64;
54
+ const R6_ROUND_REPEATS = 64;
55
+ const R6_TERMINATION_MARGIN = 32;
56
+ const AESV3_KEY_BYTES = 32;
57
+ const RC4_40_KEY_BYTES = 5;
58
+ const AESV2_KEY_BYTES = 16;
59
+ const DEFAULT_KEY_BITS = 40;
60
+ const BITS_PER_BYTE = 8;
61
+ const MAX_RC4_KEY_BYTES = 16;
62
+ const ZERO_IV = /* @__PURE__ */ new Uint8Array(16);
63
+ function requireStringBytes(dict, key) {
64
+ const value = dictGet(dict, key);
65
+ if (value?.kind !== "string") throw new PdfEncryptedError(`the /Encrypt dictionary's /${key} entry is missing or is not a direct string; this file's encryption cannot be read`);
66
+ return value.bytes;
67
+ }
68
+ function bytesEqual(a, b, length) {
69
+ if (a.length < length || b.length < length) return false;
70
+ for (let i = 0; i < length; i++) if (a[i] !== b[i]) return false;
71
+ return true;
72
+ }
73
+ function permissionsBytes(p) {
74
+ const unsigned = Math.trunc(p) >>> 0;
75
+ return new Uint8Array([
76
+ unsigned & 255,
77
+ unsigned >>> 8 & 255,
78
+ unsigned >>> 16 & 255,
79
+ unsigned >>> 24 & 255
80
+ ]);
81
+ }
82
+ function computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMetadata) {
83
+ const owner = requireStringBytes(encryptDict, "O");
84
+ const permissions = asNumber(dictGet(encryptDict, "P")) ?? 0;
85
+ const parts = [
86
+ PASSWORD_PADDING,
87
+ owner.subarray(0, PASSWORD_PADDING.length),
88
+ permissionsBytes(permissions),
89
+ fileId
90
+ ];
91
+ if (revision >= 4 && !encryptMetadata) parts.push(new Uint8Array([
92
+ 255,
93
+ 255,
94
+ 255,
95
+ 255
96
+ ]));
97
+ let digest = md5(concatBytes(parts));
98
+ if (revision >= 3) for (let i = 0; i < LEGACY_KEY_ITERATIONS; i++) digest = md5(digest.subarray(0, keyBytes));
99
+ return digest.subarray(0, keyBytes);
100
+ }
101
+ function legacyUserPasswordVerifies(encryptDict, fileId, revision, fileKey) {
102
+ const storedUser = requireStringBytes(encryptDict, "U");
103
+ if (revision === 2) return bytesEqual(rc4(fileKey, PASSWORD_PADDING), storedUser, PASSWORD_PADDING.length);
104
+ let value = rc4(fileKey, md5(concatBytes([PASSWORD_PADDING, fileId])));
105
+ for (let i = 1; i <= ALGORITHM_5_ITERATIONS; i++) {
106
+ const roundKey = Uint8Array.from(fileKey, (byte) => byte ^ i);
107
+ value = rc4(roundKey, value);
108
+ }
109
+ return bytesEqual(value, storedUser, MD5_DIGEST_BYTES);
110
+ }
111
+ function hardenedHash(password, salt, userData, revision) {
112
+ let k = sha256(concatBytes([
113
+ password,
114
+ salt,
115
+ userData
116
+ ]));
117
+ if (revision === 5) return k;
118
+ let e = new Uint8Array([0]);
119
+ let round = 0;
120
+ while (round < R6_MINIMUM_ROUNDS || e[e.length - 1] > round - R6_TERMINATION_MARGIN) {
121
+ const roundInput = concatBytes([
122
+ password,
123
+ k,
124
+ userData
125
+ ]);
126
+ const k1 = new Uint8Array(roundInput.length * R6_ROUND_REPEATS);
127
+ for (let i = 0; i < R6_ROUND_REPEATS; i++) k1.set(roundInput, i * roundInput.length);
128
+ e = aesCbcEncrypt(k.subarray(0, 16), k.subarray(16, 32), k1);
129
+ let sum = 0;
130
+ for (let i = 0; i < 16; i++) sum += e[i];
131
+ const selector = sum % 3;
132
+ k = selector === 0 ? sha256(e) : selector === 1 ? sha384(e) : sha512(e);
133
+ round++;
134
+ }
135
+ return k.subarray(0, AESV3_KEY_BYTES);
136
+ }
137
+ function computeAesV3FileKey(encryptDict, revision) {
138
+ const storedUser = requireStringBytes(encryptDict, "U");
139
+ const expectedLength = 48;
140
+ if (storedUser.length < expectedLength) throw new PdfEncryptedError(`the /Encrypt dictionary's /U entry is ${String(storedUser.length)} bytes; revision ${String(revision)} requires ${String(expectedLength)}`);
141
+ const empty = /* @__PURE__ */ new Uint8Array(0);
142
+ const validationSalt = storedUser.subarray(AESV3_KEY_BYTES, 40);
143
+ const keySalt = storedUser.subarray(40, expectedLength);
144
+ if (!bytesEqual(hardenedHash(empty, validationSalt, empty, revision), storedUser, AESV3_KEY_BYTES)) throw new PdfPasswordRequiredError();
145
+ const intermediateKey = hardenedHash(empty, keySalt, empty, revision);
146
+ const wrappedKey = requireStringBytes(encryptDict, "UE");
147
+ if (wrappedKey.length < AESV3_KEY_BYTES) throw new PdfEncryptedError(`the /Encrypt dictionary's /UE entry is ${String(wrappedKey.length)} bytes; revision ${String(revision)} requires ${String(AESV3_KEY_BYTES)}`);
148
+ return aesCbcDecrypt(intermediateKey, ZERO_IV, wrappedKey.subarray(0, AESV3_KEY_BYTES));
149
+ }
150
+ function methodFromCryptFilterName(encryptDict, entryKey) {
151
+ const name = asName(dictGet(encryptDict, entryKey)) ?? "Identity";
152
+ if (name === "Identity") return "identity";
153
+ const filters = asDict(dictGet(encryptDict, "CF"));
154
+ const filter = filters !== void 0 ? asDict(dictGet(filters, name)) : void 0;
155
+ if (filter === void 0) throw new PdfEncryptedError(`the /Encrypt dictionary names a crypt filter /${name} for /${entryKey} that its own /CF dictionary does not define`);
156
+ const method = asName(dictGet(filter, "CFM"));
157
+ if (method === "None") return "identity";
158
+ if (method === "V2") return "rc4";
159
+ if (method === "AESV2" || method === "AESV3") return "aes";
160
+ throw new PdfEncryptedError(`crypt filter /${name} uses an unsupported /CFM ${method === void 0 ? "(absent)" : `/${method}`}`);
161
+ }
162
+ function cryptFilterKeyBytes(encryptDict, declaredBits) {
163
+ const streamFilterName = asName(dictGet(encryptDict, "StmF")) ?? "Identity";
164
+ const filters = asDict(dictGet(encryptDict, "CF"));
165
+ const filter = filters !== void 0 ? asDict(dictGet(filters, streamFilterName)) : void 0;
166
+ if ((filter !== void 0 ? asName(dictGet(filter, "CFM")) : void 0) === "AESV2") return AESV2_KEY_BYTES;
167
+ const declared = filter !== void 0 ? asNumber(dictGet(filter, "Length")) : void 0;
168
+ if (declared === void 0) return Math.floor(declaredBits / BITS_PER_BYTE);
169
+ return declared >= DEFAULT_KEY_BITS ? Math.floor(declared / BITS_PER_BYTE) : declared;
170
+ }
171
+ function setUpHandler(encryptDict, fileId) {
172
+ const version = asNumber(dictGet(encryptDict, "V")) ?? 0;
173
+ const revision = asNumber(dictGet(encryptDict, "R")) ?? 0;
174
+ const declaredBits = asNumber(dictGet(encryptDict, "Length")) ?? DEFAULT_KEY_BITS;
175
+ const encryptMetadataEntry = dictGet(encryptDict, "EncryptMetadata");
176
+ const encryptMetadata = encryptMetadataEntry?.kind === "bool" ? encryptMetadataEntry.value : true;
177
+ if (version === 5) {
178
+ if (revision !== 5 && revision !== 6) throw new PdfEncryptedError(`/V 5 encryption with an unsupported revision /R ${String(revision)}`);
179
+ return {
180
+ fileKey: computeAesV3FileKey(encryptDict, revision),
181
+ streamMethod: methodFromCryptFilterName(encryptDict, "StmF"),
182
+ stringMethod: methodFromCryptFilterName(encryptDict, "StrF"),
183
+ perObjectKeys: false,
184
+ encryptMetadata
185
+ };
186
+ }
187
+ if (version !== 1 && version !== 2 && version !== 4) throw new PdfEncryptedError(`unsupported standard security handler version /V ${String(version)}`);
188
+ if (revision < 2 || revision > 4) throw new PdfEncryptedError(`unsupported standard security handler revision /R ${String(revision)}`);
189
+ const streamMethod = version === 4 ? methodFromCryptFilterName(encryptDict, "StmF") : "rc4";
190
+ const stringMethod = version === 4 ? methodFromCryptFilterName(encryptDict, "StrF") : "rc4";
191
+ const keyBytes = version === 1 ? RC4_40_KEY_BYTES : version === 2 ? Math.floor(declaredBits / BITS_PER_BYTE) : cryptFilterKeyBytes(encryptDict, declaredBits);
192
+ if (keyBytes < RC4_40_KEY_BYTES || keyBytes > MAX_RC4_KEY_BYTES) throw new PdfEncryptedError(`the /Encrypt dictionary declares a ${String(keyBytes * BITS_PER_BYTE)}-bit file key, outside the 40-128 bit range /V ${String(version)} permits`);
193
+ const fileKey = computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMetadata);
194
+ if (!legacyUserPasswordVerifies(encryptDict, fileId, revision, fileKey)) throw new PdfPasswordRequiredError();
195
+ return {
196
+ fileKey,
197
+ streamMethod,
198
+ stringMethod,
199
+ perObjectKeys: true,
200
+ encryptMetadata
201
+ };
202
+ }
203
+ function objectKey(fileKey, num, gen, method) {
204
+ const extra = new Uint8Array(OBJECT_KEY_EXTRA_BYTES);
205
+ extra[0] = num & 255;
206
+ extra[1] = num >>> 8 & 255;
207
+ extra[2] = num >>> 16 & 255;
208
+ extra[3] = gen & 255;
209
+ extra[4] = gen >>> 8 & 255;
210
+ return md5(concatBytes(method === "aes" ? [
211
+ fileKey,
212
+ extra,
213
+ AES_OBJECT_KEY_SALT
214
+ ] : [fileKey, extra])).subarray(0, Math.min(fileKey.length + OBJECT_KEY_EXTRA_BYTES, MD5_DIGEST_BYTES));
215
+ }
216
+ function decryptAes(key, data, sink) {
217
+ if (data.length <= 16) {
218
+ if (data.length !== 0 && data.length !== 16) sink({
219
+ code: "pdf/decrypt-truncated",
220
+ severity: "warning",
221
+ message: `an AES-encrypted value is ${String(data.length)} bytes, too short to carry even its own initialisation vector; treating it as empty`
222
+ });
223
+ return /* @__PURE__ */ new Uint8Array(0);
224
+ }
225
+ const body = data.subarray(16);
226
+ if (body.length % 16 !== 0) sink({
227
+ code: "pdf/decrypt-truncated",
228
+ severity: "warning",
229
+ message: `an AES-encrypted value's ciphertext is ${String(body.length)} bytes, not a whole number of 16-byte blocks; the trailing partial block is being dropped`
230
+ });
231
+ const plain = aesCbcDecrypt(key, data.subarray(0, 16), body);
232
+ const padLength = plain[plain.length - 1] ?? 0;
233
+ if (padLength < 1 || padLength > 16 || padLength > plain.length) {
234
+ sink({
235
+ code: "pdf/decrypt-bad-padding",
236
+ severity: "warning",
237
+ message: "an AES-encrypted value did not end in valid PKCS#7 padding; keeping the decrypted bytes unstripped"
238
+ });
239
+ return plain;
240
+ }
241
+ return plain.subarray(0, plain.length - padLength);
242
+ }
243
+ function applyMethod(method, fileKey, perObjectKeys, bytes, num, gen, sink) {
244
+ if (method === "identity") return bytes;
245
+ const key = perObjectKeys ? objectKey(fileKey, num, gen, method) : fileKey;
246
+ return method === "rc4" ? rc4(key, bytes) : decryptAes(key, bytes, sink);
247
+ }
248
+ function createStandardDecryptor(encryptDict, fileId, sink) {
249
+ const filter = asName(dictGet(encryptDict, "Filter"));
250
+ if (filter !== "Standard") throw new PdfEncryptedError(`this PDF uses the ${filter === void 0 ? "unnamed" : `/${filter}`} security handler; only the standard security handler is supported`);
251
+ const setup = setUpHandler(encryptDict, fileId);
252
+ return {
253
+ decryptString(bytes, num, gen) {
254
+ return applyMethod(setup.stringMethod, setup.fileKey, setup.perObjectKeys, bytes, num, gen, sink);
255
+ },
256
+ decryptStream(bytes, dict, num, gen) {
257
+ if (!setup.encryptMetadata && asName(dictGet(dict, "Type")) === "Metadata") return bytes;
258
+ return applyMethod(setup.streamMethod, setup.fileKey, setup.perObjectKeys, bytes, num, gen, sink);
259
+ }
260
+ };
261
+ }
262
+ //#endregion
263
+ export { createStandardDecryptor };
package/dist/filters.cjs CHANGED
@@ -1,7 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_bytes_reader = require("./bytes/reader.cjs");
3
- const require_bytes_flate = require("./bytes/flate.cjs");
4
3
  const require_objects = require("./objects.cjs");
4
+ const require_bytes_flate = require("./bytes/flate.cjs");
5
+ const require_image_ccitt = require("./image/ccitt.cjs");
5
6
  const require_predictors = require("./predictors.cjs");
6
7
  //#region src/filters.ts
7
8
  function decodeStream(raw, dict, sink) {
@@ -18,6 +19,7 @@ function decodeStream(raw, dict, sink) {
18
19
  } else if (filter === "ASCII85Decode" || filter === "A85") bytes = ascii85Decode(bytes);
19
20
  else if (filter === "ASCIIHexDecode" || filter === "AHx") bytes = asciiHexDecode(bytes);
20
21
  else if (filter === "RunLengthDecode" || filter === "RL") bytes = runLengthDecode(bytes);
22
+ else if (filter === "CCITTFaxDecode" || filter === "CCF") bytes = ccittFaxDecode(bytes, parm, dict, sink);
21
23
  else if (filter === "DCTDecode" || filter === "DCT") return {
22
24
  bytes,
23
25
  remainingFilter: "DCTDecode"
@@ -39,6 +41,22 @@ function decodeStream(raw, dict, sink) {
39
41
  function applyPredictorIfPresent(data, parm, sink) {
40
42
  return require_predictors.applyPredictor(data, require_predictors.readPredictorParams(parm), sink);
41
43
  }
44
+ function ccittFaxDecode(data, parm, dict, sink) {
45
+ const parmGet = (key) => parm !== void 0 ? require_objects.dictGet(parm, key) : void 0;
46
+ const rows = require_objects.asNumber(parmGet("Rows")) ?? require_objects.asNumber(require_objects.dictGet(dict, "Height") ?? require_objects.dictGet(dict, "H"));
47
+ return require_image_ccitt.decodeCcittFax(data, {
48
+ k: require_objects.asNumber(parmGet("K")),
49
+ columns: require_objects.asNumber(parmGet("Columns")),
50
+ rows,
51
+ blackIs1: require_objects.asBool(parmGet("BlackIs1")),
52
+ encodedByteAlign: require_objects.asBool(parmGet("EncodedByteAlign")),
53
+ onWarning: (message) => sink({
54
+ code: "pdf/ccitt-fax-degraded",
55
+ severity: "warning",
56
+ message
57
+ })
58
+ }).bytes;
59
+ }
42
60
  function filterNames(dict) {
43
61
  const filterObj = require_objects.dictGet(dict, "Filter") ?? require_objects.dictGet(dict, "F");
44
62
  if (filterObj === void 0) return [];
package/dist/filters.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { isAsciiWhitespace } from "./bytes/reader.js";
2
+ import { asArray, asBool, asDict, asName, asNumber, dictGet } from "./objects.js";
2
3
  import { inflateTolerant } from "./bytes/flate.js";
3
- import { asArray, asDict, asName, asNumber, dictGet } from "./objects.js";
4
+ import { decodeCcittFax } from "./image/ccitt.js";
4
5
  import { applyPredictor, readPredictorParams } from "./predictors.js";
5
6
  //#region src/filters.ts
6
7
  function decodeStream(raw, dict, sink) {
@@ -17,6 +18,7 @@ function decodeStream(raw, dict, sink) {
17
18
  } else if (filter === "ASCII85Decode" || filter === "A85") bytes = ascii85Decode(bytes);
18
19
  else if (filter === "ASCIIHexDecode" || filter === "AHx") bytes = asciiHexDecode(bytes);
19
20
  else if (filter === "RunLengthDecode" || filter === "RL") bytes = runLengthDecode(bytes);
21
+ else if (filter === "CCITTFaxDecode" || filter === "CCF") bytes = ccittFaxDecode(bytes, parm, dict, sink);
20
22
  else if (filter === "DCTDecode" || filter === "DCT") return {
21
23
  bytes,
22
24
  remainingFilter: "DCTDecode"
@@ -38,6 +40,22 @@ function decodeStream(raw, dict, sink) {
38
40
  function applyPredictorIfPresent(data, parm, sink) {
39
41
  return applyPredictor(data, readPredictorParams(parm), sink);
40
42
  }
43
+ function ccittFaxDecode(data, parm, dict, sink) {
44
+ const parmGet = (key) => parm !== void 0 ? dictGet(parm, key) : void 0;
45
+ const rows = asNumber(parmGet("Rows")) ?? asNumber(dictGet(dict, "Height") ?? dictGet(dict, "H"));
46
+ return decodeCcittFax(data, {
47
+ k: asNumber(parmGet("K")),
48
+ columns: asNumber(parmGet("Columns")),
49
+ rows,
50
+ blackIs1: asBool(parmGet("BlackIs1")),
51
+ encodedByteAlign: asBool(parmGet("EncodedByteAlign")),
52
+ onWarning: (message) => sink({
53
+ code: "pdf/ccitt-fax-degraded",
54
+ severity: "warning",
55
+ message
56
+ })
57
+ }).bytes;
58
+ }
41
59
  function filterNames(dict) {
42
60
  const filterObj = dictGet(dict, "Filter") ?? dictGet(dict, "F");
43
61
  if (filterObj === void 0) return [];
@@ -0,0 +1,38 @@
1
+ import { r as StandardFontName } from "./afm-widths-DyDq56Ph.js";
2
+ import { t as EmbeddedFace } from "./embedded-font-CbqkKgBl.js";
3
+ import { LayoutFont } from "document-schema.js";
4
+ //#region src/font-registry.d.ts
5
+ interface ProvidedFont {
6
+ readonly family: string;
7
+ readonly bold: boolean;
8
+ readonly italic: boolean;
9
+ readonly bytes: Uint8Array<ArrayBuffer>;
10
+ }
11
+ type ResolvedFace = {
12
+ readonly kind: 'embedded';
13
+ readonly face: EmbeddedFace;
14
+ } | {
15
+ readonly kind: 'standard';
16
+ readonly standardName: StandardFontName;
17
+ readonly matched: boolean;
18
+ };
19
+ interface FontSubstitution {
20
+ readonly requestedFamily: string;
21
+ readonly requestedBold: boolean;
22
+ readonly requestedItalic: boolean;
23
+ readonly reason: 'missing-face' | 'vendored-substitute';
24
+ readonly resolvedFamily: string;
25
+ }
26
+ interface FontRegistryOptions {
27
+ readonly sourceFonts?: readonly ProvidedFont[];
28
+ readonly fonts?: readonly ProvidedFont[];
29
+ readonly substitutes?: 'vendored' | 'none';
30
+ readonly onSubstitution?: (substitution: FontSubstitution) => void;
31
+ }
32
+ interface FontRegistry {
33
+ resolve(font: LayoutFont): ResolvedFace;
34
+ }
35
+ declare function createFontRegistry(options?: FontRegistryOptions): FontRegistry;
36
+ declare function resolveFaceWithRegistry(registry: FontRegistry | undefined, font: LayoutFont): ResolvedFace;
37
+ //#endregion
38
+ export { ResolvedFace as a, ProvidedFont as i, FontRegistryOptions as n, createFontRegistry as o, FontSubstitution as r, resolveFaceWithRegistry as s, FontRegistry as t };
@@ -0,0 +1,38 @@
1
+ import { r as StandardFontName } from "./afm-widths-DyDq56Ph.cjs";
2
+ import { t as EmbeddedFace } from "./embedded-font-CLedn-mT.cjs";
3
+ import { LayoutFont } from "document-schema.js";
4
+ //#region src/font-registry.d.ts
5
+ interface ProvidedFont {
6
+ readonly family: string;
7
+ readonly bold: boolean;
8
+ readonly italic: boolean;
9
+ readonly bytes: Uint8Array<ArrayBuffer>;
10
+ }
11
+ type ResolvedFace = {
12
+ readonly kind: 'embedded';
13
+ readonly face: EmbeddedFace;
14
+ } | {
15
+ readonly kind: 'standard';
16
+ readonly standardName: StandardFontName;
17
+ readonly matched: boolean;
18
+ };
19
+ interface FontSubstitution {
20
+ readonly requestedFamily: string;
21
+ readonly requestedBold: boolean;
22
+ readonly requestedItalic: boolean;
23
+ readonly reason: 'missing-face' | 'vendored-substitute';
24
+ readonly resolvedFamily: string;
25
+ }
26
+ interface FontRegistryOptions {
27
+ readonly sourceFonts?: readonly ProvidedFont[];
28
+ readonly fonts?: readonly ProvidedFont[];
29
+ readonly substitutes?: 'vendored' | 'none';
30
+ readonly onSubstitution?: (substitution: FontSubstitution) => void;
31
+ }
32
+ interface FontRegistry {
33
+ resolve(font: LayoutFont): ResolvedFace;
34
+ }
35
+ declare function createFontRegistry(options?: FontRegistryOptions): FontRegistry;
36
+ declare function resolveFaceWithRegistry(registry: FontRegistry | undefined, font: LayoutFont): ResolvedFace;
37
+ //#endregion
38
+ export { ResolvedFace as a, ProvidedFont as i, FontRegistryOptions as n, createFontRegistry as o, FontSubstitution as r, resolveFaceWithRegistry as s, FontRegistry as t };
@@ -0,0 +1,152 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_sfnt = require("./sfnt.cjs");
3
+ const require_util_base64 = require("./util/base64.cjs");
4
+ const require_fonts = require("./fonts.cjs");
5
+ const require_embedded_font = require("./embedded-font.cjs");
6
+ const require_assets_caladea_bold = require("./assets/caladea-bold.cjs");
7
+ const require_assets_caladea_bolditalic = require("./assets/caladea-bolditalic.cjs");
8
+ const require_assets_caladea_italic = require("./assets/caladea-italic.cjs");
9
+ const require_assets_caladea_regular = require("./assets/caladea-regular.cjs");
10
+ const require_assets_carlito_bold = require("./assets/carlito-bold.cjs");
11
+ const require_assets_carlito_bolditalic = require("./assets/carlito-bolditalic.cjs");
12
+ const require_assets_carlito_italic = require("./assets/carlito-italic.cjs");
13
+ const require_assets_carlito_regular = require("./assets/carlito-regular.cjs");
14
+ const require_font_substitutes = require("./font-substitutes.cjs");
15
+ let fflate = require("fflate");
16
+ //#region src/font-registry.ts
17
+ function faceCacheKey(family, bold, italic) {
18
+ return `${require_fonts.normalizeFamilyName(family)}|${bold ? 1 : 0}|${italic ? 1 : 0}`;
19
+ }
20
+ function embedFace(bytes) {
21
+ const sfnt = require_sfnt.parseSfnt(bytes);
22
+ if (sfnt === void 0) return;
23
+ return require_embedded_font.loadEmbeddedFace(sfnt);
24
+ }
25
+ function findExactFace(list, family, bold, italic) {
26
+ const normalized = require_fonts.normalizeFamilyName(family);
27
+ return list.find((candidate) => require_fonts.normalizeFamilyName(candidate.family) === normalized && candidate.bold === bold && candidate.italic === italic);
28
+ }
29
+ function findFamilyRegular(list, family) {
30
+ const normalized = require_fonts.normalizeFamilyName(family);
31
+ const familyFaces = list.filter((candidate) => require_fonts.normalizeFamilyName(candidate.family) === normalized);
32
+ if (familyFaces.length === 0) return;
33
+ return familyFaces.find((candidate) => !candidate.bold && !candidate.italic) ?? familyFaces[0];
34
+ }
35
+ const vendoredFaceBytesCache = /* @__PURE__ */ new Map();
36
+ const VENDORED_FACE_BASE64 = {
37
+ carlito: {
38
+ regular: require_assets_carlito_regular.CARLITO_REGULAR_FONT_DEFLATED_BASE64,
39
+ bold: require_assets_carlito_bold.CARLITO_BOLD_FONT_DEFLATED_BASE64,
40
+ italic: require_assets_carlito_italic.CARLITO_ITALIC_FONT_DEFLATED_BASE64,
41
+ boldItalic: require_assets_carlito_bolditalic.CARLITO_BOLDITALIC_FONT_DEFLATED_BASE64
42
+ },
43
+ caladea: {
44
+ regular: require_assets_caladea_regular.CALADEA_REGULAR_FONT_DEFLATED_BASE64,
45
+ bold: require_assets_caladea_bold.CALADEA_BOLD_FONT_DEFLATED_BASE64,
46
+ italic: require_assets_caladea_italic.CALADEA_ITALIC_FONT_DEFLATED_BASE64,
47
+ boldItalic: require_assets_caladea_bolditalic.CALADEA_BOLDITALIC_FONT_DEFLATED_BASE64
48
+ }
49
+ };
50
+ function loadVendoredFaceBytes(family, bold, italic) {
51
+ const faceKey = bold && italic ? "boldItalic" : bold ? "bold" : italic ? "italic" : "regular";
52
+ const cacheKey = `${family}-${faceKey}`;
53
+ const cached = vendoredFaceBytesCache.get(cacheKey);
54
+ if (cached !== void 0) return cached;
55
+ const deflatedBase64 = VENDORED_FACE_BASE64[family][faceKey];
56
+ const inflated = (0, fflate.inflateSync)(require_util_base64.base64ToBytes(deflatedBase64));
57
+ const bytes = new Uint8Array(inflated.length);
58
+ bytes.set(inflated);
59
+ vendoredFaceBytesCache.set(cacheKey, bytes);
60
+ return bytes;
61
+ }
62
+ function createFontRegistry(options = {}) {
63
+ const sourceFonts = options.sourceFonts ?? [];
64
+ const fonts = options.fonts ?? [];
65
+ const substitutesEnabled = (options.substitutes ?? "vendored") === "vendored";
66
+ const onSubstitution = options.onSubstitution;
67
+ const cache = /* @__PURE__ */ new Map();
68
+ function resolveUncached(family, bold, italic) {
69
+ const sourceExact = findExactFace(sourceFonts, family, bold, italic);
70
+ if (sourceExact !== void 0) {
71
+ const face = embedFace(sourceExact.bytes);
72
+ if (face !== void 0) return {
73
+ kind: "embedded",
74
+ face
75
+ };
76
+ }
77
+ const callerExact = findExactFace(fonts, family, bold, italic);
78
+ if (callerExact !== void 0) {
79
+ const face = embedFace(callerExact.bytes);
80
+ if (face !== void 0) return {
81
+ kind: "embedded",
82
+ face
83
+ };
84
+ }
85
+ const sourceFamilyRegular = findFamilyRegular(sourceFonts, family);
86
+ const callerFamilyRegular = sourceFamilyRegular === void 0 ? findFamilyRegular(fonts, family) : void 0;
87
+ const familyRegular = sourceFamilyRegular ?? callerFamilyRegular;
88
+ if (familyRegular !== void 0) {
89
+ const face = embedFace(familyRegular.bytes);
90
+ if (face !== void 0) {
91
+ onSubstitution?.({
92
+ requestedFamily: family,
93
+ requestedBold: bold,
94
+ requestedItalic: italic,
95
+ reason: "missing-face",
96
+ resolvedFamily: family
97
+ });
98
+ return {
99
+ kind: "embedded",
100
+ face
101
+ };
102
+ }
103
+ }
104
+ if (substitutesEnabled) {
105
+ const vendoredFamily = require_font_substitutes.resolveVendoredSubstituteFamily(family);
106
+ if (vendoredFamily !== void 0) {
107
+ const face = embedFace(loadVendoredFaceBytes(vendoredFamily, bold, italic));
108
+ if (face !== void 0) {
109
+ onSubstitution?.({
110
+ requestedFamily: family,
111
+ requestedBold: bold,
112
+ requestedItalic: italic,
113
+ reason: "vendored-substitute",
114
+ resolvedFamily: vendoredFamily
115
+ });
116
+ return {
117
+ kind: "embedded",
118
+ face
119
+ };
120
+ }
121
+ }
122
+ }
123
+ const standard = require_fonts.resolveStandardFont(family, bold, italic);
124
+ return {
125
+ kind: "standard",
126
+ standardName: standard.standardName,
127
+ matched: standard.matched
128
+ };
129
+ }
130
+ return { resolve(font) {
131
+ const bold = font.weight === "bold";
132
+ const italic = font.style === "italic";
133
+ const key = faceCacheKey(font.family, bold, italic);
134
+ const cached = cache.get(key);
135
+ if (cached !== void 0) return cached;
136
+ const resolved = resolveUncached(font.family, bold, italic);
137
+ cache.set(key, resolved);
138
+ return resolved;
139
+ } };
140
+ }
141
+ function resolveFaceWithRegistry(registry, font) {
142
+ if (registry !== void 0) return registry.resolve(font);
143
+ const standard = require_fonts.resolveStandardFont(font.family, font.weight === "bold", font.style === "italic");
144
+ return {
145
+ kind: "standard",
146
+ standardName: standard.standardName,
147
+ matched: standard.matched
148
+ };
149
+ }
150
+ //#endregion
151
+ exports.createFontRegistry = createFontRegistry;
152
+ exports.resolveFaceWithRegistry = resolveFaceWithRegistry;
@@ -0,0 +1,2 @@
1
+ import { a as ResolvedFace, i as ProvidedFont, n as FontRegistryOptions, o as createFontRegistry, r as FontSubstitution, s as resolveFaceWithRegistry, t as FontRegistry } from "./font-registry-yby02snZ.cjs";
2
+ export { FontRegistry, FontRegistryOptions, FontSubstitution, ProvidedFont, ResolvedFace, createFontRegistry, resolveFaceWithRegistry };
@@ -0,0 +1,2 @@
1
+ import { a as ResolvedFace, i as ProvidedFont, n as FontRegistryOptions, o as createFontRegistry, r as FontSubstitution, s as resolveFaceWithRegistry, t as FontRegistry } from "./font-registry-Cn7P9lAh.js";
2
+ export { FontRegistry, FontRegistryOptions, FontSubstitution, ProvidedFont, ResolvedFace, createFontRegistry, resolveFaceWithRegistry };