pdfkit 0.18.0 → 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/CHANGELOG.md +15 -2
- package/js/pdfkit.es.js +270 -263
- package/js/pdfkit.es.js.map +1 -1
- package/js/pdfkit.js +194 -99
- package/js/pdfkit.js.map +1 -1
- package/js/pdfkit.standalone.js +351 -294
- package/js/virtual-fs.js +1 -3
- package/package.json +24 -34
- package/rollup.config.mjs +124 -0
- package/types/jest.custom-matchers.d.ts +8 -8
- package/vitest.config.js +11 -0
package/js/pdfkit.js
CHANGED
|
@@ -4,11 +4,10 @@ var stream = require('stream');
|
|
|
4
4
|
var zlib = require('zlib');
|
|
5
5
|
var utils = require('@noble/hashes/utils');
|
|
6
6
|
var md5 = require('js-md5');
|
|
7
|
-
var
|
|
7
|
+
var sha2 = require('@noble/hashes/sha2');
|
|
8
8
|
var aes = require('@noble/ciphers/aes');
|
|
9
9
|
var fs = require('fs');
|
|
10
10
|
var fontkit = require('fontkit');
|
|
11
|
-
var events = require('events');
|
|
12
11
|
var LineBreaker = require('linebreak');
|
|
13
12
|
var PNG = require('png-js');
|
|
14
13
|
|
|
@@ -61,7 +60,7 @@ class SpotColor {
|
|
|
61
60
|
this.id = 'CS' + Object.keys(doc.spotColors).length;
|
|
62
61
|
this.name = name;
|
|
63
62
|
this.values = [C, M, Y, K];
|
|
64
|
-
this.ref = doc.ref(['Separation', this.name, 'DeviceCMYK', {
|
|
63
|
+
this.ref = doc.ref(['Separation', escapeName(this.name), 'DeviceCMYK', {
|
|
65
64
|
Range: [0, 1, 0, 1, 0, 1, 0, 1],
|
|
66
65
|
C0: [0, 0, 0, 0],
|
|
67
66
|
C1: this.values.map(value => value / 100),
|
|
@@ -77,6 +76,10 @@ class SpotColor {
|
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
const pad = (str, length) => (Array(length + 1).join('0') + str).slice(-length);
|
|
79
|
+
const isSafeCharCode = code => {
|
|
80
|
+
if (code > 0x7f) return true;
|
|
81
|
+
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;
|
|
82
|
+
};
|
|
80
83
|
const escapableRe = /[\n\r\t\b\f()\\]/g;
|
|
81
84
|
const escapable = {
|
|
82
85
|
'\n': '\\n',
|
|
@@ -88,6 +91,18 @@ const escapable = {
|
|
|
88
91
|
'(': '\\(',
|
|
89
92
|
')': '\\)'
|
|
90
93
|
};
|
|
94
|
+
const escapeName = function (name) {
|
|
95
|
+
let escapedName = '';
|
|
96
|
+
for (const char of name) {
|
|
97
|
+
const code = char.charCodeAt(0);
|
|
98
|
+
if (isSafeCharCode(code)) {
|
|
99
|
+
escapedName += char;
|
|
100
|
+
} else {
|
|
101
|
+
escapedName += `#${code.toString(16).toUpperCase().padStart(2, '0')}`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return escapedName;
|
|
105
|
+
};
|
|
91
106
|
const swapBytes = function (buff) {
|
|
92
107
|
const l = buff.length;
|
|
93
108
|
if (l & 0x01) {
|
|
@@ -459,7 +474,7 @@ function md5Hex(data) {
|
|
|
459
474
|
}
|
|
460
475
|
|
|
461
476
|
function sha256Hash(data) {
|
|
462
|
-
return
|
|
477
|
+
return sha2.sha256(data);
|
|
463
478
|
}
|
|
464
479
|
|
|
465
480
|
function aesCbcEncrypt(data, key, iv, padding = true) {
|
|
@@ -495,11 +510,7 @@ function rc4(data, key) {
|
|
|
495
510
|
|
|
496
511
|
function randomBytes(length) {
|
|
497
512
|
const bytes = new Uint8Array(length);
|
|
498
|
-
|
|
499
|
-
globalThis.crypto.getRandomValues(bytes);
|
|
500
|
-
} else {
|
|
501
|
-
require('crypto').randomFillSync(bytes);
|
|
502
|
-
}
|
|
513
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
503
514
|
return bytes;
|
|
504
515
|
}
|
|
505
516
|
|
|
@@ -927,7 +938,7 @@ const PASSWORD_PADDING = [0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64,
|
|
|
927
938
|
const {
|
|
928
939
|
number: number$2
|
|
929
940
|
} = PDFObject;
|
|
930
|
-
|
|
941
|
+
let PDFGradient$1 = class PDFGradient {
|
|
931
942
|
constructor(doc) {
|
|
932
943
|
this.doc = doc;
|
|
933
944
|
this.stops = [];
|
|
@@ -1085,8 +1096,8 @@ class PDFGradient$1 {
|
|
|
1085
1096
|
const op = stroke ? 'SCN' : 'scn';
|
|
1086
1097
|
return this.doc.addContent(`/${this.id} ${op}`);
|
|
1087
1098
|
}
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1099
|
+
};
|
|
1100
|
+
let PDFLinearGradient$1 = class PDFLinearGradient extends PDFGradient$1 {
|
|
1090
1101
|
constructor(doc, x1, y1, x2, y2) {
|
|
1091
1102
|
super(doc);
|
|
1092
1103
|
this.x1 = x1;
|
|
@@ -1104,10 +1115,10 @@ class PDFLinearGradient$1 extends PDFGradient$1 {
|
|
|
1104
1115
|
});
|
|
1105
1116
|
}
|
|
1106
1117
|
opacityGradient() {
|
|
1107
|
-
return new PDFLinearGradient
|
|
1118
|
+
return new PDFLinearGradient(this.doc, this.x1, this.y1, this.x2, this.y2);
|
|
1108
1119
|
}
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1120
|
+
};
|
|
1121
|
+
let PDFRadialGradient$1 = class PDFRadialGradient extends PDFGradient$1 {
|
|
1111
1122
|
constructor(doc, x1, y1, r1, x2, y2, r2) {
|
|
1112
1123
|
super(doc);
|
|
1113
1124
|
this.doc = doc;
|
|
@@ -1128,9 +1139,9 @@ class PDFRadialGradient$1 extends PDFGradient$1 {
|
|
|
1128
1139
|
});
|
|
1129
1140
|
}
|
|
1130
1141
|
opacityGradient() {
|
|
1131
|
-
return new PDFRadialGradient
|
|
1142
|
+
return new PDFRadialGradient(this.doc, this.x1, this.y1, this.r1, this.x2, this.y2, this.r2);
|
|
1132
1143
|
}
|
|
1133
|
-
}
|
|
1144
|
+
};
|
|
1134
1145
|
var Gradient = {
|
|
1135
1146
|
PDFGradient: PDFGradient$1,
|
|
1136
1147
|
PDFLinearGradient: PDFLinearGradient$1,
|
|
@@ -1138,7 +1149,7 @@ var Gradient = {
|
|
|
1138
1149
|
};
|
|
1139
1150
|
|
|
1140
1151
|
const underlyingColorSpaces = ['DeviceCMYK', 'DeviceRGB'];
|
|
1141
|
-
|
|
1152
|
+
let PDFTilingPattern$1 = class PDFTilingPattern {
|
|
1142
1153
|
constructor(doc, bBox, xStep, yStep, stream) {
|
|
1143
1154
|
this.doc = doc;
|
|
1144
1155
|
this.bBox = bBox;
|
|
@@ -1198,7 +1209,7 @@ class PDFTilingPattern$1 {
|
|
|
1198
1209
|
const op = stroke ? 'SCN' : 'scn';
|
|
1199
1210
|
return this.doc.addContent(`${normalizedColor.join(' ')} /${this.id} ${op}`);
|
|
1200
1211
|
}
|
|
1201
|
-
}
|
|
1212
|
+
};
|
|
1202
1213
|
var pattern = {
|
|
1203
1214
|
PDFTilingPattern: PDFTilingPattern$1
|
|
1204
1215
|
};
|
|
@@ -2007,21 +2018,42 @@ var VectorMixin = {
|
|
|
2007
2018
|
rect(x, y, w, h) {
|
|
2008
2019
|
return this.addContent(`${number$1(x)} ${number$1(y)} ${number$1(w)} ${number$1(h)} re`);
|
|
2009
2020
|
},
|
|
2010
|
-
roundedRect(x, y, w, h,
|
|
2011
|
-
if (
|
|
2012
|
-
|
|
2013
|
-
}
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2021
|
+
roundedRect(x, y, w, h, borderRadius) {
|
|
2022
|
+
if (borderRadius == null) {
|
|
2023
|
+
borderRadius = 0;
|
|
2024
|
+
}
|
|
2025
|
+
let radii;
|
|
2026
|
+
if (Array.isArray(borderRadius)) {
|
|
2027
|
+
radii = borderRadius.slice(0, 4);
|
|
2028
|
+
} else {
|
|
2029
|
+
radii = [borderRadius, borderRadius, borderRadius, borderRadius];
|
|
2030
|
+
}
|
|
2031
|
+
const limit = Math.min(0.5 * w, 0.5 * h);
|
|
2032
|
+
const rTL = Math.max(0, Math.min(radii[0] || 0, limit));
|
|
2033
|
+
const rTR = Math.max(0, Math.min(radii[1] || 0, limit));
|
|
2034
|
+
const rBR = Math.max(0, Math.min(radii[2] || 0, limit));
|
|
2035
|
+
const rBL = Math.max(0, Math.min(radii[3] || 0, limit));
|
|
2036
|
+
const cpTR = rTR * (1.0 - KAPPA);
|
|
2037
|
+
const cpBR = rBR * (1.0 - KAPPA);
|
|
2038
|
+
const cpBL = rBL * (1.0 - KAPPA);
|
|
2039
|
+
const cpTL = rTL * (1.0 - KAPPA);
|
|
2040
|
+
this.moveTo(x + rTL, y);
|
|
2041
|
+
this.lineTo(x + w - rTR, y);
|
|
2042
|
+
if (rTR > 0) {
|
|
2043
|
+
this.bezierCurveTo(x + w - cpTR, y, x + w, y + cpTR, x + w, y + rTR);
|
|
2044
|
+
}
|
|
2045
|
+
this.lineTo(x + w, y + h - rBR);
|
|
2046
|
+
if (rBR > 0) {
|
|
2047
|
+
this.bezierCurveTo(x + w, y + h - cpBR, x + w - cpBR, y + h, x + w - rBR, y + h);
|
|
2048
|
+
}
|
|
2049
|
+
this.lineTo(x + rBL, y + h);
|
|
2050
|
+
if (rBL > 0) {
|
|
2051
|
+
this.bezierCurveTo(x + cpBL, y + h, x, y + h - cpBL, x, y + h - rBL);
|
|
2052
|
+
}
|
|
2053
|
+
this.lineTo(x, y + rTL);
|
|
2054
|
+
if (rTL > 0) {
|
|
2055
|
+
this.bezierCurveTo(x, y + cpTL, x + cpTL, y, x + rTL, y);
|
|
2056
|
+
}
|
|
2025
2057
|
return this.closePath();
|
|
2026
2058
|
},
|
|
2027
2059
|
ellipse(x, y, r1, r2) {
|
|
@@ -2313,7 +2345,7 @@ class AFMFont {
|
|
|
2313
2345
|
if (match = line.match(/^Start(\w+)/)) {
|
|
2314
2346
|
section = match[1];
|
|
2315
2347
|
continue;
|
|
2316
|
-
} else if (
|
|
2348
|
+
} else if (line.match(/^End(\w+)/)) {
|
|
2317
2349
|
section = '';
|
|
2318
2350
|
continue;
|
|
2319
2351
|
}
|
|
@@ -2657,9 +2689,15 @@ class EmbeddedFont extends PDFFont {
|
|
|
2657
2689
|
descriptor.data.FontFile2 = fontFile;
|
|
2658
2690
|
}
|
|
2659
2691
|
if (this.document.subset && this.document.subset === 1) {
|
|
2660
|
-
const
|
|
2692
|
+
const maxCID = this.widths.length - 1;
|
|
2693
|
+
const cidSetBuffer = Buffer.alloc(Math.ceil((maxCID + 1) / 8), 0);
|
|
2694
|
+
for (let cid = 0; cid <= maxCID; cid++) {
|
|
2695
|
+
if (this.widths[cid] != null) {
|
|
2696
|
+
cidSetBuffer[Math.floor(cid / 8)] |= 0x80 >> cid % 8;
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2661
2699
|
const CIDSetRef = this.document.ref();
|
|
2662
|
-
CIDSetRef.write(
|
|
2700
|
+
CIDSetRef.write(cidSetBuffer);
|
|
2663
2701
|
CIDSetRef.end();
|
|
2664
2702
|
descriptor.data.CIDSet = CIDSetRef;
|
|
2665
2703
|
}
|
|
@@ -2821,9 +2859,12 @@ var FontsMixin = {
|
|
|
2821
2859
|
if (cacheKey) {
|
|
2822
2860
|
this._fontFamilies[cacheKey] = this._font;
|
|
2823
2861
|
}
|
|
2824
|
-
if (this._font.name) {
|
|
2862
|
+
if (this._font.name && !this._fontFamilies[this._font.name]) {
|
|
2825
2863
|
this._fontFamilies[this._font.name] = this._font;
|
|
2826
2864
|
}
|
|
2865
|
+
if (!cacheKey && (!this._font.name || this._fontFamilies[this._font.name] !== this._font)) {
|
|
2866
|
+
this._fontFamilies[this._font.id] = this._font;
|
|
2867
|
+
}
|
|
2827
2868
|
return this;
|
|
2828
2869
|
},
|
|
2829
2870
|
fontSize(_fontSize) {
|
|
@@ -2902,9 +2943,9 @@ var FontsMixin = {
|
|
|
2902
2943
|
|
|
2903
2944
|
const SOFT_HYPHEN = '\u00AD';
|
|
2904
2945
|
const HYPHEN = '-';
|
|
2905
|
-
class LineWrapper
|
|
2946
|
+
class LineWrapper {
|
|
2906
2947
|
constructor(document, options) {
|
|
2907
|
-
|
|
2948
|
+
this._listeners = Object.create(null);
|
|
2908
2949
|
this.document = document;
|
|
2909
2950
|
this.horizontalScaling = options.horizontalScaling || 100;
|
|
2910
2951
|
this.indent = (options.indent || 0) * this.horizontalScaling / 100;
|
|
@@ -2960,6 +3001,22 @@ class LineWrapper extends events.EventEmitter {
|
|
|
2960
3001
|
});
|
|
2961
3002
|
});
|
|
2962
3003
|
}
|
|
3004
|
+
on(event, listener) {
|
|
3005
|
+
(this._listeners[event] || (this._listeners[event] = [])).push(listener);
|
|
3006
|
+
}
|
|
3007
|
+
once(event, listener) {
|
|
3008
|
+
const wrapper = (...args) => {
|
|
3009
|
+
const listeners = this._listeners[event];
|
|
3010
|
+
listeners.splice(listeners.indexOf(wrapper), 1);
|
|
3011
|
+
listener(...args);
|
|
3012
|
+
};
|
|
3013
|
+
this.on(event, wrapper);
|
|
3014
|
+
}
|
|
3015
|
+
emit(event, ...args) {
|
|
3016
|
+
const listeners = this._listeners[event];
|
|
3017
|
+
if (!listeners) return;
|
|
3018
|
+
for (const listener of listeners.slice()) listener(...args);
|
|
3019
|
+
}
|
|
2963
3020
|
wordWidth(word) {
|
|
2964
3021
|
return PDFNumber(this.document.widthOfString(word, this) + this.characterSpacing + this.wordSpacing);
|
|
2965
3022
|
}
|
|
@@ -3025,6 +3082,9 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3025
3082
|
}
|
|
3026
3083
|
}
|
|
3027
3084
|
wrap(text, options) {
|
|
3085
|
+
const {
|
|
3086
|
+
document
|
|
3087
|
+
} = this;
|
|
3028
3088
|
this.horizontalScaling = options.horizontalScaling || 100;
|
|
3029
3089
|
if (options.indent != null) {
|
|
3030
3090
|
this.indent = options.indent * this.horizontalScaling / 100;
|
|
@@ -3038,24 +3098,20 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3038
3098
|
if (options.ellipsis != null) {
|
|
3039
3099
|
this.ellipsis = options.ellipsis;
|
|
3040
3100
|
}
|
|
3041
|
-
const nextY =
|
|
3042
|
-
if (
|
|
3101
|
+
const nextY = document.y + document.currentLineHeight(true);
|
|
3102
|
+
if (document.y > this.maxY || nextY > this.maxY) {
|
|
3043
3103
|
this.nextSection();
|
|
3044
3104
|
}
|
|
3045
3105
|
let buffer = '';
|
|
3046
3106
|
let textWidth = 0;
|
|
3047
3107
|
let wc = 0;
|
|
3048
3108
|
let lc = 0;
|
|
3049
|
-
let
|
|
3050
|
-
y
|
|
3051
|
-
} = this.document;
|
|
3109
|
+
let continueY = document.y;
|
|
3052
3110
|
const emitLine = () => {
|
|
3053
3111
|
options.textWidth = textWidth + this.wordSpacing * (wc - 1);
|
|
3054
3112
|
options.wordCount = wc;
|
|
3055
3113
|
options.lineWidth = this.lineWidth;
|
|
3056
|
-
|
|
3057
|
-
y
|
|
3058
|
-
} = this.document);
|
|
3114
|
+
continueY = document.y;
|
|
3059
3115
|
this.emit('line', buffer, options, this);
|
|
3060
3116
|
return lc++;
|
|
3061
3117
|
};
|
|
@@ -3071,8 +3127,8 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3071
3127
|
wc++;
|
|
3072
3128
|
}
|
|
3073
3129
|
if (bk.required || !this.canFit(word, w)) {
|
|
3074
|
-
const lh =
|
|
3075
|
-
if (this.height != null && this.ellipsis && PDFNumber(
|
|
3130
|
+
const lh = document.currentLineHeight(true);
|
|
3131
|
+
if (this.height != null && this.ellipsis && PDFNumber(document.y + lh * 2) > this.maxY && this.column >= this.columns) {
|
|
3076
3132
|
if (this.ellipsis === true) {
|
|
3077
3133
|
this.ellipsis = '…';
|
|
3078
3134
|
}
|
|
@@ -3101,7 +3157,7 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3101
3157
|
this.spaceLeft -= this.wordWidth(HYPHEN);
|
|
3102
3158
|
}
|
|
3103
3159
|
emitLine();
|
|
3104
|
-
if (PDFNumber(
|
|
3160
|
+
if (PDFNumber(document.y + lh) > this.maxY) {
|
|
3105
3161
|
this.emit('sectionEnd', options, this);
|
|
3106
3162
|
const shouldContinue = this.nextSection();
|
|
3107
3163
|
if (!shouldContinue) {
|
|
@@ -3136,9 +3192,9 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3136
3192
|
this.continuedX = 0;
|
|
3137
3193
|
}
|
|
3138
3194
|
this.continuedX += options.textWidth || 0;
|
|
3139
|
-
|
|
3195
|
+
document.y = continueY;
|
|
3140
3196
|
} else {
|
|
3141
|
-
|
|
3197
|
+
document.x = this.startX;
|
|
3142
3198
|
}
|
|
3143
3199
|
}
|
|
3144
3200
|
nextSection(options) {
|
|
@@ -3453,7 +3509,7 @@ var TextMixin = {
|
|
|
3453
3509
|
return this;
|
|
3454
3510
|
},
|
|
3455
3511
|
_initOptions(x = {}, y, options = {}) {
|
|
3456
|
-
if (typeof x === 'object') {
|
|
3512
|
+
if (x && typeof x === 'object') {
|
|
3457
3513
|
options = x;
|
|
3458
3514
|
x = null;
|
|
3459
3515
|
}
|
|
@@ -3486,7 +3542,7 @@ var TextMixin = {
|
|
|
3486
3542
|
if (result.columnGap == null) {
|
|
3487
3543
|
result.columnGap = 18;
|
|
3488
3544
|
}
|
|
3489
|
-
result.rotation = Number(
|
|
3545
|
+
result.rotation = Number(result.rotation ?? 0) % 360;
|
|
3490
3546
|
if (result.rotation < 0) result.rotation += 360;
|
|
3491
3547
|
return result;
|
|
3492
3548
|
},
|
|
@@ -3693,28 +3749,42 @@ var TextMixin = {
|
|
|
3693
3749
|
}
|
|
3694
3750
|
};
|
|
3695
3751
|
|
|
3752
|
+
const toBinaryString = bytes => {
|
|
3753
|
+
const chunkSize = 0x8000;
|
|
3754
|
+
let out = '';
|
|
3755
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
3756
|
+
const end = Math.min(i + chunkSize, bytes.length);
|
|
3757
|
+
out += String.fromCharCode.apply(null, bytes.subarray(i, end));
|
|
3758
|
+
}
|
|
3759
|
+
return out;
|
|
3760
|
+
};
|
|
3761
|
+
const readUInt16BE = (bytes, offset = 0) => (bytes[offset] << 8 | bytes[offset + 1]) >>> 0;
|
|
3762
|
+
const readUInt16LE = (bytes, offset = 0) => (bytes[offset + 1] << 8 | bytes[offset]) >>> 0;
|
|
3763
|
+
const readUInt32BE = (bytes, offset = 0) => bytes[offset] * 0x1000000 + (bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
|
|
3764
|
+
const readUInt32LE = (bytes, offset = 0) => (bytes[offset] | bytes[offset + 1] << 8 | bytes[offset + 2] << 16) + bytes[offset + 3] * 0x1000000 >>> 0;
|
|
3765
|
+
|
|
3696
3766
|
const parseExifOrientation = data => {
|
|
3697
3767
|
if (!data || data.length < 20) return null;
|
|
3698
3768
|
let pos = 2;
|
|
3699
3769
|
while (pos < data.length - 4) {
|
|
3700
3770
|
while (pos < data.length && data[pos] !== 0xff) pos++;
|
|
3701
3771
|
if (pos >= data.length - 4) return null;
|
|
3702
|
-
const marker =
|
|
3772
|
+
const marker = readUInt16BE(data, pos);
|
|
3703
3773
|
pos += 2;
|
|
3704
3774
|
if (marker === 0xffda) return null;
|
|
3705
3775
|
if (marker >= 0xffd0 && marker <= 0xffd9 || marker === 0xff01) continue;
|
|
3706
3776
|
if (pos + 2 > data.length) return null;
|
|
3707
|
-
const segmentLength =
|
|
3777
|
+
const segmentLength = readUInt16BE(data, pos);
|
|
3708
3778
|
if (marker === 0xffe1 && pos + 8 <= data.length) {
|
|
3709
|
-
const exifHeader = data.subarray(pos + 2, pos + 8)
|
|
3779
|
+
const exifHeader = toBinaryString(data.subarray(pos + 2, pos + 8));
|
|
3710
3780
|
if (exifHeader === 'Exif\x00\x00') {
|
|
3711
3781
|
const tiffStart = pos + 8;
|
|
3712
3782
|
if (tiffStart + 8 > data.length) return null;
|
|
3713
|
-
const byteOrder = data.subarray(tiffStart, tiffStart + 2)
|
|
3783
|
+
const byteOrder = toBinaryString(data.subarray(tiffStart, tiffStart + 2));
|
|
3714
3784
|
const isLittleEndian = byteOrder === 'II';
|
|
3715
3785
|
if (!isLittleEndian && byteOrder !== 'MM') return null;
|
|
3716
|
-
const read16 = isLittleEndian ? o =>
|
|
3717
|
-
const read32 = isLittleEndian ? o =>
|
|
3786
|
+
const read16 = isLittleEndian ? o => readUInt16LE(data, o) : o => readUInt16BE(data, o);
|
|
3787
|
+
const read32 = isLittleEndian ? o => readUInt32LE(data, o) : o => readUInt32BE(data, o);
|
|
3718
3788
|
if (read16(tiffStart + 2) !== 42) return null;
|
|
3719
3789
|
const ifdPos = tiffStart + read32(tiffStart + 4);
|
|
3720
3790
|
if (ifdPos + 2 > data.length) return null;
|
|
@@ -3769,7 +3839,7 @@ class JPEG {
|
|
|
3769
3839
|
pos += 2;
|
|
3770
3840
|
this.width = this.data.readUInt16BE(pos);
|
|
3771
3841
|
pos += 2;
|
|
3772
|
-
const channels = this.data[pos
|
|
3842
|
+
const channels = this.data[pos + 1];
|
|
3773
3843
|
this.colorSpace = COLOR_SPACE_MAP[channels];
|
|
3774
3844
|
this.obj = null;
|
|
3775
3845
|
}
|
|
@@ -3804,58 +3874,60 @@ class PNGImage {
|
|
|
3804
3874
|
this.obj = null;
|
|
3805
3875
|
}
|
|
3806
3876
|
embed(document) {
|
|
3807
|
-
let dataDecoded = false;
|
|
3808
3877
|
this.document = document;
|
|
3809
3878
|
if (this.obj) {
|
|
3810
3879
|
return;
|
|
3811
3880
|
}
|
|
3812
|
-
const
|
|
3813
|
-
|
|
3814
|
-
|
|
3881
|
+
const {
|
|
3882
|
+
image,
|
|
3883
|
+
height,
|
|
3884
|
+
width
|
|
3885
|
+
} = this;
|
|
3886
|
+
const hasAlphaChannel = image.hasAlphaChannel;
|
|
3887
|
+
const isInterlaced = image.interlaceMethod === 1;
|
|
3888
|
+
const obj = this.obj = document.ref({
|
|
3815
3889
|
Type: 'XObject',
|
|
3816
3890
|
Subtype: 'Image',
|
|
3817
|
-
BitsPerComponent: hasAlphaChannel ? 8 :
|
|
3818
|
-
Width:
|
|
3819
|
-
Height:
|
|
3891
|
+
BitsPerComponent: hasAlphaChannel ? 8 : image.bits,
|
|
3892
|
+
Width: width,
|
|
3893
|
+
Height: height,
|
|
3820
3894
|
Filter: 'FlateDecode'
|
|
3821
3895
|
});
|
|
3822
3896
|
if (!hasAlphaChannel) {
|
|
3823
|
-
const params =
|
|
3897
|
+
const params = document.ref({
|
|
3824
3898
|
Predictor: isInterlaced ? 1 : 15,
|
|
3825
|
-
Colors:
|
|
3826
|
-
BitsPerComponent:
|
|
3827
|
-
Columns:
|
|
3899
|
+
Colors: image.colors,
|
|
3900
|
+
BitsPerComponent: image.bits,
|
|
3901
|
+
Columns: width
|
|
3828
3902
|
});
|
|
3829
|
-
|
|
3903
|
+
obj.data['DecodeParms'] = params;
|
|
3830
3904
|
params.end();
|
|
3831
3905
|
}
|
|
3832
|
-
if (
|
|
3833
|
-
|
|
3906
|
+
if (image.palette.length === 0) {
|
|
3907
|
+
obj.data['ColorSpace'] = image.colorSpace;
|
|
3834
3908
|
} else {
|
|
3835
|
-
const palette =
|
|
3836
|
-
palette.end(Buffer.from(
|
|
3837
|
-
|
|
3838
|
-
}
|
|
3839
|
-
if (
|
|
3840
|
-
const val =
|
|
3841
|
-
|
|
3842
|
-
} else if (
|
|
3909
|
+
const palette = document.ref();
|
|
3910
|
+
palette.end(Buffer.from(image.palette));
|
|
3911
|
+
obj.data['ColorSpace'] = ['Indexed', 'DeviceRGB', image.palette.length / 3 - 1, palette];
|
|
3912
|
+
}
|
|
3913
|
+
if (image.transparency.grayscale != null) {
|
|
3914
|
+
const val = image.transparency.grayscale;
|
|
3915
|
+
obj.data['Mask'] = [val, val];
|
|
3916
|
+
} else if (image.transparency.rgb) {
|
|
3843
3917
|
const {
|
|
3844
3918
|
rgb
|
|
3845
|
-
} =
|
|
3919
|
+
} = image.transparency;
|
|
3846
3920
|
const mask = [];
|
|
3847
3921
|
for (let x of rgb) {
|
|
3848
3922
|
mask.push(x, x);
|
|
3849
3923
|
}
|
|
3850
|
-
|
|
3851
|
-
} else if (
|
|
3852
|
-
dataDecoded = true;
|
|
3924
|
+
obj.data['Mask'] = mask;
|
|
3925
|
+
} else if (image.transparency.indexed) {
|
|
3853
3926
|
return this.loadIndexedAlphaChannel();
|
|
3854
3927
|
} else if (hasAlphaChannel) {
|
|
3855
|
-
dataDecoded = true;
|
|
3856
3928
|
return this.splitAlphaChannel();
|
|
3857
3929
|
}
|
|
3858
|
-
if (isInterlaced &&
|
|
3930
|
+
if (isInterlaced && true) {
|
|
3859
3931
|
return this.decodeData();
|
|
3860
3932
|
}
|
|
3861
3933
|
this.finalize();
|
|
@@ -3946,7 +4018,7 @@ class PDFImage {
|
|
|
3946
4018
|
}
|
|
3947
4019
|
if (data[0] === 0xff && data[1] === 0xd8) {
|
|
3948
4020
|
return new JPEG(data, label);
|
|
3949
|
-
} else if (data[0] === 0x89 && data
|
|
4021
|
+
} else if (data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4e && data[3] === 0x47) {
|
|
3950
4022
|
return new PNGImage(data, label);
|
|
3951
4023
|
} else {
|
|
3952
4024
|
throw new Error('Unknown image format.');
|
|
@@ -4117,6 +4189,9 @@ var ImagesMixin = {
|
|
|
4117
4189
|
this.y += h;
|
|
4118
4190
|
}
|
|
4119
4191
|
this.save();
|
|
4192
|
+
if (options.opacity != null) {
|
|
4193
|
+
this._doOpacity(options.opacity, null);
|
|
4194
|
+
}
|
|
4120
4195
|
if (rotateAngle) {
|
|
4121
4196
|
this.rotate(rotateAngle, {
|
|
4122
4197
|
origin: [originX, originY]
|
|
@@ -4394,21 +4469,41 @@ class PDFStructureElement {
|
|
|
4394
4469
|
children = options;
|
|
4395
4470
|
options = {};
|
|
4396
4471
|
}
|
|
4397
|
-
if (
|
|
4472
|
+
if (options.title) {
|
|
4398
4473
|
data.T = new String(options.title);
|
|
4399
4474
|
}
|
|
4400
|
-
if (
|
|
4475
|
+
if (options.lang) {
|
|
4401
4476
|
data.Lang = new String(options.lang);
|
|
4402
4477
|
}
|
|
4403
|
-
if (
|
|
4478
|
+
if (options.alt) {
|
|
4404
4479
|
data.Alt = new String(options.alt);
|
|
4405
4480
|
}
|
|
4406
|
-
if (
|
|
4481
|
+
if (options.expanded) {
|
|
4407
4482
|
data.E = new String(options.expanded);
|
|
4408
4483
|
}
|
|
4409
|
-
if (
|
|
4484
|
+
if (options.actual) {
|
|
4410
4485
|
data.ActualText = new String(options.actual);
|
|
4411
4486
|
}
|
|
4487
|
+
const hasBbox = Array.isArray(options.bbox) && options.bbox.length === 4;
|
|
4488
|
+
const hasPlacement = typeof options.placement === 'string';
|
|
4489
|
+
if (hasBbox || hasPlacement) {
|
|
4490
|
+
const attrs = {
|
|
4491
|
+
O: 'Layout'
|
|
4492
|
+
};
|
|
4493
|
+
attrs.Placement = hasPlacement ? options.placement : 'Block';
|
|
4494
|
+
if (hasBbox) {
|
|
4495
|
+
const height = document.page.height;
|
|
4496
|
+
attrs.BBox = [options.bbox[0], height - options.bbox[3], options.bbox[2], height - options.bbox[1]];
|
|
4497
|
+
}
|
|
4498
|
+
data.A = attrs;
|
|
4499
|
+
}
|
|
4500
|
+
if (options.scope) {
|
|
4501
|
+
data.A = {
|
|
4502
|
+
...(data.A || {}),
|
|
4503
|
+
O: 'Table',
|
|
4504
|
+
Scope: options.scope
|
|
4505
|
+
};
|
|
4506
|
+
}
|
|
4412
4507
|
this._children = [];
|
|
4413
4508
|
if (children) {
|
|
4414
4509
|
if (!Array.isArray(children)) {
|
|
@@ -5082,7 +5177,7 @@ var AttachmentsMixin = {
|
|
|
5082
5177
|
const match = /^data:(.*?);base64,(.*)$/.exec(src);
|
|
5083
5178
|
if (match) {
|
|
5084
5179
|
if (match[1]) {
|
|
5085
|
-
refBody.Subtype = match[1]
|
|
5180
|
+
refBody.Subtype = escapeName(match[1]);
|
|
5086
5181
|
}
|
|
5087
5182
|
data = Buffer.from(match[2], 'base64');
|
|
5088
5183
|
} else {
|
|
@@ -5105,7 +5200,7 @@ var AttachmentsMixin = {
|
|
|
5105
5200
|
refBody.Params.ModDate = options.modifiedDate;
|
|
5106
5201
|
}
|
|
5107
5202
|
if (options.type) {
|
|
5108
|
-
refBody.Subtype = options.type
|
|
5203
|
+
refBody.Subtype = escapeName(options.type);
|
|
5109
5204
|
}
|
|
5110
5205
|
const checksum = md5Hex(new Uint8Array(data));
|
|
5111
5206
|
refBody.Params.CheckSum = new String(checksum);
|
|
@@ -5960,7 +6055,7 @@ var MetadataMixin = {
|
|
|
5960
6055
|
}
|
|
5961
6056
|
this.appendXML(`
|
|
5962
6057
|
<rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
|
|
5963
|
-
<pdf:Producer>${this.info.
|
|
6058
|
+
<pdf:Producer>${this.info.Producer}</pdf:Producer>`, false);
|
|
5964
6059
|
if (this.info.Keywords) {
|
|
5965
6060
|
this.appendXML(`
|
|
5966
6061
|
<pdf:Keywords>${this.info.Keywords}</pdf:Keywords>`, false);
|