pdfkit 0.17.2 → 0.19.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/.yarn/install-state.gz +0 -0
- package/.yarn/releases/yarn-4.10.3.cjs +942 -0
- package/.yarnrc.yml +3 -0
- package/CHANGELOG.md +163 -134
- package/LICENSE +7 -7
- package/README.md +189 -182
- package/js/data/Courier-Bold.afm +342 -342
- package/js/data/Courier-BoldOblique.afm +342 -342
- package/js/data/Courier-Oblique.afm +342 -342
- package/js/data/Courier.afm +342 -342
- package/js/data/Helvetica-Bold.afm +2827 -2827
- package/js/data/Helvetica-BoldOblique.afm +2827 -2827
- package/js/data/Helvetica-Oblique.afm +3051 -3051
- package/js/data/Helvetica.afm +3051 -3051
- package/js/data/Symbol.afm +213 -213
- package/js/data/Times-Bold.afm +2588 -2588
- package/js/data/Times-BoldItalic.afm +2384 -2384
- package/js/data/Times-Italic.afm +2667 -2667
- package/js/data/Times-Roman.afm +2419 -2419
- package/js/data/ZapfDingbats.afm +225 -225
- package/js/pdfkit.es.js +679 -407
- package/js/pdfkit.es.js.map +1 -1
- package/js/pdfkit.js +605 -246
- package/js/pdfkit.js.map +1 -1
- package/js/pdfkit.standalone.js +27578 -31717
- package/js/virtual-fs.js +1 -3
- package/jsconfig.json +12 -12
- package/package.json +83 -92
- package/rollup.config.mjs +124 -0
- package/types/jest.custom-matchers.d.ts +28 -28
- package/vitest.config.js +11 -0
- package/js/pdfkit.es5.js +0 -7493
- package/js/pdfkit.es5.js.map +0 -1
- package/js/pdfkit.esnext.js +0 -6782
- package/js/pdfkit.esnext.js.map +0 -1
package/js/pdfkit.es.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import stream from 'stream';
|
|
2
2
|
import zlib from 'zlib';
|
|
3
|
-
import
|
|
3
|
+
import { concatBytes } from '@noble/hashes/utils';
|
|
4
|
+
import md5 from 'js-md5';
|
|
5
|
+
import { sha256 } from '@noble/hashes/sha2';
|
|
6
|
+
import { cbc, ecb } from '@noble/ciphers/aes';
|
|
4
7
|
import fs from 'fs';
|
|
5
|
-
import
|
|
6
|
-
import { EventEmitter } from 'events';
|
|
8
|
+
import { create } from 'fontkit';
|
|
7
9
|
import LineBreaker from 'linebreak';
|
|
8
|
-
import exif from 'jpeg-exif';
|
|
9
10
|
import PNG from 'png-js';
|
|
10
11
|
|
|
11
12
|
class PDFAbstractReference {
|
|
@@ -15,8 +16,7 @@ class PDFAbstractReference {
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
class PDFTree {
|
|
18
|
-
constructor() {
|
|
19
|
-
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
19
|
+
constructor(options = {}) {
|
|
20
20
|
this._items = {};
|
|
21
21
|
this.limits = typeof options.limits === 'boolean' ? options.limits : true;
|
|
22
22
|
}
|
|
@@ -58,7 +58,7 @@ class SpotColor {
|
|
|
58
58
|
this.id = 'CS' + Object.keys(doc.spotColors).length;
|
|
59
59
|
this.name = name;
|
|
60
60
|
this.values = [C, M, Y, K];
|
|
61
|
-
this.ref = doc.ref(['Separation', this.name, 'DeviceCMYK', {
|
|
61
|
+
this.ref = doc.ref(['Separation', escapeName(this.name), 'DeviceCMYK', {
|
|
62
62
|
Range: [0, 1, 0, 1, 0, 1, 0, 1],
|
|
63
63
|
C0: [0, 0, 0, 0],
|
|
64
64
|
C1: this.values.map(value => value / 100),
|
|
@@ -74,6 +74,10 @@ class SpotColor {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
const pad = (str, length) => (Array(length + 1).join('0') + str).slice(-length);
|
|
77
|
+
const isSafeCharCode = code => {
|
|
78
|
+
if (code > 0x7f) return true;
|
|
79
|
+
return code > 0x20 && code !== 0x7f && code !== 0x23 && code !== 0x25 && code !== 0x28 && code !== 0x29 && code !== 0x2f && code !== 0x3c && code !== 0x3e && code !== 0x5b && code !== 0x5d && code !== 0x7b && code !== 0x7d;
|
|
80
|
+
};
|
|
77
81
|
const escapableRe = /[\n\r\t\b\f()\\]/g;
|
|
78
82
|
const escapable = {
|
|
79
83
|
'\n': '\\n',
|
|
@@ -85,6 +89,18 @@ const escapable = {
|
|
|
85
89
|
'(': '\\(',
|
|
86
90
|
')': '\\)'
|
|
87
91
|
};
|
|
92
|
+
const escapeName = function (name) {
|
|
93
|
+
let escapedName = '';
|
|
94
|
+
for (const char of name) {
|
|
95
|
+
const code = char.charCodeAt(0);
|
|
96
|
+
if (isSafeCharCode(code)) {
|
|
97
|
+
escapedName += char;
|
|
98
|
+
} else {
|
|
99
|
+
escapedName += `#${code.toString(16).toUpperCase().padStart(2, '0')}`;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return escapedName;
|
|
103
|
+
};
|
|
88
104
|
const swapBytes = function (buff) {
|
|
89
105
|
const l = buff.length;
|
|
90
106
|
if (l & 0x01) {
|
|
@@ -99,8 +115,7 @@ const swapBytes = function (buff) {
|
|
|
99
115
|
return buff;
|
|
100
116
|
};
|
|
101
117
|
class PDFObject {
|
|
102
|
-
static convert(object) {
|
|
103
|
-
let encryptFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
118
|
+
static convert(object, encryptFn = null) {
|
|
104
119
|
if (typeof object === 'string') {
|
|
105
120
|
return `/${object}`;
|
|
106
121
|
} else if (object instanceof String) {
|
|
@@ -162,8 +177,7 @@ class PDFObject {
|
|
|
162
177
|
}
|
|
163
178
|
|
|
164
179
|
class PDFReference extends PDFAbstractReference {
|
|
165
|
-
constructor(document, id) {
|
|
166
|
-
let data = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
180
|
+
constructor(document, id, data = {}) {
|
|
167
181
|
super();
|
|
168
182
|
this.document = document;
|
|
169
183
|
this.id = id;
|
|
@@ -235,9 +249,7 @@ function PDFNumber(n) {
|
|
|
235
249
|
}
|
|
236
250
|
return fArray[0];
|
|
237
251
|
}
|
|
238
|
-
function normalizeSides(sides) {
|
|
239
|
-
let defaultDefinition = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
|
|
240
|
-
let transformer = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : v => v;
|
|
252
|
+
function normalizeSides(sides, defaultDefinition = undefined, transformer = v => v) {
|
|
241
253
|
if (sides == null || typeof sides === 'object' && Object.keys(sides).length === 0) {
|
|
242
254
|
sides = defaultDefinition;
|
|
243
255
|
}
|
|
@@ -357,12 +369,12 @@ const SIZES = {
|
|
|
357
369
|
TABLOID: [792.0, 1224.0]
|
|
358
370
|
};
|
|
359
371
|
class PDFPage {
|
|
360
|
-
constructor(document) {
|
|
361
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
372
|
+
constructor(document, options = {}) {
|
|
362
373
|
this.document = document;
|
|
363
374
|
this._options = options;
|
|
364
375
|
this.size = options.size || 'letter';
|
|
365
376
|
this.layout = options.layout || 'portrait';
|
|
377
|
+
this.userUnit = options.userUnit || 1.0;
|
|
366
378
|
const dimensions = Array.isArray(this.size) ? this.size : SIZES[this.size.toUpperCase()];
|
|
367
379
|
this.width = dimensions[this.layout === 'portrait' ? 0 : 1];
|
|
368
380
|
this.height = dimensions[this.layout === 'portrait' ? 1 : 0];
|
|
@@ -378,7 +390,8 @@ class PDFPage {
|
|
|
378
390
|
Parent: this.document._root.data.Pages,
|
|
379
391
|
MediaBox: [0, 0, this.width, this.height],
|
|
380
392
|
Contents: this.content,
|
|
381
|
-
Resources: this.resources
|
|
393
|
+
Resources: this.resources,
|
|
394
|
+
UserUnit: this.userUnit
|
|
382
395
|
});
|
|
383
396
|
this.markings = [];
|
|
384
397
|
}
|
|
@@ -451,6 +464,54 @@ class PDFNameTree extends PDFTree {
|
|
|
451
464
|
}
|
|
452
465
|
}
|
|
453
466
|
|
|
467
|
+
function md5Hash(data) {
|
|
468
|
+
return new Uint8Array(md5.arrayBuffer(data));
|
|
469
|
+
}
|
|
470
|
+
function md5Hex(data) {
|
|
471
|
+
return md5(data);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
function sha256Hash(data) {
|
|
475
|
+
return sha256(data);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function aesCbcEncrypt(data, key, iv, padding = true) {
|
|
479
|
+
return cbc(key, iv, {
|
|
480
|
+
disablePadding: !padding
|
|
481
|
+
}).encrypt(data);
|
|
482
|
+
}
|
|
483
|
+
function aesEcbEncrypt(data, key) {
|
|
484
|
+
return ecb(key, {
|
|
485
|
+
disablePadding: true
|
|
486
|
+
}).encrypt(data);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
function rc4(data, key) {
|
|
490
|
+
const s = new Uint8Array(256);
|
|
491
|
+
for (let i = 0; i < 256; i++) {
|
|
492
|
+
s[i] = i;
|
|
493
|
+
}
|
|
494
|
+
let j = 0;
|
|
495
|
+
for (let i = 0; i < 256; i++) {
|
|
496
|
+
j = j + s[i] + key[i % key.length] & 0xff;
|
|
497
|
+
[s[i], s[j]] = [s[j], s[i]];
|
|
498
|
+
}
|
|
499
|
+
const output = new Uint8Array(data.length);
|
|
500
|
+
for (let i = 0, j = 0, k = 0; k < data.length; k++) {
|
|
501
|
+
i = i + 1 & 0xff;
|
|
502
|
+
j = j + s[i] & 0xff;
|
|
503
|
+
[s[i], s[j]] = [s[j], s[i]];
|
|
504
|
+
output[k] = data[k] ^ s[s[i] + s[j] & 0xff];
|
|
505
|
+
}
|
|
506
|
+
return output;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function randomBytes(length) {
|
|
510
|
+
const bytes = new Uint8Array(length);
|
|
511
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
512
|
+
return bytes;
|
|
513
|
+
}
|
|
514
|
+
|
|
454
515
|
function inRange(value, rangeGroup) {
|
|
455
516
|
if (value < rangeGroup[0]) return false;
|
|
456
517
|
let startRange = 0;
|
|
@@ -507,8 +568,7 @@ function toCodePoints(input) {
|
|
|
507
568
|
}
|
|
508
569
|
return codepoints;
|
|
509
570
|
}
|
|
510
|
-
function saslprep(input) {
|
|
511
|
-
let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
571
|
+
function saslprep(input, opts = {}) {
|
|
512
572
|
if (typeof input !== 'string') {
|
|
513
573
|
throw new TypeError('Expected string.');
|
|
514
574
|
}
|
|
@@ -542,8 +602,7 @@ function saslprep(input) {
|
|
|
542
602
|
}
|
|
543
603
|
|
|
544
604
|
class PDFSecurity {
|
|
545
|
-
static generateFileID() {
|
|
546
|
-
let info = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
605
|
+
static generateFileID(info = {}) {
|
|
547
606
|
let infoStr = `${info.CreationDate.getTime()}\n`;
|
|
548
607
|
for (let key in info) {
|
|
549
608
|
if (!info.hasOwnProperty(key)) {
|
|
@@ -551,20 +610,18 @@ class PDFSecurity {
|
|
|
551
610
|
}
|
|
552
611
|
infoStr += `${key}: ${info[key].valueOf()}\n`;
|
|
553
612
|
}
|
|
554
|
-
return
|
|
613
|
+
return Buffer.from(md5Hash(infoStr));
|
|
555
614
|
}
|
|
556
615
|
static generateRandomWordArray(bytes) {
|
|
557
|
-
return
|
|
616
|
+
return randomBytes(bytes);
|
|
558
617
|
}
|
|
559
|
-
static create(document) {
|
|
560
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
618
|
+
static create(document, options = {}) {
|
|
561
619
|
if (!options.ownerPassword && !options.userPassword) {
|
|
562
620
|
return null;
|
|
563
621
|
}
|
|
564
622
|
return new PDFSecurity(document, options);
|
|
565
623
|
}
|
|
566
|
-
constructor(document) {
|
|
567
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
624
|
+
constructor(document, options = {}) {
|
|
568
625
|
if (!options.ownerPassword && !options.userPassword) {
|
|
569
626
|
throw new Error('None of owner password and user password is defined.');
|
|
570
627
|
}
|
|
@@ -648,8 +705,8 @@ class PDFSecurity {
|
|
|
648
705
|
encDict.StrF = 'StdCF';
|
|
649
706
|
}
|
|
650
707
|
encDict.R = r;
|
|
651
|
-
encDict.O =
|
|
652
|
-
encDict.U =
|
|
708
|
+
encDict.O = Buffer.from(ownerPasswordEntry);
|
|
709
|
+
encDict.U = Buffer.from(userPasswordEntry);
|
|
653
710
|
encDict.P = permissions;
|
|
654
711
|
}
|
|
655
712
|
_setupEncryptionV5(encDict, options) {
|
|
@@ -659,10 +716,10 @@ class PDFSecurity {
|
|
|
659
716
|
const processedOwnerPassword = options.ownerPassword ? processPasswordR5(options.ownerPassword) : processedUserPassword;
|
|
660
717
|
this.encryptionKey = getEncryptionKeyR5(PDFSecurity.generateRandomWordArray);
|
|
661
718
|
const userPasswordEntry = getUserPasswordR5(processedUserPassword, PDFSecurity.generateRandomWordArray);
|
|
662
|
-
const userKeySalt =
|
|
719
|
+
const userKeySalt = userPasswordEntry.slice(40, 48);
|
|
663
720
|
const userEncryptionKeyEntry = getUserEncryptionKeyR5(processedUserPassword, userKeySalt, this.encryptionKey);
|
|
664
721
|
const ownerPasswordEntry = getOwnerPasswordR5(processedOwnerPassword, userPasswordEntry, PDFSecurity.generateRandomWordArray);
|
|
665
|
-
const ownerKeySalt =
|
|
722
|
+
const ownerKeySalt = ownerPasswordEntry.slice(40, 48);
|
|
666
723
|
const ownerEncryptionKeyEntry = getOwnerEncryptionKeyR5(processedOwnerPassword, ownerKeySalt, userPasswordEntry, this.encryptionKey);
|
|
667
724
|
const permsEntry = getEncryptedPermissionsR5(permissions, this.encryptionKey, PDFSecurity.generateRandomWordArray);
|
|
668
725
|
encDict.V = 5;
|
|
@@ -677,43 +734,43 @@ class PDFSecurity {
|
|
|
677
734
|
encDict.StmF = 'StdCF';
|
|
678
735
|
encDict.StrF = 'StdCF';
|
|
679
736
|
encDict.R = 5;
|
|
680
|
-
encDict.O =
|
|
681
|
-
encDict.OE =
|
|
682
|
-
encDict.U =
|
|
683
|
-
encDict.UE =
|
|
737
|
+
encDict.O = Buffer.from(ownerPasswordEntry);
|
|
738
|
+
encDict.OE = Buffer.from(ownerEncryptionKeyEntry);
|
|
739
|
+
encDict.U = Buffer.from(userPasswordEntry);
|
|
740
|
+
encDict.UE = Buffer.from(userEncryptionKeyEntry);
|
|
684
741
|
encDict.P = permissions;
|
|
685
|
-
encDict.Perms =
|
|
742
|
+
encDict.Perms = Buffer.from(permsEntry);
|
|
686
743
|
}
|
|
687
744
|
getEncryptFn(obj, gen) {
|
|
688
745
|
let digest;
|
|
689
746
|
if (this.version < 5) {
|
|
690
|
-
|
|
747
|
+
const suffix = new Uint8Array([obj & 0xff, obj >> 8 & 0xff, obj >> 16 & 0xff, gen & 0xff, gen >> 8 & 0xff]);
|
|
748
|
+
digest = concatBytes(this.encryptionKey, suffix);
|
|
691
749
|
}
|
|
692
750
|
if (this.version === 1 || this.version === 2) {
|
|
693
|
-
let key =
|
|
694
|
-
|
|
695
|
-
|
|
751
|
+
let key = md5Hash(digest);
|
|
752
|
+
const keyLen = Math.min(16, this.keyBits / 8 + 5);
|
|
753
|
+
key = key.slice(0, keyLen);
|
|
754
|
+
return buffer => Buffer.from(rc4(new Uint8Array(buffer), key));
|
|
696
755
|
}
|
|
697
756
|
let key;
|
|
698
757
|
if (this.version === 4) {
|
|
699
|
-
|
|
758
|
+
const saltMarker = new Uint8Array([0x73, 0x41, 0x6c, 0x54]);
|
|
759
|
+
key = md5Hash(concatBytes(digest, saltMarker));
|
|
700
760
|
} else {
|
|
701
761
|
key = this.encryptionKey;
|
|
702
762
|
}
|
|
703
763
|
const iv = PDFSecurity.generateRandomWordArray(16);
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
iv
|
|
764
|
+
return buffer => {
|
|
765
|
+
const encrypted = aesCbcEncrypt(new Uint8Array(buffer), key, iv, true);
|
|
766
|
+
return Buffer.from(concatBytes(iv, encrypted));
|
|
708
767
|
};
|
|
709
|
-
return buffer => wordArrayToBuffer(iv.clone().concat(CryptoJS.AES.encrypt(CryptoJS.lib.WordArray.create(buffer), key, options).ciphertext));
|
|
710
768
|
}
|
|
711
769
|
end() {
|
|
712
770
|
this.dictionary.end();
|
|
713
771
|
}
|
|
714
772
|
}
|
|
715
|
-
function getPermissionsR2() {
|
|
716
|
-
let permissionObject = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
773
|
+
function getPermissionsR2(permissionObject = {}) {
|
|
717
774
|
let permissions = 0xffffffc0 >> 0;
|
|
718
775
|
if (permissionObject.printing) {
|
|
719
776
|
permissions |= 0b000000000100;
|
|
@@ -729,8 +786,7 @@ function getPermissionsR2() {
|
|
|
729
786
|
}
|
|
730
787
|
return permissions;
|
|
731
788
|
}
|
|
732
|
-
function getPermissionsR3() {
|
|
733
|
-
let permissionObject = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
789
|
+
function getPermissionsR3(permissionObject = {}) {
|
|
734
790
|
let permissions = 0xfffff0c0 >> 0;
|
|
735
791
|
if (permissionObject.printing === 'lowResolution') {
|
|
736
792
|
permissions |= 0b000000000100;
|
|
@@ -759,90 +815,97 @@ function getPermissionsR3() {
|
|
|
759
815
|
return permissions;
|
|
760
816
|
}
|
|
761
817
|
function getUserPasswordR2(encryptionKey) {
|
|
762
|
-
return
|
|
818
|
+
return rc4(processPasswordR2R3R4(), encryptionKey);
|
|
763
819
|
}
|
|
764
820
|
function getUserPasswordR3R4(documentId, encryptionKey) {
|
|
765
|
-
const key = encryptionKey.
|
|
766
|
-
let cipher =
|
|
821
|
+
const key = encryptionKey.slice();
|
|
822
|
+
let cipher = md5Hash(concatBytes(processPasswordR2R3R4(), new Uint8Array(documentId)));
|
|
767
823
|
for (let i = 0; i < 20; i++) {
|
|
768
|
-
const
|
|
769
|
-
for (let j = 0; j <
|
|
770
|
-
|
|
824
|
+
const xorKey = new Uint8Array(key.length);
|
|
825
|
+
for (let j = 0; j < key.length; j++) {
|
|
826
|
+
xorKey[j] = encryptionKey[j] ^ i;
|
|
771
827
|
}
|
|
772
|
-
cipher =
|
|
828
|
+
cipher = rc4(cipher, xorKey);
|
|
773
829
|
}
|
|
774
|
-
|
|
830
|
+
const result = new Uint8Array(32);
|
|
831
|
+
result.set(cipher);
|
|
832
|
+
return result;
|
|
775
833
|
}
|
|
776
834
|
function getOwnerPasswordR2R3R4(r, keyBits, paddedUserPassword, paddedOwnerPassword) {
|
|
777
835
|
let digest = paddedOwnerPassword;
|
|
778
836
|
let round = r >= 3 ? 51 : 1;
|
|
779
837
|
for (let i = 0; i < round; i++) {
|
|
780
|
-
digest =
|
|
838
|
+
digest = md5Hash(digest);
|
|
781
839
|
}
|
|
782
|
-
const
|
|
783
|
-
key
|
|
840
|
+
const keyLen = keyBits / 8;
|
|
841
|
+
let key = digest.slice(0, keyLen);
|
|
784
842
|
let cipher = paddedUserPassword;
|
|
785
843
|
round = r >= 3 ? 20 : 1;
|
|
786
844
|
for (let i = 0; i < round; i++) {
|
|
787
|
-
const
|
|
788
|
-
for (let j = 0; j <
|
|
789
|
-
|
|
845
|
+
const xorKey = new Uint8Array(keyLen);
|
|
846
|
+
for (let j = 0; j < keyLen; j++) {
|
|
847
|
+
xorKey[j] = key[j] ^ i;
|
|
790
848
|
}
|
|
791
|
-
cipher =
|
|
849
|
+
cipher = rc4(cipher, xorKey);
|
|
792
850
|
}
|
|
793
851
|
return cipher;
|
|
794
852
|
}
|
|
795
853
|
function getEncryptionKeyR2R3R4(r, keyBits, documentId, paddedUserPassword, ownerPasswordEntry, permissions) {
|
|
796
|
-
|
|
854
|
+
const permBytes = new Uint8Array([permissions & 0xff, permissions >> 8 & 0xff, permissions >> 16 & 0xff, permissions >> 24 & 0xff]);
|
|
855
|
+
let key = concatBytes(paddedUserPassword, ownerPasswordEntry, permBytes, new Uint8Array(documentId));
|
|
797
856
|
const round = r >= 3 ? 51 : 1;
|
|
857
|
+
const keyLen = keyBits / 8;
|
|
798
858
|
for (let i = 0; i < round; i++) {
|
|
799
|
-
key =
|
|
800
|
-
key
|
|
859
|
+
key = md5Hash(key);
|
|
860
|
+
key = key.slice(0, keyLen);
|
|
801
861
|
}
|
|
802
862
|
return key;
|
|
803
863
|
}
|
|
804
864
|
function getUserPasswordR5(processedUserPassword, generateRandomWordArray) {
|
|
805
865
|
const validationSalt = generateRandomWordArray(8);
|
|
806
866
|
const keySalt = generateRandomWordArray(8);
|
|
807
|
-
|
|
867
|
+
const hash = sha256Hash(concatBytes(processedUserPassword, validationSalt));
|
|
868
|
+
return concatBytes(hash, validationSalt, keySalt);
|
|
808
869
|
}
|
|
809
870
|
function getUserEncryptionKeyR5(processedUserPassword, userKeySalt, encryptionKey) {
|
|
810
|
-
const key =
|
|
811
|
-
const
|
|
812
|
-
|
|
813
|
-
padding: CryptoJS.pad.NoPadding,
|
|
814
|
-
iv: CryptoJS.lib.WordArray.create(null, 16)
|
|
815
|
-
};
|
|
816
|
-
return CryptoJS.AES.encrypt(encryptionKey, key, options).ciphertext;
|
|
871
|
+
const key = sha256Hash(concatBytes(processedUserPassword, userKeySalt));
|
|
872
|
+
const iv = new Uint8Array(16);
|
|
873
|
+
return aesCbcEncrypt(encryptionKey, key, iv, false);
|
|
817
874
|
}
|
|
818
875
|
function getOwnerPasswordR5(processedOwnerPassword, userPasswordEntry, generateRandomWordArray) {
|
|
819
876
|
const validationSalt = generateRandomWordArray(8);
|
|
820
877
|
const keySalt = generateRandomWordArray(8);
|
|
821
|
-
|
|
878
|
+
const hash = sha256Hash(concatBytes(processedOwnerPassword, validationSalt, userPasswordEntry));
|
|
879
|
+
return concatBytes(hash, validationSalt, keySalt);
|
|
822
880
|
}
|
|
823
881
|
function getOwnerEncryptionKeyR5(processedOwnerPassword, ownerKeySalt, userPasswordEntry, encryptionKey) {
|
|
824
|
-
const key =
|
|
825
|
-
const
|
|
826
|
-
|
|
827
|
-
padding: CryptoJS.pad.NoPadding,
|
|
828
|
-
iv: CryptoJS.lib.WordArray.create(null, 16)
|
|
829
|
-
};
|
|
830
|
-
return CryptoJS.AES.encrypt(encryptionKey, key, options).ciphertext;
|
|
882
|
+
const key = sha256Hash(concatBytes(processedOwnerPassword, ownerKeySalt, userPasswordEntry));
|
|
883
|
+
const iv = new Uint8Array(16);
|
|
884
|
+
return aesCbcEncrypt(encryptionKey, key, iv, false);
|
|
831
885
|
}
|
|
832
886
|
function getEncryptionKeyR5(generateRandomWordArray) {
|
|
833
887
|
return generateRandomWordArray(32);
|
|
834
888
|
}
|
|
835
889
|
function getEncryptedPermissionsR5(permissions, encryptionKey, generateRandomWordArray) {
|
|
836
|
-
const
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
890
|
+
const data = new Uint8Array(16);
|
|
891
|
+
data[0] = permissions & 0xff;
|
|
892
|
+
data[1] = permissions >> 8 & 0xff;
|
|
893
|
+
data[2] = permissions >> 16 & 0xff;
|
|
894
|
+
data[3] = permissions >> 24 & 0xff;
|
|
895
|
+
data[4] = 0xff;
|
|
896
|
+
data[5] = 0xff;
|
|
897
|
+
data[6] = 0xff;
|
|
898
|
+
data[7] = 0xff;
|
|
899
|
+
data[8] = 0x54;
|
|
900
|
+
data[9] = 0x61;
|
|
901
|
+
data[10] = 0x64;
|
|
902
|
+
data[11] = 0x62;
|
|
903
|
+
const randomPart = generateRandomWordArray(4);
|
|
904
|
+
data.set(randomPart, 12);
|
|
905
|
+
return aesEcbEncrypt(data, encryptionKey);
|
|
842
906
|
}
|
|
843
|
-
function processPasswordR2R3R4() {
|
|
844
|
-
|
|
845
|
-
const out = Buffer.alloc(32);
|
|
907
|
+
function processPasswordR2R3R4(password = '') {
|
|
908
|
+
const out = new Uint8Array(32);
|
|
846
909
|
const length = password.length;
|
|
847
910
|
let index = 0;
|
|
848
911
|
while (index < length && index < 32) {
|
|
@@ -857,34 +920,23 @@ function processPasswordR2R3R4() {
|
|
|
857
920
|
out[index] = PASSWORD_PADDING[index - length];
|
|
858
921
|
index++;
|
|
859
922
|
}
|
|
860
|
-
return
|
|
923
|
+
return out;
|
|
861
924
|
}
|
|
862
|
-
function processPasswordR5() {
|
|
863
|
-
let password = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
|
925
|
+
function processPasswordR5(password = '') {
|
|
864
926
|
password = unescape(encodeURIComponent(saslprep(password)));
|
|
865
927
|
const length = Math.min(127, password.length);
|
|
866
|
-
const out =
|
|
928
|
+
const out = new Uint8Array(length);
|
|
867
929
|
for (let i = 0; i < length; i++) {
|
|
868
930
|
out[i] = password.charCodeAt(i);
|
|
869
931
|
}
|
|
870
|
-
return
|
|
871
|
-
}
|
|
872
|
-
function lsbFirstWord(data) {
|
|
873
|
-
return (data & 0xff) << 24 | (data & 0xff00) << 8 | data >> 8 & 0xff00 | data >> 24 & 0xff;
|
|
874
|
-
}
|
|
875
|
-
function wordArrayToBuffer(wordArray) {
|
|
876
|
-
const byteArray = [];
|
|
877
|
-
for (let i = 0; i < wordArray.sigBytes; i++) {
|
|
878
|
-
byteArray.push(wordArray.words[Math.floor(i / 4)] >> 8 * (3 - i % 4) & 0xff);
|
|
879
|
-
}
|
|
880
|
-
return Buffer.from(byteArray);
|
|
932
|
+
return out;
|
|
881
933
|
}
|
|
882
934
|
const PASSWORD_PADDING = [0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a];
|
|
883
935
|
|
|
884
936
|
const {
|
|
885
937
|
number: number$2
|
|
886
938
|
} = PDFObject;
|
|
887
|
-
|
|
939
|
+
let PDFGradient$1 = class PDFGradient {
|
|
888
940
|
constructor(doc) {
|
|
889
941
|
this.doc = doc;
|
|
890
942
|
this.stops = [];
|
|
@@ -1042,8 +1094,8 @@ class PDFGradient$1 {
|
|
|
1042
1094
|
const op = stroke ? 'SCN' : 'scn';
|
|
1043
1095
|
return this.doc.addContent(`/${this.id} ${op}`);
|
|
1044
1096
|
}
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1097
|
+
};
|
|
1098
|
+
let PDFLinearGradient$1 = class PDFLinearGradient extends PDFGradient$1 {
|
|
1047
1099
|
constructor(doc, x1, y1, x2, y2) {
|
|
1048
1100
|
super(doc);
|
|
1049
1101
|
this.x1 = x1;
|
|
@@ -1061,10 +1113,10 @@ class PDFLinearGradient$1 extends PDFGradient$1 {
|
|
|
1061
1113
|
});
|
|
1062
1114
|
}
|
|
1063
1115
|
opacityGradient() {
|
|
1064
|
-
return new PDFLinearGradient
|
|
1116
|
+
return new PDFLinearGradient(this.doc, this.x1, this.y1, this.x2, this.y2);
|
|
1065
1117
|
}
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1118
|
+
};
|
|
1119
|
+
let PDFRadialGradient$1 = class PDFRadialGradient extends PDFGradient$1 {
|
|
1068
1120
|
constructor(doc, x1, y1, r1, x2, y2, r2) {
|
|
1069
1121
|
super(doc);
|
|
1070
1122
|
this.doc = doc;
|
|
@@ -1085,9 +1137,9 @@ class PDFRadialGradient$1 extends PDFGradient$1 {
|
|
|
1085
1137
|
});
|
|
1086
1138
|
}
|
|
1087
1139
|
opacityGradient() {
|
|
1088
|
-
return new PDFRadialGradient
|
|
1140
|
+
return new PDFRadialGradient(this.doc, this.x1, this.y1, this.r1, this.x2, this.y2, this.r2);
|
|
1089
1141
|
}
|
|
1090
|
-
}
|
|
1142
|
+
};
|
|
1091
1143
|
var Gradient = {
|
|
1092
1144
|
PDFGradient: PDFGradient$1,
|
|
1093
1145
|
PDFLinearGradient: PDFLinearGradient$1,
|
|
@@ -1095,7 +1147,7 @@ var Gradient = {
|
|
|
1095
1147
|
};
|
|
1096
1148
|
|
|
1097
1149
|
const underlyingColorSpaces = ['DeviceCMYK', 'DeviceRGB'];
|
|
1098
|
-
|
|
1150
|
+
let PDFTilingPattern$1 = class PDFTilingPattern {
|
|
1099
1151
|
constructor(doc, bBox, xStep, yStep, stream) {
|
|
1100
1152
|
this.doc = doc;
|
|
1101
1153
|
this.bBox = bBox;
|
|
@@ -1155,7 +1207,7 @@ class PDFTilingPattern$1 {
|
|
|
1155
1207
|
const op = stroke ? 'SCN' : 'scn';
|
|
1156
1208
|
return this.doc.addContent(`${normalizedColor.join(' ')} /${this.id} ${op}`);
|
|
1157
1209
|
}
|
|
1158
|
-
}
|
|
1210
|
+
};
|
|
1159
1211
|
var pattern = {
|
|
1160
1212
|
PDFTilingPattern: PDFTilingPattern$1
|
|
1161
1213
|
};
|
|
@@ -1485,86 +1537,176 @@ const parameters = {
|
|
|
1485
1537
|
Z: 0,
|
|
1486
1538
|
z: 0
|
|
1487
1539
|
};
|
|
1540
|
+
const isCommand = function (c) {
|
|
1541
|
+
return c in parameters;
|
|
1542
|
+
};
|
|
1543
|
+
const isWsp = function (c) {
|
|
1544
|
+
const codePoint = c.codePointAt(0);
|
|
1545
|
+
return codePoint === 0x20 || codePoint === 0x9 || codePoint === 0xd || codePoint === 0xa;
|
|
1546
|
+
};
|
|
1547
|
+
const isDigit = function (c) {
|
|
1548
|
+
const codePoint = c.codePointAt(0);
|
|
1549
|
+
if (codePoint == null) {
|
|
1550
|
+
return false;
|
|
1551
|
+
}
|
|
1552
|
+
return 48 <= codePoint && codePoint <= 57;
|
|
1553
|
+
};
|
|
1554
|
+
const readNumber = function (string, cursor) {
|
|
1555
|
+
let i = cursor;
|
|
1556
|
+
let value = '';
|
|
1557
|
+
let state = 'none';
|
|
1558
|
+
for (; i < string.length; i += 1) {
|
|
1559
|
+
const c = string[i];
|
|
1560
|
+
if (c === '+' || c === '-') {
|
|
1561
|
+
if (state === 'none') {
|
|
1562
|
+
state = 'sign';
|
|
1563
|
+
value += c;
|
|
1564
|
+
continue;
|
|
1565
|
+
}
|
|
1566
|
+
if (state === 'e') {
|
|
1567
|
+
state = 'exponent_sign';
|
|
1568
|
+
value += c;
|
|
1569
|
+
continue;
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
if (isDigit(c)) {
|
|
1573
|
+
if (state === 'none' || state === 'sign' || state === 'whole') {
|
|
1574
|
+
state = 'whole';
|
|
1575
|
+
value += c;
|
|
1576
|
+
continue;
|
|
1577
|
+
}
|
|
1578
|
+
if (state === 'decimal_point' || state === 'decimal') {
|
|
1579
|
+
state = 'decimal';
|
|
1580
|
+
value += c;
|
|
1581
|
+
continue;
|
|
1582
|
+
}
|
|
1583
|
+
if (state === 'e' || state === 'exponent_sign' || state === 'exponent') {
|
|
1584
|
+
state = 'exponent';
|
|
1585
|
+
value += c;
|
|
1586
|
+
continue;
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
if (c === '.') {
|
|
1590
|
+
if (state === 'none' || state === 'sign' || state === 'whole') {
|
|
1591
|
+
state = 'decimal_point';
|
|
1592
|
+
value += c;
|
|
1593
|
+
continue;
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
if (c === 'E' || c === 'e') {
|
|
1597
|
+
if (state === 'whole' || state === 'decimal_point' || state === 'decimal') {
|
|
1598
|
+
state = 'e';
|
|
1599
|
+
value += c;
|
|
1600
|
+
continue;
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
break;
|
|
1604
|
+
}
|
|
1605
|
+
const number = Number.parseFloat(value);
|
|
1606
|
+
if (Number.isNaN(number)) {
|
|
1607
|
+
return [cursor, null];
|
|
1608
|
+
}
|
|
1609
|
+
return [i - 1, number];
|
|
1610
|
+
};
|
|
1488
1611
|
const parse = function (path) {
|
|
1489
|
-
|
|
1490
|
-
|
|
1612
|
+
const pathData = [];
|
|
1613
|
+
let command = null;
|
|
1491
1614
|
let args = [];
|
|
1492
|
-
let
|
|
1493
|
-
let
|
|
1494
|
-
let
|
|
1495
|
-
for (let
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1615
|
+
let argsCount = 0;
|
|
1616
|
+
let canHaveComma = false;
|
|
1617
|
+
let hadComma = false;
|
|
1618
|
+
for (let i = 0; i < path.length; i += 1) {
|
|
1619
|
+
const c = path.charAt(i);
|
|
1620
|
+
if (isWsp(c)) {
|
|
1621
|
+
continue;
|
|
1622
|
+
}
|
|
1623
|
+
if (canHaveComma && c === ',') {
|
|
1624
|
+
if (hadComma) {
|
|
1625
|
+
break;
|
|
1626
|
+
}
|
|
1627
|
+
hadComma = true;
|
|
1628
|
+
continue;
|
|
1629
|
+
}
|
|
1630
|
+
if (isCommand(c)) {
|
|
1631
|
+
if (hadComma) {
|
|
1632
|
+
return pathData;
|
|
1633
|
+
}
|
|
1634
|
+
if (command == null) {
|
|
1635
|
+
if (c !== 'M' && c !== 'm') {
|
|
1636
|
+
return pathData;
|
|
1637
|
+
}
|
|
1638
|
+
} else {
|
|
1639
|
+
if (args.length !== 0) {
|
|
1640
|
+
return pathData;
|
|
1501
1641
|
}
|
|
1502
|
-
ret[ret.length] = {
|
|
1503
|
-
cmd,
|
|
1504
|
-
args
|
|
1505
|
-
};
|
|
1506
|
-
args = [];
|
|
1507
|
-
curArg = '';
|
|
1508
|
-
foundDecimal = false;
|
|
1509
|
-
}
|
|
1510
|
-
cmd = c;
|
|
1511
|
-
} else if ([' ', ','].includes(c) || c === '-' && curArg.length > 0 && curArg[curArg.length - 1] !== 'e' || c === '.' && foundDecimal) {
|
|
1512
|
-
if (curArg.length === 0) {
|
|
1513
|
-
continue;
|
|
1514
1642
|
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1643
|
+
command = c;
|
|
1644
|
+
args = [];
|
|
1645
|
+
argsCount = parameters[command];
|
|
1646
|
+
canHaveComma = false;
|
|
1647
|
+
if (argsCount === 0) {
|
|
1648
|
+
pathData.push({
|
|
1649
|
+
command,
|
|
1518
1650
|
args
|
|
1519
|
-
};
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
continue;
|
|
1654
|
+
}
|
|
1655
|
+
if (command == null) {
|
|
1656
|
+
return pathData;
|
|
1657
|
+
}
|
|
1658
|
+
let newCursor = i;
|
|
1659
|
+
let number = null;
|
|
1660
|
+
if (command === 'A' || command === 'a') {
|
|
1661
|
+
const position = args.length;
|
|
1662
|
+
if (position === 0 || position === 1) {
|
|
1663
|
+
if (c !== '+' && c !== '-') {
|
|
1664
|
+
[newCursor, number] = readNumber(path, i);
|
|
1523
1665
|
}
|
|
1524
|
-
|
|
1525
|
-
|
|
1666
|
+
}
|
|
1667
|
+
if (position === 2 || position === 5 || position === 6) {
|
|
1668
|
+
[newCursor, number] = readNumber(path, i);
|
|
1669
|
+
}
|
|
1670
|
+
if (position === 3 || position === 4) {
|
|
1671
|
+
if (c === '0') {
|
|
1672
|
+
number = 0;
|
|
1673
|
+
}
|
|
1674
|
+
if (c === '1') {
|
|
1675
|
+
number = 1;
|
|
1526
1676
|
}
|
|
1527
|
-
} else {
|
|
1528
|
-
args[args.length] = +curArg;
|
|
1529
1677
|
}
|
|
1530
|
-
foundDecimal = c === '.';
|
|
1531
|
-
curArg = ['-', '.'].includes(c) ? c : '';
|
|
1532
1678
|
} else {
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1679
|
+
[newCursor, number] = readNumber(path, i);
|
|
1680
|
+
}
|
|
1681
|
+
if (number == null) {
|
|
1682
|
+
return pathData;
|
|
1683
|
+
}
|
|
1684
|
+
args.push(number);
|
|
1685
|
+
canHaveComma = true;
|
|
1686
|
+
hadComma = false;
|
|
1687
|
+
i = newCursor;
|
|
1688
|
+
if (args.length === argsCount) {
|
|
1689
|
+
pathData.push({
|
|
1690
|
+
command,
|
|
1543
1691
|
args
|
|
1544
|
-
};
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
cmd = 'L';
|
|
1692
|
+
});
|
|
1693
|
+
if (command === 'M') {
|
|
1694
|
+
command = 'L';
|
|
1548
1695
|
}
|
|
1549
|
-
if (
|
|
1550
|
-
|
|
1696
|
+
if (command === 'm') {
|
|
1697
|
+
command = 'l';
|
|
1551
1698
|
}
|
|
1552
|
-
|
|
1553
|
-
args[args.length] = +curArg;
|
|
1699
|
+
args = [];
|
|
1554
1700
|
}
|
|
1555
1701
|
}
|
|
1556
|
-
|
|
1557
|
-
cmd,
|
|
1558
|
-
args
|
|
1559
|
-
};
|
|
1560
|
-
return ret;
|
|
1702
|
+
return pathData;
|
|
1561
1703
|
};
|
|
1562
1704
|
const apply = function (commands, doc) {
|
|
1563
1705
|
cx = cy = px = py = sx = sy = 0;
|
|
1564
1706
|
for (let i = 0; i < commands.length; i++) {
|
|
1565
1707
|
const c = commands[i];
|
|
1566
|
-
if (typeof runners[c.
|
|
1567
|
-
runners[c.
|
|
1708
|
+
if (typeof runners[c.command] === 'function') {
|
|
1709
|
+
runners[c.command](doc, c.args);
|
|
1568
1710
|
}
|
|
1569
1711
|
}
|
|
1570
1712
|
};
|
|
@@ -1844,8 +1986,7 @@ var VectorMixin = {
|
|
|
1844
1986
|
miterLimit(m) {
|
|
1845
1987
|
return this.addContent(`${number$1(m)} M`);
|
|
1846
1988
|
},
|
|
1847
|
-
dash(length) {
|
|
1848
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
1989
|
+
dash(length, options = {}) {
|
|
1849
1990
|
const originalLength = length;
|
|
1850
1991
|
if (!Array.isArray(length)) {
|
|
1851
1992
|
length = [length, options.space || length];
|
|
@@ -1875,21 +2016,42 @@ var VectorMixin = {
|
|
|
1875
2016
|
rect(x, y, w, h) {
|
|
1876
2017
|
return this.addContent(`${number$1(x)} ${number$1(y)} ${number$1(w)} ${number$1(h)} re`);
|
|
1877
2018
|
},
|
|
1878
|
-
roundedRect(x, y, w, h,
|
|
1879
|
-
if (
|
|
1880
|
-
|
|
1881
|
-
}
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
2019
|
+
roundedRect(x, y, w, h, borderRadius) {
|
|
2020
|
+
if (borderRadius == null) {
|
|
2021
|
+
borderRadius = 0;
|
|
2022
|
+
}
|
|
2023
|
+
let radii;
|
|
2024
|
+
if (Array.isArray(borderRadius)) {
|
|
2025
|
+
radii = borderRadius.slice(0, 4);
|
|
2026
|
+
} else {
|
|
2027
|
+
radii = [borderRadius, borderRadius, borderRadius, borderRadius];
|
|
2028
|
+
}
|
|
2029
|
+
const limit = Math.min(0.5 * w, 0.5 * h);
|
|
2030
|
+
const rTL = Math.max(0, Math.min(radii[0] || 0, limit));
|
|
2031
|
+
const rTR = Math.max(0, Math.min(radii[1] || 0, limit));
|
|
2032
|
+
const rBR = Math.max(0, Math.min(radii[2] || 0, limit));
|
|
2033
|
+
const rBL = Math.max(0, Math.min(radii[3] || 0, limit));
|
|
2034
|
+
const cpTR = rTR * (1.0 - KAPPA);
|
|
2035
|
+
const cpBR = rBR * (1.0 - KAPPA);
|
|
2036
|
+
const cpBL = rBL * (1.0 - KAPPA);
|
|
2037
|
+
const cpTL = rTL * (1.0 - KAPPA);
|
|
2038
|
+
this.moveTo(x + rTL, y);
|
|
2039
|
+
this.lineTo(x + w - rTR, y);
|
|
2040
|
+
if (rTR > 0) {
|
|
2041
|
+
this.bezierCurveTo(x + w - cpTR, y, x + w, y + cpTR, x + w, y + rTR);
|
|
2042
|
+
}
|
|
2043
|
+
this.lineTo(x + w, y + h - rBR);
|
|
2044
|
+
if (rBR > 0) {
|
|
2045
|
+
this.bezierCurveTo(x + w, y + h - cpBR, x + w - cpBR, y + h, x + w - rBR, y + h);
|
|
2046
|
+
}
|
|
2047
|
+
this.lineTo(x + rBL, y + h);
|
|
2048
|
+
if (rBL > 0) {
|
|
2049
|
+
this.bezierCurveTo(x + cpBL, y + h, x, y + h - cpBL, x, y + h - rBL);
|
|
2050
|
+
}
|
|
2051
|
+
this.lineTo(x, y + rTL);
|
|
2052
|
+
if (rTL > 0) {
|
|
2053
|
+
this.bezierCurveTo(x, y + cpTL, x + cpTL, y, x + rTL, y);
|
|
2054
|
+
}
|
|
1893
2055
|
return this.closePath();
|
|
1894
2056
|
},
|
|
1895
2057
|
ellipse(x, y, r1, r2) {
|
|
@@ -1950,10 +2112,7 @@ var VectorMixin = {
|
|
|
1950
2112
|
}
|
|
1951
2113
|
return this;
|
|
1952
2114
|
},
|
|
1953
|
-
polygon() {
|
|
1954
|
-
for (var _len = arguments.length, points = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
1955
|
-
points[_key] = arguments[_key];
|
|
1956
|
-
}
|
|
2115
|
+
polygon(...points) {
|
|
1957
2116
|
this.moveTo(...(points.shift() || []));
|
|
1958
2117
|
for (let point of points) {
|
|
1959
2118
|
this.lineTo(...(point || []));
|
|
@@ -2026,8 +2185,7 @@ var VectorMixin = {
|
|
|
2026
2185
|
translate(x, y) {
|
|
2027
2186
|
return this.transform(1, 0, 0, 1, x, y);
|
|
2028
2187
|
},
|
|
2029
|
-
rotate(angle) {
|
|
2030
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
2188
|
+
rotate(angle, options = {}) {
|
|
2031
2189
|
let y;
|
|
2032
2190
|
const rad = angle * Math.PI / 180;
|
|
2033
2191
|
const cos = Math.cos(rad);
|
|
@@ -2042,8 +2200,7 @@ var VectorMixin = {
|
|
|
2042
2200
|
}
|
|
2043
2201
|
return this.transform(cos, sin, -sin, cos, x, y);
|
|
2044
2202
|
},
|
|
2045
|
-
scale(xFactor, yFactor) {
|
|
2046
|
-
let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
2203
|
+
scale(xFactor, yFactor, options = {}) {
|
|
2047
2204
|
let y;
|
|
2048
2205
|
if (yFactor == null) {
|
|
2049
2206
|
yFactor = xFactor;
|
|
@@ -2186,7 +2343,7 @@ class AFMFont {
|
|
|
2186
2343
|
if (match = line.match(/^Start(\w+)/)) {
|
|
2187
2344
|
section = match[1];
|
|
2188
2345
|
continue;
|
|
2189
|
-
} else if (
|
|
2346
|
+
} else if (line.match(/^End(\w+)/)) {
|
|
2190
2347
|
section = '';
|
|
2191
2348
|
continue;
|
|
2192
2349
|
}
|
|
@@ -2278,8 +2435,7 @@ class PDFFont {
|
|
|
2278
2435
|
embed() {
|
|
2279
2436
|
throw new Error('Must be implemented by subclasses');
|
|
2280
2437
|
}
|
|
2281
|
-
lineHeight(size) {
|
|
2282
|
-
let includeGap = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
2438
|
+
lineHeight(size, includeGap = false) {
|
|
2283
2439
|
const gap = includeGap ? this.lineGap : 0;
|
|
2284
2440
|
return (this.ascender + gap - this.descender) / 1000 * size;
|
|
2285
2441
|
}
|
|
@@ -2531,9 +2687,15 @@ class EmbeddedFont extends PDFFont {
|
|
|
2531
2687
|
descriptor.data.FontFile2 = fontFile;
|
|
2532
2688
|
}
|
|
2533
2689
|
if (this.document.subset && this.document.subset === 1) {
|
|
2534
|
-
const
|
|
2690
|
+
const maxCID = this.widths.length - 1;
|
|
2691
|
+
const cidSetBuffer = Buffer.alloc(Math.ceil((maxCID + 1) / 8), 0);
|
|
2692
|
+
for (let cid = 0; cid <= maxCID; cid++) {
|
|
2693
|
+
if (this.widths[cid] != null) {
|
|
2694
|
+
cidSetBuffer[Math.floor(cid / 8)] |= 0x80 >> cid % 8;
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2535
2697
|
const CIDSetRef = this.document.ref();
|
|
2536
|
-
CIDSetRef.write(
|
|
2698
|
+
CIDSetRef.write(cidSetBuffer);
|
|
2537
2699
|
CIDSetRef.end();
|
|
2538
2700
|
descriptor.data.CIDSet = CIDSetRef;
|
|
2539
2701
|
}
|
|
@@ -2603,7 +2765,7 @@ begincmap
|
|
|
2603
2765
|
1 begincodespacerange
|
|
2604
2766
|
<0000><ffff>
|
|
2605
2767
|
endcodespacerange
|
|
2606
|
-
|
|
2768
|
+
${ranges.length} beginbfrange
|
|
2607
2769
|
${ranges.join('\n')}
|
|
2608
2770
|
endbfrange
|
|
2609
2771
|
endcmap
|
|
@@ -2625,9 +2787,9 @@ class PDFFontFactory {
|
|
|
2625
2787
|
src = fs.readFileSync(src);
|
|
2626
2788
|
}
|
|
2627
2789
|
if (src instanceof Uint8Array) {
|
|
2628
|
-
font =
|
|
2790
|
+
font = create(src, family);
|
|
2629
2791
|
} else if (src instanceof ArrayBuffer) {
|
|
2630
|
-
font =
|
|
2792
|
+
font = create(new Uint8Array(src), family);
|
|
2631
2793
|
}
|
|
2632
2794
|
if (font == null) {
|
|
2633
2795
|
throw new Error('Not a supported font format or standard PDF font.');
|
|
@@ -2646,10 +2808,7 @@ const isEqualFont = (font1, font2) => {
|
|
|
2646
2808
|
return true;
|
|
2647
2809
|
};
|
|
2648
2810
|
var FontsMixin = {
|
|
2649
|
-
initFonts() {
|
|
2650
|
-
let defaultFont = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Helvetica';
|
|
2651
|
-
let defaultFontFamily = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
2652
|
-
let defaultFontSize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 12;
|
|
2811
|
+
initFonts(defaultFont = 'Helvetica', defaultFontFamily = null, defaultFontSize = 12) {
|
|
2653
2812
|
this._fontFamilies = {};
|
|
2654
2813
|
this._fontCount = 0;
|
|
2655
2814
|
this._fontSource = defaultFont;
|
|
@@ -2698,9 +2857,12 @@ var FontsMixin = {
|
|
|
2698
2857
|
if (cacheKey) {
|
|
2699
2858
|
this._fontFamilies[cacheKey] = this._font;
|
|
2700
2859
|
}
|
|
2701
|
-
if (this._font.name) {
|
|
2860
|
+
if (this._font.name && !this._fontFamilies[this._font.name]) {
|
|
2702
2861
|
this._fontFamilies[this._font.name] = this._font;
|
|
2703
2862
|
}
|
|
2863
|
+
if (!cacheKey && (!this._font.name || this._fontFamilies[this._font.name] !== this._font)) {
|
|
2864
|
+
this._fontFamilies[this._font.id] = this._font;
|
|
2865
|
+
}
|
|
2704
2866
|
return this;
|
|
2705
2867
|
},
|
|
2706
2868
|
fontSize(_fontSize) {
|
|
@@ -2717,10 +2879,7 @@ var FontsMixin = {
|
|
|
2717
2879
|
};
|
|
2718
2880
|
return this;
|
|
2719
2881
|
},
|
|
2720
|
-
sizeToPoint(size) {
|
|
2721
|
-
let defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
2722
|
-
let page = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.page;
|
|
2723
|
-
let percentageWidth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined;
|
|
2882
|
+
sizeToPoint(size, defaultValue = 0, page = this.page, percentageWidth = undefined) {
|
|
2724
2883
|
if (!percentageWidth) percentageWidth = this._fontSize;
|
|
2725
2884
|
if (typeof defaultValue !== 'number') defaultValue = this.sizeToPoint(defaultValue);
|
|
2726
2885
|
if (size === undefined) return defaultValue;
|
|
@@ -2782,12 +2941,13 @@ var FontsMixin = {
|
|
|
2782
2941
|
|
|
2783
2942
|
const SOFT_HYPHEN = '\u00AD';
|
|
2784
2943
|
const HYPHEN = '-';
|
|
2785
|
-
class LineWrapper
|
|
2944
|
+
class LineWrapper {
|
|
2786
2945
|
constructor(document, options) {
|
|
2787
|
-
|
|
2946
|
+
this._listeners = Object.create(null);
|
|
2788
2947
|
this.document = document;
|
|
2789
2948
|
this.horizontalScaling = options.horizontalScaling || 100;
|
|
2790
2949
|
this.indent = (options.indent || 0) * this.horizontalScaling / 100;
|
|
2950
|
+
this.indentAllLines = options.indentAllLines || false;
|
|
2791
2951
|
this.characterSpacing = (options.characterSpacing || 0) * this.horizontalScaling / 100;
|
|
2792
2952
|
this.wordSpacing = (options.wordSpacing === 0) * this.horizontalScaling / 100;
|
|
2793
2953
|
this.columns = options.columns || 1;
|
|
@@ -2839,6 +2999,22 @@ class LineWrapper extends EventEmitter {
|
|
|
2839
2999
|
});
|
|
2840
3000
|
});
|
|
2841
3001
|
}
|
|
3002
|
+
on(event, listener) {
|
|
3003
|
+
(this._listeners[event] || (this._listeners[event] = [])).push(listener);
|
|
3004
|
+
}
|
|
3005
|
+
once(event, listener) {
|
|
3006
|
+
const wrapper = (...args) => {
|
|
3007
|
+
const listeners = this._listeners[event];
|
|
3008
|
+
listeners.splice(listeners.indexOf(wrapper), 1);
|
|
3009
|
+
listener(...args);
|
|
3010
|
+
};
|
|
3011
|
+
this.on(event, wrapper);
|
|
3012
|
+
}
|
|
3013
|
+
emit(event, ...args) {
|
|
3014
|
+
const listeners = this._listeners[event];
|
|
3015
|
+
if (!listeners) return;
|
|
3016
|
+
for (const listener of listeners.slice()) listener(...args);
|
|
3017
|
+
}
|
|
2842
3018
|
wordWidth(word) {
|
|
2843
3019
|
return PDFNumber(this.document.widthOfString(word, this) + this.characterSpacing + this.wordSpacing);
|
|
2844
3020
|
}
|
|
@@ -2904,6 +3080,9 @@ class LineWrapper extends EventEmitter {
|
|
|
2904
3080
|
}
|
|
2905
3081
|
}
|
|
2906
3082
|
wrap(text, options) {
|
|
3083
|
+
const {
|
|
3084
|
+
document
|
|
3085
|
+
} = this;
|
|
2907
3086
|
this.horizontalScaling = options.horizontalScaling || 100;
|
|
2908
3087
|
if (options.indent != null) {
|
|
2909
3088
|
this.indent = options.indent * this.horizontalScaling / 100;
|
|
@@ -2917,24 +3096,20 @@ class LineWrapper extends EventEmitter {
|
|
|
2917
3096
|
if (options.ellipsis != null) {
|
|
2918
3097
|
this.ellipsis = options.ellipsis;
|
|
2919
3098
|
}
|
|
2920
|
-
const nextY =
|
|
2921
|
-
if (
|
|
3099
|
+
const nextY = document.y + document.currentLineHeight(true);
|
|
3100
|
+
if (document.y > this.maxY || nextY > this.maxY) {
|
|
2922
3101
|
this.nextSection();
|
|
2923
3102
|
}
|
|
2924
3103
|
let buffer = '';
|
|
2925
3104
|
let textWidth = 0;
|
|
2926
3105
|
let wc = 0;
|
|
2927
3106
|
let lc = 0;
|
|
2928
|
-
let
|
|
2929
|
-
y
|
|
2930
|
-
} = this.document;
|
|
3107
|
+
let continueY = document.y;
|
|
2931
3108
|
const emitLine = () => {
|
|
2932
3109
|
options.textWidth = textWidth + this.wordSpacing * (wc - 1);
|
|
2933
3110
|
options.wordCount = wc;
|
|
2934
3111
|
options.lineWidth = this.lineWidth;
|
|
2935
|
-
|
|
2936
|
-
y
|
|
2937
|
-
} = this.document);
|
|
3112
|
+
continueY = document.y;
|
|
2938
3113
|
this.emit('line', buffer, options, this);
|
|
2939
3114
|
return lc++;
|
|
2940
3115
|
};
|
|
@@ -2950,8 +3125,8 @@ class LineWrapper extends EventEmitter {
|
|
|
2950
3125
|
wc++;
|
|
2951
3126
|
}
|
|
2952
3127
|
if (bk.required || !this.canFit(word, w)) {
|
|
2953
|
-
const lh =
|
|
2954
|
-
if (this.height != null && this.ellipsis && PDFNumber(
|
|
3128
|
+
const lh = document.currentLineHeight(true);
|
|
3129
|
+
if (this.height != null && this.ellipsis && PDFNumber(document.y + lh * 2) > this.maxY && this.column >= this.columns) {
|
|
2955
3130
|
if (this.ellipsis === true) {
|
|
2956
3131
|
this.ellipsis = '…';
|
|
2957
3132
|
}
|
|
@@ -2980,7 +3155,7 @@ class LineWrapper extends EventEmitter {
|
|
|
2980
3155
|
this.spaceLeft -= this.wordWidth(HYPHEN);
|
|
2981
3156
|
}
|
|
2982
3157
|
emitLine();
|
|
2983
|
-
if (PDFNumber(
|
|
3158
|
+
if (PDFNumber(document.y + lh) > this.maxY) {
|
|
2984
3159
|
this.emit('sectionEnd', options, this);
|
|
2985
3160
|
const shouldContinue = this.nextSection();
|
|
2986
3161
|
if (!shouldContinue) {
|
|
@@ -3015,9 +3190,9 @@ class LineWrapper extends EventEmitter {
|
|
|
3015
3190
|
this.continuedX = 0;
|
|
3016
3191
|
}
|
|
3017
3192
|
this.continuedX += options.textWidth || 0;
|
|
3018
|
-
|
|
3193
|
+
document.y = continueY;
|
|
3019
3194
|
} else {
|
|
3020
|
-
|
|
3195
|
+
document.x = this.startX;
|
|
3021
3196
|
}
|
|
3022
3197
|
}
|
|
3023
3198
|
nextSection(options) {
|
|
@@ -3029,7 +3204,13 @@ class LineWrapper extends EventEmitter {
|
|
|
3029
3204
|
this.column = 1;
|
|
3030
3205
|
this.startY = this.document.page.margins.top;
|
|
3031
3206
|
this.maxY = this.document.page.maxY();
|
|
3032
|
-
this.
|
|
3207
|
+
if (this.indentAllLines) {
|
|
3208
|
+
const indent = this.continuedX || this.indent;
|
|
3209
|
+
this.document.x += indent;
|
|
3210
|
+
this.lineWidth -= indent;
|
|
3211
|
+
} else {
|
|
3212
|
+
this.document.x = this.startX;
|
|
3213
|
+
}
|
|
3033
3214
|
if (this.document._fillColor) {
|
|
3034
3215
|
this.document.fillColor(...this.document._fillColor);
|
|
3035
3216
|
}
|
|
@@ -3119,8 +3300,7 @@ var TextMixin = {
|
|
|
3119
3300
|
text(text, x, y, options) {
|
|
3120
3301
|
return this._text(text, x, y, options, this._line);
|
|
3121
3302
|
},
|
|
3122
|
-
widthOfString(string) {
|
|
3123
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
3303
|
+
widthOfString(string, options = {}) {
|
|
3124
3304
|
const horizontalScaling = options.horizontalScaling || 100;
|
|
3125
3305
|
return (this._font.widthOfString(string, this._fontSize, options.features) + (options.characterSpacing || 0) * (string.length - 1)) * horizontalScaling / 100;
|
|
3126
3306
|
},
|
|
@@ -3326,11 +3506,8 @@ var TextMixin = {
|
|
|
3326
3506
|
}
|
|
3327
3507
|
return this;
|
|
3328
3508
|
},
|
|
3329
|
-
_initOptions() {
|
|
3330
|
-
|
|
3331
|
-
let y = arguments.length > 1 ? arguments[1] : undefined;
|
|
3332
|
-
let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
3333
|
-
if (typeof x === 'object') {
|
|
3509
|
+
_initOptions(x = {}, y, options = {}) {
|
|
3510
|
+
if (x && typeof x === 'object') {
|
|
3334
3511
|
options = x;
|
|
3335
3512
|
x = null;
|
|
3336
3513
|
}
|
|
@@ -3363,13 +3540,11 @@ var TextMixin = {
|
|
|
3363
3540
|
if (result.columnGap == null) {
|
|
3364
3541
|
result.columnGap = 18;
|
|
3365
3542
|
}
|
|
3366
|
-
result.rotation = Number(
|
|
3543
|
+
result.rotation = Number(result.rotation ?? 0) % 360;
|
|
3367
3544
|
if (result.rotation < 0) result.rotation += 360;
|
|
3368
3545
|
return result;
|
|
3369
3546
|
},
|
|
3370
|
-
_line(text) {
|
|
3371
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
3372
|
-
let wrapper = arguments.length > 2 ? arguments[2] : undefined;
|
|
3547
|
+
_line(text, options = {}, wrapper) {
|
|
3373
3548
|
this._fragment(text, this.x, this.y, options);
|
|
3374
3549
|
if (wrapper) {
|
|
3375
3550
|
const lineGap = options.lineGap || this._lineGap || 0;
|
|
@@ -3439,7 +3614,11 @@ var TextMixin = {
|
|
|
3439
3614
|
}
|
|
3440
3615
|
const renderedWidth = options.textWidth + wordSpacing * (options.wordCount - 1) + characterSpacing * (text.length - 1);
|
|
3441
3616
|
if (options.link != null) {
|
|
3442
|
-
|
|
3617
|
+
const linkOptions = {};
|
|
3618
|
+
if (this._currentStructureElement && this._currentStructureElement.dictionary.data.S === 'Link') {
|
|
3619
|
+
linkOptions.structParent = this._currentStructureElement;
|
|
3620
|
+
}
|
|
3621
|
+
this.link(x, y, renderedWidth, this.currentLineHeight(), options.link, linkOptions);
|
|
3443
3622
|
}
|
|
3444
3623
|
if (options.goTo != null) {
|
|
3445
3624
|
this.goTo(x, y, renderedWidth, this.currentLineHeight(), options.goTo);
|
|
@@ -3568,6 +3747,61 @@ var TextMixin = {
|
|
|
3568
3747
|
}
|
|
3569
3748
|
};
|
|
3570
3749
|
|
|
3750
|
+
const toBinaryString = bytes => {
|
|
3751
|
+
const chunkSize = 0x8000;
|
|
3752
|
+
let out = '';
|
|
3753
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
3754
|
+
const end = Math.min(i + chunkSize, bytes.length);
|
|
3755
|
+
out += String.fromCharCode.apply(null, bytes.subarray(i, end));
|
|
3756
|
+
}
|
|
3757
|
+
return out;
|
|
3758
|
+
};
|
|
3759
|
+
const readUInt16BE = (bytes, offset = 0) => (bytes[offset] << 8 | bytes[offset + 1]) >>> 0;
|
|
3760
|
+
const readUInt16LE = (bytes, offset = 0) => (bytes[offset + 1] << 8 | bytes[offset]) >>> 0;
|
|
3761
|
+
const readUInt32BE = (bytes, offset = 0) => bytes[offset] * 0x1000000 + (bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
|
|
3762
|
+
const readUInt32LE = (bytes, offset = 0) => (bytes[offset] | bytes[offset + 1] << 8 | bytes[offset + 2] << 16) + bytes[offset + 3] * 0x1000000 >>> 0;
|
|
3763
|
+
|
|
3764
|
+
const parseExifOrientation = data => {
|
|
3765
|
+
if (!data || data.length < 20) return null;
|
|
3766
|
+
let pos = 2;
|
|
3767
|
+
while (pos < data.length - 4) {
|
|
3768
|
+
while (pos < data.length && data[pos] !== 0xff) pos++;
|
|
3769
|
+
if (pos >= data.length - 4) return null;
|
|
3770
|
+
const marker = readUInt16BE(data, pos);
|
|
3771
|
+
pos += 2;
|
|
3772
|
+
if (marker === 0xffda) return null;
|
|
3773
|
+
if (marker >= 0xffd0 && marker <= 0xffd9 || marker === 0xff01) continue;
|
|
3774
|
+
if (pos + 2 > data.length) return null;
|
|
3775
|
+
const segmentLength = readUInt16BE(data, pos);
|
|
3776
|
+
if (marker === 0xffe1 && pos + 8 <= data.length) {
|
|
3777
|
+
const exifHeader = toBinaryString(data.subarray(pos + 2, pos + 8));
|
|
3778
|
+
if (exifHeader === 'Exif\x00\x00') {
|
|
3779
|
+
const tiffStart = pos + 8;
|
|
3780
|
+
if (tiffStart + 8 > data.length) return null;
|
|
3781
|
+
const byteOrder = toBinaryString(data.subarray(tiffStart, tiffStart + 2));
|
|
3782
|
+
const isLittleEndian = byteOrder === 'II';
|
|
3783
|
+
if (!isLittleEndian && byteOrder !== 'MM') return null;
|
|
3784
|
+
const read16 = isLittleEndian ? o => readUInt16LE(data, o) : o => readUInt16BE(data, o);
|
|
3785
|
+
const read32 = isLittleEndian ? o => readUInt32LE(data, o) : o => readUInt32BE(data, o);
|
|
3786
|
+
if (read16(tiffStart + 2) !== 42) return null;
|
|
3787
|
+
const ifdPos = tiffStart + read32(tiffStart + 4);
|
|
3788
|
+
if (ifdPos + 2 > data.length) return null;
|
|
3789
|
+
const entryCount = read16(ifdPos);
|
|
3790
|
+
for (let i = 0; i < entryCount; i++) {
|
|
3791
|
+
const entryPos = ifdPos + 2 + i * 12;
|
|
3792
|
+
if (entryPos + 12 > data.length) return null;
|
|
3793
|
+
if (read16(entryPos) === 0x0112) {
|
|
3794
|
+
const value = read16(entryPos + 8);
|
|
3795
|
+
return value >= 1 && value <= 8 ? value : null;
|
|
3796
|
+
}
|
|
3797
|
+
}
|
|
3798
|
+
return null;
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
pos += segmentLength;
|
|
3802
|
+
}
|
|
3803
|
+
return null;
|
|
3804
|
+
};
|
|
3571
3805
|
const MARKERS = [0xffc0, 0xffc1, 0xffc2, 0xffc3, 0xffc5, 0xffc6, 0xffc7, 0xffc8, 0xffc9, 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf];
|
|
3572
3806
|
const COLOR_SPACE_MAP = {
|
|
3573
3807
|
1: 'DeviceGray',
|
|
@@ -3582,9 +3816,11 @@ class JPEG {
|
|
|
3582
3816
|
if (this.data.readUInt16BE(0) !== 0xffd8) {
|
|
3583
3817
|
throw 'SOI not found in JPEG';
|
|
3584
3818
|
}
|
|
3585
|
-
this.orientation =
|
|
3819
|
+
this.orientation = parseExifOrientation(this.data) || 1;
|
|
3586
3820
|
let pos = 2;
|
|
3587
3821
|
while (pos < this.data.length) {
|
|
3822
|
+
while (pos < this.data.length && this.data[pos] !== 0xff) pos++;
|
|
3823
|
+
if (pos >= this.data.length) break;
|
|
3588
3824
|
marker = this.data.readUInt16BE(pos);
|
|
3589
3825
|
pos += 2;
|
|
3590
3826
|
if (MARKERS.includes(marker)) {
|
|
@@ -3601,7 +3837,7 @@ class JPEG {
|
|
|
3601
3837
|
pos += 2;
|
|
3602
3838
|
this.width = this.data.readUInt16BE(pos);
|
|
3603
3839
|
pos += 2;
|
|
3604
|
-
const channels = this.data[pos
|
|
3840
|
+
const channels = this.data[pos + 1];
|
|
3605
3841
|
this.colorSpace = COLOR_SPACE_MAP[channels];
|
|
3606
3842
|
this.obj = null;
|
|
3607
3843
|
}
|
|
@@ -3636,58 +3872,60 @@ class PNGImage {
|
|
|
3636
3872
|
this.obj = null;
|
|
3637
3873
|
}
|
|
3638
3874
|
embed(document) {
|
|
3639
|
-
let dataDecoded = false;
|
|
3640
3875
|
this.document = document;
|
|
3641
3876
|
if (this.obj) {
|
|
3642
3877
|
return;
|
|
3643
3878
|
}
|
|
3644
|
-
const
|
|
3645
|
-
|
|
3646
|
-
|
|
3879
|
+
const {
|
|
3880
|
+
image,
|
|
3881
|
+
height,
|
|
3882
|
+
width
|
|
3883
|
+
} = this;
|
|
3884
|
+
const hasAlphaChannel = image.hasAlphaChannel;
|
|
3885
|
+
const isInterlaced = image.interlaceMethod === 1;
|
|
3886
|
+
const obj = this.obj = document.ref({
|
|
3647
3887
|
Type: 'XObject',
|
|
3648
3888
|
Subtype: 'Image',
|
|
3649
|
-
BitsPerComponent: hasAlphaChannel ? 8 :
|
|
3650
|
-
Width:
|
|
3651
|
-
Height:
|
|
3889
|
+
BitsPerComponent: hasAlphaChannel ? 8 : image.bits,
|
|
3890
|
+
Width: width,
|
|
3891
|
+
Height: height,
|
|
3652
3892
|
Filter: 'FlateDecode'
|
|
3653
3893
|
});
|
|
3654
3894
|
if (!hasAlphaChannel) {
|
|
3655
|
-
const params =
|
|
3895
|
+
const params = document.ref({
|
|
3656
3896
|
Predictor: isInterlaced ? 1 : 15,
|
|
3657
|
-
Colors:
|
|
3658
|
-
BitsPerComponent:
|
|
3659
|
-
Columns:
|
|
3897
|
+
Colors: image.colors,
|
|
3898
|
+
BitsPerComponent: image.bits,
|
|
3899
|
+
Columns: width
|
|
3660
3900
|
});
|
|
3661
|
-
|
|
3901
|
+
obj.data['DecodeParms'] = params;
|
|
3662
3902
|
params.end();
|
|
3663
3903
|
}
|
|
3664
|
-
if (
|
|
3665
|
-
|
|
3904
|
+
if (image.palette.length === 0) {
|
|
3905
|
+
obj.data['ColorSpace'] = image.colorSpace;
|
|
3666
3906
|
} else {
|
|
3667
|
-
const palette =
|
|
3668
|
-
palette.end(Buffer.from(
|
|
3669
|
-
|
|
3670
|
-
}
|
|
3671
|
-
if (
|
|
3672
|
-
const val =
|
|
3673
|
-
|
|
3674
|
-
} else if (
|
|
3907
|
+
const palette = document.ref();
|
|
3908
|
+
palette.end(Buffer.from(image.palette));
|
|
3909
|
+
obj.data['ColorSpace'] = ['Indexed', 'DeviceRGB', image.palette.length / 3 - 1, palette];
|
|
3910
|
+
}
|
|
3911
|
+
if (image.transparency.grayscale != null) {
|
|
3912
|
+
const val = image.transparency.grayscale;
|
|
3913
|
+
obj.data['Mask'] = [val, val];
|
|
3914
|
+
} else if (image.transparency.rgb) {
|
|
3675
3915
|
const {
|
|
3676
3916
|
rgb
|
|
3677
|
-
} =
|
|
3917
|
+
} = image.transparency;
|
|
3678
3918
|
const mask = [];
|
|
3679
3919
|
for (let x of rgb) {
|
|
3680
3920
|
mask.push(x, x);
|
|
3681
3921
|
}
|
|
3682
|
-
|
|
3683
|
-
} else if (
|
|
3684
|
-
dataDecoded = true;
|
|
3922
|
+
obj.data['Mask'] = mask;
|
|
3923
|
+
} else if (image.transparency.indexed) {
|
|
3685
3924
|
return this.loadIndexedAlphaChannel();
|
|
3686
3925
|
} else if (hasAlphaChannel) {
|
|
3687
|
-
dataDecoded = true;
|
|
3688
3926
|
return this.splitAlphaChannel();
|
|
3689
3927
|
}
|
|
3690
|
-
if (isInterlaced &&
|
|
3928
|
+
if (isInterlaced && true) {
|
|
3691
3929
|
return this.decodeData();
|
|
3692
3930
|
}
|
|
3693
3931
|
this.finalize();
|
|
@@ -3736,12 +3974,16 @@ class PNGImage {
|
|
|
3736
3974
|
}
|
|
3737
3975
|
loadIndexedAlphaChannel() {
|
|
3738
3976
|
const transparency = this.image.transparency.indexed;
|
|
3977
|
+
const isInterlaced = this.image.interlaceMethod === 1;
|
|
3739
3978
|
return this.image.decodePixels(pixels => {
|
|
3740
3979
|
const alphaChannel = Buffer.alloc(this.width * this.height);
|
|
3741
3980
|
let i = 0;
|
|
3742
3981
|
for (let j = 0, end = pixels.length; j < end; j++) {
|
|
3743
3982
|
alphaChannel[i++] = transparency[pixels[j]];
|
|
3744
3983
|
}
|
|
3984
|
+
if (isInterlaced) {
|
|
3985
|
+
this.imgData = zlib.deflateSync(Buffer.from(pixels));
|
|
3986
|
+
}
|
|
3745
3987
|
this.alphaChannel = zlib.deflateSync(alphaChannel);
|
|
3746
3988
|
return this.finalize();
|
|
3747
3989
|
});
|
|
@@ -3774,7 +4016,7 @@ class PDFImage {
|
|
|
3774
4016
|
}
|
|
3775
4017
|
if (data[0] === 0xff && data[1] === 0xd8) {
|
|
3776
4018
|
return new JPEG(data, label);
|
|
3777
|
-
} else if (data[0] === 0x89 && data
|
|
4019
|
+
} else if (data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4e && data[3] === 0x47) {
|
|
3778
4020
|
return new PNGImage(data, label);
|
|
3779
4021
|
} else {
|
|
3780
4022
|
throw new Error('Unknown image format.');
|
|
@@ -3787,8 +4029,7 @@ var ImagesMixin = {
|
|
|
3787
4029
|
this._imageRegistry = {};
|
|
3788
4030
|
this._imageCount = 0;
|
|
3789
4031
|
},
|
|
3790
|
-
image(src, x, y) {
|
|
3791
|
-
let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
4032
|
+
image(src, x, y, options = {}) {
|
|
3792
4033
|
let bh, bp, bw, image, ip, left, left1, originX, originY;
|
|
3793
4034
|
if (typeof x === 'object') {
|
|
3794
4035
|
options = x;
|
|
@@ -3946,6 +4187,9 @@ var ImagesMixin = {
|
|
|
3946
4187
|
this.y += h;
|
|
3947
4188
|
}
|
|
3948
4189
|
this.save();
|
|
4190
|
+
if (options.opacity != null) {
|
|
4191
|
+
this._doOpacity(options.opacity, null);
|
|
4192
|
+
}
|
|
3949
4193
|
if (rotateAngle) {
|
|
3950
4194
|
this.rotate(rotateAngle, {
|
|
3951
4195
|
origin: [originX, originY]
|
|
@@ -3971,6 +4215,12 @@ var ImagesMixin = {
|
|
|
3971
4215
|
}
|
|
3972
4216
|
};
|
|
3973
4217
|
|
|
4218
|
+
class PDFAnnotationReference {
|
|
4219
|
+
constructor(annotationRef) {
|
|
4220
|
+
this.annotationRef = annotationRef;
|
|
4221
|
+
}
|
|
4222
|
+
}
|
|
4223
|
+
|
|
3974
4224
|
var AnnotationsMixin = {
|
|
3975
4225
|
annotate(x, y, w, h, options) {
|
|
3976
4226
|
options.Type = 'Annot';
|
|
@@ -3988,17 +4238,22 @@ var AnnotationsMixin = {
|
|
|
3988
4238
|
if (typeof options.Dest === 'string') {
|
|
3989
4239
|
options.Dest = new String(options.Dest);
|
|
3990
4240
|
}
|
|
4241
|
+
const structParent = options.structParent;
|
|
4242
|
+
delete options.structParent;
|
|
3991
4243
|
for (let key in options) {
|
|
3992
4244
|
const val = options[key];
|
|
3993
4245
|
options[key[0].toUpperCase() + key.slice(1)] = val;
|
|
3994
4246
|
}
|
|
3995
4247
|
const ref = this.ref(options);
|
|
3996
4248
|
this.page.annotations.push(ref);
|
|
4249
|
+
if (structParent && typeof structParent.add === 'function') {
|
|
4250
|
+
const annotRef = new PDFAnnotationReference(ref);
|
|
4251
|
+
structParent.add(annotRef);
|
|
4252
|
+
}
|
|
3997
4253
|
ref.end();
|
|
3998
4254
|
return this;
|
|
3999
4255
|
},
|
|
4000
|
-
note(x, y, w, h, contents) {
|
|
4001
|
-
let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
4256
|
+
note(x, y, w, h, contents, options = {}) {
|
|
4002
4257
|
options.Subtype = 'Text';
|
|
4003
4258
|
options.Contents = new String(contents);
|
|
4004
4259
|
if (options.Name == null) {
|
|
@@ -4009,8 +4264,7 @@ var AnnotationsMixin = {
|
|
|
4009
4264
|
}
|
|
4010
4265
|
return this.annotate(x, y, w, h, options);
|
|
4011
4266
|
},
|
|
4012
|
-
goTo(x, y, w, h, name) {
|
|
4013
|
-
let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
4267
|
+
goTo(x, y, w, h, name, options = {}) {
|
|
4014
4268
|
options.Subtype = 'Link';
|
|
4015
4269
|
options.A = this.ref({
|
|
4016
4270
|
S: 'GoTo',
|
|
@@ -4019,8 +4273,7 @@ var AnnotationsMixin = {
|
|
|
4019
4273
|
options.A.end();
|
|
4020
4274
|
return this.annotate(x, y, w, h, options);
|
|
4021
4275
|
},
|
|
4022
|
-
link(x, y, w, h, url) {
|
|
4023
|
-
let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
4276
|
+
link(x, y, w, h, url, options = {}) {
|
|
4024
4277
|
options.Subtype = 'Link';
|
|
4025
4278
|
if (typeof url === 'number') {
|
|
4026
4279
|
const pages = this._root.data.Pages.data;
|
|
@@ -4040,62 +4293,55 @@ var AnnotationsMixin = {
|
|
|
4040
4293
|
});
|
|
4041
4294
|
options.A.end();
|
|
4042
4295
|
}
|
|
4296
|
+
if (options.structParent && !options.Contents) {
|
|
4297
|
+
options.Contents = new String('');
|
|
4298
|
+
}
|
|
4043
4299
|
return this.annotate(x, y, w, h, options);
|
|
4044
4300
|
},
|
|
4045
|
-
_markup(x, y, w, h) {
|
|
4046
|
-
let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
4301
|
+
_markup(x, y, w, h, options = {}) {
|
|
4047
4302
|
const [x1, y1, x2, y2] = this._convertRect(x, y, w, h);
|
|
4048
4303
|
options.QuadPoints = [x1, y2, x2, y2, x1, y1, x2, y1];
|
|
4049
4304
|
options.Contents = new String();
|
|
4050
4305
|
return this.annotate(x, y, w, h, options);
|
|
4051
4306
|
},
|
|
4052
|
-
highlight(x, y, w, h) {
|
|
4053
|
-
let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
4307
|
+
highlight(x, y, w, h, options = {}) {
|
|
4054
4308
|
options.Subtype = 'Highlight';
|
|
4055
4309
|
if (options.color == null) {
|
|
4056
4310
|
options.color = [241, 238, 148];
|
|
4057
4311
|
}
|
|
4058
4312
|
return this._markup(x, y, w, h, options);
|
|
4059
4313
|
},
|
|
4060
|
-
underline(x, y, w, h) {
|
|
4061
|
-
let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
4314
|
+
underline(x, y, w, h, options = {}) {
|
|
4062
4315
|
options.Subtype = 'Underline';
|
|
4063
4316
|
return this._markup(x, y, w, h, options);
|
|
4064
4317
|
},
|
|
4065
|
-
strike(x, y, w, h) {
|
|
4066
|
-
let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
4318
|
+
strike(x, y, w, h, options = {}) {
|
|
4067
4319
|
options.Subtype = 'StrikeOut';
|
|
4068
4320
|
return this._markup(x, y, w, h, options);
|
|
4069
4321
|
},
|
|
4070
|
-
lineAnnotation(x1, y1, x2, y2) {
|
|
4071
|
-
let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
4322
|
+
lineAnnotation(x1, y1, x2, y2, options = {}) {
|
|
4072
4323
|
options.Subtype = 'Line';
|
|
4073
4324
|
options.Contents = new String();
|
|
4074
4325
|
options.L = [x1, this.page.height - y1, x2, this.page.height - y2];
|
|
4075
4326
|
return this.annotate(x1, y1, x2, y2, options);
|
|
4076
4327
|
},
|
|
4077
|
-
rectAnnotation(x, y, w, h) {
|
|
4078
|
-
let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
4328
|
+
rectAnnotation(x, y, w, h, options = {}) {
|
|
4079
4329
|
options.Subtype = 'Square';
|
|
4080
4330
|
options.Contents = new String();
|
|
4081
4331
|
return this.annotate(x, y, w, h, options);
|
|
4082
4332
|
},
|
|
4083
|
-
ellipseAnnotation(x, y, w, h) {
|
|
4084
|
-
let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
4333
|
+
ellipseAnnotation(x, y, w, h, options = {}) {
|
|
4085
4334
|
options.Subtype = 'Circle';
|
|
4086
4335
|
options.Contents = new String();
|
|
4087
4336
|
return this.annotate(x, y, w, h, options);
|
|
4088
4337
|
},
|
|
4089
|
-
textAnnotation(x, y, w, h, text) {
|
|
4090
|
-
let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
4338
|
+
textAnnotation(x, y, w, h, text, options = {}) {
|
|
4091
4339
|
options.Subtype = 'FreeText';
|
|
4092
4340
|
options.Contents = new String(text);
|
|
4093
4341
|
options.DA = new String();
|
|
4094
4342
|
return this.annotate(x, y, w, h, options);
|
|
4095
4343
|
},
|
|
4096
|
-
fileAnnotation(x, y, w, h) {
|
|
4097
|
-
let file = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
4098
|
-
let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
4344
|
+
fileAnnotation(x, y, w, h, file = {}, options = {}) {
|
|
4099
4345
|
const filespec = this.file(file.src, Object.assign({
|
|
4100
4346
|
hidden: true
|
|
4101
4347
|
}, file));
|
|
@@ -4121,16 +4367,26 @@ var AnnotationsMixin = {
|
|
|
4121
4367
|
}
|
|
4122
4368
|
};
|
|
4123
4369
|
|
|
4370
|
+
const DEFAULT_OPTIONS = {
|
|
4371
|
+
top: 0,
|
|
4372
|
+
left: 0,
|
|
4373
|
+
zoom: 0,
|
|
4374
|
+
fit: true,
|
|
4375
|
+
pageNumber: null,
|
|
4376
|
+
expanded: false
|
|
4377
|
+
};
|
|
4124
4378
|
class PDFOutline {
|
|
4125
|
-
constructor(document, parent, title, dest) {
|
|
4126
|
-
let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
|
|
4127
|
-
expanded: false
|
|
4128
|
-
};
|
|
4379
|
+
constructor(document, parent, title, dest, options = DEFAULT_OPTIONS) {
|
|
4129
4380
|
this.document = document;
|
|
4130
4381
|
this.options = options;
|
|
4131
4382
|
this.outlineData = {};
|
|
4132
4383
|
if (dest !== null) {
|
|
4133
|
-
|
|
4384
|
+
const destWidth = dest.data.MediaBox[2];
|
|
4385
|
+
const destHeight = dest.data.MediaBox[3];
|
|
4386
|
+
const top = destHeight - (options.top || 0);
|
|
4387
|
+
const left = destWidth - (options.left || 0);
|
|
4388
|
+
const zoom = options.zoom || 0;
|
|
4389
|
+
this.outlineData['Dest'] = options.fit ? [dest, 'Fit'] : [dest, 'XYZ', left, top, zoom];
|
|
4134
4390
|
}
|
|
4135
4391
|
if (parent !== null) {
|
|
4136
4392
|
this.outlineData['Parent'] = parent;
|
|
@@ -4141,11 +4397,10 @@ class PDFOutline {
|
|
|
4141
4397
|
this.dictionary = this.document.ref(this.outlineData);
|
|
4142
4398
|
this.children = [];
|
|
4143
4399
|
}
|
|
4144
|
-
addItem(title) {
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
const result = new PDFOutline(this.document, this.dictionary, title, this.document.page, options);
|
|
4400
|
+
addItem(title, options = DEFAULT_OPTIONS) {
|
|
4401
|
+
const pages = this.document._root.data.Pages.data.Kids;
|
|
4402
|
+
const dest = options.pageNumber != null ? pages[options.pageNumber] : this.document.page.dictionary;
|
|
4403
|
+
const result = new PDFOutline(this.document, this.dictionary, title, dest, options);
|
|
4149
4404
|
this.children.push(result);
|
|
4150
4405
|
return result;
|
|
4151
4406
|
}
|
|
@@ -4181,7 +4436,7 @@ var OutlineMixin = {
|
|
|
4181
4436
|
this.outline.endOutline();
|
|
4182
4437
|
if (this.outline.children.length > 0) {
|
|
4183
4438
|
this._root.data.Outlines = this.outline.dictionary;
|
|
4184
|
-
return this._root.data.PageMode = 'UseOutlines';
|
|
4439
|
+
return this._root.data.PageMode = this._root.data.PageMode || 'UseOutlines';
|
|
4185
4440
|
}
|
|
4186
4441
|
}
|
|
4187
4442
|
};
|
|
@@ -4199,9 +4454,7 @@ class PDFStructureContent {
|
|
|
4199
4454
|
}
|
|
4200
4455
|
|
|
4201
4456
|
class PDFStructureElement {
|
|
4202
|
-
constructor(document, type) {
|
|
4203
|
-
let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
4204
|
-
let children = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
|
|
4457
|
+
constructor(document, type, options = {}, children = null) {
|
|
4205
4458
|
this.document = document;
|
|
4206
4459
|
this._attached = false;
|
|
4207
4460
|
this._ended = false;
|
|
@@ -4214,21 +4467,41 @@ class PDFStructureElement {
|
|
|
4214
4467
|
children = options;
|
|
4215
4468
|
options = {};
|
|
4216
4469
|
}
|
|
4217
|
-
if (
|
|
4470
|
+
if (options.title) {
|
|
4218
4471
|
data.T = new String(options.title);
|
|
4219
4472
|
}
|
|
4220
|
-
if (
|
|
4473
|
+
if (options.lang) {
|
|
4221
4474
|
data.Lang = new String(options.lang);
|
|
4222
4475
|
}
|
|
4223
|
-
if (
|
|
4476
|
+
if (options.alt) {
|
|
4224
4477
|
data.Alt = new String(options.alt);
|
|
4225
4478
|
}
|
|
4226
|
-
if (
|
|
4479
|
+
if (options.expanded) {
|
|
4227
4480
|
data.E = new String(options.expanded);
|
|
4228
4481
|
}
|
|
4229
|
-
if (
|
|
4482
|
+
if (options.actual) {
|
|
4230
4483
|
data.ActualText = new String(options.actual);
|
|
4231
4484
|
}
|
|
4485
|
+
const hasBbox = Array.isArray(options.bbox) && options.bbox.length === 4;
|
|
4486
|
+
const hasPlacement = typeof options.placement === 'string';
|
|
4487
|
+
if (hasBbox || hasPlacement) {
|
|
4488
|
+
const attrs = {
|
|
4489
|
+
O: 'Layout'
|
|
4490
|
+
};
|
|
4491
|
+
attrs.Placement = hasPlacement ? options.placement : 'Block';
|
|
4492
|
+
if (hasBbox) {
|
|
4493
|
+
const height = document.page.height;
|
|
4494
|
+
attrs.BBox = [options.bbox[0], height - options.bbox[3], options.bbox[2], height - options.bbox[1]];
|
|
4495
|
+
}
|
|
4496
|
+
data.A = attrs;
|
|
4497
|
+
}
|
|
4498
|
+
if (options.scope) {
|
|
4499
|
+
data.A = {
|
|
4500
|
+
...(data.A || {}),
|
|
4501
|
+
O: 'Table',
|
|
4502
|
+
Scope: options.scope
|
|
4503
|
+
};
|
|
4504
|
+
}
|
|
4232
4505
|
this._children = [];
|
|
4233
4506
|
if (children) {
|
|
4234
4507
|
if (!Array.isArray(children)) {
|
|
@@ -4254,6 +4527,9 @@ class PDFStructureElement {
|
|
|
4254
4527
|
if (child instanceof PDFStructureContent) {
|
|
4255
4528
|
this._addContentToParentTree(child);
|
|
4256
4529
|
}
|
|
4530
|
+
if (child instanceof PDFAnnotationReference) {
|
|
4531
|
+
this._addAnnotationToParentTree(child.annotationRef);
|
|
4532
|
+
}
|
|
4257
4533
|
if (typeof child === 'function' && this._attached) {
|
|
4258
4534
|
child = this._contentForClosure(child);
|
|
4259
4535
|
}
|
|
@@ -4261,15 +4537,20 @@ class PDFStructureElement {
|
|
|
4261
4537
|
return this;
|
|
4262
4538
|
}
|
|
4263
4539
|
_addContentToParentTree(content) {
|
|
4264
|
-
content.refs.forEach(
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
} = _ref;
|
|
4540
|
+
content.refs.forEach(({
|
|
4541
|
+
pageRef,
|
|
4542
|
+
mcid
|
|
4543
|
+
}) => {
|
|
4269
4544
|
const pageStructParents = this.document.getStructParentTree().get(pageRef.data.StructParents);
|
|
4270
4545
|
pageStructParents[mcid] = this.dictionary;
|
|
4271
4546
|
});
|
|
4272
4547
|
}
|
|
4548
|
+
_addAnnotationToParentTree(annotRef) {
|
|
4549
|
+
const parentTreeKey = this.document.createStructParentTreeNextKey();
|
|
4550
|
+
annotRef.data.StructParent = parentTreeKey;
|
|
4551
|
+
const parentTree = this.document.getStructParentTree();
|
|
4552
|
+
parentTree.add(parentTreeKey, this.dictionary);
|
|
4553
|
+
}
|
|
4273
4554
|
setParent(parentRef) {
|
|
4274
4555
|
if (this.dictionary.data.P) {
|
|
4275
4556
|
throw new Error(`Structure element added to more than one parent`);
|
|
@@ -4301,11 +4582,17 @@ class PDFStructureElement {
|
|
|
4301
4582
|
this._flush();
|
|
4302
4583
|
}
|
|
4303
4584
|
_isValidChild(child) {
|
|
4304
|
-
return child instanceof PDFStructureElement || child instanceof PDFStructureContent || typeof child === 'function';
|
|
4585
|
+
return child instanceof PDFStructureElement || child instanceof PDFStructureContent || child instanceof PDFAnnotationReference || typeof child === 'function';
|
|
4305
4586
|
}
|
|
4306
4587
|
_contentForClosure(closure) {
|
|
4307
4588
|
const content = this.document.markStructureContent(this.dictionary.data.S);
|
|
4589
|
+
const prevStructElement = this.document._currentStructureElement;
|
|
4590
|
+
this.document._currentStructureElement = this;
|
|
4591
|
+
const wasEnded = this._ended;
|
|
4592
|
+
this._ended = false;
|
|
4308
4593
|
closure();
|
|
4594
|
+
this._ended = wasEnded;
|
|
4595
|
+
this.document._currentStructureElement = prevStructElement;
|
|
4309
4596
|
this.document.endMarkedContent();
|
|
4310
4597
|
this._addContentToParentTree(content);
|
|
4311
4598
|
return content;
|
|
@@ -4340,11 +4627,10 @@ class PDFStructureElement {
|
|
|
4340
4627
|
this.dictionary.data.K.push(child.dictionary);
|
|
4341
4628
|
}
|
|
4342
4629
|
if (child instanceof PDFStructureContent) {
|
|
4343
|
-
child.refs.forEach(
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
} = _ref2;
|
|
4630
|
+
child.refs.forEach(({
|
|
4631
|
+
pageRef,
|
|
4632
|
+
mcid
|
|
4633
|
+
}) => {
|
|
4348
4634
|
if (!this.dictionary.data.Pg) {
|
|
4349
4635
|
this.dictionary.data.Pg = pageRef;
|
|
4350
4636
|
}
|
|
@@ -4359,6 +4645,15 @@ class PDFStructureElement {
|
|
|
4359
4645
|
}
|
|
4360
4646
|
});
|
|
4361
4647
|
}
|
|
4648
|
+
if (child instanceof PDFAnnotationReference) {
|
|
4649
|
+
const pageRef = this.document.page.dictionary;
|
|
4650
|
+
const objr = {
|
|
4651
|
+
Type: 'OBJR',
|
|
4652
|
+
Obj: child.annotationRef,
|
|
4653
|
+
Pg: pageRef
|
|
4654
|
+
};
|
|
4655
|
+
this.dictionary.data.K.push(objr);
|
|
4656
|
+
}
|
|
4362
4657
|
}
|
|
4363
4658
|
}
|
|
4364
4659
|
|
|
@@ -4382,8 +4677,7 @@ var MarkingsMixin = {
|
|
|
4382
4677
|
this.getStructTreeRoot();
|
|
4383
4678
|
}
|
|
4384
4679
|
},
|
|
4385
|
-
markContent(tag) {
|
|
4386
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
4680
|
+
markContent(tag, options = null) {
|
|
4387
4681
|
if (tag === 'Artifact' || options && options.mcid) {
|
|
4388
4682
|
let toClose = 0;
|
|
4389
4683
|
this.page.markings.forEach(marking => {
|
|
@@ -4438,8 +4732,7 @@ var MarkingsMixin = {
|
|
|
4438
4732
|
this.addContent(`/${tag} ${PDFObject.convert(dictionary)} BDC`);
|
|
4439
4733
|
return this;
|
|
4440
4734
|
},
|
|
4441
|
-
markStructureContent(tag) {
|
|
4442
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
4735
|
+
markStructureContent(tag, options = {}) {
|
|
4443
4736
|
const pageStructParents = this.getStructParentTree().get(this.page.structParentTreeKey);
|
|
4444
4737
|
const mcid = pageStructParents.length;
|
|
4445
4738
|
pageStructParents.push(null);
|
|
@@ -4454,11 +4747,16 @@ var MarkingsMixin = {
|
|
|
4454
4747
|
endMarkedContent() {
|
|
4455
4748
|
this.page.markings.pop();
|
|
4456
4749
|
this.addContent('EMC');
|
|
4750
|
+
if (this._textOptions) {
|
|
4751
|
+
delete this._textOptions.link;
|
|
4752
|
+
delete this._textOptions.goTo;
|
|
4753
|
+
delete this._textOptions.destination;
|
|
4754
|
+
delete this._textOptions.underline;
|
|
4755
|
+
delete this._textOptions.strike;
|
|
4756
|
+
}
|
|
4457
4757
|
return this;
|
|
4458
4758
|
},
|
|
4459
|
-
struct(type) {
|
|
4460
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
4461
|
-
let children = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
|
4759
|
+
struct(type, options = {}, children = null) {
|
|
4462
4760
|
return new PDFStructureElement(this, type, options, children);
|
|
4463
4761
|
},
|
|
4464
4762
|
addStructure(structElem) {
|
|
@@ -4623,15 +4921,13 @@ var AcroFormMixin = {
|
|
|
4623
4921
|
}
|
|
4624
4922
|
return this;
|
|
4625
4923
|
},
|
|
4626
|
-
formField(name) {
|
|
4627
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
4924
|
+
formField(name, options = {}) {
|
|
4628
4925
|
let fieldDict = this._fieldDict(name, null, options);
|
|
4629
4926
|
let fieldRef = this.ref(fieldDict);
|
|
4630
4927
|
this._addToParent(fieldRef);
|
|
4631
4928
|
return fieldRef;
|
|
4632
4929
|
},
|
|
4633
|
-
formAnnotation(name, type, x, y, w, h) {
|
|
4634
|
-
let options = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {};
|
|
4930
|
+
formAnnotation(name, type, x, y, w, h, options = {}) {
|
|
4635
4931
|
let fieldDict = this._fieldDict(name, type, options);
|
|
4636
4932
|
fieldDict.Subtype = 'Widget';
|
|
4637
4933
|
if (fieldDict.F === undefined) {
|
|
@@ -4641,28 +4937,22 @@ var AcroFormMixin = {
|
|
|
4641
4937
|
let annotRef = this.page.annotations[this.page.annotations.length - 1];
|
|
4642
4938
|
return this._addToParent(annotRef);
|
|
4643
4939
|
},
|
|
4644
|
-
formText(name, x, y, w, h) {
|
|
4645
|
-
let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
4940
|
+
formText(name, x, y, w, h, options = {}) {
|
|
4646
4941
|
return this.formAnnotation(name, 'text', x, y, w, h, options);
|
|
4647
4942
|
},
|
|
4648
|
-
formPushButton(name, x, y, w, h) {
|
|
4649
|
-
let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
4943
|
+
formPushButton(name, x, y, w, h, options = {}) {
|
|
4650
4944
|
return this.formAnnotation(name, 'pushButton', x, y, w, h, options);
|
|
4651
4945
|
},
|
|
4652
|
-
formCombo(name, x, y, w, h) {
|
|
4653
|
-
let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
4946
|
+
formCombo(name, x, y, w, h, options = {}) {
|
|
4654
4947
|
return this.formAnnotation(name, 'combo', x, y, w, h, options);
|
|
4655
4948
|
},
|
|
4656
|
-
formList(name, x, y, w, h) {
|
|
4657
|
-
let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
4949
|
+
formList(name, x, y, w, h, options = {}) {
|
|
4658
4950
|
return this.formAnnotation(name, 'list', x, y, w, h, options);
|
|
4659
4951
|
},
|
|
4660
|
-
formRadioButton(name, x, y, w, h) {
|
|
4661
|
-
let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
4952
|
+
formRadioButton(name, x, y, w, h, options = {}) {
|
|
4662
4953
|
return this.formAnnotation(name, 'radioButton', x, y, w, h, options);
|
|
4663
4954
|
},
|
|
4664
|
-
formCheckbox(name, x, y, w, h) {
|
|
4665
|
-
let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
4955
|
+
formCheckbox(name, x, y, w, h, options = {}) {
|
|
4666
4956
|
return this.formAnnotation(name, 'checkbox', x, y, w, h, options);
|
|
4667
4957
|
},
|
|
4668
4958
|
_addToParent(fieldRef) {
|
|
@@ -4677,8 +4967,7 @@ var AcroFormMixin = {
|
|
|
4677
4967
|
}
|
|
4678
4968
|
return this;
|
|
4679
4969
|
},
|
|
4680
|
-
_fieldDict(name, type) {
|
|
4681
|
-
let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
4970
|
+
_fieldDict(name, type, options = {}) {
|
|
4682
4971
|
if (!this._acroform) {
|
|
4683
4972
|
throw new Error('Call document.initForm() method before adding form elements to document');
|
|
4684
4973
|
}
|
|
@@ -4867,8 +5156,7 @@ var AcroFormMixin = {
|
|
|
4867
5156
|
};
|
|
4868
5157
|
|
|
4869
5158
|
var AttachmentsMixin = {
|
|
4870
|
-
file(src) {
|
|
4871
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
5159
|
+
file(src, options = {}) {
|
|
4872
5160
|
options.name = options.name || src;
|
|
4873
5161
|
options.relationship = options.relationship || 'Unspecified';
|
|
4874
5162
|
const refBody = {
|
|
@@ -4887,7 +5175,7 @@ var AttachmentsMixin = {
|
|
|
4887
5175
|
const match = /^data:(.*?);base64,(.*)$/.exec(src);
|
|
4888
5176
|
if (match) {
|
|
4889
5177
|
if (match[1]) {
|
|
4890
|
-
refBody.Subtype = match[1]
|
|
5178
|
+
refBody.Subtype = escapeName(match[1]);
|
|
4891
5179
|
}
|
|
4892
5180
|
data = Buffer.from(match[2], 'base64');
|
|
4893
5181
|
} else {
|
|
@@ -4910,9 +5198,9 @@ var AttachmentsMixin = {
|
|
|
4910
5198
|
refBody.Params.ModDate = options.modifiedDate;
|
|
4911
5199
|
}
|
|
4912
5200
|
if (options.type) {
|
|
4913
|
-
refBody.Subtype = options.type
|
|
5201
|
+
refBody.Subtype = escapeName(options.type);
|
|
4914
5202
|
}
|
|
4915
|
-
const checksum =
|
|
5203
|
+
const checksum = md5Hex(new Uint8Array(data));
|
|
4916
5204
|
refBody.Params.CheckSum = new String(checksum);
|
|
4917
5205
|
refBody.Params.Size = data.byteLength;
|
|
4918
5206
|
let ref;
|
|
@@ -5051,10 +5339,10 @@ const ROW_FIELDS = ['height', 'minHeight', 'maxHeight'];
|
|
|
5051
5339
|
const COLUMN_FIELDS = ['width', 'minWidth', 'maxWidth'];
|
|
5052
5340
|
function memoize(fn, maxSize) {
|
|
5053
5341
|
const cache = new Map();
|
|
5054
|
-
return function () {
|
|
5055
|
-
const key =
|
|
5342
|
+
return function (...args) {
|
|
5343
|
+
const key = args[0];
|
|
5056
5344
|
if (!cache.has(key)) {
|
|
5057
|
-
cache.set(key, fn(...
|
|
5345
|
+
cache.set(key, fn(...args));
|
|
5058
5346
|
if (cache.size > maxSize) cache.delete(cache.keys().next());
|
|
5059
5347
|
}
|
|
5060
5348
|
return cache.get(key);
|
|
@@ -5063,12 +5351,9 @@ function memoize(fn, maxSize) {
|
|
|
5063
5351
|
function isObject(item) {
|
|
5064
5352
|
return item && typeof item === 'object' && !Array.isArray(item);
|
|
5065
5353
|
}
|
|
5066
|
-
function deepMerge(target) {
|
|
5354
|
+
function deepMerge(target, ...sources) {
|
|
5067
5355
|
if (!isObject(target)) return target;
|
|
5068
5356
|
target = deepClone(target);
|
|
5069
|
-
for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
5070
|
-
sources[_key - 1] = arguments[_key];
|
|
5071
|
-
}
|
|
5072
5357
|
for (const source of sources) {
|
|
5073
5358
|
if (isObject(source)) {
|
|
5074
5359
|
for (const key in source) {
|
|
@@ -5097,14 +5382,8 @@ function normalizedDefaultStyle(defaultStyleInternal) {
|
|
|
5097
5382
|
if (typeof defaultStyle !== 'object') defaultStyle = {
|
|
5098
5383
|
text: defaultStyle
|
|
5099
5384
|
};
|
|
5100
|
-
const defaultRowStyle = Object.fromEntries(Object.entries(defaultStyle).filter(
|
|
5101
|
-
|
|
5102
|
-
return ROW_FIELDS.includes(k);
|
|
5103
|
-
}));
|
|
5104
|
-
const defaultColStyle = Object.fromEntries(Object.entries(defaultStyle).filter(_ref2 => {
|
|
5105
|
-
let [k] = _ref2;
|
|
5106
|
-
return COLUMN_FIELDS.includes(k);
|
|
5107
|
-
}));
|
|
5385
|
+
const defaultRowStyle = Object.fromEntries(Object.entries(defaultStyle).filter(([k]) => ROW_FIELDS.includes(k)));
|
|
5386
|
+
const defaultColStyle = Object.fromEntries(Object.entries(defaultStyle).filter(([k]) => COLUMN_FIELDS.includes(k)));
|
|
5108
5387
|
defaultStyle.padding = normalizeSides(defaultStyle.padding);
|
|
5109
5388
|
defaultStyle.border = normalizeSides(defaultStyle.border);
|
|
5110
5389
|
defaultStyle.borderColor = normalizeSides(defaultStyle.borderColor);
|
|
@@ -5564,7 +5843,7 @@ function renderRow(row, rowIndex) {
|
|
|
5564
5843
|
function renderCell(cell, rowStruct) {
|
|
5565
5844
|
const cellRenderer = () => {
|
|
5566
5845
|
if (cell.backgroundColor != null) {
|
|
5567
|
-
this.document.save().rect(cell.x, cell.y, cell.width, cell.height).fill(
|
|
5846
|
+
this.document.save().fillColor(cell.backgroundColor).rect(cell.x, cell.y, cell.width, cell.height).fill().restore();
|
|
5568
5847
|
}
|
|
5569
5848
|
renderBorder.call(this, cell.border, cell.borderColor, cell.x, cell.y, cell.width, cell.height);
|
|
5570
5849
|
if (cell.debug) {
|
|
@@ -5621,34 +5900,30 @@ function renderCellText(cell) {
|
|
|
5621
5900
|
if (cell.font) doc.font(rollbackFont, rollbackFontFamily, rollbackFontSize);
|
|
5622
5901
|
}
|
|
5623
5902
|
function renderBorder(border, borderColor, x, y, width, height, mask) {
|
|
5624
|
-
border = Object.fromEntries(Object.entries(border).map(
|
|
5625
|
-
let [k, v] = _ref;
|
|
5626
|
-
return [k, mask && !mask[k] ? 0 : v];
|
|
5627
|
-
}));
|
|
5903
|
+
border = Object.fromEntries(Object.entries(border).map(([k, v]) => [k, mask && !mask[k] ? 0 : v]));
|
|
5628
5904
|
const doc = this.document;
|
|
5629
5905
|
if ([border.right, border.bottom, border.left].every(val => val === border.top)) {
|
|
5630
5906
|
if (border.top > 0) {
|
|
5631
|
-
doc.save().lineWidth(border.top).rect(x, y, width, height).stroke(
|
|
5907
|
+
doc.save().lineWidth(border.top).strokeColor(borderColor.top).rect(x, y, width, height).stroke().restore();
|
|
5632
5908
|
}
|
|
5633
5909
|
} else {
|
|
5634
5910
|
if (border.top > 0) {
|
|
5635
|
-
doc.save().lineWidth(border.top).moveTo(x, y).lineTo(x + width, y).stroke(
|
|
5911
|
+
doc.save().lineWidth(border.top).moveTo(x, y).strokeColor(borderColor.top).lineTo(x + width, y).stroke().restore();
|
|
5636
5912
|
}
|
|
5637
5913
|
if (border.right > 0) {
|
|
5638
|
-
doc.save().lineWidth(border.right).moveTo(x + width, y).lineTo(x + width, y + height).stroke(
|
|
5914
|
+
doc.save().lineWidth(border.right).moveTo(x + width, y).strokeColor(borderColor.right).lineTo(x + width, y + height).stroke().restore();
|
|
5639
5915
|
}
|
|
5640
5916
|
if (border.bottom > 0) {
|
|
5641
|
-
doc.save().lineWidth(border.bottom).moveTo(x + width, y + height).lineTo(x, y + height).stroke(
|
|
5917
|
+
doc.save().lineWidth(border.bottom).moveTo(x + width, y + height).strokeColor(borderColor.bottom).lineTo(x, y + height).stroke().restore();
|
|
5642
5918
|
}
|
|
5643
5919
|
if (border.left > 0) {
|
|
5644
|
-
doc.save().lineWidth(border.left).moveTo(x, y + height).lineTo(x, y).stroke(
|
|
5920
|
+
doc.save().lineWidth(border.left).moveTo(x, y + height).strokeColor(borderColor.left).lineTo(x, y).stroke().restore();
|
|
5645
5921
|
}
|
|
5646
5922
|
}
|
|
5647
5923
|
}
|
|
5648
5924
|
|
|
5649
5925
|
class PDFTable {
|
|
5650
|
-
constructor(document) {
|
|
5651
|
-
let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
5926
|
+
constructor(document, opts = {}) {
|
|
5652
5927
|
this.document = document;
|
|
5653
5928
|
this.opts = Object.freeze(opts);
|
|
5654
5929
|
normalizeTable.call(this);
|
|
@@ -5660,8 +5935,7 @@ class PDFTable {
|
|
|
5660
5935
|
return this.end();
|
|
5661
5936
|
}
|
|
5662
5937
|
}
|
|
5663
|
-
row(row) {
|
|
5664
|
-
let lastRow = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
5938
|
+
row(row, lastRow = false) {
|
|
5665
5939
|
if (this._ended) {
|
|
5666
5940
|
throw new Error(`Table was marked as ended on row ${this._currRowIndex}`);
|
|
5667
5941
|
}
|
|
@@ -5712,8 +5986,7 @@ class PDFMetadata {
|
|
|
5712
5986
|
<?xpacket end="w"?>
|
|
5713
5987
|
`);
|
|
5714
5988
|
}
|
|
5715
|
-
append(xml) {
|
|
5716
|
-
let newline = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
5989
|
+
append(xml, newline = true) {
|
|
5717
5990
|
this._metadata = this._metadata.concat(xml);
|
|
5718
5991
|
if (newline) this._metadata = this._metadata.concat('\n');
|
|
5719
5992
|
}
|
|
@@ -5733,8 +6006,7 @@ var MetadataMixin = {
|
|
|
5733
6006
|
initMetadata() {
|
|
5734
6007
|
this.metadata = new PDFMetadata();
|
|
5735
6008
|
},
|
|
5736
|
-
appendXML(xml) {
|
|
5737
|
-
let newline = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
6009
|
+
appendXML(xml, newline = true) {
|
|
5738
6010
|
this.metadata.append(xml, newline);
|
|
5739
6011
|
},
|
|
5740
6012
|
_addInfo() {
|
|
@@ -5781,7 +6053,7 @@ var MetadataMixin = {
|
|
|
5781
6053
|
}
|
|
5782
6054
|
this.appendXML(`
|
|
5783
6055
|
<rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
|
|
5784
|
-
<pdf:Producer>${this.info.
|
|
6056
|
+
<pdf:Producer>${this.info.Producer}</pdf:Producer>`, false);
|
|
5785
6057
|
if (this.info.Keywords) {
|
|
5786
6058
|
this.appendXML(`
|
|
5787
6059
|
<pdf:Keywords>${this.info.Keywords}</pdf:Keywords>`, false);
|
|
@@ -5808,8 +6080,7 @@ var MetadataMixin = {
|
|
|
5808
6080
|
};
|
|
5809
6081
|
|
|
5810
6082
|
class PDFDocument extends stream.Readable {
|
|
5811
|
-
constructor() {
|
|
5812
|
-
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
6083
|
+
constructor(options = {}) {
|
|
5813
6084
|
super(options);
|
|
5814
6085
|
this.options = options;
|
|
5815
6086
|
switch (options.pdfVersion) {
|
|
@@ -5853,6 +6124,10 @@ class PDFDocument extends stream.Readable {
|
|
|
5853
6124
|
if (this.options.lang) {
|
|
5854
6125
|
this._root.data.Lang = new String(this.options.lang);
|
|
5855
6126
|
}
|
|
6127
|
+
if (this.options.pageLayout) {
|
|
6128
|
+
const layout = this.options.pageLayout;
|
|
6129
|
+
this._root.data.PageLayout = layout.charAt(0).toUpperCase() + layout.slice(1);
|
|
6130
|
+
}
|
|
5856
6131
|
this.page = null;
|
|
5857
6132
|
this.initMetadata();
|
|
5858
6133
|
this.initColor();
|
|
@@ -5937,10 +6212,7 @@ class PDFDocument extends stream.Readable {
|
|
|
5937
6212
|
page.end();
|
|
5938
6213
|
}
|
|
5939
6214
|
}
|
|
5940
|
-
addNamedDestination(name) {
|
|
5941
|
-
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
5942
|
-
args[_key - 1] = arguments[_key];
|
|
5943
|
-
}
|
|
6215
|
+
addNamedDestination(name, ...args) {
|
|
5944
6216
|
if (args.length === 0) {
|
|
5945
6217
|
args = ['XYZ', null, null, null];
|
|
5946
6218
|
}
|