UNPKG

223 kBJavaScriptView Raw
1import stream from 'stream';
2import fs from 'fs';
3import zlib from 'zlib';
4import CryptoJS from 'crypto-js';
5import fontkit from 'fontkit';
6import { EventEmitter } from 'events';
7import LineBreaker from 'linebreak';
8import exif from 'jpeg-exif';
9import PNG from 'png-js';
10
11function _classCallCheck(instance, Constructor) {
12 if (!(instance instanceof Constructor)) {
13 throw new TypeError("Cannot call a class as a function");
14 }
15}
16
17function _defineProperties(target, props) {
18 for (var i = 0; i < props.length; i++) {
19 var descriptor = props[i];
20 descriptor.enumerable = descriptor.enumerable || false;
21 descriptor.configurable = true;
22 if ("value" in descriptor) descriptor.writable = true;
23 Object.defineProperty(target, descriptor.key, descriptor);
24 }
25}
26
27function _createClass(Constructor, protoProps, staticProps) {
28 if (protoProps) _defineProperties(Constructor.prototype, protoProps);
29 if (staticProps) _defineProperties(Constructor, staticProps);
30 return Constructor;
31}
32
33function _defineProperty(obj, key, value) {
34 if (key in obj) {
35 Object.defineProperty(obj, key, {
36 value: value,
37 enumerable: true,
38 configurable: true,
39 writable: true
40 });
41 } else {
42 obj[key] = value;
43 }
44
45 return obj;
46}
47
48function ownKeys(object, enumerableOnly) {
49 var keys = Object.keys(object);
50
51 if (Object.getOwnPropertySymbols) {
52 var symbols = Object.getOwnPropertySymbols(object);
53 if (enumerableOnly) symbols = symbols.filter(function (sym) {
54 return Object.getOwnPropertyDescriptor(object, sym).enumerable;
55 });
56 keys.push.apply(keys, symbols);
57 }
58
59 return keys;
60}
61
62function _objectSpread2(target) {
63 for (var i = 1; i < arguments.length; i++) {
64 var source = arguments[i] != null ? arguments[i] : {};
65
66 if (i % 2) {
67 ownKeys(Object(source), true).forEach(function (key) {
68 _defineProperty(target, key, source[key]);
69 });
70 } else if (Object.getOwnPropertyDescriptors) {
71 Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
72 } else {
73 ownKeys(Object(source)).forEach(function (key) {
74 Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
75 });
76 }
77 }
78
79 return target;
80}
81
82function _inherits(subClass, superClass) {
83 if (typeof superClass !== "function" && superClass !== null) {
84 throw new TypeError("Super expression must either be null or a function");
85 }
86
87 subClass.prototype = Object.create(superClass && superClass.prototype, {
88 constructor: {
89 value: subClass,
90 writable: true,
91 configurable: true
92 }
93 });
94 if (superClass) _setPrototypeOf(subClass, superClass);
95}
96
97function _getPrototypeOf(o) {
98 _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
99 return o.__proto__ || Object.getPrototypeOf(o);
100 };
101 return _getPrototypeOf(o);
102}
103
104function _setPrototypeOf(o, p) {
105 _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
106 o.__proto__ = p;
107 return o;
108 };
109
110 return _setPrototypeOf(o, p);
111}
112
113function _isNativeReflectConstruct() {
114 if (typeof Reflect === "undefined" || !Reflect.construct) return false;
115 if (Reflect.construct.sham) return false;
116 if (typeof Proxy === "function") return true;
117
118 try {
119 Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
120 return true;
121 } catch (e) {
122 return false;
123 }
124}
125
126function _assertThisInitialized(self) {
127 if (self === void 0) {
128 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
129 }
130
131 return self;
132}
133
134function _possibleConstructorReturn(self, call) {
135 if (call && (typeof call === "object" || typeof call === "function")) {
136 return call;
137 }
138
139 return _assertThisInitialized(self);
140}
141
142function _createSuper(Derived) {
143 var hasNativeReflectConstruct = _isNativeReflectConstruct();
144
145 return function _createSuperInternal() {
146 var Super = _getPrototypeOf(Derived),
147 result;
148
149 if (hasNativeReflectConstruct) {
150 var NewTarget = _getPrototypeOf(this).constructor;
151
152 result = Reflect.construct(Super, arguments, NewTarget);
153 } else {
154 result = Super.apply(this, arguments);
155 }
156
157 return _possibleConstructorReturn(this, result);
158 };
159}
160
161function _slicedToArray(arr, i) {
162 return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
163}
164
165function _toConsumableArray(arr) {
166 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
167}
168
169function _arrayWithoutHoles(arr) {
170 if (Array.isArray(arr)) return _arrayLikeToArray(arr);
171}
172
173function _arrayWithHoles(arr) {
174 if (Array.isArray(arr)) return arr;
175}
176
177function _iterableToArray(iter) {
178 if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
179}
180
181function _iterableToArrayLimit(arr, i) {
182 if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
183 var _arr = [];
184 var _n = true;
185 var _d = false;
186 var _e = undefined;
187
188 try {
189 for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
190 _arr.push(_s.value);
191
192 if (i && _arr.length === i) break;
193 }
194 } catch (err) {
195 _d = true;
196 _e = err;
197 } finally {
198 try {
199 if (!_n && _i["return"] != null) _i["return"]();
200 } finally {
201 if (_d) throw _e;
202 }
203 }
204
205 return _arr;
206}
207
208function _unsupportedIterableToArray(o, minLen) {
209 if (!o) return;
210 if (typeof o === "string") return _arrayLikeToArray(o, minLen);
211 var n = Object.prototype.toString.call(o).slice(8, -1);
212 if (n === "Object" && o.constructor) n = o.constructor.name;
213 if (n === "Map" || n === "Set") return Array.from(o);
214 if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
215}
216
217function _arrayLikeToArray(arr, len) {
218 if (len == null || len > arr.length) len = arr.length;
219
220 for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
221
222 return arr2;
223}
224
225function _nonIterableSpread() {
226 throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
227}
228
229function _nonIterableRest() {
230 throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
231}
232
233function _createForOfIteratorHelper(o, allowArrayLike) {
234 var it;
235
236 if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
237 if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
238 if (it) o = it;
239 var i = 0;
240
241 var F = function () {};
242
243 return {
244 s: F,
245 n: function () {
246 if (i >= o.length) return {
247 done: true
248 };
249 return {
250 done: false,
251 value: o[i++]
252 };
253 },
254 e: function (e) {
255 throw e;
256 },
257 f: F
258 };
259 }
260
261 throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
262 }
263
264 var normalCompletion = true,
265 didErr = false,
266 err;
267 return {
268 s: function () {
269 it = o[Symbol.iterator]();
270 },
271 n: function () {
272 var step = it.next();
273 normalCompletion = step.done;
274 return step;
275 },
276 e: function (e) {
277 didErr = true;
278 err = e;
279 },
280 f: function () {
281 try {
282 if (!normalCompletion && it.return != null) it.return();
283 } finally {
284 if (didErr) throw err;
285 }
286 }
287 };
288}
289
290/*
291PDFAbstractReference - abstract class for PDF reference
292*/
293var PDFAbstractReference = /*#__PURE__*/function () {
294 function PDFAbstractReference() {
295 _classCallCheck(this, PDFAbstractReference);
296 }
297
298 _createClass(PDFAbstractReference, [{
299 key: "toString",
300 value: function toString() {
301 throw new Error('Must be implemented by subclasses');
302 }
303 }]);
304
305 return PDFAbstractReference;
306}();
307
308var PDFTree = /*#__PURE__*/function () {
309 function PDFTree() {
310 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
311
312 _classCallCheck(this, PDFTree);
313
314 this._items = {}; // disable /Limits output for this tree
315
316 this.limits = typeof options.limits === 'boolean' ? options.limits : true;
317 }
318
319 _createClass(PDFTree, [{
320 key: "add",
321 value: function add(key, val) {
322 return this._items[key] = val;
323 }
324 }, {
325 key: "get",
326 value: function get(key) {
327 return this._items[key];
328 }
329 }, {
330 key: "toString",
331 value: function toString() {
332 var _this = this;
333
334 // Needs to be sorted by key
335 var sortedKeys = Object.keys(this._items).sort(function (a, b) {
336 return _this._compareKeys(a, b);
337 });
338 var out = ['<<'];
339
340 if (this.limits && sortedKeys.length > 1) {
341 var first = sortedKeys[0],
342 last = sortedKeys[sortedKeys.length - 1];
343 out.push(" /Limits ".concat(PDFObject.convert([this._dataForKey(first), this._dataForKey(last)])));
344 }
345
346 out.push(" /".concat(this._keysName(), " ["));
347
348 var _iterator = _createForOfIteratorHelper(sortedKeys),
349 _step;
350
351 try {
352 for (_iterator.s(); !(_step = _iterator.n()).done;) {
353 var key = _step.value;
354 out.push(" ".concat(PDFObject.convert(this._dataForKey(key)), " ").concat(PDFObject.convert(this._items[key])));
355 }
356 } catch (err) {
357 _iterator.e(err);
358 } finally {
359 _iterator.f();
360 }
361
362 out.push(']');
363 out.push('>>');
364 return out.join('\n');
365 }
366 }, {
367 key: "_compareKeys",
368 value: function _compareKeys()
369 /*a, b*/
370 {
371 throw new Error('Must be implemented by subclasses');
372 }
373 }, {
374 key: "_keysName",
375 value: function _keysName() {
376 throw new Error('Must be implemented by subclasses');
377 }
378 }, {
379 key: "_dataForKey",
380 value: function _dataForKey()
381 /*k*/
382 {
383 throw new Error('Must be implemented by subclasses');
384 }
385 }]);
386
387 return PDFTree;
388}();
389
390var pad = function pad(str, length) {
391 return (Array(length + 1).join('0') + str).slice(-length);
392};
393
394var escapableRe = /[\n\r\t\b\f()\\]/g;
395var escapable = {
396 '\n': '\\n',
397 '\r': '\\r',
398 '\t': '\\t',
399 '\b': '\\b',
400 '\f': '\\f',
401 '\\': '\\\\',
402 '(': '\\(',
403 ')': '\\)'
404}; // Convert little endian UTF-16 to big endian
405
406var swapBytes = function swapBytes(buff) {
407 var l = buff.length;
408
409 if (l & 0x01) {
410 throw new Error('Buffer length must be even');
411 } else {
412 for (var i = 0, end = l - 1; i < end; i += 2) {
413 var a = buff[i];
414 buff[i] = buff[i + 1];
415 buff[i + 1] = a;
416 }
417 }
418
419 return buff;
420};
421
422var PDFObject = /*#__PURE__*/function () {
423 function PDFObject() {
424 _classCallCheck(this, PDFObject);
425 }
426
427 _createClass(PDFObject, null, [{
428 key: "convert",
429 value: function convert(object) {
430 var encryptFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
431
432 // String literals are converted to the PDF name type
433 if (typeof object === 'string') {
434 return "/".concat(object); // String objects are converted to PDF strings (UTF-16)
435 } else if (object instanceof String) {
436 var string = object; // Detect if this is a unicode string
437
438 var isUnicode = false;
439
440 for (var i = 0, end = string.length; i < end; i++) {
441 if (string.charCodeAt(i) > 0x7f) {
442 isUnicode = true;
443 break;
444 }
445 } // If so, encode it as big endian UTF-16
446
447
448 var stringBuffer;
449
450 if (isUnicode) {
451 stringBuffer = swapBytes(Buffer.from("\uFEFF".concat(string), 'utf16le'));
452 } else {
453 stringBuffer = Buffer.from(string.valueOf(), 'ascii');
454 } // Encrypt the string when necessary
455
456
457 if (encryptFn) {
458 string = encryptFn(stringBuffer).toString('binary');
459 } else {
460 string = stringBuffer.toString('binary');
461 } // Escape characters as required by the spec
462
463
464 string = string.replace(escapableRe, function (c) {
465 return escapable[c];
466 });
467 return "(".concat(string, ")"); // Buffers are converted to PDF hex strings
468 } else if (Buffer.isBuffer(object)) {
469 return "<".concat(object.toString('hex'), ">");
470 } else if (object instanceof PDFAbstractReference || object instanceof PDFTree) {
471 return object.toString();
472 } else if (object instanceof Date) {
473 var _string = "D:".concat(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'; // Encrypt the string when necessary
474
475
476 if (encryptFn) {
477 _string = encryptFn(Buffer.from(_string, 'ascii')).toString('binary'); // Escape characters as required by the spec
478
479 _string = _string.replace(escapableRe, function (c) {
480 return escapable[c];
481 });
482 }
483
484 return "(".concat(_string, ")");
485 } else if (Array.isArray(object)) {
486 var items = object.map(function (e) {
487 return PDFObject.convert(e, encryptFn);
488 }).join(' ');
489 return "[".concat(items, "]");
490 } else if ({}.toString.call(object) === '[object Object]') {
491 var out = ['<<'];
492
493 for (var key in object) {
494 var val = object[key];
495 out.push("/".concat(key, " ").concat(PDFObject.convert(val, encryptFn)));
496 }
497
498 out.push('>>');
499 return out.join('\n');
500 } else if (typeof object === 'number') {
501 return PDFObject.number(object);
502 } else {
503 return "".concat(object);
504 }
505 }
506 }, {
507 key: "number",
508 value: function number(n) {
509 if (n > -1e21 && n < 1e21) {
510 return Math.round(n * 1e6) / 1e6;
511 }
512
513 throw new Error("unsupported number: ".concat(n));
514 }
515 }]);
516
517 return PDFObject;
518}();
519
520var PDFReference = /*#__PURE__*/function (_PDFAbstractReference) {
521 _inherits(PDFReference, _PDFAbstractReference);
522
523 var _super = _createSuper(PDFReference);
524
525 function PDFReference(document, id) {
526 var _this;
527
528 var data = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
529
530 _classCallCheck(this, PDFReference);
531
532 _this = _super.call(this);
533 _this.document = document;
534 _this.id = id;
535 _this.data = data;
536 _this.gen = 0;
537 _this.compress = _this.document.compress && !_this.data.Filter;
538 _this.uncompressedLength = 0;
539 _this.buffer = [];
540 return _this;
541 }
542
543 _createClass(PDFReference, [{
544 key: "write",
545 value: function write(chunk) {
546 if (!Buffer.isBuffer(chunk)) {
547 chunk = Buffer.from(chunk + '\n', 'binary');
548 }
549
550 this.uncompressedLength += chunk.length;
551
552 if (this.data.Length == null) {
553 this.data.Length = 0;
554 }
555
556 this.buffer.push(chunk);
557 this.data.Length += chunk.length;
558
559 if (this.compress) {
560 return this.data.Filter = 'FlateDecode';
561 }
562 }
563 }, {
564 key: "end",
565 value: function end(chunk) {
566 if (chunk) {
567 this.write(chunk);
568 }
569
570 return this.finalize();
571 }
572 }, {
573 key: "finalize",
574 value: function finalize() {
575 this.offset = this.document._offset;
576 var encryptFn = this.document._security ? this.document._security.getEncryptFn(this.id, this.gen) : null;
577
578 if (this.buffer.length) {
579 this.buffer = Buffer.concat(this.buffer);
580
581 if (this.compress) {
582 this.buffer = zlib.deflateSync(this.buffer);
583 }
584
585 if (encryptFn) {
586 this.buffer = encryptFn(this.buffer);
587 }
588
589 this.data.Length = this.buffer.length;
590 }
591
592 this.document._write("".concat(this.id, " ").concat(this.gen, " obj"));
593
594 this.document._write(PDFObject.convert(this.data, encryptFn));
595
596 if (this.buffer.length) {
597 this.document._write('stream');
598
599 this.document._write(this.buffer);
600
601 this.buffer = []; // free up memory
602
603 this.document._write('\nendstream');
604 }
605
606 this.document._write('endobj');
607
608 this.document._refEnd(this);
609 }
610 }, {
611 key: "toString",
612 value: function toString() {
613 return "".concat(this.id, " ").concat(this.gen, " R");
614 }
615 }]);
616
617 return PDFReference;
618}(PDFAbstractReference);
619
620/*
621PDFPage - represents a single page in the PDF document
622By Devon Govett
623*/
624var DEFAULT_MARGINS = {
625 top: 72,
626 left: 72,
627 bottom: 72,
628 right: 72
629};
630var SIZES = {
631 '4A0': [4767.87, 6740.79],
632 '2A0': [3370.39, 4767.87],
633 A0: [2383.94, 3370.39],
634 A1: [1683.78, 2383.94],
635 A2: [1190.55, 1683.78],
636 A3: [841.89, 1190.55],
637 A4: [595.28, 841.89],
638 A5: [419.53, 595.28],
639 A6: [297.64, 419.53],
640 A7: [209.76, 297.64],
641 A8: [147.4, 209.76],
642 A9: [104.88, 147.4],
643 A10: [73.7, 104.88],
644 B0: [2834.65, 4008.19],
645 B1: [2004.09, 2834.65],
646 B2: [1417.32, 2004.09],
647 B3: [1000.63, 1417.32],
648 B4: [708.66, 1000.63],
649 B5: [498.9, 708.66],
650 B6: [354.33, 498.9],
651 B7: [249.45, 354.33],
652 B8: [175.75, 249.45],
653 B9: [124.72, 175.75],
654 B10: [87.87, 124.72],
655 C0: [2599.37, 3676.54],
656 C1: [1836.85, 2599.37],
657 C2: [1298.27, 1836.85],
658 C3: [918.43, 1298.27],
659 C4: [649.13, 918.43],
660 C5: [459.21, 649.13],
661 C6: [323.15, 459.21],
662 C7: [229.61, 323.15],
663 C8: [161.57, 229.61],
664 C9: [113.39, 161.57],
665 C10: [79.37, 113.39],
666 RA0: [2437.8, 3458.27],
667 RA1: [1729.13, 2437.8],
668 RA2: [1218.9, 1729.13],
669 RA3: [864.57, 1218.9],
670 RA4: [609.45, 864.57],
671 SRA0: [2551.18, 3628.35],
672 SRA1: [1814.17, 2551.18],
673 SRA2: [1275.59, 1814.17],
674 SRA3: [907.09, 1275.59],
675 SRA4: [637.8, 907.09],
676 EXECUTIVE: [521.86, 756.0],
677 FOLIO: [612.0, 936.0],
678 LEGAL: [612.0, 1008.0],
679 LETTER: [612.0, 792.0],
680 TABLOID: [792.0, 1224.0]
681};
682
683var PDFPage = /*#__PURE__*/function () {
684 function PDFPage(document) {
685 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
686
687 _classCallCheck(this, PDFPage);
688
689 this.document = document;
690 this.size = options.size || 'letter';
691 this.layout = options.layout || 'portrait'; // process margins
692
693 if (typeof options.margin === 'number') {
694 this.margins = {
695 top: options.margin,
696 left: options.margin,
697 bottom: options.margin,
698 right: options.margin
699 }; // default to 1 inch margins
700 } else {
701 this.margins = options.margins || DEFAULT_MARGINS;
702 } // calculate page dimensions
703
704
705 var dimensions = Array.isArray(this.size) ? this.size : SIZES[this.size.toUpperCase()];
706 this.width = dimensions[this.layout === 'portrait' ? 0 : 1];
707 this.height = dimensions[this.layout === 'portrait' ? 1 : 0];
708 this.content = this.document.ref(); // Initialize the Font, XObject, and ExtGState dictionaries
709
710 this.resources = this.document.ref({
711 ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI']
712 }); // The page dictionary
713
714 this.dictionary = this.document.ref({
715 Type: 'Page',
716 Parent: this.document._root.data.Pages,
717 MediaBox: [0, 0, this.width, this.height],
718 Contents: this.content,
719 Resources: this.resources
720 });
721 this.markings = [];
722 } // Lazily create these objects
723
724
725 _createClass(PDFPage, [{
726 key: "maxY",
727 value: function maxY() {
728 return this.height - this.margins.bottom;
729 }
730 }, {
731 key: "write",
732 value: function write(chunk) {
733 return this.content.write(chunk);
734 }
735 }, {
736 key: "end",
737 value: function end() {
738 this.dictionary.end();
739 this.resources.end();
740 return this.content.end();
741 }
742 }, {
743 key: "fonts",
744 get: function get() {
745 var data = this.resources.data;
746 return data.Font != null ? data.Font : data.Font = {};
747 }
748 }, {
749 key: "xobjects",
750 get: function get() {
751 var data = this.resources.data;
752 return data.XObject != null ? data.XObject : data.XObject = {};
753 }
754 }, {
755 key: "ext_gstates",
756 get: function get() {
757 var data = this.resources.data;
758 return data.ExtGState != null ? data.ExtGState : data.ExtGState = {};
759 }
760 }, {
761 key: "patterns",
762 get: function get() {
763 var data = this.resources.data;
764 return data.Pattern != null ? data.Pattern : data.Pattern = {};
765 }
766 }, {
767 key: "colorSpaces",
768 get: function get() {
769 var data = this.resources.data;
770 return data.ColorSpace || (data.ColorSpace = {});
771 }
772 }, {
773 key: "annotations",
774 get: function get() {
775 var data = this.dictionary.data;
776 return data.Annots != null ? data.Annots : data.Annots = [];
777 }
778 }, {
779 key: "structParentTreeKey",
780 get: function get() {
781 var data = this.dictionary.data;
782 return data.StructParents != null ? data.StructParents : data.StructParents = this.document.createStructParentTreeNextKey();
783 }
784 }]);
785
786 return PDFPage;
787}();
788
789var PDFNameTree = /*#__PURE__*/function (_PDFTree) {
790 _inherits(PDFNameTree, _PDFTree);
791
792 var _super = _createSuper(PDFNameTree);
793
794 function PDFNameTree() {
795 _classCallCheck(this, PDFNameTree);
796
797 return _super.apply(this, arguments);
798 }
799
800 _createClass(PDFNameTree, [{
801 key: "_compareKeys",
802 value: function _compareKeys(a, b) {
803 return a.localeCompare(b);
804 }
805 }, {
806 key: "_keysName",
807 value: function _keysName() {
808 return "Names";
809 }
810 }, {
811 key: "_dataForKey",
812 value: function _dataForKey(k) {
813 return new String(k);
814 }
815 }]);
816
817 return PDFNameTree;
818}(PDFTree);
819
820/**
821 * Check if value is in a range group.
822 * @param {number} value
823 * @param {number[]} rangeGroup
824 * @returns {boolean}
825 */
826function inRange(value, rangeGroup) {
827 if (value < rangeGroup[0]) return false;
828 var startRange = 0;
829 var endRange = rangeGroup.length / 2;
830
831 while (startRange <= endRange) {
832 var middleRange = Math.floor((startRange + endRange) / 2); // actual array index
833
834 var arrayIndex = middleRange * 2; // Check if value is in range pointed by actual index
835
836 if (value >= rangeGroup[arrayIndex] && value <= rangeGroup[arrayIndex + 1]) {
837 return true;
838 }
839
840 if (value > rangeGroup[arrayIndex + 1]) {
841 // Search Right Side Of Array
842 startRange = middleRange + 1;
843 } else {
844 // Search Left Side Of Array
845 endRange = middleRange - 1;
846 }
847 }
848
849 return false;
850}
851
852/**
853 * A.1 Unassigned code points in Unicode 3.2
854 * @link https://tools.ietf.org/html/rfc3454#appendix-A.1
855 */
856
857var 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]; // prettier-ignore-end
858
859var isUnassignedCodePoint = function isUnassignedCodePoint(character) {
860 return inRange(character, unassigned_code_points);
861}; // prettier-ignore-start
862
863/**
864 * B.1 Commonly mapped to nothing
865 * @link https://tools.ietf.org/html/rfc3454#appendix-B.1
866 */
867
868
869var 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]; // prettier-ignore-end
870
871var isCommonlyMappedToNothing = function isCommonlyMappedToNothing(character) {
872 return inRange(character, commonly_mapped_to_nothing);
873}; // prettier-ignore-start
874
875/**
876 * C.1.2 Non-ASCII space characters
877 * @link https://tools.ietf.org/html/rfc3454#appendix-C.1.2
878 */
879
880
881var non_ASCII_space_characters = [0x00a0, 0x00a0
882/* NO-BREAK SPACE */
883, 0x1680, 0x1680
884/* OGHAM SPACE MARK */
885, 0x2000, 0x2000
886/* EN QUAD */
887, 0x2001, 0x2001
888/* EM QUAD */
889, 0x2002, 0x2002
890/* EN SPACE */
891, 0x2003, 0x2003
892/* EM SPACE */
893, 0x2004, 0x2004
894/* THREE-PER-EM SPACE */
895, 0x2005, 0x2005
896/* FOUR-PER-EM SPACE */
897, 0x2006, 0x2006
898/* SIX-PER-EM SPACE */
899, 0x2007, 0x2007
900/* FIGURE SPACE */
901, 0x2008, 0x2008
902/* PUNCTUATION SPACE */
903, 0x2009, 0x2009
904/* THIN SPACE */
905, 0x200a, 0x200a
906/* HAIR SPACE */
907, 0x200b, 0x200b
908/* ZERO WIDTH SPACE */
909, 0x202f, 0x202f
910/* NARROW NO-BREAK SPACE */
911, 0x205f, 0x205f
912/* MEDIUM MATHEMATICAL SPACE */
913, 0x3000, 0x3000
914/* IDEOGRAPHIC SPACE */
915]; // prettier-ignore-end
916
917var isNonASCIISpaceCharacter = function isNonASCIISpaceCharacter(character) {
918 return inRange(character, non_ASCII_space_characters);
919}; // prettier-ignore-start
920
921
922var non_ASCII_controls_characters = [
923/**
924 * C.2.2 Non-ASCII control characters
925 * @link https://tools.ietf.org/html/rfc3454#appendix-C.2.2
926 */
9270x0080, 0x009f
928/* [CONTROL CHARACTERS] */
929, 0x06dd, 0x06dd
930/* ARABIC END OF AYAH */
931, 0x070f, 0x070f
932/* SYRIAC ABBREVIATION MARK */
933, 0x180e, 0x180e
934/* MONGOLIAN VOWEL SEPARATOR */
935, 0x200c, 0x200c
936/* ZERO WIDTH NON-JOINER */
937, 0x200d, 0x200d
938/* ZERO WIDTH JOINER */
939, 0x2028, 0x2028
940/* LINE SEPARATOR */
941, 0x2029, 0x2029
942/* PARAGRAPH SEPARATOR */
943, 0x2060, 0x2060
944/* WORD JOINER */
945, 0x2061, 0x2061
946/* FUNCTION APPLICATION */
947, 0x2062, 0x2062
948/* INVISIBLE TIMES */
949, 0x2063, 0x2063
950/* INVISIBLE SEPARATOR */
951, 0x206a, 0x206f
952/* [CONTROL CHARACTERS] */
953, 0xfeff, 0xfeff
954/* ZERO WIDTH NO-BREAK SPACE */
955, 0xfff9, 0xfffc
956/* [CONTROL CHARACTERS] */
957, 0x1d173, 0x1d17a
958/* [MUSICAL CONTROL CHARACTERS] */
959];
960var non_character_codepoints = [
961/**
962 * C.4 Non-character code points
963 * @link https://tools.ietf.org/html/rfc3454#appendix-C.4
964 */
9650xfdd0, 0xfdef
966/* [NONCHARACTER CODE POINTS] */
967, 0xfffe, 0xffff
968/* [NONCHARACTER CODE POINTS] */
969, 0x1fffe, 0x1ffff
970/* [NONCHARACTER CODE POINTS] */
971, 0x2fffe, 0x2ffff
972/* [NONCHARACTER CODE POINTS] */
973, 0x3fffe, 0x3ffff
974/* [NONCHARACTER CODE POINTS] */
975, 0x4fffe, 0x4ffff
976/* [NONCHARACTER CODE POINTS] */
977, 0x5fffe, 0x5ffff
978/* [NONCHARACTER CODE POINTS] */
979, 0x6fffe, 0x6ffff
980/* [NONCHARACTER CODE POINTS] */
981, 0x7fffe, 0x7ffff
982/* [NONCHARACTER CODE POINTS] */
983, 0x8fffe, 0x8ffff
984/* [NONCHARACTER CODE POINTS] */
985, 0x9fffe, 0x9ffff
986/* [NONCHARACTER CODE POINTS] */
987, 0xafffe, 0xaffff
988/* [NONCHARACTER CODE POINTS] */
989, 0xbfffe, 0xbffff
990/* [NONCHARACTER CODE POINTS] */
991, 0xcfffe, 0xcffff
992/* [NONCHARACTER CODE POINTS] */
993, 0xdfffe, 0xdffff
994/* [NONCHARACTER CODE POINTS] */
995, 0xefffe, 0xeffff
996/* [NONCHARACTER CODE POINTS] */
997, 0x10fffe, 0x10ffff
998/* [NONCHARACTER CODE POINTS] */
999];
1000/**
1001 * 2.3. Prohibited Output
1002 */
1003
1004var prohibited_characters = [
1005/**
1006 * C.2.1 ASCII control characters
1007 * @link https://tools.ietf.org/html/rfc3454#appendix-C.2.1
1008 */
10090, 0x001f
1010/* [CONTROL CHARACTERS] */
1011, 0x007f, 0x007f
1012/* DELETE */
1013,
1014/**
1015 * C.8 Change display properties or are deprecated
1016 * @link https://tools.ietf.org/html/rfc3454#appendix-C.8
1017 */
10180x0340, 0x0340
1019/* COMBINING GRAVE TONE MARK */
1020, 0x0341, 0x0341
1021/* COMBINING ACUTE TONE MARK */
1022, 0x200e, 0x200e
1023/* LEFT-TO-RIGHT MARK */
1024, 0x200f, 0x200f
1025/* RIGHT-TO-LEFT MARK */
1026, 0x202a, 0x202a
1027/* LEFT-TO-RIGHT EMBEDDING */
1028, 0x202b, 0x202b
1029/* RIGHT-TO-LEFT EMBEDDING */
1030, 0x202c, 0x202c
1031/* POP DIRECTIONAL FORMATTING */
1032, 0x202d, 0x202d
1033/* LEFT-TO-RIGHT OVERRIDE */
1034, 0x202e, 0x202e
1035/* RIGHT-TO-LEFT OVERRIDE */
1036, 0x206a, 0x206a
1037/* INHIBIT SYMMETRIC SWAPPING */
1038, 0x206b, 0x206b
1039/* ACTIVATE SYMMETRIC SWAPPING */
1040, 0x206c, 0x206c
1041/* INHIBIT ARABIC FORM SHAPING */
1042, 0x206d, 0x206d
1043/* ACTIVATE ARABIC FORM SHAPING */
1044, 0x206e, 0x206e
1045/* NATIONAL DIGIT SHAPES */
1046, 0x206f, 0x206f
1047/* NOMINAL DIGIT SHAPES */
1048,
1049/**
1050 * C.7 Inappropriate for canonical representation
1051 * @link https://tools.ietf.org/html/rfc3454#appendix-C.7
1052 */
10530x2ff0, 0x2ffb
1054/* [IDEOGRAPHIC DESCRIPTION CHARACTERS] */
1055,
1056/**
1057 * C.5 Surrogate codes
1058 * @link https://tools.ietf.org/html/rfc3454#appendix-C.5
1059 */
10600xd800, 0xdfff,
1061/**
1062 * C.3 Private use
1063 * @link https://tools.ietf.org/html/rfc3454#appendix-C.3
1064 */
10650xe000, 0xf8ff
1066/* [PRIVATE USE, PLANE 0] */
1067,
1068/**
1069 * C.6 Inappropriate for plain text
1070 * @link https://tools.ietf.org/html/rfc3454#appendix-C.6
1071 */
10720xfff9, 0xfff9
1073/* INTERLINEAR ANNOTATION ANCHOR */
1074, 0xfffa, 0xfffa
1075/* INTERLINEAR ANNOTATION SEPARATOR */
1076, 0xfffb, 0xfffb
1077/* INTERLINEAR ANNOTATION TERMINATOR */
1078, 0xfffc, 0xfffc
1079/* OBJECT REPLACEMENT CHARACTER */
1080, 0xfffd, 0xfffd
1081/* REPLACEMENT CHARACTER */
1082,
1083/**
1084 * C.9 Tagging characters
1085 * @link https://tools.ietf.org/html/rfc3454#appendix-C.9
1086 */
10870xe0001, 0xe0001
1088/* LANGUAGE TAG */
1089, 0xe0020, 0xe007f
1090/* [TAGGING CHARACTERS] */
1091,
1092/**
1093 * C.3 Private use
1094 * @link https://tools.ietf.org/html/rfc3454#appendix-C.3
1095 */
10960xf0000, 0xffffd
1097/* [PRIVATE USE, PLANE 15] */
1098, 0x100000, 0x10fffd
1099/* [PRIVATE USE, PLANE 16] */
1100]; // prettier-ignore-end
1101
1102var isProhibitedCharacter = function isProhibitedCharacter(character) {
1103 return inRange(character, non_ASCII_space_characters) || inRange(character, prohibited_characters) || inRange(character, non_ASCII_controls_characters) || inRange(character, non_character_codepoints);
1104}; // prettier-ignore-start
1105
1106/**
1107 * D.1 Characters with bidirectional property "R" or "AL"
1108 * @link https://tools.ietf.org/html/rfc3454#appendix-D.1
1109 */
1110
1111
1112var 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]; // prettier-ignore-end
1113
1114var isBidirectionalRAL = function isBidirectionalRAL(character) {
1115 return inRange(character, bidirectional_r_al);
1116}; // prettier-ignore-start
1117
1118/**
1119 * D.2 Characters with bidirectional property "L"
1120 * @link https://tools.ietf.org/html/rfc3454#appendix-D.2
1121 */
1122
1123
1124var 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]; // prettier-ignore-end
1125
1126var isBidirectionalL = function isBidirectionalL(character) {
1127 return inRange(character, bidirectional_l);
1128};
1129
1130/**
1131 * non-ASCII space characters [StringPrep, C.1.2] that can be
1132 * mapped to SPACE (U+0020)
1133 */
1134
1135var mapping2space = isNonASCIISpaceCharacter;
1136/**
1137 * the "commonly mapped to nothing" characters [StringPrep, B.1]
1138 * that can be mapped to nothing.
1139 */
1140
1141var mapping2nothing = isCommonlyMappedToNothing; // utils
1142
1143var getCodePoint = function getCodePoint(character) {
1144 return character.codePointAt(0);
1145};
1146
1147var first = function first(x) {
1148 return x[0];
1149};
1150
1151var last = function last(x) {
1152 return x[x.length - 1];
1153};
1154/**
1155 * Convert provided string into an array of Unicode Code Points.
1156 * Based on https://stackoverflow.com/a/21409165/1556249
1157 * and https://www.npmjs.com/package/code-point-at.
1158 * @param {string} input
1159 * @returns {number[]}
1160 */
1161
1162
1163function toCodePoints(input) {
1164 var codepoints = [];
1165 var size = input.length;
1166
1167 for (var i = 0; i < size; i += 1) {
1168 var before = input.charCodeAt(i);
1169
1170 if (before >= 0xd800 && before <= 0xdbff && size > i + 1) {
1171 var next = input.charCodeAt(i + 1);
1172
1173 if (next >= 0xdc00 && next <= 0xdfff) {
1174 codepoints.push((before - 0xd800) * 0x400 + next - 0xdc00 + 0x10000);
1175 i += 1;
1176 continue;
1177 }
1178 }
1179
1180 codepoints.push(before);
1181 }
1182
1183 return codepoints;
1184}
1185/**
1186 * SASLprep.
1187 * @param {string} input
1188 * @param {Object} opts
1189 * @param {boolean} opts.allowUnassigned
1190 * @returns {string}
1191 */
1192
1193
1194function saslprep(input) {
1195 var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1196
1197 if (typeof input !== 'string') {
1198 throw new TypeError('Expected string.');
1199 }
1200
1201 if (input.length === 0) {
1202 return '';
1203 } // 1. Map
1204
1205
1206 var mapped_input = toCodePoints(input) // 1.1 mapping to space
1207 .map(function (character) {
1208 return mapping2space(character) ? 0x20 : character;
1209 }) // 1.2 mapping to nothing
1210 .filter(function (character) {
1211 return !mapping2nothing(character);
1212 }); // 2. Normalize
1213
1214 var normalized_input = String.fromCodePoint.apply(null, mapped_input).normalize('NFKC');
1215 var normalized_map = toCodePoints(normalized_input); // 3. Prohibit
1216
1217 var hasProhibited = normalized_map.some(isProhibitedCharacter);
1218
1219 if (hasProhibited) {
1220 throw new Error('Prohibited character, see https://tools.ietf.org/html/rfc4013#section-2.3');
1221 } // Unassigned Code Points
1222
1223
1224 if (opts.allowUnassigned !== true) {
1225 var hasUnassigned = normalized_map.some(isUnassignedCodePoint);
1226
1227 if (hasUnassigned) {
1228 throw new Error('Unassigned code point, see https://tools.ietf.org/html/rfc4013#section-2.5');
1229 }
1230 } // 4. check bidi
1231
1232
1233 var hasBidiRAL = normalized_map.some(isBidirectionalRAL);
1234 var hasBidiL = normalized_map.some(isBidirectionalL); // 4.1 If a string contains any RandALCat character, the string MUST NOT
1235 // contain any LCat character.
1236
1237 if (hasBidiRAL && hasBidiL) {
1238 throw new Error('String must not contain RandALCat and LCat at the same time,' + ' see https://tools.ietf.org/html/rfc3454#section-6');
1239 }
1240 /**
1241 * 4.2 If a string contains any RandALCat character, a RandALCat
1242 * character MUST be the first character of the string, and a
1243 * RandALCat character MUST be the last character of the string.
1244 */
1245
1246
1247 var isFirstBidiRAL = isBidirectionalRAL(getCodePoint(first(normalized_input)));
1248 var isLastBidiRAL = isBidirectionalRAL(getCodePoint(last(normalized_input)));
1249
1250 if (hasBidiRAL && !(isFirstBidiRAL && isLastBidiRAL)) {
1251 throw new Error('Bidirectional RandALCat character must be the first and the last' + ' character of the string, see https://tools.ietf.org/html/rfc3454#section-6');
1252 }
1253
1254 return normalized_input;
1255}
1256
1257var PDFSecurity = /*#__PURE__*/function () {
1258 _createClass(PDFSecurity, null, [{
1259 key: "generateFileID",
1260 value: function generateFileID() {
1261 var info = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1262 var infoStr = "".concat(info.CreationDate.getTime(), "\n");
1263
1264 for (var key in info) {
1265 // eslint-disable-next-line no-prototype-builtins
1266 if (!info.hasOwnProperty(key)) {
1267 continue;
1268 }
1269
1270 infoStr += "".concat(key, ": ").concat(info[key].valueOf(), "\n");
1271 }
1272
1273 return wordArrayToBuffer(CryptoJS.MD5(infoStr));
1274 }
1275 }, {
1276 key: "generateRandomWordArray",
1277 value: function generateRandomWordArray(bytes) {
1278 return CryptoJS.lib.WordArray.random(bytes);
1279 }
1280 }, {
1281 key: "create",
1282 value: function create(document) {
1283 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1284
1285 if (!options.ownerPassword && !options.userPassword) {
1286 return null;
1287 }
1288
1289 return new PDFSecurity(document, options);
1290 }
1291 }]);
1292
1293 function PDFSecurity(document) {
1294 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1295
1296 _classCallCheck(this, PDFSecurity);
1297
1298 if (!options.ownerPassword && !options.userPassword) {
1299 throw new Error('None of owner password and user password is defined.');
1300 }
1301
1302 this.document = document;
1303
1304 this._setupEncryption(options);
1305 }
1306
1307 _createClass(PDFSecurity, [{
1308 key: "_setupEncryption",
1309 value: function _setupEncryption(options) {
1310 switch (options.pdfVersion) {
1311 case '1.4':
1312 case '1.5':
1313 this.version = 2;
1314 break;
1315
1316 case '1.6':
1317 case '1.7':
1318 this.version = 4;
1319 break;
1320
1321 case '1.7ext3':
1322 this.version = 5;
1323 break;
1324
1325 default:
1326 this.version = 1;
1327 break;
1328 }
1329
1330 var encDict = {
1331 Filter: 'Standard'
1332 };
1333
1334 switch (this.version) {
1335 case 1:
1336 case 2:
1337 case 4:
1338 this._setupEncryptionV1V2V4(this.version, encDict, options);
1339
1340 break;
1341
1342 case 5:
1343 this._setupEncryptionV5(encDict, options);
1344
1345 break;
1346 }
1347
1348 this.dictionary = this.document.ref(encDict);
1349 }
1350 }, {
1351 key: "_setupEncryptionV1V2V4",
1352 value: function _setupEncryptionV1V2V4(v, encDict, options) {
1353 var r, permissions;
1354
1355 switch (v) {
1356 case 1:
1357 r = 2;
1358 this.keyBits = 40;
1359 permissions = getPermissionsR2(options.permissions);
1360 break;
1361
1362 case 2:
1363 r = 3;
1364 this.keyBits = 128;
1365 permissions = getPermissionsR3(options.permissions);
1366 break;
1367
1368 case 4:
1369 r = 4;
1370 this.keyBits = 128;
1371 permissions = getPermissionsR3(options.permissions);
1372 break;
1373 }
1374
1375 var paddedUserPassword = processPasswordR2R3R4(options.userPassword);
1376 var paddedOwnerPassword = options.ownerPassword ? processPasswordR2R3R4(options.ownerPassword) : paddedUserPassword;
1377 var ownerPasswordEntry = getOwnerPasswordR2R3R4(r, this.keyBits, paddedUserPassword, paddedOwnerPassword);
1378 this.encryptionKey = getEncryptionKeyR2R3R4(r, this.keyBits, this.document._id, paddedUserPassword, ownerPasswordEntry, permissions);
1379 var userPasswordEntry;
1380
1381 if (r === 2) {
1382 userPasswordEntry = getUserPasswordR2(this.encryptionKey);
1383 } else {
1384 userPasswordEntry = getUserPasswordR3R4(this.document._id, this.encryptionKey);
1385 }
1386
1387 encDict.V = v;
1388
1389 if (v >= 2) {
1390 encDict.Length = this.keyBits;
1391 }
1392
1393 if (v === 4) {
1394 encDict.CF = {
1395 StdCF: {
1396 AuthEvent: 'DocOpen',
1397 CFM: 'AESV2',
1398 Length: this.keyBits / 8
1399 }
1400 };
1401 encDict.StmF = 'StdCF';
1402 encDict.StrF = 'StdCF';
1403 }
1404
1405 encDict.R = r;
1406 encDict.O = wordArrayToBuffer(ownerPasswordEntry);
1407 encDict.U = wordArrayToBuffer(userPasswordEntry);
1408 encDict.P = permissions;
1409 }
1410 }, {
1411 key: "_setupEncryptionV5",
1412 value: function _setupEncryptionV5(encDict, options) {
1413 this.keyBits = 256;
1414 var permissions = getPermissionsR3(options.permissions);
1415 var processedUserPassword = processPasswordR5(options.userPassword);
1416 var processedOwnerPassword = options.ownerPassword ? processPasswordR5(options.ownerPassword) : processedUserPassword;
1417 this.encryptionKey = getEncryptionKeyR5(PDFSecurity.generateRandomWordArray);
1418 var userPasswordEntry = getUserPasswordR5(processedUserPassword, PDFSecurity.generateRandomWordArray);
1419 var userKeySalt = CryptoJS.lib.WordArray.create(userPasswordEntry.words.slice(10, 12), 8);
1420 var userEncryptionKeyEntry = getUserEncryptionKeyR5(processedUserPassword, userKeySalt, this.encryptionKey);
1421 var ownerPasswordEntry = getOwnerPasswordR5(processedOwnerPassword, userPasswordEntry, PDFSecurity.generateRandomWordArray);
1422 var ownerKeySalt = CryptoJS.lib.WordArray.create(ownerPasswordEntry.words.slice(10, 12), 8);
1423 var ownerEncryptionKeyEntry = getOwnerEncryptionKeyR5(processedOwnerPassword, ownerKeySalt, userPasswordEntry, this.encryptionKey);
1424 var permsEntry = getEncryptedPermissionsR5(permissions, this.encryptionKey, PDFSecurity.generateRandomWordArray);
1425 encDict.V = 5;
1426 encDict.Length = this.keyBits;
1427 encDict.CF = {
1428 StdCF: {
1429 AuthEvent: 'DocOpen',
1430 CFM: 'AESV3',
1431 Length: this.keyBits / 8
1432 }
1433 };
1434 encDict.StmF = 'StdCF';
1435 encDict.StrF = 'StdCF';
1436 encDict.R = 5;
1437 encDict.O = wordArrayToBuffer(ownerPasswordEntry);
1438 encDict.OE = wordArrayToBuffer(ownerEncryptionKeyEntry);
1439 encDict.U = wordArrayToBuffer(userPasswordEntry);
1440 encDict.UE = wordArrayToBuffer(userEncryptionKeyEntry);
1441 encDict.P = permissions;
1442 encDict.Perms = wordArrayToBuffer(permsEntry);
1443 }
1444 }, {
1445 key: "getEncryptFn",
1446 value: function getEncryptFn(obj, gen) {
1447 var digest;
1448
1449 if (this.version < 5) {
1450 digest = this.encryptionKey.clone().concat(CryptoJS.lib.WordArray.create([(obj & 0xff) << 24 | (obj & 0xff00) << 8 | obj >> 8 & 0xff00 | gen & 0xff, (gen & 0xff00) << 16], 5));
1451 }
1452
1453 if (this.version === 1 || this.version === 2) {
1454 var _key = CryptoJS.MD5(digest);
1455
1456 _key.sigBytes = Math.min(16, this.keyBits / 8 + 5);
1457 return function (buffer) {
1458 return wordArrayToBuffer(CryptoJS.RC4.encrypt(CryptoJS.lib.WordArray.create(buffer), _key).ciphertext);
1459 };
1460 }
1461
1462 var key;
1463
1464 if (this.version === 4) {
1465 key = CryptoJS.MD5(digest.concat(CryptoJS.lib.WordArray.create([0x73416c54], 4)));
1466 } else {
1467 key = this.encryptionKey;
1468 }
1469
1470 var iv = PDFSecurity.generateRandomWordArray(16);
1471 var options = {
1472 mode: CryptoJS.mode.CBC,
1473 padding: CryptoJS.pad.Pkcs7,
1474 iv: iv
1475 };
1476 return function (buffer) {
1477 return wordArrayToBuffer(iv.clone().concat(CryptoJS.AES.encrypt(CryptoJS.lib.WordArray.create(buffer), key, options).ciphertext));
1478 };
1479 }
1480 }, {
1481 key: "end",
1482 value: function end() {
1483 this.dictionary.end();
1484 }
1485 }]);
1486
1487 return PDFSecurity;
1488}();
1489
1490function getPermissionsR2() {
1491 var permissionObject = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1492 var permissions = 0xffffffc0 >> 0;
1493
1494 if (permissionObject.printing) {
1495 permissions |= 4;
1496 }
1497
1498 if (permissionObject.modifying) {
1499 permissions |= 8;
1500 }
1501
1502 if (permissionObject.copying) {
1503 permissions |= 16;
1504 }
1505
1506 if (permissionObject.annotating) {
1507 permissions |= 32;
1508 }
1509
1510 return permissions;
1511}
1512
1513function getPermissionsR3() {
1514 var permissionObject = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1515 var permissions = 0xfffff0c0 >> 0;
1516
1517 if (permissionObject.printing === 'lowResolution') {
1518 permissions |= 4;
1519 }
1520
1521 if (permissionObject.printing === 'highResolution') {
1522 permissions |= 2052;
1523 }
1524
1525 if (permissionObject.modifying) {
1526 permissions |= 8;
1527 }
1528
1529 if (permissionObject.copying) {
1530 permissions |= 16;
1531 }
1532
1533 if (permissionObject.annotating) {
1534 permissions |= 32;
1535 }
1536
1537 if (permissionObject.fillingForms) {
1538 permissions |= 256;
1539 }
1540
1541 if (permissionObject.contentAccessibility) {
1542 permissions |= 512;
1543 }
1544
1545 if (permissionObject.documentAssembly) {
1546 permissions |= 1024;
1547 }
1548
1549 return permissions;
1550}
1551
1552function getUserPasswordR2(encryptionKey) {
1553 return CryptoJS.RC4.encrypt(processPasswordR2R3R4(), encryptionKey).ciphertext;
1554}
1555
1556function getUserPasswordR3R4(documentId, encryptionKey) {
1557 var key = encryptionKey.clone();
1558 var cipher = CryptoJS.MD5(processPasswordR2R3R4().concat(CryptoJS.lib.WordArray.create(documentId)));
1559
1560 for (var i = 0; i < 20; i++) {
1561 var xorRound = Math.ceil(key.sigBytes / 4);
1562
1563 for (var j = 0; j < xorRound; j++) {
1564 key.words[j] = encryptionKey.words[j] ^ (i | i << 8 | i << 16 | i << 24);
1565 }
1566
1567 cipher = CryptoJS.RC4.encrypt(cipher, key).ciphertext;
1568 }
1569
1570 return cipher.concat(CryptoJS.lib.WordArray.create(null, 16));
1571}
1572
1573function getOwnerPasswordR2R3R4(r, keyBits, paddedUserPassword, paddedOwnerPassword) {
1574 var digest = paddedOwnerPassword;
1575 var round = r >= 3 ? 51 : 1;
1576
1577 for (var i = 0; i < round; i++) {
1578 digest = CryptoJS.MD5(digest);
1579 }
1580
1581 var key = digest.clone();
1582 key.sigBytes = keyBits / 8;
1583 var cipher = paddedUserPassword;
1584 round = r >= 3 ? 20 : 1;
1585
1586 for (var _i = 0; _i < round; _i++) {
1587 var xorRound = Math.ceil(key.sigBytes / 4);
1588
1589 for (var j = 0; j < xorRound; j++) {
1590 key.words[j] = digest.words[j] ^ (_i | _i << 8 | _i << 16 | _i << 24);
1591 }
1592
1593 cipher = CryptoJS.RC4.encrypt(cipher, key).ciphertext;
1594 }
1595
1596 return cipher;
1597}
1598
1599function getEncryptionKeyR2R3R4(r, keyBits, documentId, paddedUserPassword, ownerPasswordEntry, permissions) {
1600 var key = paddedUserPassword.clone().concat(ownerPasswordEntry).concat(CryptoJS.lib.WordArray.create([lsbFirstWord(permissions)], 4)).concat(CryptoJS.lib.WordArray.create(documentId));
1601 var round = r >= 3 ? 51 : 1;
1602
1603 for (var i = 0; i < round; i++) {
1604 key = CryptoJS.MD5(key);
1605 key.sigBytes = keyBits / 8;
1606 }
1607
1608 return key;
1609}
1610
1611function getUserPasswordR5(processedUserPassword, generateRandomWordArray) {
1612 var validationSalt = generateRandomWordArray(8);
1613 var keySalt = generateRandomWordArray(8);
1614 return CryptoJS.SHA256(processedUserPassword.clone().concat(validationSalt)).concat(validationSalt).concat(keySalt);
1615}
1616
1617function getUserEncryptionKeyR5(processedUserPassword, userKeySalt, encryptionKey) {
1618 var key = CryptoJS.SHA256(processedUserPassword.clone().concat(userKeySalt));
1619 var options = {
1620 mode: CryptoJS.mode.CBC,
1621 padding: CryptoJS.pad.NoPadding,
1622 iv: CryptoJS.lib.WordArray.create(null, 16)
1623 };
1624 return CryptoJS.AES.encrypt(encryptionKey, key, options).ciphertext;
1625}
1626
1627function getOwnerPasswordR5(processedOwnerPassword, userPasswordEntry, generateRandomWordArray) {
1628 var validationSalt = generateRandomWordArray(8);
1629 var keySalt = generateRandomWordArray(8);
1630 return CryptoJS.SHA256(processedOwnerPassword.clone().concat(validationSalt).concat(userPasswordEntry)).concat(validationSalt).concat(keySalt);
1631}
1632
1633function getOwnerEncryptionKeyR5(processedOwnerPassword, ownerKeySalt, userPasswordEntry, encryptionKey) {
1634 var key = CryptoJS.SHA256(processedOwnerPassword.clone().concat(ownerKeySalt).concat(userPasswordEntry));
1635 var options = {
1636 mode: CryptoJS.mode.CBC,
1637 padding: CryptoJS.pad.NoPadding,
1638 iv: CryptoJS.lib.WordArray.create(null, 16)
1639 };
1640 return CryptoJS.AES.encrypt(encryptionKey, key, options).ciphertext;
1641}
1642
1643function getEncryptionKeyR5(generateRandomWordArray) {
1644 return generateRandomWordArray(32);
1645}
1646
1647function getEncryptedPermissionsR5(permissions, encryptionKey, generateRandomWordArray) {
1648 var cipher = CryptoJS.lib.WordArray.create([lsbFirstWord(permissions), 0xffffffff, 0x54616462], 12).concat(generateRandomWordArray(4));
1649 var options = {
1650 mode: CryptoJS.mode.ECB,
1651 padding: CryptoJS.pad.NoPadding
1652 };
1653 return CryptoJS.AES.encrypt(cipher, encryptionKey, options).ciphertext;
1654}
1655
1656function processPasswordR2R3R4() {
1657 var password = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
1658 var out = Buffer.alloc(32);
1659 var length = password.length;
1660 var index = 0;
1661
1662 while (index < length && index < 32) {
1663 var code = password.charCodeAt(index);
1664
1665 if (code > 0xff) {
1666 throw new Error('Password contains one or more invalid characters.');
1667 }
1668
1669 out[index] = code;
1670 index++;
1671 }
1672
1673 while (index < 32) {
1674 out[index] = PASSWORD_PADDING[index - length];
1675 index++;
1676 }
1677
1678 return CryptoJS.lib.WordArray.create(out);
1679}
1680
1681function processPasswordR5() {
1682 var password = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
1683 password = unescape(encodeURIComponent(saslprep(password)));
1684 var length = Math.min(127, password.length);
1685 var out = Buffer.alloc(length);
1686
1687 for (var i = 0; i < length; i++) {
1688 out[i] = password.charCodeAt(i);
1689 }
1690
1691 return CryptoJS.lib.WordArray.create(out);
1692}
1693
1694function lsbFirstWord(data) {
1695 return (data & 0xff) << 24 | (data & 0xff00) << 8 | data >> 8 & 0xff00 | data >> 24 & 0xff;
1696}
1697
1698function wordArrayToBuffer(wordArray) {
1699 var byteArray = [];
1700
1701 for (var i = 0; i < wordArray.sigBytes; i++) {
1702 byteArray.push(wordArray.words[Math.floor(i / 4)] >> 8 * (3 - i % 4) & 0xff);
1703 }
1704
1705 return Buffer.from(byteArray);
1706}
1707
1708var PASSWORD_PADDING = [0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a];
1709
1710var number = PDFObject.number;
1711
1712var PDFGradient = /*#__PURE__*/function () {
1713 function PDFGradient(doc) {
1714 _classCallCheck(this, PDFGradient);
1715
1716 this.doc = doc;
1717 this.stops = [];
1718 this.embedded = false;
1719 this.transform = [1, 0, 0, 1, 0, 0];
1720 }
1721
1722 _createClass(PDFGradient, [{
1723 key: "stop",
1724 value: function stop(pos, color, opacity) {
1725 if (opacity == null) {
1726 opacity = 1;
1727 }
1728
1729 color = this.doc._normalizeColor(color);
1730
1731 if (this.stops.length === 0) {
1732 if (color.length === 3) {
1733 this._colorSpace = 'DeviceRGB';
1734 } else if (color.length === 4) {
1735 this._colorSpace = 'DeviceCMYK';
1736 } else if (color.length === 1) {
1737 this._colorSpace = 'DeviceGray';
1738 } else {
1739 throw new Error('Unknown color space');
1740 }
1741 } else if (this._colorSpace === 'DeviceRGB' && color.length !== 3 || this._colorSpace === 'DeviceCMYK' && color.length !== 4 || this._colorSpace === 'DeviceGray' && color.length !== 1) {
1742 throw new Error('All gradient stops must use the same color space');
1743 }
1744
1745 opacity = Math.max(0, Math.min(1, opacity));
1746 this.stops.push([pos, color, opacity]);
1747 return this;
1748 }
1749 }, {
1750 key: "setTransform",
1751 value: function setTransform(m11, m12, m21, m22, dx, dy) {
1752 this.transform = [m11, m12, m21, m22, dx, dy];
1753 return this;
1754 }
1755 }, {
1756 key: "embed",
1757 value: function embed(m) {
1758 var fn;
1759 var stopsLength = this.stops.length;
1760
1761 if (stopsLength === 0) {
1762 return;
1763 }
1764
1765 this.embedded = true;
1766 this.matrix = m; // if the last stop comes before 100%, add a copy at 100%
1767
1768 var last = this.stops[stopsLength - 1];
1769
1770 if (last[0] < 1) {
1771 this.stops.push([1, last[1], last[2]]);
1772 }
1773
1774 var bounds = [];
1775 var encode = [];
1776 var stops = [];
1777
1778 for (var i = 0; i < stopsLength - 1; i++) {
1779 encode.push(0, 1);
1780
1781 if (i + 2 !== stopsLength) {
1782 bounds.push(this.stops[i + 1][0]);
1783 }
1784
1785 fn = this.doc.ref({
1786 FunctionType: 2,
1787 Domain: [0, 1],
1788 C0: this.stops[i + 0][1],
1789 C1: this.stops[i + 1][1],
1790 N: 1
1791 });
1792 stops.push(fn);
1793 fn.end();
1794 } // if there are only two stops, we don't need a stitching function
1795
1796
1797 if (stopsLength === 1) {
1798 fn = stops[0];
1799 } else {
1800 fn = this.doc.ref({
1801 FunctionType: 3,
1802 // stitching function
1803 Domain: [0, 1],
1804 Functions: stops,
1805 Bounds: bounds,
1806 Encode: encode
1807 });
1808 fn.end();
1809 }
1810
1811 this.id = "Sh".concat(++this.doc._gradCount);
1812 var shader = this.shader(fn);
1813 shader.end();
1814 var pattern = this.doc.ref({
1815 Type: 'Pattern',
1816 PatternType: 2,
1817 Shading: shader,
1818 Matrix: this.matrix.map(number)
1819 });
1820 pattern.end();
1821
1822 if (this.stops.some(function (stop) {
1823 return stop[2] < 1;
1824 })) {
1825 var grad = this.opacityGradient();
1826 grad._colorSpace = 'DeviceGray';
1827
1828 var _iterator = _createForOfIteratorHelper(this.stops),
1829 _step;
1830
1831 try {
1832 for (_iterator.s(); !(_step = _iterator.n()).done;) {
1833 var stop = _step.value;
1834 grad.stop(stop[0], [stop[2]]);
1835 }
1836 } catch (err) {
1837 _iterator.e(err);
1838 } finally {
1839 _iterator.f();
1840 }
1841
1842 grad = grad.embed(this.matrix);
1843 var pageBBox = [0, 0, this.doc.page.width, this.doc.page.height];
1844 var form = this.doc.ref({
1845 Type: 'XObject',
1846 Subtype: 'Form',
1847 FormType: 1,
1848 BBox: pageBBox,
1849 Group: {
1850 Type: 'Group',
1851 S: 'Transparency',
1852 CS: 'DeviceGray'
1853 },
1854 Resources: {
1855 ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI'],
1856 Pattern: {
1857 Sh1: grad
1858 }
1859 }
1860 });
1861 form.write('/Pattern cs /Sh1 scn');
1862 form.end("".concat(pageBBox.join(' '), " re f"));
1863 var gstate = this.doc.ref({
1864 Type: 'ExtGState',
1865 SMask: {
1866 Type: 'Mask',
1867 S: 'Luminosity',
1868 G: form
1869 }
1870 });
1871 gstate.end();
1872 var opacityPattern = this.doc.ref({
1873 Type: 'Pattern',
1874 PatternType: 1,
1875 PaintType: 1,
1876 TilingType: 2,
1877 BBox: pageBBox,
1878 XStep: pageBBox[2],
1879 YStep: pageBBox[3],
1880 Resources: {
1881 ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI'],
1882 Pattern: {
1883 Sh1: pattern
1884 },
1885 ExtGState: {
1886 Gs1: gstate
1887 }
1888 }
1889 });
1890 opacityPattern.write('/Gs1 gs /Pattern cs /Sh1 scn');
1891 opacityPattern.end("".concat(pageBBox.join(' '), " re f"));
1892 this.doc.page.patterns[this.id] = opacityPattern;
1893 } else {
1894 this.doc.page.patterns[this.id] = pattern;
1895 }
1896
1897 return pattern;
1898 }
1899 }, {
1900 key: "apply",
1901 value: function apply(stroke) {
1902 // apply gradient transform to existing document ctm
1903 var _this$doc$_ctm = _slicedToArray(this.doc._ctm, 6),
1904 m0 = _this$doc$_ctm[0],
1905 m1 = _this$doc$_ctm[1],
1906 m2 = _this$doc$_ctm[2],
1907 m3 = _this$doc$_ctm[3],
1908 m4 = _this$doc$_ctm[4],
1909 m5 = _this$doc$_ctm[5];
1910
1911 var _this$transform = _slicedToArray(this.transform, 6),
1912 m11 = _this$transform[0],
1913 m12 = _this$transform[1],
1914 m21 = _this$transform[2],
1915 m22 = _this$transform[3],
1916 dx = _this$transform[4],
1917 dy = _this$transform[5];
1918
1919 var 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];
1920
1921 if (!this.embedded || m.join(' ') !== this.matrix.join(' ')) {
1922 this.embed(m);
1923 }
1924
1925 this.doc._setColorSpace('Pattern', stroke);
1926
1927 var op = stroke ? 'SCN' : 'scn';
1928 return this.doc.addContent("/".concat(this.id, " ").concat(op));
1929 }
1930 }]);
1931
1932 return PDFGradient;
1933}();
1934
1935var PDFLinearGradient = /*#__PURE__*/function (_PDFGradient) {
1936 _inherits(PDFLinearGradient, _PDFGradient);
1937
1938 var _super = _createSuper(PDFLinearGradient);
1939
1940 function PDFLinearGradient(doc, x1, y1, x2, y2) {
1941 var _this;
1942
1943 _classCallCheck(this, PDFLinearGradient);
1944
1945 _this = _super.call(this, doc);
1946 _this.x1 = x1;
1947 _this.y1 = y1;
1948 _this.x2 = x2;
1949 _this.y2 = y2;
1950 return _this;
1951 }
1952
1953 _createClass(PDFLinearGradient, [{
1954 key: "shader",
1955 value: function shader(fn) {
1956 return this.doc.ref({
1957 ShadingType: 2,
1958 ColorSpace: this._colorSpace,
1959 Coords: [this.x1, this.y1, this.x2, this.y2],
1960 Function: fn,
1961 Extend: [true, true]
1962 });
1963 }
1964 }, {
1965 key: "opacityGradient",
1966 value: function opacityGradient() {
1967 return new PDFLinearGradient(this.doc, this.x1, this.y1, this.x2, this.y2);
1968 }
1969 }]);
1970
1971 return PDFLinearGradient;
1972}(PDFGradient);
1973
1974var PDFRadialGradient = /*#__PURE__*/function (_PDFGradient2) {
1975 _inherits(PDFRadialGradient, _PDFGradient2);
1976
1977 var _super2 = _createSuper(PDFRadialGradient);
1978
1979 function PDFRadialGradient(doc, x1, y1, r1, x2, y2, r2) {
1980 var _this2;
1981
1982 _classCallCheck(this, PDFRadialGradient);
1983
1984 _this2 = _super2.call(this, doc);
1985 _this2.doc = doc;
1986 _this2.x1 = x1;
1987 _this2.y1 = y1;
1988 _this2.r1 = r1;
1989 _this2.x2 = x2;
1990 _this2.y2 = y2;
1991 _this2.r2 = r2;
1992 return _this2;
1993 }
1994
1995 _createClass(PDFRadialGradient, [{
1996 key: "shader",
1997 value: function shader(fn) {
1998 return this.doc.ref({
1999 ShadingType: 3,
2000 ColorSpace: this._colorSpace,
2001 Coords: [this.x1, this.y1, this.r1, this.x2, this.y2, this.r2],
2002 Function: fn,
2003 Extend: [true, true]
2004 });
2005 }
2006 }, {
2007 key: "opacityGradient",
2008 value: function opacityGradient() {
2009 return new PDFRadialGradient(this.doc, this.x1, this.y1, this.r1, this.x2, this.y2, this.r2);
2010 }
2011 }]);
2012
2013 return PDFRadialGradient;
2014}(PDFGradient);
2015
2016var Gradient = {
2017 PDFGradient: PDFGradient,
2018 PDFLinearGradient: PDFLinearGradient,
2019 PDFRadialGradient: PDFRadialGradient
2020};
2021
2022/*
2023PDF tiling pattern support. Uncolored only.
2024 */
2025var underlyingColorSpaces = ['DeviceCMYK', 'DeviceRGB'];
2026
2027var PDFTilingPattern = /*#__PURE__*/function () {
2028 function PDFTilingPattern(doc, bBox, xStep, yStep, stream) {
2029 _classCallCheck(this, PDFTilingPattern);
2030
2031 this.doc = doc;
2032 this.bBox = bBox;
2033 this.xStep = xStep;
2034 this.yStep = yStep;
2035 this.stream = stream;
2036 }
2037
2038 _createClass(PDFTilingPattern, [{
2039 key: "createPattern",
2040 value: function createPattern() {
2041 // no resources needed for our current usage
2042 // required entry
2043 var resources = this.doc.ref();
2044 resources.end(); // apply default transform matrix (flipped in the default doc._ctm)
2045 // see document.js & gradient.js
2046
2047 var _this$doc$_ctm = _slicedToArray(this.doc._ctm, 6),
2048 m0 = _this$doc$_ctm[0],
2049 m1 = _this$doc$_ctm[1],
2050 m2 = _this$doc$_ctm[2],
2051 m3 = _this$doc$_ctm[3],
2052 m4 = _this$doc$_ctm[4],
2053 m5 = _this$doc$_ctm[5];
2054
2055 var m11 = 1,
2056 m12 = 0,
2057 m21 = 0,
2058 m22 = 1,
2059 dx = 0,
2060 dy = 0;
2061 var 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];
2062 var pattern = this.doc.ref({
2063 Type: 'Pattern',
2064 PatternType: 1,
2065 // tiling
2066 PaintType: 2,
2067 // 1-colored, 2-uncolored
2068 TilingType: 2,
2069 // 2-no distortion
2070 BBox: this.bBox,
2071 XStep: this.xStep,
2072 YStep: this.yStep,
2073 Matrix: m.map(function (v) {
2074 return +v.toFixed(5);
2075 }),
2076 Resources: resources
2077 });
2078 pattern.end(this.stream);
2079 return pattern;
2080 }
2081 }, {
2082 key: "embedPatternColorSpaces",
2083 value: function embedPatternColorSpaces() {
2084 var _this = this;
2085
2086 // map each pattern to an underlying color space
2087 // and embed on each page
2088 underlyingColorSpaces.forEach(function (csName) {
2089 var csId = _this.getPatternColorSpaceId(csName);
2090
2091 if (_this.doc.page.colorSpaces[csId]) return;
2092
2093 var cs = _this.doc.ref(['Pattern', csName]);
2094
2095 cs.end();
2096 _this.doc.page.colorSpaces[csId] = cs;
2097 });
2098 }
2099 }, {
2100 key: "getPatternColorSpaceId",
2101 value: function getPatternColorSpaceId(underlyingColorspace) {
2102 return "CsP".concat(underlyingColorspace);
2103 }
2104 }, {
2105 key: "embed",
2106 value: function embed() {
2107 if (!this.id) {
2108 this.doc._patternCount = this.doc._patternCount + 1;
2109 this.id = 'P' + this.doc._patternCount;
2110 this.pattern = this.createPattern();
2111 } // patterns are embedded in each page
2112
2113
2114 if (!this.doc.page.patterns[this.id]) {
2115 this.doc.page.patterns[this.id] = this.pattern;
2116 }
2117 }
2118 }, {
2119 key: "apply",
2120 value: function apply(stroke, patternColor) {
2121 // do any embedding/creating that might be needed
2122 this.embedPatternColorSpaces();
2123 this.embed();
2124
2125 var normalizedColor = this.doc._normalizeColor(patternColor);
2126
2127 if (!normalizedColor) throw Error("invalid pattern color. (value: ".concat(patternColor, ")")); // select one of the pattern color spaces
2128
2129 var csId = this.getPatternColorSpaceId(this.doc._getColorSpace(normalizedColor));
2130
2131 this.doc._setColorSpace(csId, stroke); // stroke/fill using the pattern and color (in the above underlying color space)
2132
2133
2134 var op = stroke ? 'SCN' : 'scn';
2135 return this.doc.addContent("".concat(normalizedColor.join(' '), " /").concat(this.id, " ").concat(op));
2136 }
2137 }]);
2138
2139 return PDFTilingPattern;
2140}();
2141
2142var pattern = {
2143 PDFTilingPattern: PDFTilingPattern
2144};
2145
2146var PDFGradient$1 = Gradient.PDFGradient,
2147 PDFLinearGradient$1 = Gradient.PDFLinearGradient,
2148 PDFRadialGradient$1 = Gradient.PDFRadialGradient;
2149var PDFTilingPattern$1 = pattern.PDFTilingPattern;
2150var ColorMixin = {
2151 initColor: function initColor() {
2152 // The opacity dictionaries
2153 this._opacityRegistry = {};
2154 this._opacityCount = 0;
2155 this._patternCount = 0;
2156 return this._gradCount = 0;
2157 },
2158 _normalizeColor: function _normalizeColor(color) {
2159 if (typeof color === 'string') {
2160 if (color.charAt(0) === '#') {
2161 if (color.length === 4) {
2162 color = color.replace(/#([0-9A-F])([0-9A-F])([0-9A-F])/i, '#$1$1$2$2$3$3');
2163 }
2164
2165 var hex = parseInt(color.slice(1), 16);
2166 color = [hex >> 16, hex >> 8 & 0xff, hex & 0xff];
2167 } else if (namedColors[color]) {
2168 color = namedColors[color];
2169 }
2170 }
2171
2172 if (Array.isArray(color)) {
2173 // RGB
2174 if (color.length === 3) {
2175 color = color.map(function (part) {
2176 return part / 255;
2177 }); // CMYK
2178 } else if (color.length === 4) {
2179 color = color.map(function (part) {
2180 return part / 100;
2181 });
2182 }
2183
2184 return color;
2185 }
2186
2187 return null;
2188 },
2189 _setColor: function _setColor(color, stroke) {
2190 if (color instanceof PDFGradient$1) {
2191 color.apply(stroke);
2192 return true; // see if tiling pattern, decode & apply it it
2193 } else if (Array.isArray(color) && color[0] instanceof PDFTilingPattern$1) {
2194 color[0].apply(stroke, color[1]);
2195 return true;
2196 } // any other case should be a normal color and not a pattern
2197
2198
2199 return this._setColorCore(color, stroke);
2200 },
2201 _setColorCore: function _setColorCore(color, stroke) {
2202 color = this._normalizeColor(color);
2203
2204 if (!color) {
2205 return false;
2206 }
2207
2208 var op = stroke ? 'SCN' : 'scn';
2209
2210 var space = this._getColorSpace(color);
2211
2212 this._setColorSpace(space, stroke);
2213
2214 color = color.join(' ');
2215 this.addContent("".concat(color, " ").concat(op));
2216 return true;
2217 },
2218 _setColorSpace: function _setColorSpace(space, stroke) {
2219 var op = stroke ? 'CS' : 'cs';
2220 return this.addContent("/".concat(space, " ").concat(op));
2221 },
2222 _getColorSpace: function _getColorSpace(color) {
2223 return color.length === 4 ? 'DeviceCMYK' : 'DeviceRGB';
2224 },
2225 fillColor: function fillColor(color, opacity) {
2226 var set = this._setColor(color, false);
2227
2228 if (set) {
2229 this.fillOpacity(opacity);
2230 } // save this for text wrapper, which needs to reset
2231 // the fill color on new pages
2232
2233
2234 this._fillColor = [color, opacity];
2235 return this;
2236 },
2237 strokeColor: function strokeColor(color, opacity) {
2238 var set = this._setColor(color, true);
2239
2240 if (set) {
2241 this.strokeOpacity(opacity);
2242 }
2243
2244 return this;
2245 },
2246 opacity: function opacity(_opacity) {
2247 this._doOpacity(_opacity, _opacity);
2248
2249 return this;
2250 },
2251 fillOpacity: function fillOpacity(opacity) {
2252 this._doOpacity(opacity, null);
2253
2254 return this;
2255 },
2256 strokeOpacity: function strokeOpacity(opacity) {
2257 this._doOpacity(null, opacity);
2258
2259 return this;
2260 },
2261 _doOpacity: function _doOpacity(fillOpacity, strokeOpacity) {
2262 var dictionary, name;
2263
2264 if (fillOpacity == null && strokeOpacity == null) {
2265 return;
2266 }
2267
2268 if (fillOpacity != null) {
2269 fillOpacity = Math.max(0, Math.min(1, fillOpacity));
2270 }
2271
2272 if (strokeOpacity != null) {
2273 strokeOpacity = Math.max(0, Math.min(1, strokeOpacity));
2274 }
2275
2276 var key = "".concat(fillOpacity, "_").concat(strokeOpacity);
2277
2278 if (this._opacityRegistry[key]) {
2279 var _this$_opacityRegistr = _slicedToArray(this._opacityRegistry[key], 2);
2280
2281 dictionary = _this$_opacityRegistr[0];
2282 name = _this$_opacityRegistr[1];
2283 } else {
2284 dictionary = {
2285 Type: 'ExtGState'
2286 };
2287
2288 if (fillOpacity != null) {
2289 dictionary.ca = fillOpacity;
2290 }
2291
2292 if (strokeOpacity != null) {
2293 dictionary.CA = strokeOpacity;
2294 }
2295
2296 dictionary = this.ref(dictionary);
2297 dictionary.end();
2298 var id = ++this._opacityCount;
2299 name = "Gs".concat(id);
2300 this._opacityRegistry[key] = [dictionary, name];
2301 }
2302
2303 this.page.ext_gstates[name] = dictionary;
2304 return this.addContent("/".concat(name, " gs"));
2305 },
2306 linearGradient: function linearGradient(x1, y1, x2, y2) {
2307 return new PDFLinearGradient$1(this, x1, y1, x2, y2);
2308 },
2309 radialGradient: function radialGradient(x1, y1, r1, x2, y2, r2) {
2310 return new PDFRadialGradient$1(this, x1, y1, r1, x2, y2, r2);
2311 },
2312 pattern: function pattern(bbox, xStep, yStep, stream) {
2313 return new PDFTilingPattern$1(this, bbox, xStep, yStep, stream);
2314 }
2315};
2316var namedColors = {
2317 aliceblue: [240, 248, 255],
2318 antiquewhite: [250, 235, 215],
2319 aqua: [0, 255, 255],
2320 aquamarine: [127, 255, 212],
2321 azure: [240, 255, 255],
2322 beige: [245, 245, 220],
2323 bisque: [255, 228, 196],
2324 black: [0, 0, 0],
2325 blanchedalmond: [255, 235, 205],
2326 blue: [0, 0, 255],
2327 blueviolet: [138, 43, 226],
2328 brown: [165, 42, 42],
2329 burlywood: [222, 184, 135],
2330 cadetblue: [95, 158, 160],
2331 chartreuse: [127, 255, 0],
2332 chocolate: [210, 105, 30],
2333 coral: [255, 127, 80],
2334 cornflowerblue: [100, 149, 237],
2335 cornsilk: [255, 248, 220],
2336 crimson: [220, 20, 60],
2337 cyan: [0, 255, 255],
2338 darkblue: [0, 0, 139],
2339 darkcyan: [0, 139, 139],
2340 darkgoldenrod: [184, 134, 11],
2341 darkgray: [169, 169, 169],
2342 darkgreen: [0, 100, 0],
2343 darkgrey: [169, 169, 169],
2344 darkkhaki: [189, 183, 107],
2345 darkmagenta: [139, 0, 139],
2346 darkolivegreen: [85, 107, 47],
2347 darkorange: [255, 140, 0],
2348 darkorchid: [153, 50, 204],
2349 darkred: [139, 0, 0],
2350 darksalmon: [233, 150, 122],
2351 darkseagreen: [143, 188, 143],
2352 darkslateblue: [72, 61, 139],
2353 darkslategray: [47, 79, 79],
2354 darkslategrey: [47, 79, 79],
2355 darkturquoise: [0, 206, 209],
2356 darkviolet: [148, 0, 211],
2357 deeppink: [255, 20, 147],
2358 deepskyblue: [0, 191, 255],
2359 dimgray: [105, 105, 105],
2360 dimgrey: [105, 105, 105],
2361 dodgerblue: [30, 144, 255],
2362 firebrick: [178, 34, 34],
2363 floralwhite: [255, 250, 240],
2364 forestgreen: [34, 139, 34],
2365 fuchsia: [255, 0, 255],
2366 gainsboro: [220, 220, 220],
2367 ghostwhite: [248, 248, 255],
2368 gold: [255, 215, 0],
2369 goldenrod: [218, 165, 32],
2370 gray: [128, 128, 128],
2371 grey: [128, 128, 128],
2372 green: [0, 128, 0],
2373 greenyellow: [173, 255, 47],
2374 honeydew: [240, 255, 240],
2375 hotpink: [255, 105, 180],
2376 indianred: [205, 92, 92],
2377 indigo: [75, 0, 130],
2378 ivory: [255, 255, 240],
2379 khaki: [240, 230, 140],
2380 lavender: [230, 230, 250],
2381 lavenderblush: [255, 240, 245],
2382 lawngreen: [124, 252, 0],
2383 lemonchiffon: [255, 250, 205],
2384 lightblue: [173, 216, 230],
2385 lightcoral: [240, 128, 128],
2386 lightcyan: [224, 255, 255],
2387 lightgoldenrodyellow: [250, 250, 210],
2388 lightgray: [211, 211, 211],
2389 lightgreen: [144, 238, 144],
2390 lightgrey: [211, 211, 211],
2391 lightpink: [255, 182, 193],
2392 lightsalmon: [255, 160, 122],
2393 lightseagreen: [32, 178, 170],
2394 lightskyblue: [135, 206, 250],
2395 lightslategray: [119, 136, 153],
2396 lightslategrey: [119, 136, 153],
2397 lightsteelblue: [176, 196, 222],
2398 lightyellow: [255, 255, 224],
2399 lime: [0, 255, 0],
2400 limegreen: [50, 205, 50],
2401 linen: [250, 240, 230],
2402 magenta: [255, 0, 255],
2403 maroon: [128, 0, 0],
2404 mediumaquamarine: [102, 205, 170],
2405 mediumblue: [0, 0, 205],
2406 mediumorchid: [186, 85, 211],
2407 mediumpurple: [147, 112, 219],
2408 mediumseagreen: [60, 179, 113],
2409 mediumslateblue: [123, 104, 238],
2410 mediumspringgreen: [0, 250, 154],
2411 mediumturquoise: [72, 209, 204],
2412 mediumvioletred: [199, 21, 133],
2413 midnightblue: [25, 25, 112],
2414 mintcream: [245, 255, 250],
2415 mistyrose: [255, 228, 225],
2416 moccasin: [255, 228, 181],
2417 navajowhite: [255, 222, 173],
2418 navy: [0, 0, 128],
2419 oldlace: [253, 245, 230],
2420 olive: [128, 128, 0],
2421 olivedrab: [107, 142, 35],
2422 orange: [255, 165, 0],
2423 orangered: [255, 69, 0],
2424 orchid: [218, 112, 214],
2425 palegoldenrod: [238, 232, 170],
2426 palegreen: [152, 251, 152],
2427 paleturquoise: [175, 238, 238],
2428 palevioletred: [219, 112, 147],
2429 papayawhip: [255, 239, 213],
2430 peachpuff: [255, 218, 185],
2431 peru: [205, 133, 63],
2432 pink: [255, 192, 203],
2433 plum: [221, 160, 221],
2434 powderblue: [176, 224, 230],
2435 purple: [128, 0, 128],
2436 red: [255, 0, 0],
2437 rosybrown: [188, 143, 143],
2438 royalblue: [65, 105, 225],
2439 saddlebrown: [139, 69, 19],
2440 salmon: [250, 128, 114],
2441 sandybrown: [244, 164, 96],
2442 seagreen: [46, 139, 87],
2443 seashell: [255, 245, 238],
2444 sienna: [160, 82, 45],
2445 silver: [192, 192, 192],
2446 skyblue: [135, 206, 235],
2447 slateblue: [106, 90, 205],
2448 slategray: [112, 128, 144],
2449 slategrey: [112, 128, 144],
2450 snow: [255, 250, 250],
2451 springgreen: [0, 255, 127],
2452 steelblue: [70, 130, 180],
2453 tan: [210, 180, 140],
2454 teal: [0, 128, 128],
2455 thistle: [216, 191, 216],
2456 tomato: [255, 99, 71],
2457 turquoise: [64, 224, 208],
2458 violet: [238, 130, 238],
2459 wheat: [245, 222, 179],
2460 white: [255, 255, 255],
2461 whitesmoke: [245, 245, 245],
2462 yellow: [255, 255, 0],
2463 yellowgreen: [154, 205, 50]
2464};
2465
2466var cx, cy, px, py, sx, sy;
2467cx = cy = px = py = sx = sy = 0;
2468var parameters = {
2469 A: 7,
2470 a: 7,
2471 C: 6,
2472 c: 6,
2473 H: 1,
2474 h: 1,
2475 L: 2,
2476 l: 2,
2477 M: 2,
2478 m: 2,
2479 Q: 4,
2480 q: 4,
2481 S: 4,
2482 s: 4,
2483 T: 2,
2484 t: 2,
2485 V: 1,
2486 v: 1,
2487 Z: 0,
2488 z: 0
2489};
2490
2491var parse = function parse(path) {
2492 var cmd;
2493 var ret = [];
2494 var args = [];
2495 var curArg = '';
2496 var foundDecimal = false;
2497 var params = 0;
2498
2499 var _iterator = _createForOfIteratorHelper(path),
2500 _step;
2501
2502 try {
2503 for (_iterator.s(); !(_step = _iterator.n()).done;) {
2504 var c = _step.value;
2505
2506 if (parameters[c] != null) {
2507 params = parameters[c];
2508
2509 if (cmd) {
2510 // save existing command
2511 if (curArg.length > 0) {
2512 args[args.length] = +curArg;
2513 }
2514
2515 ret[ret.length] = {
2516 cmd: cmd,
2517 args: args
2518 };
2519 args = [];
2520 curArg = '';
2521 foundDecimal = false;
2522 }
2523
2524 cmd = c;
2525 } else if ([' ', ','].includes(c) || c === '-' && curArg.length > 0 && curArg[curArg.length - 1] !== 'e' || c === '.' && foundDecimal) {
2526 if (curArg.length === 0) {
2527 continue;
2528 }
2529
2530 if (args.length === params) {
2531 // handle reused commands
2532 ret[ret.length] = {
2533 cmd: cmd,
2534 args: args
2535 };
2536 args = [+curArg]; // handle assumed commands
2537
2538 if (cmd === 'M') {
2539 cmd = 'L';
2540 }
2541
2542 if (cmd === 'm') {
2543 cmd = 'l';
2544 }
2545 } else {
2546 args[args.length] = +curArg;
2547 }
2548
2549 foundDecimal = c === '.'; // fix for negative numbers or repeated decimals with no delimeter between commands
2550
2551 curArg = ['-', '.'].includes(c) ? c : '';
2552 } else {
2553 curArg += c;
2554
2555 if (c === '.') {
2556 foundDecimal = true;
2557 }
2558 }
2559 } // add the last command
2560
2561 } catch (err) {
2562 _iterator.e(err);
2563 } finally {
2564 _iterator.f();
2565 }
2566
2567 if (curArg.length > 0) {
2568 if (args.length === params) {
2569 // handle reused commands
2570 ret[ret.length] = {
2571 cmd: cmd,
2572 args: args
2573 };
2574 args = [+curArg]; // handle assumed commands
2575
2576 if (cmd === 'M') {
2577 cmd = 'L';
2578 }
2579
2580 if (cmd === 'm') {
2581 cmd = 'l';
2582 }
2583 } else {
2584 args[args.length] = +curArg;
2585 }
2586 }
2587
2588 ret[ret.length] = {
2589 cmd: cmd,
2590 args: args
2591 };
2592 return ret;
2593};
2594
2595var _apply = function apply(commands, doc) {
2596 // current point, control point, and subpath starting point
2597 cx = cy = px = py = sx = sy = 0; // run the commands
2598
2599 for (var i = 0; i < commands.length; i++) {
2600 var c = commands[i];
2601
2602 if (typeof runners[c.cmd] === 'function') {
2603 runners[c.cmd](doc, c.args);
2604 }
2605 }
2606};
2607
2608var runners = {
2609 M: function M(doc, a) {
2610 cx = a[0];
2611 cy = a[1];
2612 px = py = null;
2613 sx = cx;
2614 sy = cy;
2615 return doc.moveTo(cx, cy);
2616 },
2617 m: function m(doc, a) {
2618 cx += a[0];
2619 cy += a[1];
2620 px = py = null;
2621 sx = cx;
2622 sy = cy;
2623 return doc.moveTo(cx, cy);
2624 },
2625 C: function C(doc, a) {
2626 cx = a[4];
2627 cy = a[5];
2628 px = a[2];
2629 py = a[3];
2630 return doc.bezierCurveTo.apply(doc, _toConsumableArray(a));
2631 },
2632 c: function c(doc, a) {
2633 doc.bezierCurveTo(a[0] + cx, a[1] + cy, a[2] + cx, a[3] + cy, a[4] + cx, a[5] + cy);
2634 px = cx + a[2];
2635 py = cy + a[3];
2636 cx += a[4];
2637 return cy += a[5];
2638 },
2639 S: function S(doc, a) {
2640 if (px === null) {
2641 px = cx;
2642 py = cy;
2643 }
2644
2645 doc.bezierCurveTo(cx - (px - cx), cy - (py - cy), a[0], a[1], a[2], a[3]);
2646 px = a[0];
2647 py = a[1];
2648 cx = a[2];
2649 return cy = a[3];
2650 },
2651 s: function s(doc, a) {
2652 if (px === null) {
2653 px = cx;
2654 py = cy;
2655 }
2656
2657 doc.bezierCurveTo(cx - (px - cx), cy - (py - cy), cx + a[0], cy + a[1], cx + a[2], cy + a[3]);
2658 px = cx + a[0];
2659 py = cy + a[1];
2660 cx += a[2];
2661 return cy += a[3];
2662 },
2663 Q: function Q(doc, a) {
2664 px = a[0];
2665 py = a[1];
2666 cx = a[2];
2667 cy = a[3];
2668 return doc.quadraticCurveTo(a[0], a[1], cx, cy);
2669 },
2670 q: function q(doc, a) {
2671 doc.quadraticCurveTo(a[0] + cx, a[1] + cy, a[2] + cx, a[3] + cy);
2672 px = cx + a[0];
2673 py = cy + a[1];
2674 cx += a[2];
2675 return cy += a[3];
2676 },
2677 T: function T(doc, a) {
2678 if (px === null) {
2679 px = cx;
2680 py = cy;
2681 } else {
2682 px = cx - (px - cx);
2683 py = cy - (py - cy);
2684 }
2685
2686 doc.quadraticCurveTo(px, py, a[0], a[1]);
2687 px = cx - (px - cx);
2688 py = cy - (py - cy);
2689 cx = a[0];
2690 return cy = a[1];
2691 },
2692 t: function t(doc, a) {
2693 if (px === null) {
2694 px = cx;
2695 py = cy;
2696 } else {
2697 px = cx - (px - cx);
2698 py = cy - (py - cy);
2699 }
2700
2701 doc.quadraticCurveTo(px, py, cx + a[0], cy + a[1]);
2702 cx += a[0];
2703 return cy += a[1];
2704 },
2705 A: function A(doc, a) {
2706 solveArc(doc, cx, cy, a);
2707 cx = a[5];
2708 return cy = a[6];
2709 },
2710 a: function a(doc, _a) {
2711 _a[5] += cx;
2712 _a[6] += cy;
2713 solveArc(doc, cx, cy, _a);
2714 cx = _a[5];
2715 return cy = _a[6];
2716 },
2717 L: function L(doc, a) {
2718 cx = a[0];
2719 cy = a[1];
2720 px = py = null;
2721 return doc.lineTo(cx, cy);
2722 },
2723 l: function l(doc, a) {
2724 cx += a[0];
2725 cy += a[1];
2726 px = py = null;
2727 return doc.lineTo(cx, cy);
2728 },
2729 H: function H(doc, a) {
2730 cx = a[0];
2731 px = py = null;
2732 return doc.lineTo(cx, cy);
2733 },
2734 h: function h(doc, a) {
2735 cx += a[0];
2736 px = py = null;
2737 return doc.lineTo(cx, cy);
2738 },
2739 V: function V(doc, a) {
2740 cy = a[0];
2741 px = py = null;
2742 return doc.lineTo(cx, cy);
2743 },
2744 v: function v(doc, a) {
2745 cy += a[0];
2746 px = py = null;
2747 return doc.lineTo(cx, cy);
2748 },
2749 Z: function Z(doc) {
2750 doc.closePath();
2751 cx = sx;
2752 return cy = sy;
2753 },
2754 z: function z(doc) {
2755 doc.closePath();
2756 cx = sx;
2757 return cy = sy;
2758 }
2759};
2760
2761var solveArc = function solveArc(doc, x, y, coords) {
2762 var _coords = _slicedToArray(coords, 7),
2763 rx = _coords[0],
2764 ry = _coords[1],
2765 rot = _coords[2],
2766 large = _coords[3],
2767 sweep = _coords[4],
2768 ex = _coords[5],
2769 ey = _coords[6];
2770
2771 var segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, x, y);
2772
2773 var _iterator2 = _createForOfIteratorHelper(segs),
2774 _step2;
2775
2776 try {
2777 for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
2778 var seg = _step2.value;
2779 var bez = segmentToBezier.apply(void 0, _toConsumableArray(seg));
2780 doc.bezierCurveTo.apply(doc, _toConsumableArray(bez));
2781 }
2782 } catch (err) {
2783 _iterator2.e(err);
2784 } finally {
2785 _iterator2.f();
2786 }
2787}; // from Inkscape svgtopdf, thanks!
2788
2789
2790var arcToSegments = function arcToSegments(x, y, rx, ry, large, sweep, rotateX, ox, oy) {
2791 var th = rotateX * (Math.PI / 180);
2792 var sin_th = Math.sin(th);
2793 var cos_th = Math.cos(th);
2794 rx = Math.abs(rx);
2795 ry = Math.abs(ry);
2796 px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5;
2797 py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5;
2798 var pl = px * px / (rx * rx) + py * py / (ry * ry);
2799
2800 if (pl > 1) {
2801 pl = Math.sqrt(pl);
2802 rx *= pl;
2803 ry *= pl;
2804 }
2805
2806 var a00 = cos_th / rx;
2807 var a01 = sin_th / rx;
2808 var a10 = -sin_th / ry;
2809 var a11 = cos_th / ry;
2810 var x0 = a00 * ox + a01 * oy;
2811 var y0 = a10 * ox + a11 * oy;
2812 var x1 = a00 * x + a01 * y;
2813 var y1 = a10 * x + a11 * y;
2814 var d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
2815 var sfactor_sq = 1 / d - 0.25;
2816
2817 if (sfactor_sq < 0) {
2818 sfactor_sq = 0;
2819 }
2820
2821 var sfactor = Math.sqrt(sfactor_sq);
2822
2823 if (sweep === large) {
2824 sfactor = -sfactor;
2825 }
2826
2827 var xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
2828 var yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
2829 var th0 = Math.atan2(y0 - yc, x0 - xc);
2830 var th1 = Math.atan2(y1 - yc, x1 - xc);
2831 var th_arc = th1 - th0;
2832
2833 if (th_arc < 0 && sweep === 1) {
2834 th_arc += 2 * Math.PI;
2835 } else if (th_arc > 0 && sweep === 0) {
2836 th_arc -= 2 * Math.PI;
2837 }
2838
2839 var segments = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001)));
2840 var result = [];
2841
2842 for (var i = 0; i < segments; i++) {
2843 var th2 = th0 + i * th_arc / segments;
2844 var th3 = th0 + (i + 1) * th_arc / segments;
2845 result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th];
2846 }
2847
2848 return result;
2849};
2850
2851var segmentToBezier = function segmentToBezier(cx, cy, th0, th1, rx, ry, sin_th, cos_th) {
2852 var a00 = cos_th * rx;
2853 var a01 = -sin_th * ry;
2854 var a10 = sin_th * rx;
2855 var a11 = cos_th * ry;
2856 var th_half = 0.5 * (th1 - th0);
2857 var t = 8 / 3 * Math.sin(th_half * 0.5) * Math.sin(th_half * 0.5) / Math.sin(th_half);
2858 var x1 = cx + Math.cos(th0) - t * Math.sin(th0);
2859 var y1 = cy + Math.sin(th0) + t * Math.cos(th0);
2860 var x3 = cx + Math.cos(th1);
2861 var y3 = cy + Math.sin(th1);
2862 var x2 = x3 + t * Math.sin(th1);
2863 var y2 = y3 - t * Math.cos(th1);
2864 return [a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3];
2865};
2866
2867var SVGPath = /*#__PURE__*/function () {
2868 function SVGPath() {
2869 _classCallCheck(this, SVGPath);
2870 }
2871
2872 _createClass(SVGPath, null, [{
2873 key: "apply",
2874 value: function apply(doc, path) {
2875 var commands = parse(path);
2876
2877 _apply(commands, doc);
2878 }
2879 }]);
2880
2881 return SVGPath;
2882}();
2883
2884var number$1 = PDFObject.number; // This constant is used to approximate a symmetrical arc using a cubic
2885// Bezier curve.
2886
2887var KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0);
2888var VectorMixin = {
2889 initVector: function initVector() {
2890 this._ctm = [1, 0, 0, 1, 0, 0]; // current transformation matrix
2891
2892 return this._ctmStack = [];
2893 },
2894 save: function save() {
2895 this._ctmStack.push(this._ctm.slice()); // TODO: save/restore colorspace and styles so not setting it unnessesarily all the time?
2896
2897
2898 return this.addContent('q');
2899 },
2900 restore: function restore() {
2901 this._ctm = this._ctmStack.pop() || [1, 0, 0, 1, 0, 0];
2902 return this.addContent('Q');
2903 },
2904 closePath: function closePath() {
2905 return this.addContent('h');
2906 },
2907 lineWidth: function lineWidth(w) {
2908 return this.addContent("".concat(number$1(w), " w"));
2909 },
2910 _CAP_STYLES: {
2911 BUTT: 0,
2912 ROUND: 1,
2913 SQUARE: 2
2914 },
2915 lineCap: function lineCap(c) {
2916 if (typeof c === 'string') {
2917 c = this._CAP_STYLES[c.toUpperCase()];
2918 }
2919
2920 return this.addContent("".concat(c, " J"));
2921 },
2922 _JOIN_STYLES: {
2923 MITER: 0,
2924 ROUND: 1,
2925 BEVEL: 2
2926 },
2927 lineJoin: function lineJoin(j) {
2928 if (typeof j === 'string') {
2929 j = this._JOIN_STYLES[j.toUpperCase()];
2930 }
2931
2932 return this.addContent("".concat(j, " j"));
2933 },
2934 miterLimit: function miterLimit(m) {
2935 return this.addContent("".concat(number$1(m), " M"));
2936 },
2937 dash: function dash(length) {
2938 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2939 var originalLength = length;
2940
2941 if (!Array.isArray(length)) {
2942 length = [length, options.space || length];
2943 }
2944
2945 var valid = length.every(function (x) {
2946 return Number.isFinite(x) && x > 0;
2947 });
2948
2949 if (!valid) {
2950 throw new Error("dash(".concat(JSON.stringify(originalLength), ", ").concat(JSON.stringify(options), ") invalid, lengths must be numeric and greater than zero"));
2951 }
2952
2953 length = length.map(number$1).join(' ');
2954 return this.addContent("[".concat(length, "] ").concat(number$1(options.phase || 0), " d"));
2955 },
2956 undash: function undash() {
2957 return this.addContent('[] 0 d');
2958 },
2959 moveTo: function moveTo(x, y) {
2960 return this.addContent("".concat(number$1(x), " ").concat(number$1(y), " m"));
2961 },
2962 lineTo: function lineTo(x, y) {
2963 return this.addContent("".concat(number$1(x), " ").concat(number$1(y), " l"));
2964 },
2965 bezierCurveTo: function bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) {
2966 return this.addContent("".concat(number$1(cp1x), " ").concat(number$1(cp1y), " ").concat(number$1(cp2x), " ").concat(number$1(cp2y), " ").concat(number$1(x), " ").concat(number$1(y), " c"));
2967 },
2968 quadraticCurveTo: function quadraticCurveTo(cpx, cpy, x, y) {
2969 return this.addContent("".concat(number$1(cpx), " ").concat(number$1(cpy), " ").concat(number$1(x), " ").concat(number$1(y), " v"));
2970 },
2971 rect: function rect(x, y, w, h) {
2972 return this.addContent("".concat(number$1(x), " ").concat(number$1(y), " ").concat(number$1(w), " ").concat(number$1(h), " re"));
2973 },
2974 roundedRect: function roundedRect(x, y, w, h, r) {
2975 if (r == null) {
2976 r = 0;
2977 }
2978
2979 r = Math.min(r, 0.5 * w, 0.5 * h); // amount to inset control points from corners (see `ellipse`)
2980
2981 var c = r * (1.0 - KAPPA);
2982 this.moveTo(x + r, y);
2983 this.lineTo(x + w - r, y);
2984 this.bezierCurveTo(x + w - c, y, x + w, y + c, x + w, y + r);
2985 this.lineTo(x + w, y + h - r);
2986 this.bezierCurveTo(x + w, y + h - c, x + w - c, y + h, x + w - r, y + h);
2987 this.lineTo(x + r, y + h);
2988 this.bezierCurveTo(x + c, y + h, x, y + h - c, x, y + h - r);
2989 this.lineTo(x, y + r);
2990 this.bezierCurveTo(x, y + c, x + c, y, x + r, y);
2991 return this.closePath();
2992 },
2993 ellipse: function ellipse(x, y, r1, r2) {
2994 // based on http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas/2173084#2173084
2995 if (r2 == null) {
2996 r2 = r1;
2997 }
2998
2999 x -= r1;
3000 y -= r2;
3001 var ox = r1 * KAPPA;
3002 var oy = r2 * KAPPA;
3003 var xe = x + r1 * 2;
3004 var ye = y + r2 * 2;
3005 var xm = x + r1;
3006 var ym = y + r2;
3007 this.moveTo(x, ym);
3008 this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
3009 this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
3010 this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
3011 this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
3012 return this.closePath();
3013 },
3014 circle: function circle(x, y, radius) {
3015 return this.ellipse(x, y, radius);
3016 },
3017 arc: function arc(x, y, radius, startAngle, endAngle, anticlockwise) {
3018 if (anticlockwise == null) {
3019 anticlockwise = false;
3020 }
3021
3022 var TWO_PI = 2.0 * Math.PI;
3023 var HALF_PI = 0.5 * Math.PI;
3024 var deltaAng = endAngle - startAngle;
3025
3026 if (Math.abs(deltaAng) > TWO_PI) {
3027 // draw only full circle if more than that is specified
3028 deltaAng = TWO_PI;
3029 } else if (deltaAng !== 0 && anticlockwise !== deltaAng < 0) {
3030 // necessary to flip direction of rendering
3031 var dir = anticlockwise ? -1 : 1;
3032 deltaAng = dir * TWO_PI + deltaAng;
3033 }
3034
3035 var numSegs = Math.ceil(Math.abs(deltaAng) / HALF_PI);
3036 var segAng = deltaAng / numSegs;
3037 var handleLen = segAng / HALF_PI * KAPPA * radius;
3038 var curAng = startAngle; // component distances between anchor point and control point
3039
3040 var deltaCx = -Math.sin(curAng) * handleLen;
3041 var deltaCy = Math.cos(curAng) * handleLen; // anchor point
3042
3043 var ax = x + Math.cos(curAng) * radius;
3044 var ay = y + Math.sin(curAng) * radius; // calculate and render segments
3045
3046 this.moveTo(ax, ay);
3047
3048 for (var segIdx = 0; segIdx < numSegs; segIdx++) {
3049 // starting control point
3050 var cp1x = ax + deltaCx;
3051 var cp1y = ay + deltaCy; // step angle
3052
3053 curAng += segAng; // next anchor point
3054
3055 ax = x + Math.cos(curAng) * radius;
3056 ay = y + Math.sin(curAng) * radius; // next control point delta
3057
3058 deltaCx = -Math.sin(curAng) * handleLen;
3059 deltaCy = Math.cos(curAng) * handleLen; // ending control point
3060
3061 var cp2x = ax - deltaCx;
3062 var cp2y = ay - deltaCy; // render segment
3063
3064 this.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, ax, ay);
3065 }
3066
3067 return this;
3068 },
3069 polygon: function polygon() {
3070 for (var _len = arguments.length, points = new Array(_len), _key = 0; _key < _len; _key++) {
3071 points[_key] = arguments[_key];
3072 }
3073
3074 this.moveTo.apply(this, _toConsumableArray(points.shift() || []));
3075
3076 for (var _i = 0, _points = points; _i < _points.length; _i++) {
3077 var point = _points[_i];
3078 this.lineTo.apply(this, _toConsumableArray(point || []));
3079 }
3080
3081 return this.closePath();
3082 },
3083 path: function path(_path) {
3084 SVGPath.apply(this, _path);
3085 return this;
3086 },
3087 _windingRule: function _windingRule(rule) {
3088 if (/even-?odd/.test(rule)) {
3089 return '*';
3090 }
3091
3092 return '';
3093 },
3094 fill: function fill(color, rule) {
3095 if (/(even-?odd)|(non-?zero)/.test(color)) {
3096 rule = color;
3097 color = null;
3098 }
3099
3100 if (color) {
3101 this.fillColor(color);
3102 }
3103
3104 return this.addContent("f".concat(this._windingRule(rule)));
3105 },
3106 stroke: function stroke(color) {
3107 if (color) {
3108 this.strokeColor(color);
3109 }
3110
3111 return this.addContent('S');
3112 },
3113 fillAndStroke: function fillAndStroke(fillColor, strokeColor, rule) {
3114 if (strokeColor == null) {
3115 strokeColor = fillColor;
3116 }
3117
3118 var isFillRule = /(even-?odd)|(non-?zero)/;
3119
3120 if (isFillRule.test(fillColor)) {
3121 rule = fillColor;
3122 fillColor = null;
3123 }
3124
3125 if (isFillRule.test(strokeColor)) {
3126 rule = strokeColor;
3127 strokeColor = fillColor;
3128 }
3129
3130 if (fillColor) {
3131 this.fillColor(fillColor);
3132 this.strokeColor(strokeColor);
3133 }
3134
3135 return this.addContent("B".concat(this._windingRule(rule)));
3136 },
3137 clip: function clip(rule) {
3138 return this.addContent("W".concat(this._windingRule(rule), " n"));
3139 },
3140 transform: function transform(m11, m12, m21, m22, dx, dy) {
3141 // keep track of the current transformation matrix
3142 if (m11 === 1 && m12 === 0 && m21 === 0 && m22 === 1 && dx === 0 && dy === 0) {
3143 // Ignore identity transforms
3144 return this;
3145 }
3146
3147 var m = this._ctm;
3148
3149 var _m = _slicedToArray(m, 6),
3150 m0 = _m[0],
3151 m1 = _m[1],
3152 m2 = _m[2],
3153 m3 = _m[3],
3154 m4 = _m[4],
3155 m5 = _m[5];
3156
3157 m[0] = m0 * m11 + m2 * m12;
3158 m[1] = m1 * m11 + m3 * m12;
3159 m[2] = m0 * m21 + m2 * m22;
3160 m[3] = m1 * m21 + m3 * m22;
3161 m[4] = m0 * dx + m2 * dy + m4;
3162 m[5] = m1 * dx + m3 * dy + m5;
3163 var values = [m11, m12, m21, m22, dx, dy].map(function (v) {
3164 return number$1(v);
3165 }).join(' ');
3166 return this.addContent("".concat(values, " cm"));
3167 },
3168 translate: function translate(x, y) {
3169 return this.transform(1, 0, 0, 1, x, y);
3170 },
3171 rotate: function rotate(angle) {
3172 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
3173 var y;
3174 var rad = angle * Math.PI / 180;
3175 var cos = Math.cos(rad);
3176 var sin = Math.sin(rad);
3177 var x = y = 0;
3178
3179 if (options.origin != null) {
3180 var _options$origin = _slicedToArray(options.origin, 2);
3181
3182 x = _options$origin[0];
3183 y = _options$origin[1];
3184 var x1 = x * cos - y * sin;
3185 var y1 = x * sin + y * cos;
3186 x -= x1;
3187 y -= y1;
3188 }
3189
3190 return this.transform(cos, sin, -sin, cos, x, y);
3191 },
3192 scale: function scale(xFactor, yFactor) {
3193 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
3194 var y;
3195
3196 if (yFactor == null) {
3197 yFactor = xFactor;
3198 }
3199
3200 if (typeof yFactor === 'object') {
3201 options = yFactor;
3202 yFactor = xFactor;
3203 }
3204
3205 var x = y = 0;
3206
3207 if (options.origin != null) {
3208 var _options$origin2 = _slicedToArray(options.origin, 2);
3209
3210 x = _options$origin2[0];
3211 y = _options$origin2[1];
3212 x -= xFactor * x;
3213 y -= yFactor * y;
3214 }
3215
3216 return this.transform(xFactor, 0, 0, yFactor, x, y);
3217 }
3218};
3219
3220var WIN_ANSI_MAP = {
3221 402: 131,
3222 8211: 150,
3223 8212: 151,
3224 8216: 145,
3225 8217: 146,
3226 8218: 130,
3227 8220: 147,
3228 8221: 148,
3229 8222: 132,
3230 8224: 134,
3231 8225: 135,
3232 8226: 149,
3233 8230: 133,
3234 8364: 128,
3235 8240: 137,
3236 8249: 139,
3237 8250: 155,
3238 710: 136,
3239 8482: 153,
3240 338: 140,
3241 339: 156,
3242 732: 152,
3243 352: 138,
3244 353: 154,
3245 376: 159,
3246 381: 142,
3247 382: 158
3248};
3249var characters = ".notdef .notdef .notdef .notdef\n.notdef .notdef .notdef .notdef\n.notdef .notdef .notdef .notdef\n.notdef .notdef .notdef .notdef\n.notdef .notdef .notdef .notdef\n.notdef .notdef .notdef .notdef\n.notdef .notdef .notdef .notdef\n.notdef .notdef .notdef .notdef\n \nspace exclam quotedbl numbersign\ndollar percent ampersand quotesingle\nparenleft parenright asterisk plus\ncomma hyphen period slash\nzero one two three\nfour five six seven\neight nine colon semicolon\nless equal greater question\n \nat A B C\nD E F G\nH I J K\nL M N O\nP Q R S\nT U V W\nX Y Z bracketleft\nbackslash bracketright asciicircum underscore\n \ngrave a b c\nd e f g\nh i j k\nl m n o\np q r s\nt u v w\nx y z braceleft\nbar braceright asciitilde .notdef\n \nEuro .notdef quotesinglbase florin\nquotedblbase ellipsis dagger daggerdbl\ncircumflex perthousand Scaron guilsinglleft\nOE .notdef Zcaron .notdef\n.notdef quoteleft quoteright quotedblleft\nquotedblright bullet endash emdash\ntilde trademark scaron guilsinglright\noe .notdef zcaron ydieresis\n \nspace exclamdown cent sterling\ncurrency yen brokenbar section\ndieresis copyright ordfeminine guillemotleft\nlogicalnot hyphen registered macron\ndegree plusminus twosuperior threesuperior\nacute mu paragraph periodcentered\ncedilla onesuperior ordmasculine guillemotright\nonequarter onehalf threequarters questiondown\n \nAgrave Aacute Acircumflex Atilde\nAdieresis Aring AE Ccedilla\nEgrave Eacute Ecircumflex Edieresis\nIgrave Iacute Icircumflex Idieresis\nEth Ntilde Ograve Oacute\nOcircumflex Otilde Odieresis multiply\nOslash Ugrave Uacute Ucircumflex\nUdieresis Yacute Thorn germandbls\n \nagrave aacute acircumflex atilde\nadieresis aring ae ccedilla\negrave eacute ecircumflex edieresis\nigrave iacute icircumflex idieresis\neth ntilde ograve oacute\nocircumflex otilde odieresis divide\noslash ugrave uacute ucircumflex\nudieresis yacute thorn ydieresis".split(/\s+/);
3250
3251var AFMFont = /*#__PURE__*/function () {
3252 _createClass(AFMFont, null, [{
3253 key: "open",
3254 value: function open(filename) {
3255 return new AFMFont(fs.readFileSync(filename, 'utf8'));
3256 }
3257 }]);
3258
3259 function AFMFont(contents) {
3260 _classCallCheck(this, AFMFont);
3261
3262 this.contents = contents;
3263 this.attributes = {};
3264 this.glyphWidths = {};
3265 this.boundingBoxes = {};
3266 this.kernPairs = {};
3267 this.parse(); // todo: remove charWidths since appears to not be used
3268
3269 this.charWidths = new Array(256);
3270
3271 for (var char = 0; char <= 255; char++) {
3272 this.charWidths[char] = this.glyphWidths[characters[char]];
3273 }
3274
3275 this.bbox = this.attributes['FontBBox'].split(/\s+/).map(function (e) {
3276 return +e;
3277 });
3278 this.ascender = +(this.attributes['Ascender'] || 0);
3279 this.descender = +(this.attributes['Descender'] || 0);
3280 this.xHeight = +(this.attributes['XHeight'] || 0);
3281 this.capHeight = +(this.attributes['CapHeight'] || 0);
3282 this.lineGap = this.bbox[3] - this.bbox[1] - (this.ascender - this.descender);
3283 }
3284
3285 _createClass(AFMFont, [{
3286 key: "parse",
3287 value: function parse() {
3288 var section = '';
3289
3290 var _iterator = _createForOfIteratorHelper(this.contents.split('\n')),
3291 _step;
3292
3293 try {
3294 for (_iterator.s(); !(_step = _iterator.n()).done;) {
3295 var line = _step.value;
3296 var match;
3297 var a;
3298
3299 if (match = line.match(/^Start(\w+)/)) {
3300 section = match[1];
3301 continue;
3302 } else if (match = line.match(/^End(\w+)/)) {
3303 section = '';
3304 continue;
3305 }
3306
3307 switch (section) {
3308 case 'FontMetrics':
3309 match = line.match(/(^\w+)\s+(.*)/);
3310 var key = match[1];
3311 var value = match[2];
3312
3313 if (a = this.attributes[key]) {
3314 if (!Array.isArray(a)) {
3315 a = this.attributes[key] = [a];
3316 }
3317
3318 a.push(value);
3319 } else {
3320 this.attributes[key] = value;
3321 }
3322
3323 break;
3324
3325 case 'CharMetrics':
3326 if (!/^CH?\s/.test(line)) {
3327 continue;
3328 }
3329
3330 var name = line.match(/\bN\s+(\.?\w+)\s*;/)[1];
3331 this.glyphWidths[name] = +line.match(/\bWX\s+(\d+)\s*;/)[1];
3332 break;
3333
3334 case 'KernPairs':
3335 match = line.match(/^KPX\s+(\.?\w+)\s+(\.?\w+)\s+(-?\d+)/);
3336
3337 if (match) {
3338 this.kernPairs[match[1] + '\0' + match[2]] = parseInt(match[3]);
3339 }
3340
3341 break;
3342 }
3343 }
3344 } catch (err) {
3345 _iterator.e(err);
3346 } finally {
3347 _iterator.f();
3348 }
3349 }
3350 }, {
3351 key: "encodeText",
3352 value: function encodeText(text) {
3353 var res = [];
3354
3355 for (var i = 0, len = text.length; i < len; i++) {
3356 var char = text.charCodeAt(i);
3357 char = WIN_ANSI_MAP[char] || char;
3358 res.push(char.toString(16));
3359 }
3360
3361 return res;
3362 }
3363 }, {
3364 key: "glyphsForString",
3365 value: function glyphsForString(string) {
3366 var glyphs = [];
3367
3368 for (var i = 0, len = string.length; i < len; i++) {
3369 var charCode = string.charCodeAt(i);
3370 glyphs.push(this.characterToGlyph(charCode));
3371 }
3372
3373 return glyphs;
3374 }
3375 }, {
3376 key: "characterToGlyph",
3377 value: function characterToGlyph(character) {
3378 return characters[WIN_ANSI_MAP[character] || character] || '.notdef';
3379 }
3380 }, {
3381 key: "widthOfGlyph",
3382 value: function widthOfGlyph(glyph) {
3383 return this.glyphWidths[glyph] || 0;
3384 }
3385 }, {
3386 key: "getKernPair",
3387 value: function getKernPair(left, right) {
3388 return this.kernPairs[left + '\0' + right] || 0;
3389 }
3390 }, {
3391 key: "advancesForGlyphs",
3392 value: function advancesForGlyphs(glyphs) {
3393 var advances = [];
3394
3395 for (var index = 0; index < glyphs.length; index++) {
3396 var left = glyphs[index];
3397 var right = glyphs[index + 1];
3398 advances.push(this.widthOfGlyph(left) + this.getKernPair(left, right));
3399 }
3400
3401 return advances;
3402 }
3403 }]);
3404
3405 return AFMFont;
3406}();
3407
3408var PDFFont = /*#__PURE__*/function () {
3409 function PDFFont() {
3410 _classCallCheck(this, PDFFont);
3411 }
3412
3413 _createClass(PDFFont, [{
3414 key: "encode",
3415 value: function encode() {
3416 throw new Error('Must be implemented by subclasses');
3417 }
3418 }, {
3419 key: "widthOfString",
3420 value: function widthOfString() {
3421 throw new Error('Must be implemented by subclasses');
3422 }
3423 }, {
3424 key: "ref",
3425 value: function ref() {
3426 return this.dictionary != null ? this.dictionary : this.dictionary = this.document.ref();
3427 }
3428 }, {
3429 key: "finalize",
3430 value: function finalize() {
3431 if (this.embedded || this.dictionary == null) {
3432 return;
3433 }
3434
3435 this.embed();
3436 return this.embedded = true;
3437 }
3438 }, {
3439 key: "embed",
3440 value: function embed() {
3441 throw new Error('Must be implemented by subclasses');
3442 }
3443 }, {
3444 key: "lineHeight",
3445 value: function lineHeight(size, includeGap) {
3446 if (includeGap == null) {
3447 includeGap = false;
3448 }
3449
3450 var gap = includeGap ? this.lineGap : 0;
3451 return (this.ascender + gap - this.descender) / 1000 * size;
3452 }
3453 }]);
3454
3455 return PDFFont;
3456}();
3457
3458var STANDARD_FONTS = {
3459 Courier: function Courier() {
3460 return fs.readFileSync(__dirname + '/data/Courier.afm', 'utf8');
3461 },
3462 'Courier-Bold': function CourierBold() {
3463 return fs.readFileSync(__dirname + '/data/Courier-Bold.afm', 'utf8');
3464 },
3465 'Courier-Oblique': function CourierOblique() {
3466 return fs.readFileSync(__dirname + '/data/Courier-Oblique.afm', 'utf8');
3467 },
3468 'Courier-BoldOblique': function CourierBoldOblique() {
3469 return fs.readFileSync(__dirname + '/data/Courier-BoldOblique.afm', 'utf8');
3470 },
3471 Helvetica: function Helvetica() {
3472 return fs.readFileSync(__dirname + '/data/Helvetica.afm', 'utf8');
3473 },
3474 'Helvetica-Bold': function HelveticaBold() {
3475 return fs.readFileSync(__dirname + '/data/Helvetica-Bold.afm', 'utf8');
3476 },
3477 'Helvetica-Oblique': function HelveticaOblique() {
3478 return fs.readFileSync(__dirname + '/data/Helvetica-Oblique.afm', 'utf8');
3479 },
3480 'Helvetica-BoldOblique': function HelveticaBoldOblique() {
3481 return fs.readFileSync(__dirname + '/data/Helvetica-BoldOblique.afm', 'utf8');
3482 },
3483 'Times-Roman': function TimesRoman() {
3484 return fs.readFileSync(__dirname + '/data/Times-Roman.afm', 'utf8');
3485 },
3486 'Times-Bold': function TimesBold() {
3487 return fs.readFileSync(__dirname + '/data/Times-Bold.afm', 'utf8');
3488 },
3489 'Times-Italic': function TimesItalic() {
3490 return fs.readFileSync(__dirname + '/data/Times-Italic.afm', 'utf8');
3491 },
3492 'Times-BoldItalic': function TimesBoldItalic() {
3493 return fs.readFileSync(__dirname + '/data/Times-BoldItalic.afm', 'utf8');
3494 },
3495 Symbol: function Symbol() {
3496 return fs.readFileSync(__dirname + '/data/Symbol.afm', 'utf8');
3497 },
3498 ZapfDingbats: function ZapfDingbats() {
3499 return fs.readFileSync(__dirname + '/data/ZapfDingbats.afm', 'utf8');
3500 }
3501};
3502
3503var StandardFont = /*#__PURE__*/function (_PDFFont) {
3504 _inherits(StandardFont, _PDFFont);
3505
3506 var _super = _createSuper(StandardFont);
3507
3508 function StandardFont(document, name, id) {
3509 var _this;
3510
3511 _classCallCheck(this, StandardFont);
3512
3513 _this = _super.call(this);
3514 _this.document = document;
3515 _this.name = name;
3516 _this.id = id;
3517 _this.font = new AFMFont(STANDARD_FONTS[_this.name]());
3518 var _this$font = _this.font;
3519 _this.ascender = _this$font.ascender;
3520 _this.descender = _this$font.descender;
3521 _this.bbox = _this$font.bbox;
3522 _this.lineGap = _this$font.lineGap;
3523 _this.xHeight = _this$font.xHeight;
3524 _this.capHeight = _this$font.capHeight;
3525 return _this;
3526 }
3527
3528 _createClass(StandardFont, [{
3529 key: "embed",
3530 value: function embed() {
3531 this.dictionary.data = {
3532 Type: 'Font',
3533 BaseFont: this.name,
3534 Subtype: 'Type1',
3535 Encoding: 'WinAnsiEncoding'
3536 };
3537 return this.dictionary.end();
3538 }
3539 }, {
3540 key: "encode",
3541 value: function encode(text) {
3542 var encoded = this.font.encodeText(text);
3543 var glyphs = this.font.glyphsForString("".concat(text));
3544 var advances = this.font.advancesForGlyphs(glyphs);
3545 var positions = [];
3546
3547 for (var i = 0; i < glyphs.length; i++) {
3548 var glyph = glyphs[i];
3549 positions.push({
3550 xAdvance: advances[i],
3551 yAdvance: 0,
3552 xOffset: 0,
3553 yOffset: 0,
3554 advanceWidth: this.font.widthOfGlyph(glyph)
3555 });
3556 }
3557
3558 return [encoded, positions];
3559 }
3560 }, {
3561 key: "widthOfString",
3562 value: function widthOfString(string, size) {
3563 var glyphs = this.font.glyphsForString("".concat(string));
3564 var advances = this.font.advancesForGlyphs(glyphs);
3565 var width = 0;
3566
3567 var _iterator = _createForOfIteratorHelper(advances),
3568 _step;
3569
3570 try {
3571 for (_iterator.s(); !(_step = _iterator.n()).done;) {
3572 var advance = _step.value;
3573 width += advance;
3574 }
3575 } catch (err) {
3576 _iterator.e(err);
3577 } finally {
3578 _iterator.f();
3579 }
3580
3581 var scale = size / 1000;
3582 return width * scale;
3583 }
3584 }], [{
3585 key: "isStandardFont",
3586 value: function isStandardFont(name) {
3587 return name in STANDARD_FONTS;
3588 }
3589 }]);
3590
3591 return StandardFont;
3592}(PDFFont);
3593
3594var toHex = function toHex(num) {
3595 return "0000".concat(num.toString(16)).slice(-4);
3596};
3597
3598var EmbeddedFont = /*#__PURE__*/function (_PDFFont) {
3599 _inherits(EmbeddedFont, _PDFFont);
3600
3601 var _super = _createSuper(EmbeddedFont);
3602
3603 function EmbeddedFont(document, font, id) {
3604 var _this;
3605
3606 _classCallCheck(this, EmbeddedFont);
3607
3608 _this = _super.call(this);
3609 _this.document = document;
3610 _this.font = font;
3611 _this.id = id;
3612 _this.subset = _this.font.createSubset();
3613 _this.unicode = [[0]];
3614 _this.widths = [_this.font.getGlyph(0).advanceWidth];
3615 _this.name = _this.font.postscriptName;
3616 _this.scale = 1000 / _this.font.unitsPerEm;
3617 _this.ascender = _this.font.ascent * _this.scale;
3618 _this.descender = _this.font.descent * _this.scale;
3619 _this.xHeight = _this.font.xHeight * _this.scale;
3620 _this.capHeight = _this.font.capHeight * _this.scale;
3621 _this.lineGap = _this.font.lineGap * _this.scale;
3622 _this.bbox = _this.font.bbox;
3623
3624 if (document.options.fontLayoutCache !== false) {
3625 _this.layoutCache = Object.create(null);
3626 }
3627
3628 return _this;
3629 }
3630
3631 _createClass(EmbeddedFont, [{
3632 key: "layoutRun",
3633 value: function layoutRun(text, features) {
3634 var run = this.font.layout(text, features); // Normalize position values
3635
3636 for (var i = 0; i < run.positions.length; i++) {
3637 var position = run.positions[i];
3638
3639 for (var key in position) {
3640 position[key] *= this.scale;
3641 }
3642
3643 position.advanceWidth = run.glyphs[i].advanceWidth * this.scale;
3644 }
3645
3646 return run;
3647 }
3648 }, {
3649 key: "layoutCached",
3650 value: function layoutCached(text) {
3651 if (!this.layoutCache) {
3652 return this.layoutRun(text);
3653 }
3654
3655 var cached;
3656
3657 if (cached = this.layoutCache[text]) {
3658 return cached;
3659 }
3660
3661 var run = this.layoutRun(text);
3662 this.layoutCache[text] = run;
3663 return run;
3664 }
3665 }, {
3666 key: "layout",
3667 value: function layout(text, features, onlyWidth) {
3668 // Skip the cache if any user defined features are applied
3669 if (features) {
3670 return this.layoutRun(text, features);
3671 }
3672
3673 var glyphs = onlyWidth ? null : [];
3674 var positions = onlyWidth ? null : [];
3675 var advanceWidth = 0; // Split the string by words to increase cache efficiency.
3676 // For this purpose, spaces and tabs are a good enough delimeter.
3677
3678 var last = 0;
3679 var index = 0;
3680
3681 while (index <= text.length) {
3682 var needle;
3683
3684 if (index === text.length && last < index || (needle = text.charAt(index), [' ', '\t'].includes(needle))) {
3685 var run = this.layoutCached(text.slice(last, ++index));
3686
3687 if (!onlyWidth) {
3688 glyphs = glyphs.concat(run.glyphs);
3689 positions = positions.concat(run.positions);
3690 }
3691
3692 advanceWidth += run.advanceWidth;
3693 last = index;
3694 } else {
3695 index++;
3696 }
3697 }
3698
3699 return {
3700 glyphs: glyphs,
3701 positions: positions,
3702 advanceWidth: advanceWidth
3703 };
3704 }
3705 }, {
3706 key: "encode",
3707 value: function encode(text, features) {
3708 var _this$layout = this.layout(text, features),
3709 glyphs = _this$layout.glyphs,
3710 positions = _this$layout.positions;
3711
3712 var res = [];
3713
3714 for (var i = 0; i < glyphs.length; i++) {
3715 var glyph = glyphs[i];
3716 var gid = this.subset.includeGlyph(glyph.id);
3717 res.push("0000".concat(gid.toString(16)).slice(-4));
3718
3719 if (this.widths[gid] == null) {
3720 this.widths[gid] = glyph.advanceWidth * this.scale;
3721 }
3722
3723 if (this.unicode[gid] == null) {
3724 this.unicode[gid] = glyph.codePoints;
3725 }
3726 }
3727
3728 return [res, positions];
3729 }
3730 }, {
3731 key: "widthOfString",
3732 value: function widthOfString(string, size, features) {
3733 var width = this.layout(string, features, true).advanceWidth;
3734 var scale = size / 1000;
3735 return width * scale;
3736 }
3737 }, {
3738 key: "embed",
3739 value: function embed() {
3740 var _this2 = this;
3741
3742 var isCFF = this.subset.cff != null;
3743 var fontFile = this.document.ref();
3744
3745 if (isCFF) {
3746 fontFile.data.Subtype = 'CIDFontType0C';
3747 }
3748
3749 this.subset.encodeStream().on('data', function (data) {
3750 return fontFile.write(data);
3751 }).on('end', function () {
3752 return fontFile.end();
3753 });
3754 var familyClass = ((this.font['OS/2'] != null ? this.font['OS/2'].sFamilyClass : undefined) || 0) >> 8;
3755 var flags = 0;
3756
3757 if (this.font.post.isFixedPitch) {
3758 flags |= 1 << 0;
3759 }
3760
3761 if (1 <= familyClass && familyClass <= 7) {
3762 flags |= 1 << 1;
3763 }
3764
3765 flags |= 1 << 2; // assume the font uses non-latin characters
3766
3767 if (familyClass === 10) {
3768 flags |= 1 << 3;
3769 }
3770
3771 if (this.font.head.macStyle.italic) {
3772 flags |= 1 << 6;
3773 } // generate a tag (6 uppercase letters. 17 is the char code offset from '0' to 'A'. 73 will map to 'Z')
3774
3775
3776 var tag = [1, 2, 3, 4, 5, 6].map(function (i) {
3777 return String.fromCharCode((_this2.id.charCodeAt(i) || 73) + 17);
3778 }).join('');
3779 var name = tag + '+' + this.font.postscriptName;
3780 var bbox = this.font.bbox;
3781 var descriptor = this.document.ref({
3782 Type: 'FontDescriptor',
3783 FontName: name,
3784 Flags: flags,
3785 FontBBox: [bbox.minX * this.scale, bbox.minY * this.scale, bbox.maxX * this.scale, bbox.maxY * this.scale],
3786 ItalicAngle: this.font.italicAngle,
3787 Ascent: this.ascender,
3788 Descent: this.descender,
3789 CapHeight: (this.font.capHeight || this.font.ascent) * this.scale,
3790 XHeight: (this.font.xHeight || 0) * this.scale,
3791 StemV: 0
3792 }); // not sure how to calculate this
3793
3794 if (isCFF) {
3795 descriptor.data.FontFile3 = fontFile;
3796 } else {
3797 descriptor.data.FontFile2 = fontFile;
3798 }
3799
3800 if (this.document.subset) {
3801 var CIDSet = Buffer.from('FFFFFFFFC0', 'hex');
3802 var CIDSetRef = this.document.ref();
3803 CIDSetRef.write(CIDSet);
3804 CIDSetRef.end();
3805 descriptor.data.CIDSet = CIDSetRef;
3806 }
3807
3808 descriptor.end();
3809 var descendantFontData = {
3810 Type: 'Font',
3811 Subtype: 'CIDFontType0',
3812 BaseFont: name,
3813 CIDSystemInfo: {
3814 Registry: new String('Adobe'),
3815 Ordering: new String('Identity'),
3816 Supplement: 0
3817 },
3818 FontDescriptor: descriptor,
3819 W: [0, this.widths]
3820 };
3821
3822 if (!isCFF) {
3823 descendantFontData.Subtype = 'CIDFontType2';
3824 descendantFontData.CIDToGIDMap = 'Identity';
3825 }
3826
3827 var descendantFont = this.document.ref(descendantFontData);
3828 descendantFont.end();
3829 this.dictionary.data = {
3830 Type: 'Font',
3831 Subtype: 'Type0',
3832 BaseFont: name,
3833 Encoding: 'Identity-H',
3834 DescendantFonts: [descendantFont],
3835 ToUnicode: this.toUnicodeCmap()
3836 };
3837 return this.dictionary.end();
3838 } // Maps the glyph ids encoded in the PDF back to unicode strings
3839 // Because of ligature substitutions and the like, there may be one or more
3840 // unicode characters represented by each glyph.
3841
3842 }, {
3843 key: "toUnicodeCmap",
3844 value: function toUnicodeCmap() {
3845 var cmap = this.document.ref();
3846 var entries = [];
3847
3848 var _iterator = _createForOfIteratorHelper(this.unicode),
3849 _step;
3850
3851 try {
3852 for (_iterator.s(); !(_step = _iterator.n()).done;) {
3853 var codePoints = _step.value;
3854 var encoded = []; // encode codePoints to utf16
3855
3856 var _iterator2 = _createForOfIteratorHelper(codePoints),
3857 _step2;
3858
3859 try {
3860 for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
3861 var value = _step2.value;
3862
3863 if (value > 0xffff) {
3864 value -= 0x10000;
3865 encoded.push(toHex(value >>> 10 & 0x3ff | 0xd800));
3866 value = 0xdc00 | value & 0x3ff;
3867 }
3868
3869 encoded.push(toHex(value));
3870 }
3871 } catch (err) {
3872 _iterator2.e(err);
3873 } finally {
3874 _iterator2.f();
3875 }
3876
3877 entries.push("<".concat(encoded.join(' '), ">"));
3878 }
3879 } catch (err) {
3880 _iterator.e(err);
3881 } finally {
3882 _iterator.f();
3883 }
3884
3885 var chunkSize = 256;
3886 var chunks = Math.ceil(entries.length / chunkSize);
3887 var ranges = [];
3888
3889 for (var i = 0; i < chunks; i++) {
3890 var start = i * chunkSize;
3891 var end = Math.min((i + 1) * chunkSize, entries.length);
3892 ranges.push("<".concat(toHex(start), "> <").concat(toHex(end - 1), "> [").concat(entries.slice(start, end).join(' '), "]"));
3893 }
3894
3895 cmap.end("/CIDInit /ProcSet findresource begin\n12 dict begin\nbegincmap\n/CIDSystemInfo <<\n /Registry (Adobe)\n /Ordering (UCS)\n /Supplement 0\n>> def\n/CMapName /Adobe-Identity-UCS def\n/CMapType 2 def\n1 begincodespacerange\n<0000><ffff>\nendcodespacerange\n1 beginbfrange\n".concat(ranges.join('\n'), "\nendbfrange\nendcmap\nCMapName currentdict /CMap defineresource pop\nend\nend"));
3896 return cmap;
3897 }
3898 }]);
3899
3900 return EmbeddedFont;
3901}(PDFFont);
3902
3903var PDFFontFactory = /*#__PURE__*/function () {
3904 function PDFFontFactory() {
3905 _classCallCheck(this, PDFFontFactory);
3906 }
3907
3908 _createClass(PDFFontFactory, null, [{
3909 key: "open",
3910 value: function open(document, src, family, id) {
3911 var font;
3912
3913 if (typeof src === 'string') {
3914 if (StandardFont.isStandardFont(src)) {
3915 return new StandardFont(document, src, id);
3916 }
3917
3918 src = fs.readFileSync(src);
3919 }
3920
3921 if (Buffer.isBuffer(src)) {
3922 font = fontkit.create(src, family);
3923 } else if (src instanceof Uint8Array) {
3924 font = fontkit.create(Buffer.from(src), family);
3925 } else if (src instanceof ArrayBuffer) {
3926 font = fontkit.create(Buffer.from(new Uint8Array(src)), family);
3927 }
3928
3929 if (font == null) {
3930 throw new Error('Not a supported font format or standard PDF font.');
3931 }
3932
3933 return new EmbeddedFont(document, font, id);
3934 }
3935 }]);
3936
3937 return PDFFontFactory;
3938}();
3939
3940var FontsMixin = {
3941 initFonts: function initFonts() {
3942 var defaultFont = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Helvetica';
3943 // Lookup table for embedded fonts
3944 this._fontFamilies = {};
3945 this._fontCount = 0; // Font state
3946
3947 this._fontSize = 12;
3948 this._font = null;
3949 this._registeredFonts = {}; // Set the default font
3950
3951 if (defaultFont) {
3952 this.font(defaultFont);
3953 }
3954 },
3955 font: function font(src, family, size) {
3956 var cacheKey, font;
3957
3958 if (typeof family === 'number') {
3959 size = family;
3960 family = null;
3961 } // check registered fonts if src is a string
3962
3963
3964 if (typeof src === 'string' && this._registeredFonts[src]) {
3965 cacheKey = src;
3966 var _this$_registeredFont = this._registeredFonts[src];
3967 src = _this$_registeredFont.src;
3968 family = _this$_registeredFont.family;
3969 } else {
3970 cacheKey = family || src;
3971
3972 if (typeof cacheKey !== 'string') {
3973 cacheKey = null;
3974 }
3975 }
3976
3977 if (size != null) {
3978 this.fontSize(size);
3979 } // fast path: check if the font is already in the PDF
3980
3981
3982 if (font = this._fontFamilies[cacheKey]) {
3983 this._font = font;
3984 return this;
3985 } // load the font
3986
3987
3988 var id = "F".concat(++this._fontCount);
3989 this._font = PDFFontFactory.open(this, src, family, id); // check for existing font familes with the same name already in the PDF
3990 // useful if the font was passed as a buffer
3991
3992 if (font = this._fontFamilies[this._font.name]) {
3993 this._font = font;
3994 return this;
3995 } // save the font for reuse later
3996
3997
3998 if (cacheKey) {
3999 this._fontFamilies[cacheKey] = this._font;
4000 }
4001
4002 if (this._font.name) {
4003 this._fontFamilies[this._font.name] = this._font;
4004 }
4005
4006 return this;
4007 },
4008 fontSize: function fontSize(_fontSize) {
4009 this._fontSize = _fontSize;
4010 return this;
4011 },
4012 currentLineHeight: function currentLineHeight(includeGap) {
4013 if (includeGap == null) {
4014 includeGap = false;
4015 }
4016
4017 return this._font.lineHeight(this._fontSize, includeGap);
4018 },
4019 registerFont: function registerFont(name, src, family) {
4020 this._registeredFonts[name] = {
4021 src: src,
4022 family: family
4023 };
4024 return this;
4025 }
4026};
4027
4028var SOFT_HYPHEN = "\xAD";
4029var HYPHEN = '-';
4030
4031var LineWrapper = /*#__PURE__*/function (_EventEmitter) {
4032 _inherits(LineWrapper, _EventEmitter);
4033
4034 var _super = _createSuper(LineWrapper);
4035
4036 function LineWrapper(document, options) {
4037 var _this;
4038
4039 _classCallCheck(this, LineWrapper);
4040
4041 _this = _super.call(this);
4042 _this.document = document;
4043 _this.indent = options.indent || 0;
4044 _this.characterSpacing = options.characterSpacing || 0;
4045 _this.wordSpacing = options.wordSpacing === 0;
4046 _this.columns = options.columns || 1;
4047 _this.columnGap = options.columnGap != null ? options.columnGap : 18; // 1/4 inch
4048
4049 _this.lineWidth = (options.width - _this.columnGap * (_this.columns - 1)) / _this.columns;
4050 _this.spaceLeft = _this.lineWidth;
4051 _this.startX = _this.document.x;
4052 _this.startY = _this.document.y;
4053 _this.column = 1;
4054 _this.ellipsis = options.ellipsis;
4055 _this.continuedX = 0;
4056 _this.features = options.features; // calculate the maximum Y position the text can appear at
4057
4058 if (options.height != null) {
4059 _this.height = options.height;
4060 _this.maxY = _this.startY + options.height;
4061 } else {
4062 _this.maxY = _this.document.page.maxY();
4063 } // handle paragraph indents
4064
4065
4066 _this.on('firstLine', function (options) {
4067 // if this is the first line of the text segment, and
4068 // we're continuing where we left off, indent that much
4069 // otherwise use the user specified indent option
4070 var indent = _this.continuedX || _this.indent;
4071 _this.document.x += indent;
4072 _this.lineWidth -= indent;
4073 return _this.once('line', function () {
4074 _this.document.x -= indent;
4075 _this.lineWidth += indent;
4076
4077 if (options.continued && !_this.continuedX) {
4078 _this.continuedX = _this.indent;
4079 }
4080
4081 if (!options.continued) {
4082 return _this.continuedX = 0;
4083 }
4084 });
4085 }); // handle left aligning last lines of paragraphs
4086
4087
4088 _this.on('lastLine', function (options) {
4089 var align = options.align;
4090
4091 if (align === 'justify') {
4092 options.align = 'left';
4093 }
4094
4095 _this.lastLine = true;
4096 return _this.once('line', function () {
4097 _this.document.y += options.paragraphGap || 0;
4098 options.align = align;
4099 return _this.lastLine = false;
4100 });
4101 });
4102
4103 return _this;
4104 }
4105
4106 _createClass(LineWrapper, [{
4107 key: "wordWidth",
4108 value: function wordWidth(word) {
4109 return this.document.widthOfString(word, this) + this.characterSpacing + this.wordSpacing;
4110 }
4111 }, {
4112 key: "canFit",
4113 value: function canFit(word, w) {
4114 if (word[word.length - 1] != SOFT_HYPHEN) {
4115 return w <= this.spaceLeft;
4116 }
4117
4118 return w + this.wordWidth(HYPHEN) <= this.spaceLeft;
4119 }
4120 }, {
4121 key: "eachWord",
4122 value: function eachWord(text, fn) {
4123 // setup a unicode line breaker
4124 var bk;
4125 var breaker = new LineBreaker(text);
4126 var last = null;
4127 var wordWidths = Object.create(null);
4128
4129 while (bk = breaker.nextBreak()) {
4130 var shouldContinue;
4131 var word = text.slice((last != null ? last.position : undefined) || 0, bk.position);
4132 var w = wordWidths[word] != null ? wordWidths[word] : wordWidths[word] = this.wordWidth(word); // if the word is longer than the whole line, chop it up
4133 // TODO: break by grapheme clusters, not JS string characters
4134
4135 if (w > this.lineWidth + this.continuedX) {
4136 // make some fake break objects
4137 var lbk = last;
4138 var fbk = {};
4139
4140 while (word.length) {
4141 // fit as much of the word as possible into the space we have
4142 var l, mightGrow;
4143
4144 if (w > this.spaceLeft) {
4145 // start our check at the end of our available space - this method is faster than a loop of each character and it resolves
4146 // an issue with long loops when processing massive words, such as a huge number of spaces
4147 l = Math.ceil(this.spaceLeft / (w / word.length));
4148 w = this.wordWidth(word.slice(0, l));
4149 mightGrow = w <= this.spaceLeft && l < word.length;
4150 } else {
4151 l = word.length;
4152 }
4153
4154 var mustShrink = w > this.spaceLeft && l > 0; // shrink or grow word as necessary after our near-guess above
4155
4156 while (mustShrink || mightGrow) {
4157 if (mustShrink) {
4158 w = this.wordWidth(word.slice(0, --l));
4159 mustShrink = w > this.spaceLeft && l > 0;
4160 } else {
4161 w = this.wordWidth(word.slice(0, ++l));
4162 mustShrink = w > this.spaceLeft && l > 0;
4163 mightGrow = w <= this.spaceLeft && l < word.length;
4164 }
4165 } // check for the edge case where a single character cannot fit into a line.
4166
4167
4168 if (l === 0 && this.spaceLeft === this.lineWidth) {
4169 l = 1;
4170 } // send a required break unless this is the last piece and a linebreak is not specified
4171
4172
4173 fbk.required = bk.required || l < word.length;
4174 shouldContinue = fn(word.slice(0, l), w, fbk, lbk);
4175 lbk = {
4176 required: false
4177 }; // get the remaining piece of the word
4178
4179 word = word.slice(l);
4180 w = this.wordWidth(word);
4181
4182 if (shouldContinue === false) {
4183 break;
4184 }
4185 }
4186 } else {
4187 // otherwise just emit the break as it was given to us
4188 shouldContinue = fn(word, w, bk, last);
4189 }
4190
4191 if (shouldContinue === false) {
4192 break;
4193 }
4194
4195 last = bk;
4196 }
4197 }
4198 }, {
4199 key: "wrap",
4200 value: function wrap(text, options) {
4201 var _this2 = this;
4202
4203 // override options from previous continued fragments
4204 if (options.indent != null) {
4205 this.indent = options.indent;
4206 }
4207
4208 if (options.characterSpacing != null) {
4209 this.characterSpacing = options.characterSpacing;
4210 }
4211
4212 if (options.wordSpacing != null) {
4213 this.wordSpacing = options.wordSpacing;
4214 }
4215
4216 if (options.ellipsis != null) {
4217 this.ellipsis = options.ellipsis;
4218 } // make sure we're actually on the page
4219 // and that the first line of is never by
4220 // itself at the bottom of a page (orphans)
4221
4222
4223 var nextY = this.document.y + this.document.currentLineHeight(true);
4224
4225 if (this.document.y > this.maxY || nextY > this.maxY) {
4226 this.nextSection();
4227 }
4228
4229 var buffer = '';
4230 var textWidth = 0;
4231 var wc = 0;
4232 var lc = 0;
4233 var y = this.document.y; // used to reset Y pos if options.continued (below)
4234
4235 var emitLine = function emitLine() {
4236 options.textWidth = textWidth + _this2.wordSpacing * (wc - 1);
4237 options.wordCount = wc;
4238 options.lineWidth = _this2.lineWidth;
4239 y = _this2.document.y;
4240
4241 _this2.emit('line', buffer, options, _this2);
4242
4243 return lc++;
4244 };
4245
4246 this.emit('sectionStart', options, this);
4247 this.eachWord(text, function (word, w, bk, last) {
4248 if (last == null || last.required) {
4249 _this2.emit('firstLine', options, _this2);
4250
4251 _this2.spaceLeft = _this2.lineWidth;
4252 }
4253
4254 if (_this2.canFit(word, w)) {
4255 buffer += word;
4256 textWidth += w;
4257 wc++;
4258 }
4259
4260 if (bk.required || !_this2.canFit(word, w)) {
4261 // if the user specified a max height and an ellipsis, and is about to pass the
4262 // max height and max columns after the next line, append the ellipsis
4263 var lh = _this2.document.currentLineHeight(true);
4264
4265 if (_this2.height != null && _this2.ellipsis && _this2.document.y + lh * 2 > _this2.maxY && _this2.column >= _this2.columns) {
4266 if (_this2.ellipsis === true) {
4267 _this2.ellipsis = '…';
4268 } // map default ellipsis character
4269
4270
4271 buffer = buffer.replace(/\s+$/, '');
4272 textWidth = _this2.wordWidth(buffer + _this2.ellipsis); // remove characters from the buffer until the ellipsis fits
4273 // to avoid infinite loop need to stop while-loop if buffer is empty string
4274
4275 while (buffer && textWidth > _this2.lineWidth) {
4276 buffer = buffer.slice(0, -1).replace(/\s+$/, '');
4277 textWidth = _this2.wordWidth(buffer + _this2.ellipsis);
4278 } // need to add ellipsis only if there is enough space for it
4279
4280
4281 if (textWidth <= _this2.lineWidth) {
4282 buffer = buffer + _this2.ellipsis;
4283 }
4284
4285 textWidth = _this2.wordWidth(buffer);
4286 }
4287
4288 if (bk.required) {
4289 if (w > _this2.spaceLeft) {
4290 emitLine();
4291 buffer = word;
4292 textWidth = w;
4293 wc = 1;
4294 }
4295
4296 _this2.emit('lastLine', options, _this2);
4297 } // Previous entry is a soft hyphen - add visible hyphen.
4298
4299
4300 if (buffer[buffer.length - 1] == SOFT_HYPHEN) {
4301 buffer = buffer.slice(0, -1) + HYPHEN;
4302 _this2.spaceLeft -= _this2.wordWidth(HYPHEN);
4303 }
4304
4305 emitLine(); // if we've reached the edge of the page,
4306 // continue on a new page or column
4307
4308 if (_this2.document.y + lh > _this2.maxY) {
4309 var shouldContinue = _this2.nextSection(); // stop if we reached the maximum height
4310
4311
4312 if (!shouldContinue) {
4313 wc = 0;
4314 buffer = '';
4315 return false;
4316 }
4317 } // reset the space left and buffer
4318
4319
4320 if (bk.required) {
4321 _this2.spaceLeft = _this2.lineWidth;
4322 buffer = '';
4323 textWidth = 0;
4324 return wc = 0;
4325 } else {
4326 // reset the space left and buffer
4327 _this2.spaceLeft = _this2.lineWidth - w;
4328 buffer = word;
4329 textWidth = w;
4330 return wc = 1;
4331 }
4332 } else {
4333 return _this2.spaceLeft -= w;
4334 }
4335 });
4336
4337 if (wc > 0) {
4338 this.emit('lastLine', options, this);
4339 emitLine();
4340 }
4341
4342 this.emit('sectionEnd', options, this); // if the wrap is set to be continued, save the X position
4343 // to start the first line of the next segment at, and reset
4344 // the y position
4345
4346 if (options.continued === true) {
4347 if (lc > 1) {
4348 this.continuedX = 0;
4349 }
4350
4351 this.continuedX += options.textWidth || 0;
4352 return this.document.y = y;
4353 } else {
4354 return this.document.x = this.startX;
4355 }
4356 }
4357 }, {
4358 key: "nextSection",
4359 value: function nextSection(options) {
4360 this.emit('sectionEnd', options, this);
4361
4362 if (++this.column > this.columns) {
4363 // if a max height was specified by the user, we're done.
4364 // otherwise, the default is to make a new page at the bottom.
4365 if (this.height != null) {
4366 return false;
4367 }
4368
4369 this.document.continueOnNewPage();
4370 this.column = 1;
4371 this.startY = this.document.page.margins.top;
4372 this.maxY = this.document.page.maxY();
4373 this.document.x = this.startX;
4374
4375 if (this.document._fillColor) {
4376 var _this$document;
4377
4378 (_this$document = this.document).fillColor.apply(_this$document, _toConsumableArray(this.document._fillColor));
4379 }
4380
4381 this.emit('pageBreak', options, this);
4382 } else {
4383 this.document.x += this.lineWidth + this.columnGap;
4384 this.document.y = this.startY;
4385 this.emit('columnBreak', options, this);
4386 }
4387
4388 this.emit('sectionStart', options, this);
4389 return true;
4390 }
4391 }]);
4392
4393 return LineWrapper;
4394}(EventEmitter);
4395
4396var number$2 = PDFObject.number;
4397var TextMixin = {
4398 initText: function initText() {
4399 this._line = this._line.bind(this); // Current coordinates
4400
4401 this.x = 0;
4402 this.y = 0;
4403 return this._lineGap = 0;
4404 },
4405 lineGap: function lineGap(_lineGap) {
4406 this._lineGap = _lineGap;
4407 return this;
4408 },
4409 moveDown: function moveDown(lines) {
4410 if (lines == null) {
4411 lines = 1;
4412 }
4413
4414 this.y += this.currentLineHeight(true) * lines + this._lineGap;
4415 return this;
4416 },
4417 moveUp: function moveUp(lines) {
4418 if (lines == null) {
4419 lines = 1;
4420 }
4421
4422 this.y -= this.currentLineHeight(true) * lines + this._lineGap;
4423 return this;
4424 },
4425 _text: function _text(text, x, y, options, lineCallback) {
4426 var _this = this;
4427
4428 options = this._initOptions(x, y, options); // Convert text to a string
4429
4430 text = text == null ? '' : "".concat(text); // if the wordSpacing option is specified, remove multiple consecutive spaces
4431
4432 if (options.wordSpacing) {
4433 text = text.replace(/\s{2,}/g, ' ');
4434 }
4435
4436 var addStructure = function addStructure() {
4437 if (options.structParent) {
4438 options.structParent.add(_this.struct(options.structType || 'P', [_this.markStructureContent(options.structType || 'P')]));
4439 }
4440 }; // word wrapping
4441
4442
4443 if (options.width) {
4444 var wrapper = this._wrapper;
4445
4446 if (!wrapper) {
4447 wrapper = new LineWrapper(this, options);
4448 wrapper.on('line', lineCallback);
4449 wrapper.on('firstLine', addStructure);
4450 }
4451
4452 this._wrapper = options.continued ? wrapper : null;
4453 this._textOptions = options.continued ? options : null;
4454 wrapper.wrap(text, options); // render paragraphs as single lines
4455 } else {
4456 var _iterator = _createForOfIteratorHelper(text.split('\n')),
4457 _step;
4458
4459 try {
4460 for (_iterator.s(); !(_step = _iterator.n()).done;) {
4461 var line = _step.value;
4462 addStructure();
4463 lineCallback(line, options);
4464 }
4465 } catch (err) {
4466 _iterator.e(err);
4467 } finally {
4468 _iterator.f();
4469 }
4470 }
4471
4472 return this;
4473 },
4474 text: function text(_text2, x, y, options) {
4475 return this._text(_text2, x, y, options, this._line);
4476 },
4477 widthOfString: function widthOfString(string) {
4478 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
4479 return this._font.widthOfString(string, this._fontSize, options.features) + (options.characterSpacing || 0) * (string.length - 1);
4480 },
4481 heightOfString: function heightOfString(text, options) {
4482 var _this2 = this;
4483
4484 var x = this.x,
4485 y = this.y;
4486 options = this._initOptions(options);
4487 options.height = Infinity; // don't break pages
4488
4489 var lineGap = options.lineGap || this._lineGap || 0;
4490
4491 this._text(text, this.x, this.y, options, function () {
4492 return _this2.y += _this2.currentLineHeight(true) + lineGap;
4493 });
4494
4495 var height = this.y - y;
4496 this.x = x;
4497 this.y = y;
4498 return height;
4499 },
4500 list: function list(_list, x, y, options, wrapper) {
4501 options = this._initOptions(x, y, options);
4502 var listType = options.listType || 'bullet';
4503 var unit = Math.round(this._font.ascender / 1000 * this._fontSize);
4504 var midLine = unit / 2;
4505 var r = options.bulletRadius || unit / 3;
4506 var indent = options.textIndent || (listType === 'bullet' ? r * 5 : unit * 2);
4507 var itemIndent = options.bulletIndent || (listType === 'bullet' ? r * 8 : unit * 2);
4508 var level = 1;
4509 var items = [];
4510 var levels = [];
4511 var numbers = [];
4512
4513 var flatten = function flatten(list) {
4514 var n = 1;
4515
4516 for (var i = 0; i < list.length; i++) {
4517 var item = list[i];
4518
4519 if (Array.isArray(item)) {
4520 level++;
4521 flatten(item);
4522 level--;
4523 } else {
4524 items.push(item);
4525 levels.push(level);
4526
4527 if (listType !== 'bullet') {
4528 numbers.push(n++);
4529 }
4530 }
4531 }
4532 };
4533
4534 flatten(_list);
4535
4536 var label = function label(n) {
4537 switch (listType) {
4538 case 'numbered':
4539 return "".concat(n, ".");
4540
4541 case 'lettered':
4542 var letter = String.fromCharCode((n - 1) % 26 + 65);
4543 var times = Math.floor((n - 1) / 26 + 1);
4544 var text = Array(times + 1).join(letter);
4545 return "".concat(text, ".");
4546 }
4547 };
4548
4549 var drawListItem = function drawListItem(listItem) {
4550 var _this3 = this;
4551
4552 wrapper = new LineWrapper(this, options);
4553 wrapper.on('line', this._line);
4554 level = 1;
4555 var i = 0;
4556 wrapper.once('firstLine', function () {
4557 var item, itemType, labelType, bodyType;
4558
4559 if (options.structParent) {
4560 if (options.structTypes) {
4561 var _options$structTypes = _slicedToArray(options.structTypes, 3);
4562
4563 itemType = _options$structTypes[0];
4564 labelType = _options$structTypes[1];
4565 bodyType = _options$structTypes[2];
4566 } else {
4567 itemType = 'LI';
4568 labelType = 'Lbl';
4569 bodyType = 'LBody';
4570 }
4571 }
4572
4573 if (itemType) {
4574 item = _this3.struct(itemType);
4575 options.structParent.add(item);
4576 } else if (options.structParent) {
4577 item = options.structParent;
4578 }
4579
4580 var l;
4581
4582 if ((l = levels[i++]) !== level) {
4583 var diff = itemIndent * (l - level);
4584 _this3.x += diff;
4585 wrapper.lineWidth -= diff;
4586 level = l;
4587 }
4588
4589 if (item && (labelType || bodyType)) {
4590 item.add(_this3.struct(labelType || bodyType, [_this3.markStructureContent(labelType || bodyType)]));
4591 }
4592
4593 switch (listType) {
4594 case 'bullet':
4595 _this3.circle(_this3.x - indent + r, _this3.y + midLine, r);
4596
4597 _this3.fill();
4598
4599 break;
4600
4601 case 'numbered':
4602 case 'lettered':
4603 var text = label(numbers[i - 1]);
4604
4605 _this3._fragment(text, _this3.x - indent, _this3.y, options);
4606
4607 break;
4608 }
4609
4610 if (item && labelType && bodyType) {
4611 item.add(_this3.struct(bodyType, [_this3.markStructureContent(bodyType)]));
4612 }
4613
4614 if (item && item !== options.structParent) {
4615 item.end();
4616 }
4617 });
4618 wrapper.on('sectionStart', function () {
4619 var pos = indent + itemIndent * (level - 1);
4620 _this3.x += pos;
4621 return wrapper.lineWidth -= pos;
4622 });
4623 wrapper.on('sectionEnd', function () {
4624 var pos = indent + itemIndent * (level - 1);
4625 _this3.x -= pos;
4626 return wrapper.lineWidth += pos;
4627 });
4628 wrapper.wrap(listItem, options);
4629 };
4630
4631 for (var i = 0; i < items.length; i++) {
4632 drawListItem.call(this, items[i]);
4633 }
4634
4635 return this;
4636 },
4637 _initOptions: function _initOptions() {
4638 var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4639 var y = arguments.length > 1 ? arguments[1] : undefined;
4640 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
4641
4642 if (typeof x === 'object') {
4643 options = x;
4644 x = null;
4645 } // clone options object
4646
4647
4648 var result = Object.assign({}, options); // extend options with previous values for continued text
4649
4650 if (this._textOptions) {
4651 for (var key in this._textOptions) {
4652 var val = this._textOptions[key];
4653
4654 if (key !== 'continued') {
4655 if (result[key] === undefined) {
4656 result[key] = val;
4657 }
4658 }
4659 }
4660 } // Update the current position
4661
4662
4663 if (x != null) {
4664 this.x = x;
4665 }
4666
4667 if (y != null) {
4668 this.y = y;
4669 } // wrap to margins if no x or y position passed
4670
4671
4672 if (result.lineBreak !== false) {
4673 if (result.width == null) {
4674 result.width = this.page.width - this.x - this.page.margins.right;
4675 }
4676
4677 result.width = Math.max(result.width, 0);
4678 }
4679
4680 if (!result.columns) {
4681 result.columns = 0;
4682 }
4683
4684 if (result.columnGap == null) {
4685 result.columnGap = 18;
4686 } // 1/4 inch
4687
4688
4689 return result;
4690 },
4691 _line: function _line(text) {
4692 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
4693 var wrapper = arguments.length > 2 ? arguments[2] : undefined;
4694
4695 this._fragment(text, this.x, this.y, options);
4696
4697 var lineGap = options.lineGap || this._lineGap || 0;
4698
4699 if (!wrapper) {
4700 return this.x += this.widthOfString(text);
4701 } else {
4702 return this.y += this.currentLineHeight(true) + lineGap;
4703 }
4704 },
4705 _fragment: function _fragment(text, x, y, options) {
4706 var _this4 = this;
4707
4708 var dy, encoded, i, positions, textWidth, words;
4709 text = "".concat(text).replace(/\n/g, '');
4710
4711 if (text.length === 0) {
4712 return;
4713 } // handle options
4714
4715
4716 var align = options.align || 'left';
4717 var wordSpacing = options.wordSpacing || 0;
4718 var characterSpacing = options.characterSpacing || 0; // text alignments
4719
4720 if (options.width) {
4721 switch (align) {
4722 case 'right':
4723 textWidth = this.widthOfString(text.replace(/\s+$/, ''), options);
4724 x += options.lineWidth - textWidth;
4725 break;
4726
4727 case 'center':
4728 x += options.lineWidth / 2 - options.textWidth / 2;
4729 break;
4730
4731 case 'justify':
4732 // calculate the word spacing value
4733 words = text.trim().split(/\s+/);
4734 textWidth = this.widthOfString(text.replace(/\s+/g, ''), options);
4735 var spaceWidth = this.widthOfString(' ') + characterSpacing;
4736 wordSpacing = Math.max(0, (options.lineWidth - textWidth) / Math.max(1, words.length - 1) - spaceWidth);
4737 break;
4738 }
4739 } // text baseline alignments based on http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling
4740
4741
4742 if (typeof options.baseline === 'number') {
4743 dy = -options.baseline;
4744 } else {
4745 switch (options.baseline) {
4746 case 'svg-middle':
4747 dy = 0.5 * this._font.xHeight;
4748 break;
4749
4750 case 'middle':
4751 case 'svg-central':
4752 dy = 0.5 * (this._font.descender + this._font.ascender);
4753 break;
4754
4755 case 'bottom':
4756 case 'ideographic':
4757 dy = this._font.descender;
4758 break;
4759
4760 case 'alphabetic':
4761 dy = 0;
4762 break;
4763
4764 case 'mathematical':
4765 dy = 0.5 * this._font.ascender;
4766 break;
4767
4768 case 'hanging':
4769 dy = 0.8 * this._font.ascender;
4770 break;
4771
4772 case 'top':
4773 dy = this._font.ascender;
4774 break;
4775
4776 default:
4777 dy = this._font.ascender;
4778 }
4779
4780 dy = dy / 1000 * this._fontSize;
4781 } // calculate the actual rendered width of the string after word and character spacing
4782
4783
4784 var renderedWidth = options.textWidth + wordSpacing * (options.wordCount - 1) + characterSpacing * (text.length - 1); // create link annotations if the link option is given
4785
4786 if (options.link != null) {
4787 this.link(x, y, renderedWidth, this.currentLineHeight(), options.link);
4788 }
4789
4790 if (options.goTo != null) {
4791 this.goTo(x, y, renderedWidth, this.currentLineHeight(), options.goTo);
4792 }
4793
4794 if (options.destination != null) {
4795 this.addNamedDestination(options.destination, 'XYZ', x, y, null);
4796 } // create underline
4797
4798
4799 if (options.underline) {
4800 this.save();
4801
4802 if (!options.stroke) {
4803 this.strokeColor.apply(this, _toConsumableArray(this._fillColor || []));
4804 }
4805
4806 var lineWidth = this._fontSize < 10 ? 0.5 : Math.floor(this._fontSize / 10);
4807 this.lineWidth(lineWidth);
4808 var lineY = y + this.currentLineHeight() - lineWidth;
4809 this.moveTo(x, lineY);
4810 this.lineTo(x + renderedWidth, lineY);
4811 this.stroke();
4812 this.restore();
4813 } // create strikethrough line
4814
4815
4816 if (options.strike) {
4817 this.save();
4818
4819 if (!options.stroke) {
4820 this.strokeColor.apply(this, _toConsumableArray(this._fillColor || []));
4821 }
4822
4823 var _lineWidth = this._fontSize < 10 ? 0.5 : Math.floor(this._fontSize / 10);
4824
4825 this.lineWidth(_lineWidth);
4826
4827 var _lineY = y + this.currentLineHeight() / 2;
4828
4829 this.moveTo(x, _lineY);
4830 this.lineTo(x + renderedWidth, _lineY);
4831 this.stroke();
4832 this.restore();
4833 }
4834
4835 this.save(); // oblique (angle in degrees or boolean)
4836
4837 if (options.oblique) {
4838 var skew;
4839
4840 if (typeof options.oblique === 'number') {
4841 skew = -Math.tan(options.oblique * Math.PI / 180);
4842 } else {
4843 skew = -0.25;
4844 }
4845
4846 this.transform(1, 0, 0, 1, x, y);
4847 this.transform(1, 0, skew, 1, -skew * dy, 0);
4848 this.transform(1, 0, 0, 1, -x, -y);
4849 } // flip coordinate system
4850
4851
4852 this.transform(1, 0, 0, -1, 0, this.page.height);
4853 y = this.page.height - y - dy; // add current font to page if necessary
4854
4855 if (this.page.fonts[this._font.id] == null) {
4856 this.page.fonts[this._font.id] = this._font.ref();
4857 } // begin the text object
4858
4859
4860 this.addContent('BT'); // text position
4861
4862 this.addContent("1 0 0 1 ".concat(number$2(x), " ").concat(number$2(y), " Tm")); // font and font size
4863
4864 this.addContent("/".concat(this._font.id, " ").concat(number$2(this._fontSize), " Tf")); // rendering mode
4865
4866 var mode = options.fill && options.stroke ? 2 : options.stroke ? 1 : 0;
4867
4868 if (mode) {
4869 this.addContent("".concat(mode, " Tr"));
4870 } // Character spacing
4871
4872
4873 if (characterSpacing) {
4874 this.addContent("".concat(number$2(characterSpacing), " Tc"));
4875 } // Add the actual text
4876 // If we have a word spacing value, we need to encode each word separately
4877 // since the normal Tw operator only works on character code 32, which isn't
4878 // used for embedded fonts.
4879
4880
4881 if (wordSpacing) {
4882 words = text.trim().split(/\s+/);
4883 wordSpacing += this.widthOfString(' ') + characterSpacing;
4884 wordSpacing *= 1000 / this._fontSize;
4885 encoded = [];
4886 positions = [];
4887
4888 var _iterator2 = _createForOfIteratorHelper(words),
4889 _step2;
4890
4891 try {
4892 for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
4893 var word = _step2.value;
4894
4895 var _this$_font$encode = this._font.encode(word, options.features),
4896 _this$_font$encode2 = _slicedToArray(_this$_font$encode, 2),
4897 encodedWord = _this$_font$encode2[0],
4898 positionsWord = _this$_font$encode2[1];
4899
4900 encoded = encoded.concat(encodedWord);
4901 positions = positions.concat(positionsWord); // add the word spacing to the end of the word
4902 // clone object because of cache
4903
4904 var space = {};
4905 var object = positions[positions.length - 1];
4906
4907 for (var key in object) {
4908 var val = object[key];
4909 space[key] = val;
4910 }
4911
4912 space.xAdvance += wordSpacing;
4913 positions[positions.length - 1] = space;
4914 }
4915 } catch (err) {
4916 _iterator2.e(err);
4917 } finally {
4918 _iterator2.f();
4919 }
4920 } else {
4921 var _this$_font$encode3 = this._font.encode(text, options.features);
4922
4923 var _this$_font$encode4 = _slicedToArray(_this$_font$encode3, 2);
4924
4925 encoded = _this$_font$encode4[0];
4926 positions = _this$_font$encode4[1];
4927 }
4928
4929 var scale = this._fontSize / 1000;
4930 var commands = [];
4931 var last = 0;
4932 var hadOffset = false; // Adds a segment of text to the TJ command buffer
4933
4934 var addSegment = function addSegment(cur) {
4935 if (last < cur) {
4936 var hex = encoded.slice(last, cur).join('');
4937 var advance = positions[cur - 1].xAdvance - positions[cur - 1].advanceWidth;
4938 commands.push("<".concat(hex, "> ").concat(number$2(-advance)));
4939 }
4940
4941 return last = cur;
4942 }; // Flushes the current TJ commands to the output stream
4943
4944
4945 var flush = function flush(i) {
4946 addSegment(i);
4947
4948 if (commands.length > 0) {
4949 _this4.addContent("[".concat(commands.join(' '), "] TJ"));
4950
4951 return commands.length = 0;
4952 }
4953 };
4954
4955 for (i = 0; i < positions.length; i++) {
4956 // If we have an x or y offset, we have to break out of the current TJ command
4957 // so we can move the text position.
4958 var pos = positions[i];
4959
4960 if (pos.xOffset || pos.yOffset) {
4961 // Flush the current buffer
4962 flush(i); // Move the text position and flush just the current character
4963
4964 this.addContent("1 0 0 1 ".concat(number$2(x + pos.xOffset * scale), " ").concat(number$2(y + pos.yOffset * scale), " Tm"));
4965 flush(i + 1);
4966 hadOffset = true;
4967 } else {
4968 // If the last character had an offset, reset the text position
4969 if (hadOffset) {
4970 this.addContent("1 0 0 1 ".concat(number$2(x), " ").concat(number$2(y), " Tm"));
4971 hadOffset = false;
4972 } // Group segments that don't have any advance adjustments
4973
4974
4975 if (pos.xAdvance - pos.advanceWidth !== 0) {
4976 addSegment(i + 1);
4977 }
4978 }
4979
4980 x += pos.xAdvance * scale;
4981 } // Flush any remaining commands
4982
4983
4984 flush(i); // end the text object
4985
4986 this.addContent('ET'); // restore flipped coordinate system
4987
4988 return this.restore();
4989 }
4990};
4991
4992var MARKERS = [0xffc0, 0xffc1, 0xffc2, 0xffc3, 0xffc5, 0xffc6, 0xffc7, 0xffc8, 0xffc9, 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf];
4993var COLOR_SPACE_MAP = {
4994 1: 'DeviceGray',
4995 3: 'DeviceRGB',
4996 4: 'DeviceCMYK'
4997};
4998
4999var JPEG = /*#__PURE__*/function () {
5000 function JPEG(data, label) {
5001 _classCallCheck(this, JPEG);
5002
5003 var marker;
5004 this.data = data;
5005 this.label = label;
5006
5007 if (this.data.readUInt16BE(0) !== 0xffd8) {
5008 throw 'SOI not found in JPEG';
5009 } // Parse the EXIF orientation
5010
5011
5012 this.orientation = exif.fromBuffer(this.data).Orientation || 1;
5013 var pos = 2;
5014
5015 while (pos < this.data.length) {
5016 marker = this.data.readUInt16BE(pos);
5017 pos += 2;
5018
5019 if (MARKERS.includes(marker)) {
5020 break;
5021 }
5022
5023 pos += this.data.readUInt16BE(pos);
5024 }
5025
5026 if (!MARKERS.includes(marker)) {
5027 throw 'Invalid JPEG.';
5028 }
5029
5030 pos += 2;
5031 this.bits = this.data[pos++];
5032 this.height = this.data.readUInt16BE(pos);
5033 pos += 2;
5034 this.width = this.data.readUInt16BE(pos);
5035 pos += 2;
5036 var channels = this.data[pos++];
5037 this.colorSpace = COLOR_SPACE_MAP[channels];
5038 this.obj = null;
5039 }
5040
5041 _createClass(JPEG, [{
5042 key: "embed",
5043 value: function embed(document) {
5044 if (this.obj) {
5045 return;
5046 }
5047
5048 this.obj = document.ref({
5049 Type: 'XObject',
5050 Subtype: 'Image',
5051 BitsPerComponent: this.bits,
5052 Width: this.width,
5053 Height: this.height,
5054 ColorSpace: this.colorSpace,
5055 Filter: 'DCTDecode'
5056 }); // add extra decode params for CMYK images. By swapping the
5057 // min and max values from the default, we invert the colors. See
5058 // section 4.8.4 of the spec.
5059
5060 if (this.colorSpace === 'DeviceCMYK') {
5061 this.obj.data['Decode'] = [1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0];
5062 }
5063
5064 this.obj.end(this.data); // free memory
5065
5066 return this.data = null;
5067 }
5068 }]);
5069
5070 return JPEG;
5071}();
5072
5073var PNGImage = /*#__PURE__*/function () {
5074 function PNGImage(data, label) {
5075 _classCallCheck(this, PNGImage);
5076
5077 this.label = label;
5078 this.image = new PNG(data);
5079 this.width = this.image.width;
5080 this.height = this.image.height;
5081 this.imgData = this.image.imgData;
5082 this.obj = null;
5083 }
5084
5085 _createClass(PNGImage, [{
5086 key: "embed",
5087 value: function embed(document) {
5088 var dataDecoded = false;
5089 this.document = document;
5090
5091 if (this.obj) {
5092 return;
5093 }
5094
5095 var hasAlphaChannel = this.image.hasAlphaChannel;
5096 var isInterlaced = this.image.interlaceMethod === 1;
5097 this.obj = this.document.ref({
5098 Type: 'XObject',
5099 Subtype: 'Image',
5100 BitsPerComponent: hasAlphaChannel ? 8 : this.image.bits,
5101 Width: this.width,
5102 Height: this.height,
5103 Filter: 'FlateDecode'
5104 });
5105
5106 if (!hasAlphaChannel) {
5107 var params = this.document.ref({
5108 Predictor: isInterlaced ? 1 : 15,
5109 Colors: this.image.colors,
5110 BitsPerComponent: this.image.bits,
5111 Columns: this.width
5112 });
5113 this.obj.data['DecodeParms'] = params;
5114 params.end();
5115 }
5116
5117 if (this.image.palette.length === 0) {
5118 this.obj.data['ColorSpace'] = this.image.colorSpace;
5119 } else {
5120 // embed the color palette in the PDF as an object stream
5121 var palette = this.document.ref();
5122 palette.end(Buffer.from(this.image.palette)); // build the color space array for the image
5123
5124 this.obj.data['ColorSpace'] = ['Indexed', 'DeviceRGB', this.image.palette.length / 3 - 1, palette];
5125 } // For PNG color types 0, 2 and 3, the transparency data is stored in
5126 // a dedicated PNG chunk.
5127
5128
5129 if (this.image.transparency.grayscale != null) {
5130 // Use Color Key Masking (spec section 4.8.5)
5131 // An array with N elements, where N is two times the number of color components.
5132 var val = this.image.transparency.grayscale;
5133 this.obj.data['Mask'] = [val, val];
5134 } else if (this.image.transparency.rgb) {
5135 // Use Color Key Masking (spec section 4.8.5)
5136 // An array with N elements, where N is two times the number of color components.
5137 var rgb = this.image.transparency.rgb;
5138 var mask = [];
5139
5140 var _iterator = _createForOfIteratorHelper(rgb),
5141 _step;
5142
5143 try {
5144 for (_iterator.s(); !(_step = _iterator.n()).done;) {
5145 var x = _step.value;
5146 mask.push(x, x);
5147 }
5148 } catch (err) {
5149 _iterator.e(err);
5150 } finally {
5151 _iterator.f();
5152 }
5153
5154 this.obj.data['Mask'] = mask;
5155 } else if (this.image.transparency.indexed) {
5156 // Create a transparency SMask for the image based on the data
5157 // in the PLTE and tRNS sections. See below for details on SMasks.
5158 dataDecoded = true;
5159 return this.loadIndexedAlphaChannel();
5160 } else if (hasAlphaChannel) {
5161 // For PNG color types 4 and 6, the transparency data is stored as a alpha
5162 // channel mixed in with the main image data. Separate this data out into an
5163 // SMask object and store it separately in the PDF.
5164 dataDecoded = true;
5165 return this.splitAlphaChannel();
5166 }
5167
5168 if (isInterlaced && !dataDecoded) {
5169 return this.decodeData();
5170 }
5171
5172 this.finalize();
5173 }
5174 }, {
5175 key: "finalize",
5176 value: function finalize() {
5177 if (this.alphaChannel) {
5178 var sMask = this.document.ref({
5179 Type: 'XObject',
5180 Subtype: 'Image',
5181 Height: this.height,
5182 Width: this.width,
5183 BitsPerComponent: 8,
5184 Filter: 'FlateDecode',
5185 ColorSpace: 'DeviceGray',
5186 Decode: [0, 1]
5187 });
5188 sMask.end(this.alphaChannel);
5189 this.obj.data['SMask'] = sMask;
5190 } // add the actual image data
5191
5192
5193 this.obj.end(this.imgData); // free memory
5194
5195 this.image = null;
5196 return this.imgData = null;
5197 }
5198 }, {
5199 key: "splitAlphaChannel",
5200 value: function splitAlphaChannel() {
5201 var _this = this;
5202
5203 return this.image.decodePixels(function (pixels) {
5204 var a, p;
5205 var colorCount = _this.image.colors;
5206 var pixelCount = _this.width * _this.height;
5207 var imgData = Buffer.alloc(pixelCount * colorCount);
5208 var alphaChannel = Buffer.alloc(pixelCount);
5209 var i = p = a = 0;
5210 var len = pixels.length; // For 16bit images copy only most significant byte (MSB) - PNG data is always stored in network byte order (MSB first)
5211
5212 var skipByteCount = _this.image.bits === 16 ? 1 : 0;
5213
5214 while (i < len) {
5215 for (var colorIndex = 0; colorIndex < colorCount; colorIndex++) {
5216 imgData[p++] = pixels[i++];
5217 i += skipByteCount;
5218 }
5219
5220 alphaChannel[a++] = pixels[i++];
5221 i += skipByteCount;
5222 }
5223
5224 _this.imgData = zlib.deflateSync(imgData);
5225 _this.alphaChannel = zlib.deflateSync(alphaChannel);
5226 return _this.finalize();
5227 });
5228 }
5229 }, {
5230 key: "loadIndexedAlphaChannel",
5231 value: function loadIndexedAlphaChannel() {
5232 var _this2 = this;
5233
5234 var transparency = this.image.transparency.indexed;
5235 return this.image.decodePixels(function (pixels) {
5236 var alphaChannel = Buffer.alloc(_this2.width * _this2.height);
5237 var i = 0;
5238
5239 for (var j = 0, end = pixels.length; j < end; j++) {
5240 alphaChannel[i++] = transparency[pixels[j]];
5241 }
5242
5243 _this2.alphaChannel = zlib.deflateSync(alphaChannel);
5244 return _this2.finalize();
5245 });
5246 }
5247 }, {
5248 key: "decodeData",
5249 value: function decodeData() {
5250 var _this3 = this;
5251
5252 this.image.decodePixels(function (pixels) {
5253 _this3.imgData = zlib.deflateSync(pixels);
5254
5255 _this3.finalize();
5256 });
5257 }
5258 }]);
5259
5260 return PNGImage;
5261}();
5262
5263var PDFImage = /*#__PURE__*/function () {
5264 function PDFImage() {
5265 _classCallCheck(this, PDFImage);
5266 }
5267
5268 _createClass(PDFImage, null, [{
5269 key: "open",
5270 value: function open(src, label) {
5271 var data;
5272
5273 if (Buffer.isBuffer(src)) {
5274 data = src;
5275 } else if (src instanceof ArrayBuffer) {
5276 data = Buffer.from(new Uint8Array(src));
5277 } else {
5278 var match;
5279
5280 if (match = /^data:.+?;base64,(.*)$/.exec(src)) {
5281 data = Buffer.from(match[1], 'base64');
5282 } else {
5283 data = fs.readFileSync(src);
5284
5285 if (!data) {
5286 return;
5287 }
5288 }
5289 }
5290
5291 if (data[0] === 0xff && data[1] === 0xd8) {
5292 return new JPEG(data, label);
5293 } else if (data[0] === 0x89 && data.toString('ascii', 1, 4) === 'PNG') {
5294 return new PNGImage(data, label);
5295 } else {
5296 throw new Error('Unknown image format.');
5297 }
5298 }
5299 }]);
5300
5301 return PDFImage;
5302}();
5303
5304var ImagesMixin = {
5305 initImages: function initImages() {
5306 this._imageRegistry = {};
5307 return this._imageCount = 0;
5308 },
5309 image: function image(src, x, y) {
5310 var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
5311 var bh, bp, bw, image, ip, left, left1, rotateAngle, originX, originY;
5312
5313 if (typeof x === 'object') {
5314 options = x;
5315 x = null;
5316 } // Ignore orientation based on document options or image options
5317
5318
5319 var ignoreOrientation = options.ignoreOrientation || options.ignoreOrientation !== false && this.options.ignoreOrientation;
5320 x = (left = x != null ? x : options.x) != null ? left : this.x;
5321 y = (left1 = y != null ? y : options.y) != null ? left1 : this.y;
5322
5323 if (typeof src === 'string') {
5324 image = this._imageRegistry[src];
5325 }
5326
5327 if (!image) {
5328 if (src.width && src.height) {
5329 image = src;
5330 } else {
5331 image = this.openImage(src);
5332 }
5333 }
5334
5335 if (!image.obj) {
5336 image.embed(this);
5337 }
5338
5339 if (this.page.xobjects[image.label] == null) {
5340 this.page.xobjects[image.label] = image.obj;
5341 }
5342
5343 var _image = image,
5344 width = _image.width,
5345 height = _image.height; // If EXIF orientation calls for it, swap width and height
5346
5347 if (!ignoreOrientation && image.orientation > 4) {
5348 var _ref = [height, width];
5349 width = _ref[0];
5350 height = _ref[1];
5351 }
5352
5353 var w = options.width || width;
5354 var h = options.height || height;
5355
5356 if (options.width && !options.height) {
5357 var wp = w / width;
5358 w = width * wp;
5359 h = height * wp;
5360 } else if (options.height && !options.width) {
5361 var hp = h / height;
5362 w = width * hp;
5363 h = height * hp;
5364 } else if (options.scale) {
5365 w = width * options.scale;
5366 h = height * options.scale;
5367 } else if (options.fit) {
5368 var _options$fit = _slicedToArray(options.fit, 2);
5369
5370 bw = _options$fit[0];
5371 bh = _options$fit[1];
5372 bp = bw / bh;
5373 ip = width / height;
5374
5375 if (ip > bp) {
5376 w = bw;
5377 h = bw / ip;
5378 } else {
5379 h = bh;
5380 w = bh * ip;
5381 }
5382 } else if (options.cover) {
5383 var _options$cover = _slicedToArray(options.cover, 2);
5384
5385 bw = _options$cover[0];
5386 bh = _options$cover[1];
5387 bp = bw / bh;
5388 ip = width / height;
5389
5390 if (ip > bp) {
5391 h = bh;
5392 w = bh * ip;
5393 } else {
5394 w = bw;
5395 h = bw / ip;
5396 }
5397 }
5398
5399 if (options.fit || options.cover) {
5400 if (options.align === 'center') {
5401 x = x + bw / 2 - w / 2;
5402 } else if (options.align === 'right') {
5403 x = x + bw - w;
5404 }
5405
5406 if (options.valign === 'center') {
5407 y = y + bh / 2 - h / 2;
5408 } else if (options.valign === 'bottom') {
5409 y = y + bh - h;
5410 }
5411 }
5412
5413 if (!ignoreOrientation) {
5414 switch (image.orientation) {
5415 // No orientation (need to flip image, though, because of the default transform matrix on the document)
5416 default:
5417 case 1:
5418 h = -h;
5419 y -= h;
5420 rotateAngle = 0;
5421 break;
5422 // Flip Horizontal
5423
5424 case 2:
5425 w = -w;
5426 h = -h;
5427 x -= w;
5428 y -= h;
5429 rotateAngle = 0;
5430 break;
5431 // Rotate 180 degrees
5432
5433 case 3:
5434 originX = x;
5435 originY = y;
5436 h = -h;
5437 x -= w;
5438 rotateAngle = 180;
5439 break;
5440 // Flip vertical
5441
5442 case 4:
5443 // Do nothing, image will be flipped
5444 break;
5445 // Flip horizontally and rotate 270 degrees CW
5446
5447 case 5:
5448 originX = x;
5449 originY = y;
5450 var _ref2 = [h, w];
5451 w = _ref2[0];
5452 h = _ref2[1];
5453 y -= h;
5454 rotateAngle = 90;
5455 break;
5456 // Rotate 90 degrees CW
5457
5458 case 6:
5459 originX = x;
5460 originY = y;
5461 var _ref3 = [h, w];
5462 w = _ref3[0];
5463 h = _ref3[1];
5464 h = -h;
5465 rotateAngle = 90;
5466 break;
5467 // Flip horizontally and rotate 90 degrees CW
5468
5469 case 7:
5470 originX = x;
5471 originY = y;
5472 var _ref4 = [h, w];
5473 w = _ref4[0];
5474 h = _ref4[1];
5475 h = -h;
5476 w = -w;
5477 x -= w;
5478 rotateAngle = 90;
5479 break;
5480 // Rotate 270 degrees CW
5481
5482 case 8:
5483 originX = x;
5484 originY = y;
5485 var _ref5 = [h, w];
5486 w = _ref5[0];
5487 h = _ref5[1];
5488 h = -h;
5489 x -= w;
5490 y -= h;
5491 rotateAngle = -90;
5492 break;
5493 }
5494 } else {
5495 h = -h;
5496 y -= h;
5497 rotateAngle = 0;
5498 } // create link annotations if the link option is given
5499
5500
5501 if (options.link != null) {
5502 this.link(x, y, w, h, options.link);
5503 }
5504
5505 if (options.goTo != null) {
5506 this.goTo(x, y, w, h, options.goTo);
5507 }
5508
5509 if (options.destination != null) {
5510 this.addNamedDestination(options.destination, 'XYZ', x, y, null);
5511 } // Set the current y position to below the image if it is in the document flow
5512
5513
5514 if (this.y === y) {
5515 this.y += h;
5516 }
5517
5518 this.save();
5519
5520 if (rotateAngle) {
5521 this.rotate(rotateAngle, {
5522 origin: [originX, originY]
5523 });
5524 }
5525
5526 this.transform(w, 0, 0, h, x, y);
5527 this.addContent("/".concat(image.label, " Do"));
5528 this.restore();
5529 return this;
5530 },
5531 openImage: function openImage(src) {
5532 var image;
5533
5534 if (typeof src === 'string') {
5535 image = this._imageRegistry[src];
5536 }
5537
5538 if (!image) {
5539 image = PDFImage.open(src, "I".concat(++this._imageCount));
5540
5541 if (typeof src === 'string') {
5542 this._imageRegistry[src] = image;
5543 }
5544 }
5545
5546 return image;
5547 }
5548};
5549
5550var AnnotationsMixin = {
5551 annotate: function annotate(x, y, w, h, options) {
5552 options.Type = 'Annot';
5553 options.Rect = this._convertRect(x, y, w, h);
5554 options.Border = [0, 0, 0];
5555
5556 if (options.Subtype === 'Link' && typeof options.F === 'undefined') {
5557 options.F = 1 << 2; // Print Annotation Flag
5558 }
5559
5560 if (options.Subtype !== 'Link') {
5561 if (options.C == null) {
5562 options.C = this._normalizeColor(options.color || [0, 0, 0]);
5563 }
5564 } // convert colors
5565
5566
5567 delete options.color;
5568
5569 if (typeof options.Dest === 'string') {
5570 options.Dest = new String(options.Dest);
5571 } // Capitalize keys
5572
5573
5574 for (var key in options) {
5575 var val = options[key];
5576 options[key[0].toUpperCase() + key.slice(1)] = val;
5577 }
5578
5579 var ref = this.ref(options);
5580 this.page.annotations.push(ref);
5581 ref.end();
5582 return this;
5583 },
5584 note: function note(x, y, w, h, contents) {
5585 var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
5586 options.Subtype = 'Text';
5587 options.Contents = new String(contents);
5588 options.Name = 'Comment';
5589
5590 if (options.color == null) {
5591 options.color = [243, 223, 92];
5592 }
5593
5594 return this.annotate(x, y, w, h, options);
5595 },
5596 goTo: function goTo(x, y, w, h, name) {
5597 var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
5598 options.Subtype = 'Link';
5599 options.A = this.ref({
5600 S: 'GoTo',
5601 D: new String(name)
5602 });
5603 options.A.end();
5604 return this.annotate(x, y, w, h, options);
5605 },
5606 link: function link(x, y, w, h, url) {
5607 var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
5608 options.Subtype = 'Link';
5609
5610 if (typeof url === 'number') {
5611 // Link to a page in the document (the page must already exist)
5612 var pages = this._root.data.Pages.data;
5613
5614 if (url >= 0 && url < pages.Kids.length) {
5615 options.A = this.ref({
5616 S: 'GoTo',
5617 D: [pages.Kids[url], 'XYZ', null, null, null]
5618 });
5619 options.A.end();
5620 } else {
5621 throw new Error("The document has no page ".concat(url));
5622 }
5623 } else {
5624 // Link to an external url
5625 options.A = this.ref({
5626 S: 'URI',
5627 URI: new String(url)
5628 });
5629 options.A.end();
5630 }
5631
5632 return this.annotate(x, y, w, h, options);
5633 },
5634 _markup: function _markup(x, y, w, h) {
5635 var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
5636
5637 var _this$_convertRect = this._convertRect(x, y, w, h),
5638 _this$_convertRect2 = _slicedToArray(_this$_convertRect, 4),
5639 x1 = _this$_convertRect2[0],
5640 y1 = _this$_convertRect2[1],
5641 x2 = _this$_convertRect2[2],
5642 y2 = _this$_convertRect2[3];
5643
5644 options.QuadPoints = [x1, y2, x2, y2, x1, y1, x2, y1];
5645 options.Contents = new String();
5646 return this.annotate(x, y, w, h, options);
5647 },
5648 highlight: function highlight(x, y, w, h) {
5649 var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
5650 options.Subtype = 'Highlight';
5651
5652 if (options.color == null) {
5653 options.color = [241, 238, 148];
5654 }
5655
5656 return this._markup(x, y, w, h, options);
5657 },
5658 underline: function underline(x, y, w, h) {
5659 var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
5660 options.Subtype = 'Underline';
5661 return this._markup(x, y, w, h, options);
5662 },
5663 strike: function strike(x, y, w, h) {
5664 var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
5665 options.Subtype = 'StrikeOut';
5666 return this._markup(x, y, w, h, options);
5667 },
5668 lineAnnotation: function lineAnnotation(x1, y1, x2, y2) {
5669 var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
5670 options.Subtype = 'Line';
5671 options.Contents = new String();
5672 options.L = [x1, this.page.height - y1, x2, this.page.height - y2];
5673 return this.annotate(x1, y1, x2, y2, options);
5674 },
5675 rectAnnotation: function rectAnnotation(x, y, w, h) {
5676 var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
5677 options.Subtype = 'Square';
5678 options.Contents = new String();
5679 return this.annotate(x, y, w, h, options);
5680 },
5681 ellipseAnnotation: function ellipseAnnotation(x, y, w, h) {
5682 var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
5683 options.Subtype = 'Circle';
5684 options.Contents = new String();
5685 return this.annotate(x, y, w, h, options);
5686 },
5687 textAnnotation: function textAnnotation(x, y, w, h, text) {
5688 var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
5689 options.Subtype = 'FreeText';
5690 options.Contents = new String(text);
5691 options.DA = new String();
5692 return this.annotate(x, y, w, h, options);
5693 },
5694 fileAnnotation: function fileAnnotation(x, y, w, h) {
5695 var file = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
5696 var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
5697 // create hidden file
5698 var filespec = this.file(file.src, Object.assign({
5699 hidden: true
5700 }, file));
5701 options.Subtype = 'FileAttachment';
5702 options.FS = filespec; // add description from filespec unless description (Contents) has already been set
5703
5704 if (options.Contents) {
5705 options.Contents = new String(options.Contents);
5706 } else if (filespec.data.Desc) {
5707 options.Contents = filespec.data.Desc;
5708 }
5709
5710 return this.annotate(x, y, w, h, options);
5711 },
5712 _convertRect: function _convertRect(x1, y1, w, h) {
5713 // flip y1 and y2
5714 var y2 = y1;
5715 y1 += h; // make x2
5716
5717 var x2 = x1 + w; // apply current transformation matrix to points
5718
5719 var _this$_ctm = _slicedToArray(this._ctm, 6),
5720 m0 = _this$_ctm[0],
5721 m1 = _this$_ctm[1],
5722 m2 = _this$_ctm[2],
5723 m3 = _this$_ctm[3],
5724 m4 = _this$_ctm[4],
5725 m5 = _this$_ctm[5];
5726
5727 x1 = m0 * x1 + m2 * y1 + m4;
5728 y1 = m1 * x1 + m3 * y1 + m5;
5729 x2 = m0 * x2 + m2 * y2 + m4;
5730 y2 = m1 * x2 + m3 * y2 + m5;
5731 return [x1, y1, x2, y2];
5732 }
5733};
5734
5735var PDFOutline = /*#__PURE__*/function () {
5736 function PDFOutline(document, parent, title, dest) {
5737 var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
5738 expanded: false
5739 };
5740
5741 _classCallCheck(this, PDFOutline);
5742
5743 this.document = document;
5744 this.options = options;
5745 this.outlineData = {};
5746
5747 if (dest !== null) {
5748 this.outlineData['Dest'] = [dest.dictionary, 'Fit'];
5749 }
5750
5751 if (parent !== null) {
5752 this.outlineData['Parent'] = parent;
5753 }
5754
5755 if (title !== null) {
5756 this.outlineData['Title'] = new String(title);
5757 }
5758
5759 this.dictionary = this.document.ref(this.outlineData);
5760 this.children = [];
5761 }
5762
5763 _createClass(PDFOutline, [{
5764 key: "addItem",
5765 value: function addItem(title) {
5766 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
5767 expanded: false
5768 };
5769 var result = new PDFOutline(this.document, this.dictionary, title, this.document.page, options);
5770 this.children.push(result);
5771 return result;
5772 }
5773 }, {
5774 key: "endOutline",
5775 value: function endOutline() {
5776 if (this.children.length > 0) {
5777 if (this.options.expanded) {
5778 this.outlineData.Count = this.children.length;
5779 }
5780
5781 var first = this.children[0],
5782 last = this.children[this.children.length - 1];
5783 this.outlineData.First = first.dictionary;
5784 this.outlineData.Last = last.dictionary;
5785
5786 for (var i = 0, len = this.children.length; i < len; i++) {
5787 var child = this.children[i];
5788
5789 if (i > 0) {
5790 child.outlineData.Prev = this.children[i - 1].dictionary;
5791 }
5792
5793 if (i < this.children.length - 1) {
5794 child.outlineData.Next = this.children[i + 1].dictionary;
5795 }
5796
5797 child.endOutline();
5798 }
5799 }
5800
5801 return this.dictionary.end();
5802 }
5803 }]);
5804
5805 return PDFOutline;
5806}();
5807
5808var OutlineMixin = {
5809 initOutline: function initOutline() {
5810 return this.outline = new PDFOutline(this, null, null, null);
5811 },
5812 endOutline: function endOutline() {
5813 this.outline.endOutline();
5814
5815 if (this.outline.children.length > 0) {
5816 this._root.data.Outlines = this.outline.dictionary;
5817 return this._root.data.PageMode = 'UseOutlines';
5818 }
5819 }
5820};
5821
5822/*
5823PDFStructureContent - a reference to a marked structure content
5824By Ben Schmidt
5825*/
5826var PDFStructureContent = /*#__PURE__*/function () {
5827 function PDFStructureContent(pageRef, mcid) {
5828 _classCallCheck(this, PDFStructureContent);
5829
5830 this.refs = [{
5831 pageRef: pageRef,
5832 mcid: mcid
5833 }];
5834 }
5835
5836 _createClass(PDFStructureContent, [{
5837 key: "push",
5838 value: function push(structContent) {
5839 var _this = this;
5840
5841 structContent.refs.forEach(function (ref) {
5842 return _this.refs.push(ref);
5843 });
5844 }
5845 }]);
5846
5847 return PDFStructureContent;
5848}();
5849
5850var PDFStructureElement = /*#__PURE__*/function () {
5851 function PDFStructureElement(document, type) {
5852 var _this = this;
5853
5854 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
5855 var children = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
5856
5857 _classCallCheck(this, PDFStructureElement);
5858
5859 this.document = document;
5860 this._attached = false;
5861 this._ended = false;
5862 this._flushed = false;
5863 this.dictionary = document.ref({
5864 // Type: "StructElem",
5865 S: type
5866 });
5867 var data = this.dictionary.data;
5868
5869 if (Array.isArray(options) || this._isValidChild(options)) {
5870 children = options;
5871 options = {};
5872 }
5873
5874 if (typeof options.title !== 'undefined') {
5875 data.T = new String(options.title);
5876 }
5877
5878 if (typeof options.lang !== 'undefined') {
5879 data.Lang = new String(options.lang);
5880 }
5881
5882 if (typeof options.alt !== 'undefined') {
5883 data.Alt = new String(options.alt);
5884 }
5885
5886 if (typeof options.expanded !== 'undefined') {
5887 data.E = new String(options.expanded);
5888 }
5889
5890 if (typeof options.actual !== 'undefined') {
5891 data.ActualText = new String(options.actual);
5892 }
5893
5894 this._children = [];
5895
5896 if (children) {
5897 if (!Array.isArray(children)) {
5898 children = [children];
5899 }
5900
5901 children.forEach(function (child) {
5902 return _this.add(child);
5903 });
5904 this.end();
5905 }
5906 }
5907
5908 _createClass(PDFStructureElement, [{
5909 key: "add",
5910 value: function add(child) {
5911 if (this._ended) {
5912 throw new Error("Cannot add child to already-ended structure element");
5913 }
5914
5915 if (!this._isValidChild(child)) {
5916 throw new Error("Invalid structure element child");
5917 }
5918
5919 if (child instanceof PDFStructureElement) {
5920 child.setParent(this.dictionary);
5921
5922 if (this._attached) {
5923 child.setAttached();
5924 }
5925 }
5926
5927 if (child instanceof PDFStructureContent) {
5928 this._addContentToParentTree(child);
5929 }
5930
5931 if (typeof child === 'function' && this._attached) {
5932 // _contentForClosure() adds the content to the parent tree
5933 child = this._contentForClosure(child);
5934 }
5935
5936 this._children.push(child);
5937
5938 return this;
5939 }
5940 }, {
5941 key: "_addContentToParentTree",
5942 value: function _addContentToParentTree(content) {
5943 var _this2 = this;
5944
5945 content.refs.forEach(function (_ref) {
5946 var pageRef = _ref.pageRef,
5947 mcid = _ref.mcid;
5948
5949 var pageStructParents = _this2.document.getStructParentTree().get(pageRef.data.StructParents);
5950
5951 pageStructParents[mcid] = _this2.dictionary;
5952 });
5953 }
5954 }, {
5955 key: "setParent",
5956 value: function setParent(parentRef) {
5957 if (this.dictionary.data.P) {
5958 throw new Error("Structure element added to more than one parent");
5959 }
5960
5961 this.dictionary.data.P = parentRef;
5962
5963 this._flush();
5964 }
5965 }, {
5966 key: "setAttached",
5967 value: function setAttached() {
5968 var _this3 = this;
5969
5970 if (this._attached) {
5971 return;
5972 }
5973
5974 this._children.forEach(function (child, index) {
5975 if (child instanceof PDFStructureElement) {
5976 child.setAttached();
5977 }
5978
5979 if (typeof child === 'function') {
5980 _this3._children[index] = _this3._contentForClosure(child);
5981 }
5982 });
5983
5984 this._attached = true;
5985
5986 this._flush();
5987 }
5988 }, {
5989 key: "end",
5990 value: function end() {
5991 if (this._ended) {
5992 return;
5993 }
5994
5995 this._children.filter(function (child) {
5996 return child instanceof PDFStructureElement;
5997 }).forEach(function (child) {
5998 return child.end();
5999 });
6000
6001 this._ended = true;
6002
6003 this._flush();
6004 }
6005 }, {
6006 key: "_isValidChild",
6007 value: function _isValidChild(child) {
6008 return child instanceof PDFStructureElement || child instanceof PDFStructureContent || typeof child === 'function';
6009 }
6010 }, {
6011 key: "_contentForClosure",
6012 value: function _contentForClosure(closure) {
6013 var content = this.document.markStructureContent(this.dictionary.data.S);
6014 closure();
6015 this.document.endMarkedContent();
6016
6017 this._addContentToParentTree(content);
6018
6019 return content;
6020 }
6021 }, {
6022 key: "_isFlushable",
6023 value: function _isFlushable() {
6024 if (!this.dictionary.data.P || !this._ended) {
6025 return false;
6026 }
6027
6028 return this._children.every(function (child) {
6029 if (typeof child === 'function') {
6030 return false;
6031 }
6032
6033 if (child instanceof PDFStructureElement) {
6034 return child._isFlushable();
6035 }
6036
6037 return true;
6038 });
6039 }
6040 }, {
6041 key: "_flush",
6042 value: function _flush() {
6043 var _this4 = this;
6044
6045 if (this._flushed || !this._isFlushable()) {
6046 return;
6047 }
6048
6049 this.dictionary.data.K = [];
6050
6051 this._children.forEach(function (child) {
6052 return _this4._flushChild(child);
6053 });
6054
6055 this.dictionary.end(); // free memory used by children; the dictionary itself may still be
6056 // referenced by a parent structure element or root, but we can
6057 // at least trim the tree here
6058
6059 this._children = [];
6060 this.dictionary.data.K = null;
6061 this._flushed = true;
6062 }
6063 }, {
6064 key: "_flushChild",
6065 value: function _flushChild(child) {
6066 var _this5 = this;
6067
6068 if (child instanceof PDFStructureElement) {
6069 this.dictionary.data.K.push(child.dictionary);
6070 }
6071
6072 if (child instanceof PDFStructureContent) {
6073 child.refs.forEach(function (_ref2) {
6074 var pageRef = _ref2.pageRef,
6075 mcid = _ref2.mcid;
6076
6077 if (!_this5.dictionary.data.Pg) {
6078 _this5.dictionary.data.Pg = pageRef;
6079 }
6080
6081 if (_this5.dictionary.data.Pg === pageRef) {
6082 _this5.dictionary.data.K.push(mcid);
6083 } else {
6084 _this5.dictionary.data.K.push({
6085 Type: "MCR",
6086 Pg: pageRef,
6087 MCID: mcid
6088 });
6089 }
6090 });
6091 }
6092 }
6093 }]);
6094
6095 return PDFStructureElement;
6096}();
6097
6098var PDFNumberTree = /*#__PURE__*/function (_PDFTree) {
6099 _inherits(PDFNumberTree, _PDFTree);
6100
6101 var _super = _createSuper(PDFNumberTree);
6102
6103 function PDFNumberTree() {
6104 _classCallCheck(this, PDFNumberTree);
6105
6106 return _super.apply(this, arguments);
6107 }
6108
6109 _createClass(PDFNumberTree, [{
6110 key: "_compareKeys",
6111 value: function _compareKeys(a, b) {
6112 return parseInt(a) - parseInt(b);
6113 }
6114 }, {
6115 key: "_keysName",
6116 value: function _keysName() {
6117 return "Nums";
6118 }
6119 }, {
6120 key: "_dataForKey",
6121 value: function _dataForKey(k) {
6122 return parseInt(k);
6123 }
6124 }]);
6125
6126 return PDFNumberTree;
6127}(PDFTree);
6128
6129var MarkingsMixin = {
6130 initMarkings: function initMarkings(options) {
6131 this.structChildren = [];
6132
6133 if (options.tagged) {
6134 this.getMarkInfoDictionary().data.Marked = true;
6135 this.getStructTreeRoot();
6136 }
6137 },
6138 markContent: function markContent(tag) {
6139 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
6140
6141 if (tag === 'Artifact' || options && options.mcid) {
6142 var toClose = 0;
6143 this.page.markings.forEach(function (marking) {
6144 if (toClose || marking.structContent || marking.tag === 'Artifact') {
6145 toClose++;
6146 }
6147 });
6148
6149 while (toClose--) {
6150 this.endMarkedContent();
6151 }
6152 }
6153
6154 if (!options) {
6155 this.page.markings.push({
6156 tag: tag
6157 });
6158 this.addContent("/".concat(tag, " BMC"));
6159 return this;
6160 }
6161
6162 this.page.markings.push({
6163 tag: tag,
6164 options: options
6165 });
6166 var dictionary = {};
6167
6168 if (typeof options.mcid !== 'undefined') {
6169 dictionary.MCID = options.mcid;
6170 }
6171
6172 if (tag === 'Artifact') {
6173 if (typeof options.type === 'string') {
6174 dictionary.Type = options.type;
6175 }
6176
6177 if (Array.isArray(options.bbox)) {
6178 dictionary.BBox = [options.bbox[0], this.page.height - options.bbox[3], options.bbox[2], this.page.height - options.bbox[1]];
6179 }
6180
6181 if (Array.isArray(options.attached) && options.attached.every(function (val) {
6182 return typeof val === 'string';
6183 })) {
6184 dictionary.Attached = options.attached;
6185 }
6186 }
6187
6188 if (tag === 'Span') {
6189 if (options.lang) {
6190 dictionary.Lang = new String(options.lang);
6191 }
6192
6193 if (options.alt) {
6194 dictionary.Alt = new String(options.alt);
6195 }
6196
6197 if (options.expanded) {
6198 dictionary.E = new String(options.expanded);
6199 }
6200
6201 if (options.actual) {
6202 dictionary.ActualText = new String(options.actual);
6203 }
6204 }
6205
6206 this.addContent("/".concat(tag, " ").concat(PDFObject.convert(dictionary), " BDC"));
6207 return this;
6208 },
6209 markStructureContent: function markStructureContent(tag) {
6210 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6211 var pageStructParents = this.getStructParentTree().get(this.page.structParentTreeKey);
6212 var mcid = pageStructParents.length;
6213 pageStructParents.push(null);
6214 this.markContent(tag, _objectSpread2(_objectSpread2({}, options), {}, {
6215 mcid: mcid
6216 }));
6217 var structContent = new PDFStructureContent(this.page.dictionary, mcid);
6218 this.page.markings.slice(-1)[0].structContent = structContent;
6219 return structContent;
6220 },
6221 endMarkedContent: function endMarkedContent() {
6222 this.page.markings.pop();
6223 this.addContent('EMC');
6224 return this;
6225 },
6226 struct: function struct(type) {
6227 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6228 var children = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
6229 return new PDFStructureElement(this, type, options, children);
6230 },
6231 addStructure: function addStructure(structElem) {
6232 var structTreeRoot = this.getStructTreeRoot();
6233 structElem.setParent(structTreeRoot);
6234 structElem.setAttached();
6235 this.structChildren.push(structElem);
6236
6237 if (!structTreeRoot.data.K) {
6238 structTreeRoot.data.K = [];
6239 }
6240
6241 structTreeRoot.data.K.push(structElem.dictionary);
6242 return this;
6243 },
6244 initPageMarkings: function initPageMarkings(pageMarkings) {
6245 var _this = this;
6246
6247 pageMarkings.forEach(function (marking) {
6248 if (marking.structContent) {
6249 var structContent = marking.structContent;
6250
6251 var newStructContent = _this.markStructureContent(marking.tag, marking.options);
6252
6253 structContent.push(newStructContent);
6254 _this.page.markings.slice(-1)[0].structContent = structContent;
6255 } else {
6256 _this.markContent(marking.tag, marking.options);
6257 }
6258 });
6259 },
6260 endPageMarkings: function endPageMarkings(page) {
6261 var pageMarkings = page.markings;
6262 pageMarkings.forEach(function () {
6263 return page.write('EMC');
6264 });
6265 page.markings = [];
6266 return pageMarkings;
6267 },
6268 getMarkInfoDictionary: function getMarkInfoDictionary() {
6269 if (!this._root.data.MarkInfo) {
6270 this._root.data.MarkInfo = this.ref({});
6271 }
6272
6273 return this._root.data.MarkInfo;
6274 },
6275 getStructTreeRoot: function getStructTreeRoot() {
6276 if (!this._root.data.StructTreeRoot) {
6277 this._root.data.StructTreeRoot = this.ref({
6278 Type: 'StructTreeRoot',
6279 ParentTree: new PDFNumberTree(),
6280 ParentTreeNextKey: 0
6281 });
6282 }
6283
6284 return this._root.data.StructTreeRoot;
6285 },
6286 getStructParentTree: function getStructParentTree() {
6287 return this.getStructTreeRoot().data.ParentTree;
6288 },
6289 createStructParentTreeNextKey: function createStructParentTreeNextKey() {
6290 // initialise the MarkInfo dictionary
6291 this.getMarkInfoDictionary();
6292 var structTreeRoot = this.getStructTreeRoot();
6293 var key = structTreeRoot.data.ParentTreeNextKey++;
6294 structTreeRoot.data.ParentTree.add(key, []);
6295 return key;
6296 },
6297 endMarkings: function endMarkings() {
6298 var structTreeRoot = this._root.data.StructTreeRoot;
6299
6300 if (structTreeRoot) {
6301 structTreeRoot.end();
6302 this.structChildren.forEach(function (structElem) {
6303 return structElem.end();
6304 });
6305 }
6306
6307 if (this._root.data.MarkInfo) {
6308 this._root.data.MarkInfo.end();
6309 }
6310 }
6311};
6312
6313var FIELD_FLAGS = {
6314 readOnly: 1,
6315 required: 2,
6316 noExport: 4,
6317 multiline: 0x1000,
6318 password: 0x2000,
6319 toggleToOffButton: 0x4000,
6320 radioButton: 0x8000,
6321 pushButton: 0x10000,
6322 combo: 0x20000,
6323 edit: 0x40000,
6324 sort: 0x80000,
6325 multiSelect: 0x200000,
6326 noSpell: 0x400000
6327};
6328var FIELD_JUSTIFY = {
6329 left: 0,
6330 center: 1,
6331 right: 2
6332};
6333var VALUE_MAP = {
6334 value: 'V',
6335 defaultValue: 'DV'
6336};
6337var FORMAT_SPECIAL = {
6338 zip: '0',
6339 zipPlus4: '1',
6340 zip4: '1',
6341 phone: '2',
6342 ssn: '3'
6343};
6344var FORMAT_DEFAULT = {
6345 number: {
6346 nDec: 0,
6347 sepComma: false,
6348 negStyle: 'MinusBlack',
6349 currency: '',
6350 currencyPrepend: true
6351 },
6352 percent: {
6353 nDec: 0,
6354 sepComma: false
6355 }
6356};
6357var AcroFormMixin = {
6358 /**
6359 * Must call if adding AcroForms to a document. Must also call font() before
6360 * this method to set the default font.
6361 */
6362 initForm: function initForm() {
6363 if (!this._font) {
6364 throw new Error('Must set a font before calling initForm method');
6365 }
6366
6367 this._acroform = {
6368 fonts: {},
6369 defaultFont: this._font.name
6370 };
6371 this._acroform.fonts[this._font.id] = this._font.ref();
6372 var data = {
6373 Fields: [],
6374 NeedAppearances: true,
6375 DA: new String("/".concat(this._font.id, " 0 Tf 0 g")),
6376 DR: {
6377 Font: {}
6378 }
6379 };
6380 data.DR.Font[this._font.id] = this._font.ref();
6381 var AcroForm = this.ref(data);
6382 this._root.data.AcroForm = AcroForm;
6383 return this;
6384 },
6385
6386 /**
6387 * Called automatically by document.js
6388 */
6389 endAcroForm: function endAcroForm() {
6390 var _this = this;
6391
6392 if (this._root.data.AcroForm) {
6393 if (!Object.keys(this._acroform.fonts).length && !this._acroform.defaultFont) {
6394 throw new Error('No fonts specified for PDF form');
6395 }
6396
6397 var fontDict = this._root.data.AcroForm.data.DR.Font;
6398 Object.keys(this._acroform.fonts).forEach(function (name) {
6399 fontDict[name] = _this._acroform.fonts[name];
6400 });
6401
6402 this._root.data.AcroForm.data.Fields.forEach(function (fieldRef) {
6403 _this._endChild(fieldRef);
6404 });
6405
6406 this._root.data.AcroForm.end();
6407 }
6408
6409 return this;
6410 },
6411 _endChild: function _endChild(ref) {
6412 var _this2 = this;
6413
6414 if (Array.isArray(ref.data.Kids)) {
6415 ref.data.Kids.forEach(function (childRef) {
6416 _this2._endChild(childRef);
6417 });
6418 ref.end();
6419 }
6420
6421 return this;
6422 },
6423
6424 /**
6425 * Creates and adds a form field to the document. Form fields are intermediate
6426 * nodes in a PDF form that are used to specify form name heirarchy and form
6427 * value defaults.
6428 * @param {string} name - field name (T attribute in field dictionary)
6429 * @param {object} options - other attributes to include in field dictionary
6430 */
6431 formField: function formField(name) {
6432 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6433
6434 var fieldDict = this._fieldDict(name, null, options);
6435
6436 var fieldRef = this.ref(fieldDict);
6437
6438 this._addToParent(fieldRef);
6439
6440 return fieldRef;
6441 },
6442
6443 /**
6444 * Creates and adds a Form Annotation to the document. Form annotations are
6445 * called Widget annotations internally within a PDF file.
6446 * @param {string} name - form field name (T attribute of widget annotation
6447 * dictionary)
6448 * @param {number} x
6449 * @param {number} y
6450 * @param {number} w
6451 * @param {number} h
6452 * @param {object} options
6453 */
6454 formAnnotation: function formAnnotation(name, type, x, y, w, h) {
6455 var options = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {};
6456
6457 var fieldDict = this._fieldDict(name, type, options);
6458
6459 fieldDict.Subtype = 'Widget';
6460
6461 if (fieldDict.F === undefined) {
6462 fieldDict.F = 4; // print the annotation
6463 } // Add Field annot to page, and get it's ref
6464
6465
6466 this.annotate(x, y, w, h, fieldDict);
6467 var annotRef = this.page.annotations[this.page.annotations.length - 1];
6468 return this._addToParent(annotRef);
6469 },
6470 formText: function formText(name, x, y, w, h) {
6471 var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
6472 return this.formAnnotation(name, 'text', x, y, w, h, options);
6473 },
6474 formPushButton: function formPushButton(name, x, y, w, h) {
6475 var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
6476 return this.formAnnotation(name, 'pushButton', x, y, w, h, options);
6477 },
6478 formCombo: function formCombo(name, x, y, w, h) {
6479 var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
6480 return this.formAnnotation(name, 'combo', x, y, w, h, options);
6481 },
6482 formList: function formList(name, x, y, w, h) {
6483 var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
6484 return this.formAnnotation(name, 'list', x, y, w, h, options);
6485 },
6486 formRadioButton: function formRadioButton(name, x, y, w, h) {
6487 var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
6488 return this.formAnnotation(name, 'radioButton', x, y, w, h, options);
6489 },
6490 formCheckbox: function formCheckbox(name, x, y, w, h) {
6491 var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
6492 return this.formAnnotation(name, 'checkbox', x, y, w, h, options);
6493 },
6494 _addToParent: function _addToParent(fieldRef) {
6495 var parent = fieldRef.data.Parent;
6496
6497 if (parent) {
6498 if (!parent.data.Kids) {
6499 parent.data.Kids = [];
6500 }
6501
6502 parent.data.Kids.push(fieldRef);
6503 } else {
6504 this._root.data.AcroForm.data.Fields.push(fieldRef);
6505 }
6506
6507 return this;
6508 },
6509 _fieldDict: function _fieldDict(name, type) {
6510 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
6511
6512 if (!this._acroform) {
6513 throw new Error('Call document.initForms() method before adding form elements to document');
6514 }
6515
6516 var opts = Object.assign({}, options);
6517
6518 if (type !== null) {
6519 opts = this._resolveType(type, options);
6520 }
6521
6522 opts = this._resolveFlags(opts);
6523 opts = this._resolveJustify(opts);
6524 opts = this._resolveFont(opts);
6525 opts = this._resolveStrings(opts);
6526 opts = this._resolveColors(opts);
6527 opts = this._resolveFormat(opts);
6528 opts.T = new String(name);
6529
6530 if (opts.parent) {
6531 opts.Parent = opts.parent;
6532 delete opts.parent;
6533 }
6534
6535 return opts;
6536 },
6537 _resolveType: function _resolveType(type, opts) {
6538 if (type === 'text') {
6539 opts.FT = 'Tx';
6540 } else if (type === 'pushButton') {
6541 opts.FT = 'Btn';
6542 opts.pushButton = true;
6543 } else if (type === 'radioButton') {
6544 opts.FT = 'Btn';
6545 opts.radioButton = true;
6546 } else if (type === 'checkbox') {
6547 opts.FT = 'Btn';
6548 } else if (type === 'combo') {
6549 opts.FT = 'Ch';
6550 opts.combo = true;
6551 } else if (type === 'list') {
6552 opts.FT = 'Ch';
6553 } else {
6554 throw new Error("Invalid form annotation type '".concat(type, "'"));
6555 }
6556
6557 return opts;
6558 },
6559 _resolveFormat: function _resolveFormat(opts) {
6560 var f = opts.format;
6561
6562 if (f && f.type) {
6563 var fnKeystroke;
6564 var fnFormat;
6565 var params = '';
6566
6567 if (FORMAT_SPECIAL[f.type] !== undefined) {
6568 fnKeystroke = "AFSpecial_Keystroke";
6569 fnFormat = "AFSpecial_Format";
6570 params = FORMAT_SPECIAL[f.type];
6571 } else {
6572 var format = f.type.charAt(0).toUpperCase() + f.type.slice(1);
6573 fnKeystroke = "AF".concat(format, "_Keystroke");
6574 fnFormat = "AF".concat(format, "_Format");
6575
6576 if (f.type === 'date') {
6577 fnKeystroke += 'Ex';
6578 params = String(f.param);
6579 } else if (f.type === 'time') {
6580 params = String(f.param);
6581 } else if (f.type === 'number') {
6582 var p = Object.assign({}, FORMAT_DEFAULT.number, f);
6583 params = String([String(p.nDec), p.sepComma ? '0' : '1', '"' + p.negStyle + '"', 'null', '"' + p.currency + '"', String(p.currencyPrepend)].join(','));
6584 } else if (f.type === 'percent') {
6585 var _p = Object.assign({}, FORMAT_DEFAULT.percent, f);
6586
6587 params = String([String(_p.nDec), _p.sepComma ? '0' : '1'].join(','));
6588 }
6589 }
6590
6591 opts.AA = opts.AA ? opts.AA : {};
6592 opts.AA.K = {
6593 S: 'JavaScript',
6594 JS: new String("".concat(fnKeystroke, "(").concat(params, ");"))
6595 };
6596 opts.AA.F = {
6597 S: 'JavaScript',
6598 JS: new String("".concat(fnFormat, "(").concat(params, ");"))
6599 };
6600 }
6601
6602 delete opts.format;
6603 return opts;
6604 },
6605 _resolveColors: function _resolveColors(opts) {
6606 var color = this._normalizeColor(opts.backgroundColor);
6607
6608 if (color) {
6609 if (!opts.MK) {
6610 opts.MK = {};
6611 }
6612
6613 opts.MK.BG = color;
6614 }
6615
6616 color = this._normalizeColor(opts.borderColor);
6617
6618 if (color) {
6619 if (!opts.MK) {
6620 opts.MK = {};
6621 }
6622
6623 opts.MK.BC = color;
6624 }
6625
6626 delete opts.backgroundColor;
6627 delete opts.borderColor;
6628 return opts;
6629 },
6630 _resolveFlags: function _resolveFlags(options) {
6631 var result = 0;
6632 Object.keys(options).forEach(function (key) {
6633 if (FIELD_FLAGS[key]) {
6634 if (options[key]) {
6635 result |= FIELD_FLAGS[key];
6636 }
6637
6638 delete options[key];
6639 }
6640 });
6641
6642 if (result !== 0) {
6643 options.Ff = options.Ff ? options.Ff : 0;
6644 options.Ff |= result;
6645 }
6646
6647 return options;
6648 },
6649 _resolveJustify: function _resolveJustify(options) {
6650 var result = 0;
6651
6652 if (options.align !== undefined) {
6653 if (typeof FIELD_JUSTIFY[options.align] === 'number') {
6654 result = FIELD_JUSTIFY[options.align];
6655 }
6656
6657 delete options.align;
6658 }
6659
6660 if (result !== 0) {
6661 options.Q = result; // default
6662 }
6663
6664 return options;
6665 },
6666 _resolveFont: function _resolveFont(options) {
6667 // add current font to document-level AcroForm dict if necessary
6668 if (this._acroform.fonts[this._font.id] === null) {
6669 this._acroform.fonts[this._font.id] = this._font.ref();
6670 } // add current font to field's resource dict (RD) if not the default acroform font
6671
6672
6673 if (this._acroform.defaultFont !== this._font.name) {
6674 options.DR = {
6675 Font: {}
6676 }; // Get the fontSize option. If not set use auto sizing
6677
6678 var fontSize = options.fontSize || 0;
6679 options.DR.Font[this._font.id] = this._font.ref();
6680 options.DA = new String("/".concat(this._font.id, " ").concat(fontSize, " Tf 0 g"));
6681 }
6682
6683 return options;
6684 },
6685 _resolveStrings: function _resolveStrings(options) {
6686 var select = [];
6687
6688 function appendChoices(a) {
6689 if (Array.isArray(a)) {
6690 for (var idx = 0; idx < a.length; idx++) {
6691 if (typeof a[idx] === 'string') {
6692 select.push(new String(a[idx]));
6693 } else {
6694 select.push(a[idx]);
6695 }
6696 }
6697 }
6698 }
6699
6700 appendChoices(options.Opt);
6701
6702 if (options.select) {
6703 appendChoices(options.select);
6704 delete options.select;
6705 }
6706
6707 if (select.length) {
6708 options.Opt = select;
6709 }
6710
6711 Object.keys(VALUE_MAP).forEach(function (key) {
6712 if (options[key] !== undefined) {
6713 options[VALUE_MAP[key]] = options[key];
6714 delete options[key];
6715 }
6716 });
6717 ['V', 'DV'].forEach(function (key) {
6718 if (typeof options[key] === 'string') {
6719 options[key] = new String(options[key]);
6720 }
6721 });
6722
6723 if (options.MK && options.MK.CA) {
6724 options.MK.CA = new String(options.MK.CA);
6725 }
6726
6727 if (options.label) {
6728 options.MK = options.MK ? options.MK : {};
6729 options.MK.CA = new String(options.label);
6730 delete options.label;
6731 }
6732
6733 return options;
6734 }
6735};
6736
6737var AttachmentsMixin = {
6738 /**
6739 * Embed contents of `src` in PDF
6740 * @param {Buffer | ArrayBuffer | string} src input Buffer, ArrayBuffer, base64 encoded string or path to file
6741 * @param {object} options
6742 * * options.name: filename to be shown in PDF, will use `src` if none set
6743 * * options.type: filetype to be shown in PDF
6744 * * options.description: description to be shown in PDF
6745 * * options.hidden: if true, do not add attachment to EmbeddedFiles dictionary. Useful for file attachment annotations
6746 * * options.creationDate: override creation date
6747 * * options.modifiedDate: override modified date
6748 * @returns filespec reference
6749 */
6750 file: function file(src) {
6751 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6752 options.name = options.name || src;
6753 var refBody = {
6754 Type: 'EmbeddedFile',
6755 Params: {}
6756 };
6757 var data;
6758
6759 if (!src) {
6760 throw new Error('No src specified');
6761 }
6762
6763 if (Buffer.isBuffer(src)) {
6764 data = src;
6765 } else if (src instanceof ArrayBuffer) {
6766 data = Buffer.from(new Uint8Array(src));
6767 } else {
6768 var match;
6769
6770 if (match = /^data:(.*?);base64,(.*)$/.exec(src)) {
6771 if (match[1]) {
6772 refBody.Subtype = match[1].replace('/', '#2F');
6773 }
6774
6775 data = Buffer.from(match[2], 'base64');
6776 } else {
6777 data = fs.readFileSync(src);
6778
6779 if (!data) {
6780 throw new Error("Could not read contents of file at filepath ".concat(src));
6781 } // update CreationDate and ModDate
6782
6783
6784 var _fs$statSync = fs.statSync(src),
6785 birthtime = _fs$statSync.birthtime,
6786 ctime = _fs$statSync.ctime;
6787
6788 refBody.Params.CreationDate = birthtime;
6789 refBody.Params.ModDate = ctime;
6790 }
6791 } // override creation date and modified date
6792
6793
6794 if (options.creationDate instanceof Date) {
6795 refBody.Params.CreationDate = options.creationDate;
6796 }
6797
6798 if (options.modifiedDate instanceof Date) {
6799 refBody.Params.ModDate = options.modifiedDate;
6800 } // add optional subtype
6801
6802
6803 if (options.type) {
6804 refBody.Subtype = options.type.replace('/', '#2F');
6805 } // add checksum and size information
6806
6807
6808 var checksum = CryptoJS.MD5(CryptoJS.lib.WordArray.create(new Uint8Array(data)));
6809 refBody.Params.CheckSum = new String(checksum);
6810 refBody.Params.Size = data.byteLength; // save some space when embedding the same file again
6811 // if a file with the same name and metadata exists, reuse its reference
6812
6813 var ref;
6814 if (!this._fileRegistry) this._fileRegistry = {};
6815 var file = this._fileRegistry[options.name];
6816
6817 if (file && isEqual(refBody, file)) {
6818 ref = file.ref;
6819 } else {
6820 ref = this.ref(refBody);
6821 ref.end(data);
6822 this._fileRegistry[options.name] = _objectSpread2(_objectSpread2({}, refBody), {}, {
6823 ref: ref
6824 });
6825 } // add filespec for embedded file
6826
6827
6828 var fileSpecBody = {
6829 Type: 'Filespec',
6830 F: new String(options.name),
6831 EF: {
6832 F: ref
6833 },
6834 UF: new String(options.name)
6835 };
6836
6837 if (options.description) {
6838 fileSpecBody.Desc = new String(options.description);
6839 }
6840
6841 var filespec = this.ref(fileSpecBody);
6842 filespec.end();
6843
6844 if (!options.hidden) {
6845 this.addNamedEmbeddedFile(options.name, filespec);
6846 }
6847
6848 return filespec;
6849 }
6850};
6851/** check two embedded file metadata objects for equality */
6852
6853function isEqual(a, b) {
6854 return a.Subtype === b.Subtype && a.Params.CheckSum.toString() === b.Params.CheckSum.toString() && a.Params.Size === b.Params.Size && a.Params.CreationDate === b.Params.CreationDate && a.Params.ModDate === b.Params.ModDate;
6855}
6856
6857var PDFA = {
6858 initPDFA: function initPDFA(pSubset) {
6859 if (pSubset.charAt(pSubset.length - 3) === '-') {
6860 this.subset_conformance = pSubset.charAt(pSubset.length - 1).toUpperCase();
6861 this.subset = parseInt(pSubset.charAt(pSubset.length - 2));
6862 } else {
6863 // Default to Basic conformance when user doesn't specify
6864 this.subset_conformance = 'B';
6865 this.subset = parseInt(pSubset.charAt(pSubset.length - 1));
6866 }
6867 },
6868 endSubset: function endSubset() {
6869 this._addPdfaMetadata();
6870
6871 var jsPath = "".concat(__dirname, "/data/sRGB_IEC61966_2_1.icc");
6872 var jestPath = "".concat(__dirname, "/../color_profiles/sRGB_IEC61966_2_1.icc");
6873
6874 this._addColorOutputIntent(fs.existsSync(jsPath) ? jsPath : jestPath);
6875 },
6876 _addColorOutputIntent: function _addColorOutputIntent(pICCPath) {
6877 var iccProfile = fs.readFileSync(pICCPath);
6878 var colorProfileRef = this.ref({
6879 Length: iccProfile.length,
6880 N: 3
6881 });
6882 colorProfileRef.write(iccProfile);
6883 colorProfileRef.end();
6884 var intentRef = this.ref({
6885 Type: 'OutputIntent',
6886 S: 'GTS_PDFA1',
6887 Info: new String('sRGB IEC61966-2.1'),
6888 OutputConditionIdentifier: new String('sRGB IEC61966-2.1'),
6889 DestOutputProfile: colorProfileRef
6890 });
6891 intentRef.end();
6892 this._root.data.OutputIntents = [intentRef];
6893 },
6894 _getPdfaid: function _getPdfaid() {
6895 return "\n <rdf:Description xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\" rdf:about=\"\">\n <pdfaid:part>".concat(this.subset, "</pdfaid:part>\n <pdfaid:conformance>").concat(this.subset_conformance, "</pdfaid:conformance>\n </rdf:Description>\n ");
6896 },
6897 _addPdfaMetadata: function _addPdfaMetadata() {
6898 this.appendXML(this._getPdfaid());
6899 }
6900};
6901
6902var PDFUA = {
6903 initPDFUA: function initPDFUA() {
6904 this.subset = 1;
6905 },
6906 endSubset: function endSubset() {
6907 this._addPdfuaMetadata();
6908 },
6909 _addPdfuaMetadata: function _addPdfuaMetadata() {
6910 this.appendXML(this._getPdfuaid());
6911 },
6912 _getPdfuaid: function _getPdfuaid() {
6913 return "\n <rdf:Description xmlns:pdfuaid=\"http://www.aiim.org/pdfua/ns/id/\" rdf:about=\"\">\n <pdfuaid:part>".concat(this.subset, "</pdfuaid:part>\n </rdf:Description>\n ");
6914 }
6915};
6916
6917var SubsetMixin = {
6918 _importSubset: function _importSubset(subset) {
6919 Object.assign(this, subset);
6920 },
6921 initSubset: function initSubset(options) {
6922 switch (options.subset) {
6923 case 'PDF/A-1':
6924 case 'PDF/A-1a':
6925 case 'PDF/A-1b':
6926 case 'PDF/A-2':
6927 case 'PDF/A-2a':
6928 case 'PDF/A-2b':
6929 case 'PDF/A-3':
6930 case 'PDF/A-3a':
6931 case 'PDF/A-3b':
6932 this._importSubset(PDFA);
6933
6934 this.initPDFA(options.subset);
6935 break;
6936
6937 case 'PDF/UA':
6938 this._importSubset(PDFUA);
6939
6940 this.initPDFUA();
6941 break;
6942 }
6943 }
6944};
6945
6946var PDFMetadata = /*#__PURE__*/function () {
6947 function PDFMetadata() {
6948 _classCallCheck(this, PDFMetadata);
6949
6950 this._metadata = "\n <?xpacket begin=\"\uFEFF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n <x:xmpmeta xmlns:x=\"adobe:ns:meta/\">\n <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n ";
6951 }
6952
6953 _createClass(PDFMetadata, [{
6954 key: "_closeTags",
6955 value: function _closeTags() {
6956 this._metadata = this._metadata.concat("\n </rdf:RDF>\n </x:xmpmeta>\n <?xpacket end=\"w\"?>\n ");
6957 }
6958 }, {
6959 key: "append",
6960 value: function append(xml) {
6961 var newline = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
6962 this._metadata = this._metadata.concat(xml);
6963 if (newline) this._metadata = this._metadata.concat('\n');
6964 }
6965 }, {
6966 key: "getXML",
6967 value: function getXML() {
6968 return this._metadata;
6969 }
6970 }, {
6971 key: "getLength",
6972 value: function getLength() {
6973 return this._metadata.length;
6974 }
6975 }, {
6976 key: "end",
6977 value: function end() {
6978 this._closeTags();
6979
6980 this._metadata = this._metadata.trim();
6981 }
6982 }]);
6983
6984 return PDFMetadata;
6985}();
6986
6987var MetadataMixin = {
6988 initMetadata: function initMetadata() {
6989 this.metadata = new PDFMetadata();
6990 },
6991 appendXML: function appendXML(xml) {
6992 var newline = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
6993 this.metadata.append(xml, newline);
6994 },
6995 _addInfo: function _addInfo() {
6996 this.appendXML("\n <rdf:Description rdf:about=\"\" xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\">\n <xmp:CreateDate>".concat(this.info.CreationDate.toISOString().split('.')[0] + "Z", "</xmp:CreateDate>\n <xmp:CreatorTool>").concat(this.info.Creator, "</xmp:CreatorTool>\n </rdf:Description>\n "));
6997
6998 if (this.info.Title || this.info.Author || this.info.Subject) {
6999 this.appendXML("\n <rdf:Description rdf:about=\"\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n ");
7000
7001 if (this.info.Title) {
7002 this.appendXML("\n <dc:title>\n <rdf:Alt>\n <rdf:li xml:lang=\"x-default\">".concat(this.info.Title, "</rdf:li>\n </rdf:Alt>\n </dc:title>\n "));
7003 }
7004
7005 if (this.info.Author) {
7006 this.appendXML("\n <dc:creator>\n <rdf:Seq>\n <rdf:li>".concat(this.info.Author, "</rdf:li>\n </rdf:Seq>\n </dc:creator>\n "));
7007 }
7008
7009 if (this.info.Subject) {
7010 this.appendXML("\n <dc:description>\n <rdf:Alt>\n <rdf:li xml:lang=\"x-default\">".concat(this.info.Subject, "</rdf:li>\n </rdf:Alt>\n </dc:description>\n "));
7011 }
7012
7013 this.appendXML("\n </rdf:Description>\n ");
7014 }
7015
7016 this.appendXML("\n <rdf:Description rdf:about=\"\" xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n <pdf:Producer>".concat(this.info.Creator, "</pdf:Producer>"), false);
7017
7018 if (this.info.Keywords) {
7019 this.appendXML("\n <pdf:Keywords>".concat(this.info.Keywords, "</pdf:Keywords>"), false);
7020 }
7021
7022 this.appendXML("\n </rdf:Description>\n ");
7023 },
7024 endMetadata: function endMetadata() {
7025 this._addInfo();
7026
7027 this.metadata.end();
7028 /*
7029 Metadata was introduced in PDF 1.4, so adding it to 1.3
7030 will likely only take up more space.
7031 */
7032
7033 if (this.version != 1.3) {
7034 this.metadataRef = this.ref({
7035 length: this.metadata.getLength(),
7036 Type: 'Metadata',
7037 Subtype: 'XML'
7038 });
7039 this.metadataRef.compress = false;
7040 this.metadataRef.write(Buffer.from(this.metadata.getXML(), 'utf-8'));
7041 this.metadataRef.end();
7042 this._root.data.Metadata = this.metadataRef;
7043 }
7044 }
7045};
7046
7047var PDFDocument = /*#__PURE__*/function (_stream$Readable) {
7048 _inherits(PDFDocument, _stream$Readable);
7049
7050 var _super = _createSuper(PDFDocument);
7051
7052 function PDFDocument() {
7053 var _this;
7054
7055 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
7056
7057 _classCallCheck(this, PDFDocument);
7058
7059 _this = _super.call(this, options);
7060 _this.options = options; // PDF version
7061
7062 switch (options.pdfVersion) {
7063 case '1.4':
7064 _this.version = 1.4;
7065 break;
7066
7067 case '1.5':
7068 _this.version = 1.5;
7069 break;
7070
7071 case '1.6':
7072 _this.version = 1.6;
7073 break;
7074
7075 case '1.7':
7076 case '1.7ext3':
7077 _this.version = 1.7;
7078 break;
7079
7080 default:
7081 _this.version = 1.3;
7082 break;
7083 } // Whether streams should be compressed
7084
7085
7086 _this.compress = _this.options.compress != null ? _this.options.compress : true;
7087 _this._pageBuffer = [];
7088 _this._pageBufferStart = 0; // The PDF object store
7089
7090 _this._offsets = [];
7091 _this._waiting = 0;
7092 _this._ended = false;
7093 _this._offset = 0;
7094
7095 var Pages = _this.ref({
7096 Type: 'Pages',
7097 Count: 0,
7098 Kids: []
7099 });
7100
7101 var Names = _this.ref({
7102 Dests: new PDFNameTree()
7103 });
7104
7105 _this._root = _this.ref({
7106 Type: 'Catalog',
7107 Pages: Pages,
7108 Names: Names
7109 });
7110
7111 if (_this.options.lang) {
7112 _this._root.data.Lang = new String(_this.options.lang);
7113 } // The current page
7114
7115
7116 _this.page = null; // Initialize mixins
7117
7118 _this.initMetadata();
7119
7120 _this.initColor();
7121
7122 _this.initVector();
7123
7124 _this.initFonts(options.font);
7125
7126 _this.initText();
7127
7128 _this.initImages();
7129
7130 _this.initOutline();
7131
7132 _this.initMarkings(options);
7133
7134 _this.initSubset(options); // Initialize the metadata
7135
7136
7137 _this.info = {
7138 Producer: 'PDFKit',
7139 Creator: 'PDFKit',
7140 CreationDate: new Date()
7141 };
7142
7143 if (_this.options.info) {
7144 for (var key in _this.options.info) {
7145 var val = _this.options.info[key];
7146 _this.info[key] = val;
7147 }
7148 }
7149
7150 if (_this.options.displayTitle) {
7151 _this._root.data.ViewerPreferences = _this.ref({
7152 DisplayDocTitle: true
7153 });
7154 } // Generate file ID
7155
7156
7157 _this._id = PDFSecurity.generateFileID(_this.info); // Initialize security settings
7158
7159 _this._security = PDFSecurity.create(_assertThisInitialized(_this), options); // Write the header
7160 // PDF version
7161
7162 _this._write("%PDF-".concat(_this.version)); // 4 binary chars, as recommended by the spec
7163
7164
7165 _this._write('%\xFF\xFF\xFF\xFF'); // Add the first page
7166
7167
7168 if (_this.options.autoFirstPage !== false) {
7169 _this.addPage();
7170 }
7171
7172 return _this;
7173 }
7174
7175 _createClass(PDFDocument, [{
7176 key: "addPage",
7177 value: function addPage(options) {
7178 if (options == null) {
7179 options = this.options;
7180 } // end the current page if needed
7181
7182
7183 if (!this.options.bufferPages) {
7184 this.flushPages();
7185 } // create a page object
7186
7187
7188 this.page = new PDFPage(this, options);
7189
7190 this._pageBuffer.push(this.page); // add the page to the object store
7191
7192
7193 var pages = this._root.data.Pages.data;
7194 pages.Kids.push(this.page.dictionary);
7195 pages.Count++; // reset x and y coordinates
7196
7197 this.x = this.page.margins.left;
7198 this.y = this.page.margins.top; // flip PDF coordinate system so that the origin is in
7199 // the top left rather than the bottom left
7200
7201 this._ctm = [1, 0, 0, 1, 0, 0];
7202 this.transform(1, 0, 0, -1, 0, this.page.height);
7203 this.emit('pageAdded');
7204 return this;
7205 }
7206 }, {
7207 key: "continueOnNewPage",
7208 value: function continueOnNewPage(options) {
7209 var pageMarkings = this.endPageMarkings(this.page);
7210 this.addPage(options);
7211 this.initPageMarkings(pageMarkings);
7212 return this;
7213 }
7214 }, {
7215 key: "bufferedPageRange",
7216 value: function bufferedPageRange() {
7217 return {
7218 start: this._pageBufferStart,
7219 count: this._pageBuffer.length
7220 };
7221 }
7222 }, {
7223 key: "switchToPage",
7224 value: function switchToPage(n) {
7225 var page;
7226
7227 if (!(page = this._pageBuffer[n - this._pageBufferStart])) {
7228 throw new Error("switchToPage(".concat(n, ") out of bounds, current buffer covers pages ").concat(this._pageBufferStart, " to ").concat(this._pageBufferStart + this._pageBuffer.length - 1));
7229 }
7230
7231 return this.page = page;
7232 }
7233 }, {
7234 key: "flushPages",
7235 value: function flushPages() {
7236 // this local variable exists so we're future-proof against
7237 // reentrant calls to flushPages.
7238 var pages = this._pageBuffer;
7239 this._pageBuffer = [];
7240 this._pageBufferStart += pages.length;
7241
7242 var _iterator = _createForOfIteratorHelper(pages),
7243 _step;
7244
7245 try {
7246 for (_iterator.s(); !(_step = _iterator.n()).done;) {
7247 var page = _step.value;
7248 this.endPageMarkings(page);
7249 page.end();
7250 }
7251 } catch (err) {
7252 _iterator.e(err);
7253 } finally {
7254 _iterator.f();
7255 }
7256 }
7257 }, {
7258 key: "addNamedDestination",
7259 value: function addNamedDestination(name) {
7260 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
7261 args[_key - 1] = arguments[_key];
7262 }
7263
7264 if (args.length === 0) {
7265 args = ['XYZ', null, null, null];
7266 }
7267
7268 if (args[0] === 'XYZ' && args[2] !== null) {
7269 args[2] = this.page.height - args[2];
7270 }
7271
7272 args.unshift(this.page.dictionary);
7273
7274 this._root.data.Names.data.Dests.add(name, args);
7275 }
7276 }, {
7277 key: "addNamedEmbeddedFile",
7278 value: function addNamedEmbeddedFile(name, ref) {
7279 if (!this._root.data.Names.data.EmbeddedFiles) {
7280 // disabling /Limits for this tree fixes attachments not showing in Adobe Reader
7281 this._root.data.Names.data.EmbeddedFiles = new PDFNameTree({
7282 limits: false
7283 });
7284 } // add filespec to EmbeddedFiles
7285
7286
7287 this._root.data.Names.data.EmbeddedFiles.add(name, ref);
7288 }
7289 }, {
7290 key: "addNamedJavaScript",
7291 value: function addNamedJavaScript(name, js) {
7292 if (!this._root.data.Names.data.JavaScript) {
7293 this._root.data.Names.data.JavaScript = new PDFNameTree();
7294 }
7295
7296 var data = {
7297 JS: new String(js),
7298 S: 'JavaScript'
7299 };
7300
7301 this._root.data.Names.data.JavaScript.add(name, data);
7302 }
7303 }, {
7304 key: "ref",
7305 value: function ref(data) {
7306 var ref = new PDFReference(this, this._offsets.length + 1, data);
7307
7308 this._offsets.push(null); // placeholder for this object's offset once it is finalized
7309
7310
7311 this._waiting++;
7312 return ref;
7313 }
7314 }, {
7315 key: "_read",
7316 value: function _read() {} // do nothing, but this method is required by node
7317
7318 }, {
7319 key: "_write",
7320 value: function _write(data) {
7321 if (!Buffer.isBuffer(data)) {
7322 data = Buffer.from(data + '\n', 'binary');
7323 }
7324
7325 this.push(data);
7326 return this._offset += data.length;
7327 }
7328 }, {
7329 key: "addContent",
7330 value: function addContent(data) {
7331 this.page.write(data);
7332 return this;
7333 }
7334 }, {
7335 key: "_refEnd",
7336 value: function _refEnd(ref) {
7337 this._offsets[ref.id - 1] = ref.offset;
7338
7339 if (--this._waiting === 0 && this._ended) {
7340 this._finalize();
7341
7342 return this._ended = false;
7343 }
7344 }
7345 }, {
7346 key: "write",
7347 value: function write(filename, fn) {
7348 // print a deprecation warning with a stacktrace
7349 var err = new Error("PDFDocument#write is deprecated, and will be removed in a future version of PDFKit. Please pipe the document into a Node stream.");
7350 console.warn(err.stack);
7351 this.pipe(fs.createWriteStream(filename));
7352 this.end();
7353 return this.once('end', fn);
7354 }
7355 }, {
7356 key: "end",
7357 value: function end() {
7358 this.flushPages();
7359 this._info = this.ref();
7360
7361 for (var key in this.info) {
7362 var val = this.info[key];
7363
7364 if (typeof val === 'string') {
7365 val = new String(val);
7366 }
7367
7368 var entry = this.ref(val);
7369 entry.end();
7370 this._info.data[key] = entry;
7371 }
7372
7373 this._info.end();
7374
7375 for (var name in this._fontFamilies) {
7376 var font = this._fontFamilies[name];
7377 font.finalize();
7378 }
7379
7380 this.endOutline();
7381 this.endMarkings();
7382
7383 if (this.subset) {
7384 this.endSubset();
7385 }
7386
7387 this.endMetadata();
7388
7389 this._root.end();
7390
7391 this._root.data.Pages.end();
7392
7393 this._root.data.Names.end();
7394
7395 this.endAcroForm();
7396
7397 if (this._root.data.ViewerPreferences) {
7398 this._root.data.ViewerPreferences.end();
7399 }
7400
7401 if (this._security) {
7402 this._security.end();
7403 }
7404
7405 if (this._waiting === 0) {
7406 return this._finalize();
7407 } else {
7408 return this._ended = true;
7409 }
7410 }
7411 }, {
7412 key: "_finalize",
7413 value: function _finalize() {
7414 // generate xref
7415 var xRefOffset = this._offset;
7416
7417 this._write('xref');
7418
7419 this._write("0 ".concat(this._offsets.length + 1));
7420
7421 this._write('0000000000 65535 f ');
7422
7423 var _iterator2 = _createForOfIteratorHelper(this._offsets),
7424 _step2;
7425
7426 try {
7427 for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
7428 var offset = _step2.value;
7429 offset = "0000000000".concat(offset).slice(-10);
7430
7431 this._write(offset + ' 00000 n ');
7432 } // trailer
7433
7434 } catch (err) {
7435 _iterator2.e(err);
7436 } finally {
7437 _iterator2.f();
7438 }
7439
7440 var trailer = {
7441 Size: this._offsets.length + 1,
7442 Root: this._root,
7443 Info: this._info,
7444 ID: [this._id, this._id]
7445 };
7446
7447 if (this._security) {
7448 trailer.Encrypt = this._security.dictionary;
7449 }
7450
7451 this._write('trailer');
7452
7453 this._write(PDFObject.convert(trailer));
7454
7455 this._write('startxref');
7456
7457 this._write("".concat(xRefOffset));
7458
7459 this._write('%%EOF'); // end the stream
7460
7461
7462 return this.push(null);
7463 }
7464 }, {
7465 key: "toString",
7466 value: function toString() {
7467 return '[object PDFDocument]';
7468 }
7469 }]);
7470
7471 return PDFDocument;
7472}(stream.Readable);
7473
7474var mixin = function mixin(methods) {
7475 Object.assign(PDFDocument.prototype, methods);
7476};
7477
7478mixin(MetadataMixin);
7479mixin(ColorMixin);
7480mixin(VectorMixin);
7481mixin(FontsMixin);
7482mixin(TextMixin);
7483mixin(ImagesMixin);
7484mixin(AnnotationsMixin);
7485mixin(OutlineMixin);
7486mixin(MarkingsMixin);
7487mixin(AcroFormMixin);
7488mixin(AttachmentsMixin);
7489mixin(SubsetMixin);
7490PDFDocument.LineWrapper = LineWrapper;
7491
7492export default PDFDocument;
7493//# sourceMappingURL=pdfkit.es5.js.map