pdfkit 0.17.2 → 0.18.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 +150 -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 +424 -159
- package/js/pdfkit.es.js.map +1 -1
- package/js/pdfkit.js +423 -159
- package/js/pdfkit.js.map +1 -1
- package/js/pdfkit.standalone.js +27350 -31546
- package/jsconfig.json +12 -12
- package/package.json +93 -92
- package/types/jest.custom-matchers.d.ts +28 -28
- 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.js
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
var stream = require('stream');
|
|
4
4
|
var zlib = require('zlib');
|
|
5
|
-
var
|
|
5
|
+
var utils = require('@noble/hashes/utils');
|
|
6
|
+
var md5 = require('js-md5');
|
|
7
|
+
var sha256 = require('@noble/hashes/sha256');
|
|
8
|
+
var aes = require('@noble/ciphers/aes');
|
|
6
9
|
var fs = require('fs');
|
|
7
10
|
var fontkit = require('fontkit');
|
|
8
11
|
var events = require('events');
|
|
9
12
|
var LineBreaker = require('linebreak');
|
|
10
|
-
var exif = require('jpeg-exif');
|
|
11
13
|
var PNG = require('png-js');
|
|
12
14
|
|
|
13
15
|
class PDFAbstractReference {
|
|
@@ -359,6 +361,7 @@ class PDFPage {
|
|
|
359
361
|
this._options = options;
|
|
360
362
|
this.size = options.size || 'letter';
|
|
361
363
|
this.layout = options.layout || 'portrait';
|
|
364
|
+
this.userUnit = options.userUnit || 1.0;
|
|
362
365
|
const dimensions = Array.isArray(this.size) ? this.size : SIZES[this.size.toUpperCase()];
|
|
363
366
|
this.width = dimensions[this.layout === 'portrait' ? 0 : 1];
|
|
364
367
|
this.height = dimensions[this.layout === 'portrait' ? 1 : 0];
|
|
@@ -374,7 +377,8 @@ class PDFPage {
|
|
|
374
377
|
Parent: this.document._root.data.Pages,
|
|
375
378
|
MediaBox: [0, 0, this.width, this.height],
|
|
376
379
|
Contents: this.content,
|
|
377
|
-
Resources: this.resources
|
|
380
|
+
Resources: this.resources,
|
|
381
|
+
UserUnit: this.userUnit
|
|
378
382
|
});
|
|
379
383
|
this.markings = [];
|
|
380
384
|
}
|
|
@@ -447,6 +451,58 @@ class PDFNameTree extends PDFTree {
|
|
|
447
451
|
}
|
|
448
452
|
}
|
|
449
453
|
|
|
454
|
+
function md5Hash(data) {
|
|
455
|
+
return new Uint8Array(md5.arrayBuffer(data));
|
|
456
|
+
}
|
|
457
|
+
function md5Hex(data) {
|
|
458
|
+
return md5(data);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function sha256Hash(data) {
|
|
462
|
+
return sha256.sha256(data);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function aesCbcEncrypt(data, key, iv, padding = true) {
|
|
466
|
+
return aes.cbc(key, iv, {
|
|
467
|
+
disablePadding: !padding
|
|
468
|
+
}).encrypt(data);
|
|
469
|
+
}
|
|
470
|
+
function aesEcbEncrypt(data, key) {
|
|
471
|
+
return aes.ecb(key, {
|
|
472
|
+
disablePadding: true
|
|
473
|
+
}).encrypt(data);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function rc4(data, key) {
|
|
477
|
+
const s = new Uint8Array(256);
|
|
478
|
+
for (let i = 0; i < 256; i++) {
|
|
479
|
+
s[i] = i;
|
|
480
|
+
}
|
|
481
|
+
let j = 0;
|
|
482
|
+
for (let i = 0; i < 256; i++) {
|
|
483
|
+
j = j + s[i] + key[i % key.length] & 0xff;
|
|
484
|
+
[s[i], s[j]] = [s[j], s[i]];
|
|
485
|
+
}
|
|
486
|
+
const output = new Uint8Array(data.length);
|
|
487
|
+
for (let i = 0, j = 0, k = 0; k < data.length; k++) {
|
|
488
|
+
i = i + 1 & 0xff;
|
|
489
|
+
j = j + s[i] & 0xff;
|
|
490
|
+
[s[i], s[j]] = [s[j], s[i]];
|
|
491
|
+
output[k] = data[k] ^ s[s[i] + s[j] & 0xff];
|
|
492
|
+
}
|
|
493
|
+
return output;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function randomBytes(length) {
|
|
497
|
+
const bytes = new Uint8Array(length);
|
|
498
|
+
if (globalThis.crypto?.getRandomValues) {
|
|
499
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
500
|
+
} else {
|
|
501
|
+
require('crypto').randomFillSync(bytes);
|
|
502
|
+
}
|
|
503
|
+
return bytes;
|
|
504
|
+
}
|
|
505
|
+
|
|
450
506
|
function inRange(value, rangeGroup) {
|
|
451
507
|
if (value < rangeGroup[0]) return false;
|
|
452
508
|
let startRange = 0;
|
|
@@ -545,10 +601,10 @@ class PDFSecurity {
|
|
|
545
601
|
}
|
|
546
602
|
infoStr += `${key}: ${info[key].valueOf()}\n`;
|
|
547
603
|
}
|
|
548
|
-
return
|
|
604
|
+
return Buffer.from(md5Hash(infoStr));
|
|
549
605
|
}
|
|
550
606
|
static generateRandomWordArray(bytes) {
|
|
551
|
-
return
|
|
607
|
+
return randomBytes(bytes);
|
|
552
608
|
}
|
|
553
609
|
static create(document, options = {}) {
|
|
554
610
|
if (!options.ownerPassword && !options.userPassword) {
|
|
@@ -640,8 +696,8 @@ class PDFSecurity {
|
|
|
640
696
|
encDict.StrF = 'StdCF';
|
|
641
697
|
}
|
|
642
698
|
encDict.R = r;
|
|
643
|
-
encDict.O =
|
|
644
|
-
encDict.U =
|
|
699
|
+
encDict.O = Buffer.from(ownerPasswordEntry);
|
|
700
|
+
encDict.U = Buffer.from(userPasswordEntry);
|
|
645
701
|
encDict.P = permissions;
|
|
646
702
|
}
|
|
647
703
|
_setupEncryptionV5(encDict, options) {
|
|
@@ -651,10 +707,10 @@ class PDFSecurity {
|
|
|
651
707
|
const processedOwnerPassword = options.ownerPassword ? processPasswordR5(options.ownerPassword) : processedUserPassword;
|
|
652
708
|
this.encryptionKey = getEncryptionKeyR5(PDFSecurity.generateRandomWordArray);
|
|
653
709
|
const userPasswordEntry = getUserPasswordR5(processedUserPassword, PDFSecurity.generateRandomWordArray);
|
|
654
|
-
const userKeySalt =
|
|
710
|
+
const userKeySalt = userPasswordEntry.slice(40, 48);
|
|
655
711
|
const userEncryptionKeyEntry = getUserEncryptionKeyR5(processedUserPassword, userKeySalt, this.encryptionKey);
|
|
656
712
|
const ownerPasswordEntry = getOwnerPasswordR5(processedOwnerPassword, userPasswordEntry, PDFSecurity.generateRandomWordArray);
|
|
657
|
-
const ownerKeySalt =
|
|
713
|
+
const ownerKeySalt = ownerPasswordEntry.slice(40, 48);
|
|
658
714
|
const ownerEncryptionKeyEntry = getOwnerEncryptionKeyR5(processedOwnerPassword, ownerKeySalt, userPasswordEntry, this.encryptionKey);
|
|
659
715
|
const permsEntry = getEncryptedPermissionsR5(permissions, this.encryptionKey, PDFSecurity.generateRandomWordArray);
|
|
660
716
|
encDict.V = 5;
|
|
@@ -669,36 +725,37 @@ class PDFSecurity {
|
|
|
669
725
|
encDict.StmF = 'StdCF';
|
|
670
726
|
encDict.StrF = 'StdCF';
|
|
671
727
|
encDict.R = 5;
|
|
672
|
-
encDict.O =
|
|
673
|
-
encDict.OE =
|
|
674
|
-
encDict.U =
|
|
675
|
-
encDict.UE =
|
|
728
|
+
encDict.O = Buffer.from(ownerPasswordEntry);
|
|
729
|
+
encDict.OE = Buffer.from(ownerEncryptionKeyEntry);
|
|
730
|
+
encDict.U = Buffer.from(userPasswordEntry);
|
|
731
|
+
encDict.UE = Buffer.from(userEncryptionKeyEntry);
|
|
676
732
|
encDict.P = permissions;
|
|
677
|
-
encDict.Perms =
|
|
733
|
+
encDict.Perms = Buffer.from(permsEntry);
|
|
678
734
|
}
|
|
679
735
|
getEncryptFn(obj, gen) {
|
|
680
736
|
let digest;
|
|
681
737
|
if (this.version < 5) {
|
|
682
|
-
|
|
738
|
+
const suffix = new Uint8Array([obj & 0xff, obj >> 8 & 0xff, obj >> 16 & 0xff, gen & 0xff, gen >> 8 & 0xff]);
|
|
739
|
+
digest = utils.concatBytes(this.encryptionKey, suffix);
|
|
683
740
|
}
|
|
684
741
|
if (this.version === 1 || this.version === 2) {
|
|
685
|
-
let key =
|
|
686
|
-
|
|
687
|
-
|
|
742
|
+
let key = md5Hash(digest);
|
|
743
|
+
const keyLen = Math.min(16, this.keyBits / 8 + 5);
|
|
744
|
+
key = key.slice(0, keyLen);
|
|
745
|
+
return buffer => Buffer.from(rc4(new Uint8Array(buffer), key));
|
|
688
746
|
}
|
|
689
747
|
let key;
|
|
690
748
|
if (this.version === 4) {
|
|
691
|
-
|
|
749
|
+
const saltMarker = new Uint8Array([0x73, 0x41, 0x6c, 0x54]);
|
|
750
|
+
key = md5Hash(utils.concatBytes(digest, saltMarker));
|
|
692
751
|
} else {
|
|
693
752
|
key = this.encryptionKey;
|
|
694
753
|
}
|
|
695
754
|
const iv = PDFSecurity.generateRandomWordArray(16);
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
iv
|
|
755
|
+
return buffer => {
|
|
756
|
+
const encrypted = aesCbcEncrypt(new Uint8Array(buffer), key, iv, true);
|
|
757
|
+
return Buffer.from(utils.concatBytes(iv, encrypted));
|
|
700
758
|
};
|
|
701
|
-
return buffer => wordArrayToBuffer(iv.clone().concat(CryptoJS.AES.encrypt(CryptoJS.lib.WordArray.create(buffer), key, options).ciphertext));
|
|
702
759
|
}
|
|
703
760
|
end() {
|
|
704
761
|
this.dictionary.end();
|
|
@@ -749,89 +806,97 @@ function getPermissionsR3(permissionObject = {}) {
|
|
|
749
806
|
return permissions;
|
|
750
807
|
}
|
|
751
808
|
function getUserPasswordR2(encryptionKey) {
|
|
752
|
-
return
|
|
809
|
+
return rc4(processPasswordR2R3R4(), encryptionKey);
|
|
753
810
|
}
|
|
754
811
|
function getUserPasswordR3R4(documentId, encryptionKey) {
|
|
755
|
-
const key = encryptionKey.
|
|
756
|
-
let cipher =
|
|
812
|
+
const key = encryptionKey.slice();
|
|
813
|
+
let cipher = md5Hash(utils.concatBytes(processPasswordR2R3R4(), new Uint8Array(documentId)));
|
|
757
814
|
for (let i = 0; i < 20; i++) {
|
|
758
|
-
const
|
|
759
|
-
for (let j = 0; j <
|
|
760
|
-
|
|
815
|
+
const xorKey = new Uint8Array(key.length);
|
|
816
|
+
for (let j = 0; j < key.length; j++) {
|
|
817
|
+
xorKey[j] = encryptionKey[j] ^ i;
|
|
761
818
|
}
|
|
762
|
-
cipher =
|
|
819
|
+
cipher = rc4(cipher, xorKey);
|
|
763
820
|
}
|
|
764
|
-
|
|
821
|
+
const result = new Uint8Array(32);
|
|
822
|
+
result.set(cipher);
|
|
823
|
+
return result;
|
|
765
824
|
}
|
|
766
825
|
function getOwnerPasswordR2R3R4(r, keyBits, paddedUserPassword, paddedOwnerPassword) {
|
|
767
826
|
let digest = paddedOwnerPassword;
|
|
768
827
|
let round = r >= 3 ? 51 : 1;
|
|
769
828
|
for (let i = 0; i < round; i++) {
|
|
770
|
-
digest =
|
|
829
|
+
digest = md5Hash(digest);
|
|
771
830
|
}
|
|
772
|
-
const
|
|
773
|
-
key
|
|
831
|
+
const keyLen = keyBits / 8;
|
|
832
|
+
let key = digest.slice(0, keyLen);
|
|
774
833
|
let cipher = paddedUserPassword;
|
|
775
834
|
round = r >= 3 ? 20 : 1;
|
|
776
835
|
for (let i = 0; i < round; i++) {
|
|
777
|
-
const
|
|
778
|
-
for (let j = 0; j <
|
|
779
|
-
|
|
836
|
+
const xorKey = new Uint8Array(keyLen);
|
|
837
|
+
for (let j = 0; j < keyLen; j++) {
|
|
838
|
+
xorKey[j] = key[j] ^ i;
|
|
780
839
|
}
|
|
781
|
-
cipher =
|
|
840
|
+
cipher = rc4(cipher, xorKey);
|
|
782
841
|
}
|
|
783
842
|
return cipher;
|
|
784
843
|
}
|
|
785
844
|
function getEncryptionKeyR2R3R4(r, keyBits, documentId, paddedUserPassword, ownerPasswordEntry, permissions) {
|
|
786
|
-
|
|
845
|
+
const permBytes = new Uint8Array([permissions & 0xff, permissions >> 8 & 0xff, permissions >> 16 & 0xff, permissions >> 24 & 0xff]);
|
|
846
|
+
let key = utils.concatBytes(paddedUserPassword, ownerPasswordEntry, permBytes, new Uint8Array(documentId));
|
|
787
847
|
const round = r >= 3 ? 51 : 1;
|
|
848
|
+
const keyLen = keyBits / 8;
|
|
788
849
|
for (let i = 0; i < round; i++) {
|
|
789
|
-
key =
|
|
790
|
-
key
|
|
850
|
+
key = md5Hash(key);
|
|
851
|
+
key = key.slice(0, keyLen);
|
|
791
852
|
}
|
|
792
853
|
return key;
|
|
793
854
|
}
|
|
794
855
|
function getUserPasswordR5(processedUserPassword, generateRandomWordArray) {
|
|
795
856
|
const validationSalt = generateRandomWordArray(8);
|
|
796
857
|
const keySalt = generateRandomWordArray(8);
|
|
797
|
-
|
|
858
|
+
const hash = sha256Hash(utils.concatBytes(processedUserPassword, validationSalt));
|
|
859
|
+
return utils.concatBytes(hash, validationSalt, keySalt);
|
|
798
860
|
}
|
|
799
861
|
function getUserEncryptionKeyR5(processedUserPassword, userKeySalt, encryptionKey) {
|
|
800
|
-
const key =
|
|
801
|
-
const
|
|
802
|
-
|
|
803
|
-
padding: CryptoJS.pad.NoPadding,
|
|
804
|
-
iv: CryptoJS.lib.WordArray.create(null, 16)
|
|
805
|
-
};
|
|
806
|
-
return CryptoJS.AES.encrypt(encryptionKey, key, options).ciphertext;
|
|
862
|
+
const key = sha256Hash(utils.concatBytes(processedUserPassword, userKeySalt));
|
|
863
|
+
const iv = new Uint8Array(16);
|
|
864
|
+
return aesCbcEncrypt(encryptionKey, key, iv, false);
|
|
807
865
|
}
|
|
808
866
|
function getOwnerPasswordR5(processedOwnerPassword, userPasswordEntry, generateRandomWordArray) {
|
|
809
867
|
const validationSalt = generateRandomWordArray(8);
|
|
810
868
|
const keySalt = generateRandomWordArray(8);
|
|
811
|
-
|
|
869
|
+
const hash = sha256Hash(utils.concatBytes(processedOwnerPassword, validationSalt, userPasswordEntry));
|
|
870
|
+
return utils.concatBytes(hash, validationSalt, keySalt);
|
|
812
871
|
}
|
|
813
872
|
function getOwnerEncryptionKeyR5(processedOwnerPassword, ownerKeySalt, userPasswordEntry, encryptionKey) {
|
|
814
|
-
const key =
|
|
815
|
-
const
|
|
816
|
-
|
|
817
|
-
padding: CryptoJS.pad.NoPadding,
|
|
818
|
-
iv: CryptoJS.lib.WordArray.create(null, 16)
|
|
819
|
-
};
|
|
820
|
-
return CryptoJS.AES.encrypt(encryptionKey, key, options).ciphertext;
|
|
873
|
+
const key = sha256Hash(utils.concatBytes(processedOwnerPassword, ownerKeySalt, userPasswordEntry));
|
|
874
|
+
const iv = new Uint8Array(16);
|
|
875
|
+
return aesCbcEncrypt(encryptionKey, key, iv, false);
|
|
821
876
|
}
|
|
822
877
|
function getEncryptionKeyR5(generateRandomWordArray) {
|
|
823
878
|
return generateRandomWordArray(32);
|
|
824
879
|
}
|
|
825
880
|
function getEncryptedPermissionsR5(permissions, encryptionKey, generateRandomWordArray) {
|
|
826
|
-
const
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
881
|
+
const data = new Uint8Array(16);
|
|
882
|
+
data[0] = permissions & 0xff;
|
|
883
|
+
data[1] = permissions >> 8 & 0xff;
|
|
884
|
+
data[2] = permissions >> 16 & 0xff;
|
|
885
|
+
data[3] = permissions >> 24 & 0xff;
|
|
886
|
+
data[4] = 0xff;
|
|
887
|
+
data[5] = 0xff;
|
|
888
|
+
data[6] = 0xff;
|
|
889
|
+
data[7] = 0xff;
|
|
890
|
+
data[8] = 0x54;
|
|
891
|
+
data[9] = 0x61;
|
|
892
|
+
data[10] = 0x64;
|
|
893
|
+
data[11] = 0x62;
|
|
894
|
+
const randomPart = generateRandomWordArray(4);
|
|
895
|
+
data.set(randomPart, 12);
|
|
896
|
+
return aesEcbEncrypt(data, encryptionKey);
|
|
832
897
|
}
|
|
833
898
|
function processPasswordR2R3R4(password = '') {
|
|
834
|
-
const out =
|
|
899
|
+
const out = new Uint8Array(32);
|
|
835
900
|
const length = password.length;
|
|
836
901
|
let index = 0;
|
|
837
902
|
while (index < length && index < 32) {
|
|
@@ -846,26 +911,16 @@ function processPasswordR2R3R4(password = '') {
|
|
|
846
911
|
out[index] = PASSWORD_PADDING[index - length];
|
|
847
912
|
index++;
|
|
848
913
|
}
|
|
849
|
-
return
|
|
914
|
+
return out;
|
|
850
915
|
}
|
|
851
916
|
function processPasswordR5(password = '') {
|
|
852
917
|
password = unescape(encodeURIComponent(saslprep(password)));
|
|
853
918
|
const length = Math.min(127, password.length);
|
|
854
|
-
const out =
|
|
919
|
+
const out = new Uint8Array(length);
|
|
855
920
|
for (let i = 0; i < length; i++) {
|
|
856
921
|
out[i] = password.charCodeAt(i);
|
|
857
922
|
}
|
|
858
|
-
return
|
|
859
|
-
}
|
|
860
|
-
function lsbFirstWord(data) {
|
|
861
|
-
return (data & 0xff) << 24 | (data & 0xff00) << 8 | data >> 8 & 0xff00 | data >> 24 & 0xff;
|
|
862
|
-
}
|
|
863
|
-
function wordArrayToBuffer(wordArray) {
|
|
864
|
-
const byteArray = [];
|
|
865
|
-
for (let i = 0; i < wordArray.sigBytes; i++) {
|
|
866
|
-
byteArray.push(wordArray.words[Math.floor(i / 4)] >> 8 * (3 - i % 4) & 0xff);
|
|
867
|
-
}
|
|
868
|
-
return Buffer.from(byteArray);
|
|
923
|
+
return out;
|
|
869
924
|
}
|
|
870
925
|
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];
|
|
871
926
|
|
|
@@ -1473,86 +1528,176 @@ const parameters = {
|
|
|
1473
1528
|
Z: 0,
|
|
1474
1529
|
z: 0
|
|
1475
1530
|
};
|
|
1531
|
+
const isCommand = function (c) {
|
|
1532
|
+
return c in parameters;
|
|
1533
|
+
};
|
|
1534
|
+
const isWsp = function (c) {
|
|
1535
|
+
const codePoint = c.codePointAt(0);
|
|
1536
|
+
return codePoint === 0x20 || codePoint === 0x9 || codePoint === 0xd || codePoint === 0xa;
|
|
1537
|
+
};
|
|
1538
|
+
const isDigit = function (c) {
|
|
1539
|
+
const codePoint = c.codePointAt(0);
|
|
1540
|
+
if (codePoint == null) {
|
|
1541
|
+
return false;
|
|
1542
|
+
}
|
|
1543
|
+
return 48 <= codePoint && codePoint <= 57;
|
|
1544
|
+
};
|
|
1545
|
+
const readNumber = function (string, cursor) {
|
|
1546
|
+
let i = cursor;
|
|
1547
|
+
let value = '';
|
|
1548
|
+
let state = 'none';
|
|
1549
|
+
for (; i < string.length; i += 1) {
|
|
1550
|
+
const c = string[i];
|
|
1551
|
+
if (c === '+' || c === '-') {
|
|
1552
|
+
if (state === 'none') {
|
|
1553
|
+
state = 'sign';
|
|
1554
|
+
value += c;
|
|
1555
|
+
continue;
|
|
1556
|
+
}
|
|
1557
|
+
if (state === 'e') {
|
|
1558
|
+
state = 'exponent_sign';
|
|
1559
|
+
value += c;
|
|
1560
|
+
continue;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
if (isDigit(c)) {
|
|
1564
|
+
if (state === 'none' || state === 'sign' || state === 'whole') {
|
|
1565
|
+
state = 'whole';
|
|
1566
|
+
value += c;
|
|
1567
|
+
continue;
|
|
1568
|
+
}
|
|
1569
|
+
if (state === 'decimal_point' || state === 'decimal') {
|
|
1570
|
+
state = 'decimal';
|
|
1571
|
+
value += c;
|
|
1572
|
+
continue;
|
|
1573
|
+
}
|
|
1574
|
+
if (state === 'e' || state === 'exponent_sign' || state === 'exponent') {
|
|
1575
|
+
state = 'exponent';
|
|
1576
|
+
value += c;
|
|
1577
|
+
continue;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
if (c === '.') {
|
|
1581
|
+
if (state === 'none' || state === 'sign' || state === 'whole') {
|
|
1582
|
+
state = 'decimal_point';
|
|
1583
|
+
value += c;
|
|
1584
|
+
continue;
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
if (c === 'E' || c === 'e') {
|
|
1588
|
+
if (state === 'whole' || state === 'decimal_point' || state === 'decimal') {
|
|
1589
|
+
state = 'e';
|
|
1590
|
+
value += c;
|
|
1591
|
+
continue;
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
break;
|
|
1595
|
+
}
|
|
1596
|
+
const number = Number.parseFloat(value);
|
|
1597
|
+
if (Number.isNaN(number)) {
|
|
1598
|
+
return [cursor, null];
|
|
1599
|
+
}
|
|
1600
|
+
return [i - 1, number];
|
|
1601
|
+
};
|
|
1476
1602
|
const parse = function (path) {
|
|
1477
|
-
|
|
1478
|
-
|
|
1603
|
+
const pathData = [];
|
|
1604
|
+
let command = null;
|
|
1479
1605
|
let args = [];
|
|
1480
|
-
let
|
|
1481
|
-
let
|
|
1482
|
-
let
|
|
1483
|
-
for (let
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1606
|
+
let argsCount = 0;
|
|
1607
|
+
let canHaveComma = false;
|
|
1608
|
+
let hadComma = false;
|
|
1609
|
+
for (let i = 0; i < path.length; i += 1) {
|
|
1610
|
+
const c = path.charAt(i);
|
|
1611
|
+
if (isWsp(c)) {
|
|
1612
|
+
continue;
|
|
1613
|
+
}
|
|
1614
|
+
if (canHaveComma && c === ',') {
|
|
1615
|
+
if (hadComma) {
|
|
1616
|
+
break;
|
|
1617
|
+
}
|
|
1618
|
+
hadComma = true;
|
|
1619
|
+
continue;
|
|
1620
|
+
}
|
|
1621
|
+
if (isCommand(c)) {
|
|
1622
|
+
if (hadComma) {
|
|
1623
|
+
return pathData;
|
|
1624
|
+
}
|
|
1625
|
+
if (command == null) {
|
|
1626
|
+
if (c !== 'M' && c !== 'm') {
|
|
1627
|
+
return pathData;
|
|
1489
1628
|
}
|
|
1490
|
-
|
|
1491
|
-
|
|
1629
|
+
} else {
|
|
1630
|
+
if (args.length !== 0) {
|
|
1631
|
+
return pathData;
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
command = c;
|
|
1635
|
+
args = [];
|
|
1636
|
+
argsCount = parameters[command];
|
|
1637
|
+
canHaveComma = false;
|
|
1638
|
+
if (argsCount === 0) {
|
|
1639
|
+
pathData.push({
|
|
1640
|
+
command,
|
|
1492
1641
|
args
|
|
1493
|
-
};
|
|
1494
|
-
args = [];
|
|
1495
|
-
curArg = '';
|
|
1496
|
-
foundDecimal = false;
|
|
1642
|
+
});
|
|
1497
1643
|
}
|
|
1498
|
-
|
|
1499
|
-
}
|
|
1500
|
-
|
|
1501
|
-
|
|
1644
|
+
continue;
|
|
1645
|
+
}
|
|
1646
|
+
if (command == null) {
|
|
1647
|
+
return pathData;
|
|
1648
|
+
}
|
|
1649
|
+
let newCursor = i;
|
|
1650
|
+
let number = null;
|
|
1651
|
+
if (command === 'A' || command === 'a') {
|
|
1652
|
+
const position = args.length;
|
|
1653
|
+
if (position === 0 || position === 1) {
|
|
1654
|
+
if (c !== '+' && c !== '-') {
|
|
1655
|
+
[newCursor, number] = readNumber(path, i);
|
|
1656
|
+
}
|
|
1502
1657
|
}
|
|
1503
|
-
if (
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
if (cmd === 'M') {
|
|
1510
|
-
cmd = 'L';
|
|
1658
|
+
if (position === 2 || position === 5 || position === 6) {
|
|
1659
|
+
[newCursor, number] = readNumber(path, i);
|
|
1660
|
+
}
|
|
1661
|
+
if (position === 3 || position === 4) {
|
|
1662
|
+
if (c === '0') {
|
|
1663
|
+
number = 0;
|
|
1511
1664
|
}
|
|
1512
|
-
if (
|
|
1513
|
-
|
|
1665
|
+
if (c === '1') {
|
|
1666
|
+
number = 1;
|
|
1514
1667
|
}
|
|
1515
|
-
} else {
|
|
1516
|
-
args[args.length] = +curArg;
|
|
1517
1668
|
}
|
|
1518
|
-
foundDecimal = c === '.';
|
|
1519
|
-
curArg = ['-', '.'].includes(c) ? c : '';
|
|
1520
1669
|
} else {
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
}
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1670
|
+
[newCursor, number] = readNumber(path, i);
|
|
1671
|
+
}
|
|
1672
|
+
if (number == null) {
|
|
1673
|
+
return pathData;
|
|
1674
|
+
}
|
|
1675
|
+
args.push(number);
|
|
1676
|
+
canHaveComma = true;
|
|
1677
|
+
hadComma = false;
|
|
1678
|
+
i = newCursor;
|
|
1679
|
+
if (args.length === argsCount) {
|
|
1680
|
+
pathData.push({
|
|
1681
|
+
command,
|
|
1531
1682
|
args
|
|
1532
|
-
};
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
cmd = 'L';
|
|
1683
|
+
});
|
|
1684
|
+
if (command === 'M') {
|
|
1685
|
+
command = 'L';
|
|
1536
1686
|
}
|
|
1537
|
-
if (
|
|
1538
|
-
|
|
1687
|
+
if (command === 'm') {
|
|
1688
|
+
command = 'l';
|
|
1539
1689
|
}
|
|
1540
|
-
|
|
1541
|
-
args[args.length] = +curArg;
|
|
1690
|
+
args = [];
|
|
1542
1691
|
}
|
|
1543
1692
|
}
|
|
1544
|
-
|
|
1545
|
-
cmd,
|
|
1546
|
-
args
|
|
1547
|
-
};
|
|
1548
|
-
return ret;
|
|
1693
|
+
return pathData;
|
|
1549
1694
|
};
|
|
1550
1695
|
const apply = function (commands, doc) {
|
|
1551
1696
|
cx = cy = px = py = sx = sy = 0;
|
|
1552
1697
|
for (let i = 0; i < commands.length; i++) {
|
|
1553
1698
|
const c = commands[i];
|
|
1554
|
-
if (typeof runners[c.
|
|
1555
|
-
runners[c.
|
|
1699
|
+
if (typeof runners[c.command] === 'function') {
|
|
1700
|
+
runners[c.command](doc, c.args);
|
|
1556
1701
|
}
|
|
1557
1702
|
}
|
|
1558
1703
|
};
|
|
@@ -2584,7 +2729,7 @@ begincmap
|
|
|
2584
2729
|
1 begincodespacerange
|
|
2585
2730
|
<0000><ffff>
|
|
2586
2731
|
endcodespacerange
|
|
2587
|
-
|
|
2732
|
+
${ranges.length} beginbfrange
|
|
2588
2733
|
${ranges.join('\n')}
|
|
2589
2734
|
endbfrange
|
|
2590
2735
|
endcmap
|
|
@@ -2763,6 +2908,7 @@ class LineWrapper extends events.EventEmitter {
|
|
|
2763
2908
|
this.document = document;
|
|
2764
2909
|
this.horizontalScaling = options.horizontalScaling || 100;
|
|
2765
2910
|
this.indent = (options.indent || 0) * this.horizontalScaling / 100;
|
|
2911
|
+
this.indentAllLines = options.indentAllLines || false;
|
|
2766
2912
|
this.characterSpacing = (options.characterSpacing || 0) * this.horizontalScaling / 100;
|
|
2767
2913
|
this.wordSpacing = (options.wordSpacing === 0) * this.horizontalScaling / 100;
|
|
2768
2914
|
this.columns = options.columns || 1;
|
|
@@ -3004,7 +3150,13 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3004
3150
|
this.column = 1;
|
|
3005
3151
|
this.startY = this.document.page.margins.top;
|
|
3006
3152
|
this.maxY = this.document.page.maxY();
|
|
3007
|
-
this.
|
|
3153
|
+
if (this.indentAllLines) {
|
|
3154
|
+
const indent = this.continuedX || this.indent;
|
|
3155
|
+
this.document.x += indent;
|
|
3156
|
+
this.lineWidth -= indent;
|
|
3157
|
+
} else {
|
|
3158
|
+
this.document.x = this.startX;
|
|
3159
|
+
}
|
|
3008
3160
|
if (this.document._fillColor) {
|
|
3009
3161
|
this.document.fillColor(...this.document._fillColor);
|
|
3010
3162
|
}
|
|
@@ -3408,7 +3560,11 @@ var TextMixin = {
|
|
|
3408
3560
|
}
|
|
3409
3561
|
const renderedWidth = options.textWidth + wordSpacing * (options.wordCount - 1) + characterSpacing * (text.length - 1);
|
|
3410
3562
|
if (options.link != null) {
|
|
3411
|
-
|
|
3563
|
+
const linkOptions = {};
|
|
3564
|
+
if (this._currentStructureElement && this._currentStructureElement.dictionary.data.S === 'Link') {
|
|
3565
|
+
linkOptions.structParent = this._currentStructureElement;
|
|
3566
|
+
}
|
|
3567
|
+
this.link(x, y, renderedWidth, this.currentLineHeight(), options.link, linkOptions);
|
|
3412
3568
|
}
|
|
3413
3569
|
if (options.goTo != null) {
|
|
3414
3570
|
this.goTo(x, y, renderedWidth, this.currentLineHeight(), options.goTo);
|
|
@@ -3537,6 +3693,47 @@ var TextMixin = {
|
|
|
3537
3693
|
}
|
|
3538
3694
|
};
|
|
3539
3695
|
|
|
3696
|
+
const parseExifOrientation = data => {
|
|
3697
|
+
if (!data || data.length < 20) return null;
|
|
3698
|
+
let pos = 2;
|
|
3699
|
+
while (pos < data.length - 4) {
|
|
3700
|
+
while (pos < data.length && data[pos] !== 0xff) pos++;
|
|
3701
|
+
if (pos >= data.length - 4) return null;
|
|
3702
|
+
const marker = data.readUInt16BE(pos);
|
|
3703
|
+
pos += 2;
|
|
3704
|
+
if (marker === 0xffda) return null;
|
|
3705
|
+
if (marker >= 0xffd0 && marker <= 0xffd9 || marker === 0xff01) continue;
|
|
3706
|
+
if (pos + 2 > data.length) return null;
|
|
3707
|
+
const segmentLength = data.readUInt16BE(pos);
|
|
3708
|
+
if (marker === 0xffe1 && pos + 8 <= data.length) {
|
|
3709
|
+
const exifHeader = data.subarray(pos + 2, pos + 8).toString('binary');
|
|
3710
|
+
if (exifHeader === 'Exif\x00\x00') {
|
|
3711
|
+
const tiffStart = pos + 8;
|
|
3712
|
+
if (tiffStart + 8 > data.length) return null;
|
|
3713
|
+
const byteOrder = data.subarray(tiffStart, tiffStart + 2).toString('ascii');
|
|
3714
|
+
const isLittleEndian = byteOrder === 'II';
|
|
3715
|
+
if (!isLittleEndian && byteOrder !== 'MM') return null;
|
|
3716
|
+
const read16 = isLittleEndian ? o => data.readUInt16LE(o) : o => data.readUInt16BE(o);
|
|
3717
|
+
const read32 = isLittleEndian ? o => data.readUInt32LE(o) : o => data.readUInt32BE(o);
|
|
3718
|
+
if (read16(tiffStart + 2) !== 42) return null;
|
|
3719
|
+
const ifdPos = tiffStart + read32(tiffStart + 4);
|
|
3720
|
+
if (ifdPos + 2 > data.length) return null;
|
|
3721
|
+
const entryCount = read16(ifdPos);
|
|
3722
|
+
for (let i = 0; i < entryCount; i++) {
|
|
3723
|
+
const entryPos = ifdPos + 2 + i * 12;
|
|
3724
|
+
if (entryPos + 12 > data.length) return null;
|
|
3725
|
+
if (read16(entryPos) === 0x0112) {
|
|
3726
|
+
const value = read16(entryPos + 8);
|
|
3727
|
+
return value >= 1 && value <= 8 ? value : null;
|
|
3728
|
+
}
|
|
3729
|
+
}
|
|
3730
|
+
return null;
|
|
3731
|
+
}
|
|
3732
|
+
}
|
|
3733
|
+
pos += segmentLength;
|
|
3734
|
+
}
|
|
3735
|
+
return null;
|
|
3736
|
+
};
|
|
3540
3737
|
const MARKERS = [0xffc0, 0xffc1, 0xffc2, 0xffc3, 0xffc5, 0xffc6, 0xffc7, 0xffc8, 0xffc9, 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf];
|
|
3541
3738
|
const COLOR_SPACE_MAP = {
|
|
3542
3739
|
1: 'DeviceGray',
|
|
@@ -3551,9 +3748,11 @@ class JPEG {
|
|
|
3551
3748
|
if (this.data.readUInt16BE(0) !== 0xffd8) {
|
|
3552
3749
|
throw 'SOI not found in JPEG';
|
|
3553
3750
|
}
|
|
3554
|
-
this.orientation =
|
|
3751
|
+
this.orientation = parseExifOrientation(this.data) || 1;
|
|
3555
3752
|
let pos = 2;
|
|
3556
3753
|
while (pos < this.data.length) {
|
|
3754
|
+
while (pos < this.data.length && this.data[pos] !== 0xff) pos++;
|
|
3755
|
+
if (pos >= this.data.length) break;
|
|
3557
3756
|
marker = this.data.readUInt16BE(pos);
|
|
3558
3757
|
pos += 2;
|
|
3559
3758
|
if (MARKERS.includes(marker)) {
|
|
@@ -3705,12 +3904,16 @@ class PNGImage {
|
|
|
3705
3904
|
}
|
|
3706
3905
|
loadIndexedAlphaChannel() {
|
|
3707
3906
|
const transparency = this.image.transparency.indexed;
|
|
3907
|
+
const isInterlaced = this.image.interlaceMethod === 1;
|
|
3708
3908
|
return this.image.decodePixels(pixels => {
|
|
3709
3909
|
const alphaChannel = Buffer.alloc(this.width * this.height);
|
|
3710
3910
|
let i = 0;
|
|
3711
3911
|
for (let j = 0, end = pixels.length; j < end; j++) {
|
|
3712
3912
|
alphaChannel[i++] = transparency[pixels[j]];
|
|
3713
3913
|
}
|
|
3914
|
+
if (isInterlaced) {
|
|
3915
|
+
this.imgData = zlib.deflateSync(Buffer.from(pixels));
|
|
3916
|
+
}
|
|
3714
3917
|
this.alphaChannel = zlib.deflateSync(alphaChannel);
|
|
3715
3918
|
return this.finalize();
|
|
3716
3919
|
});
|
|
@@ -3939,6 +4142,12 @@ var ImagesMixin = {
|
|
|
3939
4142
|
}
|
|
3940
4143
|
};
|
|
3941
4144
|
|
|
4145
|
+
class PDFAnnotationReference {
|
|
4146
|
+
constructor(annotationRef) {
|
|
4147
|
+
this.annotationRef = annotationRef;
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
|
|
3942
4151
|
var AnnotationsMixin = {
|
|
3943
4152
|
annotate(x, y, w, h, options) {
|
|
3944
4153
|
options.Type = 'Annot';
|
|
@@ -3956,12 +4165,18 @@ var AnnotationsMixin = {
|
|
|
3956
4165
|
if (typeof options.Dest === 'string') {
|
|
3957
4166
|
options.Dest = new String(options.Dest);
|
|
3958
4167
|
}
|
|
4168
|
+
const structParent = options.structParent;
|
|
4169
|
+
delete options.structParent;
|
|
3959
4170
|
for (let key in options) {
|
|
3960
4171
|
const val = options[key];
|
|
3961
4172
|
options[key[0].toUpperCase() + key.slice(1)] = val;
|
|
3962
4173
|
}
|
|
3963
4174
|
const ref = this.ref(options);
|
|
3964
4175
|
this.page.annotations.push(ref);
|
|
4176
|
+
if (structParent && typeof structParent.add === 'function') {
|
|
4177
|
+
const annotRef = new PDFAnnotationReference(ref);
|
|
4178
|
+
structParent.add(annotRef);
|
|
4179
|
+
}
|
|
3965
4180
|
ref.end();
|
|
3966
4181
|
return this;
|
|
3967
4182
|
},
|
|
@@ -4005,6 +4220,9 @@ var AnnotationsMixin = {
|
|
|
4005
4220
|
});
|
|
4006
4221
|
options.A.end();
|
|
4007
4222
|
}
|
|
4223
|
+
if (options.structParent && !options.Contents) {
|
|
4224
|
+
options.Contents = new String('');
|
|
4225
|
+
}
|
|
4008
4226
|
return this.annotate(x, y, w, h, options);
|
|
4009
4227
|
},
|
|
4010
4228
|
_markup(x, y, w, h, options = {}) {
|
|
@@ -4076,15 +4294,26 @@ var AnnotationsMixin = {
|
|
|
4076
4294
|
}
|
|
4077
4295
|
};
|
|
4078
4296
|
|
|
4297
|
+
const DEFAULT_OPTIONS = {
|
|
4298
|
+
top: 0,
|
|
4299
|
+
left: 0,
|
|
4300
|
+
zoom: 0,
|
|
4301
|
+
fit: true,
|
|
4302
|
+
pageNumber: null,
|
|
4303
|
+
expanded: false
|
|
4304
|
+
};
|
|
4079
4305
|
class PDFOutline {
|
|
4080
|
-
constructor(document, parent, title, dest, options = {
|
|
4081
|
-
expanded: false
|
|
4082
|
-
}) {
|
|
4306
|
+
constructor(document, parent, title, dest, options = DEFAULT_OPTIONS) {
|
|
4083
4307
|
this.document = document;
|
|
4084
4308
|
this.options = options;
|
|
4085
4309
|
this.outlineData = {};
|
|
4086
4310
|
if (dest !== null) {
|
|
4087
|
-
|
|
4311
|
+
const destWidth = dest.data.MediaBox[2];
|
|
4312
|
+
const destHeight = dest.data.MediaBox[3];
|
|
4313
|
+
const top = destHeight - (options.top || 0);
|
|
4314
|
+
const left = destWidth - (options.left || 0);
|
|
4315
|
+
const zoom = options.zoom || 0;
|
|
4316
|
+
this.outlineData['Dest'] = options.fit ? [dest, 'Fit'] : [dest, 'XYZ', left, top, zoom];
|
|
4088
4317
|
}
|
|
4089
4318
|
if (parent !== null) {
|
|
4090
4319
|
this.outlineData['Parent'] = parent;
|
|
@@ -4095,10 +4324,10 @@ class PDFOutline {
|
|
|
4095
4324
|
this.dictionary = this.document.ref(this.outlineData);
|
|
4096
4325
|
this.children = [];
|
|
4097
4326
|
}
|
|
4098
|
-
addItem(title, options = {
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
const result = new PDFOutline(this.document, this.dictionary, title,
|
|
4327
|
+
addItem(title, options = DEFAULT_OPTIONS) {
|
|
4328
|
+
const pages = this.document._root.data.Pages.data.Kids;
|
|
4329
|
+
const dest = options.pageNumber != null ? pages[options.pageNumber] : this.document.page.dictionary;
|
|
4330
|
+
const result = new PDFOutline(this.document, this.dictionary, title, dest, options);
|
|
4102
4331
|
this.children.push(result);
|
|
4103
4332
|
return result;
|
|
4104
4333
|
}
|
|
@@ -4134,7 +4363,7 @@ var OutlineMixin = {
|
|
|
4134
4363
|
this.outline.endOutline();
|
|
4135
4364
|
if (this.outline.children.length > 0) {
|
|
4136
4365
|
this._root.data.Outlines = this.outline.dictionary;
|
|
4137
|
-
return this._root.data.PageMode = 'UseOutlines';
|
|
4366
|
+
return this._root.data.PageMode = this._root.data.PageMode || 'UseOutlines';
|
|
4138
4367
|
}
|
|
4139
4368
|
}
|
|
4140
4369
|
};
|
|
@@ -4205,6 +4434,9 @@ class PDFStructureElement {
|
|
|
4205
4434
|
if (child instanceof PDFStructureContent) {
|
|
4206
4435
|
this._addContentToParentTree(child);
|
|
4207
4436
|
}
|
|
4437
|
+
if (child instanceof PDFAnnotationReference) {
|
|
4438
|
+
this._addAnnotationToParentTree(child.annotationRef);
|
|
4439
|
+
}
|
|
4208
4440
|
if (typeof child === 'function' && this._attached) {
|
|
4209
4441
|
child = this._contentForClosure(child);
|
|
4210
4442
|
}
|
|
@@ -4220,6 +4452,12 @@ class PDFStructureElement {
|
|
|
4220
4452
|
pageStructParents[mcid] = this.dictionary;
|
|
4221
4453
|
});
|
|
4222
4454
|
}
|
|
4455
|
+
_addAnnotationToParentTree(annotRef) {
|
|
4456
|
+
const parentTreeKey = this.document.createStructParentTreeNextKey();
|
|
4457
|
+
annotRef.data.StructParent = parentTreeKey;
|
|
4458
|
+
const parentTree = this.document.getStructParentTree();
|
|
4459
|
+
parentTree.add(parentTreeKey, this.dictionary);
|
|
4460
|
+
}
|
|
4223
4461
|
setParent(parentRef) {
|
|
4224
4462
|
if (this.dictionary.data.P) {
|
|
4225
4463
|
throw new Error(`Structure element added to more than one parent`);
|
|
@@ -4251,11 +4489,17 @@ class PDFStructureElement {
|
|
|
4251
4489
|
this._flush();
|
|
4252
4490
|
}
|
|
4253
4491
|
_isValidChild(child) {
|
|
4254
|
-
return child instanceof PDFStructureElement || child instanceof PDFStructureContent || typeof child === 'function';
|
|
4492
|
+
return child instanceof PDFStructureElement || child instanceof PDFStructureContent || child instanceof PDFAnnotationReference || typeof child === 'function';
|
|
4255
4493
|
}
|
|
4256
4494
|
_contentForClosure(closure) {
|
|
4257
4495
|
const content = this.document.markStructureContent(this.dictionary.data.S);
|
|
4496
|
+
const prevStructElement = this.document._currentStructureElement;
|
|
4497
|
+
this.document._currentStructureElement = this;
|
|
4498
|
+
const wasEnded = this._ended;
|
|
4499
|
+
this._ended = false;
|
|
4258
4500
|
closure();
|
|
4501
|
+
this._ended = wasEnded;
|
|
4502
|
+
this.document._currentStructureElement = prevStructElement;
|
|
4259
4503
|
this.document.endMarkedContent();
|
|
4260
4504
|
this._addContentToParentTree(content);
|
|
4261
4505
|
return content;
|
|
@@ -4308,6 +4552,15 @@ class PDFStructureElement {
|
|
|
4308
4552
|
}
|
|
4309
4553
|
});
|
|
4310
4554
|
}
|
|
4555
|
+
if (child instanceof PDFAnnotationReference) {
|
|
4556
|
+
const pageRef = this.document.page.dictionary;
|
|
4557
|
+
const objr = {
|
|
4558
|
+
Type: 'OBJR',
|
|
4559
|
+
Obj: child.annotationRef,
|
|
4560
|
+
Pg: pageRef
|
|
4561
|
+
};
|
|
4562
|
+
this.dictionary.data.K.push(objr);
|
|
4563
|
+
}
|
|
4311
4564
|
}
|
|
4312
4565
|
}
|
|
4313
4566
|
|
|
@@ -4401,6 +4654,13 @@ var MarkingsMixin = {
|
|
|
4401
4654
|
endMarkedContent() {
|
|
4402
4655
|
this.page.markings.pop();
|
|
4403
4656
|
this.addContent('EMC');
|
|
4657
|
+
if (this._textOptions) {
|
|
4658
|
+
delete this._textOptions.link;
|
|
4659
|
+
delete this._textOptions.goTo;
|
|
4660
|
+
delete this._textOptions.destination;
|
|
4661
|
+
delete this._textOptions.underline;
|
|
4662
|
+
delete this._textOptions.strike;
|
|
4663
|
+
}
|
|
4404
4664
|
return this;
|
|
4405
4665
|
},
|
|
4406
4666
|
struct(type, options = {}, children = null) {
|
|
@@ -4847,7 +5107,7 @@ var AttachmentsMixin = {
|
|
|
4847
5107
|
if (options.type) {
|
|
4848
5108
|
refBody.Subtype = options.type.replace('/', '#2F');
|
|
4849
5109
|
}
|
|
4850
|
-
const checksum =
|
|
5110
|
+
const checksum = md5Hex(new Uint8Array(data));
|
|
4851
5111
|
refBody.Params.CheckSum = new String(checksum);
|
|
4852
5112
|
refBody.Params.Size = data.byteLength;
|
|
4853
5113
|
let ref;
|
|
@@ -5490,7 +5750,7 @@ function renderRow(row, rowIndex) {
|
|
|
5490
5750
|
function renderCell(cell, rowStruct) {
|
|
5491
5751
|
const cellRenderer = () => {
|
|
5492
5752
|
if (cell.backgroundColor != null) {
|
|
5493
|
-
this.document.save().rect(cell.x, cell.y, cell.width, cell.height).fill(
|
|
5753
|
+
this.document.save().fillColor(cell.backgroundColor).rect(cell.x, cell.y, cell.width, cell.height).fill().restore();
|
|
5494
5754
|
}
|
|
5495
5755
|
renderBorder.call(this, cell.border, cell.borderColor, cell.x, cell.y, cell.width, cell.height);
|
|
5496
5756
|
if (cell.debug) {
|
|
@@ -5551,20 +5811,20 @@ function renderBorder(border, borderColor, x, y, width, height, mask) {
|
|
|
5551
5811
|
const doc = this.document;
|
|
5552
5812
|
if ([border.right, border.bottom, border.left].every(val => val === border.top)) {
|
|
5553
5813
|
if (border.top > 0) {
|
|
5554
|
-
doc.save().lineWidth(border.top).rect(x, y, width, height).stroke(
|
|
5814
|
+
doc.save().lineWidth(border.top).strokeColor(borderColor.top).rect(x, y, width, height).stroke().restore();
|
|
5555
5815
|
}
|
|
5556
5816
|
} else {
|
|
5557
5817
|
if (border.top > 0) {
|
|
5558
|
-
doc.save().lineWidth(border.top).moveTo(x, y).lineTo(x + width, y).stroke(
|
|
5818
|
+
doc.save().lineWidth(border.top).moveTo(x, y).strokeColor(borderColor.top).lineTo(x + width, y).stroke().restore();
|
|
5559
5819
|
}
|
|
5560
5820
|
if (border.right > 0) {
|
|
5561
|
-
doc.save().lineWidth(border.right).moveTo(x + width, y).lineTo(x + width, y + height).stroke(
|
|
5821
|
+
doc.save().lineWidth(border.right).moveTo(x + width, y).strokeColor(borderColor.right).lineTo(x + width, y + height).stroke().restore();
|
|
5562
5822
|
}
|
|
5563
5823
|
if (border.bottom > 0) {
|
|
5564
|
-
doc.save().lineWidth(border.bottom).moveTo(x + width, y + height).lineTo(x, y + height).stroke(
|
|
5824
|
+
doc.save().lineWidth(border.bottom).moveTo(x + width, y + height).strokeColor(borderColor.bottom).lineTo(x, y + height).stroke().restore();
|
|
5565
5825
|
}
|
|
5566
5826
|
if (border.left > 0) {
|
|
5567
|
-
doc.save().lineWidth(border.left).moveTo(x, y + height).lineTo(x, y).stroke(
|
|
5827
|
+
doc.save().lineWidth(border.left).moveTo(x, y + height).strokeColor(borderColor.left).lineTo(x, y).stroke().restore();
|
|
5568
5828
|
}
|
|
5569
5829
|
}
|
|
5570
5830
|
}
|
|
@@ -5771,6 +6031,10 @@ class PDFDocument extends stream.Readable {
|
|
|
5771
6031
|
if (this.options.lang) {
|
|
5772
6032
|
this._root.data.Lang = new String(this.options.lang);
|
|
5773
6033
|
}
|
|
6034
|
+
if (this.options.pageLayout) {
|
|
6035
|
+
const layout = this.options.pageLayout;
|
|
6036
|
+
this._root.data.PageLayout = layout.charAt(0).toUpperCase() + layout.slice(1);
|
|
6037
|
+
}
|
|
5774
6038
|
this.page = null;
|
|
5775
6039
|
this.initMetadata();
|
|
5776
6040
|
this.initColor();
|