pdfkit 0.16.0 → 0.17.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/.git-blame-ignore-revs +1 -0
- package/CHANGELOG.md +13 -0
- package/js/pdfkit.es.js +989 -782
- package/js/pdfkit.es.js.map +1 -1
- package/js/pdfkit.es5.js +7493 -0
- package/js/pdfkit.es5.js.map +1 -0
- package/js/pdfkit.esnext.js +6782 -0
- package/js/pdfkit.esnext.js.map +1 -0
- package/js/pdfkit.js +968 -783
- package/js/pdfkit.js.map +1 -1
- package/js/pdfkit.standalone.js +968 -783
- package/package.json +3 -3
package/js/pdfkit.standalone.js
CHANGED
|
@@ -12,23 +12,15 @@ var LineBreaker = require('linebreak');
|
|
|
12
12
|
var exif = require('jpeg-exif');
|
|
13
13
|
var PNG = require('png-js');
|
|
14
14
|
|
|
15
|
-
/*
|
|
16
|
-
PDFAbstractReference - abstract class for PDF reference
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
15
|
class PDFAbstractReference {
|
|
20
16
|
toString() {
|
|
21
17
|
throw new Error('Must be implemented by subclasses');
|
|
22
18
|
}
|
|
23
19
|
}
|
|
24
20
|
|
|
25
|
-
/*
|
|
26
|
-
PDFTree - abstract base class for name and number tree objects
|
|
27
|
-
*/
|
|
28
21
|
class PDFTree {
|
|
29
22
|
constructor(options = {}) {
|
|
30
23
|
this._items = {};
|
|
31
|
-
// disable /Limits output for this tree
|
|
32
24
|
this.limits = typeof options.limits === 'boolean' ? options.limits : true;
|
|
33
25
|
}
|
|
34
26
|
add(key, val) {
|
|
@@ -38,7 +30,6 @@ class PDFTree {
|
|
|
38
30
|
return this._items[key];
|
|
39
31
|
}
|
|
40
32
|
toString() {
|
|
41
|
-
// Needs to be sorted by key
|
|
42
33
|
const sortedKeys = Object.keys(this._items).sort((a, b) => this._compareKeys(a, b));
|
|
43
34
|
const out = ['<<'];
|
|
44
35
|
if (this.limits && sortedKeys.length > 1) {
|
|
@@ -54,15 +45,13 @@ class PDFTree {
|
|
|
54
45
|
out.push('>>');
|
|
55
46
|
return out.join('\n');
|
|
56
47
|
}
|
|
57
|
-
_compareKeys(
|
|
58
|
-
) {
|
|
48
|
+
_compareKeys() {
|
|
59
49
|
throw new Error('Must be implemented by subclasses');
|
|
60
50
|
}
|
|
61
51
|
_keysName() {
|
|
62
52
|
throw new Error('Must be implemented by subclasses');
|
|
63
53
|
}
|
|
64
|
-
_dataForKey(
|
|
65
|
-
) {
|
|
54
|
+
_dataForKey() {
|
|
66
55
|
throw new Error('Must be implemented by subclasses');
|
|
67
56
|
}
|
|
68
57
|
}
|
|
@@ -87,10 +76,6 @@ class SpotColor {
|
|
|
87
76
|
}
|
|
88
77
|
}
|
|
89
78
|
|
|
90
|
-
/*
|
|
91
|
-
PDFObject - converts JavaScript types into their corresponding PDF types.
|
|
92
|
-
By Devon Govett
|
|
93
|
-
*/
|
|
94
79
|
const pad = (str, length) => (Array(length + 1).join('0') + str).slice(-length);
|
|
95
80
|
const escapableRe = /[\n\r\t\b\f()\\]/g;
|
|
96
81
|
const escapable = {
|
|
@@ -103,8 +88,6 @@ const escapable = {
|
|
|
103
88
|
'(': '\\(',
|
|
104
89
|
')': '\\)'
|
|
105
90
|
};
|
|
106
|
-
|
|
107
|
-
// Convert little endian UTF-16 to big endian
|
|
108
91
|
const swapBytes = function (buff) {
|
|
109
92
|
const l = buff.length;
|
|
110
93
|
if (l & 0x01) {
|
|
@@ -120,14 +103,10 @@ const swapBytes = function (buff) {
|
|
|
120
103
|
};
|
|
121
104
|
class PDFObject {
|
|
122
105
|
static convert(object, encryptFn = null) {
|
|
123
|
-
// String literals are converted to the PDF name type
|
|
124
106
|
if (typeof object === 'string') {
|
|
125
107
|
return `/${object}`;
|
|
126
|
-
|
|
127
|
-
// String objects are converted to PDF strings (UTF-16)
|
|
128
108
|
} else if (object instanceof String) {
|
|
129
109
|
let string = object;
|
|
130
|
-
// Detect if this is a unicode string
|
|
131
110
|
let isUnicode = false;
|
|
132
111
|
for (let i = 0, end = string.length; i < end; i++) {
|
|
133
112
|
if (string.charCodeAt(i) > 0x7f) {
|
|
@@ -135,39 +114,27 @@ class PDFObject {
|
|
|
135
114
|
break;
|
|
136
115
|
}
|
|
137
116
|
}
|
|
138
|
-
|
|
139
|
-
// If so, encode it as big endian UTF-16
|
|
140
117
|
let stringBuffer;
|
|
141
118
|
if (isUnicode) {
|
|
142
119
|
stringBuffer = swapBytes(Buffer.from(`\ufeff${string}`, 'utf16le'));
|
|
143
120
|
} else {
|
|
144
121
|
stringBuffer = Buffer.from(string.valueOf(), 'ascii');
|
|
145
122
|
}
|
|
146
|
-
|
|
147
|
-
// Encrypt the string when necessary
|
|
148
123
|
if (encryptFn) {
|
|
149
124
|
string = encryptFn(stringBuffer).toString('binary');
|
|
150
125
|
} else {
|
|
151
126
|
string = stringBuffer.toString('binary');
|
|
152
127
|
}
|
|
153
|
-
|
|
154
|
-
// Escape characters as required by the spec
|
|
155
128
|
string = string.replace(escapableRe, c => escapable[c]);
|
|
156
129
|
return `(${string})`;
|
|
157
|
-
|
|
158
|
-
// Buffers are converted to PDF hex strings
|
|
159
130
|
} else if (Buffer.isBuffer(object)) {
|
|
160
131
|
return `<${object.toString('hex')}>`;
|
|
161
132
|
} else if (object instanceof PDFAbstractReference || object instanceof PDFTree || object instanceof SpotColor) {
|
|
162
133
|
return object.toString();
|
|
163
134
|
} else if (object instanceof Date) {
|
|
164
135
|
let string = `D:${pad(object.getUTCFullYear(), 4)}` + pad(object.getUTCMonth() + 1, 2) + pad(object.getUTCDate(), 2) + pad(object.getUTCHours(), 2) + pad(object.getUTCMinutes(), 2) + pad(object.getUTCSeconds(), 2) + 'Z';
|
|
165
|
-
|
|
166
|
-
// Encrypt the string when necessary
|
|
167
136
|
if (encryptFn) {
|
|
168
137
|
string = encryptFn(Buffer.from(string, 'ascii')).toString('binary');
|
|
169
|
-
|
|
170
|
-
// Escape characters as required by the spec
|
|
171
138
|
string = string.replace(escapableRe, c => escapable[c]);
|
|
172
139
|
}
|
|
173
140
|
return `(${string})`;
|
|
@@ -196,10 +163,6 @@ class PDFObject {
|
|
|
196
163
|
}
|
|
197
164
|
}
|
|
198
165
|
|
|
199
|
-
/*
|
|
200
|
-
PDFReference - represents a reference to another object in the PDF object heirarchy
|
|
201
|
-
By Devon Govett
|
|
202
|
-
*/
|
|
203
166
|
class PDFReference extends PDFAbstractReference {
|
|
204
167
|
constructor(document, id, data = {}) {
|
|
205
168
|
super();
|
|
@@ -222,14 +185,14 @@ class PDFReference extends PDFAbstractReference {
|
|
|
222
185
|
this.buffer.push(chunk);
|
|
223
186
|
this.data.Length += chunk.length;
|
|
224
187
|
if (this.compress) {
|
|
225
|
-
|
|
188
|
+
this.data.Filter = 'FlateDecode';
|
|
226
189
|
}
|
|
227
190
|
}
|
|
228
191
|
end(chunk) {
|
|
229
192
|
if (chunk) {
|
|
230
193
|
this.write(chunk);
|
|
231
194
|
}
|
|
232
|
-
|
|
195
|
+
this.finalize();
|
|
233
196
|
}
|
|
234
197
|
finalize() {
|
|
235
198
|
this.offset = this.document._offset;
|
|
@@ -249,7 +212,7 @@ class PDFReference extends PDFAbstractReference {
|
|
|
249
212
|
if (this.buffer.length) {
|
|
250
213
|
this.document._write('stream');
|
|
251
214
|
this.document._write(this.buffer);
|
|
252
|
-
this.buffer = [];
|
|
215
|
+
this.buffer = [];
|
|
253
216
|
this.document._write('\nendstream');
|
|
254
217
|
}
|
|
255
218
|
this.document._write('endobj');
|
|
@@ -260,10 +223,69 @@ class PDFReference extends PDFAbstractReference {
|
|
|
260
223
|
}
|
|
261
224
|
}
|
|
262
225
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
226
|
+
function PDFNumber(n) {
|
|
227
|
+
return Math.fround(n);
|
|
228
|
+
}
|
|
229
|
+
function normalizeSides(sides, defaultDefinition = undefined, transformer = v => v) {
|
|
230
|
+
if (sides == null || typeof sides === 'object' && Object.keys(sides).length === 0) {
|
|
231
|
+
sides = defaultDefinition;
|
|
232
|
+
}
|
|
233
|
+
if (sides == null || typeof sides !== 'object') {
|
|
234
|
+
sides = {
|
|
235
|
+
top: sides,
|
|
236
|
+
right: sides,
|
|
237
|
+
bottom: sides,
|
|
238
|
+
left: sides
|
|
239
|
+
};
|
|
240
|
+
} else if (Array.isArray(sides)) {
|
|
241
|
+
if (sides.length === 2) {
|
|
242
|
+
sides = {
|
|
243
|
+
vertical: sides[0],
|
|
244
|
+
horizontal: sides[1]
|
|
245
|
+
};
|
|
246
|
+
} else {
|
|
247
|
+
sides = {
|
|
248
|
+
top: sides[0],
|
|
249
|
+
right: sides[1],
|
|
250
|
+
bottom: sides[2],
|
|
251
|
+
left: sides[3]
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if ('vertical' in sides || 'horizontal' in sides) {
|
|
256
|
+
sides = {
|
|
257
|
+
top: sides.vertical,
|
|
258
|
+
right: sides.horizontal,
|
|
259
|
+
bottom: sides.vertical,
|
|
260
|
+
left: sides.horizontal
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
top: transformer(sides.top),
|
|
265
|
+
right: transformer(sides.right),
|
|
266
|
+
bottom: transformer(sides.bottom),
|
|
267
|
+
left: transformer(sides.left)
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
const MM_TO_CM = 1 / 10;
|
|
271
|
+
const CM_TO_IN = 1 / 2.54;
|
|
272
|
+
const PX_TO_IN = 1 / 96;
|
|
273
|
+
const IN_TO_PT = 72;
|
|
274
|
+
const PC_TO_PT = 12;
|
|
275
|
+
function cosine(a) {
|
|
276
|
+
if (a === 0) return 1;
|
|
277
|
+
if (a === 90) return 0;
|
|
278
|
+
if (a === 180) return -1;
|
|
279
|
+
if (a === 270) return 0;
|
|
280
|
+
return Math.cos(a * Math.PI / 180);
|
|
281
|
+
}
|
|
282
|
+
function sine(a) {
|
|
283
|
+
if (a === 0) return 0;
|
|
284
|
+
if (a === 90) return 1;
|
|
285
|
+
if (a === 180) return 0;
|
|
286
|
+
if (a === 270) return -1;
|
|
287
|
+
return Math.sin(a * Math.PI / 180);
|
|
288
|
+
}
|
|
267
289
|
|
|
268
290
|
const DEFAULT_MARGINS = {
|
|
269
291
|
top: 72,
|
|
@@ -326,35 +348,19 @@ const SIZES = {
|
|
|
326
348
|
class PDFPage {
|
|
327
349
|
constructor(document, options = {}) {
|
|
328
350
|
this.document = document;
|
|
351
|
+
this._options = options;
|
|
329
352
|
this.size = options.size || 'letter';
|
|
330
353
|
this.layout = options.layout || 'portrait';
|
|
331
|
-
|
|
332
|
-
// process margins
|
|
333
|
-
if (typeof options.margin === 'number') {
|
|
334
|
-
this.margins = {
|
|
335
|
-
top: options.margin,
|
|
336
|
-
left: options.margin,
|
|
337
|
-
bottom: options.margin,
|
|
338
|
-
right: options.margin
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
// default to 1 inch margins
|
|
342
|
-
} else {
|
|
343
|
-
this.margins = options.margins || DEFAULT_MARGINS;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// calculate page dimensions
|
|
347
354
|
const dimensions = Array.isArray(this.size) ? this.size : SIZES[this.size.toUpperCase()];
|
|
348
355
|
this.width = dimensions[this.layout === 'portrait' ? 0 : 1];
|
|
349
356
|
this.height = dimensions[this.layout === 'portrait' ? 1 : 0];
|
|
350
357
|
this.content = this.document.ref();
|
|
351
|
-
|
|
352
|
-
|
|
358
|
+
if (options.font) document.font(options.font, options.fontFamily);
|
|
359
|
+
if (options.fontSize) document.fontSize(options.fontSize);
|
|
360
|
+
this.margins = normalizeSides(options.margin ?? options.margins, DEFAULT_MARGINS, x => document.sizeToPoint(x, 0, this));
|
|
353
361
|
this.resources = this.document.ref({
|
|
354
362
|
ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI']
|
|
355
363
|
});
|
|
356
|
-
|
|
357
|
-
// The page dictionary
|
|
358
364
|
this.dictionary = this.document.ref({
|
|
359
365
|
Type: 'Page',
|
|
360
366
|
Parent: this.document._root.data.Pages,
|
|
@@ -364,8 +370,6 @@ class PDFPage {
|
|
|
364
370
|
});
|
|
365
371
|
this.markings = [];
|
|
366
372
|
}
|
|
367
|
-
|
|
368
|
-
// Lazily create these objects
|
|
369
373
|
get fonts() {
|
|
370
374
|
const data = this.resources.data;
|
|
371
375
|
return data.Font != null ? data.Font : data.Font = {};
|
|
@@ -394,14 +398,18 @@ class PDFPage {
|
|
|
394
398
|
const data = this.dictionary.data;
|
|
395
399
|
return data.StructParents != null ? data.StructParents : data.StructParents = this.document.createStructParentTreeNextKey();
|
|
396
400
|
}
|
|
401
|
+
get contentWidth() {
|
|
402
|
+
return this.width - this.margins.left - this.margins.right;
|
|
403
|
+
}
|
|
404
|
+
get contentHeight() {
|
|
405
|
+
return this.height - this.margins.top - this.margins.bottom;
|
|
406
|
+
}
|
|
397
407
|
maxY() {
|
|
398
408
|
return this.height - this.margins.bottom;
|
|
399
409
|
}
|
|
400
410
|
write(chunk) {
|
|
401
411
|
return this.content.write(chunk);
|
|
402
412
|
}
|
|
403
|
-
|
|
404
|
-
// Set tab order if document is tagged for accessibility.
|
|
405
413
|
_setTabOrder() {
|
|
406
414
|
if (!this.dictionary.Tabs && this.document.hasMarkInfoDictionary()) {
|
|
407
415
|
this.dictionary.data.Tabs = 'S';
|
|
@@ -419,191 +427,57 @@ class PDFPage {
|
|
|
419
427
|
}
|
|
420
428
|
}
|
|
421
429
|
|
|
422
|
-
/*
|
|
423
|
-
PDFNameTree - represents a name tree object
|
|
424
|
-
*/
|
|
425
430
|
class PDFNameTree extends PDFTree {
|
|
426
431
|
_compareKeys(a, b) {
|
|
427
432
|
return a.localeCompare(b);
|
|
428
433
|
}
|
|
429
434
|
_keysName() {
|
|
430
|
-
return
|
|
435
|
+
return 'Names';
|
|
431
436
|
}
|
|
432
437
|
_dataForKey(k) {
|
|
433
438
|
return new String(k);
|
|
434
439
|
}
|
|
435
440
|
}
|
|
436
441
|
|
|
437
|
-
/**
|
|
438
|
-
* Check if value is in a range group.
|
|
439
|
-
* @param {number} value
|
|
440
|
-
* @param {number[]} rangeGroup
|
|
441
|
-
* @returns {boolean}
|
|
442
|
-
*/
|
|
443
442
|
function inRange(value, rangeGroup) {
|
|
444
443
|
if (value < rangeGroup[0]) return false;
|
|
445
444
|
let startRange = 0;
|
|
446
445
|
let endRange = rangeGroup.length / 2;
|
|
447
446
|
while (startRange <= endRange) {
|
|
448
447
|
const middleRange = Math.floor((startRange + endRange) / 2);
|
|
449
|
-
|
|
450
|
-
// actual array index
|
|
451
448
|
const arrayIndex = middleRange * 2;
|
|
452
|
-
|
|
453
|
-
// Check if value is in range pointed by actual index
|
|
454
449
|
if (value >= rangeGroup[arrayIndex] && value <= rangeGroup[arrayIndex + 1]) {
|
|
455
450
|
return true;
|
|
456
451
|
}
|
|
457
452
|
if (value > rangeGroup[arrayIndex + 1]) {
|
|
458
|
-
// Search Right Side Of Array
|
|
459
453
|
startRange = middleRange + 1;
|
|
460
454
|
} else {
|
|
461
|
-
// Search Left Side Of Array
|
|
462
455
|
endRange = middleRange - 1;
|
|
463
456
|
}
|
|
464
457
|
}
|
|
465
458
|
return false;
|
|
466
459
|
}
|
|
467
460
|
|
|
468
|
-
// prettier-ignore-start
|
|
469
|
-
/**
|
|
470
|
-
* A.1 Unassigned code points in Unicode 3.2
|
|
471
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-A.1
|
|
472
|
-
*/
|
|
473
461
|
const unassigned_code_points = [0x0221, 0x0221, 0x0234, 0x024f, 0x02ae, 0x02af, 0x02ef, 0x02ff, 0x0350, 0x035f, 0x0370, 0x0373, 0x0376, 0x0379, 0x037b, 0x037d, 0x037f, 0x0383, 0x038b, 0x038b, 0x038d, 0x038d, 0x03a2, 0x03a2, 0x03cf, 0x03cf, 0x03f7, 0x03ff, 0x0487, 0x0487, 0x04cf, 0x04cf, 0x04f6, 0x04f7, 0x04fa, 0x04ff, 0x0510, 0x0530, 0x0557, 0x0558, 0x0560, 0x0560, 0x0588, 0x0588, 0x058b, 0x0590, 0x05a2, 0x05a2, 0x05ba, 0x05ba, 0x05c5, 0x05cf, 0x05eb, 0x05ef, 0x05f5, 0x060b, 0x060d, 0x061a, 0x061c, 0x061e, 0x0620, 0x0620, 0x063b, 0x063f, 0x0656, 0x065f, 0x06ee, 0x06ef, 0x06ff, 0x06ff, 0x070e, 0x070e, 0x072d, 0x072f, 0x074b, 0x077f, 0x07b2, 0x0900, 0x0904, 0x0904, 0x093a, 0x093b, 0x094e, 0x094f, 0x0955, 0x0957, 0x0971, 0x0980, 0x0984, 0x0984, 0x098d, 0x098e, 0x0991, 0x0992, 0x09a9, 0x09a9, 0x09b1, 0x09b1, 0x09b3, 0x09b5, 0x09ba, 0x09bb, 0x09bd, 0x09bd, 0x09c5, 0x09c6, 0x09c9, 0x09ca, 0x09ce, 0x09d6, 0x09d8, 0x09db, 0x09de, 0x09de, 0x09e4, 0x09e5, 0x09fb, 0x0a01, 0x0a03, 0x0a04, 0x0a0b, 0x0a0e, 0x0a11, 0x0a12, 0x0a29, 0x0a29, 0x0a31, 0x0a31, 0x0a34, 0x0a34, 0x0a37, 0x0a37, 0x0a3a, 0x0a3b, 0x0a3d, 0x0a3d, 0x0a43, 0x0a46, 0x0a49, 0x0a4a, 0x0a4e, 0x0a58, 0x0a5d, 0x0a5d, 0x0a5f, 0x0a65, 0x0a75, 0x0a80, 0x0a84, 0x0a84, 0x0a8c, 0x0a8c, 0x0a8e, 0x0a8e, 0x0a92, 0x0a92, 0x0aa9, 0x0aa9, 0x0ab1, 0x0ab1, 0x0ab4, 0x0ab4, 0x0aba, 0x0abb, 0x0ac6, 0x0ac6, 0x0aca, 0x0aca, 0x0ace, 0x0acf, 0x0ad1, 0x0adf, 0x0ae1, 0x0ae5, 0x0af0, 0x0b00, 0x0b04, 0x0b04, 0x0b0d, 0x0b0e, 0x0b11, 0x0b12, 0x0b29, 0x0b29, 0x0b31, 0x0b31, 0x0b34, 0x0b35, 0x0b3a, 0x0b3b, 0x0b44, 0x0b46, 0x0b49, 0x0b4a, 0x0b4e, 0x0b55, 0x0b58, 0x0b5b, 0x0b5e, 0x0b5e, 0x0b62, 0x0b65, 0x0b71, 0x0b81, 0x0b84, 0x0b84, 0x0b8b, 0x0b8d, 0x0b91, 0x0b91, 0x0b96, 0x0b98, 0x0b9b, 0x0b9b, 0x0b9d, 0x0b9d, 0x0ba0, 0x0ba2, 0x0ba5, 0x0ba7, 0x0bab, 0x0bad, 0x0bb6, 0x0bb6, 0x0bba, 0x0bbd, 0x0bc3, 0x0bc5, 0x0bc9, 0x0bc9, 0x0bce, 0x0bd6, 0x0bd8, 0x0be6, 0x0bf3, 0x0c00, 0x0c04, 0x0c04, 0x0c0d, 0x0c0d, 0x0c11, 0x0c11, 0x0c29, 0x0c29, 0x0c34, 0x0c34, 0x0c3a, 0x0c3d, 0x0c45, 0x0c45, 0x0c49, 0x0c49, 0x0c4e, 0x0c54, 0x0c57, 0x0c5f, 0x0c62, 0x0c65, 0x0c70, 0x0c81, 0x0c84, 0x0c84, 0x0c8d, 0x0c8d, 0x0c91, 0x0c91, 0x0ca9, 0x0ca9, 0x0cb4, 0x0cb4, 0x0cba, 0x0cbd, 0x0cc5, 0x0cc5, 0x0cc9, 0x0cc9, 0x0cce, 0x0cd4, 0x0cd7, 0x0cdd, 0x0cdf, 0x0cdf, 0x0ce2, 0x0ce5, 0x0cf0, 0x0d01, 0x0d04, 0x0d04, 0x0d0d, 0x0d0d, 0x0d11, 0x0d11, 0x0d29, 0x0d29, 0x0d3a, 0x0d3d, 0x0d44, 0x0d45, 0x0d49, 0x0d49, 0x0d4e, 0x0d56, 0x0d58, 0x0d5f, 0x0d62, 0x0d65, 0x0d70, 0x0d81, 0x0d84, 0x0d84, 0x0d97, 0x0d99, 0x0db2, 0x0db2, 0x0dbc, 0x0dbc, 0x0dbe, 0x0dbf, 0x0dc7, 0x0dc9, 0x0dcb, 0x0dce, 0x0dd5, 0x0dd5, 0x0dd7, 0x0dd7, 0x0de0, 0x0df1, 0x0df5, 0x0e00, 0x0e3b, 0x0e3e, 0x0e5c, 0x0e80, 0x0e83, 0x0e83, 0x0e85, 0x0e86, 0x0e89, 0x0e89, 0x0e8b, 0x0e8c, 0x0e8e, 0x0e93, 0x0e98, 0x0e98, 0x0ea0, 0x0ea0, 0x0ea4, 0x0ea4, 0x0ea6, 0x0ea6, 0x0ea8, 0x0ea9, 0x0eac, 0x0eac, 0x0eba, 0x0eba, 0x0ebe, 0x0ebf, 0x0ec5, 0x0ec5, 0x0ec7, 0x0ec7, 0x0ece, 0x0ecf, 0x0eda, 0x0edb, 0x0ede, 0x0eff, 0x0f48, 0x0f48, 0x0f6b, 0x0f70, 0x0f8c, 0x0f8f, 0x0f98, 0x0f98, 0x0fbd, 0x0fbd, 0x0fcd, 0x0fce, 0x0fd0, 0x0fff, 0x1022, 0x1022, 0x1028, 0x1028, 0x102b, 0x102b, 0x1033, 0x1035, 0x103a, 0x103f, 0x105a, 0x109f, 0x10c6, 0x10cf, 0x10f9, 0x10fa, 0x10fc, 0x10ff, 0x115a, 0x115e, 0x11a3, 0x11a7, 0x11fa, 0x11ff, 0x1207, 0x1207, 0x1247, 0x1247, 0x1249, 0x1249, 0x124e, 0x124f, 0x1257, 0x1257, 0x1259, 0x1259, 0x125e, 0x125f, 0x1287, 0x1287, 0x1289, 0x1289, 0x128e, 0x128f, 0x12af, 0x12af, 0x12b1, 0x12b1, 0x12b6, 0x12b7, 0x12bf, 0x12bf, 0x12c1, 0x12c1, 0x12c6, 0x12c7, 0x12cf, 0x12cf, 0x12d7, 0x12d7, 0x12ef, 0x12ef, 0x130f, 0x130f, 0x1311, 0x1311, 0x1316, 0x1317, 0x131f, 0x131f, 0x1347, 0x1347, 0x135b, 0x1360, 0x137d, 0x139f, 0x13f5, 0x1400, 0x1677, 0x167f, 0x169d, 0x169f, 0x16f1, 0x16ff, 0x170d, 0x170d, 0x1715, 0x171f, 0x1737, 0x173f, 0x1754, 0x175f, 0x176d, 0x176d, 0x1771, 0x1771, 0x1774, 0x177f, 0x17dd, 0x17df, 0x17ea, 0x17ff, 0x180f, 0x180f, 0x181a, 0x181f, 0x1878, 0x187f, 0x18aa, 0x1dff, 0x1e9c, 0x1e9f, 0x1efa, 0x1eff, 0x1f16, 0x1f17, 0x1f1e, 0x1f1f, 0x1f46, 0x1f47, 0x1f4e, 0x1f4f, 0x1f58, 0x1f58, 0x1f5a, 0x1f5a, 0x1f5c, 0x1f5c, 0x1f5e, 0x1f5e, 0x1f7e, 0x1f7f, 0x1fb5, 0x1fb5, 0x1fc5, 0x1fc5, 0x1fd4, 0x1fd5, 0x1fdc, 0x1fdc, 0x1ff0, 0x1ff1, 0x1ff5, 0x1ff5, 0x1fff, 0x1fff, 0x2053, 0x2056, 0x2058, 0x205e, 0x2064, 0x2069, 0x2072, 0x2073, 0x208f, 0x209f, 0x20b2, 0x20cf, 0x20eb, 0x20ff, 0x213b, 0x213c, 0x214c, 0x2152, 0x2184, 0x218f, 0x23cf, 0x23ff, 0x2427, 0x243f, 0x244b, 0x245f, 0x24ff, 0x24ff, 0x2614, 0x2615, 0x2618, 0x2618, 0x267e, 0x267f, 0x268a, 0x2700, 0x2705, 0x2705, 0x270a, 0x270b, 0x2728, 0x2728, 0x274c, 0x274c, 0x274e, 0x274e, 0x2753, 0x2755, 0x2757, 0x2757, 0x275f, 0x2760, 0x2795, 0x2797, 0x27b0, 0x27b0, 0x27bf, 0x27cf, 0x27ec, 0x27ef, 0x2b00, 0x2e7f, 0x2e9a, 0x2e9a, 0x2ef4, 0x2eff, 0x2fd6, 0x2fef, 0x2ffc, 0x2fff, 0x3040, 0x3040, 0x3097, 0x3098, 0x3100, 0x3104, 0x312d, 0x3130, 0x318f, 0x318f, 0x31b8, 0x31ef, 0x321d, 0x321f, 0x3244, 0x3250, 0x327c, 0x327e, 0x32cc, 0x32cf, 0x32ff, 0x32ff, 0x3377, 0x337a, 0x33de, 0x33df, 0x33ff, 0x33ff, 0x4db6, 0x4dff, 0x9fa6, 0x9fff, 0xa48d, 0xa48f, 0xa4c7, 0xabff, 0xd7a4, 0xd7ff, 0xfa2e, 0xfa2f, 0xfa6b, 0xfaff, 0xfb07, 0xfb12, 0xfb18, 0xfb1c, 0xfb37, 0xfb37, 0xfb3d, 0xfb3d, 0xfb3f, 0xfb3f, 0xfb42, 0xfb42, 0xfb45, 0xfb45, 0xfbb2, 0xfbd2, 0xfd40, 0xfd4f, 0xfd90, 0xfd91, 0xfdc8, 0xfdcf, 0xfdfd, 0xfdff, 0xfe10, 0xfe1f, 0xfe24, 0xfe2f, 0xfe47, 0xfe48, 0xfe53, 0xfe53, 0xfe67, 0xfe67, 0xfe6c, 0xfe6f, 0xfe75, 0xfe75, 0xfefd, 0xfefe, 0xff00, 0xff00, 0xffbf, 0xffc1, 0xffc8, 0xffc9, 0xffd0, 0xffd1, 0xffd8, 0xffd9, 0xffdd, 0xffdf, 0xffe7, 0xffe7, 0xffef, 0xfff8, 0x10000, 0x102ff, 0x1031f, 0x1031f, 0x10324, 0x1032f, 0x1034b, 0x103ff, 0x10426, 0x10427, 0x1044e, 0x1cfff, 0x1d0f6, 0x1d0ff, 0x1d127, 0x1d129, 0x1d1de, 0x1d3ff, 0x1d455, 0x1d455, 0x1d49d, 0x1d49d, 0x1d4a0, 0x1d4a1, 0x1d4a3, 0x1d4a4, 0x1d4a7, 0x1d4a8, 0x1d4ad, 0x1d4ad, 0x1d4ba, 0x1d4ba, 0x1d4bc, 0x1d4bc, 0x1d4c1, 0x1d4c1, 0x1d4c4, 0x1d4c4, 0x1d506, 0x1d506, 0x1d50b, 0x1d50c, 0x1d515, 0x1d515, 0x1d51d, 0x1d51d, 0x1d53a, 0x1d53a, 0x1d53f, 0x1d53f, 0x1d545, 0x1d545, 0x1d547, 0x1d549, 0x1d551, 0x1d551, 0x1d6a4, 0x1d6a7, 0x1d7ca, 0x1d7cd, 0x1d800, 0x1fffd, 0x2a6d7, 0x2f7ff, 0x2fa1e, 0x2fffd, 0x30000, 0x3fffd, 0x40000, 0x4fffd, 0x50000, 0x5fffd, 0x60000, 0x6fffd, 0x70000, 0x7fffd, 0x80000, 0x8fffd, 0x90000, 0x9fffd, 0xa0000, 0xafffd, 0xb0000, 0xbfffd, 0xc0000, 0xcfffd, 0xd0000, 0xdfffd, 0xe0000, 0xe0000, 0xe0002, 0xe001f, 0xe0080, 0xefffd];
|
|
474
|
-
// prettier-ignore-end
|
|
475
|
-
|
|
476
462
|
const isUnassignedCodePoint = character => inRange(character, unassigned_code_points);
|
|
477
|
-
|
|
478
|
-
// prettier-ignore-start
|
|
479
|
-
/**
|
|
480
|
-
* B.1 Commonly mapped to nothing
|
|
481
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-B.1
|
|
482
|
-
*/
|
|
483
463
|
const commonly_mapped_to_nothing = [0x00ad, 0x00ad, 0x034f, 0x034f, 0x1806, 0x1806, 0x180b, 0x180b, 0x180c, 0x180c, 0x180d, 0x180d, 0x200b, 0x200b, 0x200c, 0x200c, 0x200d, 0x200d, 0x2060, 0x2060, 0xfe00, 0xfe00, 0xfe01, 0xfe01, 0xfe02, 0xfe02, 0xfe03, 0xfe03, 0xfe04, 0xfe04, 0xfe05, 0xfe05, 0xfe06, 0xfe06, 0xfe07, 0xfe07, 0xfe08, 0xfe08, 0xfe09, 0xfe09, 0xfe0a, 0xfe0a, 0xfe0b, 0xfe0b, 0xfe0c, 0xfe0c, 0xfe0d, 0xfe0d, 0xfe0e, 0xfe0e, 0xfe0f, 0xfe0f, 0xfeff, 0xfeff];
|
|
484
|
-
// prettier-ignore-end
|
|
485
|
-
|
|
486
464
|
const isCommonlyMappedToNothing = character => inRange(character, commonly_mapped_to_nothing);
|
|
487
|
-
|
|
488
|
-
// prettier-ignore-start
|
|
489
|
-
/**
|
|
490
|
-
* C.1.2 Non-ASCII space characters
|
|
491
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-C.1.2
|
|
492
|
-
*/
|
|
493
|
-
const non_ASCII_space_characters = [0x00a0, 0x00a0 /* NO-BREAK SPACE */, 0x1680, 0x1680 /* OGHAM SPACE MARK */, 0x2000, 0x2000 /* EN QUAD */, 0x2001, 0x2001 /* EM QUAD */, 0x2002, 0x2002 /* EN SPACE */, 0x2003, 0x2003 /* EM SPACE */, 0x2004, 0x2004 /* THREE-PER-EM SPACE */, 0x2005, 0x2005 /* FOUR-PER-EM SPACE */, 0x2006, 0x2006 /* SIX-PER-EM SPACE */, 0x2007, 0x2007 /* FIGURE SPACE */, 0x2008, 0x2008 /* PUNCTUATION SPACE */, 0x2009, 0x2009 /* THIN SPACE */, 0x200a, 0x200a /* HAIR SPACE */, 0x200b, 0x200b /* ZERO WIDTH SPACE */, 0x202f, 0x202f /* NARROW NO-BREAK SPACE */, 0x205f, 0x205f /* MEDIUM MATHEMATICAL SPACE */, 0x3000, 0x3000 /* IDEOGRAPHIC SPACE */];
|
|
494
|
-
// prettier-ignore-end
|
|
495
|
-
|
|
465
|
+
const non_ASCII_space_characters = [0x00a0, 0x00a0, 0x1680, 0x1680, 0x2000, 0x2000, 0x2001, 0x2001, 0x2002, 0x2002, 0x2003, 0x2003, 0x2004, 0x2004, 0x2005, 0x2005, 0x2006, 0x2006, 0x2007, 0x2007, 0x2008, 0x2008, 0x2009, 0x2009, 0x200a, 0x200a, 0x200b, 0x200b, 0x202f, 0x202f, 0x205f, 0x205f, 0x3000, 0x3000];
|
|
496
466
|
const isNonASCIISpaceCharacter = character => inRange(character, non_ASCII_space_characters);
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
const
|
|
500
|
-
/**
|
|
501
|
-
* C.2.2 Non-ASCII control characters
|
|
502
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-C.2.2
|
|
503
|
-
*/
|
|
504
|
-
0x0080, 0x009f /* [CONTROL CHARACTERS] */, 0x06dd, 0x06dd /* ARABIC END OF AYAH */, 0x070f, 0x070f /* SYRIAC ABBREVIATION MARK */, 0x180e, 0x180e /* MONGOLIAN VOWEL SEPARATOR */, 0x200c, 0x200c /* ZERO WIDTH NON-JOINER */, 0x200d, 0x200d /* ZERO WIDTH JOINER */, 0x2028, 0x2028 /* LINE SEPARATOR */, 0x2029, 0x2029 /* PARAGRAPH SEPARATOR */, 0x2060, 0x2060 /* WORD JOINER */, 0x2061, 0x2061 /* FUNCTION APPLICATION */, 0x2062, 0x2062 /* INVISIBLE TIMES */, 0x2063, 0x2063 /* INVISIBLE SEPARATOR */, 0x206a, 0x206f /* [CONTROL CHARACTERS] */, 0xfeff, 0xfeff /* ZERO WIDTH NO-BREAK SPACE */, 0xfff9, 0xfffc /* [CONTROL CHARACTERS] */, 0x1d173, 0x1d17a /* [MUSICAL CONTROL CHARACTERS] */];
|
|
505
|
-
const non_character_codepoints = [
|
|
506
|
-
/**
|
|
507
|
-
* C.4 Non-character code points
|
|
508
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-C.4
|
|
509
|
-
*/
|
|
510
|
-
0xfdd0, 0xfdef /* [NONCHARACTER CODE POINTS] */, 0xfffe, 0xffff /* [NONCHARACTER CODE POINTS] */, 0x1fffe, 0x1ffff /* [NONCHARACTER CODE POINTS] */, 0x2fffe, 0x2ffff /* [NONCHARACTER CODE POINTS] */, 0x3fffe, 0x3ffff /* [NONCHARACTER CODE POINTS] */, 0x4fffe, 0x4ffff /* [NONCHARACTER CODE POINTS] */, 0x5fffe, 0x5ffff /* [NONCHARACTER CODE POINTS] */, 0x6fffe, 0x6ffff /* [NONCHARACTER CODE POINTS] */, 0x7fffe, 0x7ffff /* [NONCHARACTER CODE POINTS] */, 0x8fffe, 0x8ffff /* [NONCHARACTER CODE POINTS] */, 0x9fffe, 0x9ffff /* [NONCHARACTER CODE POINTS] */, 0xafffe, 0xaffff /* [NONCHARACTER CODE POINTS] */, 0xbfffe, 0xbffff /* [NONCHARACTER CODE POINTS] */, 0xcfffe, 0xcffff /* [NONCHARACTER CODE POINTS] */, 0xdfffe, 0xdffff /* [NONCHARACTER CODE POINTS] */, 0xefffe, 0xeffff /* [NONCHARACTER CODE POINTS] */, 0x10fffe, 0x10ffff /* [NONCHARACTER CODE POINTS] */];
|
|
511
|
-
|
|
512
|
-
/**
|
|
513
|
-
* 2.3. Prohibited Output
|
|
514
|
-
*/
|
|
515
|
-
const prohibited_characters = [
|
|
516
|
-
/**
|
|
517
|
-
* C.2.1 ASCII control characters
|
|
518
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-C.2.1
|
|
519
|
-
*/
|
|
520
|
-
0, 0x001f /* [CONTROL CHARACTERS] */, 0x007f, 0x007f /* DELETE */,
|
|
521
|
-
/**
|
|
522
|
-
* C.8 Change display properties or are deprecated
|
|
523
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-C.8
|
|
524
|
-
*/
|
|
525
|
-
0x0340, 0x0340 /* COMBINING GRAVE TONE MARK */, 0x0341, 0x0341 /* COMBINING ACUTE TONE MARK */, 0x200e, 0x200e /* LEFT-TO-RIGHT MARK */, 0x200f, 0x200f /* RIGHT-TO-LEFT MARK */, 0x202a, 0x202a /* LEFT-TO-RIGHT EMBEDDING */, 0x202b, 0x202b /* RIGHT-TO-LEFT EMBEDDING */, 0x202c, 0x202c /* POP DIRECTIONAL FORMATTING */, 0x202d, 0x202d /* LEFT-TO-RIGHT OVERRIDE */, 0x202e, 0x202e /* RIGHT-TO-LEFT OVERRIDE */, 0x206a, 0x206a /* INHIBIT SYMMETRIC SWAPPING */, 0x206b, 0x206b /* ACTIVATE SYMMETRIC SWAPPING */, 0x206c, 0x206c /* INHIBIT ARABIC FORM SHAPING */, 0x206d, 0x206d /* ACTIVATE ARABIC FORM SHAPING */, 0x206e, 0x206e /* NATIONAL DIGIT SHAPES */, 0x206f, 0x206f /* NOMINAL DIGIT SHAPES */,
|
|
526
|
-
/**
|
|
527
|
-
* C.7 Inappropriate for canonical representation
|
|
528
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-C.7
|
|
529
|
-
*/
|
|
530
|
-
0x2ff0, 0x2ffb /* [IDEOGRAPHIC DESCRIPTION CHARACTERS] */,
|
|
531
|
-
/**
|
|
532
|
-
* C.5 Surrogate codes
|
|
533
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-C.5
|
|
534
|
-
*/
|
|
535
|
-
0xd800, 0xdfff,
|
|
536
|
-
/**
|
|
537
|
-
* C.3 Private use
|
|
538
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-C.3
|
|
539
|
-
*/
|
|
540
|
-
0xe000, 0xf8ff /* [PRIVATE USE, PLANE 0] */,
|
|
541
|
-
/**
|
|
542
|
-
* C.6 Inappropriate for plain text
|
|
543
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-C.6
|
|
544
|
-
*/
|
|
545
|
-
0xfff9, 0xfff9 /* INTERLINEAR ANNOTATION ANCHOR */, 0xfffa, 0xfffa /* INTERLINEAR ANNOTATION SEPARATOR */, 0xfffb, 0xfffb /* INTERLINEAR ANNOTATION TERMINATOR */, 0xfffc, 0xfffc /* OBJECT REPLACEMENT CHARACTER */, 0xfffd, 0xfffd /* REPLACEMENT CHARACTER */,
|
|
546
|
-
/**
|
|
547
|
-
* C.9 Tagging characters
|
|
548
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-C.9
|
|
549
|
-
*/
|
|
550
|
-
0xe0001, 0xe0001 /* LANGUAGE TAG */, 0xe0020, 0xe007f /* [TAGGING CHARACTERS] */,
|
|
551
|
-
/**
|
|
552
|
-
* C.3 Private use
|
|
553
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-C.3
|
|
554
|
-
*/
|
|
555
|
-
|
|
556
|
-
0xf0000, 0xffffd /* [PRIVATE USE, PLANE 15] */, 0x100000, 0x10fffd /* [PRIVATE USE, PLANE 16] */];
|
|
557
|
-
// prettier-ignore-end
|
|
558
|
-
|
|
467
|
+
const non_ASCII_controls_characters = [0x0080, 0x009f, 0x06dd, 0x06dd, 0x070f, 0x070f, 0x180e, 0x180e, 0x200c, 0x200c, 0x200d, 0x200d, 0x2028, 0x2028, 0x2029, 0x2029, 0x2060, 0x2060, 0x2061, 0x2061, 0x2062, 0x2062, 0x2063, 0x2063, 0x206a, 0x206f, 0xfeff, 0xfeff, 0xfff9, 0xfffc, 0x1d173, 0x1d17a];
|
|
468
|
+
const non_character_codepoints = [0xfdd0, 0xfdef, 0xfffe, 0xffff, 0x1fffe, 0x1ffff, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xefffe, 0xeffff, 0x10fffe, 0x10ffff];
|
|
469
|
+
const prohibited_characters = [0, 0x001f, 0x007f, 0x007f, 0x0340, 0x0340, 0x0341, 0x0341, 0x200e, 0x200e, 0x200f, 0x200f, 0x202a, 0x202a, 0x202b, 0x202b, 0x202c, 0x202c, 0x202d, 0x202d, 0x202e, 0x202e, 0x206a, 0x206a, 0x206b, 0x206b, 0x206c, 0x206c, 0x206d, 0x206d, 0x206e, 0x206e, 0x206f, 0x206f, 0x2ff0, 0x2ffb, 0xd800, 0xdfff, 0xe000, 0xf8ff, 0xfff9, 0xfff9, 0xfffa, 0xfffa, 0xfffb, 0xfffb, 0xfffc, 0xfffc, 0xfffd, 0xfffd, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xf0000, 0xffffd, 0x100000, 0x10fffd];
|
|
559
470
|
const isProhibitedCharacter = character => inRange(character, non_ASCII_space_characters) || inRange(character, prohibited_characters) || inRange(character, non_ASCII_controls_characters) || inRange(character, non_character_codepoints);
|
|
560
|
-
|
|
561
|
-
// prettier-ignore-start
|
|
562
|
-
/**
|
|
563
|
-
* D.1 Characters with bidirectional property "R" or "AL"
|
|
564
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-D.1
|
|
565
|
-
*/
|
|
566
471
|
const bidirectional_r_al = [0x05be, 0x05be, 0x05c0, 0x05c0, 0x05c3, 0x05c3, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x061b, 0x061b, 0x061f, 0x061f, 0x0621, 0x063a, 0x0640, 0x064a, 0x066d, 0x066f, 0x0671, 0x06d5, 0x06dd, 0x06dd, 0x06e5, 0x06e6, 0x06fa, 0x06fe, 0x0700, 0x070d, 0x0710, 0x0710, 0x0712, 0x072c, 0x0780, 0x07a5, 0x07b1, 0x07b1, 0x200f, 0x200f, 0xfb1d, 0xfb1d, 0xfb1f, 0xfb28, 0xfb2a, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfc, 0xfe70, 0xfe74, 0xfe76, 0xfefc];
|
|
567
|
-
// prettier-ignore-end
|
|
568
|
-
|
|
569
472
|
const isBidirectionalRAL = character => inRange(character, bidirectional_r_al);
|
|
570
|
-
|
|
571
|
-
// prettier-ignore-start
|
|
572
|
-
/**
|
|
573
|
-
* D.2 Characters with bidirectional property "L"
|
|
574
|
-
* @link https://tools.ietf.org/html/rfc3454#appendix-D.2
|
|
575
|
-
*/
|
|
576
473
|
const bidirectional_l = [0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, 0x00ba, 0x00ba, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x0220, 0x0222, 0x0233, 0x0250, 0x02ad, 0x02b0, 0x02b8, 0x02bb, 0x02c1, 0x02d0, 0x02d1, 0x02e0, 0x02e4, 0x02ee, 0x02ee, 0x037a, 0x037a, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, 0x03d0, 0x03f5, 0x0400, 0x0482, 0x048a, 0x04ce, 0x04d0, 0x04f5, 0x04f8, 0x04f9, 0x0500, 0x050f, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x0589, 0x0903, 0x0903, 0x0905, 0x0939, 0x093d, 0x0940, 0x0949, 0x094c, 0x0950, 0x0950, 0x0958, 0x0961, 0x0964, 0x0970, 0x0982, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09be, 0x09c0, 0x09c7, 0x09c8, 0x09cb, 0x09cc, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e1, 0x09e6, 0x09f1, 0x09f4, 0x09fa, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3e, 0x0a40, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a6f, 0x0a72, 0x0a74, 0x0a83, 0x0a83, 0x0a85, 0x0a8b, 0x0a8d, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abd, 0x0ac0, 0x0ac9, 0x0ac9, 0x0acb, 0x0acc, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae0, 0x0ae6, 0x0aef, 0x0b02, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b36, 0x0b39, 0x0b3d, 0x0b3e, 0x0b40, 0x0b40, 0x0b47, 0x0b48, 0x0b4b, 0x0b4c, 0x0b57, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b66, 0x0b70, 0x0b83, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb5, 0x0bb7, 0x0bb9, 0x0bbe, 0x0bbf, 0x0bc1, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcc, 0x0bd7, 0x0bd7, 0x0be7, 0x0bf2, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c41, 0x0c44, 0x0c60, 0x0c61, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbe, 0x0cbe, 0x0cc0, 0x0cc4, 0x0cc7, 0x0cc8, 0x0cca, 0x0ccb, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0ce6, 0x0cef, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, 0x0d3e, 0x0d40, 0x0d46, 0x0d48, 0x0d4a, 0x0d4c, 0x0d57, 0x0d57, 0x0d60, 0x0d61, 0x0d66, 0x0d6f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dcf, 0x0dd1, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e30, 0x0e32, 0x0e33, 0x0e40, 0x0e46, 0x0e4f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb0, 0x0eb2, 0x0eb3, 0x0ebd, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f17, 0x0f1a, 0x0f34, 0x0f36, 0x0f36, 0x0f38, 0x0f38, 0x0f3e, 0x0f47, 0x0f49, 0x0f6a, 0x0f7f, 0x0f7f, 0x0f85, 0x0f85, 0x0f88, 0x0f8b, 0x0fbe, 0x0fc5, 0x0fc7, 0x0fcc, 0x0fcf, 0x0fcf, 0x1000, 0x1021, 0x1023, 0x1027, 0x1029, 0x102a, 0x102c, 0x102c, 0x1031, 0x1031, 0x1038, 0x1038, 0x1040, 0x1057, 0x10a0, 0x10c5, 0x10d0, 0x10f8, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, 0x1200, 0x1206, 0x1208, 0x1246, 0x1248, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1286, 0x1288, 0x1288, 0x128a, 0x128d, 0x1290, 0x12ae, 0x12b0, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12ce, 0x12d0, 0x12d6, 0x12d8, 0x12ee, 0x12f0, 0x130e, 0x1310, 0x1310, 0x1312, 0x1315, 0x1318, 0x131e, 0x1320, 0x1346, 0x1348, 0x135a, 0x1361, 0x137c, 0x13a0, 0x13f4, 0x1401, 0x1676, 0x1681, 0x169a, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1711, 0x1720, 0x1731, 0x1735, 0x1736, 0x1740, 0x1751, 0x1760, 0x176c, 0x176e, 0x1770, 0x1780, 0x17b6, 0x17be, 0x17c5, 0x17c7, 0x17c8, 0x17d4, 0x17da, 0x17dc, 0x17dc, 0x17e0, 0x17e9, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18a8, 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, 0x200e, 0x200e, 0x2071, 0x2071, 0x207f, 0x207f, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2119, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x212d, 0x212f, 0x2131, 0x2133, 0x2139, 0x213d, 0x213f, 0x2145, 0x2149, 0x2160, 0x2183, 0x2336, 0x237a, 0x2395, 0x2395, 0x249c, 0x24e9, 0x3005, 0x3007, 0x3021, 0x3029, 0x3031, 0x3035, 0x3038, 0x303c, 0x3041, 0x3096, 0x309d, 0x309f, 0x30a1, 0x30fa, 0x30fc, 0x30ff, 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x31b7, 0x31f0, 0x321c, 0x3220, 0x3243, 0x3260, 0x327b, 0x327f, 0x32b0, 0x32c0, 0x32cb, 0x32d0, 0x32fe, 0x3300, 0x3376, 0x337b, 0x33dd, 0x33e0, 0x33fe, 0x3400, 0x4db5, 0x4e00, 0x9fa5, 0xa000, 0xa48c, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfa30, 0xfa6a, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xff21, 0xff3a, 0xff41, 0xff5a, 0xff66, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10400, 0x10425, 0x10428, 0x1044d, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d12a, 0x1d166, 0x1d16a, 0x1d172, 0x1d183, 0x1d184, 0x1d18c, 0x1d1a9, 0x1d1ae, 0x1d1dd, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c0, 0x1d4c2, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a3, 0x1d6a8, 0x1d7c9, 0x20000, 0x2a6d6, 0x2f800, 0x2fa1d, 0xf0000, 0xffffd, 0x100000, 0x10fffd];
|
|
577
|
-
// prettier-ignore-end
|
|
578
|
-
|
|
579
474
|
const isBidirectionalL = character => inRange(character, bidirectional_l);
|
|
580
475
|
|
|
581
|
-
// 2.1. Mapping
|
|
582
|
-
|
|
583
|
-
/**
|
|
584
|
-
* non-ASCII space characters [StringPrep, C.1.2] that can be
|
|
585
|
-
* mapped to SPACE (U+0020)
|
|
586
|
-
*/
|
|
587
476
|
const mapping2space = isNonASCIISpaceCharacter;
|
|
588
|
-
|
|
589
|
-
/**
|
|
590
|
-
* the "commonly mapped to nothing" characters [StringPrep, B.1]
|
|
591
|
-
* that can be mapped to nothing.
|
|
592
|
-
*/
|
|
593
477
|
const mapping2nothing = isCommonlyMappedToNothing;
|
|
594
|
-
|
|
595
|
-
// utils
|
|
596
478
|
const getCodePoint = character => character.codePointAt(0);
|
|
597
479
|
const first = x => x[0];
|
|
598
480
|
const last = x => x[x.length - 1];
|
|
599
|
-
|
|
600
|
-
/**
|
|
601
|
-
* Convert provided string into an array of Unicode Code Points.
|
|
602
|
-
* Based on https://stackoverflow.com/a/21409165/1556249
|
|
603
|
-
* and https://www.npmjs.com/package/code-point-at.
|
|
604
|
-
* @param {string} input
|
|
605
|
-
* @returns {number[]}
|
|
606
|
-
*/
|
|
607
481
|
function toCodePoints(input) {
|
|
608
482
|
const codepoints = [];
|
|
609
483
|
const size = input.length;
|
|
@@ -621,14 +495,6 @@ function toCodePoints(input) {
|
|
|
621
495
|
}
|
|
622
496
|
return codepoints;
|
|
623
497
|
}
|
|
624
|
-
|
|
625
|
-
/**
|
|
626
|
-
* SASLprep.
|
|
627
|
-
* @param {string} input
|
|
628
|
-
* @param {Object} opts
|
|
629
|
-
* @param {boolean} opts.allowUnassigned
|
|
630
|
-
* @returns {string}
|
|
631
|
-
*/
|
|
632
498
|
function saslprep(input, opts = {}) {
|
|
633
499
|
if (typeof input !== 'string') {
|
|
634
500
|
throw new TypeError('Expected string.');
|
|
@@ -636,49 +502,24 @@ function saslprep(input, opts = {}) {
|
|
|
636
502
|
if (input.length === 0) {
|
|
637
503
|
return '';
|
|
638
504
|
}
|
|
639
|
-
|
|
640
|
-
// 1. Map
|
|
641
|
-
const mapped_input = toCodePoints(input)
|
|
642
|
-
// 1.1 mapping to space
|
|
643
|
-
.map(character => mapping2space(character) ? 0x20 : character)
|
|
644
|
-
// 1.2 mapping to nothing
|
|
645
|
-
.filter(character => !mapping2nothing(character));
|
|
646
|
-
|
|
647
|
-
// 2. Normalize
|
|
505
|
+
const mapped_input = toCodePoints(input).map(character => mapping2space(character) ? 0x20 : character).filter(character => !mapping2nothing(character));
|
|
648
506
|
const normalized_input = String.fromCodePoint.apply(null, mapped_input).normalize('NFKC');
|
|
649
507
|
const normalized_map = toCodePoints(normalized_input);
|
|
650
|
-
|
|
651
|
-
// 3. Prohibit
|
|
652
508
|
const hasProhibited = normalized_map.some(isProhibitedCharacter);
|
|
653
509
|
if (hasProhibited) {
|
|
654
510
|
throw new Error('Prohibited character, see https://tools.ietf.org/html/rfc4013#section-2.3');
|
|
655
511
|
}
|
|
656
|
-
|
|
657
|
-
// Unassigned Code Points
|
|
658
512
|
if (opts.allowUnassigned !== true) {
|
|
659
513
|
const hasUnassigned = normalized_map.some(isUnassignedCodePoint);
|
|
660
514
|
if (hasUnassigned) {
|
|
661
515
|
throw new Error('Unassigned code point, see https://tools.ietf.org/html/rfc4013#section-2.5');
|
|
662
516
|
}
|
|
663
517
|
}
|
|
664
|
-
|
|
665
|
-
// 4. check bidi
|
|
666
|
-
|
|
667
518
|
const hasBidiRAL = normalized_map.some(isBidirectionalRAL);
|
|
668
519
|
const hasBidiL = normalized_map.some(isBidirectionalL);
|
|
669
|
-
|
|
670
|
-
// 4.1 If a string contains any RandALCat character, the string MUST NOT
|
|
671
|
-
// contain any LCat character.
|
|
672
520
|
if (hasBidiRAL && hasBidiL) {
|
|
673
521
|
throw new Error('String must not contain RandALCat and LCat at the same time,' + ' see https://tools.ietf.org/html/rfc3454#section-6');
|
|
674
522
|
}
|
|
675
|
-
|
|
676
|
-
/**
|
|
677
|
-
* 4.2 If a string contains any RandALCat character, a RandALCat
|
|
678
|
-
* character MUST be the first character of the string, and a
|
|
679
|
-
* RandALCat character MUST be the last character of the string.
|
|
680
|
-
*/
|
|
681
|
-
|
|
682
523
|
const isFirstBidiRAL = isBidirectionalRAL(getCodePoint(first(normalized_input)));
|
|
683
524
|
const isLastBidiRAL = isBidirectionalRAL(getCodePoint(last(normalized_input)));
|
|
684
525
|
if (hasBidiRAL && !(isFirstBidiRAL && isLastBidiRAL)) {
|
|
@@ -687,15 +528,10 @@ function saslprep(input, opts = {}) {
|
|
|
687
528
|
return normalized_input;
|
|
688
529
|
}
|
|
689
530
|
|
|
690
|
-
/*
|
|
691
|
-
PDFSecurity - represents PDF security settings
|
|
692
|
-
By Yang Liu <hi@zesik.com>
|
|
693
|
-
*/
|
|
694
531
|
class PDFSecurity {
|
|
695
532
|
static generateFileID(info = {}) {
|
|
696
533
|
let infoStr = `${info.CreationDate.getTime()}\n`;
|
|
697
534
|
for (let key in info) {
|
|
698
|
-
// eslint-disable-next-line no-prototype-builtins
|
|
699
535
|
if (!info.hasOwnProperty(key)) {
|
|
700
536
|
continue;
|
|
701
537
|
}
|
|
@@ -1069,8 +905,6 @@ class PDFGradient$1 {
|
|
|
1069
905
|
}
|
|
1070
906
|
this.embedded = true;
|
|
1071
907
|
this.matrix = m;
|
|
1072
|
-
|
|
1073
|
-
// if the last stop comes before 100%, add a copy at 100%
|
|
1074
908
|
const last = this.stops[stopsLength - 1];
|
|
1075
909
|
if (last[0] < 1) {
|
|
1076
910
|
this.stops.push([1, last[1], last[2]]);
|
|
@@ -1093,14 +927,11 @@ class PDFGradient$1 {
|
|
|
1093
927
|
stops.push(fn);
|
|
1094
928
|
fn.end();
|
|
1095
929
|
}
|
|
1096
|
-
|
|
1097
|
-
// if there are only two stops, we don't need a stitching function
|
|
1098
930
|
if (stopsLength === 1) {
|
|
1099
931
|
fn = stops[0];
|
|
1100
932
|
} else {
|
|
1101
933
|
fn = this.doc.ref({
|
|
1102
934
|
FunctionType: 3,
|
|
1103
|
-
// stitching function
|
|
1104
935
|
Domain: [0, 1],
|
|
1105
936
|
Functions: stops,
|
|
1106
937
|
Bounds: bounds,
|
|
@@ -1181,7 +1012,6 @@ class PDFGradient$1 {
|
|
|
1181
1012
|
return pattern;
|
|
1182
1013
|
}
|
|
1183
1014
|
apply(stroke) {
|
|
1184
|
-
// apply gradient transform to existing document ctm
|
|
1185
1015
|
const [m0, m1, m2, m3, m4, m5] = this.doc._ctm;
|
|
1186
1016
|
const [m11, m12, m21, m22, dx, dy] = this.transform;
|
|
1187
1017
|
const m = [m0 * m11 + m2 * m12, m1 * m11 + m3 * m12, m0 * m21 + m2 * m22, m1 * m21 + m3 * m22, m0 * dx + m2 * dy + m4, m1 * dx + m3 * dy + m5];
|
|
@@ -1244,10 +1074,6 @@ var Gradient = {
|
|
|
1244
1074
|
PDFRadialGradient: PDFRadialGradient$1
|
|
1245
1075
|
};
|
|
1246
1076
|
|
|
1247
|
-
/*
|
|
1248
|
-
PDF tiling pattern support. Uncolored only.
|
|
1249
|
-
*/
|
|
1250
|
-
|
|
1251
1077
|
const underlyingColorSpaces = ['DeviceCMYK', 'DeviceRGB'];
|
|
1252
1078
|
class PDFTilingPattern$1 {
|
|
1253
1079
|
constructor(doc, bBox, xStep, yStep, stream) {
|
|
@@ -1258,23 +1084,16 @@ class PDFTilingPattern$1 {
|
|
|
1258
1084
|
this.stream = stream;
|
|
1259
1085
|
}
|
|
1260
1086
|
createPattern() {
|
|
1261
|
-
// no resources needed for our current usage
|
|
1262
|
-
// required entry
|
|
1263
1087
|
const resources = this.doc.ref();
|
|
1264
1088
|
resources.end();
|
|
1265
|
-
// apply default transform matrix (flipped in the default doc._ctm)
|
|
1266
|
-
// see document.js & gradient.js
|
|
1267
1089
|
const [m0, m1, m2, m3, m4, m5] = this.doc._ctm;
|
|
1268
1090
|
const [m11, m12, m21, m22, dx, dy] = [1, 0, 0, 1, 0, 0];
|
|
1269
1091
|
const m = [m0 * m11 + m2 * m12, m1 * m11 + m3 * m12, m0 * m21 + m2 * m22, m1 * m21 + m3 * m22, m0 * dx + m2 * dy + m4, m1 * dx + m3 * dy + m5];
|
|
1270
1092
|
const pattern = this.doc.ref({
|
|
1271
1093
|
Type: 'Pattern',
|
|
1272
1094
|
PatternType: 1,
|
|
1273
|
-
// tiling
|
|
1274
1095
|
PaintType: 2,
|
|
1275
|
-
// 1-colored, 2-uncolored
|
|
1276
1096
|
TilingType: 2,
|
|
1277
|
-
// 2-no distortion
|
|
1278
1097
|
BBox: this.bBox,
|
|
1279
1098
|
XStep: this.xStep,
|
|
1280
1099
|
YStep: this.yStep,
|
|
@@ -1285,8 +1104,6 @@ class PDFTilingPattern$1 {
|
|
|
1285
1104
|
return pattern;
|
|
1286
1105
|
}
|
|
1287
1106
|
embedPatternColorSpaces() {
|
|
1288
|
-
// map each pattern to an underlying color space
|
|
1289
|
-
// and embed on each page
|
|
1290
1107
|
underlyingColorSpaces.forEach(csName => {
|
|
1291
1108
|
const csId = this.getPatternColorSpaceId(csName);
|
|
1292
1109
|
if (this.doc.page.colorSpaces[csId]) return;
|
|
@@ -1304,24 +1121,17 @@ class PDFTilingPattern$1 {
|
|
|
1304
1121
|
this.id = 'P' + this.doc._patternCount;
|
|
1305
1122
|
this.pattern = this.createPattern();
|
|
1306
1123
|
}
|
|
1307
|
-
|
|
1308
|
-
// patterns are embedded in each page
|
|
1309
1124
|
if (!this.doc.page.patterns[this.id]) {
|
|
1310
1125
|
this.doc.page.patterns[this.id] = this.pattern;
|
|
1311
1126
|
}
|
|
1312
1127
|
}
|
|
1313
1128
|
apply(stroke, patternColor) {
|
|
1314
|
-
// do any embedding/creating that might be needed
|
|
1315
1129
|
this.embedPatternColorSpaces();
|
|
1316
1130
|
this.embed();
|
|
1317
1131
|
const normalizedColor = this.doc._normalizeColor(patternColor);
|
|
1318
1132
|
if (!normalizedColor) throw Error(`invalid pattern color. (value: ${patternColor})`);
|
|
1319
|
-
|
|
1320
|
-
// select one of the pattern color spaces
|
|
1321
1133
|
const csId = this.getPatternColorSpaceId(this.doc._getColorSpace(normalizedColor));
|
|
1322
1134
|
this.doc._setColorSpace(csId, stroke);
|
|
1323
|
-
|
|
1324
|
-
// stroke/fill using the pattern and color (in the above underlying color space)
|
|
1325
1135
|
const op = stroke ? 'SCN' : 'scn';
|
|
1326
1136
|
return this.doc.addContent(`${normalizedColor.join(' ')} /${this.id} ${op}`);
|
|
1327
1137
|
}
|
|
@@ -1341,11 +1151,10 @@ const {
|
|
|
1341
1151
|
var ColorMixin = {
|
|
1342
1152
|
initColor() {
|
|
1343
1153
|
this.spotColors = {};
|
|
1344
|
-
// The opacity dictionaries
|
|
1345
1154
|
this._opacityRegistry = {};
|
|
1346
1155
|
this._opacityCount = 0;
|
|
1347
1156
|
this._patternCount = 0;
|
|
1348
|
-
|
|
1157
|
+
this._gradCount = 0;
|
|
1349
1158
|
},
|
|
1350
1159
|
_normalizeColor(color) {
|
|
1351
1160
|
if (typeof color === 'string') {
|
|
@@ -1362,10 +1171,8 @@ var ColorMixin = {
|
|
|
1362
1171
|
}
|
|
1363
1172
|
}
|
|
1364
1173
|
if (Array.isArray(color)) {
|
|
1365
|
-
// RGB
|
|
1366
1174
|
if (color.length === 3) {
|
|
1367
1175
|
color = color.map(part => part / 255);
|
|
1368
|
-
// CMYK
|
|
1369
1176
|
} else if (color.length === 4) {
|
|
1370
1177
|
color = color.map(part => part / 100);
|
|
1371
1178
|
}
|
|
@@ -1377,12 +1184,10 @@ var ColorMixin = {
|
|
|
1377
1184
|
if (color instanceof PDFGradient) {
|
|
1378
1185
|
color.apply(stroke);
|
|
1379
1186
|
return true;
|
|
1380
|
-
// see if tiling pattern, decode & apply it it
|
|
1381
1187
|
} else if (Array.isArray(color) && color[0] instanceof PDFTilingPattern) {
|
|
1382
1188
|
color[0].apply(stroke, color[1]);
|
|
1383
1189
|
return true;
|
|
1384
1190
|
}
|
|
1385
|
-
// any other case should be a normal color and not a pattern
|
|
1386
1191
|
return this._setColorCore(color, stroke);
|
|
1387
1192
|
},
|
|
1388
1193
|
_setColorCore(color, stroke) {
|
|
@@ -1416,9 +1221,6 @@ var ColorMixin = {
|
|
|
1416
1221
|
if (set) {
|
|
1417
1222
|
this.fillOpacity(opacity);
|
|
1418
1223
|
}
|
|
1419
|
-
|
|
1420
|
-
// save this for text wrapper, which needs to reset
|
|
1421
|
-
// the fill color on new pages
|
|
1422
1224
|
this._fillColor = [color, opacity];
|
|
1423
1225
|
return this;
|
|
1424
1226
|
},
|
|
@@ -1674,7 +1476,6 @@ const parse = function (path) {
|
|
|
1674
1476
|
if (parameters[c] != null) {
|
|
1675
1477
|
params = parameters[c];
|
|
1676
1478
|
if (cmd) {
|
|
1677
|
-
// save existing command
|
|
1678
1479
|
if (curArg.length > 0) {
|
|
1679
1480
|
args[args.length] = +curArg;
|
|
1680
1481
|
}
|
|
@@ -1692,14 +1493,11 @@ const parse = function (path) {
|
|
|
1692
1493
|
continue;
|
|
1693
1494
|
}
|
|
1694
1495
|
if (args.length === params) {
|
|
1695
|
-
// handle reused commands
|
|
1696
1496
|
ret[ret.length] = {
|
|
1697
1497
|
cmd,
|
|
1698
1498
|
args
|
|
1699
1499
|
};
|
|
1700
1500
|
args = [+curArg];
|
|
1701
|
-
|
|
1702
|
-
// handle assumed commands
|
|
1703
1501
|
if (cmd === 'M') {
|
|
1704
1502
|
cmd = 'L';
|
|
1705
1503
|
}
|
|
@@ -1710,8 +1508,6 @@ const parse = function (path) {
|
|
|
1710
1508
|
args[args.length] = +curArg;
|
|
1711
1509
|
}
|
|
1712
1510
|
foundDecimal = c === '.';
|
|
1713
|
-
|
|
1714
|
-
// fix for negative numbers or repeated decimals with no delimeter between commands
|
|
1715
1511
|
curArg = ['-', '.'].includes(c) ? c : '';
|
|
1716
1512
|
} else {
|
|
1717
1513
|
curArg += c;
|
|
@@ -1720,18 +1516,13 @@ const parse = function (path) {
|
|
|
1720
1516
|
}
|
|
1721
1517
|
}
|
|
1722
1518
|
}
|
|
1723
|
-
|
|
1724
|
-
// add the last command
|
|
1725
1519
|
if (curArg.length > 0) {
|
|
1726
1520
|
if (args.length === params) {
|
|
1727
|
-
// handle reused commands
|
|
1728
1521
|
ret[ret.length] = {
|
|
1729
1522
|
cmd,
|
|
1730
1523
|
args
|
|
1731
1524
|
};
|
|
1732
1525
|
args = [+curArg];
|
|
1733
|
-
|
|
1734
|
-
// handle assumed commands
|
|
1735
1526
|
if (cmd === 'M') {
|
|
1736
1527
|
cmd = 'L';
|
|
1737
1528
|
}
|
|
@@ -1749,10 +1540,7 @@ const parse = function (path) {
|
|
|
1749
1540
|
return ret;
|
|
1750
1541
|
};
|
|
1751
1542
|
const apply = function (commands, doc) {
|
|
1752
|
-
// current point, control point, and subpath starting point
|
|
1753
1543
|
cx = cy = px = py = sx = sy = 0;
|
|
1754
|
-
|
|
1755
|
-
// run the commands
|
|
1756
1544
|
for (let i = 0; i < commands.length; i++) {
|
|
1757
1545
|
const c = commands[i];
|
|
1758
1546
|
if (typeof runners[c.cmd] === 'function') {
|
|
@@ -1916,8 +1704,6 @@ const solveArc = function (doc, x, y, coords) {
|
|
|
1916
1704
|
doc.bezierCurveTo(...bez);
|
|
1917
1705
|
}
|
|
1918
1706
|
};
|
|
1919
|
-
|
|
1920
|
-
// from Inkscape svgtopdf, thanks!
|
|
1921
1707
|
const arcToSegments = function (x, y, rx, ry, large, sweep, rotateX, ox, oy) {
|
|
1922
1708
|
const th = rotateX * (Math.PI / 180);
|
|
1923
1709
|
const sin_th = Math.sin(th);
|
|
@@ -1993,18 +1779,14 @@ class SVGPath {
|
|
|
1993
1779
|
const {
|
|
1994
1780
|
number: number$1
|
|
1995
1781
|
} = PDFObject;
|
|
1996
|
-
|
|
1997
|
-
// This constant is used to approximate a symmetrical arc using a cubic
|
|
1998
|
-
// Bezier curve.
|
|
1999
1782
|
const KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0);
|
|
2000
1783
|
var VectorMixin = {
|
|
2001
1784
|
initVector() {
|
|
2002
|
-
this._ctm = [1, 0, 0, 1, 0, 0];
|
|
2003
|
-
|
|
1785
|
+
this._ctm = [1, 0, 0, 1, 0, 0];
|
|
1786
|
+
this._ctmStack = [];
|
|
2004
1787
|
},
|
|
2005
1788
|
save() {
|
|
2006
1789
|
this._ctmStack.push(this._ctm.slice());
|
|
2007
|
-
// TODO: save/restore colorspace and styles so not setting it unnessesarily all the time?
|
|
2008
1790
|
return this.addContent('q');
|
|
2009
1791
|
},
|
|
2010
1792
|
restore() {
|
|
@@ -2077,8 +1859,6 @@ var VectorMixin = {
|
|
|
2077
1859
|
r = 0;
|
|
2078
1860
|
}
|
|
2079
1861
|
r = Math.min(r, 0.5 * w, 0.5 * h);
|
|
2080
|
-
|
|
2081
|
-
// amount to inset control points from corners (see `ellipse`)
|
|
2082
1862
|
const c = r * (1.0 - KAPPA);
|
|
2083
1863
|
this.moveTo(x + r, y);
|
|
2084
1864
|
this.lineTo(x + w - r, y);
|
|
@@ -2092,7 +1872,6 @@ var VectorMixin = {
|
|
|
2092
1872
|
return this.closePath();
|
|
2093
1873
|
},
|
|
2094
1874
|
ellipse(x, y, r1, r2) {
|
|
2095
|
-
// based on http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas/2173084#2173084
|
|
2096
1875
|
if (r2 == null) {
|
|
2097
1876
|
r2 = r1;
|
|
2098
1877
|
}
|
|
@@ -2122,10 +1901,8 @@ var VectorMixin = {
|
|
|
2122
1901
|
const HALF_PI = 0.5 * Math.PI;
|
|
2123
1902
|
let deltaAng = endAngle - startAngle;
|
|
2124
1903
|
if (Math.abs(deltaAng) > TWO_PI) {
|
|
2125
|
-
// draw only full circle if more than that is specified
|
|
2126
1904
|
deltaAng = TWO_PI;
|
|
2127
1905
|
} else if (deltaAng !== 0 && anticlockwise !== deltaAng < 0) {
|
|
2128
|
-
// necessary to flip direction of rendering
|
|
2129
1906
|
const dir = anticlockwise ? -1 : 1;
|
|
2130
1907
|
deltaAng = dir * TWO_PI + deltaAng;
|
|
2131
1908
|
}
|
|
@@ -2133,38 +1910,21 @@ var VectorMixin = {
|
|
|
2133
1910
|
const segAng = deltaAng / numSegs;
|
|
2134
1911
|
const handleLen = segAng / HALF_PI * KAPPA * radius;
|
|
2135
1912
|
let curAng = startAngle;
|
|
2136
|
-
|
|
2137
|
-
// component distances between anchor point and control point
|
|
2138
1913
|
let deltaCx = -Math.sin(curAng) * handleLen;
|
|
2139
1914
|
let deltaCy = Math.cos(curAng) * handleLen;
|
|
2140
|
-
|
|
2141
|
-
// anchor point
|
|
2142
1915
|
let ax = x + Math.cos(curAng) * radius;
|
|
2143
1916
|
let ay = y + Math.sin(curAng) * radius;
|
|
2144
|
-
|
|
2145
|
-
// calculate and render segments
|
|
2146
1917
|
this.moveTo(ax, ay);
|
|
2147
1918
|
for (let segIdx = 0; segIdx < numSegs; segIdx++) {
|
|
2148
|
-
// starting control point
|
|
2149
1919
|
const cp1x = ax + deltaCx;
|
|
2150
1920
|
const cp1y = ay + deltaCy;
|
|
2151
|
-
|
|
2152
|
-
// step angle
|
|
2153
1921
|
curAng += segAng;
|
|
2154
|
-
|
|
2155
|
-
// next anchor point
|
|
2156
1922
|
ax = x + Math.cos(curAng) * radius;
|
|
2157
1923
|
ay = y + Math.sin(curAng) * radius;
|
|
2158
|
-
|
|
2159
|
-
// next control point delta
|
|
2160
1924
|
deltaCx = -Math.sin(curAng) * handleLen;
|
|
2161
1925
|
deltaCy = Math.cos(curAng) * handleLen;
|
|
2162
|
-
|
|
2163
|
-
// ending control point
|
|
2164
1926
|
const cp2x = ax - deltaCx;
|
|
2165
1927
|
const cp2y = ay - deltaCy;
|
|
2166
|
-
|
|
2167
|
-
// render segment
|
|
2168
1928
|
this.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, ax, ay);
|
|
2169
1929
|
}
|
|
2170
1930
|
return this;
|
|
@@ -2225,9 +1985,7 @@ var VectorMixin = {
|
|
|
2225
1985
|
return this.addContent(`W${this._windingRule(rule)} n`);
|
|
2226
1986
|
},
|
|
2227
1987
|
transform(m11, m12, m21, m22, dx, dy) {
|
|
2228
|
-
// keep track of the current transformation matrix
|
|
2229
1988
|
if (m11 === 1 && m12 === 0 && m21 === 0 && m22 === 1 && dx === 0 && dy === 0) {
|
|
2230
|
-
// Ignore identity transforms
|
|
2231
1989
|
return this;
|
|
2232
1990
|
}
|
|
2233
1991
|
const m = this._ctm;
|
|
@@ -2391,7 +2149,6 @@ class AFMFont {
|
|
|
2391
2149
|
this.boundingBoxes = {};
|
|
2392
2150
|
this.kernPairs = {};
|
|
2393
2151
|
this.parse();
|
|
2394
|
-
// todo: remove charWidths since appears to not be used
|
|
2395
2152
|
this.charWidths = new Array(256);
|
|
2396
2153
|
for (let char = 0; char <= 255; char++) {
|
|
2397
2154
|
this.charWidths[char] = this.glyphWidths[characters[char]];
|
|
@@ -2498,21 +2255,17 @@ class PDFFont {
|
|
|
2498
2255
|
return;
|
|
2499
2256
|
}
|
|
2500
2257
|
this.embed();
|
|
2501
|
-
|
|
2258
|
+
this.embedded = true;
|
|
2502
2259
|
}
|
|
2503
2260
|
embed() {
|
|
2504
2261
|
throw new Error('Must be implemented by subclasses');
|
|
2505
2262
|
}
|
|
2506
|
-
lineHeight(size, includeGap) {
|
|
2507
|
-
if (includeGap == null) {
|
|
2508
|
-
includeGap = false;
|
|
2509
|
-
}
|
|
2263
|
+
lineHeight(size, includeGap = false) {
|
|
2510
2264
|
const gap = includeGap ? this.lineGap : 0;
|
|
2511
2265
|
return (this.ascender + gap - this.descender) / 1000 * size;
|
|
2512
2266
|
}
|
|
2513
2267
|
}
|
|
2514
2268
|
|
|
2515
|
-
// This insanity is so bundlers can inline the font files
|
|
2516
2269
|
const STANDARD_FONTS = {
|
|
2517
2270
|
Courier() {
|
|
2518
2271
|
return "StartFontMetrics 4.1\r\nComment Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.\r\nComment Creation Date: Thu May 1 17:27:09 1997\r\nComment UniqueID 43050\r\nComment VMusage 39754 50779\r\nFontName Courier\r\nFullName Courier\r\nFamilyName Courier\r\nWeight Medium\r\nItalicAngle 0\r\nIsFixedPitch true\r\nCharacterSet ExtendedRoman\r\nFontBBox -23 -250 715 805 \r\nUnderlinePosition -100\r\nUnderlineThickness 50\r\nVersion 003.000\r\nNotice Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.\r\nEncodingScheme AdobeStandardEncoding\r\nCapHeight 562\r\nXHeight 426\r\nAscender 629\r\nDescender -157\r\nStdHW 51\r\nStdVW 51\r\nStartCharMetrics 315\r\nC 32 ; WX 600 ; N space ; B 0 0 0 0 ;\r\nC 33 ; WX 600 ; N exclam ; B 236 -15 364 572 ;\r\nC 34 ; WX 600 ; N quotedbl ; B 187 328 413 562 ;\r\nC 35 ; WX 600 ; N numbersign ; B 93 -32 507 639 ;\r\nC 36 ; WX 600 ; N dollar ; B 105 -126 496 662 ;\r\nC 37 ; WX 600 ; N percent ; B 81 -15 518 622 ;\r\nC 38 ; WX 600 ; N ampersand ; B 63 -15 538 543 ;\r\nC 39 ; WX 600 ; N quoteright ; B 213 328 376 562 ;\r\nC 40 ; WX 600 ; N parenleft ; B 269 -108 440 622 ;\r\nC 41 ; WX 600 ; N parenright ; B 160 -108 331 622 ;\r\nC 42 ; WX 600 ; N asterisk ; B 116 257 484 607 ;\r\nC 43 ; WX 600 ; N plus ; B 80 44 520 470 ;\r\nC 44 ; WX 600 ; N comma ; B 181 -112 344 122 ;\r\nC 45 ; WX 600 ; N hyphen ; B 103 231 497 285 ;\r\nC 46 ; WX 600 ; N period ; B 229 -15 371 109 ;\r\nC 47 ; WX 600 ; N slash ; B 125 -80 475 629 ;\r\nC 48 ; WX 600 ; N zero ; B 106 -15 494 622 ;\r\nC 49 ; WX 600 ; N one ; B 96 0 505 622 ;\r\nC 50 ; WX 600 ; N two ; B 70 0 471 622 ;\r\nC 51 ; WX 600 ; N three ; B 75 -15 466 622 ;\r\nC 52 ; WX 600 ; N four ; B 78 0 500 622 ;\r\nC 53 ; WX 600 ; N five ; B 92 -15 497 607 ;\r\nC 54 ; WX 600 ; N six ; B 111 -15 497 622 ;\r\nC 55 ; WX 600 ; N seven ; B 82 0 483 607 ;\r\nC 56 ; WX 600 ; N eight ; B 102 -15 498 622 ;\r\nC 57 ; WX 600 ; N nine ; B 96 -15 489 622 ;\r\nC 58 ; WX 600 ; N colon ; B 229 -15 371 385 ;\r\nC 59 ; WX 600 ; N semicolon ; B 181 -112 371 385 ;\r\nC 60 ; WX 600 ; N less ; B 41 42 519 472 ;\r\nC 61 ; WX 600 ; N equal ; B 80 138 520 376 ;\r\nC 62 ; WX 600 ; N greater ; B 66 42 544 472 ;\r\nC 63 ; WX 600 ; N question ; B 129 -15 492 572 ;\r\nC 64 ; WX 600 ; N at ; B 77 -15 533 622 ;\r\nC 65 ; WX 600 ; N A ; B 3 0 597 562 ;\r\nC 66 ; WX 600 ; N B ; B 43 0 559 562 ;\r\nC 67 ; WX 600 ; N C ; B 41 -18 540 580 ;\r\nC 68 ; WX 600 ; N D ; B 43 0 574 562 ;\r\nC 69 ; WX 600 ; N E ; B 53 0 550 562 ;\r\nC 70 ; WX 600 ; N F ; B 53 0 545 562 ;\r\nC 71 ; WX 600 ; N G ; B 31 -18 575 580 ;\r\nC 72 ; WX 600 ; N H ; B 32 0 568 562 ;\r\nC 73 ; WX 600 ; N I ; B 96 0 504 562 ;\r\nC 74 ; WX 600 ; N J ; B 34 -18 566 562 ;\r\nC 75 ; WX 600 ; N K ; B 38 0 582 562 ;\r\nC 76 ; WX 600 ; N L ; B 47 0 554 562 ;\r\nC 77 ; WX 600 ; N M ; B 4 0 596 562 ;\r\nC 78 ; WX 600 ; N N ; B 7 -13 593 562 ;\r\nC 79 ; WX 600 ; N O ; B 43 -18 557 580 ;\r\nC 80 ; WX 600 ; N P ; B 79 0 558 562 ;\r\nC 81 ; WX 600 ; N Q ; B 43 -138 557 580 ;\r\nC 82 ; WX 600 ; N R ; B 38 0 588 562 ;\r\nC 83 ; WX 600 ; N S ; B 72 -20 529 580 ;\r\nC 84 ; WX 600 ; N T ; B 38 0 563 562 ;\r\nC 85 ; WX 600 ; N U ; B 17 -18 583 562 ;\r\nC 86 ; WX 600 ; N V ; B -4 -13 604 562 ;\r\nC 87 ; WX 600 ; N W ; B -3 -13 603 562 ;\r\nC 88 ; WX 600 ; N X ; B 23 0 577 562 ;\r\nC 89 ; WX 600 ; N Y ; B 24 0 576 562 ;\r\nC 90 ; WX 600 ; N Z ; B 86 0 514 562 ;\r\nC 91 ; WX 600 ; N bracketleft ; B 269 -108 442 622 ;\r\nC 92 ; WX 600 ; N backslash ; B 118 -80 482 629 ;\r\nC 93 ; WX 600 ; N bracketright ; B 158 -108 331 622 ;\r\nC 94 ; WX 600 ; N asciicircum ; B 94 354 506 622 ;\r\nC 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ;\r\nC 96 ; WX 600 ; N quoteleft ; B 224 328 387 562 ;\r\nC 97 ; WX 600 ; N a ; B 53 -15 559 441 ;\r\nC 98 ; WX 600 ; N b ; B 14 -15 575 629 ;\r\nC 99 ; WX 600 ; N c ; B 66 -15 529 441 ;\r\nC 100 ; WX 600 ; N d ; B 45 -15 591 629 ;\r\nC 101 ; WX 600 ; N e ; B 66 -15 548 441 ;\r\nC 102 ; WX 600 ; N f ; B 114 0 531 629 ; L i fi ; L l fl ;\r\nC 103 ; WX 600 ; N g ; B 45 -157 566 441 ;\r\nC 104 ; WX 600 ; N h ; B 18 0 582 629 ;\r\nC 105 ; WX 600 ; N i ; B 95 0 505 657 ;\r\nC 106 ; WX 600 ; N j ; B 82 -157 410 657 ;\r\nC 107 ; WX 600 ; N k ; B 43 0 580 629 ;\r\nC 108 ; WX 600 ; N l ; B 95 0 505 629 ;\r\nC 109 ; WX 600 ; N m ; B -5 0 605 441 ;\r\nC 110 ; WX 600 ; N n ; B 26 0 575 441 ;\r\nC 111 ; WX 600 ; N o ; B 62 -15 538 441 ;\r\nC 112 ; WX 600 ; N p ; B 9 -157 555 441 ;\r\nC 113 ; WX 600 ; N q ; B 45 -157 591 441 ;\r\nC 114 ; WX 600 ; N r ; B 60 0 559 441 ;\r\nC 115 ; WX 600 ; N s ; B 80 -15 513 441 ;\r\nC 116 ; WX 600 ; N t ; B 87 -15 530 561 ;\r\nC 117 ; WX 600 ; N u ; B 21 -15 562 426 ;\r\nC 118 ; WX 600 ; N v ; B 10 -10 590 426 ;\r\nC 119 ; WX 600 ; N w ; B -4 -10 604 426 ;\r\nC 120 ; WX 600 ; N x ; B 20 0 580 426 ;\r\nC 121 ; WX 600 ; N y ; B 7 -157 592 426 ;\r\nC 122 ; WX 600 ; N z ; B 99 0 502 426 ;\r\nC 123 ; WX 600 ; N braceleft ; B 182 -108 437 622 ;\r\nC 124 ; WX 600 ; N bar ; B 275 -250 326 750 ;\r\nC 125 ; WX 600 ; N braceright ; B 163 -108 418 622 ;\r\nC 126 ; WX 600 ; N asciitilde ; B 63 197 540 320 ;\r\nC 161 ; WX 600 ; N exclamdown ; B 236 -157 364 430 ;\r\nC 162 ; WX 600 ; N cent ; B 96 -49 500 614 ;\r\nC 163 ; WX 600 ; N sterling ; B 84 -21 521 611 ;\r\nC 164 ; WX 600 ; N fraction ; B 92 -57 509 665 ;\r\nC 165 ; WX 600 ; N yen ; B 26 0 574 562 ;\r\nC 166 ; WX 600 ; N florin ; B 4 -143 539 622 ;\r\nC 167 ; WX 600 ; N section ; B 113 -78 488 580 ;\r\nC 168 ; WX 600 ; N currency ; B 73 58 527 506 ;\r\nC 169 ; WX 600 ; N quotesingle ; B 259 328 341 562 ;\r\nC 170 ; WX 600 ; N quotedblleft ; B 143 328 471 562 ;\r\nC 171 ; WX 600 ; N guillemotleft ; B 37 70 563 446 ;\r\nC 172 ; WX 600 ; N guilsinglleft ; B 149 70 451 446 ;\r\nC 173 ; WX 600 ; N guilsinglright ; B 149 70 451 446 ;\r\nC 174 ; WX 600 ; N fi ; B 3 0 597 629 ;\r\nC 175 ; WX 600 ; N fl ; B 3 0 597 629 ;\r\nC 177 ; WX 600 ; N endash ; B 75 231 525 285 ;\r\nC 178 ; WX 600 ; N dagger ; B 141 -78 459 580 ;\r\nC 179 ; WX 600 ; N daggerdbl ; B 141 -78 459 580 ;\r\nC 180 ; WX 600 ; N periodcentered ; B 222 189 378 327 ;\r\nC 182 ; WX 600 ; N paragraph ; B 50 -78 511 562 ;\r\nC 183 ; WX 600 ; N bullet ; B 172 130 428 383 ;\r\nC 184 ; WX 600 ; N quotesinglbase ; B 213 -134 376 100 ;\r\nC 185 ; WX 600 ; N quotedblbase ; B 143 -134 457 100 ;\r\nC 186 ; WX 600 ; N quotedblright ; B 143 328 457 562 ;\r\nC 187 ; WX 600 ; N guillemotright ; B 37 70 563 446 ;\r\nC 188 ; WX 600 ; N ellipsis ; B 37 -15 563 111 ;\r\nC 189 ; WX 600 ; N perthousand ; B 3 -15 600 622 ;\r\nC 191 ; WX 600 ; N questiondown ; B 108 -157 471 430 ;\r\nC 193 ; WX 600 ; N grave ; B 151 497 378 672 ;\r\nC 194 ; WX 600 ; N acute ; B 242 497 469 672 ;\r\nC 195 ; WX 600 ; N circumflex ; B 124 477 476 654 ;\r\nC 196 ; WX 600 ; N tilde ; B 105 489 503 606 ;\r\nC 197 ; WX 600 ; N macron ; B 120 525 480 565 ;\r\nC 198 ; WX 600 ; N breve ; B 153 501 447 609 ;\r\nC 199 ; WX 600 ; N dotaccent ; B 249 537 352 640 ;\r\nC 200 ; WX 600 ; N dieresis ; B 148 537 453 640 ;\r\nC 202 ; WX 600 ; N ring ; B 218 463 382 627 ;\r\nC 203 ; WX 600 ; N cedilla ; B 224 -151 362 10 ;\r\nC 205 ; WX 600 ; N hungarumlaut ; B 133 497 540 672 ;\r\nC 206 ; WX 600 ; N ogonek ; B 211 -172 407 4 ;\r\nC 207 ; WX 600 ; N caron ; B 124 492 476 669 ;\r\nC 208 ; WX 600 ; N emdash ; B 0 231 600 285 ;\r\nC 225 ; WX 600 ; N AE ; B 3 0 550 562 ;\r\nC 227 ; WX 600 ; N ordfeminine ; B 156 249 442 580 ;\r\nC 232 ; WX 600 ; N Lslash ; B 47 0 554 562 ;\r\nC 233 ; WX 600 ; N Oslash ; B 43 -80 557 629 ;\r\nC 234 ; WX 600 ; N OE ; B 7 0 567 562 ;\r\nC 235 ; WX 600 ; N ordmasculine ; B 157 249 443 580 ;\r\nC 241 ; WX 600 ; N ae ; B 19 -15 570 441 ;\r\nC 245 ; WX 600 ; N dotlessi ; B 95 0 505 426 ;\r\nC 248 ; WX 600 ; N lslash ; B 95 0 505 629 ;\r\nC 249 ; WX 600 ; N oslash ; B 62 -80 538 506 ;\r\nC 250 ; WX 600 ; N oe ; B 19 -15 559 441 ;\r\nC 251 ; WX 600 ; N germandbls ; B 48 -15 588 629 ;\r\nC -1 ; WX 600 ; N Idieresis ; B 96 0 504 753 ;\r\nC -1 ; WX 600 ; N eacute ; B 66 -15 548 672 ;\r\nC -1 ; WX 600 ; N abreve ; B 53 -15 559 609 ;\r\nC -1 ; WX 600 ; N uhungarumlaut ; B 21 -15 580 672 ;\r\nC -1 ; WX 600 ; N ecaron ; B 66 -15 548 669 ;\r\nC -1 ; WX 600 ; N Ydieresis ; B 24 0 576 753 ;\r\nC -1 ; WX 600 ; N divide ; B 87 48 513 467 ;\r\nC -1 ; WX 600 ; N Yacute ; B 24 0 576 805 ;\r\nC -1 ; WX 600 ; N Acircumflex ; B 3 0 597 787 ;\r\nC -1 ; WX 600 ; N aacute ; B 53 -15 559 672 ;\r\nC -1 ; WX 600 ; N Ucircumflex ; B 17 -18 583 787 ;\r\nC -1 ; WX 600 ; N yacute ; B 7 -157 592 672 ;\r\nC -1 ; WX 600 ; N scommaaccent ; B 80 -250 513 441 ;\r\nC -1 ; WX 600 ; N ecircumflex ; B 66 -15 548 654 ;\r\nC -1 ; WX 600 ; N Uring ; B 17 -18 583 760 ;\r\nC -1 ; WX 600 ; N Udieresis ; B 17 -18 583 753 ;\r\nC -1 ; WX 600 ; N aogonek ; B 53 -172 587 441 ;\r\nC -1 ; WX 600 ; N Uacute ; B 17 -18 583 805 ;\r\nC -1 ; WX 600 ; N uogonek ; B 21 -172 590 426 ;\r\nC -1 ; WX 600 ; N Edieresis ; B 53 0 550 753 ;\r\nC -1 ; WX 600 ; N Dcroat ; B 30 0 574 562 ;\r\nC -1 ; WX 600 ; N commaaccent ; B 198 -250 335 -58 ;\r\nC -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ;\r\nC -1 ; WX 600 ; N Emacron ; B 53 0 550 698 ;\r\nC -1 ; WX 600 ; N ccaron ; B 66 -15 529 669 ;\r\nC -1 ; WX 600 ; N aring ; B 53 -15 559 627 ;\r\nC -1 ; WX 600 ; N Ncommaaccent ; B 7 -250 593 562 ;\r\nC -1 ; WX 600 ; N lacute ; B 95 0 505 805 ;\r\nC -1 ; WX 600 ; N agrave ; B 53 -15 559 672 ;\r\nC -1 ; WX 600 ; N Tcommaaccent ; B 38 -250 563 562 ;\r\nC -1 ; WX 600 ; N Cacute ; B 41 -18 540 805 ;\r\nC -1 ; WX 600 ; N atilde ; B 53 -15 559 606 ;\r\nC -1 ; WX 600 ; N Edotaccent ; B 53 0 550 753 ;\r\nC -1 ; WX 600 ; N scaron ; B 80 -15 513 669 ;\r\nC -1 ; WX 600 ; N scedilla ; B 80 -151 513 441 ;\r\nC -1 ; WX 600 ; N iacute ; B 95 0 505 672 ;\r\nC -1 ; WX 600 ; N lozenge ; B 18 0 443 706 ;\r\nC -1 ; WX 600 ; N Rcaron ; B 38 0 588 802 ;\r\nC -1 ; WX 600 ; N Gcommaaccent ; B 31 -250 575 580 ;\r\nC -1 ; WX 600 ; N ucircumflex ; B 21 -15 562 654 ;\r\nC -1 ; WX 600 ; N acircumflex ; B 53 -15 559 654 ;\r\nC -1 ; WX 600 ; N Amacron ; B 3 0 597 698 ;\r\nC -1 ; WX 600 ; N rcaron ; B 60 0 559 669 ;\r\nC -1 ; WX 600 ; N ccedilla ; B 66 -151 529 441 ;\r\nC -1 ; WX 600 ; N Zdotaccent ; B 86 0 514 753 ;\r\nC -1 ; WX 600 ; N Thorn ; B 79 0 538 562 ;\r\nC -1 ; WX 600 ; N Omacron ; B 43 -18 557 698 ;\r\nC -1 ; WX 600 ; N Racute ; B 38 0 588 805 ;\r\nC -1 ; WX 600 ; N Sacute ; B 72 -20 529 805 ;\r\nC -1 ; WX 600 ; N dcaron ; B 45 -15 715 629 ;\r\nC -1 ; WX 600 ; N Umacron ; B 17 -18 583 698 ;\r\nC -1 ; WX 600 ; N uring ; B 21 -15 562 627 ;\r\nC -1 ; WX 600 ; N threesuperior ; B 155 240 406 622 ;\r\nC -1 ; WX 600 ; N Ograve ; B 43 -18 557 805 ;\r\nC -1 ; WX 600 ; N Agrave ; B 3 0 597 805 ;\r\nC -1 ; WX 600 ; N Abreve ; B 3 0 597 732 ;\r\nC -1 ; WX 600 ; N multiply ; B 87 43 515 470 ;\r\nC -1 ; WX 600 ; N uacute ; B 21 -15 562 672 ;\r\nC -1 ; WX 600 ; N Tcaron ; B 38 0 563 802 ;\r\nC -1 ; WX 600 ; N partialdiff ; B 17 -38 459 710 ;\r\nC -1 ; WX 600 ; N ydieresis ; B 7 -157 592 620 ;\r\nC -1 ; WX 600 ; N Nacute ; B 7 -13 593 805 ;\r\nC -1 ; WX 600 ; N icircumflex ; B 94 0 505 654 ;\r\nC -1 ; WX 600 ; N Ecircumflex ; B 53 0 550 787 ;\r\nC -1 ; WX 600 ; N adieresis ; B 53 -15 559 620 ;\r\nC -1 ; WX 600 ; N edieresis ; B 66 -15 548 620 ;\r\nC -1 ; WX 600 ; N cacute ; B 66 -15 529 672 ;\r\nC -1 ; WX 600 ; N nacute ; B 26 0 575 672 ;\r\nC -1 ; WX 600 ; N umacron ; B 21 -15 562 565 ;\r\nC -1 ; WX 600 ; N Ncaron ; B 7 -13 593 802 ;\r\nC -1 ; WX 600 ; N Iacute ; B 96 0 504 805 ;\r\nC -1 ; WX 600 ; N plusminus ; B 87 44 513 558 ;\r\nC -1 ; WX 600 ; N brokenbar ; B 275 -175 326 675 ;\r\nC -1 ; WX 600 ; N registered ; B 0 -18 600 580 ;\r\nC -1 ; WX 600 ; N Gbreve ; B 31 -18 575 732 ;\r\nC -1 ; WX 600 ; N Idotaccent ; B 96 0 504 753 ;\r\nC -1 ; WX 600 ; N summation ; B 15 -10 585 706 ;\r\nC -1 ; WX 600 ; N Egrave ; B 53 0 550 805 ;\r\nC -1 ; WX 600 ; N racute ; B 60 0 559 672 ;\r\nC -1 ; WX 600 ; N omacron ; B 62 -15 538 565 ;\r\nC -1 ; WX 600 ; N Zacute ; B 86 0 514 805 ;\r\nC -1 ; WX 600 ; N Zcaron ; B 86 0 514 802 ;\r\nC -1 ; WX 600 ; N greaterequal ; B 98 0 502 710 ;\r\nC -1 ; WX 600 ; N Eth ; B 30 0 574 562 ;\r\nC -1 ; WX 600 ; N Ccedilla ; B 41 -151 540 580 ;\r\nC -1 ; WX 600 ; N lcommaaccent ; B 95 -250 505 629 ;\r\nC -1 ; WX 600 ; N tcaron ; B 87 -15 530 717 ;\r\nC -1 ; WX 600 ; N eogonek ; B 66 -172 548 441 ;\r\nC -1 ; WX 600 ; N Uogonek ; B 17 -172 583 562 ;\r\nC -1 ; WX 600 ; N Aacute ; B 3 0 597 805 ;\r\nC -1 ; WX 600 ; N Adieresis ; B 3 0 597 753 ;\r\nC -1 ; WX 600 ; N egrave ; B 66 -15 548 672 ;\r\nC -1 ; WX 600 ; N zacute ; B 99 0 502 672 ;\r\nC -1 ; WX 600 ; N iogonek ; B 95 -172 505 657 ;\r\nC -1 ; WX 600 ; N Oacute ; B 43 -18 557 805 ;\r\nC -1 ; WX 600 ; N oacute ; B 62 -15 538 672 ;\r\nC -1 ; WX 600 ; N amacron ; B 53 -15 559 565 ;\r\nC -1 ; WX 600 ; N sacute ; B 80 -15 513 672 ;\r\nC -1 ; WX 600 ; N idieresis ; B 95 0 505 620 ;\r\nC -1 ; WX 600 ; N Ocircumflex ; B 43 -18 557 787 ;\r\nC -1 ; WX 600 ; N Ugrave ; B 17 -18 583 805 ;\r\nC -1 ; WX 600 ; N Delta ; B 6 0 598 688 ;\r\nC -1 ; WX 600 ; N thorn ; B -6 -157 555 629 ;\r\nC -1 ; WX 600 ; N twosuperior ; B 177 249 424 622 ;\r\nC -1 ; WX 600 ; N Odieresis ; B 43 -18 557 753 ;\r\nC -1 ; WX 600 ; N mu ; B 21 -157 562 426 ;\r\nC -1 ; WX 600 ; N igrave ; B 95 0 505 672 ;\r\nC -1 ; WX 600 ; N ohungarumlaut ; B 62 -15 580 672 ;\r\nC -1 ; WX 600 ; N Eogonek ; B 53 -172 561 562 ;\r\nC -1 ; WX 600 ; N dcroat ; B 45 -15 591 629 ;\r\nC -1 ; WX 600 ; N threequarters ; B 8 -56 593 666 ;\r\nC -1 ; WX 600 ; N Scedilla ; B 72 -151 529 580 ;\r\nC -1 ; WX 600 ; N lcaron ; B 95 0 533 629 ;\r\nC -1 ; WX 600 ; N Kcommaaccent ; B 38 -250 582 562 ;\r\nC -1 ; WX 600 ; N Lacute ; B 47 0 554 805 ;\r\nC -1 ; WX 600 ; N trademark ; B -23 263 623 562 ;\r\nC -1 ; WX 600 ; N edotaccent ; B 66 -15 548 620 ;\r\nC -1 ; WX 600 ; N Igrave ; B 96 0 504 805 ;\r\nC -1 ; WX 600 ; N Imacron ; B 96 0 504 698 ;\r\nC -1 ; WX 600 ; N Lcaron ; B 47 0 554 562 ;\r\nC -1 ; WX 600 ; N onehalf ; B 0 -57 611 665 ;\r\nC -1 ; WX 600 ; N lessequal ; B 98 0 502 710 ;\r\nC -1 ; WX 600 ; N ocircumflex ; B 62 -15 538 654 ;\r\nC -1 ; WX 600 ; N ntilde ; B 26 0 575 606 ;\r\nC -1 ; WX 600 ; N Uhungarumlaut ; B 17 -18 590 805 ;\r\nC -1 ; WX 600 ; N Eacute ; B 53 0 550 805 ;\r\nC -1 ; WX 600 ; N emacron ; B 66 -15 548 565 ;\r\nC -1 ; WX 600 ; N gbreve ; B 45 -157 566 609 ;\r\nC -1 ; WX 600 ; N onequarter ; B 0 -57 600 665 ;\r\nC -1 ; WX 600 ; N Scaron ; B 72 -20 529 802 ;\r\nC -1 ; WX 600 ; N Scommaaccent ; B 72 -250 529 580 ;\r\nC -1 ; WX 600 ; N Ohungarumlaut ; B 43 -18 580 805 ;\r\nC -1 ; WX 600 ; N degree ; B 123 269 477 622 ;\r\nC -1 ; WX 600 ; N ograve ; B 62 -15 538 672 ;\r\nC -1 ; WX 600 ; N Ccaron ; B 41 -18 540 802 ;\r\nC -1 ; WX 600 ; N ugrave ; B 21 -15 562 672 ;\r\nC -1 ; WX 600 ; N radical ; B 3 -15 597 792 ;\r\nC -1 ; WX 600 ; N Dcaron ; B 43 0 574 802 ;\r\nC -1 ; WX 600 ; N rcommaaccent ; B 60 -250 559 441 ;\r\nC -1 ; WX 600 ; N Ntilde ; B 7 -13 593 729 ;\r\nC -1 ; WX 600 ; N otilde ; B 62 -15 538 606 ;\r\nC -1 ; WX 600 ; N Rcommaaccent ; B 38 -250 588 562 ;\r\nC -1 ; WX 600 ; N Lcommaaccent ; B 47 -250 554 562 ;\r\nC -1 ; WX 600 ; N Atilde ; B 3 0 597 729 ;\r\nC -1 ; WX 600 ; N Aogonek ; B 3 -172 608 562 ;\r\nC -1 ; WX 600 ; N Aring ; B 3 0 597 750 ;\r\nC -1 ; WX 600 ; N Otilde ; B 43 -18 557 729 ;\r\nC -1 ; WX 600 ; N zdotaccent ; B 99 0 502 620 ;\r\nC -1 ; WX 600 ; N Ecaron ; B 53 0 550 802 ;\r\nC -1 ; WX 600 ; N Iogonek ; B 96 -172 504 562 ;\r\nC -1 ; WX 600 ; N kcommaaccent ; B 43 -250 580 629 ;\r\nC -1 ; WX 600 ; N minus ; B 80 232 520 283 ;\r\nC -1 ; WX 600 ; N Icircumflex ; B 96 0 504 787 ;\r\nC -1 ; WX 600 ; N ncaron ; B 26 0 575 669 ;\r\nC -1 ; WX 600 ; N tcommaaccent ; B 87 -250 530 561 ;\r\nC -1 ; WX 600 ; N logicalnot ; B 87 108 513 369 ;\r\nC -1 ; WX 600 ; N odieresis ; B 62 -15 538 620 ;\r\nC -1 ; WX 600 ; N udieresis ; B 21 -15 562 620 ;\r\nC -1 ; WX 600 ; N notequal ; B 15 -16 540 529 ;\r\nC -1 ; WX 600 ; N gcommaaccent ; B 45 -157 566 708 ;\r\nC -1 ; WX 600 ; N eth ; B 62 -15 538 629 ;\r\nC -1 ; WX 600 ; N zcaron ; B 99 0 502 669 ;\r\nC -1 ; WX 600 ; N ncommaaccent ; B 26 -250 575 441 ;\r\nC -1 ; WX 600 ; N onesuperior ; B 172 249 428 622 ;\r\nC -1 ; WX 600 ; N imacron ; B 95 0 505 565 ;\r\nC -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;\r\nEndCharMetrics\r\nEndFontMetrics\r\n";
|
|
@@ -2640,8 +2393,6 @@ class EmbeddedFont extends PDFFont {
|
|
|
2640
2393
|
}
|
|
2641
2394
|
layoutRun(text, features) {
|
|
2642
2395
|
const run = this.font.layout(text, features);
|
|
2643
|
-
|
|
2644
|
-
// Normalize position values
|
|
2645
2396
|
for (let i = 0; i < run.positions.length; i++) {
|
|
2646
2397
|
const position = run.positions[i];
|
|
2647
2398
|
for (let key in position) {
|
|
@@ -2664,16 +2415,12 @@ class EmbeddedFont extends PDFFont {
|
|
|
2664
2415
|
return run;
|
|
2665
2416
|
}
|
|
2666
2417
|
layout(text, features, onlyWidth) {
|
|
2667
|
-
// Skip the cache if any user defined features are applied
|
|
2668
2418
|
if (features) {
|
|
2669
2419
|
return this.layoutRun(text, features);
|
|
2670
2420
|
}
|
|
2671
2421
|
let glyphs = onlyWidth ? null : [];
|
|
2672
2422
|
let positions = onlyWidth ? null : [];
|
|
2673
2423
|
let advanceWidth = 0;
|
|
2674
|
-
|
|
2675
|
-
// Split the string by words to increase cache efficiency.
|
|
2676
|
-
// For this purpose, spaces and tabs are a good enough delimeter.
|
|
2677
2424
|
let last = 0;
|
|
2678
2425
|
let index = 0;
|
|
2679
2426
|
while (index <= text.length) {
|
|
@@ -2735,17 +2482,15 @@ class EmbeddedFont extends PDFFont {
|
|
|
2735
2482
|
if (1 <= familyClass && familyClass <= 7) {
|
|
2736
2483
|
flags |= 1 << 1;
|
|
2737
2484
|
}
|
|
2738
|
-
flags |= 1 << 2;
|
|
2485
|
+
flags |= 1 << 2;
|
|
2739
2486
|
if (familyClass === 10) {
|
|
2740
2487
|
flags |= 1 << 3;
|
|
2741
2488
|
}
|
|
2742
2489
|
if (this.font.head.macStyle.italic) {
|
|
2743
2490
|
flags |= 1 << 6;
|
|
2744
2491
|
}
|
|
2745
|
-
|
|
2746
|
-
// generate a tag (6 uppercase letters. 17 is the char code offset from '0' to 'A'. 73 will map to 'Z')
|
|
2747
2492
|
const tag = [1, 2, 3, 4, 5, 6].map(i => String.fromCharCode((this.id.charCodeAt(i) || 73) + 17)).join('');
|
|
2748
|
-
const name = tag + '+' + this.font.postscriptName
|
|
2493
|
+
const name = tag + '+' + this.font.postscriptName?.replaceAll(' ', '_');
|
|
2749
2494
|
const {
|
|
2750
2495
|
bbox
|
|
2751
2496
|
} = this.font;
|
|
@@ -2760,8 +2505,7 @@ class EmbeddedFont extends PDFFont {
|
|
|
2760
2505
|
CapHeight: (this.font.capHeight || this.font.ascent) * this.scale,
|
|
2761
2506
|
XHeight: (this.font.xHeight || 0) * this.scale,
|
|
2762
2507
|
StemV: 0
|
|
2763
|
-
});
|
|
2764
|
-
|
|
2508
|
+
});
|
|
2765
2509
|
if (isCFF) {
|
|
2766
2510
|
descriptor.data.FontFile3 = fontFile;
|
|
2767
2511
|
} else {
|
|
@@ -2803,17 +2547,11 @@ class EmbeddedFont extends PDFFont {
|
|
|
2803
2547
|
};
|
|
2804
2548
|
return this.dictionary.end();
|
|
2805
2549
|
}
|
|
2806
|
-
|
|
2807
|
-
// Maps the glyph ids encoded in the PDF back to unicode strings
|
|
2808
|
-
// Because of ligature substitutions and the like, there may be one or more
|
|
2809
|
-
// unicode characters represented by each glyph.
|
|
2810
2550
|
toUnicodeCmap() {
|
|
2811
2551
|
const cmap = this.document.ref();
|
|
2812
2552
|
const entries = [];
|
|
2813
2553
|
for (let codePoints of this.unicode) {
|
|
2814
2554
|
const encoded = [];
|
|
2815
|
-
|
|
2816
|
-
// encode codePoints to utf16
|
|
2817
2555
|
for (let value of codePoints) {
|
|
2818
2556
|
if (value > 0xffff) {
|
|
2819
2557
|
value -= 0x10000;
|
|
@@ -2880,31 +2618,26 @@ class PDFFontFactory {
|
|
|
2880
2618
|
}
|
|
2881
2619
|
|
|
2882
2620
|
const isEqualFont = (font1, font2) => {
|
|
2883
|
-
// compare font checksum
|
|
2884
2621
|
if (font1.font._tables?.head?.checkSumAdjustment !== font2.font._tables?.head?.checkSumAdjustment) {
|
|
2885
2622
|
return false;
|
|
2886
2623
|
}
|
|
2887
|
-
|
|
2888
|
-
// compare font name table
|
|
2889
2624
|
if (JSON.stringify(font1.font._tables?.name?.records) !== JSON.stringify(font2.font._tables?.name?.records)) {
|
|
2890
2625
|
return false;
|
|
2891
2626
|
}
|
|
2892
2627
|
return true;
|
|
2893
2628
|
};
|
|
2894
2629
|
var FontsMixin = {
|
|
2895
|
-
initFonts(defaultFont = 'Helvetica') {
|
|
2896
|
-
// Lookup table for embedded fonts
|
|
2630
|
+
initFonts(defaultFont = 'Helvetica', defaultFontFamily = null, defaultFontSize = 12) {
|
|
2897
2631
|
this._fontFamilies = {};
|
|
2898
2632
|
this._fontCount = 0;
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
this._fontSize =
|
|
2633
|
+
this._fontSource = defaultFont;
|
|
2634
|
+
this._fontFamily = defaultFontFamily;
|
|
2635
|
+
this._fontSize = defaultFontSize;
|
|
2902
2636
|
this._font = null;
|
|
2637
|
+
this._remSize = defaultFontSize;
|
|
2903
2638
|
this._registeredFonts = {};
|
|
2904
|
-
|
|
2905
|
-
// Set the default font
|
|
2906
2639
|
if (defaultFont) {
|
|
2907
|
-
this.font(defaultFont);
|
|
2640
|
+
this.font(defaultFont, defaultFontFamily);
|
|
2908
2641
|
}
|
|
2909
2642
|
},
|
|
2910
2643
|
font(src, family, size) {
|
|
@@ -2913,8 +2646,6 @@ var FontsMixin = {
|
|
|
2913
2646
|
size = family;
|
|
2914
2647
|
family = null;
|
|
2915
2648
|
}
|
|
2916
|
-
|
|
2917
|
-
// check registered fonts if src is a string
|
|
2918
2649
|
if (typeof src === 'string' && this._registeredFonts[src]) {
|
|
2919
2650
|
cacheKey = src;
|
|
2920
2651
|
({
|
|
@@ -2927,28 +2658,21 @@ var FontsMixin = {
|
|
|
2927
2658
|
cacheKey = null;
|
|
2928
2659
|
}
|
|
2929
2660
|
}
|
|
2661
|
+
this._fontSource = src;
|
|
2662
|
+
this._fontFamily = family;
|
|
2930
2663
|
if (size != null) {
|
|
2931
2664
|
this.fontSize(size);
|
|
2932
2665
|
}
|
|
2933
|
-
|
|
2934
|
-
// fast path: check if the font is already in the PDF
|
|
2935
2666
|
if (font = this._fontFamilies[cacheKey]) {
|
|
2936
2667
|
this._font = font;
|
|
2937
2668
|
return this;
|
|
2938
2669
|
}
|
|
2939
|
-
|
|
2940
|
-
// load the font
|
|
2941
2670
|
const id = `F${++this._fontCount}`;
|
|
2942
2671
|
this._font = PDFFontFactory.open(this, src, family, id);
|
|
2943
|
-
|
|
2944
|
-
// check for existing font familes with the same name already in the PDF
|
|
2945
|
-
// useful if the font was passed as a buffer
|
|
2946
2672
|
if ((font = this._fontFamilies[this._font.name]) && isEqualFont(this._font, font)) {
|
|
2947
2673
|
this._font = font;
|
|
2948
2674
|
return this;
|
|
2949
2675
|
}
|
|
2950
|
-
|
|
2951
|
-
// save the font for reuse later
|
|
2952
2676
|
if (cacheKey) {
|
|
2953
2677
|
this._fontFamilies[cacheKey] = this._font;
|
|
2954
2678
|
}
|
|
@@ -2958,13 +2682,10 @@ var FontsMixin = {
|
|
|
2958
2682
|
return this;
|
|
2959
2683
|
},
|
|
2960
2684
|
fontSize(_fontSize) {
|
|
2961
|
-
this._fontSize = _fontSize;
|
|
2685
|
+
this._fontSize = this.sizeToPoint(_fontSize);
|
|
2962
2686
|
return this;
|
|
2963
2687
|
},
|
|
2964
2688
|
currentLineHeight(includeGap) {
|
|
2965
|
-
if (includeGap == null) {
|
|
2966
|
-
includeGap = false;
|
|
2967
|
-
}
|
|
2968
2689
|
return this._font.lineHeight(this._fontSize, includeGap);
|
|
2969
2690
|
},
|
|
2970
2691
|
registerFont(name, src, family) {
|
|
@@ -2973,6 +2694,64 @@ var FontsMixin = {
|
|
|
2973
2694
|
family
|
|
2974
2695
|
};
|
|
2975
2696
|
return this;
|
|
2697
|
+
},
|
|
2698
|
+
sizeToPoint(size, defaultValue = 0, page = this.page, percentageWidth = undefined) {
|
|
2699
|
+
if (!percentageWidth) percentageWidth = this._fontSize;
|
|
2700
|
+
if (typeof defaultValue !== 'number') defaultValue = this.sizeToPoint(defaultValue);
|
|
2701
|
+
if (size === undefined) return defaultValue;
|
|
2702
|
+
if (typeof size === 'number') return size;
|
|
2703
|
+
if (typeof size === 'boolean') return Number(size);
|
|
2704
|
+
const match = String(size).match(/((\d+)?(\.\d+)?)(em|in|px|cm|mm|pc|ex|ch|rem|vw|vh|vmin|vmax|%|pt)?/);
|
|
2705
|
+
if (!match) throw new Error(`Unsupported size '${size}'`);
|
|
2706
|
+
let multiplier;
|
|
2707
|
+
switch (match[4]) {
|
|
2708
|
+
case 'em':
|
|
2709
|
+
multiplier = this._fontSize;
|
|
2710
|
+
break;
|
|
2711
|
+
case 'in':
|
|
2712
|
+
multiplier = IN_TO_PT;
|
|
2713
|
+
break;
|
|
2714
|
+
case 'px':
|
|
2715
|
+
multiplier = PX_TO_IN * IN_TO_PT;
|
|
2716
|
+
break;
|
|
2717
|
+
case 'cm':
|
|
2718
|
+
multiplier = CM_TO_IN * IN_TO_PT;
|
|
2719
|
+
break;
|
|
2720
|
+
case 'mm':
|
|
2721
|
+
multiplier = MM_TO_CM * CM_TO_IN * IN_TO_PT;
|
|
2722
|
+
break;
|
|
2723
|
+
case 'pc':
|
|
2724
|
+
multiplier = PC_TO_PT;
|
|
2725
|
+
break;
|
|
2726
|
+
case 'ex':
|
|
2727
|
+
multiplier = this.currentLineHeight();
|
|
2728
|
+
break;
|
|
2729
|
+
case 'ch':
|
|
2730
|
+
multiplier = this.widthOfString('0');
|
|
2731
|
+
break;
|
|
2732
|
+
case 'rem':
|
|
2733
|
+
multiplier = this._remSize;
|
|
2734
|
+
break;
|
|
2735
|
+
case 'vw':
|
|
2736
|
+
multiplier = page.width / 100;
|
|
2737
|
+
break;
|
|
2738
|
+
case 'vh':
|
|
2739
|
+
multiplier = page.height / 100;
|
|
2740
|
+
break;
|
|
2741
|
+
case 'vmin':
|
|
2742
|
+
multiplier = Math.min(page.width, page.height) / 100;
|
|
2743
|
+
break;
|
|
2744
|
+
case 'vmax':
|
|
2745
|
+
multiplier = Math.max(page.width, page.height) / 100;
|
|
2746
|
+
break;
|
|
2747
|
+
case '%':
|
|
2748
|
+
multiplier = percentageWidth / 100;
|
|
2749
|
+
break;
|
|
2750
|
+
case 'pt':
|
|
2751
|
+
default:
|
|
2752
|
+
multiplier = 1;
|
|
2753
|
+
}
|
|
2754
|
+
return multiplier * Number(match[1]);
|
|
2976
2755
|
}
|
|
2977
2756
|
};
|
|
2978
2757
|
|
|
@@ -2987,7 +2766,7 @@ class LineWrapper extends events.EventEmitter {
|
|
|
2987
2766
|
this.characterSpacing = (options.characterSpacing || 0) * this.horizontalScaling / 100;
|
|
2988
2767
|
this.wordSpacing = (options.wordSpacing === 0) * this.horizontalScaling / 100;
|
|
2989
2768
|
this.columns = options.columns || 1;
|
|
2990
|
-
this.columnGap = (options.columnGap != null ? options.columnGap : 18) * this.horizontalScaling / 100;
|
|
2769
|
+
this.columnGap = (options.columnGap != null ? options.columnGap : 18) * this.horizontalScaling / 100;
|
|
2991
2770
|
this.lineWidth = (options.width * this.horizontalScaling / 100 - this.columnGap * (this.columns - 1)) / this.columns;
|
|
2992
2771
|
this.spaceLeft = this.lineWidth;
|
|
2993
2772
|
this.startX = this.document.x;
|
|
@@ -2996,44 +2775,30 @@ class LineWrapper extends events.EventEmitter {
|
|
|
2996
2775
|
this.ellipsis = options.ellipsis;
|
|
2997
2776
|
this.continuedX = 0;
|
|
2998
2777
|
this.features = options.features;
|
|
2999
|
-
|
|
3000
|
-
// calculate the maximum Y position the text can appear at
|
|
3001
2778
|
if (options.height != null) {
|
|
3002
2779
|
this.height = options.height;
|
|
3003
|
-
this.maxY = this.startY + options.height;
|
|
2780
|
+
this.maxY = PDFNumber(this.startY + options.height);
|
|
3004
2781
|
} else {
|
|
3005
|
-
this.maxY = this.document.page.maxY();
|
|
2782
|
+
this.maxY = PDFNumber(this.document.page.maxY());
|
|
3006
2783
|
}
|
|
3007
|
-
|
|
3008
|
-
// handle paragraph indents
|
|
3009
2784
|
this.on('firstLine', options => {
|
|
3010
|
-
// if this is the first line of the text segment, and
|
|
3011
|
-
// we're continuing where we left off, indent that much
|
|
3012
|
-
// otherwise use the user specified indent option
|
|
3013
2785
|
const indent = this.continuedX || this.indent;
|
|
3014
2786
|
this.document.x += indent;
|
|
3015
2787
|
this.lineWidth -= indent;
|
|
3016
|
-
|
|
3017
|
-
// if indentAllLines is set to true
|
|
3018
|
-
// we're not resetting the indentation for this paragraph after the first line
|
|
3019
2788
|
if (options.indentAllLines) {
|
|
3020
2789
|
return;
|
|
3021
2790
|
}
|
|
3022
|
-
|
|
3023
|
-
// otherwise we start the next line without indent
|
|
3024
|
-
return this.once('line', () => {
|
|
2791
|
+
this.once('line', () => {
|
|
3025
2792
|
this.document.x -= indent;
|
|
3026
2793
|
this.lineWidth += indent;
|
|
3027
2794
|
if (options.continued && !this.continuedX) {
|
|
3028
2795
|
this.continuedX = this.indent;
|
|
3029
2796
|
}
|
|
3030
2797
|
if (!options.continued) {
|
|
3031
|
-
|
|
2798
|
+
this.continuedX = 0;
|
|
3032
2799
|
}
|
|
3033
2800
|
});
|
|
3034
2801
|
});
|
|
3035
|
-
|
|
3036
|
-
// handle left aligning last lines of paragraphs
|
|
3037
2802
|
this.on('lastLine', options => {
|
|
3038
2803
|
const {
|
|
3039
2804
|
align
|
|
@@ -3042,7 +2807,7 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3042
2807
|
options.align = 'left';
|
|
3043
2808
|
}
|
|
3044
2809
|
this.lastLine = true;
|
|
3045
|
-
|
|
2810
|
+
this.once('line', () => {
|
|
3046
2811
|
this.document.y += options.paragraphGap || 0;
|
|
3047
2812
|
options.align = align;
|
|
3048
2813
|
return this.lastLine = false;
|
|
@@ -3059,7 +2824,6 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3059
2824
|
return w + this.wordWidth(HYPHEN) <= this.spaceLeft;
|
|
3060
2825
|
}
|
|
3061
2826
|
eachWord(text, fn) {
|
|
3062
|
-
// setup a unicode line breaker
|
|
3063
2827
|
let bk;
|
|
3064
2828
|
const breaker = new LineBreaker(text);
|
|
3065
2829
|
let last = null;
|
|
@@ -3068,19 +2832,12 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3068
2832
|
var shouldContinue;
|
|
3069
2833
|
let word = text.slice((last != null ? last.position : undefined) || 0, bk.position);
|
|
3070
2834
|
let w = wordWidths[word] != null ? wordWidths[word] : wordWidths[word] = this.wordWidth(word);
|
|
3071
|
-
|
|
3072
|
-
// if the word is longer than the whole line, chop it up
|
|
3073
|
-
// TODO: break by grapheme clusters, not JS string characters
|
|
3074
2835
|
if (w > this.lineWidth + this.continuedX) {
|
|
3075
|
-
// make some fake break objects
|
|
3076
2836
|
let lbk = last;
|
|
3077
2837
|
const fbk = {};
|
|
3078
2838
|
while (word.length) {
|
|
3079
|
-
// fit as much of the word as possible into the space we have
|
|
3080
2839
|
var l, mightGrow;
|
|
3081
2840
|
if (w > this.spaceLeft) {
|
|
3082
|
-
// start our check at the end of our available space - this method is faster than a loop of each character and it resolves
|
|
3083
|
-
// an issue with long loops when processing massive words, such as a huge number of spaces
|
|
3084
2841
|
l = Math.ceil(this.spaceLeft / (w / word.length));
|
|
3085
2842
|
w = this.wordWidth(word.slice(0, l));
|
|
3086
2843
|
mightGrow = w <= this.spaceLeft && l < word.length;
|
|
@@ -3088,7 +2845,6 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3088
2845
|
l = word.length;
|
|
3089
2846
|
}
|
|
3090
2847
|
let mustShrink = w > this.spaceLeft && l > 0;
|
|
3091
|
-
// shrink or grow word as necessary after our near-guess above
|
|
3092
2848
|
while (mustShrink || mightGrow) {
|
|
3093
2849
|
if (mustShrink) {
|
|
3094
2850
|
w = this.wordWidth(word.slice(0, --l));
|
|
@@ -3099,20 +2855,14 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3099
2855
|
mightGrow = w <= this.spaceLeft && l < word.length;
|
|
3100
2856
|
}
|
|
3101
2857
|
}
|
|
3102
|
-
|
|
3103
|
-
// check for the edge case where a single character cannot fit into a line.
|
|
3104
2858
|
if (l === 0 && this.spaceLeft === this.lineWidth) {
|
|
3105
2859
|
l = 1;
|
|
3106
2860
|
}
|
|
3107
|
-
|
|
3108
|
-
// send a required break unless this is the last piece and a linebreak is not specified
|
|
3109
2861
|
fbk.required = bk.required || l < word.length;
|
|
3110
2862
|
shouldContinue = fn(word.slice(0, l), w, fbk, lbk);
|
|
3111
2863
|
lbk = {
|
|
3112
2864
|
required: false
|
|
3113
2865
|
};
|
|
3114
|
-
|
|
3115
|
-
// get the remaining piece of the word
|
|
3116
2866
|
word = word.slice(l);
|
|
3117
2867
|
w = this.wordWidth(word);
|
|
3118
2868
|
if (shouldContinue === false) {
|
|
@@ -3120,7 +2870,6 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3120
2870
|
}
|
|
3121
2871
|
}
|
|
3122
2872
|
} else {
|
|
3123
|
-
// otherwise just emit the break as it was given to us
|
|
3124
2873
|
shouldContinue = fn(word, w, bk, last);
|
|
3125
2874
|
}
|
|
3126
2875
|
if (shouldContinue === false) {
|
|
@@ -3130,7 +2879,6 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3130
2879
|
}
|
|
3131
2880
|
}
|
|
3132
2881
|
wrap(text, options) {
|
|
3133
|
-
// override options from previous continued fragments
|
|
3134
2882
|
this.horizontalScaling = options.horizontalScaling || 100;
|
|
3135
2883
|
if (options.indent != null) {
|
|
3136
2884
|
this.indent = options.indent * this.horizontalScaling / 100;
|
|
@@ -3144,10 +2892,6 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3144
2892
|
if (options.ellipsis != null) {
|
|
3145
2893
|
this.ellipsis = options.ellipsis;
|
|
3146
2894
|
}
|
|
3147
|
-
|
|
3148
|
-
// make sure we're actually on the page
|
|
3149
|
-
// and that the first line of is never by
|
|
3150
|
-
// itself at the bottom of a page (orphans)
|
|
3151
2895
|
const nextY = this.document.y + this.document.currentLineHeight(true);
|
|
3152
2896
|
if (this.document.y > this.maxY || nextY > this.maxY) {
|
|
3153
2897
|
this.nextSection();
|
|
@@ -3158,7 +2902,7 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3158
2902
|
let lc = 0;
|
|
3159
2903
|
let {
|
|
3160
2904
|
y
|
|
3161
|
-
} = this.document;
|
|
2905
|
+
} = this.document;
|
|
3162
2906
|
const emitLine = () => {
|
|
3163
2907
|
options.textWidth = textWidth + this.wordSpacing * (wc - 1);
|
|
3164
2908
|
options.wordCount = wc;
|
|
@@ -3181,23 +2925,17 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3181
2925
|
wc++;
|
|
3182
2926
|
}
|
|
3183
2927
|
if (bk.required || !this.canFit(word, w)) {
|
|
3184
|
-
// if the user specified a max height and an ellipsis, and is about to pass the
|
|
3185
|
-
// max height and max columns after the next line, append the ellipsis
|
|
3186
2928
|
const lh = this.document.currentLineHeight(true);
|
|
3187
|
-
if (this.height != null && this.ellipsis && this.document.y + lh * 2 > this.maxY && this.column >= this.columns) {
|
|
2929
|
+
if (this.height != null && this.ellipsis && PDFNumber(this.document.y + lh * 2) > this.maxY && this.column >= this.columns) {
|
|
3188
2930
|
if (this.ellipsis === true) {
|
|
3189
2931
|
this.ellipsis = '…';
|
|
3190
|
-
}
|
|
2932
|
+
}
|
|
3191
2933
|
buffer = buffer.replace(/\s+$/, '');
|
|
3192
2934
|
textWidth = this.wordWidth(buffer + this.ellipsis);
|
|
3193
|
-
|
|
3194
|
-
// remove characters from the buffer until the ellipsis fits
|
|
3195
|
-
// to avoid infinite loop need to stop while-loop if buffer is empty string
|
|
3196
2935
|
while (buffer && textWidth > this.lineWidth) {
|
|
3197
2936
|
buffer = buffer.slice(0, -1).replace(/\s+$/, '');
|
|
3198
2937
|
textWidth = this.wordWidth(buffer + this.ellipsis);
|
|
3199
2938
|
}
|
|
3200
|
-
// need to add ellipsis only if there is enough space for it
|
|
3201
2939
|
if (textWidth <= this.lineWidth) {
|
|
3202
2940
|
buffer = buffer + this.ellipsis;
|
|
3203
2941
|
}
|
|
@@ -3212,35 +2950,25 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3212
2950
|
}
|
|
3213
2951
|
this.emit('lastLine', options, this);
|
|
3214
2952
|
}
|
|
3215
|
-
|
|
3216
|
-
// Previous entry is a soft hyphen - add visible hyphen.
|
|
3217
2953
|
if (buffer[buffer.length - 1] == SOFT_HYPHEN) {
|
|
3218
2954
|
buffer = buffer.slice(0, -1) + HYPHEN;
|
|
3219
2955
|
this.spaceLeft -= this.wordWidth(HYPHEN);
|
|
3220
2956
|
}
|
|
3221
2957
|
emitLine();
|
|
3222
|
-
|
|
3223
|
-
// if we've reached the edge of the page,
|
|
3224
|
-
// continue on a new page or column
|
|
3225
|
-
if (this.document.y + lh > this.maxY) {
|
|
2958
|
+
if (PDFNumber(this.document.y + lh) > this.maxY) {
|
|
3226
2959
|
const shouldContinue = this.nextSection();
|
|
3227
|
-
|
|
3228
|
-
// stop if we reached the maximum height
|
|
3229
2960
|
if (!shouldContinue) {
|
|
3230
2961
|
wc = 0;
|
|
3231
2962
|
buffer = '';
|
|
3232
2963
|
return false;
|
|
3233
2964
|
}
|
|
3234
2965
|
}
|
|
3235
|
-
|
|
3236
|
-
// reset the space left and buffer
|
|
3237
2966
|
if (bk.required) {
|
|
3238
2967
|
this.spaceLeft = this.lineWidth;
|
|
3239
2968
|
buffer = '';
|
|
3240
2969
|
textWidth = 0;
|
|
3241
2970
|
return wc = 0;
|
|
3242
2971
|
} else {
|
|
3243
|
-
// reset the space left and buffer
|
|
3244
2972
|
this.spaceLeft = this.lineWidth - w;
|
|
3245
2973
|
buffer = word;
|
|
3246
2974
|
textWidth = w;
|
|
@@ -3255,25 +2983,19 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3255
2983
|
emitLine();
|
|
3256
2984
|
}
|
|
3257
2985
|
this.emit('sectionEnd', options, this);
|
|
3258
|
-
|
|
3259
|
-
// if the wrap is set to be continued, save the X position
|
|
3260
|
-
// to start the first line of the next segment at, and reset
|
|
3261
|
-
// the y position
|
|
3262
2986
|
if (options.continued === true) {
|
|
3263
2987
|
if (lc > 1) {
|
|
3264
2988
|
this.continuedX = 0;
|
|
3265
2989
|
}
|
|
3266
2990
|
this.continuedX += options.textWidth || 0;
|
|
3267
|
-
|
|
2991
|
+
this.document.y = y;
|
|
3268
2992
|
} else {
|
|
3269
|
-
|
|
2993
|
+
this.document.x = this.startX;
|
|
3270
2994
|
}
|
|
3271
2995
|
}
|
|
3272
2996
|
nextSection(options) {
|
|
3273
2997
|
this.emit('sectionEnd', options, this);
|
|
3274
2998
|
if (++this.column > this.columns) {
|
|
3275
|
-
// if a max height was specified by the user, we're done.
|
|
3276
|
-
// otherwise, the default is to make a new page at the bottom.
|
|
3277
2999
|
if (this.height != null) {
|
|
3278
3000
|
return false;
|
|
3279
3001
|
}
|
|
@@ -3302,10 +3024,9 @@ const {
|
|
|
3302
3024
|
var TextMixin = {
|
|
3303
3025
|
initText() {
|
|
3304
3026
|
this._line = this._line.bind(this);
|
|
3305
|
-
// Current coordinates
|
|
3306
3027
|
this.x = 0;
|
|
3307
3028
|
this.y = 0;
|
|
3308
|
-
|
|
3029
|
+
this._lineGap = 0;
|
|
3309
3030
|
},
|
|
3310
3031
|
lineGap(_lineGap) {
|
|
3311
3032
|
this._lineGap = _lineGap;
|
|
@@ -3327,11 +3048,7 @@ var TextMixin = {
|
|
|
3327
3048
|
},
|
|
3328
3049
|
_text(text, x, y, options, lineCallback) {
|
|
3329
3050
|
options = this._initOptions(x, y, options);
|
|
3330
|
-
|
|
3331
|
-
// Convert text to a string
|
|
3332
3051
|
text = text == null ? '' : `${text}`;
|
|
3333
|
-
|
|
3334
|
-
// if the wordSpacing option is specified, remove multiple consecutive spaces
|
|
3335
3052
|
if (options.wordSpacing) {
|
|
3336
3053
|
text = text.replace(/\s{2,}/g, ' ');
|
|
3337
3054
|
}
|
|
@@ -3340,8 +3057,12 @@ var TextMixin = {
|
|
|
3340
3057
|
options.structParent.add(this.struct(options.structType || 'P', [this.markStructureContent(options.structType || 'P')]));
|
|
3341
3058
|
}
|
|
3342
3059
|
};
|
|
3343
|
-
|
|
3344
|
-
|
|
3060
|
+
if (options.rotation !== 0) {
|
|
3061
|
+
this.save();
|
|
3062
|
+
this.rotate(-options.rotation, {
|
|
3063
|
+
origin: [this.x, this.y]
|
|
3064
|
+
});
|
|
3065
|
+
}
|
|
3345
3066
|
if (options.width) {
|
|
3346
3067
|
let wrapper = this._wrapper;
|
|
3347
3068
|
if (!wrapper) {
|
|
@@ -3352,14 +3073,13 @@ var TextMixin = {
|
|
|
3352
3073
|
this._wrapper = options.continued ? wrapper : null;
|
|
3353
3074
|
this._textOptions = options.continued ? options : null;
|
|
3354
3075
|
wrapper.wrap(text, options);
|
|
3355
|
-
|
|
3356
|
-
// render paragraphs as single lines
|
|
3357
3076
|
} else {
|
|
3358
3077
|
for (let line of text.split('\n')) {
|
|
3359
3078
|
addStructure();
|
|
3360
3079
|
lineCallback(line, options);
|
|
3361
3080
|
}
|
|
3362
3081
|
}
|
|
3082
|
+
if (options.rotation !== 0) this.restore();
|
|
3363
3083
|
return this;
|
|
3364
3084
|
},
|
|
3365
3085
|
text(text, x, y, options) {
|
|
@@ -3369,17 +3089,108 @@ var TextMixin = {
|
|
|
3369
3089
|
const horizontalScaling = options.horizontalScaling || 100;
|
|
3370
3090
|
return (this._font.widthOfString(string, this._fontSize, options.features) + (options.characterSpacing || 0) * (string.length - 1)) * horizontalScaling / 100;
|
|
3371
3091
|
},
|
|
3092
|
+
boundsOfString(string, x, y, options) {
|
|
3093
|
+
options = this._initOptions(x, y, options);
|
|
3094
|
+
({
|
|
3095
|
+
x,
|
|
3096
|
+
y
|
|
3097
|
+
} = this);
|
|
3098
|
+
const lineGap = options.lineGap ?? this._lineGap ?? 0;
|
|
3099
|
+
const lineHeight = this.currentLineHeight(true) + lineGap;
|
|
3100
|
+
let contentWidth = 0;
|
|
3101
|
+
string = String(string ?? '');
|
|
3102
|
+
if (options.wordSpacing) {
|
|
3103
|
+
string = string.replace(/\s{2,}/g, ' ');
|
|
3104
|
+
}
|
|
3105
|
+
if (options.width) {
|
|
3106
|
+
let wrapper = new LineWrapper(this, options);
|
|
3107
|
+
wrapper.on('line', (text, options) => {
|
|
3108
|
+
this.y += lineHeight;
|
|
3109
|
+
text = text.replace(/\n/g, '');
|
|
3110
|
+
if (text.length) {
|
|
3111
|
+
let wordSpacing = options.wordSpacing ?? 0;
|
|
3112
|
+
const characterSpacing = options.characterSpacing ?? 0;
|
|
3113
|
+
if (options.width && options.align === 'justify') {
|
|
3114
|
+
const words = text.trim().split(/\s+/);
|
|
3115
|
+
const textWidth = this.widthOfString(text.replace(/\s+/g, ''), options);
|
|
3116
|
+
const spaceWidth = this.widthOfString(' ') + characterSpacing;
|
|
3117
|
+
wordSpacing = Math.max(0, (options.lineWidth - textWidth) / Math.max(1, words.length - 1) - spaceWidth);
|
|
3118
|
+
}
|
|
3119
|
+
contentWidth = Math.max(contentWidth, options.textWidth + wordSpacing * (options.wordCount - 1) + characterSpacing * (text.length - 1));
|
|
3120
|
+
}
|
|
3121
|
+
});
|
|
3122
|
+
wrapper.wrap(string, options);
|
|
3123
|
+
} else {
|
|
3124
|
+
for (let line of string.split('\n')) {
|
|
3125
|
+
const lineWidth = this.widthOfString(line, options);
|
|
3126
|
+
this.y += lineHeight;
|
|
3127
|
+
contentWidth = Math.max(contentWidth, lineWidth);
|
|
3128
|
+
}
|
|
3129
|
+
}
|
|
3130
|
+
let contentHeight = this.y - y;
|
|
3131
|
+
if (options.height) contentHeight = Math.min(contentHeight, options.height);
|
|
3132
|
+
this.x = x;
|
|
3133
|
+
this.y = y;
|
|
3134
|
+
if (options.rotation === 0) {
|
|
3135
|
+
return {
|
|
3136
|
+
x,
|
|
3137
|
+
y,
|
|
3138
|
+
width: contentWidth,
|
|
3139
|
+
height: contentHeight
|
|
3140
|
+
};
|
|
3141
|
+
} else if (options.rotation === 90) {
|
|
3142
|
+
return {
|
|
3143
|
+
x: x,
|
|
3144
|
+
y: y - contentWidth,
|
|
3145
|
+
width: contentHeight,
|
|
3146
|
+
height: contentWidth
|
|
3147
|
+
};
|
|
3148
|
+
} else if (options.rotation === 180) {
|
|
3149
|
+
return {
|
|
3150
|
+
x: x - contentWidth,
|
|
3151
|
+
y: y - contentHeight,
|
|
3152
|
+
width: contentWidth,
|
|
3153
|
+
height: contentHeight
|
|
3154
|
+
};
|
|
3155
|
+
} else if (options.rotation === 270) {
|
|
3156
|
+
return {
|
|
3157
|
+
x: x - contentHeight,
|
|
3158
|
+
y: y,
|
|
3159
|
+
width: contentHeight,
|
|
3160
|
+
height: contentWidth
|
|
3161
|
+
};
|
|
3162
|
+
}
|
|
3163
|
+
const cos = cosine(options.rotation);
|
|
3164
|
+
const sin = sine(options.rotation);
|
|
3165
|
+
const x1 = x;
|
|
3166
|
+
const y1 = y;
|
|
3167
|
+
const x2 = x + contentWidth * cos;
|
|
3168
|
+
const y2 = y - contentWidth * sin;
|
|
3169
|
+
const x3 = x + contentWidth * cos + contentHeight * sin;
|
|
3170
|
+
const y3 = y - contentWidth * sin + contentHeight * cos;
|
|
3171
|
+
const x4 = x + contentHeight * sin;
|
|
3172
|
+
const y4 = y + contentHeight * cos;
|
|
3173
|
+
const xMin = Math.min(x1, x2, x3, x4);
|
|
3174
|
+
const xMax = Math.max(x1, x2, x3, x4);
|
|
3175
|
+
const yMin = Math.min(y1, y2, y3, y4);
|
|
3176
|
+
const yMax = Math.max(y1, y2, y3, y4);
|
|
3177
|
+
return {
|
|
3178
|
+
x: xMin,
|
|
3179
|
+
y: yMin,
|
|
3180
|
+
width: xMax - xMin,
|
|
3181
|
+
height: yMax - yMin
|
|
3182
|
+
};
|
|
3183
|
+
},
|
|
3372
3184
|
heightOfString(text, options) {
|
|
3373
3185
|
const {
|
|
3374
3186
|
x,
|
|
3375
3187
|
y
|
|
3376
3188
|
} = this;
|
|
3377
3189
|
options = this._initOptions(options);
|
|
3378
|
-
options.height = Infinity;
|
|
3379
|
-
|
|
3190
|
+
options.height = Infinity;
|
|
3380
3191
|
const lineGap = options.lineGap || this._lineGap || 0;
|
|
3381
3192
|
this._text(text, this.x, this.y, options, () => {
|
|
3382
|
-
|
|
3193
|
+
this.y += this.currentLineHeight(true) + lineGap;
|
|
3383
3194
|
});
|
|
3384
3195
|
const height = this.y - y;
|
|
3385
3196
|
this.x = x;
|
|
@@ -3477,12 +3288,12 @@ var TextMixin = {
|
|
|
3477
3288
|
wrapper.on('sectionStart', () => {
|
|
3478
3289
|
const pos = indent + itemIndent * (level - 1);
|
|
3479
3290
|
this.x += pos;
|
|
3480
|
-
|
|
3291
|
+
wrapper.lineWidth -= pos;
|
|
3481
3292
|
});
|
|
3482
3293
|
wrapper.on('sectionEnd', () => {
|
|
3483
3294
|
const pos = indent + itemIndent * (level - 1);
|
|
3484
3295
|
this.x -= pos;
|
|
3485
|
-
|
|
3296
|
+
wrapper.lineWidth += pos;
|
|
3486
3297
|
});
|
|
3487
3298
|
wrapper.wrap(listItem, options);
|
|
3488
3299
|
};
|
|
@@ -3496,11 +3307,7 @@ var TextMixin = {
|
|
|
3496
3307
|
options = x;
|
|
3497
3308
|
x = null;
|
|
3498
3309
|
}
|
|
3499
|
-
|
|
3500
|
-
// clone options object
|
|
3501
3310
|
const result = Object.assign({}, options);
|
|
3502
|
-
|
|
3503
|
-
// extend options with previous values for continued text
|
|
3504
3311
|
if (this._textOptions) {
|
|
3505
3312
|
for (let key in this._textOptions) {
|
|
3506
3313
|
const val = this._textOptions[key];
|
|
@@ -3511,16 +3318,12 @@ var TextMixin = {
|
|
|
3511
3318
|
}
|
|
3512
3319
|
}
|
|
3513
3320
|
}
|
|
3514
|
-
|
|
3515
|
-
// Update the current position
|
|
3516
3321
|
if (x != null) {
|
|
3517
3322
|
this.x = x;
|
|
3518
3323
|
}
|
|
3519
3324
|
if (y != null) {
|
|
3520
3325
|
this.y = y;
|
|
3521
3326
|
}
|
|
3522
|
-
|
|
3523
|
-
// wrap to margins if no x or y position passed
|
|
3524
3327
|
if (result.lineBreak !== false) {
|
|
3525
3328
|
if (result.width == null) {
|
|
3526
3329
|
result.width = this.page.width - this.x - this.page.margins.right;
|
|
@@ -3532,17 +3335,18 @@ var TextMixin = {
|
|
|
3532
3335
|
}
|
|
3533
3336
|
if (result.columnGap == null) {
|
|
3534
3337
|
result.columnGap = 18;
|
|
3535
|
-
}
|
|
3536
|
-
|
|
3338
|
+
}
|
|
3339
|
+
result.rotation = Number(options.rotation ?? 0) % 360;
|
|
3340
|
+
if (result.rotation < 0) result.rotation += 360;
|
|
3537
3341
|
return result;
|
|
3538
3342
|
},
|
|
3539
3343
|
_line(text, options = {}, wrapper) {
|
|
3540
3344
|
this._fragment(text, this.x, this.y, options);
|
|
3541
3345
|
const lineGap = options.lineGap || this._lineGap || 0;
|
|
3542
3346
|
if (!wrapper) {
|
|
3543
|
-
|
|
3347
|
+
this.x += this.widthOfString(text, options);
|
|
3544
3348
|
} else {
|
|
3545
|
-
|
|
3349
|
+
this.y += this.currentLineHeight(true) + lineGap;
|
|
3546
3350
|
}
|
|
3547
3351
|
},
|
|
3548
3352
|
_fragment(text, x, y, options) {
|
|
@@ -3551,14 +3355,10 @@ var TextMixin = {
|
|
|
3551
3355
|
if (text.length === 0) {
|
|
3552
3356
|
return;
|
|
3553
3357
|
}
|
|
3554
|
-
|
|
3555
|
-
// handle options
|
|
3556
3358
|
const align = options.align || 'left';
|
|
3557
3359
|
let wordSpacing = options.wordSpacing || 0;
|
|
3558
3360
|
const characterSpacing = options.characterSpacing || 0;
|
|
3559
3361
|
const horizontalScaling = options.horizontalScaling || 100;
|
|
3560
|
-
|
|
3561
|
-
// text alignments
|
|
3562
3362
|
if (options.width) {
|
|
3563
3363
|
switch (align) {
|
|
3564
3364
|
case 'right':
|
|
@@ -3569,7 +3369,6 @@ var TextMixin = {
|
|
|
3569
3369
|
x += options.lineWidth / 2 - options.textWidth / 2;
|
|
3570
3370
|
break;
|
|
3571
3371
|
case 'justify':
|
|
3572
|
-
// calculate the word spacing value
|
|
3573
3372
|
words = text.trim().split(/\s+/);
|
|
3574
3373
|
textWidth = this.widthOfString(text.replace(/\s+/g, ''), options);
|
|
3575
3374
|
var spaceWidth = this.widthOfString(' ') + characterSpacing;
|
|
@@ -3577,8 +3376,6 @@ var TextMixin = {
|
|
|
3577
3376
|
break;
|
|
3578
3377
|
}
|
|
3579
3378
|
}
|
|
3580
|
-
|
|
3581
|
-
// text baseline alignments based on http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling
|
|
3582
3379
|
if (typeof options.baseline === 'number') {
|
|
3583
3380
|
dy = -options.baseline;
|
|
3584
3381
|
} else {
|
|
@@ -3611,11 +3408,7 @@ var TextMixin = {
|
|
|
3611
3408
|
}
|
|
3612
3409
|
dy = dy / 1000 * this._fontSize;
|
|
3613
3410
|
}
|
|
3614
|
-
|
|
3615
|
-
// calculate the actual rendered width of the string after word and character spacing
|
|
3616
3411
|
const renderedWidth = options.textWidth + wordSpacing * (options.wordCount - 1) + characterSpacing * (text.length - 1);
|
|
3617
|
-
|
|
3618
|
-
// create link annotations if the link option is given
|
|
3619
3412
|
if (options.link != null) {
|
|
3620
3413
|
this.link(x, y, renderedWidth, this.currentLineHeight(), options.link);
|
|
3621
3414
|
}
|
|
@@ -3625,8 +3418,6 @@ var TextMixin = {
|
|
|
3625
3418
|
if (options.destination != null) {
|
|
3626
3419
|
this.addNamedDestination(options.destination, 'XYZ', x, y, null);
|
|
3627
3420
|
}
|
|
3628
|
-
|
|
3629
|
-
// create underline
|
|
3630
3421
|
if (options.underline) {
|
|
3631
3422
|
this.save();
|
|
3632
3423
|
if (!options.stroke) {
|
|
@@ -3640,8 +3431,6 @@ var TextMixin = {
|
|
|
3640
3431
|
this.stroke();
|
|
3641
3432
|
this.restore();
|
|
3642
3433
|
}
|
|
3643
|
-
|
|
3644
|
-
// create strikethrough line
|
|
3645
3434
|
if (options.strike) {
|
|
3646
3435
|
this.save();
|
|
3647
3436
|
if (!options.stroke) {
|
|
@@ -3656,8 +3445,6 @@ var TextMixin = {
|
|
|
3656
3445
|
this.restore();
|
|
3657
3446
|
}
|
|
3658
3447
|
this.save();
|
|
3659
|
-
|
|
3660
|
-
// oblique (angle in degrees or boolean)
|
|
3661
3448
|
if (options.oblique) {
|
|
3662
3449
|
let skew;
|
|
3663
3450
|
if (typeof options.oblique === 'number') {
|
|
@@ -3669,45 +3456,24 @@ var TextMixin = {
|
|
|
3669
3456
|
this.transform(1, 0, skew, 1, -skew * dy, 0);
|
|
3670
3457
|
this.transform(1, 0, 0, 1, -x, -y);
|
|
3671
3458
|
}
|
|
3672
|
-
|
|
3673
|
-
// flip coordinate system
|
|
3674
3459
|
this.transform(1, 0, 0, -1, 0, this.page.height);
|
|
3675
3460
|
y = this.page.height - y - dy;
|
|
3676
|
-
|
|
3677
|
-
// add current font to page if necessary
|
|
3678
3461
|
if (this.page.fonts[this._font.id] == null) {
|
|
3679
3462
|
this.page.fonts[this._font.id] = this._font.ref();
|
|
3680
3463
|
}
|
|
3681
|
-
|
|
3682
|
-
// begin the text object
|
|
3683
3464
|
this.addContent('BT');
|
|
3684
|
-
|
|
3685
|
-
// text position
|
|
3686
3465
|
this.addContent(`1 0 0 1 ${number(x)} ${number(y)} Tm`);
|
|
3687
|
-
|
|
3688
|
-
// font and font size
|
|
3689
3466
|
this.addContent(`/${this._font.id} ${number(this._fontSize)} Tf`);
|
|
3690
|
-
|
|
3691
|
-
// rendering mode
|
|
3692
3467
|
const mode = options.fill && options.stroke ? 2 : options.stroke ? 1 : 0;
|
|
3693
3468
|
if (mode) {
|
|
3694
3469
|
this.addContent(`${mode} Tr`);
|
|
3695
3470
|
}
|
|
3696
|
-
|
|
3697
|
-
// Character spacing
|
|
3698
3471
|
if (characterSpacing) {
|
|
3699
3472
|
this.addContent(`${number(characterSpacing)} Tc`);
|
|
3700
3473
|
}
|
|
3701
|
-
|
|
3702
|
-
// Horizontal scaling
|
|
3703
3474
|
if (horizontalScaling !== 100) {
|
|
3704
3475
|
this.addContent(`${horizontalScaling} Tz`);
|
|
3705
3476
|
}
|
|
3706
|
-
|
|
3707
|
-
// Add the actual text
|
|
3708
|
-
// If we have a word spacing value, we need to encode each word separately
|
|
3709
|
-
// since the normal Tw operator only works on character code 32, which isn't
|
|
3710
|
-
// used for embedded fonts.
|
|
3711
3477
|
if (wordSpacing) {
|
|
3712
3478
|
words = text.trim().split(/\s+/);
|
|
3713
3479
|
wordSpacing += this.widthOfString(' ') + characterSpacing;
|
|
@@ -3718,9 +3484,6 @@ var TextMixin = {
|
|
|
3718
3484
|
const [encodedWord, positionsWord] = this._font.encode(word, options.features);
|
|
3719
3485
|
encoded = encoded.concat(encodedWord);
|
|
3720
3486
|
positions = positions.concat(positionsWord);
|
|
3721
|
-
|
|
3722
|
-
// add the word spacing to the end of the word
|
|
3723
|
-
// clone object because of cache
|
|
3724
3487
|
const space = {};
|
|
3725
3488
|
const object = positions[positions.length - 1];
|
|
3726
3489
|
for (let key in object) {
|
|
@@ -3737,60 +3500,42 @@ var TextMixin = {
|
|
|
3737
3500
|
const commands = [];
|
|
3738
3501
|
let last = 0;
|
|
3739
3502
|
let hadOffset = false;
|
|
3740
|
-
|
|
3741
|
-
// Adds a segment of text to the TJ command buffer
|
|
3742
3503
|
const addSegment = cur => {
|
|
3743
3504
|
if (last < cur) {
|
|
3744
3505
|
const hex = encoded.slice(last, cur).join('');
|
|
3745
3506
|
const advance = positions[cur - 1].xAdvance - positions[cur - 1].advanceWidth;
|
|
3746
3507
|
commands.push(`<${hex}> ${number(-advance)}`);
|
|
3747
3508
|
}
|
|
3748
|
-
|
|
3509
|
+
last = cur;
|
|
3749
3510
|
};
|
|
3750
|
-
|
|
3751
|
-
// Flushes the current TJ commands to the output stream
|
|
3752
3511
|
const flush = i => {
|
|
3753
3512
|
addSegment(i);
|
|
3754
3513
|
if (commands.length > 0) {
|
|
3755
3514
|
this.addContent(`[${commands.join(' ')}] TJ`);
|
|
3756
|
-
|
|
3515
|
+
commands.length = 0;
|
|
3757
3516
|
}
|
|
3758
3517
|
};
|
|
3759
3518
|
for (i = 0; i < positions.length; i++) {
|
|
3760
|
-
// If we have an x or y offset, we have to break out of the current TJ command
|
|
3761
|
-
// so we can move the text position.
|
|
3762
3519
|
const pos = positions[i];
|
|
3763
3520
|
if (pos.xOffset || pos.yOffset) {
|
|
3764
|
-
// Flush the current buffer
|
|
3765
3521
|
flush(i);
|
|
3766
|
-
|
|
3767
|
-
// Move the text position and flush just the current character
|
|
3768
3522
|
this.addContent(`1 0 0 1 ${number(x + pos.xOffset * scale)} ${number(y + pos.yOffset * scale)} Tm`);
|
|
3769
3523
|
flush(i + 1);
|
|
3770
3524
|
hadOffset = true;
|
|
3771
3525
|
} else {
|
|
3772
|
-
// If the last character had an offset, reset the text position
|
|
3773
3526
|
if (hadOffset) {
|
|
3774
3527
|
this.addContent(`1 0 0 1 ${number(x)} ${number(y)} Tm`);
|
|
3775
3528
|
hadOffset = false;
|
|
3776
3529
|
}
|
|
3777
|
-
|
|
3778
|
-
// Group segments that don't have any advance adjustments
|
|
3779
3530
|
if (pos.xAdvance - pos.advanceWidth !== 0) {
|
|
3780
3531
|
addSegment(i + 1);
|
|
3781
3532
|
}
|
|
3782
3533
|
}
|
|
3783
3534
|
x += pos.xAdvance * scale;
|
|
3784
3535
|
}
|
|
3785
|
-
|
|
3786
|
-
// Flush any remaining commands
|
|
3787
3536
|
flush(i);
|
|
3788
|
-
|
|
3789
|
-
// end the text object
|
|
3790
3537
|
this.addContent('ET');
|
|
3791
|
-
|
|
3792
|
-
// restore flipped coordinate system
|
|
3793
|
-
return this.restore();
|
|
3538
|
+
this.restore();
|
|
3794
3539
|
}
|
|
3795
3540
|
};
|
|
3796
3541
|
|
|
@@ -3808,8 +3553,6 @@ class JPEG {
|
|
|
3808
3553
|
if (this.data.readUInt16BE(0) !== 0xffd8) {
|
|
3809
3554
|
throw 'SOI not found in JPEG';
|
|
3810
3555
|
}
|
|
3811
|
-
|
|
3812
|
-
// Parse the EXIF orientation
|
|
3813
3556
|
this.orientation = exif.fromBuffer(this.data).Orientation || 1;
|
|
3814
3557
|
let pos = 2;
|
|
3815
3558
|
while (pos < this.data.length) {
|
|
@@ -3846,16 +3589,10 @@ class JPEG {
|
|
|
3846
3589
|
ColorSpace: this.colorSpace,
|
|
3847
3590
|
Filter: 'DCTDecode'
|
|
3848
3591
|
});
|
|
3849
|
-
|
|
3850
|
-
// add extra decode params for CMYK images. By swapping the
|
|
3851
|
-
// min and max values from the default, we invert the colors. See
|
|
3852
|
-
// section 4.8.4 of the spec.
|
|
3853
3592
|
if (this.colorSpace === 'DeviceCMYK') {
|
|
3854
3593
|
this.obj.data['Decode'] = [1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0];
|
|
3855
3594
|
}
|
|
3856
3595
|
this.obj.end(this.data);
|
|
3857
|
-
|
|
3858
|
-
// free memory
|
|
3859
3596
|
return this.data = null;
|
|
3860
3597
|
}
|
|
3861
3598
|
}
|
|
@@ -3898,24 +3635,14 @@ class PNGImage {
|
|
|
3898
3635
|
if (this.image.palette.length === 0) {
|
|
3899
3636
|
this.obj.data['ColorSpace'] = this.image.colorSpace;
|
|
3900
3637
|
} else {
|
|
3901
|
-
// embed the color palette in the PDF as an object stream
|
|
3902
3638
|
const palette = this.document.ref();
|
|
3903
3639
|
palette.end(Buffer.from(this.image.palette));
|
|
3904
|
-
|
|
3905
|
-
// build the color space array for the image
|
|
3906
3640
|
this.obj.data['ColorSpace'] = ['Indexed', 'DeviceRGB', this.image.palette.length / 3 - 1, palette];
|
|
3907
3641
|
}
|
|
3908
|
-
|
|
3909
|
-
// For PNG color types 0, 2 and 3, the transparency data is stored in
|
|
3910
|
-
// a dedicated PNG chunk.
|
|
3911
3642
|
if (this.image.transparency.grayscale != null) {
|
|
3912
|
-
// Use Color Key Masking (spec section 4.8.5)
|
|
3913
|
-
// An array with N elements, where N is two times the number of color components.
|
|
3914
3643
|
const val = this.image.transparency.grayscale;
|
|
3915
3644
|
this.obj.data['Mask'] = [val, val];
|
|
3916
3645
|
} else if (this.image.transparency.rgb) {
|
|
3917
|
-
// Use Color Key Masking (spec section 4.8.5)
|
|
3918
|
-
// An array with N elements, where N is two times the number of color components.
|
|
3919
3646
|
const {
|
|
3920
3647
|
rgb
|
|
3921
3648
|
} = this.image.transparency;
|
|
@@ -3925,14 +3652,9 @@ class PNGImage {
|
|
|
3925
3652
|
}
|
|
3926
3653
|
this.obj.data['Mask'] = mask;
|
|
3927
3654
|
} else if (this.image.transparency.indexed) {
|
|
3928
|
-
// Create a transparency SMask for the image based on the data
|
|
3929
|
-
// in the PLTE and tRNS sections. See below for details on SMasks.
|
|
3930
3655
|
dataDecoded = true;
|
|
3931
3656
|
return this.loadIndexedAlphaChannel();
|
|
3932
3657
|
} else if (hasAlphaChannel) {
|
|
3933
|
-
// For PNG color types 4 and 6, the transparency data is stored as a alpha
|
|
3934
|
-
// channel mixed in with the main image data. Separate this data out into an
|
|
3935
|
-
// SMask object and store it separately in the PDF.
|
|
3936
3658
|
dataDecoded = true;
|
|
3937
3659
|
return this.splitAlphaChannel();
|
|
3938
3660
|
}
|
|
@@ -3956,11 +3678,7 @@ class PNGImage {
|
|
|
3956
3678
|
sMask.end(this.alphaChannel);
|
|
3957
3679
|
this.obj.data['SMask'] = sMask;
|
|
3958
3680
|
}
|
|
3959
|
-
|
|
3960
|
-
// add the actual image data
|
|
3961
3681
|
this.obj.end(this.imgData);
|
|
3962
|
-
|
|
3963
|
-
// free memory
|
|
3964
3682
|
this.image = null;
|
|
3965
3683
|
return this.imgData = null;
|
|
3966
3684
|
}
|
|
@@ -3973,7 +3691,6 @@ class PNGImage {
|
|
|
3973
3691
|
const alphaChannel = Buffer.alloc(pixelCount);
|
|
3974
3692
|
let i = p = a = 0;
|
|
3975
3693
|
const len = pixels.length;
|
|
3976
|
-
// For 16bit images copy only most significant byte (MSB) - PNG data is always stored in network byte order (MSB first)
|
|
3977
3694
|
const skipByteCount = this.image.bits === 16 ? 1 : 0;
|
|
3978
3695
|
while (i < len) {
|
|
3979
3696
|
for (let colorIndex = 0; colorIndex < colorCount; colorIndex++) {
|
|
@@ -4008,10 +3725,6 @@ class PNGImage {
|
|
|
4008
3725
|
}
|
|
4009
3726
|
}
|
|
4010
3727
|
|
|
4011
|
-
/*
|
|
4012
|
-
PDFImage - embeds images in PDF documents
|
|
4013
|
-
By Devon Govett
|
|
4014
|
-
*/
|
|
4015
3728
|
class PDFImage {
|
|
4016
3729
|
static open(src, label) {
|
|
4017
3730
|
let data;
|
|
@@ -4043,17 +3756,16 @@ class PDFImage {
|
|
|
4043
3756
|
var ImagesMixin = {
|
|
4044
3757
|
initImages() {
|
|
4045
3758
|
this._imageRegistry = {};
|
|
4046
|
-
|
|
3759
|
+
this._imageCount = 0;
|
|
4047
3760
|
},
|
|
4048
3761
|
image(src, x, y, options = {}) {
|
|
4049
|
-
let bh, bp, bw, image, ip, left, left1,
|
|
3762
|
+
let bh, bp, bw, image, ip, left, left1, originX, originY;
|
|
4050
3763
|
if (typeof x === 'object') {
|
|
4051
3764
|
options = x;
|
|
4052
3765
|
x = null;
|
|
4053
3766
|
}
|
|
4054
|
-
|
|
4055
|
-
// Ignore orientation based on document options or image options
|
|
4056
3767
|
const ignoreOrientation = options.ignoreOrientation || options.ignoreOrientation !== false && this.options.ignoreOrientation;
|
|
3768
|
+
const inDocumentFlow = typeof y !== 'number';
|
|
4057
3769
|
x = (left = x != null ? x : options.x) != null ? left : this.x;
|
|
4058
3770
|
y = (left1 = y != null ? y : options.y) != null ? left1 : this.y;
|
|
4059
3771
|
if (typeof src === 'string') {
|
|
@@ -4076,8 +3788,6 @@ var ImagesMixin = {
|
|
|
4076
3788
|
width,
|
|
4077
3789
|
height
|
|
4078
3790
|
} = image;
|
|
4079
|
-
|
|
4080
|
-
// If EXIF orientation calls for it, swap width and height
|
|
4081
3791
|
if (!ignoreOrientation && image.orientation > 4) {
|
|
4082
3792
|
[width, height] = [height, width];
|
|
4083
3793
|
}
|
|
@@ -4129,80 +3839,70 @@ var ImagesMixin = {
|
|
|
4129
3839
|
y = y + bh - h;
|
|
4130
3840
|
}
|
|
4131
3841
|
}
|
|
3842
|
+
let rotateAngle = 0;
|
|
3843
|
+
let xTransform = x;
|
|
3844
|
+
let yTransform = y;
|
|
3845
|
+
let hTransform = h;
|
|
3846
|
+
let wTransform = w;
|
|
4132
3847
|
if (!ignoreOrientation) {
|
|
4133
3848
|
switch (image.orientation) {
|
|
4134
|
-
// No orientation (need to flip image, though, because of the default transform matrix on the document)
|
|
4135
3849
|
default:
|
|
4136
3850
|
case 1:
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
rotateAngle = 0;
|
|
3851
|
+
hTransform = -h;
|
|
3852
|
+
yTransform += h;
|
|
4140
3853
|
break;
|
|
4141
|
-
// Flip Horizontal
|
|
4142
3854
|
case 2:
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
rotateAngle = 0;
|
|
3855
|
+
wTransform = -w;
|
|
3856
|
+
hTransform = -h;
|
|
3857
|
+
xTransform += w;
|
|
3858
|
+
yTransform += h;
|
|
4148
3859
|
break;
|
|
4149
|
-
// Rotate 180 degrees
|
|
4150
3860
|
case 3:
|
|
4151
3861
|
originX = x;
|
|
4152
3862
|
originY = y;
|
|
4153
|
-
|
|
4154
|
-
|
|
3863
|
+
hTransform = -h;
|
|
3864
|
+
xTransform -= w;
|
|
4155
3865
|
rotateAngle = 180;
|
|
4156
3866
|
break;
|
|
4157
|
-
// Flip vertical
|
|
4158
3867
|
case 4:
|
|
4159
|
-
// Do nothing, image will be flipped
|
|
4160
|
-
|
|
4161
3868
|
break;
|
|
4162
|
-
// Flip horizontally and rotate 270 degrees CW
|
|
4163
3869
|
case 5:
|
|
4164
3870
|
originX = x;
|
|
4165
3871
|
originY = y;
|
|
4166
|
-
|
|
4167
|
-
|
|
3872
|
+
wTransform = h;
|
|
3873
|
+
hTransform = w;
|
|
3874
|
+
yTransform -= hTransform;
|
|
4168
3875
|
rotateAngle = 90;
|
|
4169
3876
|
break;
|
|
4170
|
-
// Rotate 90 degrees CW
|
|
4171
3877
|
case 6:
|
|
4172
3878
|
originX = x;
|
|
4173
3879
|
originY = y;
|
|
4174
|
-
|
|
4175
|
-
|
|
3880
|
+
wTransform = h;
|
|
3881
|
+
hTransform = -w;
|
|
4176
3882
|
rotateAngle = 90;
|
|
4177
3883
|
break;
|
|
4178
|
-
// Flip horizontally and rotate 90 degrees CW
|
|
4179
3884
|
case 7:
|
|
4180
3885
|
originX = x;
|
|
4181
3886
|
originY = y;
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
x -= w;
|
|
3887
|
+
hTransform = -w;
|
|
3888
|
+
wTransform = -h;
|
|
3889
|
+
xTransform += h;
|
|
4186
3890
|
rotateAngle = 90;
|
|
4187
3891
|
break;
|
|
4188
|
-
// Rotate 270 degrees CW
|
|
4189
3892
|
case 8:
|
|
4190
3893
|
originX = x;
|
|
4191
3894
|
originY = y;
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
3895
|
+
wTransform = h;
|
|
3896
|
+
hTransform = -w;
|
|
3897
|
+
xTransform -= h;
|
|
3898
|
+
yTransform += w;
|
|
4196
3899
|
rotateAngle = -90;
|
|
4197
3900
|
break;
|
|
4198
3901
|
}
|
|
4199
3902
|
} else {
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
rotateAngle = 0;
|
|
3903
|
+
hTransform = -h;
|
|
3904
|
+
yTransform += h;
|
|
4203
3905
|
}
|
|
4204
|
-
|
|
4205
|
-
// create link annotations if the link option is given
|
|
4206
3906
|
if (options.link != null) {
|
|
4207
3907
|
this.link(x, y, w, h, options.link);
|
|
4208
3908
|
}
|
|
@@ -4212,9 +3912,7 @@ var ImagesMixin = {
|
|
|
4212
3912
|
if (options.destination != null) {
|
|
4213
3913
|
this.addNamedDestination(options.destination, 'XYZ', x, y, null);
|
|
4214
3914
|
}
|
|
4215
|
-
|
|
4216
|
-
// Set the current y position to below the image if it is in the document flow
|
|
4217
|
-
if (this.y === y) {
|
|
3915
|
+
if (inDocumentFlow) {
|
|
4218
3916
|
this.y += h;
|
|
4219
3917
|
}
|
|
4220
3918
|
this.save();
|
|
@@ -4223,7 +3921,7 @@ var ImagesMixin = {
|
|
|
4223
3921
|
origin: [originX, originY]
|
|
4224
3922
|
});
|
|
4225
3923
|
}
|
|
4226
|
-
this.transform(
|
|
3924
|
+
this.transform(wTransform, 0, 0, hTransform, xTransform, yTransform);
|
|
4227
3925
|
this.addContent(`/${image.label} Do`);
|
|
4228
3926
|
this.restore();
|
|
4229
3927
|
return this;
|
|
@@ -4249,19 +3947,17 @@ var AnnotationsMixin = {
|
|
|
4249
3947
|
options.Rect = this._convertRect(x, y, w, h);
|
|
4250
3948
|
options.Border = [0, 0, 0];
|
|
4251
3949
|
if (options.Subtype === 'Link' && typeof options.F === 'undefined') {
|
|
4252
|
-
options.F = 1 << 2;
|
|
3950
|
+
options.F = 1 << 2;
|
|
4253
3951
|
}
|
|
4254
3952
|
if (options.Subtype !== 'Link') {
|
|
4255
3953
|
if (options.C == null) {
|
|
4256
3954
|
options.C = this._normalizeColor(options.color || [0, 0, 0]);
|
|
4257
3955
|
}
|
|
4258
|
-
}
|
|
3956
|
+
}
|
|
4259
3957
|
delete options.color;
|
|
4260
3958
|
if (typeof options.Dest === 'string') {
|
|
4261
3959
|
options.Dest = new String(options.Dest);
|
|
4262
3960
|
}
|
|
4263
|
-
|
|
4264
|
-
// Capitalize keys
|
|
4265
3961
|
for (let key in options) {
|
|
4266
3962
|
const val = options[key];
|
|
4267
3963
|
options[key[0].toUpperCase() + key.slice(1)] = val;
|
|
@@ -4294,7 +3990,6 @@ var AnnotationsMixin = {
|
|
|
4294
3990
|
link(x, y, w, h, url, options = {}) {
|
|
4295
3991
|
options.Subtype = 'Link';
|
|
4296
3992
|
if (typeof url === 'number') {
|
|
4297
|
-
// Link to a page in the document (the page must already exist)
|
|
4298
3993
|
const pages = this._root.data.Pages.data;
|
|
4299
3994
|
if (url >= 0 && url < pages.Kids.length) {
|
|
4300
3995
|
options.A = this.ref({
|
|
@@ -4306,7 +4001,6 @@ var AnnotationsMixin = {
|
|
|
4306
4001
|
throw new Error(`The document has no page ${url}`);
|
|
4307
4002
|
}
|
|
4308
4003
|
} else {
|
|
4309
|
-
// Link to an external url
|
|
4310
4004
|
options.A = this.ref({
|
|
4311
4005
|
S: 'URI',
|
|
4312
4006
|
URI: new String(url)
|
|
@@ -4359,14 +4053,11 @@ var AnnotationsMixin = {
|
|
|
4359
4053
|
return this.annotate(x, y, w, h, options);
|
|
4360
4054
|
},
|
|
4361
4055
|
fileAnnotation(x, y, w, h, file = {}, options = {}) {
|
|
4362
|
-
// create hidden file
|
|
4363
4056
|
const filespec = this.file(file.src, Object.assign({
|
|
4364
4057
|
hidden: true
|
|
4365
4058
|
}, file));
|
|
4366
4059
|
options.Subtype = 'FileAttachment';
|
|
4367
4060
|
options.FS = filespec;
|
|
4368
|
-
|
|
4369
|
-
// add description from filespec unless description (Contents) has already been set
|
|
4370
4061
|
if (options.Contents) {
|
|
4371
4062
|
options.Contents = new String(options.Contents);
|
|
4372
4063
|
} else if (filespec.data.Desc) {
|
|
@@ -4375,14 +4066,9 @@ var AnnotationsMixin = {
|
|
|
4375
4066
|
return this.annotate(x, y, w, h, options);
|
|
4376
4067
|
},
|
|
4377
4068
|
_convertRect(x1, y1, w, h) {
|
|
4378
|
-
// flip y1 and y2
|
|
4379
4069
|
let y2 = y1;
|
|
4380
4070
|
y1 += h;
|
|
4381
|
-
|
|
4382
|
-
// make x2
|
|
4383
4071
|
let x2 = x1 + w;
|
|
4384
|
-
|
|
4385
|
-
// apply current transformation matrix to points
|
|
4386
4072
|
const [m0, m1, m2, m3, m4, m5] = this._ctm;
|
|
4387
4073
|
x1 = m0 * x1 + m2 * y1 + m4;
|
|
4388
4074
|
y1 = m1 * x1 + m3 * y1 + m5;
|
|
@@ -4444,7 +4130,7 @@ class PDFOutline {
|
|
|
4444
4130
|
|
|
4445
4131
|
var OutlineMixin = {
|
|
4446
4132
|
initOutline() {
|
|
4447
|
-
|
|
4133
|
+
this.outline = new PDFOutline(this, null, null, null);
|
|
4448
4134
|
},
|
|
4449
4135
|
endOutline() {
|
|
4450
4136
|
this.outline.endOutline();
|
|
@@ -4455,11 +4141,6 @@ var OutlineMixin = {
|
|
|
4455
4141
|
}
|
|
4456
4142
|
};
|
|
4457
4143
|
|
|
4458
|
-
/*
|
|
4459
|
-
PDFStructureContent - a reference to a marked structure content
|
|
4460
|
-
By Ben Schmidt
|
|
4461
|
-
*/
|
|
4462
|
-
|
|
4463
4144
|
class PDFStructureContent {
|
|
4464
4145
|
constructor(pageRef, mcid) {
|
|
4465
4146
|
this.refs = [{
|
|
@@ -4472,10 +4153,6 @@ class PDFStructureContent {
|
|
|
4472
4153
|
}
|
|
4473
4154
|
}
|
|
4474
4155
|
|
|
4475
|
-
/*
|
|
4476
|
-
PDFStructureElement - represents an element in the PDF logical structure tree
|
|
4477
|
-
By Ben Schmidt
|
|
4478
|
-
*/
|
|
4479
4156
|
class PDFStructureElement {
|
|
4480
4157
|
constructor(document, type, options = {}, children = null) {
|
|
4481
4158
|
this.document = document;
|
|
@@ -4483,7 +4160,6 @@ class PDFStructureElement {
|
|
|
4483
4160
|
this._ended = false;
|
|
4484
4161
|
this._flushed = false;
|
|
4485
4162
|
this.dictionary = document.ref({
|
|
4486
|
-
// Type: "StructElem",
|
|
4487
4163
|
S: type
|
|
4488
4164
|
});
|
|
4489
4165
|
const data = this.dictionary.data;
|
|
@@ -4532,7 +4208,6 @@ class PDFStructureElement {
|
|
|
4532
4208
|
this._addContentToParentTree(child);
|
|
4533
4209
|
}
|
|
4534
4210
|
if (typeof child === 'function' && this._attached) {
|
|
4535
|
-
// _contentForClosure() adds the content to the parent tree
|
|
4536
4211
|
child = this._contentForClosure(child);
|
|
4537
4212
|
}
|
|
4538
4213
|
this._children.push(child);
|
|
@@ -4608,10 +4283,6 @@ class PDFStructureElement {
|
|
|
4608
4283
|
this.dictionary.data.K = [];
|
|
4609
4284
|
this._children.forEach(child => this._flushChild(child));
|
|
4610
4285
|
this.dictionary.end();
|
|
4611
|
-
|
|
4612
|
-
// free memory used by children; the dictionary itself may still be
|
|
4613
|
-
// referenced by a parent structure element or root, but we can
|
|
4614
|
-
// at least trim the tree here
|
|
4615
4286
|
this._children = [];
|
|
4616
4287
|
this.dictionary.data.K = null;
|
|
4617
4288
|
this._flushed = true;
|
|
@@ -4632,7 +4303,7 @@ class PDFStructureElement {
|
|
|
4632
4303
|
this.dictionary.data.K.push(mcid);
|
|
4633
4304
|
} else {
|
|
4634
4305
|
this.dictionary.data.K.push({
|
|
4635
|
-
Type:
|
|
4306
|
+
Type: 'MCR',
|
|
4636
4307
|
Pg: pageRef,
|
|
4637
4308
|
MCID: mcid
|
|
4638
4309
|
});
|
|
@@ -4642,25 +4313,18 @@ class PDFStructureElement {
|
|
|
4642
4313
|
}
|
|
4643
4314
|
}
|
|
4644
4315
|
|
|
4645
|
-
/*
|
|
4646
|
-
PDFNumberTree - represents a number tree object
|
|
4647
|
-
*/
|
|
4648
4316
|
class PDFNumberTree extends PDFTree {
|
|
4649
4317
|
_compareKeys(a, b) {
|
|
4650
4318
|
return parseInt(a) - parseInt(b);
|
|
4651
4319
|
}
|
|
4652
4320
|
_keysName() {
|
|
4653
|
-
return
|
|
4321
|
+
return 'Nums';
|
|
4654
4322
|
}
|
|
4655
4323
|
_dataForKey(k) {
|
|
4656
4324
|
return parseInt(k);
|
|
4657
4325
|
}
|
|
4658
4326
|
}
|
|
4659
4327
|
|
|
4660
|
-
/*
|
|
4661
|
-
Markings mixin - support marked content sequences in content streams
|
|
4662
|
-
By Ben Schmidt
|
|
4663
|
-
*/
|
|
4664
4328
|
var MarkingsMixin = {
|
|
4665
4329
|
initMarkings(options) {
|
|
4666
4330
|
this.structChildren = [];
|
|
@@ -4796,7 +4460,6 @@ var MarkingsMixin = {
|
|
|
4796
4460
|
return this.getStructTreeRoot().data.ParentTree;
|
|
4797
4461
|
},
|
|
4798
4462
|
createStructParentTreeNextKey() {
|
|
4799
|
-
// initialise the MarkInfo dictionary
|
|
4800
4463
|
this.getMarkInfoDictionary();
|
|
4801
4464
|
const structTreeRoot = this.getStructTreeRoot();
|
|
4802
4465
|
const key = structTreeRoot.data.ParentTreeNextKey++;
|
|
@@ -4860,10 +4523,6 @@ const FORMAT_DEFAULT = {
|
|
|
4860
4523
|
}
|
|
4861
4524
|
};
|
|
4862
4525
|
var AcroFormMixin = {
|
|
4863
|
-
/**
|
|
4864
|
-
* Must call if adding AcroForms to a document. Must also call font() before
|
|
4865
|
-
* this method to set the default font.
|
|
4866
|
-
*/
|
|
4867
4526
|
initForm() {
|
|
4868
4527
|
if (!this._font) {
|
|
4869
4528
|
throw new Error('Must set a font before calling initForm method');
|
|
@@ -4886,9 +4545,6 @@ var AcroFormMixin = {
|
|
|
4886
4545
|
this._root.data.AcroForm = AcroForm;
|
|
4887
4546
|
return this;
|
|
4888
4547
|
},
|
|
4889
|
-
/**
|
|
4890
|
-
* Called automatically by document.js
|
|
4891
|
-
*/
|
|
4892
4548
|
endAcroForm() {
|
|
4893
4549
|
if (this._root.data.AcroForm) {
|
|
4894
4550
|
if (!Object.keys(this._acroform.fonts).length && !this._acroform.defaultFont) {
|
|
@@ -4914,38 +4570,18 @@ var AcroFormMixin = {
|
|
|
4914
4570
|
}
|
|
4915
4571
|
return this;
|
|
4916
4572
|
},
|
|
4917
|
-
/**
|
|
4918
|
-
* Creates and adds a form field to the document. Form fields are intermediate
|
|
4919
|
-
* nodes in a PDF form that are used to specify form name heirarchy and form
|
|
4920
|
-
* value defaults.
|
|
4921
|
-
* @param {string} name - field name (T attribute in field dictionary)
|
|
4922
|
-
* @param {object} options - other attributes to include in field dictionary
|
|
4923
|
-
*/
|
|
4924
4573
|
formField(name, options = {}) {
|
|
4925
4574
|
let fieldDict = this._fieldDict(name, null, options);
|
|
4926
4575
|
let fieldRef = this.ref(fieldDict);
|
|
4927
4576
|
this._addToParent(fieldRef);
|
|
4928
4577
|
return fieldRef;
|
|
4929
4578
|
},
|
|
4930
|
-
/**
|
|
4931
|
-
* Creates and adds a Form Annotation to the document. Form annotations are
|
|
4932
|
-
* called Widget annotations internally within a PDF file.
|
|
4933
|
-
* @param {string} name - form field name (T attribute of widget annotation
|
|
4934
|
-
* dictionary)
|
|
4935
|
-
* @param {number} x
|
|
4936
|
-
* @param {number} y
|
|
4937
|
-
* @param {number} w
|
|
4938
|
-
* @param {number} h
|
|
4939
|
-
* @param {object} options
|
|
4940
|
-
*/
|
|
4941
4579
|
formAnnotation(name, type, x, y, w, h, options = {}) {
|
|
4942
4580
|
let fieldDict = this._fieldDict(name, type, options);
|
|
4943
4581
|
fieldDict.Subtype = 'Widget';
|
|
4944
4582
|
if (fieldDict.F === undefined) {
|
|
4945
|
-
fieldDict.F = 4;
|
|
4583
|
+
fieldDict.F = 4;
|
|
4946
4584
|
}
|
|
4947
|
-
|
|
4948
|
-
// Add Field annot to page, and get it's ref
|
|
4949
4585
|
this.annotate(x, y, w, h, fieldDict);
|
|
4950
4586
|
let annotRef = this.page.annotations[this.page.annotations.length - 1];
|
|
4951
4587
|
return this._addToParent(annotRef);
|
|
@@ -5106,23 +4742,18 @@ var AcroFormMixin = {
|
|
|
5106
4742
|
delete options.align;
|
|
5107
4743
|
}
|
|
5108
4744
|
if (result !== 0) {
|
|
5109
|
-
options.Q = result;
|
|
4745
|
+
options.Q = result;
|
|
5110
4746
|
}
|
|
5111
4747
|
return options;
|
|
5112
4748
|
},
|
|
5113
4749
|
_resolveFont(options) {
|
|
5114
|
-
// add current font to document-level AcroForm dict if necessary
|
|
5115
4750
|
if (this._acroform.fonts[this._font.id] == null) {
|
|
5116
4751
|
this._acroform.fonts[this._font.id] = this._font.ref();
|
|
5117
4752
|
}
|
|
5118
|
-
|
|
5119
|
-
// add current font to field's resource dict (RD) if not the default acroform font
|
|
5120
4753
|
if (this._acroform.defaultFont !== this._font.name) {
|
|
5121
4754
|
options.DR = {
|
|
5122
4755
|
Font: {}
|
|
5123
4756
|
};
|
|
5124
|
-
|
|
5125
|
-
// Get the fontSize option. If not set use auto sizing
|
|
5126
4757
|
const fontSize = options.fontSize || 0;
|
|
5127
4758
|
options.DR.Font[this._font.id] = this._font.ref();
|
|
5128
4759
|
options.DA = new String(`/${this._font.id} ${fontSize} Tf 0 g`);
|
|
@@ -5174,19 +4805,6 @@ var AcroFormMixin = {
|
|
|
5174
4805
|
};
|
|
5175
4806
|
|
|
5176
4807
|
var AttachmentsMixin = {
|
|
5177
|
-
/**
|
|
5178
|
-
* Embed contents of `src` in PDF
|
|
5179
|
-
* @param {Buffer | ArrayBuffer | string} src input Buffer, ArrayBuffer, base64 encoded string or path to file
|
|
5180
|
-
* @param {object} options
|
|
5181
|
-
* * options.name: filename to be shown in PDF, will use `src` if none set
|
|
5182
|
-
* * options.type: filetype to be shown in PDF
|
|
5183
|
-
* * options.description: description to be shown in PDF
|
|
5184
|
-
* * options.hidden: if true, do not add attachment to EmbeddedFiles dictionary. Useful for file attachment annotations
|
|
5185
|
-
* * options.creationDate: override creation date
|
|
5186
|
-
* * options.modifiedDate: override modified date
|
|
5187
|
-
* * options.relationship: Relationship between the PDF document and its attached file. Can be 'Alternative', 'Data', 'Source', 'Supplement' or 'Unspecified'.
|
|
5188
|
-
* @returns filespec reference
|
|
5189
|
-
*/
|
|
5190
4808
|
file(src, options = {}) {
|
|
5191
4809
|
options.name = options.name || src;
|
|
5192
4810
|
options.relationship = options.relationship || 'Unspecified';
|
|
@@ -5214,8 +4832,6 @@ var AttachmentsMixin = {
|
|
|
5214
4832
|
if (!data) {
|
|
5215
4833
|
throw new Error(`Could not read contents of file at filepath ${src}`);
|
|
5216
4834
|
}
|
|
5217
|
-
|
|
5218
|
-
// update CreationDate and ModDate
|
|
5219
4835
|
const {
|
|
5220
4836
|
birthtime,
|
|
5221
4837
|
ctime
|
|
@@ -5224,26 +4840,18 @@ var AttachmentsMixin = {
|
|
|
5224
4840
|
refBody.Params.ModDate = ctime;
|
|
5225
4841
|
}
|
|
5226
4842
|
}
|
|
5227
|
-
|
|
5228
|
-
// override creation date and modified date
|
|
5229
4843
|
if (options.creationDate instanceof Date) {
|
|
5230
4844
|
refBody.Params.CreationDate = options.creationDate;
|
|
5231
4845
|
}
|
|
5232
4846
|
if (options.modifiedDate instanceof Date) {
|
|
5233
4847
|
refBody.Params.ModDate = options.modifiedDate;
|
|
5234
4848
|
}
|
|
5235
|
-
// add optional subtype
|
|
5236
4849
|
if (options.type) {
|
|
5237
4850
|
refBody.Subtype = options.type.replace('/', '#2F');
|
|
5238
4851
|
}
|
|
5239
|
-
|
|
5240
|
-
// add checksum and size information
|
|
5241
4852
|
const checksum = CryptoJS.MD5(CryptoJS.lib.WordArray.create(new Uint8Array(data)));
|
|
5242
4853
|
refBody.Params.CheckSum = new String(checksum);
|
|
5243
4854
|
refBody.Params.Size = data.byteLength;
|
|
5244
|
-
|
|
5245
|
-
// save some space when embedding the same file again
|
|
5246
|
-
// if a file with the same name and metadata exists, reuse its reference
|
|
5247
4855
|
let ref;
|
|
5248
4856
|
if (!this._fileRegistry) this._fileRegistry = {};
|
|
5249
4857
|
let file = this._fileRegistry[options.name];
|
|
@@ -5257,7 +4865,6 @@ var AttachmentsMixin = {
|
|
|
5257
4865
|
ref
|
|
5258
4866
|
};
|
|
5259
4867
|
}
|
|
5260
|
-
// add filespec for embedded file
|
|
5261
4868
|
const fileSpecBody = {
|
|
5262
4869
|
Type: 'Filespec',
|
|
5263
4870
|
AFRelationship: options.relationship,
|
|
@@ -5275,8 +4882,6 @@ var AttachmentsMixin = {
|
|
|
5275
4882
|
if (!options.hidden) {
|
|
5276
4883
|
this.addNamedEmbeddedFile(options.name, filespec);
|
|
5277
4884
|
}
|
|
5278
|
-
|
|
5279
|
-
// Add file to the catalogue to be PDF/A3 compliant
|
|
5280
4885
|
if (this._root.data.AF) {
|
|
5281
4886
|
this._root.data.AF.push(filespec);
|
|
5282
4887
|
} else {
|
|
@@ -5285,8 +4890,6 @@ var AttachmentsMixin = {
|
|
|
5285
4890
|
return filespec;
|
|
5286
4891
|
}
|
|
5287
4892
|
};
|
|
5288
|
-
|
|
5289
|
-
/** check two embedded file metadata objects for equality */
|
|
5290
4893
|
function isEqual(a, b) {
|
|
5291
4894
|
return a.Subtype === b.Subtype && a.Params.CheckSum.toString() === b.Params.CheckSum.toString() && a.Params.Size === b.Params.Size && a.Params.CreationDate.getTime() === b.Params.CreationDate.getTime() && (a.Params.ModDate === undefined && b.Params.ModDate === undefined || a.Params.ModDate.getTime() === b.Params.ModDate.getTime());
|
|
5292
4895
|
}
|
|
@@ -5297,7 +4900,6 @@ var PDFA = {
|
|
|
5297
4900
|
this.subset_conformance = pSubset.charAt(pSubset.length - 1).toUpperCase();
|
|
5298
4901
|
this.subset = parseInt(pSubset.charAt(pSubset.length - 2));
|
|
5299
4902
|
} else {
|
|
5300
|
-
// Default to Basic conformance when user doesn't specify
|
|
5301
4903
|
this.subset_conformance = 'B';
|
|
5302
4904
|
this.subset = parseInt(pSubset.charAt(pSubset.length - 1));
|
|
5303
4905
|
}
|
|
@@ -5382,6 +4984,642 @@ var SubsetMixin = {
|
|
|
5382
4984
|
}
|
|
5383
4985
|
};
|
|
5384
4986
|
|
|
4987
|
+
const ROW_FIELDS = ['height', 'minHeight', 'maxHeight'];
|
|
4988
|
+
const COLUMN_FIELDS = ['width', 'minWidth', 'maxWidth'];
|
|
4989
|
+
function memoize(fn, maxSize) {
|
|
4990
|
+
const cache = new Map();
|
|
4991
|
+
return function (...args) {
|
|
4992
|
+
const key = args[0];
|
|
4993
|
+
if (!cache.has(key)) {
|
|
4994
|
+
cache.set(key, fn(...args));
|
|
4995
|
+
if (cache.size > maxSize) cache.delete(cache.keys().next());
|
|
4996
|
+
}
|
|
4997
|
+
return cache.get(key);
|
|
4998
|
+
};
|
|
4999
|
+
}
|
|
5000
|
+
function isObject(item) {
|
|
5001
|
+
return item && typeof item === 'object' && !Array.isArray(item);
|
|
5002
|
+
}
|
|
5003
|
+
function deepMerge(target, ...sources) {
|
|
5004
|
+
if (!isObject(target)) return target;
|
|
5005
|
+
target = deepClone(target);
|
|
5006
|
+
for (const source of sources) {
|
|
5007
|
+
if (isObject(source)) {
|
|
5008
|
+
for (const key in source) {
|
|
5009
|
+
if (isObject(source[key])) {
|
|
5010
|
+
if (!(key in target)) target[key] = {};
|
|
5011
|
+
target[key] = deepMerge(target[key], source[key]);
|
|
5012
|
+
} else if (source[key] !== undefined) {
|
|
5013
|
+
target[key] = deepClone(source[key]);
|
|
5014
|
+
}
|
|
5015
|
+
}
|
|
5016
|
+
}
|
|
5017
|
+
}
|
|
5018
|
+
return target;
|
|
5019
|
+
}
|
|
5020
|
+
function deepClone(obj) {
|
|
5021
|
+
let result = obj;
|
|
5022
|
+
if (typeof obj == 'object') {
|
|
5023
|
+
result = Array.isArray(obj) ? [] : {};
|
|
5024
|
+
for (const key in obj) result[key] = deepClone(obj[key]);
|
|
5025
|
+
}
|
|
5026
|
+
return result;
|
|
5027
|
+
}
|
|
5028
|
+
|
|
5029
|
+
function normalizedDefaultStyle(defaultStyleInternal) {
|
|
5030
|
+
let defaultStyle = defaultStyleInternal;
|
|
5031
|
+
if (typeof defaultStyle !== 'object') defaultStyle = {
|
|
5032
|
+
text: defaultStyle
|
|
5033
|
+
};
|
|
5034
|
+
const defaultRowStyle = Object.fromEntries(Object.entries(defaultStyle).filter(([k]) => ROW_FIELDS.includes(k)));
|
|
5035
|
+
const defaultColStyle = Object.fromEntries(Object.entries(defaultStyle).filter(([k]) => COLUMN_FIELDS.includes(k)));
|
|
5036
|
+
defaultStyle.padding = normalizeSides(defaultStyle.padding);
|
|
5037
|
+
defaultStyle.border = normalizeSides(defaultStyle.border);
|
|
5038
|
+
defaultStyle.borderColor = normalizeSides(defaultStyle.borderColor);
|
|
5039
|
+
defaultStyle.align = normalizeAlignment(defaultStyle.align);
|
|
5040
|
+
return {
|
|
5041
|
+
defaultStyle,
|
|
5042
|
+
defaultRowStyle,
|
|
5043
|
+
defaultColStyle
|
|
5044
|
+
};
|
|
5045
|
+
}
|
|
5046
|
+
function normalizedRowStyle(defaultRowStyle, rowStyleInternal, i) {
|
|
5047
|
+
let rowStyle = rowStyleInternal(i);
|
|
5048
|
+
if (rowStyle == null || typeof rowStyle !== 'object') {
|
|
5049
|
+
rowStyle = {
|
|
5050
|
+
height: rowStyle
|
|
5051
|
+
};
|
|
5052
|
+
}
|
|
5053
|
+
rowStyle.padding = normalizeSides(rowStyle.padding);
|
|
5054
|
+
rowStyle.border = normalizeSides(rowStyle.border);
|
|
5055
|
+
rowStyle.borderColor = normalizeSides(rowStyle.borderColor);
|
|
5056
|
+
rowStyle.align = normalizeAlignment(rowStyle.align);
|
|
5057
|
+
rowStyle = deepMerge(defaultRowStyle, rowStyle);
|
|
5058
|
+
const document = this.document;
|
|
5059
|
+
const page = document.page;
|
|
5060
|
+
const contentHeight = page.contentHeight;
|
|
5061
|
+
if (rowStyle.height == null || rowStyle.height === 'auto') {
|
|
5062
|
+
rowStyle.height = 'auto';
|
|
5063
|
+
} else {
|
|
5064
|
+
rowStyle.height = document.sizeToPoint(rowStyle.height, 0, page, contentHeight);
|
|
5065
|
+
}
|
|
5066
|
+
rowStyle.minHeight = document.sizeToPoint(rowStyle.minHeight, 0, page, contentHeight);
|
|
5067
|
+
rowStyle.maxHeight = document.sizeToPoint(rowStyle.maxHeight, 0, page, contentHeight);
|
|
5068
|
+
return rowStyle;
|
|
5069
|
+
}
|
|
5070
|
+
function normalizedColumnStyle(defaultColStyle, colStyleInternal, i) {
|
|
5071
|
+
let colStyle = colStyleInternal(i);
|
|
5072
|
+
if (colStyle == null || typeof colStyle !== 'object') {
|
|
5073
|
+
colStyle = {
|
|
5074
|
+
width: colStyle
|
|
5075
|
+
};
|
|
5076
|
+
}
|
|
5077
|
+
colStyle.padding = normalizeSides(colStyle.padding);
|
|
5078
|
+
colStyle.border = normalizeSides(colStyle.border);
|
|
5079
|
+
colStyle.borderColor = normalizeSides(colStyle.borderColor);
|
|
5080
|
+
colStyle.align = normalizeAlignment(colStyle.align);
|
|
5081
|
+
colStyle = deepMerge(defaultColStyle, colStyle);
|
|
5082
|
+
if (colStyle.width == null || colStyle.width === '*') {
|
|
5083
|
+
colStyle.width = '*';
|
|
5084
|
+
} else {
|
|
5085
|
+
colStyle.width = this.document.sizeToPoint(colStyle.width, 0, this.document.page, this._maxWidth);
|
|
5086
|
+
}
|
|
5087
|
+
colStyle.minWidth = this.document.sizeToPoint(colStyle.minWidth, 0, this.document.page, this._maxWidth);
|
|
5088
|
+
colStyle.maxWidth = this.document.sizeToPoint(colStyle.maxWidth, 0, this.document.page, this._maxWidth);
|
|
5089
|
+
return colStyle;
|
|
5090
|
+
}
|
|
5091
|
+
function normalizeAlignment(align) {
|
|
5092
|
+
return align == null || typeof align === 'string' ? {
|
|
5093
|
+
x: align,
|
|
5094
|
+
y: align
|
|
5095
|
+
} : align;
|
|
5096
|
+
}
|
|
5097
|
+
|
|
5098
|
+
function normalizeTable() {
|
|
5099
|
+
const doc = this.document;
|
|
5100
|
+
const opts = this.opts;
|
|
5101
|
+
let index = doc._tableIndex++;
|
|
5102
|
+
this._id = new String(opts.id ?? `table-${index}`);
|
|
5103
|
+
this._position = {
|
|
5104
|
+
x: doc.sizeToPoint(opts.position?.x, doc.x),
|
|
5105
|
+
y: doc.sizeToPoint(opts.position?.y, doc.y)
|
|
5106
|
+
};
|
|
5107
|
+
this._maxWidth = doc.sizeToPoint(opts.maxWidth, doc.page.width - doc.page.margins.right - this._position.x);
|
|
5108
|
+
const {
|
|
5109
|
+
defaultStyle,
|
|
5110
|
+
defaultColStyle,
|
|
5111
|
+
defaultRowStyle
|
|
5112
|
+
} = normalizedDefaultStyle(opts.defaultStyle);
|
|
5113
|
+
this._defaultStyle = defaultStyle;
|
|
5114
|
+
let colStyle;
|
|
5115
|
+
if (opts.columnStyles) {
|
|
5116
|
+
if (Array.isArray(opts.columnStyles)) {
|
|
5117
|
+
colStyle = i => opts.columnStyles[i];
|
|
5118
|
+
} else if (typeof opts.columnStyles === 'function') {
|
|
5119
|
+
colStyle = memoize(i => opts.columnStyles(i), Infinity);
|
|
5120
|
+
} else if (typeof opts.columnStyles === 'object') {
|
|
5121
|
+
colStyle = () => opts.columnStyles;
|
|
5122
|
+
}
|
|
5123
|
+
}
|
|
5124
|
+
if (!colStyle) colStyle = () => ({});
|
|
5125
|
+
this._colStyle = normalizedColumnStyle.bind(this, defaultColStyle, colStyle);
|
|
5126
|
+
let rowStyle;
|
|
5127
|
+
if (opts.rowStyles) {
|
|
5128
|
+
if (Array.isArray(opts.rowStyles)) {
|
|
5129
|
+
rowStyle = i => opts.rowStyles[i];
|
|
5130
|
+
} else if (typeof opts.rowStyles === 'function') {
|
|
5131
|
+
rowStyle = memoize(i => opts.rowStyles(i), 10);
|
|
5132
|
+
} else if (typeof opts.rowStyles === 'object') {
|
|
5133
|
+
rowStyle = () => opts.rowStyles;
|
|
5134
|
+
}
|
|
5135
|
+
}
|
|
5136
|
+
if (!rowStyle) rowStyle = () => ({});
|
|
5137
|
+
this._rowStyle = normalizedRowStyle.bind(this, defaultRowStyle, rowStyle);
|
|
5138
|
+
}
|
|
5139
|
+
function normalizeText(text) {
|
|
5140
|
+
if (text != null) text = `${text}`;
|
|
5141
|
+
return text;
|
|
5142
|
+
}
|
|
5143
|
+
function normalizeCell(cell, rowIndex, colIndex) {
|
|
5144
|
+
const colStyle = this._colStyle(colIndex);
|
|
5145
|
+
let rowStyle = this._rowStyle(rowIndex);
|
|
5146
|
+
const font = deepMerge({}, colStyle.font, rowStyle.font, cell.font);
|
|
5147
|
+
const customFont = Object.values(font).filter(v => v != null).length > 0;
|
|
5148
|
+
const doc = this.document;
|
|
5149
|
+
const rollbackFont = doc._fontSource;
|
|
5150
|
+
const rollbackFontSize = doc._fontSize;
|
|
5151
|
+
const rollbackFontFamily = doc._fontFamily;
|
|
5152
|
+
if (customFont) {
|
|
5153
|
+
if (font.src) doc.font(font.src, font.family);
|
|
5154
|
+
if (font.size) doc.fontSize(font.size);
|
|
5155
|
+
rowStyle = this._rowStyle(rowIndex);
|
|
5156
|
+
}
|
|
5157
|
+
cell.padding = normalizeSides(cell.padding);
|
|
5158
|
+
cell.border = normalizeSides(cell.border);
|
|
5159
|
+
cell.borderColor = normalizeSides(cell.borderColor);
|
|
5160
|
+
const config = deepMerge(this._defaultStyle, colStyle, rowStyle, cell);
|
|
5161
|
+
config.rowIndex = rowIndex;
|
|
5162
|
+
config.colIndex = colIndex;
|
|
5163
|
+
config.font = font ?? {};
|
|
5164
|
+
config.customFont = customFont;
|
|
5165
|
+
config.text = normalizeText(config.text);
|
|
5166
|
+
config.rowSpan = config.rowSpan ?? 1;
|
|
5167
|
+
config.colSpan = config.colSpan ?? 1;
|
|
5168
|
+
config.padding = normalizeSides(config.padding, '0.25em', x => doc.sizeToPoint(x, '0.25em'));
|
|
5169
|
+
config.border = normalizeSides(config.border, 1, x => doc.sizeToPoint(x, 1));
|
|
5170
|
+
config.borderColor = normalizeSides(config.borderColor, 'black', x => x ?? 'black');
|
|
5171
|
+
config.align = normalizeAlignment(config.align);
|
|
5172
|
+
config.align.x = config.align.x ?? 'left';
|
|
5173
|
+
config.align.y = config.align.y ?? 'top';
|
|
5174
|
+
config.textStroke = doc.sizeToPoint(config.textStroke, 0);
|
|
5175
|
+
config.textStrokeColor = config.textStrokeColor ?? 'black';
|
|
5176
|
+
config.textColor = config.textColor ?? 'black';
|
|
5177
|
+
config.textOptions = config.textOptions ?? {};
|
|
5178
|
+
config.id = new String(config.id ?? `${this._id}-${rowIndex}-${colIndex}`);
|
|
5179
|
+
config.type = config.type?.toUpperCase() === 'TH' ? 'TH' : 'TD';
|
|
5180
|
+
if (config.scope) {
|
|
5181
|
+
config.scope = config.scope.toLowerCase();
|
|
5182
|
+
if (config.scope === 'row') config.scope = 'Row';else if (config.scope === 'both') config.scope = 'Both';else if (config.scope === 'column') config.scope = 'Column';
|
|
5183
|
+
}
|
|
5184
|
+
if (typeof this.opts.debug === 'boolean') config.debug = this.opts.debug;
|
|
5185
|
+
if (customFont) doc.font(rollbackFont, rollbackFontFamily, rollbackFontSize);
|
|
5186
|
+
return config;
|
|
5187
|
+
}
|
|
5188
|
+
function normalizeRow(row, rowIndex) {
|
|
5189
|
+
if (!this._cellClaim) this._cellClaim = new Set();
|
|
5190
|
+
let colIndex = 0;
|
|
5191
|
+
return row.map(cell => {
|
|
5192
|
+
if (cell == null || typeof cell !== 'object') cell = {
|
|
5193
|
+
text: cell
|
|
5194
|
+
};
|
|
5195
|
+
while (this._cellClaim.has(`${rowIndex},${colIndex}`)) {
|
|
5196
|
+
colIndex++;
|
|
5197
|
+
}
|
|
5198
|
+
cell = normalizeCell.call(this, cell, rowIndex, colIndex);
|
|
5199
|
+
for (let i = 0; i < cell.rowSpan; i++) {
|
|
5200
|
+
for (let j = 0; j < cell.colSpan; j++) {
|
|
5201
|
+
this._cellClaim.add(`${rowIndex + i},${colIndex + j}`);
|
|
5202
|
+
}
|
|
5203
|
+
}
|
|
5204
|
+
colIndex += cell.colSpan;
|
|
5205
|
+
return cell;
|
|
5206
|
+
});
|
|
5207
|
+
}
|
|
5208
|
+
|
|
5209
|
+
function ensure(row) {
|
|
5210
|
+
this._columnWidths = [];
|
|
5211
|
+
ensureColumnWidths.call(this, row.reduce((a, cell) => a + cell.colSpan, 0));
|
|
5212
|
+
this._rowHeights = [];
|
|
5213
|
+
this._rowYPos = [this._position.y];
|
|
5214
|
+
this._rowBuffer = new Set();
|
|
5215
|
+
}
|
|
5216
|
+
function ensureColumnWidths(numCols) {
|
|
5217
|
+
let starColumnIndexes = [];
|
|
5218
|
+
let starMinAcc = 0;
|
|
5219
|
+
let unclaimedWidth = this._maxWidth;
|
|
5220
|
+
for (let i = 0; i < numCols; i++) {
|
|
5221
|
+
let col = this._colStyle(i);
|
|
5222
|
+
if (col.width === '*') {
|
|
5223
|
+
starColumnIndexes[i] = col;
|
|
5224
|
+
starMinAcc += col.minWidth;
|
|
5225
|
+
} else {
|
|
5226
|
+
unclaimedWidth -= col.width;
|
|
5227
|
+
this._columnWidths[i] = col.width;
|
|
5228
|
+
}
|
|
5229
|
+
}
|
|
5230
|
+
let starColCount = starColumnIndexes.reduce(x => x + 1, 0);
|
|
5231
|
+
if (starMinAcc >= unclaimedWidth) {
|
|
5232
|
+
starColumnIndexes.forEach((cell, i) => {
|
|
5233
|
+
this._columnWidths[i] = cell.minWidth;
|
|
5234
|
+
});
|
|
5235
|
+
} else if (starColCount > 0) {
|
|
5236
|
+
starColumnIndexes.forEach((col, i) => {
|
|
5237
|
+
let starSize = unclaimedWidth / starColCount;
|
|
5238
|
+
this._columnWidths[i] = Math.max(starSize, col.minWidth);
|
|
5239
|
+
if (col.maxWidth > 0) {
|
|
5240
|
+
this._columnWidths[i] = Math.min(this._columnWidths[i], col.maxWidth);
|
|
5241
|
+
}
|
|
5242
|
+
unclaimedWidth -= this._columnWidths[i];
|
|
5243
|
+
starColCount--;
|
|
5244
|
+
});
|
|
5245
|
+
}
|
|
5246
|
+
let tempX = this._position.x;
|
|
5247
|
+
this._columnXPos = Array.from(this._columnWidths, v => {
|
|
5248
|
+
const t = tempX;
|
|
5249
|
+
tempX += v;
|
|
5250
|
+
return t;
|
|
5251
|
+
});
|
|
5252
|
+
}
|
|
5253
|
+
function measure(row, rowIndex) {
|
|
5254
|
+
row.forEach(cell => this._rowBuffer.add(cell));
|
|
5255
|
+
if (rowIndex > 0) {
|
|
5256
|
+
this._rowYPos[rowIndex] = this._rowYPos[rowIndex - 1] + this._rowHeights[rowIndex - 1];
|
|
5257
|
+
}
|
|
5258
|
+
const rowStyle = this._rowStyle(rowIndex);
|
|
5259
|
+
let toRender = [];
|
|
5260
|
+
this._rowBuffer.forEach(cell => {
|
|
5261
|
+
if (cell.rowIndex + cell.rowSpan - 1 === rowIndex) {
|
|
5262
|
+
toRender.push(measureCell.call(this, cell, rowStyle.height));
|
|
5263
|
+
this._rowBuffer.delete(cell);
|
|
5264
|
+
}
|
|
5265
|
+
});
|
|
5266
|
+
let rowHeight = rowStyle.height;
|
|
5267
|
+
if (rowHeight === 'auto') {
|
|
5268
|
+
rowHeight = toRender.reduce((acc, cell) => {
|
|
5269
|
+
let minHeight = cell.textBounds.height + cell.padding.top + cell.padding.bottom;
|
|
5270
|
+
for (let i = 0; i < cell.rowSpan - 1; i++) {
|
|
5271
|
+
minHeight -= this._rowHeights[cell.rowIndex + i];
|
|
5272
|
+
}
|
|
5273
|
+
return Math.max(acc, minHeight);
|
|
5274
|
+
}, 0);
|
|
5275
|
+
}
|
|
5276
|
+
rowHeight = Math.max(rowHeight, rowStyle.minHeight);
|
|
5277
|
+
if (rowStyle.maxHeight > 0) {
|
|
5278
|
+
rowHeight = Math.min(rowHeight, rowStyle.maxHeight);
|
|
5279
|
+
}
|
|
5280
|
+
this._rowHeights[rowIndex] = rowHeight;
|
|
5281
|
+
let newPage = false;
|
|
5282
|
+
if (rowHeight > this.document.page.contentHeight) {
|
|
5283
|
+
console.warn(new Error(`Row ${rowIndex} requested more than the safe page height, row has been clamped`).stack.slice(7));
|
|
5284
|
+
this._rowHeights[rowIndex] = this.document.page.maxY() - this._rowYPos[rowIndex];
|
|
5285
|
+
} else if (this._rowYPos[rowIndex] + rowHeight >= this.document.page.maxY()) {
|
|
5286
|
+
this._rowYPos[rowIndex] = this.document.page.margins.top;
|
|
5287
|
+
newPage = true;
|
|
5288
|
+
}
|
|
5289
|
+
return {
|
|
5290
|
+
newPage,
|
|
5291
|
+
toRender: toRender.map(cell => measureCell.call(this, cell, rowHeight))
|
|
5292
|
+
};
|
|
5293
|
+
}
|
|
5294
|
+
function measureCell(cell, rowHeight) {
|
|
5295
|
+
let cellWidth = 0;
|
|
5296
|
+
for (let i = 0; i < cell.colSpan; i++) {
|
|
5297
|
+
cellWidth += this._columnWidths[cell.colIndex + i];
|
|
5298
|
+
}
|
|
5299
|
+
let cellHeight = rowHeight;
|
|
5300
|
+
if (cellHeight === 'auto') {
|
|
5301
|
+
cellHeight = this.document.page.contentHeight;
|
|
5302
|
+
} else {
|
|
5303
|
+
for (let i = 0; i < cell.rowSpan - 1; i++) {
|
|
5304
|
+
cellHeight += this._rowHeights[cell.rowIndex + i];
|
|
5305
|
+
}
|
|
5306
|
+
}
|
|
5307
|
+
const textAllocatedWidth = cellWidth - cell.padding.left - cell.padding.right;
|
|
5308
|
+
const textAllocatedHeight = cellHeight - cell.padding.top - cell.padding.bottom;
|
|
5309
|
+
const rotation = cell.textOptions.rotation ?? 0;
|
|
5310
|
+
const {
|
|
5311
|
+
width: textMaxWidth,
|
|
5312
|
+
height: textMaxHeight
|
|
5313
|
+
} = computeBounds(rotation, textAllocatedWidth, textAllocatedHeight);
|
|
5314
|
+
const textOptions = {
|
|
5315
|
+
align: cell.align.x,
|
|
5316
|
+
ellipsis: true,
|
|
5317
|
+
stroke: cell.textStroke > 0,
|
|
5318
|
+
fill: true,
|
|
5319
|
+
width: textMaxWidth,
|
|
5320
|
+
height: textMaxHeight,
|
|
5321
|
+
rotation,
|
|
5322
|
+
...cell.textOptions
|
|
5323
|
+
};
|
|
5324
|
+
let textBounds = {
|
|
5325
|
+
x: 0,
|
|
5326
|
+
y: 0,
|
|
5327
|
+
width: 0,
|
|
5328
|
+
height: 0
|
|
5329
|
+
};
|
|
5330
|
+
if (cell.text) {
|
|
5331
|
+
const rollbackFont = this.document._fontSource;
|
|
5332
|
+
const rollbackFontSize = this.document._fontSize;
|
|
5333
|
+
const rollbackFontFamily = this.document._fontFamily;
|
|
5334
|
+
if (cell.font?.src) this.document.font(cell.font.src, cell.font?.family);
|
|
5335
|
+
if (cell.font?.size) this.document.fontSize(cell.font.size);
|
|
5336
|
+
const unRotatedTextBounds = this.document.boundsOfString(cell.text, 0, 0, {
|
|
5337
|
+
...textOptions,
|
|
5338
|
+
rotation: 0
|
|
5339
|
+
});
|
|
5340
|
+
textOptions.width = unRotatedTextBounds.width;
|
|
5341
|
+
textOptions.height = unRotatedTextBounds.height;
|
|
5342
|
+
textBounds = this.document.boundsOfString(cell.text, 0, 0, textOptions);
|
|
5343
|
+
this.document.font(rollbackFont, rollbackFontFamily, rollbackFontSize);
|
|
5344
|
+
}
|
|
5345
|
+
return {
|
|
5346
|
+
...cell,
|
|
5347
|
+
textOptions,
|
|
5348
|
+
x: this._columnXPos[cell.colIndex],
|
|
5349
|
+
y: this._rowYPos[cell.rowIndex],
|
|
5350
|
+
textX: this._columnXPos[cell.colIndex] + cell.padding.left,
|
|
5351
|
+
textY: this._rowYPos[cell.rowIndex] + cell.padding.top,
|
|
5352
|
+
width: cellWidth,
|
|
5353
|
+
height: cellHeight,
|
|
5354
|
+
textAllocatedHeight,
|
|
5355
|
+
textAllocatedWidth,
|
|
5356
|
+
textBounds
|
|
5357
|
+
};
|
|
5358
|
+
}
|
|
5359
|
+
function computeBounds(rotation, allocWidth, allocHeight) {
|
|
5360
|
+
let textMaxWidth, textMaxHeight;
|
|
5361
|
+
const cos = cosine(rotation);
|
|
5362
|
+
const sin = sine(rotation);
|
|
5363
|
+
if (rotation === 0 || rotation === 180) {
|
|
5364
|
+
textMaxWidth = allocWidth;
|
|
5365
|
+
textMaxHeight = allocHeight;
|
|
5366
|
+
} else if (rotation === 90 || rotation === 270) {
|
|
5367
|
+
textMaxWidth = allocHeight;
|
|
5368
|
+
textMaxHeight = allocWidth;
|
|
5369
|
+
} else if (rotation < 90 || rotation > 180 && rotation < 270) {
|
|
5370
|
+
textMaxWidth = allocWidth / (2 * cos);
|
|
5371
|
+
textMaxHeight = allocWidth / (2 * sin);
|
|
5372
|
+
} else {
|
|
5373
|
+
textMaxHeight = allocWidth / (2 * cos);
|
|
5374
|
+
textMaxWidth = allocWidth / (2 * sin);
|
|
5375
|
+
}
|
|
5376
|
+
const EF = sin * textMaxWidth;
|
|
5377
|
+
const FG = cos * textMaxHeight;
|
|
5378
|
+
if (EF + FG > allocHeight) {
|
|
5379
|
+
const denominator = cos * cos - sin * sin;
|
|
5380
|
+
if (rotation === 0 || rotation === 180) {
|
|
5381
|
+
textMaxWidth = allocWidth;
|
|
5382
|
+
textMaxHeight = allocHeight;
|
|
5383
|
+
} else if (rotation === 90 || rotation === 270) {
|
|
5384
|
+
textMaxWidth = allocHeight;
|
|
5385
|
+
textMaxHeight = allocWidth;
|
|
5386
|
+
} else if (rotation < 90 || rotation > 180 && rotation < 270) {
|
|
5387
|
+
textMaxWidth = (allocWidth * cos - allocHeight * sin) / denominator;
|
|
5388
|
+
textMaxHeight = (allocHeight * cos - allocWidth * sin) / denominator;
|
|
5389
|
+
} else {
|
|
5390
|
+
textMaxHeight = (allocWidth * cos - allocHeight * sin) / denominator;
|
|
5391
|
+
textMaxWidth = (allocHeight * cos - allocWidth * sin) / denominator;
|
|
5392
|
+
}
|
|
5393
|
+
}
|
|
5394
|
+
return {
|
|
5395
|
+
width: Math.abs(textMaxWidth),
|
|
5396
|
+
height: Math.abs(textMaxHeight)
|
|
5397
|
+
};
|
|
5398
|
+
}
|
|
5399
|
+
|
|
5400
|
+
function accommodateTable() {
|
|
5401
|
+
const structParent = this.opts.structParent;
|
|
5402
|
+
if (structParent) {
|
|
5403
|
+
this._tableStruct = this.document.struct('Table');
|
|
5404
|
+
this._tableStruct.dictionary.data.ID = this._id;
|
|
5405
|
+
if (structParent instanceof PDFStructureElement) {
|
|
5406
|
+
structParent.add(this._tableStruct);
|
|
5407
|
+
} else if (structParent instanceof PDFDocument) {
|
|
5408
|
+
structParent.addStructure(this._tableStruct);
|
|
5409
|
+
}
|
|
5410
|
+
this._headerRowLookup = {};
|
|
5411
|
+
this._headerColumnLookup = {};
|
|
5412
|
+
}
|
|
5413
|
+
}
|
|
5414
|
+
function accommodateCleanup() {
|
|
5415
|
+
if (this._tableStruct) this._tableStruct.end();
|
|
5416
|
+
}
|
|
5417
|
+
function accessibleRow(row, rowIndex, renderCell) {
|
|
5418
|
+
const rowStruct = this.document.struct('TR');
|
|
5419
|
+
rowStruct.dictionary.data.ID = new String(`${this._id}-${rowIndex}`);
|
|
5420
|
+
this._tableStruct.add(rowStruct);
|
|
5421
|
+
row.forEach(cell => renderCell(cell, rowStruct));
|
|
5422
|
+
rowStruct.end();
|
|
5423
|
+
}
|
|
5424
|
+
function accessibleCell(cell, rowStruct, callback) {
|
|
5425
|
+
const doc = this.document;
|
|
5426
|
+
const cellStruct = doc.struct(cell.type, {
|
|
5427
|
+
title: cell.title
|
|
5428
|
+
});
|
|
5429
|
+
cellStruct.dictionary.data.ID = cell.id;
|
|
5430
|
+
rowStruct.add(cellStruct);
|
|
5431
|
+
const padding = cell.padding;
|
|
5432
|
+
const border = cell.border;
|
|
5433
|
+
const attributes = {
|
|
5434
|
+
O: 'Table',
|
|
5435
|
+
Width: cell.width,
|
|
5436
|
+
Height: cell.height,
|
|
5437
|
+
Padding: [padding.top, padding.bottom, padding.left, padding.right],
|
|
5438
|
+
RowSpan: cell.rowSpan > 1 ? cell.rowSpan : undefined,
|
|
5439
|
+
ColSpan: cell.colSpan > 1 ? cell.colSpan : undefined,
|
|
5440
|
+
BorderThickness: [border.top, border.bottom, border.left, border.right]
|
|
5441
|
+
};
|
|
5442
|
+
if (cell.type === 'TH') {
|
|
5443
|
+
if (cell.scope === 'Row' || cell.scope === 'Both') {
|
|
5444
|
+
for (let i = 0; i < cell.rowSpan; i++) {
|
|
5445
|
+
if (!this._headerRowLookup[cell.rowIndex + i]) {
|
|
5446
|
+
this._headerRowLookup[cell.rowIndex + i] = [];
|
|
5447
|
+
}
|
|
5448
|
+
this._headerRowLookup[cell.rowIndex + i].push(cell.id);
|
|
5449
|
+
}
|
|
5450
|
+
attributes.Scope = cell.scope;
|
|
5451
|
+
}
|
|
5452
|
+
if (cell.scope === 'Column' || cell.scope === 'Both') {
|
|
5453
|
+
for (let i = 0; i < cell.colSpan; i++) {
|
|
5454
|
+
if (!this._headerColumnLookup[cell.colIndex + i]) {
|
|
5455
|
+
this._headerColumnLookup[cell.colIndex + i] = [];
|
|
5456
|
+
}
|
|
5457
|
+
this._headerColumnLookup[cell.colIndex + i].push(cell.id);
|
|
5458
|
+
}
|
|
5459
|
+
attributes.Scope = cell.scope;
|
|
5460
|
+
}
|
|
5461
|
+
}
|
|
5462
|
+
const Headers = new Set([...Array.from({
|
|
5463
|
+
length: cell.colSpan
|
|
5464
|
+
}, (_, i) => this._headerColumnLookup[cell.colIndex + i]).flat(), ...Array.from({
|
|
5465
|
+
length: cell.rowSpan
|
|
5466
|
+
}, (_, i) => this._headerRowLookup[cell.rowIndex + i]).flat()].filter(Boolean));
|
|
5467
|
+
if (Headers.size) attributes.Headers = Array.from(Headers);
|
|
5468
|
+
const normalizeColor = doc._normalizeColor;
|
|
5469
|
+
if (cell.backgroundColor != null) {
|
|
5470
|
+
attributes.BackgroundColor = normalizeColor(cell.backgroundColor);
|
|
5471
|
+
}
|
|
5472
|
+
const hasBorder = [border.top, border.bottom, border.left, border.right];
|
|
5473
|
+
if (hasBorder.some(x => x)) {
|
|
5474
|
+
const borderColor = cell.borderColor;
|
|
5475
|
+
attributes.BorderColor = [hasBorder[0] ? normalizeColor(borderColor.top) : null, hasBorder[1] ? normalizeColor(borderColor.bottom) : null, hasBorder[2] ? normalizeColor(borderColor.left) : null, hasBorder[3] ? normalizeColor(borderColor.right) : null];
|
|
5476
|
+
}
|
|
5477
|
+
Object.keys(attributes).forEach(key => attributes[key] === undefined && delete attributes[key]);
|
|
5478
|
+
cellStruct.dictionary.data.A = doc.ref(attributes);
|
|
5479
|
+
cellStruct.add(callback);
|
|
5480
|
+
cellStruct.end();
|
|
5481
|
+
cellStruct.dictionary.data.A.end();
|
|
5482
|
+
}
|
|
5483
|
+
|
|
5484
|
+
function renderRow(row, rowIndex) {
|
|
5485
|
+
if (this._tableStruct) {
|
|
5486
|
+
accessibleRow.call(this, row, rowIndex, renderCell.bind(this));
|
|
5487
|
+
} else {
|
|
5488
|
+
row.forEach(cell => renderCell.call(this, cell));
|
|
5489
|
+
}
|
|
5490
|
+
return this._rowYPos[rowIndex] + this._rowHeights[rowIndex];
|
|
5491
|
+
}
|
|
5492
|
+
function renderCell(cell, rowStruct) {
|
|
5493
|
+
const cellRenderer = () => {
|
|
5494
|
+
if (cell.backgroundColor != null) {
|
|
5495
|
+
this.document.save().rect(cell.x, cell.y, cell.width, cell.height).fill(cell.backgroundColor).restore();
|
|
5496
|
+
}
|
|
5497
|
+
renderBorder.call(this, cell.border, cell.borderColor, cell.x, cell.y, cell.width, cell.height);
|
|
5498
|
+
if (cell.debug) {
|
|
5499
|
+
this.document.save();
|
|
5500
|
+
this.document.dash(1, {
|
|
5501
|
+
space: 1
|
|
5502
|
+
}).lineWidth(1).strokeOpacity(0.3);
|
|
5503
|
+
this.document.rect(cell.x, cell.y, cell.width, cell.height).stroke('green');
|
|
5504
|
+
this.document.restore();
|
|
5505
|
+
}
|
|
5506
|
+
if (cell.text) renderCellText.call(this, cell);
|
|
5507
|
+
};
|
|
5508
|
+
if (rowStruct) accessibleCell.call(this, cell, rowStruct, cellRenderer);else cellRenderer();
|
|
5509
|
+
}
|
|
5510
|
+
function renderCellText(cell) {
|
|
5511
|
+
const doc = this.document;
|
|
5512
|
+
const rollbackFont = doc._fontSource;
|
|
5513
|
+
const rollbackFontSize = doc._fontSize;
|
|
5514
|
+
const rollbackFontFamily = doc._fontFamily;
|
|
5515
|
+
if (cell.customFont) {
|
|
5516
|
+
if (cell.font.src) doc.font(cell.font.src, cell.font.family);
|
|
5517
|
+
if (cell.font.size) doc.fontSize(cell.font.size);
|
|
5518
|
+
}
|
|
5519
|
+
const x = cell.textX;
|
|
5520
|
+
const y = cell.textY;
|
|
5521
|
+
const Ah = cell.textAllocatedHeight;
|
|
5522
|
+
const Aw = cell.textAllocatedWidth;
|
|
5523
|
+
const Cw = cell.textBounds.width;
|
|
5524
|
+
const Ch = cell.textBounds.height;
|
|
5525
|
+
const Ox = -cell.textBounds.x;
|
|
5526
|
+
const Oy = -cell.textBounds.y;
|
|
5527
|
+
const PxScale = cell.align.x === 'right' ? 1 : cell.align.x === 'center' ? 0.5 : 0;
|
|
5528
|
+
const Px = (Aw - Cw) * PxScale;
|
|
5529
|
+
const PyScale = cell.align.y === 'bottom' ? 1 : cell.align.y === 'center' ? 0.5 : 0;
|
|
5530
|
+
const Py = (Ah - Ch) * PyScale;
|
|
5531
|
+
const dx = Px + Ox;
|
|
5532
|
+
const dy = Py + Oy;
|
|
5533
|
+
if (cell.debug) {
|
|
5534
|
+
doc.save();
|
|
5535
|
+
doc.dash(1, {
|
|
5536
|
+
space: 1
|
|
5537
|
+
}).lineWidth(1).strokeOpacity(0.3);
|
|
5538
|
+
if (cell.text) {
|
|
5539
|
+
doc.moveTo(x + Px, y).lineTo(x + Px, y + Ah).moveTo(x + Px + Cw, y).lineTo(x + Px + Cw, y + Ah).stroke('blue').moveTo(x, y + Py).lineTo(x + Aw, y + Py).moveTo(x, y + Py + Ch).lineTo(x + Aw, y + Py + Ch).stroke('green');
|
|
5540
|
+
}
|
|
5541
|
+
doc.rect(x, y, Aw, Ah).stroke('orange');
|
|
5542
|
+
doc.restore();
|
|
5543
|
+
}
|
|
5544
|
+
doc.save().rect(x, y, Aw, Ah).clip();
|
|
5545
|
+
doc.fillColor(cell.textColor).strokeColor(cell.textStrokeColor);
|
|
5546
|
+
if (cell.textStroke > 0) doc.lineWidth(cell.textStroke);
|
|
5547
|
+
doc.text(cell.text, x + dx, y + dy, cell.textOptions);
|
|
5548
|
+
doc.restore();
|
|
5549
|
+
if (cell.font) doc.font(rollbackFont, rollbackFontFamily, rollbackFontSize);
|
|
5550
|
+
}
|
|
5551
|
+
function renderBorder(border, borderColor, x, y, width, height, mask) {
|
|
5552
|
+
border = Object.fromEntries(Object.entries(border).map(([k, v]) => [k, mask && !mask[k] ? 0 : v]));
|
|
5553
|
+
const doc = this.document;
|
|
5554
|
+
if ([border.right, border.bottom, border.left].every(val => val === border.top)) {
|
|
5555
|
+
if (border.top > 0) {
|
|
5556
|
+
doc.save().lineWidth(border.top).rect(x, y, width, height).stroke(borderColor.top).restore();
|
|
5557
|
+
}
|
|
5558
|
+
} else {
|
|
5559
|
+
if (border.top > 0) {
|
|
5560
|
+
doc.save().lineWidth(border.top).moveTo(x, y).lineTo(x + width, y).stroke(borderColor.top).restore();
|
|
5561
|
+
}
|
|
5562
|
+
if (border.right > 0) {
|
|
5563
|
+
doc.save().lineWidth(border.right).moveTo(x + width, y).lineTo(x + width, y + height).stroke(borderColor.right).restore();
|
|
5564
|
+
}
|
|
5565
|
+
if (border.bottom > 0) {
|
|
5566
|
+
doc.save().lineWidth(border.bottom).moveTo(x + width, y + height).lineTo(x, y + height).stroke(borderColor.bottom).restore();
|
|
5567
|
+
}
|
|
5568
|
+
if (border.left > 0) {
|
|
5569
|
+
doc.save().lineWidth(border.left).moveTo(x, y + height).lineTo(x, y).stroke(borderColor.left).restore();
|
|
5570
|
+
}
|
|
5571
|
+
}
|
|
5572
|
+
}
|
|
5573
|
+
|
|
5574
|
+
class PDFTable {
|
|
5575
|
+
constructor(document, opts = {}) {
|
|
5576
|
+
this.document = document;
|
|
5577
|
+
this.opts = Object.freeze(opts);
|
|
5578
|
+
normalizeTable.call(this);
|
|
5579
|
+
accommodateTable.call(this);
|
|
5580
|
+
this._currRowIndex = 0;
|
|
5581
|
+
this._ended = false;
|
|
5582
|
+
if (opts.data) {
|
|
5583
|
+
for (const row of opts.data) this.row(row);
|
|
5584
|
+
return this.end();
|
|
5585
|
+
}
|
|
5586
|
+
}
|
|
5587
|
+
row(row, lastRow = false) {
|
|
5588
|
+
if (this._ended) {
|
|
5589
|
+
throw new Error(`Table was marked as ended on row ${this._currRowIndex}`);
|
|
5590
|
+
}
|
|
5591
|
+
row = Array.from(row);
|
|
5592
|
+
row = normalizeRow.call(this, row, this._currRowIndex);
|
|
5593
|
+
if (this._currRowIndex === 0) ensure.call(this, row);
|
|
5594
|
+
const {
|
|
5595
|
+
newPage,
|
|
5596
|
+
toRender
|
|
5597
|
+
} = measure.call(this, row, this._currRowIndex);
|
|
5598
|
+
if (newPage) this.document.continueOnNewPage();
|
|
5599
|
+
const yPos = renderRow.call(this, toRender, this._currRowIndex);
|
|
5600
|
+
this.document.x = this._position.x;
|
|
5601
|
+
this.document.y = yPos;
|
|
5602
|
+
if (lastRow) return this.end();
|
|
5603
|
+
this._currRowIndex++;
|
|
5604
|
+
return this;
|
|
5605
|
+
}
|
|
5606
|
+
end() {
|
|
5607
|
+
while (this._rowBuffer?.size) this.row([]);
|
|
5608
|
+
this._ended = true;
|
|
5609
|
+
accommodateCleanup.call(this);
|
|
5610
|
+
return this.document;
|
|
5611
|
+
}
|
|
5612
|
+
}
|
|
5613
|
+
|
|
5614
|
+
var TableMixin = {
|
|
5615
|
+
initTables() {
|
|
5616
|
+
this._tableIndex = 0;
|
|
5617
|
+
},
|
|
5618
|
+
table(opts) {
|
|
5619
|
+
return new PDFTable(this, opts);
|
|
5620
|
+
}
|
|
5621
|
+
};
|
|
5622
|
+
|
|
5385
5623
|
class PDFMetadata {
|
|
5386
5624
|
constructor() {
|
|
5387
5625
|
this._metadata = `
|
|
@@ -5423,7 +5661,7 @@ var MetadataMixin = {
|
|
|
5423
5661
|
_addInfo() {
|
|
5424
5662
|
this.appendXML(`
|
|
5425
5663
|
<rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
|
|
5426
|
-
<xmp:CreateDate>${this.info.CreationDate.toISOString().split('.')[0] +
|
|
5664
|
+
<xmp:CreateDate>${this.info.CreationDate.toISOString().split('.')[0] + 'Z'}</xmp:CreateDate>
|
|
5427
5665
|
<xmp:CreatorTool>${this.info.Creator}</xmp:CreatorTool>
|
|
5428
5666
|
</rdf:Description>
|
|
5429
5667
|
`);
|
|
@@ -5476,11 +5714,6 @@ var MetadataMixin = {
|
|
|
5476
5714
|
endMetadata() {
|
|
5477
5715
|
this._addInfo();
|
|
5478
5716
|
this.metadata.end();
|
|
5479
|
-
|
|
5480
|
-
/*
|
|
5481
|
-
Metadata was introduced in PDF 1.4, so adding it to 1.3
|
|
5482
|
-
will likely only take up more space.
|
|
5483
|
-
*/
|
|
5484
5717
|
if (this.version != 1.3) {
|
|
5485
5718
|
this.metadataRef = this.ref({
|
|
5486
5719
|
length: this.metadata.getLength(),
|
|
@@ -5495,16 +5728,10 @@ var MetadataMixin = {
|
|
|
5495
5728
|
}
|
|
5496
5729
|
};
|
|
5497
5730
|
|
|
5498
|
-
/*
|
|
5499
|
-
PDFDocument - represents an entire PDF document
|
|
5500
|
-
By Devon Govett
|
|
5501
|
-
*/
|
|
5502
5731
|
class PDFDocument extends stream.Readable {
|
|
5503
5732
|
constructor(options = {}) {
|
|
5504
5733
|
super(options);
|
|
5505
5734
|
this.options = options;
|
|
5506
|
-
|
|
5507
|
-
// PDF version
|
|
5508
5735
|
switch (options.pdfVersion) {
|
|
5509
5736
|
case '1.4':
|
|
5510
5737
|
this.version = 1.4;
|
|
@@ -5523,13 +5750,9 @@ class PDFDocument extends stream.Readable {
|
|
|
5523
5750
|
this.version = 1.3;
|
|
5524
5751
|
break;
|
|
5525
5752
|
}
|
|
5526
|
-
|
|
5527
|
-
// Whether streams should be compressed
|
|
5528
5753
|
this.compress = this.options.compress != null ? this.options.compress : true;
|
|
5529
5754
|
this._pageBuffer = [];
|
|
5530
5755
|
this._pageBufferStart = 0;
|
|
5531
|
-
|
|
5532
|
-
// The PDF object store
|
|
5533
5756
|
this._offsets = [];
|
|
5534
5757
|
this._waiting = 0;
|
|
5535
5758
|
this._ended = false;
|
|
@@ -5550,11 +5773,7 @@ class PDFDocument extends stream.Readable {
|
|
|
5550
5773
|
if (this.options.lang) {
|
|
5551
5774
|
this._root.data.Lang = new String(this.options.lang);
|
|
5552
5775
|
}
|
|
5553
|
-
|
|
5554
|
-
// The current page
|
|
5555
5776
|
this.page = null;
|
|
5556
|
-
|
|
5557
|
-
// Initialize mixins
|
|
5558
5777
|
this.initMetadata();
|
|
5559
5778
|
this.initColor();
|
|
5560
5779
|
this.initVector();
|
|
@@ -5563,9 +5782,8 @@ class PDFDocument extends stream.Readable {
|
|
|
5563
5782
|
this.initImages();
|
|
5564
5783
|
this.initOutline();
|
|
5565
5784
|
this.initMarkings(options);
|
|
5785
|
+
this.initTables();
|
|
5566
5786
|
this.initSubset(options);
|
|
5567
|
-
|
|
5568
|
-
// Initialize the metadata
|
|
5569
5787
|
this.info = {
|
|
5570
5788
|
Producer: 'PDFKit',
|
|
5571
5789
|
Creator: 'PDFKit',
|
|
@@ -5582,21 +5800,10 @@ class PDFDocument extends stream.Readable {
|
|
|
5582
5800
|
DisplayDocTitle: true
|
|
5583
5801
|
});
|
|
5584
5802
|
}
|
|
5585
|
-
|
|
5586
|
-
// Generate file ID
|
|
5587
5803
|
this._id = PDFSecurity.generateFileID(this.info);
|
|
5588
|
-
|
|
5589
|
-
// Initialize security settings
|
|
5590
5804
|
this._security = PDFSecurity.create(this, options);
|
|
5591
|
-
|
|
5592
|
-
// Write the header
|
|
5593
|
-
// PDF version
|
|
5594
5805
|
this._write(`%PDF-${this.version}`);
|
|
5595
|
-
|
|
5596
|
-
// 4 binary chars, as recommended by the spec
|
|
5597
5806
|
this._write('%\xFF\xFF\xFF\xFF');
|
|
5598
|
-
|
|
5599
|
-
// Add the first page
|
|
5600
5807
|
if (this.options.autoFirstPage !== false) {
|
|
5601
5808
|
this.addPage();
|
|
5602
5809
|
}
|
|
@@ -5607,27 +5814,16 @@ class PDFDocument extends stream.Readable {
|
|
|
5607
5814
|
options
|
|
5608
5815
|
} = this);
|
|
5609
5816
|
}
|
|
5610
|
-
|
|
5611
|
-
// end the current page if needed
|
|
5612
5817
|
if (!this.options.bufferPages) {
|
|
5613
5818
|
this.flushPages();
|
|
5614
5819
|
}
|
|
5615
|
-
|
|
5616
|
-
// create a page object
|
|
5617
5820
|
this.page = new PDFPage(this, options);
|
|
5618
5821
|
this._pageBuffer.push(this.page);
|
|
5619
|
-
|
|
5620
|
-
// add the page to the object store
|
|
5621
5822
|
const pages = this._root.data.Pages.data;
|
|
5622
5823
|
pages.Kids.push(this.page.dictionary);
|
|
5623
5824
|
pages.Count++;
|
|
5624
|
-
|
|
5625
|
-
// reset x and y coordinates
|
|
5626
5825
|
this.x = this.page.margins.left;
|
|
5627
5826
|
this.y = this.page.margins.top;
|
|
5628
|
-
|
|
5629
|
-
// flip PDF coordinate system so that the origin is in
|
|
5630
|
-
// the top left rather than the bottom left
|
|
5631
5827
|
this._ctm = [1, 0, 0, 1, 0, 0];
|
|
5632
5828
|
this.transform(1, 0, 0, -1, 0, this.page.height);
|
|
5633
5829
|
this.emit('pageAdded');
|
|
@@ -5635,7 +5831,7 @@ class PDFDocument extends stream.Readable {
|
|
|
5635
5831
|
}
|
|
5636
5832
|
continueOnNewPage(options) {
|
|
5637
5833
|
const pageMarkings = this.endPageMarkings(this.page);
|
|
5638
|
-
this.addPage(options);
|
|
5834
|
+
this.addPage(options ?? this.page._options);
|
|
5639
5835
|
this.initPageMarkings(pageMarkings);
|
|
5640
5836
|
return this;
|
|
5641
5837
|
}
|
|
@@ -5653,8 +5849,6 @@ class PDFDocument extends stream.Readable {
|
|
|
5653
5849
|
return this.page = page;
|
|
5654
5850
|
}
|
|
5655
5851
|
flushPages() {
|
|
5656
|
-
// this local variable exists so we're future-proof against
|
|
5657
|
-
// reentrant calls to flushPages.
|
|
5658
5852
|
const pages = this._pageBuffer;
|
|
5659
5853
|
this._pageBuffer = [];
|
|
5660
5854
|
this._pageBufferStart += pages.length;
|
|
@@ -5675,13 +5869,10 @@ class PDFDocument extends stream.Readable {
|
|
|
5675
5869
|
}
|
|
5676
5870
|
addNamedEmbeddedFile(name, ref) {
|
|
5677
5871
|
if (!this._root.data.Names.data.EmbeddedFiles) {
|
|
5678
|
-
// disabling /Limits for this tree fixes attachments not showing in Adobe Reader
|
|
5679
5872
|
this._root.data.Names.data.EmbeddedFiles = new PDFNameTree({
|
|
5680
5873
|
limits: false
|
|
5681
5874
|
});
|
|
5682
5875
|
}
|
|
5683
|
-
|
|
5684
|
-
// add filespec to EmbeddedFiles
|
|
5685
5876
|
this._root.data.Names.data.EmbeddedFiles.add(name, ref);
|
|
5686
5877
|
}
|
|
5687
5878
|
addNamedJavaScript(name, js) {
|
|
@@ -5696,19 +5887,17 @@ class PDFDocument extends stream.Readable {
|
|
|
5696
5887
|
}
|
|
5697
5888
|
ref(data) {
|
|
5698
5889
|
const ref = new PDFReference(this, this._offsets.length + 1, data);
|
|
5699
|
-
this._offsets.push(null);
|
|
5890
|
+
this._offsets.push(null);
|
|
5700
5891
|
this._waiting++;
|
|
5701
5892
|
return ref;
|
|
5702
5893
|
}
|
|
5703
5894
|
_read() {}
|
|
5704
|
-
// do nothing, but this method is required by node
|
|
5705
|
-
|
|
5706
5895
|
_write(data) {
|
|
5707
5896
|
if (!Buffer.isBuffer(data)) {
|
|
5708
5897
|
data = Buffer.from(data + '\n', 'binary');
|
|
5709
5898
|
}
|
|
5710
5899
|
this.push(data);
|
|
5711
|
-
|
|
5900
|
+
this._offset += data.length;
|
|
5712
5901
|
}
|
|
5713
5902
|
addContent(data) {
|
|
5714
5903
|
this.page.write(data);
|
|
@@ -5718,7 +5907,7 @@ class PDFDocument extends stream.Readable {
|
|
|
5718
5907
|
this._offsets[ref.id - 1] = ref.offset;
|
|
5719
5908
|
if (--this._waiting === 0 && this._ended) {
|
|
5720
5909
|
this._finalize();
|
|
5721
|
-
|
|
5910
|
+
this._ended = false;
|
|
5722
5911
|
}
|
|
5723
5912
|
}
|
|
5724
5913
|
end() {
|
|
@@ -5755,13 +5944,12 @@ class PDFDocument extends stream.Readable {
|
|
|
5755
5944
|
this._security.end();
|
|
5756
5945
|
}
|
|
5757
5946
|
if (this._waiting === 0) {
|
|
5758
|
-
|
|
5947
|
+
this._finalize();
|
|
5759
5948
|
} else {
|
|
5760
|
-
|
|
5949
|
+
this._ended = true;
|
|
5761
5950
|
}
|
|
5762
5951
|
}
|
|
5763
5952
|
_finalize() {
|
|
5764
|
-
// generate xref
|
|
5765
5953
|
const xRefOffset = this._offset;
|
|
5766
5954
|
this._write('xref');
|
|
5767
5955
|
this._write(`0 ${this._offsets.length + 1}`);
|
|
@@ -5770,8 +5958,6 @@ class PDFDocument extends stream.Readable {
|
|
|
5770
5958
|
offset = `0000000000${offset}`.slice(-10);
|
|
5771
5959
|
this._write(offset + ' 00000 n ');
|
|
5772
5960
|
}
|
|
5773
|
-
|
|
5774
|
-
// trailer
|
|
5775
5961
|
const trailer = {
|
|
5776
5962
|
Size: this._offsets.length + 1,
|
|
5777
5963
|
Root: this._root,
|
|
@@ -5786,9 +5972,7 @@ class PDFDocument extends stream.Readable {
|
|
|
5786
5972
|
this._write('startxref');
|
|
5787
5973
|
this._write(`${xRefOffset}`);
|
|
5788
5974
|
this._write('%%EOF');
|
|
5789
|
-
|
|
5790
|
-
// end the stream
|
|
5791
|
-
return this.push(null);
|
|
5975
|
+
this.push(null);
|
|
5792
5976
|
}
|
|
5793
5977
|
toString() {
|
|
5794
5978
|
return '[object PDFDocument]';
|
|
@@ -5809,6 +5993,7 @@ mixin(MarkingsMixin);
|
|
|
5809
5993
|
mixin(AcroFormMixin);
|
|
5810
5994
|
mixin(AttachmentsMixin);
|
|
5811
5995
|
mixin(SubsetMixin);
|
|
5996
|
+
mixin(TableMixin);
|
|
5812
5997
|
PDFDocument.LineWrapper = LineWrapper;
|
|
5813
5998
|
|
|
5814
5999
|
module.exports = PDFDocument;
|