pdfkit 0.16.0 → 0.17.1
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/CHANGELOG.md +19 -0
- package/js/pdfkit.es.js +1007 -798
- 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 +986 -799
- package/js/pdfkit.js.map +1 -1
- package/js/pdfkit.standalone.js +986 -799
- package/package.json +4 -4
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,79 @@ class PDFReference extends PDFAbstractReference {
|
|
|
260
223
|
}
|
|
261
224
|
}
|
|
262
225
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
226
|
+
const fArray = new Float32Array(1);
|
|
227
|
+
const uArray = new Uint32Array(fArray.buffer);
|
|
228
|
+
function PDFNumber(n) {
|
|
229
|
+
const rounded = Math.fround(n);
|
|
230
|
+
if (rounded <= n) return rounded;
|
|
231
|
+
fArray[0] = n;
|
|
232
|
+
if (n <= 0) {
|
|
233
|
+
uArray[0] += 1;
|
|
234
|
+
} else {
|
|
235
|
+
uArray[0] -= 1;
|
|
236
|
+
}
|
|
237
|
+
return fArray[0];
|
|
238
|
+
}
|
|
239
|
+
function normalizeSides(sides, defaultDefinition = undefined, transformer = v => v) {
|
|
240
|
+
if (sides == null || typeof sides === 'object' && Object.keys(sides).length === 0) {
|
|
241
|
+
sides = defaultDefinition;
|
|
242
|
+
}
|
|
243
|
+
if (sides == null || typeof sides !== 'object') {
|
|
244
|
+
sides = {
|
|
245
|
+
top: sides,
|
|
246
|
+
right: sides,
|
|
247
|
+
bottom: sides,
|
|
248
|
+
left: sides
|
|
249
|
+
};
|
|
250
|
+
} else if (Array.isArray(sides)) {
|
|
251
|
+
if (sides.length === 2) {
|
|
252
|
+
sides = {
|
|
253
|
+
vertical: sides[0],
|
|
254
|
+
horizontal: sides[1]
|
|
255
|
+
};
|
|
256
|
+
} else {
|
|
257
|
+
sides = {
|
|
258
|
+
top: sides[0],
|
|
259
|
+
right: sides[1],
|
|
260
|
+
bottom: sides[2],
|
|
261
|
+
left: sides[3]
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if ('vertical' in sides || 'horizontal' in sides) {
|
|
266
|
+
sides = {
|
|
267
|
+
top: sides.vertical,
|
|
268
|
+
right: sides.horizontal,
|
|
269
|
+
bottom: sides.vertical,
|
|
270
|
+
left: sides.horizontal
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
top: transformer(sides.top),
|
|
275
|
+
right: transformer(sides.right),
|
|
276
|
+
bottom: transformer(sides.bottom),
|
|
277
|
+
left: transformer(sides.left)
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
const MM_TO_CM = 1 / 10;
|
|
281
|
+
const CM_TO_IN = 1 / 2.54;
|
|
282
|
+
const PX_TO_IN = 1 / 96;
|
|
283
|
+
const IN_TO_PT = 72;
|
|
284
|
+
const PC_TO_PT = 12;
|
|
285
|
+
function cosine(a) {
|
|
286
|
+
if (a === 0) return 1;
|
|
287
|
+
if (a === 90) return 0;
|
|
288
|
+
if (a === 180) return -1;
|
|
289
|
+
if (a === 270) return 0;
|
|
290
|
+
return Math.cos(a * Math.PI / 180);
|
|
291
|
+
}
|
|
292
|
+
function sine(a) {
|
|
293
|
+
if (a === 0) return 0;
|
|
294
|
+
if (a === 90) return 1;
|
|
295
|
+
if (a === 180) return 0;
|
|
296
|
+
if (a === 270) return -1;
|
|
297
|
+
return Math.sin(a * Math.PI / 180);
|
|
298
|
+
}
|
|
267
299
|
|
|
268
300
|
const DEFAULT_MARGINS = {
|
|
269
301
|
top: 72,
|
|
@@ -326,35 +358,19 @@ const SIZES = {
|
|
|
326
358
|
class PDFPage {
|
|
327
359
|
constructor(document, options = {}) {
|
|
328
360
|
this.document = document;
|
|
361
|
+
this._options = options;
|
|
329
362
|
this.size = options.size || 'letter';
|
|
330
363
|
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
364
|
const dimensions = Array.isArray(this.size) ? this.size : SIZES[this.size.toUpperCase()];
|
|
348
365
|
this.width = dimensions[this.layout === 'portrait' ? 0 : 1];
|
|
349
366
|
this.height = dimensions[this.layout === 'portrait' ? 1 : 0];
|
|
350
367
|
this.content = this.document.ref();
|
|
351
|
-
|
|
352
|
-
|
|
368
|
+
if (options.font) document.font(options.font, options.fontFamily);
|
|
369
|
+
if (options.fontSize) document.fontSize(options.fontSize);
|
|
370
|
+
this.margins = normalizeSides(options.margin ?? options.margins, DEFAULT_MARGINS, x => document.sizeToPoint(x, 0, this));
|
|
353
371
|
this.resources = this.document.ref({
|
|
354
372
|
ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI']
|
|
355
373
|
});
|
|
356
|
-
|
|
357
|
-
// The page dictionary
|
|
358
374
|
this.dictionary = this.document.ref({
|
|
359
375
|
Type: 'Page',
|
|
360
376
|
Parent: this.document._root.data.Pages,
|
|
@@ -364,8 +380,6 @@ class PDFPage {
|
|
|
364
380
|
});
|
|
365
381
|
this.markings = [];
|
|
366
382
|
}
|
|
367
|
-
|
|
368
|
-
// Lazily create these objects
|
|
369
383
|
get fonts() {
|
|
370
384
|
const data = this.resources.data;
|
|
371
385
|
return data.Font != null ? data.Font : data.Font = {};
|
|
@@ -394,14 +408,18 @@ class PDFPage {
|
|
|
394
408
|
const data = this.dictionary.data;
|
|
395
409
|
return data.StructParents != null ? data.StructParents : data.StructParents = this.document.createStructParentTreeNextKey();
|
|
396
410
|
}
|
|
411
|
+
get contentWidth() {
|
|
412
|
+
return this.width - this.margins.left - this.margins.right;
|
|
413
|
+
}
|
|
414
|
+
get contentHeight() {
|
|
415
|
+
return this.height - this.margins.top - this.margins.bottom;
|
|
416
|
+
}
|
|
397
417
|
maxY() {
|
|
398
418
|
return this.height - this.margins.bottom;
|
|
399
419
|
}
|
|
400
420
|
write(chunk) {
|
|
401
421
|
return this.content.write(chunk);
|
|
402
422
|
}
|
|
403
|
-
|
|
404
|
-
// Set tab order if document is tagged for accessibility.
|
|
405
423
|
_setTabOrder() {
|
|
406
424
|
if (!this.dictionary.Tabs && this.document.hasMarkInfoDictionary()) {
|
|
407
425
|
this.dictionary.data.Tabs = 'S';
|
|
@@ -419,191 +437,57 @@ class PDFPage {
|
|
|
419
437
|
}
|
|
420
438
|
}
|
|
421
439
|
|
|
422
|
-
/*
|
|
423
|
-
PDFNameTree - represents a name tree object
|
|
424
|
-
*/
|
|
425
440
|
class PDFNameTree extends PDFTree {
|
|
426
441
|
_compareKeys(a, b) {
|
|
427
442
|
return a.localeCompare(b);
|
|
428
443
|
}
|
|
429
444
|
_keysName() {
|
|
430
|
-
return
|
|
445
|
+
return 'Names';
|
|
431
446
|
}
|
|
432
447
|
_dataForKey(k) {
|
|
433
448
|
return new String(k);
|
|
434
449
|
}
|
|
435
450
|
}
|
|
436
451
|
|
|
437
|
-
/**
|
|
438
|
-
* Check if value is in a range group.
|
|
439
|
-
* @param {number} value
|
|
440
|
-
* @param {number[]} rangeGroup
|
|
441
|
-
* @returns {boolean}
|
|
442
|
-
*/
|
|
443
452
|
function inRange(value, rangeGroup) {
|
|
444
453
|
if (value < rangeGroup[0]) return false;
|
|
445
454
|
let startRange = 0;
|
|
446
455
|
let endRange = rangeGroup.length / 2;
|
|
447
456
|
while (startRange <= endRange) {
|
|
448
457
|
const middleRange = Math.floor((startRange + endRange) / 2);
|
|
449
|
-
|
|
450
|
-
// actual array index
|
|
451
458
|
const arrayIndex = middleRange * 2;
|
|
452
|
-
|
|
453
|
-
// Check if value is in range pointed by actual index
|
|
454
459
|
if (value >= rangeGroup[arrayIndex] && value <= rangeGroup[arrayIndex + 1]) {
|
|
455
460
|
return true;
|
|
456
461
|
}
|
|
457
462
|
if (value > rangeGroup[arrayIndex + 1]) {
|
|
458
|
-
// Search Right Side Of Array
|
|
459
463
|
startRange = middleRange + 1;
|
|
460
464
|
} else {
|
|
461
|
-
// Search Left Side Of Array
|
|
462
465
|
endRange = middleRange - 1;
|
|
463
466
|
}
|
|
464
467
|
}
|
|
465
468
|
return false;
|
|
466
469
|
}
|
|
467
470
|
|
|
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
471
|
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
472
|
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
473
|
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
474
|
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
|
-
|
|
475
|
+
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
476
|
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
|
-
|
|
477
|
+
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];
|
|
478
|
+
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];
|
|
479
|
+
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
480
|
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
481
|
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
482
|
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
483
|
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
484
|
const isBidirectionalL = character => inRange(character, bidirectional_l);
|
|
580
485
|
|
|
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
486
|
const mapping2space = isNonASCIISpaceCharacter;
|
|
588
|
-
|
|
589
|
-
/**
|
|
590
|
-
* the "commonly mapped to nothing" characters [StringPrep, B.1]
|
|
591
|
-
* that can be mapped to nothing.
|
|
592
|
-
*/
|
|
593
487
|
const mapping2nothing = isCommonlyMappedToNothing;
|
|
594
|
-
|
|
595
|
-
// utils
|
|
596
488
|
const getCodePoint = character => character.codePointAt(0);
|
|
597
489
|
const first = x => x[0];
|
|
598
490
|
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
491
|
function toCodePoints(input) {
|
|
608
492
|
const codepoints = [];
|
|
609
493
|
const size = input.length;
|
|
@@ -621,14 +505,6 @@ function toCodePoints(input) {
|
|
|
621
505
|
}
|
|
622
506
|
return codepoints;
|
|
623
507
|
}
|
|
624
|
-
|
|
625
|
-
/**
|
|
626
|
-
* SASLprep.
|
|
627
|
-
* @param {string} input
|
|
628
|
-
* @param {Object} opts
|
|
629
|
-
* @param {boolean} opts.allowUnassigned
|
|
630
|
-
* @returns {string}
|
|
631
|
-
*/
|
|
632
508
|
function saslprep(input, opts = {}) {
|
|
633
509
|
if (typeof input !== 'string') {
|
|
634
510
|
throw new TypeError('Expected string.');
|
|
@@ -636,49 +512,24 @@ function saslprep(input, opts = {}) {
|
|
|
636
512
|
if (input.length === 0) {
|
|
637
513
|
return '';
|
|
638
514
|
}
|
|
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
|
|
515
|
+
const mapped_input = toCodePoints(input).map(character => mapping2space(character) ? 0x20 : character).filter(character => !mapping2nothing(character));
|
|
648
516
|
const normalized_input = String.fromCodePoint.apply(null, mapped_input).normalize('NFKC');
|
|
649
517
|
const normalized_map = toCodePoints(normalized_input);
|
|
650
|
-
|
|
651
|
-
// 3. Prohibit
|
|
652
518
|
const hasProhibited = normalized_map.some(isProhibitedCharacter);
|
|
653
519
|
if (hasProhibited) {
|
|
654
520
|
throw new Error('Prohibited character, see https://tools.ietf.org/html/rfc4013#section-2.3');
|
|
655
521
|
}
|
|
656
|
-
|
|
657
|
-
// Unassigned Code Points
|
|
658
522
|
if (opts.allowUnassigned !== true) {
|
|
659
523
|
const hasUnassigned = normalized_map.some(isUnassignedCodePoint);
|
|
660
524
|
if (hasUnassigned) {
|
|
661
525
|
throw new Error('Unassigned code point, see https://tools.ietf.org/html/rfc4013#section-2.5');
|
|
662
526
|
}
|
|
663
527
|
}
|
|
664
|
-
|
|
665
|
-
// 4. check bidi
|
|
666
|
-
|
|
667
528
|
const hasBidiRAL = normalized_map.some(isBidirectionalRAL);
|
|
668
529
|
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
530
|
if (hasBidiRAL && hasBidiL) {
|
|
673
531
|
throw new Error('String must not contain RandALCat and LCat at the same time,' + ' see https://tools.ietf.org/html/rfc3454#section-6');
|
|
674
532
|
}
|
|
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
533
|
const isFirstBidiRAL = isBidirectionalRAL(getCodePoint(first(normalized_input)));
|
|
683
534
|
const isLastBidiRAL = isBidirectionalRAL(getCodePoint(last(normalized_input)));
|
|
684
535
|
if (hasBidiRAL && !(isFirstBidiRAL && isLastBidiRAL)) {
|
|
@@ -687,15 +538,10 @@ function saslprep(input, opts = {}) {
|
|
|
687
538
|
return normalized_input;
|
|
688
539
|
}
|
|
689
540
|
|
|
690
|
-
/*
|
|
691
|
-
PDFSecurity - represents PDF security settings
|
|
692
|
-
By Yang Liu <hi@zesik.com>
|
|
693
|
-
*/
|
|
694
541
|
class PDFSecurity {
|
|
695
542
|
static generateFileID(info = {}) {
|
|
696
543
|
let infoStr = `${info.CreationDate.getTime()}\n`;
|
|
697
544
|
for (let key in info) {
|
|
698
|
-
// eslint-disable-next-line no-prototype-builtins
|
|
699
545
|
if (!info.hasOwnProperty(key)) {
|
|
700
546
|
continue;
|
|
701
547
|
}
|
|
@@ -1069,8 +915,6 @@ class PDFGradient$1 {
|
|
|
1069
915
|
}
|
|
1070
916
|
this.embedded = true;
|
|
1071
917
|
this.matrix = m;
|
|
1072
|
-
|
|
1073
|
-
// if the last stop comes before 100%, add a copy at 100%
|
|
1074
918
|
const last = this.stops[stopsLength - 1];
|
|
1075
919
|
if (last[0] < 1) {
|
|
1076
920
|
this.stops.push([1, last[1], last[2]]);
|
|
@@ -1093,14 +937,11 @@ class PDFGradient$1 {
|
|
|
1093
937
|
stops.push(fn);
|
|
1094
938
|
fn.end();
|
|
1095
939
|
}
|
|
1096
|
-
|
|
1097
|
-
// if there are only two stops, we don't need a stitching function
|
|
1098
940
|
if (stopsLength === 1) {
|
|
1099
941
|
fn = stops[0];
|
|
1100
942
|
} else {
|
|
1101
943
|
fn = this.doc.ref({
|
|
1102
944
|
FunctionType: 3,
|
|
1103
|
-
// stitching function
|
|
1104
945
|
Domain: [0, 1],
|
|
1105
946
|
Functions: stops,
|
|
1106
947
|
Bounds: bounds,
|
|
@@ -1181,7 +1022,6 @@ class PDFGradient$1 {
|
|
|
1181
1022
|
return pattern;
|
|
1182
1023
|
}
|
|
1183
1024
|
apply(stroke) {
|
|
1184
|
-
// apply gradient transform to existing document ctm
|
|
1185
1025
|
const [m0, m1, m2, m3, m4, m5] = this.doc._ctm;
|
|
1186
1026
|
const [m11, m12, m21, m22, dx, dy] = this.transform;
|
|
1187
1027
|
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 +1084,6 @@ var Gradient = {
|
|
|
1244
1084
|
PDFRadialGradient: PDFRadialGradient$1
|
|
1245
1085
|
};
|
|
1246
1086
|
|
|
1247
|
-
/*
|
|
1248
|
-
PDF tiling pattern support. Uncolored only.
|
|
1249
|
-
*/
|
|
1250
|
-
|
|
1251
1087
|
const underlyingColorSpaces = ['DeviceCMYK', 'DeviceRGB'];
|
|
1252
1088
|
class PDFTilingPattern$1 {
|
|
1253
1089
|
constructor(doc, bBox, xStep, yStep, stream) {
|
|
@@ -1258,23 +1094,16 @@ class PDFTilingPattern$1 {
|
|
|
1258
1094
|
this.stream = stream;
|
|
1259
1095
|
}
|
|
1260
1096
|
createPattern() {
|
|
1261
|
-
// no resources needed for our current usage
|
|
1262
|
-
// required entry
|
|
1263
1097
|
const resources = this.doc.ref();
|
|
1264
1098
|
resources.end();
|
|
1265
|
-
// apply default transform matrix (flipped in the default doc._ctm)
|
|
1266
|
-
// see document.js & gradient.js
|
|
1267
1099
|
const [m0, m1, m2, m3, m4, m5] = this.doc._ctm;
|
|
1268
1100
|
const [m11, m12, m21, m22, dx, dy] = [1, 0, 0, 1, 0, 0];
|
|
1269
1101
|
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
1102
|
const pattern = this.doc.ref({
|
|
1271
1103
|
Type: 'Pattern',
|
|
1272
1104
|
PatternType: 1,
|
|
1273
|
-
// tiling
|
|
1274
1105
|
PaintType: 2,
|
|
1275
|
-
// 1-colored, 2-uncolored
|
|
1276
1106
|
TilingType: 2,
|
|
1277
|
-
// 2-no distortion
|
|
1278
1107
|
BBox: this.bBox,
|
|
1279
1108
|
XStep: this.xStep,
|
|
1280
1109
|
YStep: this.yStep,
|
|
@@ -1285,8 +1114,6 @@ class PDFTilingPattern$1 {
|
|
|
1285
1114
|
return pattern;
|
|
1286
1115
|
}
|
|
1287
1116
|
embedPatternColorSpaces() {
|
|
1288
|
-
// map each pattern to an underlying color space
|
|
1289
|
-
// and embed on each page
|
|
1290
1117
|
underlyingColorSpaces.forEach(csName => {
|
|
1291
1118
|
const csId = this.getPatternColorSpaceId(csName);
|
|
1292
1119
|
if (this.doc.page.colorSpaces[csId]) return;
|
|
@@ -1304,24 +1131,17 @@ class PDFTilingPattern$1 {
|
|
|
1304
1131
|
this.id = 'P' + this.doc._patternCount;
|
|
1305
1132
|
this.pattern = this.createPattern();
|
|
1306
1133
|
}
|
|
1307
|
-
|
|
1308
|
-
// patterns are embedded in each page
|
|
1309
1134
|
if (!this.doc.page.patterns[this.id]) {
|
|
1310
1135
|
this.doc.page.patterns[this.id] = this.pattern;
|
|
1311
1136
|
}
|
|
1312
1137
|
}
|
|
1313
1138
|
apply(stroke, patternColor) {
|
|
1314
|
-
// do any embedding/creating that might be needed
|
|
1315
1139
|
this.embedPatternColorSpaces();
|
|
1316
1140
|
this.embed();
|
|
1317
1141
|
const normalizedColor = this.doc._normalizeColor(patternColor);
|
|
1318
1142
|
if (!normalizedColor) throw Error(`invalid pattern color. (value: ${patternColor})`);
|
|
1319
|
-
|
|
1320
|
-
// select one of the pattern color spaces
|
|
1321
1143
|
const csId = this.getPatternColorSpaceId(this.doc._getColorSpace(normalizedColor));
|
|
1322
1144
|
this.doc._setColorSpace(csId, stroke);
|
|
1323
|
-
|
|
1324
|
-
// stroke/fill using the pattern and color (in the above underlying color space)
|
|
1325
1145
|
const op = stroke ? 'SCN' : 'scn';
|
|
1326
1146
|
return this.doc.addContent(`${normalizedColor.join(' ')} /${this.id} ${op}`);
|
|
1327
1147
|
}
|
|
@@ -1341,11 +1161,10 @@ const {
|
|
|
1341
1161
|
var ColorMixin = {
|
|
1342
1162
|
initColor() {
|
|
1343
1163
|
this.spotColors = {};
|
|
1344
|
-
// The opacity dictionaries
|
|
1345
1164
|
this._opacityRegistry = {};
|
|
1346
1165
|
this._opacityCount = 0;
|
|
1347
1166
|
this._patternCount = 0;
|
|
1348
|
-
|
|
1167
|
+
this._gradCount = 0;
|
|
1349
1168
|
},
|
|
1350
1169
|
_normalizeColor(color) {
|
|
1351
1170
|
if (typeof color === 'string') {
|
|
@@ -1362,10 +1181,8 @@ var ColorMixin = {
|
|
|
1362
1181
|
}
|
|
1363
1182
|
}
|
|
1364
1183
|
if (Array.isArray(color)) {
|
|
1365
|
-
// RGB
|
|
1366
1184
|
if (color.length === 3) {
|
|
1367
1185
|
color = color.map(part => part / 255);
|
|
1368
|
-
// CMYK
|
|
1369
1186
|
} else if (color.length === 4) {
|
|
1370
1187
|
color = color.map(part => part / 100);
|
|
1371
1188
|
}
|
|
@@ -1377,12 +1194,10 @@ var ColorMixin = {
|
|
|
1377
1194
|
if (color instanceof PDFGradient) {
|
|
1378
1195
|
color.apply(stroke);
|
|
1379
1196
|
return true;
|
|
1380
|
-
// see if tiling pattern, decode & apply it it
|
|
1381
1197
|
} else if (Array.isArray(color) && color[0] instanceof PDFTilingPattern) {
|
|
1382
1198
|
color[0].apply(stroke, color[1]);
|
|
1383
1199
|
return true;
|
|
1384
1200
|
}
|
|
1385
|
-
// any other case should be a normal color and not a pattern
|
|
1386
1201
|
return this._setColorCore(color, stroke);
|
|
1387
1202
|
},
|
|
1388
1203
|
_setColorCore(color, stroke) {
|
|
@@ -1416,9 +1231,6 @@ var ColorMixin = {
|
|
|
1416
1231
|
if (set) {
|
|
1417
1232
|
this.fillOpacity(opacity);
|
|
1418
1233
|
}
|
|
1419
|
-
|
|
1420
|
-
// save this for text wrapper, which needs to reset
|
|
1421
|
-
// the fill color on new pages
|
|
1422
1234
|
this._fillColor = [color, opacity];
|
|
1423
1235
|
return this;
|
|
1424
1236
|
},
|
|
@@ -1674,7 +1486,6 @@ const parse = function (path) {
|
|
|
1674
1486
|
if (parameters[c] != null) {
|
|
1675
1487
|
params = parameters[c];
|
|
1676
1488
|
if (cmd) {
|
|
1677
|
-
// save existing command
|
|
1678
1489
|
if (curArg.length > 0) {
|
|
1679
1490
|
args[args.length] = +curArg;
|
|
1680
1491
|
}
|
|
@@ -1692,14 +1503,11 @@ const parse = function (path) {
|
|
|
1692
1503
|
continue;
|
|
1693
1504
|
}
|
|
1694
1505
|
if (args.length === params) {
|
|
1695
|
-
// handle reused commands
|
|
1696
1506
|
ret[ret.length] = {
|
|
1697
1507
|
cmd,
|
|
1698
1508
|
args
|
|
1699
1509
|
};
|
|
1700
1510
|
args = [+curArg];
|
|
1701
|
-
|
|
1702
|
-
// handle assumed commands
|
|
1703
1511
|
if (cmd === 'M') {
|
|
1704
1512
|
cmd = 'L';
|
|
1705
1513
|
}
|
|
@@ -1710,8 +1518,6 @@ const parse = function (path) {
|
|
|
1710
1518
|
args[args.length] = +curArg;
|
|
1711
1519
|
}
|
|
1712
1520
|
foundDecimal = c === '.';
|
|
1713
|
-
|
|
1714
|
-
// fix for negative numbers or repeated decimals with no delimeter between commands
|
|
1715
1521
|
curArg = ['-', '.'].includes(c) ? c : '';
|
|
1716
1522
|
} else {
|
|
1717
1523
|
curArg += c;
|
|
@@ -1720,18 +1526,13 @@ const parse = function (path) {
|
|
|
1720
1526
|
}
|
|
1721
1527
|
}
|
|
1722
1528
|
}
|
|
1723
|
-
|
|
1724
|
-
// add the last command
|
|
1725
1529
|
if (curArg.length > 0) {
|
|
1726
1530
|
if (args.length === params) {
|
|
1727
|
-
// handle reused commands
|
|
1728
1531
|
ret[ret.length] = {
|
|
1729
1532
|
cmd,
|
|
1730
1533
|
args
|
|
1731
1534
|
};
|
|
1732
1535
|
args = [+curArg];
|
|
1733
|
-
|
|
1734
|
-
// handle assumed commands
|
|
1735
1536
|
if (cmd === 'M') {
|
|
1736
1537
|
cmd = 'L';
|
|
1737
1538
|
}
|
|
@@ -1749,10 +1550,7 @@ const parse = function (path) {
|
|
|
1749
1550
|
return ret;
|
|
1750
1551
|
};
|
|
1751
1552
|
const apply = function (commands, doc) {
|
|
1752
|
-
// current point, control point, and subpath starting point
|
|
1753
1553
|
cx = cy = px = py = sx = sy = 0;
|
|
1754
|
-
|
|
1755
|
-
// run the commands
|
|
1756
1554
|
for (let i = 0; i < commands.length; i++) {
|
|
1757
1555
|
const c = commands[i];
|
|
1758
1556
|
if (typeof runners[c.cmd] === 'function') {
|
|
@@ -1916,8 +1714,6 @@ const solveArc = function (doc, x, y, coords) {
|
|
|
1916
1714
|
doc.bezierCurveTo(...bez);
|
|
1917
1715
|
}
|
|
1918
1716
|
};
|
|
1919
|
-
|
|
1920
|
-
// from Inkscape svgtopdf, thanks!
|
|
1921
1717
|
const arcToSegments = function (x, y, rx, ry, large, sweep, rotateX, ox, oy) {
|
|
1922
1718
|
const th = rotateX * (Math.PI / 180);
|
|
1923
1719
|
const sin_th = Math.sin(th);
|
|
@@ -1993,18 +1789,14 @@ class SVGPath {
|
|
|
1993
1789
|
const {
|
|
1994
1790
|
number: number$1
|
|
1995
1791
|
} = PDFObject;
|
|
1996
|
-
|
|
1997
|
-
// This constant is used to approximate a symmetrical arc using a cubic
|
|
1998
|
-
// Bezier curve.
|
|
1999
1792
|
const KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0);
|
|
2000
1793
|
var VectorMixin = {
|
|
2001
1794
|
initVector() {
|
|
2002
|
-
this._ctm = [1, 0, 0, 1, 0, 0];
|
|
2003
|
-
|
|
1795
|
+
this._ctm = [1, 0, 0, 1, 0, 0];
|
|
1796
|
+
this._ctmStack = [];
|
|
2004
1797
|
},
|
|
2005
1798
|
save() {
|
|
2006
1799
|
this._ctmStack.push(this._ctm.slice());
|
|
2007
|
-
// TODO: save/restore colorspace and styles so not setting it unnessesarily all the time?
|
|
2008
1800
|
return this.addContent('q');
|
|
2009
1801
|
},
|
|
2010
1802
|
restore() {
|
|
@@ -2077,8 +1869,6 @@ var VectorMixin = {
|
|
|
2077
1869
|
r = 0;
|
|
2078
1870
|
}
|
|
2079
1871
|
r = Math.min(r, 0.5 * w, 0.5 * h);
|
|
2080
|
-
|
|
2081
|
-
// amount to inset control points from corners (see `ellipse`)
|
|
2082
1872
|
const c = r * (1.0 - KAPPA);
|
|
2083
1873
|
this.moveTo(x + r, y);
|
|
2084
1874
|
this.lineTo(x + w - r, y);
|
|
@@ -2092,7 +1882,6 @@ var VectorMixin = {
|
|
|
2092
1882
|
return this.closePath();
|
|
2093
1883
|
},
|
|
2094
1884
|
ellipse(x, y, r1, r2) {
|
|
2095
|
-
// based on http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas/2173084#2173084
|
|
2096
1885
|
if (r2 == null) {
|
|
2097
1886
|
r2 = r1;
|
|
2098
1887
|
}
|
|
@@ -2122,10 +1911,8 @@ var VectorMixin = {
|
|
|
2122
1911
|
const HALF_PI = 0.5 * Math.PI;
|
|
2123
1912
|
let deltaAng = endAngle - startAngle;
|
|
2124
1913
|
if (Math.abs(deltaAng) > TWO_PI) {
|
|
2125
|
-
// draw only full circle if more than that is specified
|
|
2126
1914
|
deltaAng = TWO_PI;
|
|
2127
1915
|
} else if (deltaAng !== 0 && anticlockwise !== deltaAng < 0) {
|
|
2128
|
-
// necessary to flip direction of rendering
|
|
2129
1916
|
const dir = anticlockwise ? -1 : 1;
|
|
2130
1917
|
deltaAng = dir * TWO_PI + deltaAng;
|
|
2131
1918
|
}
|
|
@@ -2133,38 +1920,21 @@ var VectorMixin = {
|
|
|
2133
1920
|
const segAng = deltaAng / numSegs;
|
|
2134
1921
|
const handleLen = segAng / HALF_PI * KAPPA * radius;
|
|
2135
1922
|
let curAng = startAngle;
|
|
2136
|
-
|
|
2137
|
-
// component distances between anchor point and control point
|
|
2138
1923
|
let deltaCx = -Math.sin(curAng) * handleLen;
|
|
2139
1924
|
let deltaCy = Math.cos(curAng) * handleLen;
|
|
2140
|
-
|
|
2141
|
-
// anchor point
|
|
2142
1925
|
let ax = x + Math.cos(curAng) * radius;
|
|
2143
1926
|
let ay = y + Math.sin(curAng) * radius;
|
|
2144
|
-
|
|
2145
|
-
// calculate and render segments
|
|
2146
1927
|
this.moveTo(ax, ay);
|
|
2147
1928
|
for (let segIdx = 0; segIdx < numSegs; segIdx++) {
|
|
2148
|
-
// starting control point
|
|
2149
1929
|
const cp1x = ax + deltaCx;
|
|
2150
1930
|
const cp1y = ay + deltaCy;
|
|
2151
|
-
|
|
2152
|
-
// step angle
|
|
2153
1931
|
curAng += segAng;
|
|
2154
|
-
|
|
2155
|
-
// next anchor point
|
|
2156
1932
|
ax = x + Math.cos(curAng) * radius;
|
|
2157
1933
|
ay = y + Math.sin(curAng) * radius;
|
|
2158
|
-
|
|
2159
|
-
// next control point delta
|
|
2160
1934
|
deltaCx = -Math.sin(curAng) * handleLen;
|
|
2161
1935
|
deltaCy = Math.cos(curAng) * handleLen;
|
|
2162
|
-
|
|
2163
|
-
// ending control point
|
|
2164
1936
|
const cp2x = ax - deltaCx;
|
|
2165
1937
|
const cp2y = ay - deltaCy;
|
|
2166
|
-
|
|
2167
|
-
// render segment
|
|
2168
1938
|
this.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, ax, ay);
|
|
2169
1939
|
}
|
|
2170
1940
|
return this;
|
|
@@ -2225,9 +1995,7 @@ var VectorMixin = {
|
|
|
2225
1995
|
return this.addContent(`W${this._windingRule(rule)} n`);
|
|
2226
1996
|
},
|
|
2227
1997
|
transform(m11, m12, m21, m22, dx, dy) {
|
|
2228
|
-
// keep track of the current transformation matrix
|
|
2229
1998
|
if (m11 === 1 && m12 === 0 && m21 === 0 && m22 === 1 && dx === 0 && dy === 0) {
|
|
2230
|
-
// Ignore identity transforms
|
|
2231
1999
|
return this;
|
|
2232
2000
|
}
|
|
2233
2001
|
const m = this._ctm;
|
|
@@ -2381,21 +2149,12 @@ oslash ugrave uacute ucircumflex
|
|
|
2381
2149
|
udieresis yacute thorn ydieresis\
|
|
2382
2150
|
`.split(/\s+/);
|
|
2383
2151
|
class AFMFont {
|
|
2384
|
-
static open(filename) {
|
|
2385
|
-
return new AFMFont(fs.readFileSync(filename, 'utf8'));
|
|
2386
|
-
}
|
|
2387
2152
|
constructor(contents) {
|
|
2388
|
-
this.contents = contents;
|
|
2389
2153
|
this.attributes = {};
|
|
2390
2154
|
this.glyphWidths = {};
|
|
2391
2155
|
this.boundingBoxes = {};
|
|
2392
2156
|
this.kernPairs = {};
|
|
2393
|
-
this.parse();
|
|
2394
|
-
// todo: remove charWidths since appears to not be used
|
|
2395
|
-
this.charWidths = new Array(256);
|
|
2396
|
-
for (let char = 0; char <= 255; char++) {
|
|
2397
|
-
this.charWidths[char] = this.glyphWidths[characters[char]];
|
|
2398
|
-
}
|
|
2157
|
+
this.parse(contents);
|
|
2399
2158
|
this.bbox = this.attributes['FontBBox'].split(/\s+/).map(e => +e);
|
|
2400
2159
|
this.ascender = +(this.attributes['Ascender'] || 0);
|
|
2401
2160
|
this.descender = +(this.attributes['Descender'] || 0);
|
|
@@ -2403,9 +2162,9 @@ class AFMFont {
|
|
|
2403
2162
|
this.capHeight = +(this.attributes['CapHeight'] || 0);
|
|
2404
2163
|
this.lineGap = this.bbox[3] - this.bbox[1] - (this.ascender - this.descender);
|
|
2405
2164
|
}
|
|
2406
|
-
parse() {
|
|
2165
|
+
parse(contents) {
|
|
2407
2166
|
let section = '';
|
|
2408
|
-
for (let line of
|
|
2167
|
+
for (let line of contents.split('\n')) {
|
|
2409
2168
|
var match;
|
|
2410
2169
|
var a;
|
|
2411
2170
|
if (match = line.match(/^Start(\w+)/)) {
|
|
@@ -2498,21 +2257,17 @@ class PDFFont {
|
|
|
2498
2257
|
return;
|
|
2499
2258
|
}
|
|
2500
2259
|
this.embed();
|
|
2501
|
-
|
|
2260
|
+
this.embedded = true;
|
|
2502
2261
|
}
|
|
2503
2262
|
embed() {
|
|
2504
2263
|
throw new Error('Must be implemented by subclasses');
|
|
2505
2264
|
}
|
|
2506
|
-
lineHeight(size, includeGap) {
|
|
2507
|
-
if (includeGap == null) {
|
|
2508
|
-
includeGap = false;
|
|
2509
|
-
}
|
|
2265
|
+
lineHeight(size, includeGap = false) {
|
|
2510
2266
|
const gap = includeGap ? this.lineGap : 0;
|
|
2511
2267
|
return (this.ascender + gap - this.descender) / 1000 * size;
|
|
2512
2268
|
}
|
|
2513
2269
|
}
|
|
2514
2270
|
|
|
2515
|
-
// This insanity is so bundlers can inline the font files
|
|
2516
2271
|
const STANDARD_FONTS = {
|
|
2517
2272
|
Courier() {
|
|
2518
2273
|
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 +2395,6 @@ class EmbeddedFont extends PDFFont {
|
|
|
2640
2395
|
}
|
|
2641
2396
|
layoutRun(text, features) {
|
|
2642
2397
|
const run = this.font.layout(text, features);
|
|
2643
|
-
|
|
2644
|
-
// Normalize position values
|
|
2645
2398
|
for (let i = 0; i < run.positions.length; i++) {
|
|
2646
2399
|
const position = run.positions[i];
|
|
2647
2400
|
for (let key in position) {
|
|
@@ -2664,16 +2417,12 @@ class EmbeddedFont extends PDFFont {
|
|
|
2664
2417
|
return run;
|
|
2665
2418
|
}
|
|
2666
2419
|
layout(text, features, onlyWidth) {
|
|
2667
|
-
// Skip the cache if any user defined features are applied
|
|
2668
2420
|
if (features) {
|
|
2669
2421
|
return this.layoutRun(text, features);
|
|
2670
2422
|
}
|
|
2671
2423
|
let glyphs = onlyWidth ? null : [];
|
|
2672
2424
|
let positions = onlyWidth ? null : [];
|
|
2673
2425
|
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
2426
|
let last = 0;
|
|
2678
2427
|
let index = 0;
|
|
2679
2428
|
while (index <= text.length) {
|
|
@@ -2735,17 +2484,15 @@ class EmbeddedFont extends PDFFont {
|
|
|
2735
2484
|
if (1 <= familyClass && familyClass <= 7) {
|
|
2736
2485
|
flags |= 1 << 1;
|
|
2737
2486
|
}
|
|
2738
|
-
flags |= 1 << 2;
|
|
2487
|
+
flags |= 1 << 2;
|
|
2739
2488
|
if (familyClass === 10) {
|
|
2740
2489
|
flags |= 1 << 3;
|
|
2741
2490
|
}
|
|
2742
2491
|
if (this.font.head.macStyle.italic) {
|
|
2743
2492
|
flags |= 1 << 6;
|
|
2744
2493
|
}
|
|
2745
|
-
|
|
2746
|
-
// generate a tag (6 uppercase letters. 17 is the char code offset from '0' to 'A'. 73 will map to 'Z')
|
|
2747
2494
|
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
|
|
2495
|
+
const name = tag + '+' + this.font.postscriptName?.replaceAll(' ', '_');
|
|
2749
2496
|
const {
|
|
2750
2497
|
bbox
|
|
2751
2498
|
} = this.font;
|
|
@@ -2760,8 +2507,7 @@ class EmbeddedFont extends PDFFont {
|
|
|
2760
2507
|
CapHeight: (this.font.capHeight || this.font.ascent) * this.scale,
|
|
2761
2508
|
XHeight: (this.font.xHeight || 0) * this.scale,
|
|
2762
2509
|
StemV: 0
|
|
2763
|
-
});
|
|
2764
|
-
|
|
2510
|
+
});
|
|
2765
2511
|
if (isCFF) {
|
|
2766
2512
|
descriptor.data.FontFile3 = fontFile;
|
|
2767
2513
|
} else {
|
|
@@ -2803,17 +2549,11 @@ class EmbeddedFont extends PDFFont {
|
|
|
2803
2549
|
};
|
|
2804
2550
|
return this.dictionary.end();
|
|
2805
2551
|
}
|
|
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
2552
|
toUnicodeCmap() {
|
|
2811
2553
|
const cmap = this.document.ref();
|
|
2812
2554
|
const entries = [];
|
|
2813
2555
|
for (let codePoints of this.unicode) {
|
|
2814
2556
|
const encoded = [];
|
|
2815
|
-
|
|
2816
|
-
// encode codePoints to utf16
|
|
2817
2557
|
for (let value of codePoints) {
|
|
2818
2558
|
if (value > 0xffff) {
|
|
2819
2559
|
value -= 0x10000;
|
|
@@ -2880,31 +2620,26 @@ class PDFFontFactory {
|
|
|
2880
2620
|
}
|
|
2881
2621
|
|
|
2882
2622
|
const isEqualFont = (font1, font2) => {
|
|
2883
|
-
// compare font checksum
|
|
2884
2623
|
if (font1.font._tables?.head?.checkSumAdjustment !== font2.font._tables?.head?.checkSumAdjustment) {
|
|
2885
2624
|
return false;
|
|
2886
2625
|
}
|
|
2887
|
-
|
|
2888
|
-
// compare font name table
|
|
2889
2626
|
if (JSON.stringify(font1.font._tables?.name?.records) !== JSON.stringify(font2.font._tables?.name?.records)) {
|
|
2890
2627
|
return false;
|
|
2891
2628
|
}
|
|
2892
2629
|
return true;
|
|
2893
2630
|
};
|
|
2894
2631
|
var FontsMixin = {
|
|
2895
|
-
initFonts(defaultFont = 'Helvetica') {
|
|
2896
|
-
// Lookup table for embedded fonts
|
|
2632
|
+
initFonts(defaultFont = 'Helvetica', defaultFontFamily = null, defaultFontSize = 12) {
|
|
2897
2633
|
this._fontFamilies = {};
|
|
2898
2634
|
this._fontCount = 0;
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
this._fontSize =
|
|
2635
|
+
this._fontSource = defaultFont;
|
|
2636
|
+
this._fontFamily = defaultFontFamily;
|
|
2637
|
+
this._fontSize = defaultFontSize;
|
|
2902
2638
|
this._font = null;
|
|
2639
|
+
this._remSize = defaultFontSize;
|
|
2903
2640
|
this._registeredFonts = {};
|
|
2904
|
-
|
|
2905
|
-
// Set the default font
|
|
2906
2641
|
if (defaultFont) {
|
|
2907
|
-
this.font(defaultFont);
|
|
2642
|
+
this.font(defaultFont, defaultFontFamily);
|
|
2908
2643
|
}
|
|
2909
2644
|
},
|
|
2910
2645
|
font(src, family, size) {
|
|
@@ -2913,8 +2648,6 @@ var FontsMixin = {
|
|
|
2913
2648
|
size = family;
|
|
2914
2649
|
family = null;
|
|
2915
2650
|
}
|
|
2916
|
-
|
|
2917
|
-
// check registered fonts if src is a string
|
|
2918
2651
|
if (typeof src === 'string' && this._registeredFonts[src]) {
|
|
2919
2652
|
cacheKey = src;
|
|
2920
2653
|
({
|
|
@@ -2927,28 +2660,21 @@ var FontsMixin = {
|
|
|
2927
2660
|
cacheKey = null;
|
|
2928
2661
|
}
|
|
2929
2662
|
}
|
|
2663
|
+
this._fontSource = src;
|
|
2664
|
+
this._fontFamily = family;
|
|
2930
2665
|
if (size != null) {
|
|
2931
2666
|
this.fontSize(size);
|
|
2932
2667
|
}
|
|
2933
|
-
|
|
2934
|
-
// fast path: check if the font is already in the PDF
|
|
2935
2668
|
if (font = this._fontFamilies[cacheKey]) {
|
|
2936
2669
|
this._font = font;
|
|
2937
2670
|
return this;
|
|
2938
2671
|
}
|
|
2939
|
-
|
|
2940
|
-
// load the font
|
|
2941
2672
|
const id = `F${++this._fontCount}`;
|
|
2942
2673
|
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
2674
|
if ((font = this._fontFamilies[this._font.name]) && isEqualFont(this._font, font)) {
|
|
2947
2675
|
this._font = font;
|
|
2948
2676
|
return this;
|
|
2949
2677
|
}
|
|
2950
|
-
|
|
2951
|
-
// save the font for reuse later
|
|
2952
2678
|
if (cacheKey) {
|
|
2953
2679
|
this._fontFamilies[cacheKey] = this._font;
|
|
2954
2680
|
}
|
|
@@ -2958,13 +2684,10 @@ var FontsMixin = {
|
|
|
2958
2684
|
return this;
|
|
2959
2685
|
},
|
|
2960
2686
|
fontSize(_fontSize) {
|
|
2961
|
-
this._fontSize = _fontSize;
|
|
2687
|
+
this._fontSize = this.sizeToPoint(_fontSize);
|
|
2962
2688
|
return this;
|
|
2963
2689
|
},
|
|
2964
2690
|
currentLineHeight(includeGap) {
|
|
2965
|
-
if (includeGap == null) {
|
|
2966
|
-
includeGap = false;
|
|
2967
|
-
}
|
|
2968
2691
|
return this._font.lineHeight(this._fontSize, includeGap);
|
|
2969
2692
|
},
|
|
2970
2693
|
registerFont(name, src, family) {
|
|
@@ -2973,6 +2696,64 @@ var FontsMixin = {
|
|
|
2973
2696
|
family
|
|
2974
2697
|
};
|
|
2975
2698
|
return this;
|
|
2699
|
+
},
|
|
2700
|
+
sizeToPoint(size, defaultValue = 0, page = this.page, percentageWidth = undefined) {
|
|
2701
|
+
if (!percentageWidth) percentageWidth = this._fontSize;
|
|
2702
|
+
if (typeof defaultValue !== 'number') defaultValue = this.sizeToPoint(defaultValue);
|
|
2703
|
+
if (size === undefined) return defaultValue;
|
|
2704
|
+
if (typeof size === 'number') return size;
|
|
2705
|
+
if (typeof size === 'boolean') return Number(size);
|
|
2706
|
+
const match = String(size).match(/((\d+)?(\.\d+)?)(em|in|px|cm|mm|pc|ex|ch|rem|vw|vh|vmin|vmax|%|pt)?/);
|
|
2707
|
+
if (!match) throw new Error(`Unsupported size '${size}'`);
|
|
2708
|
+
let multiplier;
|
|
2709
|
+
switch (match[4]) {
|
|
2710
|
+
case 'em':
|
|
2711
|
+
multiplier = this._fontSize;
|
|
2712
|
+
break;
|
|
2713
|
+
case 'in':
|
|
2714
|
+
multiplier = IN_TO_PT;
|
|
2715
|
+
break;
|
|
2716
|
+
case 'px':
|
|
2717
|
+
multiplier = PX_TO_IN * IN_TO_PT;
|
|
2718
|
+
break;
|
|
2719
|
+
case 'cm':
|
|
2720
|
+
multiplier = CM_TO_IN * IN_TO_PT;
|
|
2721
|
+
break;
|
|
2722
|
+
case 'mm':
|
|
2723
|
+
multiplier = MM_TO_CM * CM_TO_IN * IN_TO_PT;
|
|
2724
|
+
break;
|
|
2725
|
+
case 'pc':
|
|
2726
|
+
multiplier = PC_TO_PT;
|
|
2727
|
+
break;
|
|
2728
|
+
case 'ex':
|
|
2729
|
+
multiplier = this.currentLineHeight();
|
|
2730
|
+
break;
|
|
2731
|
+
case 'ch':
|
|
2732
|
+
multiplier = this.widthOfString('0');
|
|
2733
|
+
break;
|
|
2734
|
+
case 'rem':
|
|
2735
|
+
multiplier = this._remSize;
|
|
2736
|
+
break;
|
|
2737
|
+
case 'vw':
|
|
2738
|
+
multiplier = page.width / 100;
|
|
2739
|
+
break;
|
|
2740
|
+
case 'vh':
|
|
2741
|
+
multiplier = page.height / 100;
|
|
2742
|
+
break;
|
|
2743
|
+
case 'vmin':
|
|
2744
|
+
multiplier = Math.min(page.width, page.height) / 100;
|
|
2745
|
+
break;
|
|
2746
|
+
case 'vmax':
|
|
2747
|
+
multiplier = Math.max(page.width, page.height) / 100;
|
|
2748
|
+
break;
|
|
2749
|
+
case '%':
|
|
2750
|
+
multiplier = percentageWidth / 100;
|
|
2751
|
+
break;
|
|
2752
|
+
case 'pt':
|
|
2753
|
+
default:
|
|
2754
|
+
multiplier = 1;
|
|
2755
|
+
}
|
|
2756
|
+
return multiplier * Number(match[1]);
|
|
2976
2757
|
}
|
|
2977
2758
|
};
|
|
2978
2759
|
|
|
@@ -2987,7 +2768,7 @@ class LineWrapper extends events.EventEmitter {
|
|
|
2987
2768
|
this.characterSpacing = (options.characterSpacing || 0) * this.horizontalScaling / 100;
|
|
2988
2769
|
this.wordSpacing = (options.wordSpacing === 0) * this.horizontalScaling / 100;
|
|
2989
2770
|
this.columns = options.columns || 1;
|
|
2990
|
-
this.columnGap = (options.columnGap != null ? options.columnGap : 18) * this.horizontalScaling / 100;
|
|
2771
|
+
this.columnGap = (options.columnGap != null ? options.columnGap : 18) * this.horizontalScaling / 100;
|
|
2991
2772
|
this.lineWidth = (options.width * this.horizontalScaling / 100 - this.columnGap * (this.columns - 1)) / this.columns;
|
|
2992
2773
|
this.spaceLeft = this.lineWidth;
|
|
2993
2774
|
this.startX = this.document.x;
|
|
@@ -2996,44 +2777,30 @@ class LineWrapper extends events.EventEmitter {
|
|
|
2996
2777
|
this.ellipsis = options.ellipsis;
|
|
2997
2778
|
this.continuedX = 0;
|
|
2998
2779
|
this.features = options.features;
|
|
2999
|
-
|
|
3000
|
-
// calculate the maximum Y position the text can appear at
|
|
3001
2780
|
if (options.height != null) {
|
|
3002
2781
|
this.height = options.height;
|
|
3003
|
-
this.maxY = this.startY + options.height;
|
|
2782
|
+
this.maxY = PDFNumber(this.startY + options.height);
|
|
3004
2783
|
} else {
|
|
3005
|
-
this.maxY = this.document.page.maxY();
|
|
2784
|
+
this.maxY = PDFNumber(this.document.page.maxY());
|
|
3006
2785
|
}
|
|
3007
|
-
|
|
3008
|
-
// handle paragraph indents
|
|
3009
2786
|
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
2787
|
const indent = this.continuedX || this.indent;
|
|
3014
2788
|
this.document.x += indent;
|
|
3015
2789
|
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
2790
|
if (options.indentAllLines) {
|
|
3020
2791
|
return;
|
|
3021
2792
|
}
|
|
3022
|
-
|
|
3023
|
-
// otherwise we start the next line without indent
|
|
3024
|
-
return this.once('line', () => {
|
|
2793
|
+
this.once('line', () => {
|
|
3025
2794
|
this.document.x -= indent;
|
|
3026
2795
|
this.lineWidth += indent;
|
|
3027
2796
|
if (options.continued && !this.continuedX) {
|
|
3028
2797
|
this.continuedX = this.indent;
|
|
3029
2798
|
}
|
|
3030
2799
|
if (!options.continued) {
|
|
3031
|
-
|
|
2800
|
+
this.continuedX = 0;
|
|
3032
2801
|
}
|
|
3033
2802
|
});
|
|
3034
2803
|
});
|
|
3035
|
-
|
|
3036
|
-
// handle left aligning last lines of paragraphs
|
|
3037
2804
|
this.on('lastLine', options => {
|
|
3038
2805
|
const {
|
|
3039
2806
|
align
|
|
@@ -3042,7 +2809,7 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3042
2809
|
options.align = 'left';
|
|
3043
2810
|
}
|
|
3044
2811
|
this.lastLine = true;
|
|
3045
|
-
|
|
2812
|
+
this.once('line', () => {
|
|
3046
2813
|
this.document.y += options.paragraphGap || 0;
|
|
3047
2814
|
options.align = align;
|
|
3048
2815
|
return this.lastLine = false;
|
|
@@ -3050,7 +2817,7 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3050
2817
|
});
|
|
3051
2818
|
}
|
|
3052
2819
|
wordWidth(word) {
|
|
3053
|
-
return this.document.widthOfString(word, this) + this.characterSpacing + this.wordSpacing;
|
|
2820
|
+
return PDFNumber(this.document.widthOfString(word, this) + this.characterSpacing + this.wordSpacing);
|
|
3054
2821
|
}
|
|
3055
2822
|
canFit(word, w) {
|
|
3056
2823
|
if (word[word.length - 1] != SOFT_HYPHEN) {
|
|
@@ -3059,7 +2826,6 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3059
2826
|
return w + this.wordWidth(HYPHEN) <= this.spaceLeft;
|
|
3060
2827
|
}
|
|
3061
2828
|
eachWord(text, fn) {
|
|
3062
|
-
// setup a unicode line breaker
|
|
3063
2829
|
let bk;
|
|
3064
2830
|
const breaker = new LineBreaker(text);
|
|
3065
2831
|
let last = null;
|
|
@@ -3068,19 +2834,12 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3068
2834
|
var shouldContinue;
|
|
3069
2835
|
let word = text.slice((last != null ? last.position : undefined) || 0, bk.position);
|
|
3070
2836
|
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
2837
|
if (w > this.lineWidth + this.continuedX) {
|
|
3075
|
-
// make some fake break objects
|
|
3076
2838
|
let lbk = last;
|
|
3077
2839
|
const fbk = {};
|
|
3078
2840
|
while (word.length) {
|
|
3079
|
-
// fit as much of the word as possible into the space we have
|
|
3080
2841
|
var l, mightGrow;
|
|
3081
2842
|
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
2843
|
l = Math.ceil(this.spaceLeft / (w / word.length));
|
|
3085
2844
|
w = this.wordWidth(word.slice(0, l));
|
|
3086
2845
|
mightGrow = w <= this.spaceLeft && l < word.length;
|
|
@@ -3088,7 +2847,6 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3088
2847
|
l = word.length;
|
|
3089
2848
|
}
|
|
3090
2849
|
let mustShrink = w > this.spaceLeft && l > 0;
|
|
3091
|
-
// shrink or grow word as necessary after our near-guess above
|
|
3092
2850
|
while (mustShrink || mightGrow) {
|
|
3093
2851
|
if (mustShrink) {
|
|
3094
2852
|
w = this.wordWidth(word.slice(0, --l));
|
|
@@ -3099,20 +2857,14 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3099
2857
|
mightGrow = w <= this.spaceLeft && l < word.length;
|
|
3100
2858
|
}
|
|
3101
2859
|
}
|
|
3102
|
-
|
|
3103
|
-
// check for the edge case where a single character cannot fit into a line.
|
|
3104
2860
|
if (l === 0 && this.spaceLeft === this.lineWidth) {
|
|
3105
2861
|
l = 1;
|
|
3106
2862
|
}
|
|
3107
|
-
|
|
3108
|
-
// send a required break unless this is the last piece and a linebreak is not specified
|
|
3109
2863
|
fbk.required = bk.required || l < word.length;
|
|
3110
2864
|
shouldContinue = fn(word.slice(0, l), w, fbk, lbk);
|
|
3111
2865
|
lbk = {
|
|
3112
2866
|
required: false
|
|
3113
2867
|
};
|
|
3114
|
-
|
|
3115
|
-
// get the remaining piece of the word
|
|
3116
2868
|
word = word.slice(l);
|
|
3117
2869
|
w = this.wordWidth(word);
|
|
3118
2870
|
if (shouldContinue === false) {
|
|
@@ -3120,7 +2872,6 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3120
2872
|
}
|
|
3121
2873
|
}
|
|
3122
2874
|
} else {
|
|
3123
|
-
// otherwise just emit the break as it was given to us
|
|
3124
2875
|
shouldContinue = fn(word, w, bk, last);
|
|
3125
2876
|
}
|
|
3126
2877
|
if (shouldContinue === false) {
|
|
@@ -3130,7 +2881,6 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3130
2881
|
}
|
|
3131
2882
|
}
|
|
3132
2883
|
wrap(text, options) {
|
|
3133
|
-
// override options from previous continued fragments
|
|
3134
2884
|
this.horizontalScaling = options.horizontalScaling || 100;
|
|
3135
2885
|
if (options.indent != null) {
|
|
3136
2886
|
this.indent = options.indent * this.horizontalScaling / 100;
|
|
@@ -3144,10 +2894,6 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3144
2894
|
if (options.ellipsis != null) {
|
|
3145
2895
|
this.ellipsis = options.ellipsis;
|
|
3146
2896
|
}
|
|
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
2897
|
const nextY = this.document.y + this.document.currentLineHeight(true);
|
|
3152
2898
|
if (this.document.y > this.maxY || nextY > this.maxY) {
|
|
3153
2899
|
this.nextSection();
|
|
@@ -3158,7 +2904,7 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3158
2904
|
let lc = 0;
|
|
3159
2905
|
let {
|
|
3160
2906
|
y
|
|
3161
|
-
} = this.document;
|
|
2907
|
+
} = this.document;
|
|
3162
2908
|
const emitLine = () => {
|
|
3163
2909
|
options.textWidth = textWidth + this.wordSpacing * (wc - 1);
|
|
3164
2910
|
options.wordCount = wc;
|
|
@@ -3181,23 +2927,17 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3181
2927
|
wc++;
|
|
3182
2928
|
}
|
|
3183
2929
|
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
2930
|
const lh = this.document.currentLineHeight(true);
|
|
3187
|
-
if (this.height != null && this.ellipsis && this.document.y + lh * 2 > this.maxY && this.column >= this.columns) {
|
|
2931
|
+
if (this.height != null && this.ellipsis && PDFNumber(this.document.y + lh * 2) > this.maxY && this.column >= this.columns) {
|
|
3188
2932
|
if (this.ellipsis === true) {
|
|
3189
2933
|
this.ellipsis = '…';
|
|
3190
|
-
}
|
|
2934
|
+
}
|
|
3191
2935
|
buffer = buffer.replace(/\s+$/, '');
|
|
3192
2936
|
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
2937
|
while (buffer && textWidth > this.lineWidth) {
|
|
3197
2938
|
buffer = buffer.slice(0, -1).replace(/\s+$/, '');
|
|
3198
2939
|
textWidth = this.wordWidth(buffer + this.ellipsis);
|
|
3199
2940
|
}
|
|
3200
|
-
// need to add ellipsis only if there is enough space for it
|
|
3201
2941
|
if (textWidth <= this.lineWidth) {
|
|
3202
2942
|
buffer = buffer + this.ellipsis;
|
|
3203
2943
|
}
|
|
@@ -3212,35 +2952,25 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3212
2952
|
}
|
|
3213
2953
|
this.emit('lastLine', options, this);
|
|
3214
2954
|
}
|
|
3215
|
-
|
|
3216
|
-
// Previous entry is a soft hyphen - add visible hyphen.
|
|
3217
2955
|
if (buffer[buffer.length - 1] == SOFT_HYPHEN) {
|
|
3218
2956
|
buffer = buffer.slice(0, -1) + HYPHEN;
|
|
3219
2957
|
this.spaceLeft -= this.wordWidth(HYPHEN);
|
|
3220
2958
|
}
|
|
3221
2959
|
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) {
|
|
2960
|
+
if (PDFNumber(this.document.y + lh) > this.maxY) {
|
|
3226
2961
|
const shouldContinue = this.nextSection();
|
|
3227
|
-
|
|
3228
|
-
// stop if we reached the maximum height
|
|
3229
2962
|
if (!shouldContinue) {
|
|
3230
2963
|
wc = 0;
|
|
3231
2964
|
buffer = '';
|
|
3232
2965
|
return false;
|
|
3233
2966
|
}
|
|
3234
2967
|
}
|
|
3235
|
-
|
|
3236
|
-
// reset the space left and buffer
|
|
3237
2968
|
if (bk.required) {
|
|
3238
2969
|
this.spaceLeft = this.lineWidth;
|
|
3239
2970
|
buffer = '';
|
|
3240
2971
|
textWidth = 0;
|
|
3241
2972
|
return wc = 0;
|
|
3242
2973
|
} else {
|
|
3243
|
-
// reset the space left and buffer
|
|
3244
2974
|
this.spaceLeft = this.lineWidth - w;
|
|
3245
2975
|
buffer = word;
|
|
3246
2976
|
textWidth = w;
|
|
@@ -3255,25 +2985,19 @@ class LineWrapper extends events.EventEmitter {
|
|
|
3255
2985
|
emitLine();
|
|
3256
2986
|
}
|
|
3257
2987
|
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
2988
|
if (options.continued === true) {
|
|
3263
2989
|
if (lc > 1) {
|
|
3264
2990
|
this.continuedX = 0;
|
|
3265
2991
|
}
|
|
3266
2992
|
this.continuedX += options.textWidth || 0;
|
|
3267
|
-
|
|
2993
|
+
this.document.y = y;
|
|
3268
2994
|
} else {
|
|
3269
|
-
|
|
2995
|
+
this.document.x = this.startX;
|
|
3270
2996
|
}
|
|
3271
2997
|
}
|
|
3272
2998
|
nextSection(options) {
|
|
3273
2999
|
this.emit('sectionEnd', options, this);
|
|
3274
3000
|
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
3001
|
if (this.height != null) {
|
|
3278
3002
|
return false;
|
|
3279
3003
|
}
|
|
@@ -3302,10 +3026,9 @@ const {
|
|
|
3302
3026
|
var TextMixin = {
|
|
3303
3027
|
initText() {
|
|
3304
3028
|
this._line = this._line.bind(this);
|
|
3305
|
-
// Current coordinates
|
|
3306
3029
|
this.x = 0;
|
|
3307
3030
|
this.y = 0;
|
|
3308
|
-
|
|
3031
|
+
this._lineGap = 0;
|
|
3309
3032
|
},
|
|
3310
3033
|
lineGap(_lineGap) {
|
|
3311
3034
|
this._lineGap = _lineGap;
|
|
@@ -3327,11 +3050,7 @@ var TextMixin = {
|
|
|
3327
3050
|
},
|
|
3328
3051
|
_text(text, x, y, options, lineCallback) {
|
|
3329
3052
|
options = this._initOptions(x, y, options);
|
|
3330
|
-
|
|
3331
|
-
// Convert text to a string
|
|
3332
3053
|
text = text == null ? '' : `${text}`;
|
|
3333
|
-
|
|
3334
|
-
// if the wordSpacing option is specified, remove multiple consecutive spaces
|
|
3335
3054
|
if (options.wordSpacing) {
|
|
3336
3055
|
text = text.replace(/\s{2,}/g, ' ');
|
|
3337
3056
|
}
|
|
@@ -3340,8 +3059,12 @@ var TextMixin = {
|
|
|
3340
3059
|
options.structParent.add(this.struct(options.structType || 'P', [this.markStructureContent(options.structType || 'P')]));
|
|
3341
3060
|
}
|
|
3342
3061
|
};
|
|
3343
|
-
|
|
3344
|
-
|
|
3062
|
+
if (options.rotation !== 0) {
|
|
3063
|
+
this.save();
|
|
3064
|
+
this.rotate(-options.rotation, {
|
|
3065
|
+
origin: [this.x, this.y]
|
|
3066
|
+
});
|
|
3067
|
+
}
|
|
3345
3068
|
if (options.width) {
|
|
3346
3069
|
let wrapper = this._wrapper;
|
|
3347
3070
|
if (!wrapper) {
|
|
@@ -3352,14 +3075,13 @@ var TextMixin = {
|
|
|
3352
3075
|
this._wrapper = options.continued ? wrapper : null;
|
|
3353
3076
|
this._textOptions = options.continued ? options : null;
|
|
3354
3077
|
wrapper.wrap(text, options);
|
|
3355
|
-
|
|
3356
|
-
// render paragraphs as single lines
|
|
3357
3078
|
} else {
|
|
3358
3079
|
for (let line of text.split('\n')) {
|
|
3359
3080
|
addStructure();
|
|
3360
3081
|
lineCallback(line, options);
|
|
3361
3082
|
}
|
|
3362
3083
|
}
|
|
3084
|
+
if (options.rotation !== 0) this.restore();
|
|
3363
3085
|
return this;
|
|
3364
3086
|
},
|
|
3365
3087
|
text(text, x, y, options) {
|
|
@@ -3369,17 +3091,108 @@ var TextMixin = {
|
|
|
3369
3091
|
const horizontalScaling = options.horizontalScaling || 100;
|
|
3370
3092
|
return (this._font.widthOfString(string, this._fontSize, options.features) + (options.characterSpacing || 0) * (string.length - 1)) * horizontalScaling / 100;
|
|
3371
3093
|
},
|
|
3094
|
+
boundsOfString(string, x, y, options) {
|
|
3095
|
+
options = this._initOptions(x, y, options);
|
|
3096
|
+
({
|
|
3097
|
+
x,
|
|
3098
|
+
y
|
|
3099
|
+
} = this);
|
|
3100
|
+
const lineGap = options.lineGap ?? this._lineGap ?? 0;
|
|
3101
|
+
const lineHeight = this.currentLineHeight(true) + lineGap;
|
|
3102
|
+
let contentWidth = 0;
|
|
3103
|
+
string = String(string ?? '');
|
|
3104
|
+
if (options.wordSpacing) {
|
|
3105
|
+
string = string.replace(/\s{2,}/g, ' ');
|
|
3106
|
+
}
|
|
3107
|
+
if (options.width) {
|
|
3108
|
+
let wrapper = new LineWrapper(this, options);
|
|
3109
|
+
wrapper.on('line', (text, options) => {
|
|
3110
|
+
this.y += lineHeight;
|
|
3111
|
+
text = text.replace(/\n/g, '');
|
|
3112
|
+
if (text.length) {
|
|
3113
|
+
let wordSpacing = options.wordSpacing ?? 0;
|
|
3114
|
+
const characterSpacing = options.characterSpacing ?? 0;
|
|
3115
|
+
if (options.width && options.align === 'justify') {
|
|
3116
|
+
const words = text.trim().split(/\s+/);
|
|
3117
|
+
const textWidth = this.widthOfString(text.replace(/\s+/g, ''), options);
|
|
3118
|
+
const spaceWidth = this.widthOfString(' ') + characterSpacing;
|
|
3119
|
+
wordSpacing = Math.max(0, (options.lineWidth - textWidth) / Math.max(1, words.length - 1) - spaceWidth);
|
|
3120
|
+
}
|
|
3121
|
+
contentWidth = Math.max(contentWidth, options.textWidth + wordSpacing * (options.wordCount - 1) + characterSpacing * (text.length - 1));
|
|
3122
|
+
}
|
|
3123
|
+
});
|
|
3124
|
+
wrapper.wrap(string, options);
|
|
3125
|
+
} else {
|
|
3126
|
+
for (let line of string.split('\n')) {
|
|
3127
|
+
const lineWidth = this.widthOfString(line, options);
|
|
3128
|
+
this.y += lineHeight;
|
|
3129
|
+
contentWidth = Math.max(contentWidth, lineWidth);
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
let contentHeight = this.y - y;
|
|
3133
|
+
if (options.height) contentHeight = Math.min(contentHeight, options.height);
|
|
3134
|
+
this.x = x;
|
|
3135
|
+
this.y = y;
|
|
3136
|
+
if (options.rotation === 0) {
|
|
3137
|
+
return {
|
|
3138
|
+
x,
|
|
3139
|
+
y,
|
|
3140
|
+
width: contentWidth,
|
|
3141
|
+
height: contentHeight
|
|
3142
|
+
};
|
|
3143
|
+
} else if (options.rotation === 90) {
|
|
3144
|
+
return {
|
|
3145
|
+
x: x,
|
|
3146
|
+
y: y - contentWidth,
|
|
3147
|
+
width: contentHeight,
|
|
3148
|
+
height: contentWidth
|
|
3149
|
+
};
|
|
3150
|
+
} else if (options.rotation === 180) {
|
|
3151
|
+
return {
|
|
3152
|
+
x: x - contentWidth,
|
|
3153
|
+
y: y - contentHeight,
|
|
3154
|
+
width: contentWidth,
|
|
3155
|
+
height: contentHeight
|
|
3156
|
+
};
|
|
3157
|
+
} else if (options.rotation === 270) {
|
|
3158
|
+
return {
|
|
3159
|
+
x: x - contentHeight,
|
|
3160
|
+
y: y,
|
|
3161
|
+
width: contentHeight,
|
|
3162
|
+
height: contentWidth
|
|
3163
|
+
};
|
|
3164
|
+
}
|
|
3165
|
+
const cos = cosine(options.rotation);
|
|
3166
|
+
const sin = sine(options.rotation);
|
|
3167
|
+
const x1 = x;
|
|
3168
|
+
const y1 = y;
|
|
3169
|
+
const x2 = x + contentWidth * cos;
|
|
3170
|
+
const y2 = y - contentWidth * sin;
|
|
3171
|
+
const x3 = x + contentWidth * cos + contentHeight * sin;
|
|
3172
|
+
const y3 = y - contentWidth * sin + contentHeight * cos;
|
|
3173
|
+
const x4 = x + contentHeight * sin;
|
|
3174
|
+
const y4 = y + contentHeight * cos;
|
|
3175
|
+
const xMin = Math.min(x1, x2, x3, x4);
|
|
3176
|
+
const xMax = Math.max(x1, x2, x3, x4);
|
|
3177
|
+
const yMin = Math.min(y1, y2, y3, y4);
|
|
3178
|
+
const yMax = Math.max(y1, y2, y3, y4);
|
|
3179
|
+
return {
|
|
3180
|
+
x: xMin,
|
|
3181
|
+
y: yMin,
|
|
3182
|
+
width: xMax - xMin,
|
|
3183
|
+
height: yMax - yMin
|
|
3184
|
+
};
|
|
3185
|
+
},
|
|
3372
3186
|
heightOfString(text, options) {
|
|
3373
3187
|
const {
|
|
3374
3188
|
x,
|
|
3375
3189
|
y
|
|
3376
3190
|
} = this;
|
|
3377
3191
|
options = this._initOptions(options);
|
|
3378
|
-
options.height = Infinity;
|
|
3379
|
-
|
|
3192
|
+
options.height = Infinity;
|
|
3380
3193
|
const lineGap = options.lineGap || this._lineGap || 0;
|
|
3381
3194
|
this._text(text, this.x, this.y, options, () => {
|
|
3382
|
-
|
|
3195
|
+
this.y += this.currentLineHeight(true) + lineGap;
|
|
3383
3196
|
});
|
|
3384
3197
|
const height = this.y - y;
|
|
3385
3198
|
this.x = x;
|
|
@@ -3477,12 +3290,12 @@ var TextMixin = {
|
|
|
3477
3290
|
wrapper.on('sectionStart', () => {
|
|
3478
3291
|
const pos = indent + itemIndent * (level - 1);
|
|
3479
3292
|
this.x += pos;
|
|
3480
|
-
|
|
3293
|
+
wrapper.lineWidth -= pos;
|
|
3481
3294
|
});
|
|
3482
3295
|
wrapper.on('sectionEnd', () => {
|
|
3483
3296
|
const pos = indent + itemIndent * (level - 1);
|
|
3484
3297
|
this.x -= pos;
|
|
3485
|
-
|
|
3298
|
+
wrapper.lineWidth += pos;
|
|
3486
3299
|
});
|
|
3487
3300
|
wrapper.wrap(listItem, options);
|
|
3488
3301
|
};
|
|
@@ -3496,11 +3309,7 @@ var TextMixin = {
|
|
|
3496
3309
|
options = x;
|
|
3497
3310
|
x = null;
|
|
3498
3311
|
}
|
|
3499
|
-
|
|
3500
|
-
// clone options object
|
|
3501
3312
|
const result = Object.assign({}, options);
|
|
3502
|
-
|
|
3503
|
-
// extend options with previous values for continued text
|
|
3504
3313
|
if (this._textOptions) {
|
|
3505
3314
|
for (let key in this._textOptions) {
|
|
3506
3315
|
const val = this._textOptions[key];
|
|
@@ -3511,16 +3320,12 @@ var TextMixin = {
|
|
|
3511
3320
|
}
|
|
3512
3321
|
}
|
|
3513
3322
|
}
|
|
3514
|
-
|
|
3515
|
-
// Update the current position
|
|
3516
3323
|
if (x != null) {
|
|
3517
3324
|
this.x = x;
|
|
3518
3325
|
}
|
|
3519
3326
|
if (y != null) {
|
|
3520
3327
|
this.y = y;
|
|
3521
3328
|
}
|
|
3522
|
-
|
|
3523
|
-
// wrap to margins if no x or y position passed
|
|
3524
3329
|
if (result.lineBreak !== false) {
|
|
3525
3330
|
if (result.width == null) {
|
|
3526
3331
|
result.width = this.page.width - this.x - this.page.margins.right;
|
|
@@ -3532,17 +3337,18 @@ var TextMixin = {
|
|
|
3532
3337
|
}
|
|
3533
3338
|
if (result.columnGap == null) {
|
|
3534
3339
|
result.columnGap = 18;
|
|
3535
|
-
}
|
|
3536
|
-
|
|
3340
|
+
}
|
|
3341
|
+
result.rotation = Number(options.rotation ?? 0) % 360;
|
|
3342
|
+
if (result.rotation < 0) result.rotation += 360;
|
|
3537
3343
|
return result;
|
|
3538
3344
|
},
|
|
3539
3345
|
_line(text, options = {}, wrapper) {
|
|
3540
3346
|
this._fragment(text, this.x, this.y, options);
|
|
3541
3347
|
const lineGap = options.lineGap || this._lineGap || 0;
|
|
3542
3348
|
if (!wrapper) {
|
|
3543
|
-
|
|
3349
|
+
this.x += this.widthOfString(text, options);
|
|
3544
3350
|
} else {
|
|
3545
|
-
|
|
3351
|
+
this.y += this.currentLineHeight(true) + lineGap;
|
|
3546
3352
|
}
|
|
3547
3353
|
},
|
|
3548
3354
|
_fragment(text, x, y, options) {
|
|
@@ -3551,14 +3357,10 @@ var TextMixin = {
|
|
|
3551
3357
|
if (text.length === 0) {
|
|
3552
3358
|
return;
|
|
3553
3359
|
}
|
|
3554
|
-
|
|
3555
|
-
// handle options
|
|
3556
3360
|
const align = options.align || 'left';
|
|
3557
3361
|
let wordSpacing = options.wordSpacing || 0;
|
|
3558
3362
|
const characterSpacing = options.characterSpacing || 0;
|
|
3559
3363
|
const horizontalScaling = options.horizontalScaling || 100;
|
|
3560
|
-
|
|
3561
|
-
// text alignments
|
|
3562
3364
|
if (options.width) {
|
|
3563
3365
|
switch (align) {
|
|
3564
3366
|
case 'right':
|
|
@@ -3569,7 +3371,6 @@ var TextMixin = {
|
|
|
3569
3371
|
x += options.lineWidth / 2 - options.textWidth / 2;
|
|
3570
3372
|
break;
|
|
3571
3373
|
case 'justify':
|
|
3572
|
-
// calculate the word spacing value
|
|
3573
3374
|
words = text.trim().split(/\s+/);
|
|
3574
3375
|
textWidth = this.widthOfString(text.replace(/\s+/g, ''), options);
|
|
3575
3376
|
var spaceWidth = this.widthOfString(' ') + characterSpacing;
|
|
@@ -3577,8 +3378,6 @@ var TextMixin = {
|
|
|
3577
3378
|
break;
|
|
3578
3379
|
}
|
|
3579
3380
|
}
|
|
3580
|
-
|
|
3581
|
-
// text baseline alignments based on http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling
|
|
3582
3381
|
if (typeof options.baseline === 'number') {
|
|
3583
3382
|
dy = -options.baseline;
|
|
3584
3383
|
} else {
|
|
@@ -3611,11 +3410,7 @@ var TextMixin = {
|
|
|
3611
3410
|
}
|
|
3612
3411
|
dy = dy / 1000 * this._fontSize;
|
|
3613
3412
|
}
|
|
3614
|
-
|
|
3615
|
-
// calculate the actual rendered width of the string after word and character spacing
|
|
3616
3413
|
const renderedWidth = options.textWidth + wordSpacing * (options.wordCount - 1) + characterSpacing * (text.length - 1);
|
|
3617
|
-
|
|
3618
|
-
// create link annotations if the link option is given
|
|
3619
3414
|
if (options.link != null) {
|
|
3620
3415
|
this.link(x, y, renderedWidth, this.currentLineHeight(), options.link);
|
|
3621
3416
|
}
|
|
@@ -3625,8 +3420,6 @@ var TextMixin = {
|
|
|
3625
3420
|
if (options.destination != null) {
|
|
3626
3421
|
this.addNamedDestination(options.destination, 'XYZ', x, y, null);
|
|
3627
3422
|
}
|
|
3628
|
-
|
|
3629
|
-
// create underline
|
|
3630
3423
|
if (options.underline) {
|
|
3631
3424
|
this.save();
|
|
3632
3425
|
if (!options.stroke) {
|
|
@@ -3640,8 +3433,6 @@ var TextMixin = {
|
|
|
3640
3433
|
this.stroke();
|
|
3641
3434
|
this.restore();
|
|
3642
3435
|
}
|
|
3643
|
-
|
|
3644
|
-
// create strikethrough line
|
|
3645
3436
|
if (options.strike) {
|
|
3646
3437
|
this.save();
|
|
3647
3438
|
if (!options.stroke) {
|
|
@@ -3656,8 +3447,6 @@ var TextMixin = {
|
|
|
3656
3447
|
this.restore();
|
|
3657
3448
|
}
|
|
3658
3449
|
this.save();
|
|
3659
|
-
|
|
3660
|
-
// oblique (angle in degrees or boolean)
|
|
3661
3450
|
if (options.oblique) {
|
|
3662
3451
|
let skew;
|
|
3663
3452
|
if (typeof options.oblique === 'number') {
|
|
@@ -3669,45 +3458,24 @@ var TextMixin = {
|
|
|
3669
3458
|
this.transform(1, 0, skew, 1, -skew * dy, 0);
|
|
3670
3459
|
this.transform(1, 0, 0, 1, -x, -y);
|
|
3671
3460
|
}
|
|
3672
|
-
|
|
3673
|
-
// flip coordinate system
|
|
3674
3461
|
this.transform(1, 0, 0, -1, 0, this.page.height);
|
|
3675
3462
|
y = this.page.height - y - dy;
|
|
3676
|
-
|
|
3677
|
-
// add current font to page if necessary
|
|
3678
3463
|
if (this.page.fonts[this._font.id] == null) {
|
|
3679
3464
|
this.page.fonts[this._font.id] = this._font.ref();
|
|
3680
3465
|
}
|
|
3681
|
-
|
|
3682
|
-
// begin the text object
|
|
3683
3466
|
this.addContent('BT');
|
|
3684
|
-
|
|
3685
|
-
// text position
|
|
3686
3467
|
this.addContent(`1 0 0 1 ${number(x)} ${number(y)} Tm`);
|
|
3687
|
-
|
|
3688
|
-
// font and font size
|
|
3689
3468
|
this.addContent(`/${this._font.id} ${number(this._fontSize)} Tf`);
|
|
3690
|
-
|
|
3691
|
-
// rendering mode
|
|
3692
3469
|
const mode = options.fill && options.stroke ? 2 : options.stroke ? 1 : 0;
|
|
3693
3470
|
if (mode) {
|
|
3694
3471
|
this.addContent(`${mode} Tr`);
|
|
3695
3472
|
}
|
|
3696
|
-
|
|
3697
|
-
// Character spacing
|
|
3698
3473
|
if (characterSpacing) {
|
|
3699
3474
|
this.addContent(`${number(characterSpacing)} Tc`);
|
|
3700
3475
|
}
|
|
3701
|
-
|
|
3702
|
-
// Horizontal scaling
|
|
3703
3476
|
if (horizontalScaling !== 100) {
|
|
3704
3477
|
this.addContent(`${horizontalScaling} Tz`);
|
|
3705
3478
|
}
|
|
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
3479
|
if (wordSpacing) {
|
|
3712
3480
|
words = text.trim().split(/\s+/);
|
|
3713
3481
|
wordSpacing += this.widthOfString(' ') + characterSpacing;
|
|
@@ -3718,9 +3486,6 @@ var TextMixin = {
|
|
|
3718
3486
|
const [encodedWord, positionsWord] = this._font.encode(word, options.features);
|
|
3719
3487
|
encoded = encoded.concat(encodedWord);
|
|
3720
3488
|
positions = positions.concat(positionsWord);
|
|
3721
|
-
|
|
3722
|
-
// add the word spacing to the end of the word
|
|
3723
|
-
// clone object because of cache
|
|
3724
3489
|
const space = {};
|
|
3725
3490
|
const object = positions[positions.length - 1];
|
|
3726
3491
|
for (let key in object) {
|
|
@@ -3737,60 +3502,42 @@ var TextMixin = {
|
|
|
3737
3502
|
const commands = [];
|
|
3738
3503
|
let last = 0;
|
|
3739
3504
|
let hadOffset = false;
|
|
3740
|
-
|
|
3741
|
-
// Adds a segment of text to the TJ command buffer
|
|
3742
3505
|
const addSegment = cur => {
|
|
3743
3506
|
if (last < cur) {
|
|
3744
3507
|
const hex = encoded.slice(last, cur).join('');
|
|
3745
3508
|
const advance = positions[cur - 1].xAdvance - positions[cur - 1].advanceWidth;
|
|
3746
3509
|
commands.push(`<${hex}> ${number(-advance)}`);
|
|
3747
3510
|
}
|
|
3748
|
-
|
|
3511
|
+
last = cur;
|
|
3749
3512
|
};
|
|
3750
|
-
|
|
3751
|
-
// Flushes the current TJ commands to the output stream
|
|
3752
3513
|
const flush = i => {
|
|
3753
3514
|
addSegment(i);
|
|
3754
3515
|
if (commands.length > 0) {
|
|
3755
3516
|
this.addContent(`[${commands.join(' ')}] TJ`);
|
|
3756
|
-
|
|
3517
|
+
commands.length = 0;
|
|
3757
3518
|
}
|
|
3758
3519
|
};
|
|
3759
3520
|
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
3521
|
const pos = positions[i];
|
|
3763
3522
|
if (pos.xOffset || pos.yOffset) {
|
|
3764
|
-
// Flush the current buffer
|
|
3765
3523
|
flush(i);
|
|
3766
|
-
|
|
3767
|
-
// Move the text position and flush just the current character
|
|
3768
3524
|
this.addContent(`1 0 0 1 ${number(x + pos.xOffset * scale)} ${number(y + pos.yOffset * scale)} Tm`);
|
|
3769
3525
|
flush(i + 1);
|
|
3770
3526
|
hadOffset = true;
|
|
3771
3527
|
} else {
|
|
3772
|
-
// If the last character had an offset, reset the text position
|
|
3773
3528
|
if (hadOffset) {
|
|
3774
3529
|
this.addContent(`1 0 0 1 ${number(x)} ${number(y)} Tm`);
|
|
3775
3530
|
hadOffset = false;
|
|
3776
3531
|
}
|
|
3777
|
-
|
|
3778
|
-
// Group segments that don't have any advance adjustments
|
|
3779
3532
|
if (pos.xAdvance - pos.advanceWidth !== 0) {
|
|
3780
3533
|
addSegment(i + 1);
|
|
3781
3534
|
}
|
|
3782
3535
|
}
|
|
3783
3536
|
x += pos.xAdvance * scale;
|
|
3784
3537
|
}
|
|
3785
|
-
|
|
3786
|
-
// Flush any remaining commands
|
|
3787
3538
|
flush(i);
|
|
3788
|
-
|
|
3789
|
-
// end the text object
|
|
3790
3539
|
this.addContent('ET');
|
|
3791
|
-
|
|
3792
|
-
// restore flipped coordinate system
|
|
3793
|
-
return this.restore();
|
|
3540
|
+
this.restore();
|
|
3794
3541
|
}
|
|
3795
3542
|
};
|
|
3796
3543
|
|
|
@@ -3808,8 +3555,6 @@ class JPEG {
|
|
|
3808
3555
|
if (this.data.readUInt16BE(0) !== 0xffd8) {
|
|
3809
3556
|
throw 'SOI not found in JPEG';
|
|
3810
3557
|
}
|
|
3811
|
-
|
|
3812
|
-
// Parse the EXIF orientation
|
|
3813
3558
|
this.orientation = exif.fromBuffer(this.data).Orientation || 1;
|
|
3814
3559
|
let pos = 2;
|
|
3815
3560
|
while (pos < this.data.length) {
|
|
@@ -3846,16 +3591,10 @@ class JPEG {
|
|
|
3846
3591
|
ColorSpace: this.colorSpace,
|
|
3847
3592
|
Filter: 'DCTDecode'
|
|
3848
3593
|
});
|
|
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
3594
|
if (this.colorSpace === 'DeviceCMYK') {
|
|
3854
3595
|
this.obj.data['Decode'] = [1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0];
|
|
3855
3596
|
}
|
|
3856
3597
|
this.obj.end(this.data);
|
|
3857
|
-
|
|
3858
|
-
// free memory
|
|
3859
3598
|
return this.data = null;
|
|
3860
3599
|
}
|
|
3861
3600
|
}
|
|
@@ -3898,24 +3637,14 @@ class PNGImage {
|
|
|
3898
3637
|
if (this.image.palette.length === 0) {
|
|
3899
3638
|
this.obj.data['ColorSpace'] = this.image.colorSpace;
|
|
3900
3639
|
} else {
|
|
3901
|
-
// embed the color palette in the PDF as an object stream
|
|
3902
3640
|
const palette = this.document.ref();
|
|
3903
3641
|
palette.end(Buffer.from(this.image.palette));
|
|
3904
|
-
|
|
3905
|
-
// build the color space array for the image
|
|
3906
3642
|
this.obj.data['ColorSpace'] = ['Indexed', 'DeviceRGB', this.image.palette.length / 3 - 1, palette];
|
|
3907
3643
|
}
|
|
3908
|
-
|
|
3909
|
-
// For PNG color types 0, 2 and 3, the transparency data is stored in
|
|
3910
|
-
// a dedicated PNG chunk.
|
|
3911
3644
|
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
3645
|
const val = this.image.transparency.grayscale;
|
|
3915
3646
|
this.obj.data['Mask'] = [val, val];
|
|
3916
3647
|
} 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
3648
|
const {
|
|
3920
3649
|
rgb
|
|
3921
3650
|
} = this.image.transparency;
|
|
@@ -3925,14 +3654,9 @@ class PNGImage {
|
|
|
3925
3654
|
}
|
|
3926
3655
|
this.obj.data['Mask'] = mask;
|
|
3927
3656
|
} 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
3657
|
dataDecoded = true;
|
|
3931
3658
|
return this.loadIndexedAlphaChannel();
|
|
3932
3659
|
} 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
3660
|
dataDecoded = true;
|
|
3937
3661
|
return this.splitAlphaChannel();
|
|
3938
3662
|
}
|
|
@@ -3956,11 +3680,7 @@ class PNGImage {
|
|
|
3956
3680
|
sMask.end(this.alphaChannel);
|
|
3957
3681
|
this.obj.data['SMask'] = sMask;
|
|
3958
3682
|
}
|
|
3959
|
-
|
|
3960
|
-
// add the actual image data
|
|
3961
3683
|
this.obj.end(this.imgData);
|
|
3962
|
-
|
|
3963
|
-
// free memory
|
|
3964
3684
|
this.image = null;
|
|
3965
3685
|
return this.imgData = null;
|
|
3966
3686
|
}
|
|
@@ -3973,7 +3693,6 @@ class PNGImage {
|
|
|
3973
3693
|
const alphaChannel = Buffer.alloc(pixelCount);
|
|
3974
3694
|
let i = p = a = 0;
|
|
3975
3695
|
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
3696
|
const skipByteCount = this.image.bits === 16 ? 1 : 0;
|
|
3978
3697
|
while (i < len) {
|
|
3979
3698
|
for (let colorIndex = 0; colorIndex < colorCount; colorIndex++) {
|
|
@@ -4008,10 +3727,6 @@ class PNGImage {
|
|
|
4008
3727
|
}
|
|
4009
3728
|
}
|
|
4010
3729
|
|
|
4011
|
-
/*
|
|
4012
|
-
PDFImage - embeds images in PDF documents
|
|
4013
|
-
By Devon Govett
|
|
4014
|
-
*/
|
|
4015
3730
|
class PDFImage {
|
|
4016
3731
|
static open(src, label) {
|
|
4017
3732
|
let data;
|
|
@@ -4020,8 +3735,8 @@ class PDFImage {
|
|
|
4020
3735
|
} else if (src instanceof ArrayBuffer) {
|
|
4021
3736
|
data = Buffer.from(new Uint8Array(src));
|
|
4022
3737
|
} else {
|
|
4023
|
-
|
|
4024
|
-
if (match
|
|
3738
|
+
const match = /^data:.+?;base64,(.*)$/.exec(src);
|
|
3739
|
+
if (match) {
|
|
4025
3740
|
data = Buffer.from(match[1], 'base64');
|
|
4026
3741
|
} else {
|
|
4027
3742
|
data = fs.readFileSync(src);
|
|
@@ -4043,17 +3758,16 @@ class PDFImage {
|
|
|
4043
3758
|
var ImagesMixin = {
|
|
4044
3759
|
initImages() {
|
|
4045
3760
|
this._imageRegistry = {};
|
|
4046
|
-
|
|
3761
|
+
this._imageCount = 0;
|
|
4047
3762
|
},
|
|
4048
3763
|
image(src, x, y, options = {}) {
|
|
4049
|
-
let bh, bp, bw, image, ip, left, left1,
|
|
3764
|
+
let bh, bp, bw, image, ip, left, left1, originX, originY;
|
|
4050
3765
|
if (typeof x === 'object') {
|
|
4051
3766
|
options = x;
|
|
4052
3767
|
x = null;
|
|
4053
3768
|
}
|
|
4054
|
-
|
|
4055
|
-
// Ignore orientation based on document options or image options
|
|
4056
3769
|
const ignoreOrientation = options.ignoreOrientation || options.ignoreOrientation !== false && this.options.ignoreOrientation;
|
|
3770
|
+
const inDocumentFlow = typeof y !== 'number';
|
|
4057
3771
|
x = (left = x != null ? x : options.x) != null ? left : this.x;
|
|
4058
3772
|
y = (left1 = y != null ? y : options.y) != null ? left1 : this.y;
|
|
4059
3773
|
if (typeof src === 'string') {
|
|
@@ -4076,8 +3790,6 @@ var ImagesMixin = {
|
|
|
4076
3790
|
width,
|
|
4077
3791
|
height
|
|
4078
3792
|
} = image;
|
|
4079
|
-
|
|
4080
|
-
// If EXIF orientation calls for it, swap width and height
|
|
4081
3793
|
if (!ignoreOrientation && image.orientation > 4) {
|
|
4082
3794
|
[width, height] = [height, width];
|
|
4083
3795
|
}
|
|
@@ -4129,80 +3841,70 @@ var ImagesMixin = {
|
|
|
4129
3841
|
y = y + bh - h;
|
|
4130
3842
|
}
|
|
4131
3843
|
}
|
|
3844
|
+
let rotateAngle = 0;
|
|
3845
|
+
let xTransform = x;
|
|
3846
|
+
let yTransform = y;
|
|
3847
|
+
let hTransform = h;
|
|
3848
|
+
let wTransform = w;
|
|
4132
3849
|
if (!ignoreOrientation) {
|
|
4133
3850
|
switch (image.orientation) {
|
|
4134
|
-
// No orientation (need to flip image, though, because of the default transform matrix on the document)
|
|
4135
3851
|
default:
|
|
4136
3852
|
case 1:
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
rotateAngle = 0;
|
|
3853
|
+
hTransform = -h;
|
|
3854
|
+
yTransform += h;
|
|
4140
3855
|
break;
|
|
4141
|
-
// Flip Horizontal
|
|
4142
3856
|
case 2:
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
rotateAngle = 0;
|
|
3857
|
+
wTransform = -w;
|
|
3858
|
+
hTransform = -h;
|
|
3859
|
+
xTransform += w;
|
|
3860
|
+
yTransform += h;
|
|
4148
3861
|
break;
|
|
4149
|
-
// Rotate 180 degrees
|
|
4150
3862
|
case 3:
|
|
4151
3863
|
originX = x;
|
|
4152
3864
|
originY = y;
|
|
4153
|
-
|
|
4154
|
-
|
|
3865
|
+
hTransform = -h;
|
|
3866
|
+
xTransform -= w;
|
|
4155
3867
|
rotateAngle = 180;
|
|
4156
3868
|
break;
|
|
4157
|
-
// Flip vertical
|
|
4158
3869
|
case 4:
|
|
4159
|
-
// Do nothing, image will be flipped
|
|
4160
|
-
|
|
4161
3870
|
break;
|
|
4162
|
-
// Flip horizontally and rotate 270 degrees CW
|
|
4163
3871
|
case 5:
|
|
4164
3872
|
originX = x;
|
|
4165
3873
|
originY = y;
|
|
4166
|
-
|
|
4167
|
-
|
|
3874
|
+
wTransform = h;
|
|
3875
|
+
hTransform = w;
|
|
3876
|
+
yTransform -= hTransform;
|
|
4168
3877
|
rotateAngle = 90;
|
|
4169
3878
|
break;
|
|
4170
|
-
// Rotate 90 degrees CW
|
|
4171
3879
|
case 6:
|
|
4172
3880
|
originX = x;
|
|
4173
3881
|
originY = y;
|
|
4174
|
-
|
|
4175
|
-
|
|
3882
|
+
wTransform = h;
|
|
3883
|
+
hTransform = -w;
|
|
4176
3884
|
rotateAngle = 90;
|
|
4177
3885
|
break;
|
|
4178
|
-
// Flip horizontally and rotate 90 degrees CW
|
|
4179
3886
|
case 7:
|
|
4180
3887
|
originX = x;
|
|
4181
3888
|
originY = y;
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
x -= w;
|
|
3889
|
+
hTransform = -w;
|
|
3890
|
+
wTransform = -h;
|
|
3891
|
+
xTransform += h;
|
|
4186
3892
|
rotateAngle = 90;
|
|
4187
3893
|
break;
|
|
4188
|
-
// Rotate 270 degrees CW
|
|
4189
3894
|
case 8:
|
|
4190
3895
|
originX = x;
|
|
4191
3896
|
originY = y;
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
3897
|
+
wTransform = h;
|
|
3898
|
+
hTransform = -w;
|
|
3899
|
+
xTransform -= h;
|
|
3900
|
+
yTransform += w;
|
|
4196
3901
|
rotateAngle = -90;
|
|
4197
3902
|
break;
|
|
4198
3903
|
}
|
|
4199
3904
|
} else {
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
rotateAngle = 0;
|
|
3905
|
+
hTransform = -h;
|
|
3906
|
+
yTransform += h;
|
|
4203
3907
|
}
|
|
4204
|
-
|
|
4205
|
-
// create link annotations if the link option is given
|
|
4206
3908
|
if (options.link != null) {
|
|
4207
3909
|
this.link(x, y, w, h, options.link);
|
|
4208
3910
|
}
|
|
@@ -4212,9 +3914,7 @@ var ImagesMixin = {
|
|
|
4212
3914
|
if (options.destination != null) {
|
|
4213
3915
|
this.addNamedDestination(options.destination, 'XYZ', x, y, null);
|
|
4214
3916
|
}
|
|
4215
|
-
|
|
4216
|
-
// Set the current y position to below the image if it is in the document flow
|
|
4217
|
-
if (this.y === y) {
|
|
3917
|
+
if (inDocumentFlow) {
|
|
4218
3918
|
this.y += h;
|
|
4219
3919
|
}
|
|
4220
3920
|
this.save();
|
|
@@ -4223,7 +3923,7 @@ var ImagesMixin = {
|
|
|
4223
3923
|
origin: [originX, originY]
|
|
4224
3924
|
});
|
|
4225
3925
|
}
|
|
4226
|
-
this.transform(
|
|
3926
|
+
this.transform(wTransform, 0, 0, hTransform, xTransform, yTransform);
|
|
4227
3927
|
this.addContent(`/${image.label} Do`);
|
|
4228
3928
|
this.restore();
|
|
4229
3929
|
return this;
|
|
@@ -4249,19 +3949,17 @@ var AnnotationsMixin = {
|
|
|
4249
3949
|
options.Rect = this._convertRect(x, y, w, h);
|
|
4250
3950
|
options.Border = [0, 0, 0];
|
|
4251
3951
|
if (options.Subtype === 'Link' && typeof options.F === 'undefined') {
|
|
4252
|
-
options.F = 1 << 2;
|
|
3952
|
+
options.F = 1 << 2;
|
|
4253
3953
|
}
|
|
4254
3954
|
if (options.Subtype !== 'Link') {
|
|
4255
3955
|
if (options.C == null) {
|
|
4256
3956
|
options.C = this._normalizeColor(options.color || [0, 0, 0]);
|
|
4257
3957
|
}
|
|
4258
|
-
}
|
|
3958
|
+
}
|
|
4259
3959
|
delete options.color;
|
|
4260
3960
|
if (typeof options.Dest === 'string') {
|
|
4261
3961
|
options.Dest = new String(options.Dest);
|
|
4262
3962
|
}
|
|
4263
|
-
|
|
4264
|
-
// Capitalize keys
|
|
4265
3963
|
for (let key in options) {
|
|
4266
3964
|
const val = options[key];
|
|
4267
3965
|
options[key[0].toUpperCase() + key.slice(1)] = val;
|
|
@@ -4294,7 +3992,6 @@ var AnnotationsMixin = {
|
|
|
4294
3992
|
link(x, y, w, h, url, options = {}) {
|
|
4295
3993
|
options.Subtype = 'Link';
|
|
4296
3994
|
if (typeof url === 'number') {
|
|
4297
|
-
// Link to a page in the document (the page must already exist)
|
|
4298
3995
|
const pages = this._root.data.Pages.data;
|
|
4299
3996
|
if (url >= 0 && url < pages.Kids.length) {
|
|
4300
3997
|
options.A = this.ref({
|
|
@@ -4306,7 +4003,6 @@ var AnnotationsMixin = {
|
|
|
4306
4003
|
throw new Error(`The document has no page ${url}`);
|
|
4307
4004
|
}
|
|
4308
4005
|
} else {
|
|
4309
|
-
// Link to an external url
|
|
4310
4006
|
options.A = this.ref({
|
|
4311
4007
|
S: 'URI',
|
|
4312
4008
|
URI: new String(url)
|
|
@@ -4359,14 +4055,11 @@ var AnnotationsMixin = {
|
|
|
4359
4055
|
return this.annotate(x, y, w, h, options);
|
|
4360
4056
|
},
|
|
4361
4057
|
fileAnnotation(x, y, w, h, file = {}, options = {}) {
|
|
4362
|
-
// create hidden file
|
|
4363
4058
|
const filespec = this.file(file.src, Object.assign({
|
|
4364
4059
|
hidden: true
|
|
4365
4060
|
}, file));
|
|
4366
4061
|
options.Subtype = 'FileAttachment';
|
|
4367
4062
|
options.FS = filespec;
|
|
4368
|
-
|
|
4369
|
-
// add description from filespec unless description (Contents) has already been set
|
|
4370
4063
|
if (options.Contents) {
|
|
4371
4064
|
options.Contents = new String(options.Contents);
|
|
4372
4065
|
} else if (filespec.data.Desc) {
|
|
@@ -4375,14 +4068,9 @@ var AnnotationsMixin = {
|
|
|
4375
4068
|
return this.annotate(x, y, w, h, options);
|
|
4376
4069
|
},
|
|
4377
4070
|
_convertRect(x1, y1, w, h) {
|
|
4378
|
-
// flip y1 and y2
|
|
4379
4071
|
let y2 = y1;
|
|
4380
4072
|
y1 += h;
|
|
4381
|
-
|
|
4382
|
-
// make x2
|
|
4383
4073
|
let x2 = x1 + w;
|
|
4384
|
-
|
|
4385
|
-
// apply current transformation matrix to points
|
|
4386
4074
|
const [m0, m1, m2, m3, m4, m5] = this._ctm;
|
|
4387
4075
|
x1 = m0 * x1 + m2 * y1 + m4;
|
|
4388
4076
|
y1 = m1 * x1 + m3 * y1 + m5;
|
|
@@ -4444,7 +4132,7 @@ class PDFOutline {
|
|
|
4444
4132
|
|
|
4445
4133
|
var OutlineMixin = {
|
|
4446
4134
|
initOutline() {
|
|
4447
|
-
|
|
4135
|
+
this.outline = new PDFOutline(this, null, null, null);
|
|
4448
4136
|
},
|
|
4449
4137
|
endOutline() {
|
|
4450
4138
|
this.outline.endOutline();
|
|
@@ -4455,11 +4143,6 @@ var OutlineMixin = {
|
|
|
4455
4143
|
}
|
|
4456
4144
|
};
|
|
4457
4145
|
|
|
4458
|
-
/*
|
|
4459
|
-
PDFStructureContent - a reference to a marked structure content
|
|
4460
|
-
By Ben Schmidt
|
|
4461
|
-
*/
|
|
4462
|
-
|
|
4463
4146
|
class PDFStructureContent {
|
|
4464
4147
|
constructor(pageRef, mcid) {
|
|
4465
4148
|
this.refs = [{
|
|
@@ -4472,10 +4155,6 @@ class PDFStructureContent {
|
|
|
4472
4155
|
}
|
|
4473
4156
|
}
|
|
4474
4157
|
|
|
4475
|
-
/*
|
|
4476
|
-
PDFStructureElement - represents an element in the PDF logical structure tree
|
|
4477
|
-
By Ben Schmidt
|
|
4478
|
-
*/
|
|
4479
4158
|
class PDFStructureElement {
|
|
4480
4159
|
constructor(document, type, options = {}, children = null) {
|
|
4481
4160
|
this.document = document;
|
|
@@ -4483,7 +4162,6 @@ class PDFStructureElement {
|
|
|
4483
4162
|
this._ended = false;
|
|
4484
4163
|
this._flushed = false;
|
|
4485
4164
|
this.dictionary = document.ref({
|
|
4486
|
-
// Type: "StructElem",
|
|
4487
4165
|
S: type
|
|
4488
4166
|
});
|
|
4489
4167
|
const data = this.dictionary.data;
|
|
@@ -4532,7 +4210,6 @@ class PDFStructureElement {
|
|
|
4532
4210
|
this._addContentToParentTree(child);
|
|
4533
4211
|
}
|
|
4534
4212
|
if (typeof child === 'function' && this._attached) {
|
|
4535
|
-
// _contentForClosure() adds the content to the parent tree
|
|
4536
4213
|
child = this._contentForClosure(child);
|
|
4537
4214
|
}
|
|
4538
4215
|
this._children.push(child);
|
|
@@ -4608,10 +4285,6 @@ class PDFStructureElement {
|
|
|
4608
4285
|
this.dictionary.data.K = [];
|
|
4609
4286
|
this._children.forEach(child => this._flushChild(child));
|
|
4610
4287
|
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
4288
|
this._children = [];
|
|
4616
4289
|
this.dictionary.data.K = null;
|
|
4617
4290
|
this._flushed = true;
|
|
@@ -4632,7 +4305,7 @@ class PDFStructureElement {
|
|
|
4632
4305
|
this.dictionary.data.K.push(mcid);
|
|
4633
4306
|
} else {
|
|
4634
4307
|
this.dictionary.data.K.push({
|
|
4635
|
-
Type:
|
|
4308
|
+
Type: 'MCR',
|
|
4636
4309
|
Pg: pageRef,
|
|
4637
4310
|
MCID: mcid
|
|
4638
4311
|
});
|
|
@@ -4642,25 +4315,18 @@ class PDFStructureElement {
|
|
|
4642
4315
|
}
|
|
4643
4316
|
}
|
|
4644
4317
|
|
|
4645
|
-
/*
|
|
4646
|
-
PDFNumberTree - represents a number tree object
|
|
4647
|
-
*/
|
|
4648
4318
|
class PDFNumberTree extends PDFTree {
|
|
4649
4319
|
_compareKeys(a, b) {
|
|
4650
4320
|
return parseInt(a) - parseInt(b);
|
|
4651
4321
|
}
|
|
4652
4322
|
_keysName() {
|
|
4653
|
-
return
|
|
4323
|
+
return 'Nums';
|
|
4654
4324
|
}
|
|
4655
4325
|
_dataForKey(k) {
|
|
4656
4326
|
return parseInt(k);
|
|
4657
4327
|
}
|
|
4658
4328
|
}
|
|
4659
4329
|
|
|
4660
|
-
/*
|
|
4661
|
-
Markings mixin - support marked content sequences in content streams
|
|
4662
|
-
By Ben Schmidt
|
|
4663
|
-
*/
|
|
4664
4330
|
var MarkingsMixin = {
|
|
4665
4331
|
initMarkings(options) {
|
|
4666
4332
|
this.structChildren = [];
|
|
@@ -4796,7 +4462,6 @@ var MarkingsMixin = {
|
|
|
4796
4462
|
return this.getStructTreeRoot().data.ParentTree;
|
|
4797
4463
|
},
|
|
4798
4464
|
createStructParentTreeNextKey() {
|
|
4799
|
-
// initialise the MarkInfo dictionary
|
|
4800
4465
|
this.getMarkInfoDictionary();
|
|
4801
4466
|
const structTreeRoot = this.getStructTreeRoot();
|
|
4802
4467
|
const key = structTreeRoot.data.ParentTreeNextKey++;
|
|
@@ -4860,10 +4525,6 @@ const FORMAT_DEFAULT = {
|
|
|
4860
4525
|
}
|
|
4861
4526
|
};
|
|
4862
4527
|
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
4528
|
initForm() {
|
|
4868
4529
|
if (!this._font) {
|
|
4869
4530
|
throw new Error('Must set a font before calling initForm method');
|
|
@@ -4886,9 +4547,6 @@ var AcroFormMixin = {
|
|
|
4886
4547
|
this._root.data.AcroForm = AcroForm;
|
|
4887
4548
|
return this;
|
|
4888
4549
|
},
|
|
4889
|
-
/**
|
|
4890
|
-
* Called automatically by document.js
|
|
4891
|
-
*/
|
|
4892
4550
|
endAcroForm() {
|
|
4893
4551
|
if (this._root.data.AcroForm) {
|
|
4894
4552
|
if (!Object.keys(this._acroform.fonts).length && !this._acroform.defaultFont) {
|
|
@@ -4914,38 +4572,18 @@ var AcroFormMixin = {
|
|
|
4914
4572
|
}
|
|
4915
4573
|
return this;
|
|
4916
4574
|
},
|
|
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
4575
|
formField(name, options = {}) {
|
|
4925
4576
|
let fieldDict = this._fieldDict(name, null, options);
|
|
4926
4577
|
let fieldRef = this.ref(fieldDict);
|
|
4927
4578
|
this._addToParent(fieldRef);
|
|
4928
4579
|
return fieldRef;
|
|
4929
4580
|
},
|
|
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
4581
|
formAnnotation(name, type, x, y, w, h, options = {}) {
|
|
4942
4582
|
let fieldDict = this._fieldDict(name, type, options);
|
|
4943
4583
|
fieldDict.Subtype = 'Widget';
|
|
4944
4584
|
if (fieldDict.F === undefined) {
|
|
4945
|
-
fieldDict.F = 4;
|
|
4585
|
+
fieldDict.F = 4;
|
|
4946
4586
|
}
|
|
4947
|
-
|
|
4948
|
-
// Add Field annot to page, and get it's ref
|
|
4949
4587
|
this.annotate(x, y, w, h, fieldDict);
|
|
4950
4588
|
let annotRef = this.page.annotations[this.page.annotations.length - 1];
|
|
4951
4589
|
return this._addToParent(annotRef);
|
|
@@ -5106,23 +4744,18 @@ var AcroFormMixin = {
|
|
|
5106
4744
|
delete options.align;
|
|
5107
4745
|
}
|
|
5108
4746
|
if (result !== 0) {
|
|
5109
|
-
options.Q = result;
|
|
4747
|
+
options.Q = result;
|
|
5110
4748
|
}
|
|
5111
4749
|
return options;
|
|
5112
4750
|
},
|
|
5113
4751
|
_resolveFont(options) {
|
|
5114
|
-
// add current font to document-level AcroForm dict if necessary
|
|
5115
4752
|
if (this._acroform.fonts[this._font.id] == null) {
|
|
5116
4753
|
this._acroform.fonts[this._font.id] = this._font.ref();
|
|
5117
4754
|
}
|
|
5118
|
-
|
|
5119
|
-
// add current font to field's resource dict (RD) if not the default acroform font
|
|
5120
4755
|
if (this._acroform.defaultFont !== this._font.name) {
|
|
5121
4756
|
options.DR = {
|
|
5122
4757
|
Font: {}
|
|
5123
4758
|
};
|
|
5124
|
-
|
|
5125
|
-
// Get the fontSize option. If not set use auto sizing
|
|
5126
4759
|
const fontSize = options.fontSize || 0;
|
|
5127
4760
|
options.DR.Font[this._font.id] = this._font.ref();
|
|
5128
4761
|
options.DA = new String(`/${this._font.id} ${fontSize} Tf 0 g`);
|
|
@@ -5174,19 +4807,6 @@ var AcroFormMixin = {
|
|
|
5174
4807
|
};
|
|
5175
4808
|
|
|
5176
4809
|
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
4810
|
file(src, options = {}) {
|
|
5191
4811
|
options.name = options.name || src;
|
|
5192
4812
|
options.relationship = options.relationship || 'Unspecified';
|
|
@@ -5203,8 +4823,8 @@ var AttachmentsMixin = {
|
|
|
5203
4823
|
} else if (src instanceof ArrayBuffer) {
|
|
5204
4824
|
data = Buffer.from(new Uint8Array(src));
|
|
5205
4825
|
} else {
|
|
5206
|
-
|
|
5207
|
-
if (match
|
|
4826
|
+
const match = /^data:(.*?);base64,(.*)$/.exec(src);
|
|
4827
|
+
if (match) {
|
|
5208
4828
|
if (match[1]) {
|
|
5209
4829
|
refBody.Subtype = match[1].replace('/', '#2F');
|
|
5210
4830
|
}
|
|
@@ -5214,8 +4834,6 @@ var AttachmentsMixin = {
|
|
|
5214
4834
|
if (!data) {
|
|
5215
4835
|
throw new Error(`Could not read contents of file at filepath ${src}`);
|
|
5216
4836
|
}
|
|
5217
|
-
|
|
5218
|
-
// update CreationDate and ModDate
|
|
5219
4837
|
const {
|
|
5220
4838
|
birthtime,
|
|
5221
4839
|
ctime
|
|
@@ -5224,26 +4842,18 @@ var AttachmentsMixin = {
|
|
|
5224
4842
|
refBody.Params.ModDate = ctime;
|
|
5225
4843
|
}
|
|
5226
4844
|
}
|
|
5227
|
-
|
|
5228
|
-
// override creation date and modified date
|
|
5229
4845
|
if (options.creationDate instanceof Date) {
|
|
5230
4846
|
refBody.Params.CreationDate = options.creationDate;
|
|
5231
4847
|
}
|
|
5232
4848
|
if (options.modifiedDate instanceof Date) {
|
|
5233
4849
|
refBody.Params.ModDate = options.modifiedDate;
|
|
5234
4850
|
}
|
|
5235
|
-
// add optional subtype
|
|
5236
4851
|
if (options.type) {
|
|
5237
4852
|
refBody.Subtype = options.type.replace('/', '#2F');
|
|
5238
4853
|
}
|
|
5239
|
-
|
|
5240
|
-
// add checksum and size information
|
|
5241
4854
|
const checksum = CryptoJS.MD5(CryptoJS.lib.WordArray.create(new Uint8Array(data)));
|
|
5242
4855
|
refBody.Params.CheckSum = new String(checksum);
|
|
5243
4856
|
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
4857
|
let ref;
|
|
5248
4858
|
if (!this._fileRegistry) this._fileRegistry = {};
|
|
5249
4859
|
let file = this._fileRegistry[options.name];
|
|
@@ -5257,7 +4867,6 @@ var AttachmentsMixin = {
|
|
|
5257
4867
|
ref
|
|
5258
4868
|
};
|
|
5259
4869
|
}
|
|
5260
|
-
// add filespec for embedded file
|
|
5261
4870
|
const fileSpecBody = {
|
|
5262
4871
|
Type: 'Filespec',
|
|
5263
4872
|
AFRelationship: options.relationship,
|
|
@@ -5275,8 +4884,6 @@ var AttachmentsMixin = {
|
|
|
5275
4884
|
if (!options.hidden) {
|
|
5276
4885
|
this.addNamedEmbeddedFile(options.name, filespec);
|
|
5277
4886
|
}
|
|
5278
|
-
|
|
5279
|
-
// Add file to the catalogue to be PDF/A3 compliant
|
|
5280
4887
|
if (this._root.data.AF) {
|
|
5281
4888
|
this._root.data.AF.push(filespec);
|
|
5282
4889
|
} else {
|
|
@@ -5285,8 +4892,6 @@ var AttachmentsMixin = {
|
|
|
5285
4892
|
return filespec;
|
|
5286
4893
|
}
|
|
5287
4894
|
};
|
|
5288
|
-
|
|
5289
|
-
/** check two embedded file metadata objects for equality */
|
|
5290
4895
|
function isEqual(a, b) {
|
|
5291
4896
|
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
4897
|
}
|
|
@@ -5297,7 +4902,6 @@ var PDFA = {
|
|
|
5297
4902
|
this.subset_conformance = pSubset.charAt(pSubset.length - 1).toUpperCase();
|
|
5298
4903
|
this.subset = parseInt(pSubset.charAt(pSubset.length - 2));
|
|
5299
4904
|
} else {
|
|
5300
|
-
// Default to Basic conformance when user doesn't specify
|
|
5301
4905
|
this.subset_conformance = 'B';
|
|
5302
4906
|
this.subset = parseInt(pSubset.charAt(pSubset.length - 1));
|
|
5303
4907
|
}
|
|
@@ -5382,6 +4986,642 @@ var SubsetMixin = {
|
|
|
5382
4986
|
}
|
|
5383
4987
|
};
|
|
5384
4988
|
|
|
4989
|
+
const ROW_FIELDS = ['height', 'minHeight', 'maxHeight'];
|
|
4990
|
+
const COLUMN_FIELDS = ['width', 'minWidth', 'maxWidth'];
|
|
4991
|
+
function memoize(fn, maxSize) {
|
|
4992
|
+
const cache = new Map();
|
|
4993
|
+
return function (...args) {
|
|
4994
|
+
const key = args[0];
|
|
4995
|
+
if (!cache.has(key)) {
|
|
4996
|
+
cache.set(key, fn(...args));
|
|
4997
|
+
if (cache.size > maxSize) cache.delete(cache.keys().next());
|
|
4998
|
+
}
|
|
4999
|
+
return cache.get(key);
|
|
5000
|
+
};
|
|
5001
|
+
}
|
|
5002
|
+
function isObject(item) {
|
|
5003
|
+
return item && typeof item === 'object' && !Array.isArray(item);
|
|
5004
|
+
}
|
|
5005
|
+
function deepMerge(target, ...sources) {
|
|
5006
|
+
if (!isObject(target)) return target;
|
|
5007
|
+
target = deepClone(target);
|
|
5008
|
+
for (const source of sources) {
|
|
5009
|
+
if (isObject(source)) {
|
|
5010
|
+
for (const key in source) {
|
|
5011
|
+
if (isObject(source[key])) {
|
|
5012
|
+
if (!(key in target)) target[key] = {};
|
|
5013
|
+
target[key] = deepMerge(target[key], source[key]);
|
|
5014
|
+
} else if (source[key] !== undefined) {
|
|
5015
|
+
target[key] = deepClone(source[key]);
|
|
5016
|
+
}
|
|
5017
|
+
}
|
|
5018
|
+
}
|
|
5019
|
+
}
|
|
5020
|
+
return target;
|
|
5021
|
+
}
|
|
5022
|
+
function deepClone(obj) {
|
|
5023
|
+
let result = obj;
|
|
5024
|
+
if (obj && typeof obj == 'object') {
|
|
5025
|
+
result = Array.isArray(obj) ? [] : {};
|
|
5026
|
+
for (const key in obj) result[key] = deepClone(obj[key]);
|
|
5027
|
+
}
|
|
5028
|
+
return result;
|
|
5029
|
+
}
|
|
5030
|
+
|
|
5031
|
+
function normalizedDefaultStyle(defaultStyleInternal) {
|
|
5032
|
+
let defaultStyle = defaultStyleInternal;
|
|
5033
|
+
if (typeof defaultStyle !== 'object') defaultStyle = {
|
|
5034
|
+
text: defaultStyle
|
|
5035
|
+
};
|
|
5036
|
+
const defaultRowStyle = Object.fromEntries(Object.entries(defaultStyle).filter(([k]) => ROW_FIELDS.includes(k)));
|
|
5037
|
+
const defaultColStyle = Object.fromEntries(Object.entries(defaultStyle).filter(([k]) => COLUMN_FIELDS.includes(k)));
|
|
5038
|
+
defaultStyle.padding = normalizeSides(defaultStyle.padding);
|
|
5039
|
+
defaultStyle.border = normalizeSides(defaultStyle.border);
|
|
5040
|
+
defaultStyle.borderColor = normalizeSides(defaultStyle.borderColor);
|
|
5041
|
+
defaultStyle.align = normalizeAlignment(defaultStyle.align);
|
|
5042
|
+
return {
|
|
5043
|
+
defaultStyle,
|
|
5044
|
+
defaultRowStyle,
|
|
5045
|
+
defaultColStyle
|
|
5046
|
+
};
|
|
5047
|
+
}
|
|
5048
|
+
function normalizedRowStyle(defaultRowStyle, rowStyleInternal, i) {
|
|
5049
|
+
let rowStyle = rowStyleInternal(i);
|
|
5050
|
+
if (rowStyle == null || typeof rowStyle !== 'object') {
|
|
5051
|
+
rowStyle = {
|
|
5052
|
+
height: rowStyle
|
|
5053
|
+
};
|
|
5054
|
+
}
|
|
5055
|
+
rowStyle.padding = normalizeSides(rowStyle.padding);
|
|
5056
|
+
rowStyle.border = normalizeSides(rowStyle.border);
|
|
5057
|
+
rowStyle.borderColor = normalizeSides(rowStyle.borderColor);
|
|
5058
|
+
rowStyle.align = normalizeAlignment(rowStyle.align);
|
|
5059
|
+
rowStyle = deepMerge(defaultRowStyle, rowStyle);
|
|
5060
|
+
const document = this.document;
|
|
5061
|
+
const page = document.page;
|
|
5062
|
+
const contentHeight = page.contentHeight;
|
|
5063
|
+
if (rowStyle.height == null || rowStyle.height === 'auto') {
|
|
5064
|
+
rowStyle.height = 'auto';
|
|
5065
|
+
} else {
|
|
5066
|
+
rowStyle.height = document.sizeToPoint(rowStyle.height, 0, page, contentHeight);
|
|
5067
|
+
}
|
|
5068
|
+
rowStyle.minHeight = document.sizeToPoint(rowStyle.minHeight, 0, page, contentHeight);
|
|
5069
|
+
rowStyle.maxHeight = document.sizeToPoint(rowStyle.maxHeight, 0, page, contentHeight);
|
|
5070
|
+
return rowStyle;
|
|
5071
|
+
}
|
|
5072
|
+
function normalizedColumnStyle(defaultColStyle, colStyleInternal, i) {
|
|
5073
|
+
let colStyle = colStyleInternal(i);
|
|
5074
|
+
if (colStyle == null || typeof colStyle !== 'object') {
|
|
5075
|
+
colStyle = {
|
|
5076
|
+
width: colStyle
|
|
5077
|
+
};
|
|
5078
|
+
}
|
|
5079
|
+
colStyle.padding = normalizeSides(colStyle.padding);
|
|
5080
|
+
colStyle.border = normalizeSides(colStyle.border);
|
|
5081
|
+
colStyle.borderColor = normalizeSides(colStyle.borderColor);
|
|
5082
|
+
colStyle.align = normalizeAlignment(colStyle.align);
|
|
5083
|
+
colStyle = deepMerge(defaultColStyle, colStyle);
|
|
5084
|
+
if (colStyle.width == null || colStyle.width === '*') {
|
|
5085
|
+
colStyle.width = '*';
|
|
5086
|
+
} else {
|
|
5087
|
+
colStyle.width = this.document.sizeToPoint(colStyle.width, 0, this.document.page, this._maxWidth);
|
|
5088
|
+
}
|
|
5089
|
+
colStyle.minWidth = this.document.sizeToPoint(colStyle.minWidth, 0, this.document.page, this._maxWidth);
|
|
5090
|
+
colStyle.maxWidth = this.document.sizeToPoint(colStyle.maxWidth, 0, this.document.page, this._maxWidth);
|
|
5091
|
+
return colStyle;
|
|
5092
|
+
}
|
|
5093
|
+
function normalizeAlignment(align) {
|
|
5094
|
+
return align == null || typeof align === 'string' ? {
|
|
5095
|
+
x: align,
|
|
5096
|
+
y: align
|
|
5097
|
+
} : align;
|
|
5098
|
+
}
|
|
5099
|
+
|
|
5100
|
+
function normalizeTable() {
|
|
5101
|
+
const doc = this.document;
|
|
5102
|
+
const opts = this.opts;
|
|
5103
|
+
let index = doc._tableIndex++;
|
|
5104
|
+
this._id = new String(opts.id ?? `table-${index}`);
|
|
5105
|
+
this._position = {
|
|
5106
|
+
x: doc.sizeToPoint(opts.position?.x, doc.x),
|
|
5107
|
+
y: doc.sizeToPoint(opts.position?.y, doc.y)
|
|
5108
|
+
};
|
|
5109
|
+
this._maxWidth = doc.sizeToPoint(opts.maxWidth, doc.page.width - doc.page.margins.right - this._position.x);
|
|
5110
|
+
const {
|
|
5111
|
+
defaultStyle,
|
|
5112
|
+
defaultColStyle,
|
|
5113
|
+
defaultRowStyle
|
|
5114
|
+
} = normalizedDefaultStyle(opts.defaultStyle);
|
|
5115
|
+
this._defaultStyle = defaultStyle;
|
|
5116
|
+
let colStyle;
|
|
5117
|
+
if (opts.columnStyles) {
|
|
5118
|
+
if (Array.isArray(opts.columnStyles)) {
|
|
5119
|
+
colStyle = i => opts.columnStyles[i];
|
|
5120
|
+
} else if (typeof opts.columnStyles === 'function') {
|
|
5121
|
+
colStyle = memoize(i => opts.columnStyles(i), Infinity);
|
|
5122
|
+
} else if (typeof opts.columnStyles === 'object') {
|
|
5123
|
+
colStyle = () => opts.columnStyles;
|
|
5124
|
+
}
|
|
5125
|
+
}
|
|
5126
|
+
if (!colStyle) colStyle = () => ({});
|
|
5127
|
+
this._colStyle = normalizedColumnStyle.bind(this, defaultColStyle, colStyle);
|
|
5128
|
+
let rowStyle;
|
|
5129
|
+
if (opts.rowStyles) {
|
|
5130
|
+
if (Array.isArray(opts.rowStyles)) {
|
|
5131
|
+
rowStyle = i => opts.rowStyles[i];
|
|
5132
|
+
} else if (typeof opts.rowStyles === 'function') {
|
|
5133
|
+
rowStyle = memoize(i => opts.rowStyles(i), 10);
|
|
5134
|
+
} else if (typeof opts.rowStyles === 'object') {
|
|
5135
|
+
rowStyle = () => opts.rowStyles;
|
|
5136
|
+
}
|
|
5137
|
+
}
|
|
5138
|
+
if (!rowStyle) rowStyle = () => ({});
|
|
5139
|
+
this._rowStyle = normalizedRowStyle.bind(this, defaultRowStyle, rowStyle);
|
|
5140
|
+
}
|
|
5141
|
+
function normalizeText(text) {
|
|
5142
|
+
if (text != null) text = `${text}`;
|
|
5143
|
+
return text;
|
|
5144
|
+
}
|
|
5145
|
+
function normalizeCell(cell, rowIndex, colIndex) {
|
|
5146
|
+
const colStyle = this._colStyle(colIndex);
|
|
5147
|
+
let rowStyle = this._rowStyle(rowIndex);
|
|
5148
|
+
const font = deepMerge({}, colStyle.font, rowStyle.font, cell.font);
|
|
5149
|
+
const customFont = Object.values(font).filter(v => v != null).length > 0;
|
|
5150
|
+
const doc = this.document;
|
|
5151
|
+
const rollbackFont = doc._fontSource;
|
|
5152
|
+
const rollbackFontSize = doc._fontSize;
|
|
5153
|
+
const rollbackFontFamily = doc._fontFamily;
|
|
5154
|
+
if (customFont) {
|
|
5155
|
+
if (font.src) doc.font(font.src, font.family);
|
|
5156
|
+
if (font.size) doc.fontSize(font.size);
|
|
5157
|
+
rowStyle = this._rowStyle(rowIndex);
|
|
5158
|
+
}
|
|
5159
|
+
cell.padding = normalizeSides(cell.padding);
|
|
5160
|
+
cell.border = normalizeSides(cell.border);
|
|
5161
|
+
cell.borderColor = normalizeSides(cell.borderColor);
|
|
5162
|
+
const config = deepMerge(this._defaultStyle, colStyle, rowStyle, cell);
|
|
5163
|
+
config.rowIndex = rowIndex;
|
|
5164
|
+
config.colIndex = colIndex;
|
|
5165
|
+
config.font = font ?? {};
|
|
5166
|
+
config.customFont = customFont;
|
|
5167
|
+
config.text = normalizeText(config.text);
|
|
5168
|
+
config.rowSpan = config.rowSpan ?? 1;
|
|
5169
|
+
config.colSpan = config.colSpan ?? 1;
|
|
5170
|
+
config.padding = normalizeSides(config.padding, '0.25em', x => doc.sizeToPoint(x, '0.25em'));
|
|
5171
|
+
config.border = normalizeSides(config.border, 1, x => doc.sizeToPoint(x, 1));
|
|
5172
|
+
config.borderColor = normalizeSides(config.borderColor, 'black', x => x ?? 'black');
|
|
5173
|
+
config.align = normalizeAlignment(config.align);
|
|
5174
|
+
config.align.x = config.align.x ?? 'left';
|
|
5175
|
+
config.align.y = config.align.y ?? 'top';
|
|
5176
|
+
config.textStroke = doc.sizeToPoint(config.textStroke, 0);
|
|
5177
|
+
config.textStrokeColor = config.textStrokeColor ?? 'black';
|
|
5178
|
+
config.textColor = config.textColor ?? 'black';
|
|
5179
|
+
config.textOptions = config.textOptions ?? {};
|
|
5180
|
+
config.id = new String(config.id ?? `${this._id}-${rowIndex}-${colIndex}`);
|
|
5181
|
+
config.type = config.type?.toUpperCase() === 'TH' ? 'TH' : 'TD';
|
|
5182
|
+
if (config.scope) {
|
|
5183
|
+
config.scope = config.scope.toLowerCase();
|
|
5184
|
+
if (config.scope === 'row') config.scope = 'Row';else if (config.scope === 'both') config.scope = 'Both';else if (config.scope === 'column') config.scope = 'Column';
|
|
5185
|
+
}
|
|
5186
|
+
if (typeof this.opts.debug === 'boolean') config.debug = this.opts.debug;
|
|
5187
|
+
if (customFont) doc.font(rollbackFont, rollbackFontFamily, rollbackFontSize);
|
|
5188
|
+
return config;
|
|
5189
|
+
}
|
|
5190
|
+
function normalizeRow(row, rowIndex) {
|
|
5191
|
+
if (!this._cellClaim) this._cellClaim = new Set();
|
|
5192
|
+
let colIndex = 0;
|
|
5193
|
+
return row.map(cell => {
|
|
5194
|
+
if (cell == null || typeof cell !== 'object') cell = {
|
|
5195
|
+
text: cell
|
|
5196
|
+
};
|
|
5197
|
+
while (this._cellClaim.has(`${rowIndex},${colIndex}`)) {
|
|
5198
|
+
colIndex++;
|
|
5199
|
+
}
|
|
5200
|
+
cell = normalizeCell.call(this, cell, rowIndex, colIndex);
|
|
5201
|
+
for (let i = 0; i < cell.rowSpan; i++) {
|
|
5202
|
+
for (let j = 0; j < cell.colSpan; j++) {
|
|
5203
|
+
this._cellClaim.add(`${rowIndex + i},${colIndex + j}`);
|
|
5204
|
+
}
|
|
5205
|
+
}
|
|
5206
|
+
colIndex += cell.colSpan;
|
|
5207
|
+
return cell;
|
|
5208
|
+
});
|
|
5209
|
+
}
|
|
5210
|
+
|
|
5211
|
+
function ensure(row) {
|
|
5212
|
+
this._columnWidths = [];
|
|
5213
|
+
ensureColumnWidths.call(this, row.reduce((a, cell) => a + cell.colSpan, 0));
|
|
5214
|
+
this._rowHeights = [];
|
|
5215
|
+
this._rowYPos = [this._position.y];
|
|
5216
|
+
this._rowBuffer = new Set();
|
|
5217
|
+
}
|
|
5218
|
+
function ensureColumnWidths(numCols) {
|
|
5219
|
+
let starColumnIndexes = [];
|
|
5220
|
+
let starMinAcc = 0;
|
|
5221
|
+
let unclaimedWidth = this._maxWidth;
|
|
5222
|
+
for (let i = 0; i < numCols; i++) {
|
|
5223
|
+
let col = this._colStyle(i);
|
|
5224
|
+
if (col.width === '*') {
|
|
5225
|
+
starColumnIndexes[i] = col;
|
|
5226
|
+
starMinAcc += col.minWidth;
|
|
5227
|
+
} else {
|
|
5228
|
+
unclaimedWidth -= col.width;
|
|
5229
|
+
this._columnWidths[i] = col.width;
|
|
5230
|
+
}
|
|
5231
|
+
}
|
|
5232
|
+
let starColCount = starColumnIndexes.reduce(x => x + 1, 0);
|
|
5233
|
+
if (starMinAcc >= unclaimedWidth) {
|
|
5234
|
+
starColumnIndexes.forEach((cell, i) => {
|
|
5235
|
+
this._columnWidths[i] = cell.minWidth;
|
|
5236
|
+
});
|
|
5237
|
+
} else if (starColCount > 0) {
|
|
5238
|
+
starColumnIndexes.forEach((col, i) => {
|
|
5239
|
+
let starSize = unclaimedWidth / starColCount;
|
|
5240
|
+
this._columnWidths[i] = Math.max(starSize, col.minWidth);
|
|
5241
|
+
if (col.maxWidth > 0) {
|
|
5242
|
+
this._columnWidths[i] = Math.min(this._columnWidths[i], col.maxWidth);
|
|
5243
|
+
}
|
|
5244
|
+
unclaimedWidth -= this._columnWidths[i];
|
|
5245
|
+
starColCount--;
|
|
5246
|
+
});
|
|
5247
|
+
}
|
|
5248
|
+
let tempX = this._position.x;
|
|
5249
|
+
this._columnXPos = Array.from(this._columnWidths, v => {
|
|
5250
|
+
const t = tempX;
|
|
5251
|
+
tempX += v;
|
|
5252
|
+
return t;
|
|
5253
|
+
});
|
|
5254
|
+
}
|
|
5255
|
+
function measure(row, rowIndex) {
|
|
5256
|
+
row.forEach(cell => this._rowBuffer.add(cell));
|
|
5257
|
+
if (rowIndex > 0) {
|
|
5258
|
+
this._rowYPos[rowIndex] = this._rowYPos[rowIndex - 1] + this._rowHeights[rowIndex - 1];
|
|
5259
|
+
}
|
|
5260
|
+
const rowStyle = this._rowStyle(rowIndex);
|
|
5261
|
+
let toRender = [];
|
|
5262
|
+
this._rowBuffer.forEach(cell => {
|
|
5263
|
+
if (cell.rowIndex + cell.rowSpan - 1 === rowIndex) {
|
|
5264
|
+
toRender.push(measureCell.call(this, cell, rowStyle.height));
|
|
5265
|
+
this._rowBuffer.delete(cell);
|
|
5266
|
+
}
|
|
5267
|
+
});
|
|
5268
|
+
let rowHeight = rowStyle.height;
|
|
5269
|
+
if (rowHeight === 'auto') {
|
|
5270
|
+
rowHeight = toRender.reduce((acc, cell) => {
|
|
5271
|
+
let minHeight = cell.textBounds.height + cell.padding.top + cell.padding.bottom;
|
|
5272
|
+
for (let i = 0; i < cell.rowSpan - 1; i++) {
|
|
5273
|
+
minHeight -= this._rowHeights[cell.rowIndex + i];
|
|
5274
|
+
}
|
|
5275
|
+
return Math.max(acc, minHeight);
|
|
5276
|
+
}, 0);
|
|
5277
|
+
}
|
|
5278
|
+
rowHeight = Math.max(rowHeight, rowStyle.minHeight);
|
|
5279
|
+
if (rowStyle.maxHeight > 0) {
|
|
5280
|
+
rowHeight = Math.min(rowHeight, rowStyle.maxHeight);
|
|
5281
|
+
}
|
|
5282
|
+
this._rowHeights[rowIndex] = rowHeight;
|
|
5283
|
+
let newPage = false;
|
|
5284
|
+
if (rowHeight > this.document.page.contentHeight) {
|
|
5285
|
+
console.warn(new Error(`Row ${rowIndex} requested more than the safe page height, row has been clamped`).stack.slice(7));
|
|
5286
|
+
this._rowHeights[rowIndex] = this.document.page.maxY() - this._rowYPos[rowIndex];
|
|
5287
|
+
} else if (this._rowYPos[rowIndex] + rowHeight >= this.document.page.maxY()) {
|
|
5288
|
+
this._rowYPos[rowIndex] = this.document.page.margins.top;
|
|
5289
|
+
newPage = true;
|
|
5290
|
+
}
|
|
5291
|
+
return {
|
|
5292
|
+
newPage,
|
|
5293
|
+
toRender: toRender.map(cell => measureCell.call(this, cell, rowHeight))
|
|
5294
|
+
};
|
|
5295
|
+
}
|
|
5296
|
+
function measureCell(cell, rowHeight) {
|
|
5297
|
+
let cellWidth = 0;
|
|
5298
|
+
for (let i = 0; i < cell.colSpan; i++) {
|
|
5299
|
+
cellWidth += this._columnWidths[cell.colIndex + i];
|
|
5300
|
+
}
|
|
5301
|
+
let cellHeight = rowHeight;
|
|
5302
|
+
if (cellHeight === 'auto') {
|
|
5303
|
+
cellHeight = this.document.page.contentHeight;
|
|
5304
|
+
} else {
|
|
5305
|
+
for (let i = 0; i < cell.rowSpan - 1; i++) {
|
|
5306
|
+
cellHeight += this._rowHeights[cell.rowIndex + i];
|
|
5307
|
+
}
|
|
5308
|
+
}
|
|
5309
|
+
const textAllocatedWidth = cellWidth - cell.padding.left - cell.padding.right;
|
|
5310
|
+
const textAllocatedHeight = cellHeight - cell.padding.top - cell.padding.bottom;
|
|
5311
|
+
const rotation = cell.textOptions.rotation ?? 0;
|
|
5312
|
+
const {
|
|
5313
|
+
width: textMaxWidth,
|
|
5314
|
+
height: textMaxHeight
|
|
5315
|
+
} = computeBounds(rotation, textAllocatedWidth, textAllocatedHeight);
|
|
5316
|
+
const textOptions = {
|
|
5317
|
+
align: cell.align.x,
|
|
5318
|
+
ellipsis: true,
|
|
5319
|
+
stroke: cell.textStroke > 0,
|
|
5320
|
+
fill: true,
|
|
5321
|
+
width: textMaxWidth,
|
|
5322
|
+
height: textMaxHeight,
|
|
5323
|
+
rotation,
|
|
5324
|
+
...cell.textOptions
|
|
5325
|
+
};
|
|
5326
|
+
let textBounds = {
|
|
5327
|
+
x: 0,
|
|
5328
|
+
y: 0,
|
|
5329
|
+
width: 0,
|
|
5330
|
+
height: 0
|
|
5331
|
+
};
|
|
5332
|
+
if (cell.text) {
|
|
5333
|
+
const rollbackFont = this.document._fontSource;
|
|
5334
|
+
const rollbackFontSize = this.document._fontSize;
|
|
5335
|
+
const rollbackFontFamily = this.document._fontFamily;
|
|
5336
|
+
if (cell.font?.src) this.document.font(cell.font.src, cell.font?.family);
|
|
5337
|
+
if (cell.font?.size) this.document.fontSize(cell.font.size);
|
|
5338
|
+
const unRotatedTextBounds = this.document.boundsOfString(cell.text, 0, 0, {
|
|
5339
|
+
...textOptions,
|
|
5340
|
+
rotation: 0
|
|
5341
|
+
});
|
|
5342
|
+
textOptions.width = unRotatedTextBounds.width;
|
|
5343
|
+
textOptions.height = unRotatedTextBounds.height;
|
|
5344
|
+
textBounds = this.document.boundsOfString(cell.text, 0, 0, textOptions);
|
|
5345
|
+
this.document.font(rollbackFont, rollbackFontFamily, rollbackFontSize);
|
|
5346
|
+
}
|
|
5347
|
+
return {
|
|
5348
|
+
...cell,
|
|
5349
|
+
textOptions,
|
|
5350
|
+
x: this._columnXPos[cell.colIndex],
|
|
5351
|
+
y: this._rowYPos[cell.rowIndex],
|
|
5352
|
+
textX: this._columnXPos[cell.colIndex] + cell.padding.left,
|
|
5353
|
+
textY: this._rowYPos[cell.rowIndex] + cell.padding.top,
|
|
5354
|
+
width: cellWidth,
|
|
5355
|
+
height: cellHeight,
|
|
5356
|
+
textAllocatedHeight,
|
|
5357
|
+
textAllocatedWidth,
|
|
5358
|
+
textBounds
|
|
5359
|
+
};
|
|
5360
|
+
}
|
|
5361
|
+
function computeBounds(rotation, allocWidth, allocHeight) {
|
|
5362
|
+
let textMaxWidth, textMaxHeight;
|
|
5363
|
+
const cos = cosine(rotation);
|
|
5364
|
+
const sin = sine(rotation);
|
|
5365
|
+
if (rotation === 0 || rotation === 180) {
|
|
5366
|
+
textMaxWidth = allocWidth;
|
|
5367
|
+
textMaxHeight = allocHeight;
|
|
5368
|
+
} else if (rotation === 90 || rotation === 270) {
|
|
5369
|
+
textMaxWidth = allocHeight;
|
|
5370
|
+
textMaxHeight = allocWidth;
|
|
5371
|
+
} else if (rotation < 90 || rotation > 180 && rotation < 270) {
|
|
5372
|
+
textMaxWidth = allocWidth / (2 * cos);
|
|
5373
|
+
textMaxHeight = allocWidth / (2 * sin);
|
|
5374
|
+
} else {
|
|
5375
|
+
textMaxHeight = allocWidth / (2 * cos);
|
|
5376
|
+
textMaxWidth = allocWidth / (2 * sin);
|
|
5377
|
+
}
|
|
5378
|
+
const EF = sin * textMaxWidth;
|
|
5379
|
+
const FG = cos * textMaxHeight;
|
|
5380
|
+
if (EF + FG > allocHeight) {
|
|
5381
|
+
const denominator = cos * cos - sin * sin;
|
|
5382
|
+
if (rotation === 0 || rotation === 180) {
|
|
5383
|
+
textMaxWidth = allocWidth;
|
|
5384
|
+
textMaxHeight = allocHeight;
|
|
5385
|
+
} else if (rotation === 90 || rotation === 270) {
|
|
5386
|
+
textMaxWidth = allocHeight;
|
|
5387
|
+
textMaxHeight = allocWidth;
|
|
5388
|
+
} else if (rotation < 90 || rotation > 180 && rotation < 270) {
|
|
5389
|
+
textMaxWidth = (allocWidth * cos - allocHeight * sin) / denominator;
|
|
5390
|
+
textMaxHeight = (allocHeight * cos - allocWidth * sin) / denominator;
|
|
5391
|
+
} else {
|
|
5392
|
+
textMaxHeight = (allocWidth * cos - allocHeight * sin) / denominator;
|
|
5393
|
+
textMaxWidth = (allocHeight * cos - allocWidth * sin) / denominator;
|
|
5394
|
+
}
|
|
5395
|
+
}
|
|
5396
|
+
return {
|
|
5397
|
+
width: Math.abs(textMaxWidth),
|
|
5398
|
+
height: Math.abs(textMaxHeight)
|
|
5399
|
+
};
|
|
5400
|
+
}
|
|
5401
|
+
|
|
5402
|
+
function accommodateTable() {
|
|
5403
|
+
const structParent = this.opts.structParent;
|
|
5404
|
+
if (structParent) {
|
|
5405
|
+
this._tableStruct = this.document.struct('Table');
|
|
5406
|
+
this._tableStruct.dictionary.data.ID = this._id;
|
|
5407
|
+
if (structParent instanceof PDFStructureElement) {
|
|
5408
|
+
structParent.add(this._tableStruct);
|
|
5409
|
+
} else if (structParent instanceof PDFDocument) {
|
|
5410
|
+
structParent.addStructure(this._tableStruct);
|
|
5411
|
+
}
|
|
5412
|
+
this._headerRowLookup = {};
|
|
5413
|
+
this._headerColumnLookup = {};
|
|
5414
|
+
}
|
|
5415
|
+
}
|
|
5416
|
+
function accommodateCleanup() {
|
|
5417
|
+
if (this._tableStruct) this._tableStruct.end();
|
|
5418
|
+
}
|
|
5419
|
+
function accessibleRow(row, rowIndex, renderCell) {
|
|
5420
|
+
const rowStruct = this.document.struct('TR');
|
|
5421
|
+
rowStruct.dictionary.data.ID = new String(`${this._id}-${rowIndex}`);
|
|
5422
|
+
this._tableStruct.add(rowStruct);
|
|
5423
|
+
row.forEach(cell => renderCell(cell, rowStruct));
|
|
5424
|
+
rowStruct.end();
|
|
5425
|
+
}
|
|
5426
|
+
function accessibleCell(cell, rowStruct, callback) {
|
|
5427
|
+
const doc = this.document;
|
|
5428
|
+
const cellStruct = doc.struct(cell.type, {
|
|
5429
|
+
title: cell.title
|
|
5430
|
+
});
|
|
5431
|
+
cellStruct.dictionary.data.ID = cell.id;
|
|
5432
|
+
rowStruct.add(cellStruct);
|
|
5433
|
+
const padding = cell.padding;
|
|
5434
|
+
const border = cell.border;
|
|
5435
|
+
const attributes = {
|
|
5436
|
+
O: 'Table',
|
|
5437
|
+
Width: cell.width,
|
|
5438
|
+
Height: cell.height,
|
|
5439
|
+
Padding: [padding.top, padding.bottom, padding.left, padding.right],
|
|
5440
|
+
RowSpan: cell.rowSpan > 1 ? cell.rowSpan : undefined,
|
|
5441
|
+
ColSpan: cell.colSpan > 1 ? cell.colSpan : undefined,
|
|
5442
|
+
BorderThickness: [border.top, border.bottom, border.left, border.right]
|
|
5443
|
+
};
|
|
5444
|
+
if (cell.type === 'TH') {
|
|
5445
|
+
if (cell.scope === 'Row' || cell.scope === 'Both') {
|
|
5446
|
+
for (let i = 0; i < cell.rowSpan; i++) {
|
|
5447
|
+
if (!this._headerRowLookup[cell.rowIndex + i]) {
|
|
5448
|
+
this._headerRowLookup[cell.rowIndex + i] = [];
|
|
5449
|
+
}
|
|
5450
|
+
this._headerRowLookup[cell.rowIndex + i].push(cell.id);
|
|
5451
|
+
}
|
|
5452
|
+
attributes.Scope = cell.scope;
|
|
5453
|
+
}
|
|
5454
|
+
if (cell.scope === 'Column' || cell.scope === 'Both') {
|
|
5455
|
+
for (let i = 0; i < cell.colSpan; i++) {
|
|
5456
|
+
if (!this._headerColumnLookup[cell.colIndex + i]) {
|
|
5457
|
+
this._headerColumnLookup[cell.colIndex + i] = [];
|
|
5458
|
+
}
|
|
5459
|
+
this._headerColumnLookup[cell.colIndex + i].push(cell.id);
|
|
5460
|
+
}
|
|
5461
|
+
attributes.Scope = cell.scope;
|
|
5462
|
+
}
|
|
5463
|
+
}
|
|
5464
|
+
const Headers = new Set([...Array.from({
|
|
5465
|
+
length: cell.colSpan
|
|
5466
|
+
}, (_, i) => this._headerColumnLookup[cell.colIndex + i]).flat(), ...Array.from({
|
|
5467
|
+
length: cell.rowSpan
|
|
5468
|
+
}, (_, i) => this._headerRowLookup[cell.rowIndex + i]).flat()].filter(Boolean));
|
|
5469
|
+
if (Headers.size) attributes.Headers = Array.from(Headers);
|
|
5470
|
+
const normalizeColor = doc._normalizeColor;
|
|
5471
|
+
if (cell.backgroundColor != null) {
|
|
5472
|
+
attributes.BackgroundColor = normalizeColor(cell.backgroundColor);
|
|
5473
|
+
}
|
|
5474
|
+
const hasBorder = [border.top, border.bottom, border.left, border.right];
|
|
5475
|
+
if (hasBorder.some(x => x)) {
|
|
5476
|
+
const borderColor = cell.borderColor;
|
|
5477
|
+
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];
|
|
5478
|
+
}
|
|
5479
|
+
Object.keys(attributes).forEach(key => attributes[key] === undefined && delete attributes[key]);
|
|
5480
|
+
cellStruct.dictionary.data.A = doc.ref(attributes);
|
|
5481
|
+
cellStruct.add(callback);
|
|
5482
|
+
cellStruct.end();
|
|
5483
|
+
cellStruct.dictionary.data.A.end();
|
|
5484
|
+
}
|
|
5485
|
+
|
|
5486
|
+
function renderRow(row, rowIndex) {
|
|
5487
|
+
if (this._tableStruct) {
|
|
5488
|
+
accessibleRow.call(this, row, rowIndex, renderCell.bind(this));
|
|
5489
|
+
} else {
|
|
5490
|
+
row.forEach(cell => renderCell.call(this, cell));
|
|
5491
|
+
}
|
|
5492
|
+
return this._rowYPos[rowIndex] + this._rowHeights[rowIndex];
|
|
5493
|
+
}
|
|
5494
|
+
function renderCell(cell, rowStruct) {
|
|
5495
|
+
const cellRenderer = () => {
|
|
5496
|
+
if (cell.backgroundColor != null) {
|
|
5497
|
+
this.document.save().rect(cell.x, cell.y, cell.width, cell.height).fill(cell.backgroundColor).restore();
|
|
5498
|
+
}
|
|
5499
|
+
renderBorder.call(this, cell.border, cell.borderColor, cell.x, cell.y, cell.width, cell.height);
|
|
5500
|
+
if (cell.debug) {
|
|
5501
|
+
this.document.save();
|
|
5502
|
+
this.document.dash(1, {
|
|
5503
|
+
space: 1
|
|
5504
|
+
}).lineWidth(1).strokeOpacity(0.3);
|
|
5505
|
+
this.document.rect(cell.x, cell.y, cell.width, cell.height).stroke('green');
|
|
5506
|
+
this.document.restore();
|
|
5507
|
+
}
|
|
5508
|
+
if (cell.text) renderCellText.call(this, cell);
|
|
5509
|
+
};
|
|
5510
|
+
if (rowStruct) accessibleCell.call(this, cell, rowStruct, cellRenderer);else cellRenderer();
|
|
5511
|
+
}
|
|
5512
|
+
function renderCellText(cell) {
|
|
5513
|
+
const doc = this.document;
|
|
5514
|
+
const rollbackFont = doc._fontSource;
|
|
5515
|
+
const rollbackFontSize = doc._fontSize;
|
|
5516
|
+
const rollbackFontFamily = doc._fontFamily;
|
|
5517
|
+
if (cell.customFont) {
|
|
5518
|
+
if (cell.font.src) doc.font(cell.font.src, cell.font.family);
|
|
5519
|
+
if (cell.font.size) doc.fontSize(cell.font.size);
|
|
5520
|
+
}
|
|
5521
|
+
const x = cell.textX;
|
|
5522
|
+
const y = cell.textY;
|
|
5523
|
+
const Ah = cell.textAllocatedHeight;
|
|
5524
|
+
const Aw = cell.textAllocatedWidth;
|
|
5525
|
+
const Cw = cell.textBounds.width;
|
|
5526
|
+
const Ch = cell.textBounds.height;
|
|
5527
|
+
const Ox = -cell.textBounds.x;
|
|
5528
|
+
const Oy = -cell.textBounds.y;
|
|
5529
|
+
const PxScale = cell.align.x === 'right' ? 1 : cell.align.x === 'center' ? 0.5 : 0;
|
|
5530
|
+
const Px = (Aw - Cw) * PxScale;
|
|
5531
|
+
const PyScale = cell.align.y === 'bottom' ? 1 : cell.align.y === 'center' ? 0.5 : 0;
|
|
5532
|
+
const Py = (Ah - Ch) * PyScale;
|
|
5533
|
+
const dx = Px + Ox;
|
|
5534
|
+
const dy = Py + Oy;
|
|
5535
|
+
if (cell.debug) {
|
|
5536
|
+
doc.save();
|
|
5537
|
+
doc.dash(1, {
|
|
5538
|
+
space: 1
|
|
5539
|
+
}).lineWidth(1).strokeOpacity(0.3);
|
|
5540
|
+
if (cell.text) {
|
|
5541
|
+
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');
|
|
5542
|
+
}
|
|
5543
|
+
doc.rect(x, y, Aw, Ah).stroke('orange');
|
|
5544
|
+
doc.restore();
|
|
5545
|
+
}
|
|
5546
|
+
doc.save().rect(x, y, Aw, Ah).clip();
|
|
5547
|
+
doc.fillColor(cell.textColor).strokeColor(cell.textStrokeColor);
|
|
5548
|
+
if (cell.textStroke > 0) doc.lineWidth(cell.textStroke);
|
|
5549
|
+
doc.text(cell.text, x + dx, y + dy, cell.textOptions);
|
|
5550
|
+
doc.restore();
|
|
5551
|
+
if (cell.font) doc.font(rollbackFont, rollbackFontFamily, rollbackFontSize);
|
|
5552
|
+
}
|
|
5553
|
+
function renderBorder(border, borderColor, x, y, width, height, mask) {
|
|
5554
|
+
border = Object.fromEntries(Object.entries(border).map(([k, v]) => [k, mask && !mask[k] ? 0 : v]));
|
|
5555
|
+
const doc = this.document;
|
|
5556
|
+
if ([border.right, border.bottom, border.left].every(val => val === border.top)) {
|
|
5557
|
+
if (border.top > 0) {
|
|
5558
|
+
doc.save().lineWidth(border.top).rect(x, y, width, height).stroke(borderColor.top).restore();
|
|
5559
|
+
}
|
|
5560
|
+
} else {
|
|
5561
|
+
if (border.top > 0) {
|
|
5562
|
+
doc.save().lineWidth(border.top).moveTo(x, y).lineTo(x + width, y).stroke(borderColor.top).restore();
|
|
5563
|
+
}
|
|
5564
|
+
if (border.right > 0) {
|
|
5565
|
+
doc.save().lineWidth(border.right).moveTo(x + width, y).lineTo(x + width, y + height).stroke(borderColor.right).restore();
|
|
5566
|
+
}
|
|
5567
|
+
if (border.bottom > 0) {
|
|
5568
|
+
doc.save().lineWidth(border.bottom).moveTo(x + width, y + height).lineTo(x, y + height).stroke(borderColor.bottom).restore();
|
|
5569
|
+
}
|
|
5570
|
+
if (border.left > 0) {
|
|
5571
|
+
doc.save().lineWidth(border.left).moveTo(x, y + height).lineTo(x, y).stroke(borderColor.left).restore();
|
|
5572
|
+
}
|
|
5573
|
+
}
|
|
5574
|
+
}
|
|
5575
|
+
|
|
5576
|
+
class PDFTable {
|
|
5577
|
+
constructor(document, opts = {}) {
|
|
5578
|
+
this.document = document;
|
|
5579
|
+
this.opts = Object.freeze(opts);
|
|
5580
|
+
normalizeTable.call(this);
|
|
5581
|
+
accommodateTable.call(this);
|
|
5582
|
+
this._currRowIndex = 0;
|
|
5583
|
+
this._ended = false;
|
|
5584
|
+
if (opts.data) {
|
|
5585
|
+
for (const row of opts.data) this.row(row);
|
|
5586
|
+
return this.end();
|
|
5587
|
+
}
|
|
5588
|
+
}
|
|
5589
|
+
row(row, lastRow = false) {
|
|
5590
|
+
if (this._ended) {
|
|
5591
|
+
throw new Error(`Table was marked as ended on row ${this._currRowIndex}`);
|
|
5592
|
+
}
|
|
5593
|
+
row = Array.from(row);
|
|
5594
|
+
row = normalizeRow.call(this, row, this._currRowIndex);
|
|
5595
|
+
if (this._currRowIndex === 0) ensure.call(this, row);
|
|
5596
|
+
const {
|
|
5597
|
+
newPage,
|
|
5598
|
+
toRender
|
|
5599
|
+
} = measure.call(this, row, this._currRowIndex);
|
|
5600
|
+
if (newPage) this.document.continueOnNewPage();
|
|
5601
|
+
const yPos = renderRow.call(this, toRender, this._currRowIndex);
|
|
5602
|
+
this.document.x = this._position.x;
|
|
5603
|
+
this.document.y = yPos;
|
|
5604
|
+
if (lastRow) return this.end();
|
|
5605
|
+
this._currRowIndex++;
|
|
5606
|
+
return this;
|
|
5607
|
+
}
|
|
5608
|
+
end() {
|
|
5609
|
+
while (this._rowBuffer?.size) this.row([]);
|
|
5610
|
+
this._ended = true;
|
|
5611
|
+
accommodateCleanup.call(this);
|
|
5612
|
+
return this.document;
|
|
5613
|
+
}
|
|
5614
|
+
}
|
|
5615
|
+
|
|
5616
|
+
var TableMixin = {
|
|
5617
|
+
initTables() {
|
|
5618
|
+
this._tableIndex = 0;
|
|
5619
|
+
},
|
|
5620
|
+
table(opts) {
|
|
5621
|
+
return new PDFTable(this, opts);
|
|
5622
|
+
}
|
|
5623
|
+
};
|
|
5624
|
+
|
|
5385
5625
|
class PDFMetadata {
|
|
5386
5626
|
constructor() {
|
|
5387
5627
|
this._metadata = `
|
|
@@ -5423,7 +5663,7 @@ var MetadataMixin = {
|
|
|
5423
5663
|
_addInfo() {
|
|
5424
5664
|
this.appendXML(`
|
|
5425
5665
|
<rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
|
|
5426
|
-
<xmp:CreateDate>${this.info.CreationDate.toISOString().split('.')[0] +
|
|
5666
|
+
<xmp:CreateDate>${this.info.CreationDate.toISOString().split('.')[0] + 'Z'}</xmp:CreateDate>
|
|
5427
5667
|
<xmp:CreatorTool>${this.info.Creator}</xmp:CreatorTool>
|
|
5428
5668
|
</rdf:Description>
|
|
5429
5669
|
`);
|
|
@@ -5476,11 +5716,6 @@ var MetadataMixin = {
|
|
|
5476
5716
|
endMetadata() {
|
|
5477
5717
|
this._addInfo();
|
|
5478
5718
|
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
5719
|
if (this.version != 1.3) {
|
|
5485
5720
|
this.metadataRef = this.ref({
|
|
5486
5721
|
length: this.metadata.getLength(),
|
|
@@ -5495,16 +5730,10 @@ var MetadataMixin = {
|
|
|
5495
5730
|
}
|
|
5496
5731
|
};
|
|
5497
5732
|
|
|
5498
|
-
/*
|
|
5499
|
-
PDFDocument - represents an entire PDF document
|
|
5500
|
-
By Devon Govett
|
|
5501
|
-
*/
|
|
5502
5733
|
class PDFDocument extends stream.Readable {
|
|
5503
5734
|
constructor(options = {}) {
|
|
5504
5735
|
super(options);
|
|
5505
5736
|
this.options = options;
|
|
5506
|
-
|
|
5507
|
-
// PDF version
|
|
5508
5737
|
switch (options.pdfVersion) {
|
|
5509
5738
|
case '1.4':
|
|
5510
5739
|
this.version = 1.4;
|
|
@@ -5523,13 +5752,9 @@ class PDFDocument extends stream.Readable {
|
|
|
5523
5752
|
this.version = 1.3;
|
|
5524
5753
|
break;
|
|
5525
5754
|
}
|
|
5526
|
-
|
|
5527
|
-
// Whether streams should be compressed
|
|
5528
5755
|
this.compress = this.options.compress != null ? this.options.compress : true;
|
|
5529
5756
|
this._pageBuffer = [];
|
|
5530
5757
|
this._pageBufferStart = 0;
|
|
5531
|
-
|
|
5532
|
-
// The PDF object store
|
|
5533
5758
|
this._offsets = [];
|
|
5534
5759
|
this._waiting = 0;
|
|
5535
5760
|
this._ended = false;
|
|
@@ -5550,11 +5775,7 @@ class PDFDocument extends stream.Readable {
|
|
|
5550
5775
|
if (this.options.lang) {
|
|
5551
5776
|
this._root.data.Lang = new String(this.options.lang);
|
|
5552
5777
|
}
|
|
5553
|
-
|
|
5554
|
-
// The current page
|
|
5555
5778
|
this.page = null;
|
|
5556
|
-
|
|
5557
|
-
// Initialize mixins
|
|
5558
5779
|
this.initMetadata();
|
|
5559
5780
|
this.initColor();
|
|
5560
5781
|
this.initVector();
|
|
@@ -5563,9 +5784,8 @@ class PDFDocument extends stream.Readable {
|
|
|
5563
5784
|
this.initImages();
|
|
5564
5785
|
this.initOutline();
|
|
5565
5786
|
this.initMarkings(options);
|
|
5787
|
+
this.initTables();
|
|
5566
5788
|
this.initSubset(options);
|
|
5567
|
-
|
|
5568
|
-
// Initialize the metadata
|
|
5569
5789
|
this.info = {
|
|
5570
5790
|
Producer: 'PDFKit',
|
|
5571
5791
|
Creator: 'PDFKit',
|
|
@@ -5582,21 +5802,10 @@ class PDFDocument extends stream.Readable {
|
|
|
5582
5802
|
DisplayDocTitle: true
|
|
5583
5803
|
});
|
|
5584
5804
|
}
|
|
5585
|
-
|
|
5586
|
-
// Generate file ID
|
|
5587
5805
|
this._id = PDFSecurity.generateFileID(this.info);
|
|
5588
|
-
|
|
5589
|
-
// Initialize security settings
|
|
5590
5806
|
this._security = PDFSecurity.create(this, options);
|
|
5591
|
-
|
|
5592
|
-
// Write the header
|
|
5593
|
-
// PDF version
|
|
5594
5807
|
this._write(`%PDF-${this.version}`);
|
|
5595
|
-
|
|
5596
|
-
// 4 binary chars, as recommended by the spec
|
|
5597
5808
|
this._write('%\xFF\xFF\xFF\xFF');
|
|
5598
|
-
|
|
5599
|
-
// Add the first page
|
|
5600
5809
|
if (this.options.autoFirstPage !== false) {
|
|
5601
5810
|
this.addPage();
|
|
5602
5811
|
}
|
|
@@ -5607,27 +5816,16 @@ class PDFDocument extends stream.Readable {
|
|
|
5607
5816
|
options
|
|
5608
5817
|
} = this);
|
|
5609
5818
|
}
|
|
5610
|
-
|
|
5611
|
-
// end the current page if needed
|
|
5612
5819
|
if (!this.options.bufferPages) {
|
|
5613
5820
|
this.flushPages();
|
|
5614
5821
|
}
|
|
5615
|
-
|
|
5616
|
-
// create a page object
|
|
5617
5822
|
this.page = new PDFPage(this, options);
|
|
5618
5823
|
this._pageBuffer.push(this.page);
|
|
5619
|
-
|
|
5620
|
-
// add the page to the object store
|
|
5621
5824
|
const pages = this._root.data.Pages.data;
|
|
5622
5825
|
pages.Kids.push(this.page.dictionary);
|
|
5623
5826
|
pages.Count++;
|
|
5624
|
-
|
|
5625
|
-
// reset x and y coordinates
|
|
5626
5827
|
this.x = this.page.margins.left;
|
|
5627
5828
|
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
5829
|
this._ctm = [1, 0, 0, 1, 0, 0];
|
|
5632
5830
|
this.transform(1, 0, 0, -1, 0, this.page.height);
|
|
5633
5831
|
this.emit('pageAdded');
|
|
@@ -5635,7 +5833,7 @@ class PDFDocument extends stream.Readable {
|
|
|
5635
5833
|
}
|
|
5636
5834
|
continueOnNewPage(options) {
|
|
5637
5835
|
const pageMarkings = this.endPageMarkings(this.page);
|
|
5638
|
-
this.addPage(options);
|
|
5836
|
+
this.addPage(options ?? this.page._options);
|
|
5639
5837
|
this.initPageMarkings(pageMarkings);
|
|
5640
5838
|
return this;
|
|
5641
5839
|
}
|
|
@@ -5653,8 +5851,6 @@ class PDFDocument extends stream.Readable {
|
|
|
5653
5851
|
return this.page = page;
|
|
5654
5852
|
}
|
|
5655
5853
|
flushPages() {
|
|
5656
|
-
// this local variable exists so we're future-proof against
|
|
5657
|
-
// reentrant calls to flushPages.
|
|
5658
5854
|
const pages = this._pageBuffer;
|
|
5659
5855
|
this._pageBuffer = [];
|
|
5660
5856
|
this._pageBufferStart += pages.length;
|
|
@@ -5675,13 +5871,10 @@ class PDFDocument extends stream.Readable {
|
|
|
5675
5871
|
}
|
|
5676
5872
|
addNamedEmbeddedFile(name, ref) {
|
|
5677
5873
|
if (!this._root.data.Names.data.EmbeddedFiles) {
|
|
5678
|
-
// disabling /Limits for this tree fixes attachments not showing in Adobe Reader
|
|
5679
5874
|
this._root.data.Names.data.EmbeddedFiles = new PDFNameTree({
|
|
5680
5875
|
limits: false
|
|
5681
5876
|
});
|
|
5682
5877
|
}
|
|
5683
|
-
|
|
5684
|
-
// add filespec to EmbeddedFiles
|
|
5685
5878
|
this._root.data.Names.data.EmbeddedFiles.add(name, ref);
|
|
5686
5879
|
}
|
|
5687
5880
|
addNamedJavaScript(name, js) {
|
|
@@ -5696,19 +5889,17 @@ class PDFDocument extends stream.Readable {
|
|
|
5696
5889
|
}
|
|
5697
5890
|
ref(data) {
|
|
5698
5891
|
const ref = new PDFReference(this, this._offsets.length + 1, data);
|
|
5699
|
-
this._offsets.push(null);
|
|
5892
|
+
this._offsets.push(null);
|
|
5700
5893
|
this._waiting++;
|
|
5701
5894
|
return ref;
|
|
5702
5895
|
}
|
|
5703
5896
|
_read() {}
|
|
5704
|
-
// do nothing, but this method is required by node
|
|
5705
|
-
|
|
5706
5897
|
_write(data) {
|
|
5707
5898
|
if (!Buffer.isBuffer(data)) {
|
|
5708
5899
|
data = Buffer.from(data + '\n', 'binary');
|
|
5709
5900
|
}
|
|
5710
5901
|
this.push(data);
|
|
5711
|
-
|
|
5902
|
+
this._offset += data.length;
|
|
5712
5903
|
}
|
|
5713
5904
|
addContent(data) {
|
|
5714
5905
|
this.page.write(data);
|
|
@@ -5718,7 +5909,7 @@ class PDFDocument extends stream.Readable {
|
|
|
5718
5909
|
this._offsets[ref.id - 1] = ref.offset;
|
|
5719
5910
|
if (--this._waiting === 0 && this._ended) {
|
|
5720
5911
|
this._finalize();
|
|
5721
|
-
|
|
5912
|
+
this._ended = false;
|
|
5722
5913
|
}
|
|
5723
5914
|
}
|
|
5724
5915
|
end() {
|
|
@@ -5755,13 +5946,12 @@ class PDFDocument extends stream.Readable {
|
|
|
5755
5946
|
this._security.end();
|
|
5756
5947
|
}
|
|
5757
5948
|
if (this._waiting === 0) {
|
|
5758
|
-
|
|
5949
|
+
this._finalize();
|
|
5759
5950
|
} else {
|
|
5760
|
-
|
|
5951
|
+
this._ended = true;
|
|
5761
5952
|
}
|
|
5762
5953
|
}
|
|
5763
5954
|
_finalize() {
|
|
5764
|
-
// generate xref
|
|
5765
5955
|
const xRefOffset = this._offset;
|
|
5766
5956
|
this._write('xref');
|
|
5767
5957
|
this._write(`0 ${this._offsets.length + 1}`);
|
|
@@ -5770,8 +5960,6 @@ class PDFDocument extends stream.Readable {
|
|
|
5770
5960
|
offset = `0000000000${offset}`.slice(-10);
|
|
5771
5961
|
this._write(offset + ' 00000 n ');
|
|
5772
5962
|
}
|
|
5773
|
-
|
|
5774
|
-
// trailer
|
|
5775
5963
|
const trailer = {
|
|
5776
5964
|
Size: this._offsets.length + 1,
|
|
5777
5965
|
Root: this._root,
|
|
@@ -5786,9 +5974,7 @@ class PDFDocument extends stream.Readable {
|
|
|
5786
5974
|
this._write('startxref');
|
|
5787
5975
|
this._write(`${xRefOffset}`);
|
|
5788
5976
|
this._write('%%EOF');
|
|
5789
|
-
|
|
5790
|
-
// end the stream
|
|
5791
|
-
return this.push(null);
|
|
5977
|
+
this.push(null);
|
|
5792
5978
|
}
|
|
5793
5979
|
toString() {
|
|
5794
5980
|
return '[object PDFDocument]';
|
|
@@ -5809,6 +5995,7 @@ mixin(MarkingsMixin);
|
|
|
5809
5995
|
mixin(AcroFormMixin);
|
|
5810
5996
|
mixin(AttachmentsMixin);
|
|
5811
5997
|
mixin(SubsetMixin);
|
|
5998
|
+
mixin(TableMixin);
|
|
5812
5999
|
PDFDocument.LineWrapper = LineWrapper;
|
|
5813
6000
|
|
|
5814
6001
|
module.exports = PDFDocument;
|