UNPKG

990 kBJavaScriptView Raw
1/** @license
2 *
3 * jsPDF - PDF Document creation from JavaScript
4 * Version 2.3.0 Built on 2021-01-15T15:15:16.555Z
5 * CommitID 00000000
6 *
7 * Copyright (c) 2010-2020 James Hall <james@parall.ax>, https://github.com/MrRio/jsPDF
8 * 2015-2020 yWorks GmbH, http://www.yworks.com
9 * 2015-2020 Lukas Holländer <lukas.hollaender@yworks.com>, https://github.com/HackbrettXXX
10 * 2016-2018 Aras Abbasi <aras.abbasi@gmail.com>
11 * 2010 Aaron Spike, https://github.com/acspike
12 * 2012 Willow Systems Corporation, willow-systems.com
13 * 2012 Pablo Hess, https://github.com/pablohess
14 * 2012 Florian Jenett, https://github.com/fjenett
15 * 2013 Warren Weckesser, https://github.com/warrenweckesser
16 * 2013 Youssef Beddad, https://github.com/lifof
17 * 2013 Lee Driscoll, https://github.com/lsdriscoll
18 * 2013 Stefan Slonevskiy, https://github.com/stefslon
19 * 2013 Jeremy Morel, https://github.com/jmorel
20 * 2013 Christoph Hartmann, https://github.com/chris-rock
21 * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
22 * 2014 James Makes, https://github.com/dollaruw
23 * 2014 Diego Casorran, https://github.com/diegocr
24 * 2014 Steven Spungin, https://github.com/Flamenco
25 * 2014 Kenneth Glassey, https://github.com/Gavvers
26 *
27 * Permission is hereby granted, free of charge, to any person obtaining
28 * a copy of this software and associated documentation files (the
29 * "Software"), to deal in the Software without restriction, including
30 * without limitation the rights to use, copy, modify, merge, publish,
31 * distribute, sublicense, and/or sell copies of the Software, and to
32 * permit persons to whom the Software is furnished to do so, subject to
33 * the following conditions:
34 *
35 * The above copyright notice and this permission notice shall be
36 * included in all copies or substantial portions of the Software.
37 *
38 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
39 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
40 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
41 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
42 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
43 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
44 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
45 *
46 * Contributor(s):
47 * siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango,
48 * kim3er, mfo, alnorth, Flamenco
49 */
50
51(function (global, factory) {
52 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
53 typeof define === 'function' && define.amd ? define(['exports'], factory) :
54 (global = global || self, factory(global.jspdf = {}));
55}(this, (function (exports) { 'use strict';
56
57 var globalObject = (function() {
58 return "undefined" !== typeof window
59 ? window
60 : "undefined" !== typeof global
61 ? global
62 : "undefined" !== typeof self
63 ? self
64 : this;
65 })();
66
67 function consoleLog() {
68 if (globalObject.console && typeof globalObject.console.log === "function") {
69 globalObject.console.log.apply(globalObject.console, arguments);
70 }
71 }
72
73 function consoleWarn(str) {
74 if (globalObject.console) {
75 if (typeof globalObject.console.warn === "function") {
76 globalObject.console.warn.apply(globalObject.console, arguments);
77 } else {
78 consoleLog.call(null, arguments);
79 }
80 }
81 }
82
83 function consoleError(str) {
84 if (globalObject.console) {
85 if (typeof globalObject.console.error === "function") {
86 globalObject.console.error.apply(globalObject.console, arguments);
87 } else {
88 consoleLog(str);
89 }
90 }
91 }
92 var console = {
93 log: consoleLog,
94 warn: consoleWarn,
95 error: consoleError
96 };
97
98 /**
99 * @license
100 * FileSaver.js
101 * A saveAs() FileSaver implementation.
102 *
103 * By Eli Grey, http://eligrey.com
104 *
105 * License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT)
106 * source : http://purl.eligrey.com/github/FileSaver.js
107 */
108
109 function bom(blob, opts) {
110 if (typeof opts === "undefined") opts = { autoBom: false };
111 else if (typeof opts !== "object") {
112 console.warn("Deprecated: Expected third argument to be a object");
113 opts = { autoBom: !opts };
114 }
115
116 // prepend BOM for UTF-8 XML and text/* types (including HTML)
117 // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
118 if (
119 opts.autoBom &&
120 /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(
121 blob.type
122 )
123 ) {
124 return new Blob([String.fromCharCode(0xfeff), blob], { type: blob.type });
125 }
126 return blob;
127 }
128
129 function download(url, name, opts) {
130 var xhr = new XMLHttpRequest();
131 xhr.open("GET", url);
132 xhr.responseType = "blob";
133 xhr.onload = function() {
134 saveAs(xhr.response, name, opts);
135 };
136 xhr.onerror = function() {
137 console.error("could not download file");
138 };
139 xhr.send();
140 }
141
142 function corsEnabled(url) {
143 var xhr = new XMLHttpRequest();
144 // use sync to avoid popup blocker
145 xhr.open("HEAD", url, false);
146 try {
147 xhr.send();
148 } catch (e) {}
149 return xhr.status >= 200 && xhr.status <= 299;
150 }
151
152 // `a.click()` doesn't work for all browsers (#465)
153 function click(node) {
154 try {
155 node.dispatchEvent(new MouseEvent("click"));
156 } catch (e) {
157 var evt = document.createEvent("MouseEvents");
158 evt.initMouseEvent(
159 "click",
160 true,
161 true,
162 window,
163 0,
164 0,
165 0,
166 80,
167 20,
168 false,
169 false,
170 false,
171 false,
172 0,
173 null
174 );
175 node.dispatchEvent(evt);
176 }
177 }
178
179 var saveAs =
180 globalObject.saveAs ||
181 // probably in some web worker
182 (typeof window !== "object" || window !== globalObject
183 ? function saveAs() {
184 /* noop */
185 }
186 : // Use download attribute first if possible (#193 Lumia mobile)
187 "download" in HTMLAnchorElement.prototype
188 ? function saveAs(blob, name, opts) {
189 var URL = globalObject.URL || globalObject.webkitURL;
190 var a = document.createElement("a");
191 name = name || blob.name || "download";
192
193 a.download = name;
194 a.rel = "noopener"; // tabnabbing
195
196 // TODO: detect chrome extensions & packaged apps
197 // a.target = '_blank'
198
199 if (typeof blob === "string") {
200 // Support regular links
201 a.href = blob;
202 if (a.origin !== location.origin) {
203 corsEnabled(a.href)
204 ? download(blob, name, opts)
205 : click(a, (a.target = "_blank"));
206 } else {
207 click(a);
208 }
209 } else {
210 // Support blobs
211 a.href = URL.createObjectURL(blob);
212 setTimeout(function() {
213 URL.revokeObjectURL(a.href);
214 }, 4e4); // 40s
215 setTimeout(function() {
216 click(a);
217 }, 0);
218 }
219 }
220 : // Use msSaveOrOpenBlob as a second approach
221 "msSaveOrOpenBlob" in navigator
222 ? function saveAs(blob, name, opts) {
223 name = name || blob.name || "download";
224
225 if (typeof blob === "string") {
226 if (corsEnabled(blob)) {
227 download(blob, name, opts);
228 } else {
229 var a = document.createElement("a");
230 a.href = blob;
231 a.target = "_blank";
232 setTimeout(function() {
233 click(a);
234 });
235 }
236 } else {
237 navigator.msSaveOrOpenBlob(bom(blob, opts), name);
238 }
239 }
240 : // Fallback to using FileReader and a popup
241 function saveAs(blob, name, opts, popup) {
242 // Open a popup immediately do go around popup blocker
243 // Mostly only available on user interaction and the fileReader is async so...
244 popup = popup || open("", "_blank");
245 if (popup) {
246 popup.document.title = popup.document.body.innerText =
247 "downloading...";
248 }
249
250 if (typeof blob === "string") return download(blob, name, opts);
251
252 var force = blob.type === "application/octet-stream";
253 var isSafari =
254 /constructor/i.test(globalObject.HTMLElement) || globalObject.safari;
255 var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent);
256
257 if (
258 (isChromeIOS || (force && isSafari)) &&
259 typeof FileReader === "object"
260 ) {
261 // Safari doesn't allow downloading of blob URLs
262 var reader = new FileReader();
263 reader.onloadend = function() {
264 var url = reader.result;
265 url = isChromeIOS
266 ? url
267 : url.replace(/^data:[^;]*;/, "data:attachment/file;");
268 if (popup) popup.location.href = url;
269 else location = url;
270 popup = null; // reverse-tabnabbing #460
271 };
272 reader.readAsDataURL(blob);
273 } else {
274 var URL = globalObject.URL || globalObject.webkitURL;
275 var url = URL.createObjectURL(blob);
276 if (popup) popup.location = url;
277 else location.href = url;
278 popup = null; // reverse-tabnabbing #460
279 setTimeout(function() {
280 URL.revokeObjectURL(url);
281 }, 4e4); // 40s
282 }
283 });
284
285 /**
286 * A class to parse color values
287 * @author Stoyan Stefanov <sstoo@gmail.com>
288 * {@link http://www.phpied.com/rgb-color-parser-in-javascript/}
289 * @license Use it if you like it
290 */
291
292 function RGBColor(color_string) {
293 color_string = color_string || "";
294 this.ok = false;
295
296 // strip any leading #
297 if (color_string.charAt(0) == "#") {
298 // remove # if any
299 color_string = color_string.substr(1, 6);
300 }
301
302 color_string = color_string.replace(/ /g, "");
303 color_string = color_string.toLowerCase();
304
305 var channels;
306
307 // before getting into regexps, try simple matches
308 // and overwrite the input
309 var simple_colors = {
310 aliceblue: "f0f8ff",
311 antiquewhite: "faebd7",
312 aqua: "00ffff",
313 aquamarine: "7fffd4",
314 azure: "f0ffff",
315 beige: "f5f5dc",
316 bisque: "ffe4c4",
317 black: "000000",
318 blanchedalmond: "ffebcd",
319 blue: "0000ff",
320 blueviolet: "8a2be2",
321 brown: "a52a2a",
322 burlywood: "deb887",
323 cadetblue: "5f9ea0",
324 chartreuse: "7fff00",
325 chocolate: "d2691e",
326 coral: "ff7f50",
327 cornflowerblue: "6495ed",
328 cornsilk: "fff8dc",
329 crimson: "dc143c",
330 cyan: "00ffff",
331 darkblue: "00008b",
332 darkcyan: "008b8b",
333 darkgoldenrod: "b8860b",
334 darkgray: "a9a9a9",
335 darkgreen: "006400",
336 darkkhaki: "bdb76b",
337 darkmagenta: "8b008b",
338 darkolivegreen: "556b2f",
339 darkorange: "ff8c00",
340 darkorchid: "9932cc",
341 darkred: "8b0000",
342 darksalmon: "e9967a",
343 darkseagreen: "8fbc8f",
344 darkslateblue: "483d8b",
345 darkslategray: "2f4f4f",
346 darkturquoise: "00ced1",
347 darkviolet: "9400d3",
348 deeppink: "ff1493",
349 deepskyblue: "00bfff",
350 dimgray: "696969",
351 dodgerblue: "1e90ff",
352 feldspar: "d19275",
353 firebrick: "b22222",
354 floralwhite: "fffaf0",
355 forestgreen: "228b22",
356 fuchsia: "ff00ff",
357 gainsboro: "dcdcdc",
358 ghostwhite: "f8f8ff",
359 gold: "ffd700",
360 goldenrod: "daa520",
361 gray: "808080",
362 green: "008000",
363 greenyellow: "adff2f",
364 honeydew: "f0fff0",
365 hotpink: "ff69b4",
366 indianred: "cd5c5c",
367 indigo: "4b0082",
368 ivory: "fffff0",
369 khaki: "f0e68c",
370 lavender: "e6e6fa",
371 lavenderblush: "fff0f5",
372 lawngreen: "7cfc00",
373 lemonchiffon: "fffacd",
374 lightblue: "add8e6",
375 lightcoral: "f08080",
376 lightcyan: "e0ffff",
377 lightgoldenrodyellow: "fafad2",
378 lightgrey: "d3d3d3",
379 lightgreen: "90ee90",
380 lightpink: "ffb6c1",
381 lightsalmon: "ffa07a",
382 lightseagreen: "20b2aa",
383 lightskyblue: "87cefa",
384 lightslateblue: "8470ff",
385 lightslategray: "778899",
386 lightsteelblue: "b0c4de",
387 lightyellow: "ffffe0",
388 lime: "00ff00",
389 limegreen: "32cd32",
390 linen: "faf0e6",
391 magenta: "ff00ff",
392 maroon: "800000",
393 mediumaquamarine: "66cdaa",
394 mediumblue: "0000cd",
395 mediumorchid: "ba55d3",
396 mediumpurple: "9370d8",
397 mediumseagreen: "3cb371",
398 mediumslateblue: "7b68ee",
399 mediumspringgreen: "00fa9a",
400 mediumturquoise: "48d1cc",
401 mediumvioletred: "c71585",
402 midnightblue: "191970",
403 mintcream: "f5fffa",
404 mistyrose: "ffe4e1",
405 moccasin: "ffe4b5",
406 navajowhite: "ffdead",
407 navy: "000080",
408 oldlace: "fdf5e6",
409 olive: "808000",
410 olivedrab: "6b8e23",
411 orange: "ffa500",
412 orangered: "ff4500",
413 orchid: "da70d6",
414 palegoldenrod: "eee8aa",
415 palegreen: "98fb98",
416 paleturquoise: "afeeee",
417 palevioletred: "d87093",
418 papayawhip: "ffefd5",
419 peachpuff: "ffdab9",
420 peru: "cd853f",
421 pink: "ffc0cb",
422 plum: "dda0dd",
423 powderblue: "b0e0e6",
424 purple: "800080",
425 red: "ff0000",
426 rosybrown: "bc8f8f",
427 royalblue: "4169e1",
428 saddlebrown: "8b4513",
429 salmon: "fa8072",
430 sandybrown: "f4a460",
431 seagreen: "2e8b57",
432 seashell: "fff5ee",
433 sienna: "a0522d",
434 silver: "c0c0c0",
435 skyblue: "87ceeb",
436 slateblue: "6a5acd",
437 slategray: "708090",
438 snow: "fffafa",
439 springgreen: "00ff7f",
440 steelblue: "4682b4",
441 tan: "d2b48c",
442 teal: "008080",
443 thistle: "d8bfd8",
444 tomato: "ff6347",
445 turquoise: "40e0d0",
446 violet: "ee82ee",
447 violetred: "d02090",
448 wheat: "f5deb3",
449 white: "ffffff",
450 whitesmoke: "f5f5f5",
451 yellow: "ffff00",
452 yellowgreen: "9acd32"
453 };
454 color_string = simple_colors[color_string] || color_string;
455
456 // array of color definition objects
457 var color_defs = [
458 {
459 re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
460 example: ["rgb(123, 234, 45)", "rgb(255,234,245)"],
461 process: function(bits) {
462 return [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3])];
463 }
464 },
465 {
466 re: /^(\w{2})(\w{2})(\w{2})$/,
467 example: ["#00ff00", "336699"],
468 process: function(bits) {
469 return [
470 parseInt(bits[1], 16),
471 parseInt(bits[2], 16),
472 parseInt(bits[3], 16)
473 ];
474 }
475 },
476 {
477 re: /^(\w{1})(\w{1})(\w{1})$/,
478 example: ["#fb0", "f0f"],
479 process: function(bits) {
480 return [
481 parseInt(bits[1] + bits[1], 16),
482 parseInt(bits[2] + bits[2], 16),
483 parseInt(bits[3] + bits[3], 16)
484 ];
485 }
486 }
487 ];
488
489 // search through the definitions to find a match
490 for (var i = 0; i < color_defs.length; i++) {
491 var re = color_defs[i].re;
492 var processor = color_defs[i].process;
493 var bits = re.exec(color_string);
494 if (bits) {
495 channels = processor(bits);
496 this.r = channels[0];
497 this.g = channels[1];
498 this.b = channels[2];
499 this.ok = true;
500 }
501 }
502
503 // validate/cleanup values
504 this.r = this.r < 0 || isNaN(this.r) ? 0 : this.r > 255 ? 255 : this.r;
505 this.g = this.g < 0 || isNaN(this.g) ? 0 : this.g > 255 ? 255 : this.g;
506 this.b = this.b < 0 || isNaN(this.b) ? 0 : this.b > 255 ? 255 : this.b;
507
508 // some getters
509 this.toRGB = function() {
510 return "rgb(" + this.r + ", " + this.g + ", " + this.b + ")";
511 };
512 this.toHex = function() {
513 var r = this.r.toString(16);
514 var g = this.g.toString(16);
515 var b = this.b.toString(16);
516 if (r.length == 1) r = "0" + r;
517 if (g.length == 1) g = "0" + g;
518 if (b.length == 1) b = "0" + b;
519 return "#" + r + g + b;
520 };
521 }
522
523 var atob, btoa;
524
525 (function() {
526 atob = globalObject.atob.bind(globalObject);
527 btoa = globalObject.btoa.bind(globalObject);
528 return;
529
530 })();
531
532 /**
533 * @license
534 * Joseph Myers does not specify a particular license for his work.
535 *
536 * Author: Joseph Myers
537 * Accessed from: http://www.myersdaily.org/joseph/javascript/md5.js
538 *
539 * Modified by: Owen Leong
540 */
541
542 function md5cycle(x, k) {
543 var a = x[0],
544 b = x[1],
545 c = x[2],
546 d = x[3];
547
548 a = ff(a, b, c, d, k[0], 7, -680876936);
549 d = ff(d, a, b, c, k[1], 12, -389564586);
550 c = ff(c, d, a, b, k[2], 17, 606105819);
551 b = ff(b, c, d, a, k[3], 22, -1044525330);
552 a = ff(a, b, c, d, k[4], 7, -176418897);
553 d = ff(d, a, b, c, k[5], 12, 1200080426);
554 c = ff(c, d, a, b, k[6], 17, -1473231341);
555 b = ff(b, c, d, a, k[7], 22, -45705983);
556 a = ff(a, b, c, d, k[8], 7, 1770035416);
557 d = ff(d, a, b, c, k[9], 12, -1958414417);
558 c = ff(c, d, a, b, k[10], 17, -42063);
559 b = ff(b, c, d, a, k[11], 22, -1990404162);
560 a = ff(a, b, c, d, k[12], 7, 1804603682);
561 d = ff(d, a, b, c, k[13], 12, -40341101);
562 c = ff(c, d, a, b, k[14], 17, -1502002290);
563 b = ff(b, c, d, a, k[15], 22, 1236535329);
564
565 a = gg(a, b, c, d, k[1], 5, -165796510);
566 d = gg(d, a, b, c, k[6], 9, -1069501632);
567 c = gg(c, d, a, b, k[11], 14, 643717713);
568 b = gg(b, c, d, a, k[0], 20, -373897302);
569 a = gg(a, b, c, d, k[5], 5, -701558691);
570 d = gg(d, a, b, c, k[10], 9, 38016083);
571 c = gg(c, d, a, b, k[15], 14, -660478335);
572 b = gg(b, c, d, a, k[4], 20, -405537848);
573 a = gg(a, b, c, d, k[9], 5, 568446438);
574 d = gg(d, a, b, c, k[14], 9, -1019803690);
575 c = gg(c, d, a, b, k[3], 14, -187363961);
576 b = gg(b, c, d, a, k[8], 20, 1163531501);
577 a = gg(a, b, c, d, k[13], 5, -1444681467);
578 d = gg(d, a, b, c, k[2], 9, -51403784);
579 c = gg(c, d, a, b, k[7], 14, 1735328473);
580 b = gg(b, c, d, a, k[12], 20, -1926607734);
581
582 a = hh(a, b, c, d, k[5], 4, -378558);
583 d = hh(d, a, b, c, k[8], 11, -2022574463);
584 c = hh(c, d, a, b, k[11], 16, 1839030562);
585 b = hh(b, c, d, a, k[14], 23, -35309556);
586 a = hh(a, b, c, d, k[1], 4, -1530992060);
587 d = hh(d, a, b, c, k[4], 11, 1272893353);
588 c = hh(c, d, a, b, k[7], 16, -155497632);
589 b = hh(b, c, d, a, k[10], 23, -1094730640);
590 a = hh(a, b, c, d, k[13], 4, 681279174);
591 d = hh(d, a, b, c, k[0], 11, -358537222);
592 c = hh(c, d, a, b, k[3], 16, -722521979);
593 b = hh(b, c, d, a, k[6], 23, 76029189);
594 a = hh(a, b, c, d, k[9], 4, -640364487);
595 d = hh(d, a, b, c, k[12], 11, -421815835);
596 c = hh(c, d, a, b, k[15], 16, 530742520);
597 b = hh(b, c, d, a, k[2], 23, -995338651);
598
599 a = ii(a, b, c, d, k[0], 6, -198630844);
600 d = ii(d, a, b, c, k[7], 10, 1126891415);
601 c = ii(c, d, a, b, k[14], 15, -1416354905);
602 b = ii(b, c, d, a, k[5], 21, -57434055);
603 a = ii(a, b, c, d, k[12], 6, 1700485571);
604 d = ii(d, a, b, c, k[3], 10, -1894986606);
605 c = ii(c, d, a, b, k[10], 15, -1051523);
606 b = ii(b, c, d, a, k[1], 21, -2054922799);
607 a = ii(a, b, c, d, k[8], 6, 1873313359);
608 d = ii(d, a, b, c, k[15], 10, -30611744);
609 c = ii(c, d, a, b, k[6], 15, -1560198380);
610 b = ii(b, c, d, a, k[13], 21, 1309151649);
611 a = ii(a, b, c, d, k[4], 6, -145523070);
612 d = ii(d, a, b, c, k[11], 10, -1120210379);
613 c = ii(c, d, a, b, k[2], 15, 718787259);
614 b = ii(b, c, d, a, k[9], 21, -343485551);
615
616 x[0] = add32(a, x[0]);
617 x[1] = add32(b, x[1]);
618 x[2] = add32(c, x[2]);
619 x[3] = add32(d, x[3]);
620 }
621
622 function cmn(q, a, b, x, s, t) {
623 a = add32(add32(a, q), add32(x, t));
624 return add32((a << s) | (a >>> (32 - s)), b);
625 }
626
627 function ff(a, b, c, d, x, s, t) {
628 return cmn((b & c) | (~b & d), a, b, x, s, t);
629 }
630
631 function gg(a, b, c, d, x, s, t) {
632 return cmn((b & d) | (c & ~d), a, b, x, s, t);
633 }
634
635 function hh(a, b, c, d, x, s, t) {
636 return cmn(b ^ c ^ d, a, b, x, s, t);
637 }
638
639 function ii(a, b, c, d, x, s, t) {
640 return cmn(c ^ (b | ~d), a, b, x, s, t);
641 }
642
643 function md51(s) {
644 // txt = '';
645 var n = s.length,
646 state = [1732584193, -271733879, -1732584194, 271733878],
647 i;
648 for (i = 64; i <= s.length; i += 64) {
649 md5cycle(state, md5blk(s.substring(i - 64, i)));
650 }
651 s = s.substring(i - 64);
652 var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
653 for (i = 0; i < s.length; i++)
654 tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
655 tail[i >> 2] |= 0x80 << (i % 4 << 3);
656 if (i > 55) {
657 md5cycle(state, tail);
658 for (i = 0; i < 16; i++) tail[i] = 0;
659 }
660 tail[14] = n * 8;
661 md5cycle(state, tail);
662 return state;
663 }
664
665 /* there needs to be support for Unicode here,
666 * unless we pretend that we can redefine the MD-5
667 * algorithm for multi-byte characters (perhaps
668 * by adding every four 16-bit characters and
669 * shortening the sum to 32 bits). Otherwise
670 * I suggest performing MD-5 as if every character
671 * was two bytes--e.g., 0040 0025 = @%--but then
672 * how will an ordinary MD-5 sum be matched?
673 * There is no way to standardize text to something
674 * like UTF-8 before transformation; speed cost is
675 * utterly prohibitive. The JavaScript standard
676 * itself needs to look at this: it should start
677 * providing access to strings as preformed UTF-8
678 * 8-bit unsigned value arrays.
679 */
680 function md5blk(s) {
681 /* I figured global was faster. */
682 var md5blks = [],
683 i; /* Andy King said do it this way. */
684 for (i = 0; i < 64; i += 4) {
685 md5blks[i >> 2] =
686 s.charCodeAt(i) +
687 (s.charCodeAt(i + 1) << 8) +
688 (s.charCodeAt(i + 2) << 16) +
689 (s.charCodeAt(i + 3) << 24);
690 }
691 return md5blks;
692 }
693
694 var hex_chr = "0123456789abcdef".split("");
695
696 function rhex(n) {
697 var s = "",
698 j = 0;
699 for (; j < 4; j++)
700 s += hex_chr[(n >> (j * 8 + 4)) & 0x0f] + hex_chr[(n >> (j * 8)) & 0x0f];
701 return s;
702 }
703
704 function hex(x) {
705 for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]);
706 return x.join("");
707 }
708
709 // Converts a 4-byte number to byte string
710 function singleToByteString(n) {
711 return String.fromCharCode(
712 (n & 0xff) >> 0,
713 (n & 0xff00) >> 8,
714 (n & 0xff0000) >> 16,
715 (n & 0xff000000) >> 24
716 );
717 }
718
719 // Converts an array of numbers to a byte string
720 function toByteString(x) {
721 return x.map(singleToByteString).join("");
722 }
723
724 // Returns the MD5 hash as a byte string
725 function md5Bin(s) {
726 return toByteString(md51(s));
727 }
728
729 // Returns MD5 hash as a hex string
730 function md5(s) {
731 return hex(md51(s));
732 }
733
734 /* this function is much faster,
735 so if possible we use it. Some IEs
736 are the only ones I know of that
737 need the idiotic second function,
738 generated by an if clause. */
739
740 function add32(a, b) {
741 return (a + b) & 0xffffffff;
742 }
743
744 if (md5("hello") != "5d41402abc4b2a76b9719d911017c592") {
745 function add32(x, y) {
746 var lsw = (x & 0xffff) + (y & 0xffff),
747 msw = (x >> 16) + (y >> 16) + (lsw >> 16);
748 return (msw << 16) | (lsw & 0xffff);
749 }
750 }
751
752 /**
753 * @license
754 * FPDF is released under a permissive license: there is no usage restriction.
755 * You may embed it freely in your application (commercial or not), with or
756 * without modifications.
757 *
758 * Reference: http://www.fpdf.org/en/script/script37.php
759 */
760
761 function repeat(str, num) {
762 return new Array(num + 1).join(str);
763 }
764
765 /**
766 * Converts a byte string to a hex string
767 *
768 * @name rc4
769 * @function
770 * @param {string} key Byte string of encryption key
771 * @param {string} data Byte string of data to be encrypted
772 * @returns {string} Encrypted string
773 */
774 function rc4(key, data) {
775 var lastKey, lastState;
776 if (key !== lastKey) {
777 var k = repeat(key, ((256 / key.length) >> 0) + 1);
778 var state = [];
779 for (var i = 0; i < 256; i++) {
780 state[i] = i;
781 }
782 var j = 0;
783 for (var i = 0; i < 256; i++) {
784 var t = state[i];
785 j = (j + t + k.charCodeAt(i)) % 256;
786 state[i] = state[j];
787 state[j] = t;
788 }
789 lastKey = key;
790 lastState = state;
791 } else {
792 state = lastState;
793 }
794 var length = data.length;
795 var a = 0;
796 var b = 0;
797 var out = "";
798 for (var i = 0; i < length; i++) {
799 a = (a + 1) % 256;
800 t = state[a];
801 b = (b + t) % 256;
802 state[a] = state[b];
803 state[b] = t;
804 k = state[(state[a] + state[b]) % 256];
805 out += String.fromCharCode(data.charCodeAt(i) ^ k);
806 }
807 return out;
808 }
809
810 /**
811 * @license
812 * Licensed under the MIT License.
813 * http://opensource.org/licenses/mit-license
814 * Author: Owen Leong (@owenl131)
815 * Date: 15 Oct 2020
816 * References:
817 * https://www.cs.cmu.edu/~dst/Adobe/Gallery/anon21jul01-pdf-encryption.txt
818 * https://github.com/foliojs/pdfkit/blob/master/lib/security.js
819 * http://www.fpdf.org/en/script/script37.php
820 */
821
822 var permissionOptions = {
823 print: 4,
824 modify: 8,
825 copy: 16,
826 "annot-forms": 32
827 };
828
829 /**
830 * Initializes encryption settings
831 *
832 * @name constructor
833 * @function
834 * @param {Array} permissions Permissions allowed for user, "print", "modify", "copy" and "annot-forms".
835 * @param {String} userPassword Permissions apply to this user. Leaving this empty means the document
836 * is not password protected but viewer has the above permissions.
837 * @param {String} ownerPassword Owner has full functionalities to the file.
838 * @param {String} fileId As hex string, should be same as the file ID in the trailer.
839 * @example
840 * var security = new PDFSecurity(["print"])
841 */
842 function PDFSecurity(permissions, userPassword, ownerPassword, fileId) {
843 this.v = 1; // algorithm 1, future work can add in more recent encryption schemes
844 this.r = 2; // revision 2
845
846 // set flags for what functionalities the user can access
847 let protection = 192;
848 permissions.forEach(function(perm) {
849 if (typeof permissionOptions.perm !== "undefined") {
850 throw new Error("Invalid permission: " + perm);
851 }
852 protection += permissionOptions[perm];
853 });
854
855 // padding is used to pad the passwords to 32 bytes, also is hashed and stored in the final PDF
856 this.padding =
857 "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08" +
858 "\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
859 let paddedUserPassword = (userPassword + this.padding).substr(0, 32);
860 let paddedOwnerPassword = (ownerPassword + this.padding).substr(0, 32);
861
862 this.O = this.processOwnerPassword(paddedUserPassword, paddedOwnerPassword);
863 this.P = -((protection ^ 255) + 1);
864 this.encryptionKey = md5Bin(
865 paddedUserPassword +
866 this.O +
867 this.lsbFirstWord(this.P) +
868 this.hexToBytes(fileId)
869 ).substr(0, 5);
870 this.U = rc4(this.encryptionKey, this.padding);
871 }
872
873 /**
874 * Breaks down a 4-byte number into its individual bytes, with the least significant bit first
875 *
876 * @name lsbFirstWord
877 * @function
878 * @param {number} data 32-bit number
879 * @returns {Array}
880 */
881 PDFSecurity.prototype.lsbFirstWord = function(data) {
882 return String.fromCharCode(
883 (data >> 0) & 0xff,
884 (data >> 8) & 0xff,
885 (data >> 16) & 0xff,
886 (data >> 24) & 0xff
887 );
888 };
889
890 /**
891 * Converts a byte string to a hex string
892 *
893 * @name toHexString
894 * @function
895 * @param {String} byteString Byte string
896 * @returns {String}
897 */
898 PDFSecurity.prototype.toHexString = function(byteString) {
899 return byteString
900 .split("")
901 .map(function(byte) {
902 return ("0" + (byte.charCodeAt(0) & 0xff).toString(16)).slice(-2);
903 })
904 .join("");
905 };
906
907 /**
908 * Converts a hex string to a byte string
909 *
910 * @name hexToBytes
911 * @function
912 * @param {String} hex Hex string
913 * @returns {String}
914 */
915 PDFSecurity.prototype.hexToBytes = function(hex) {
916 for (var bytes = [], c = 0; c < hex.length; c += 2)
917 bytes.push(String.fromCharCode(parseInt(hex.substr(c, 2), 16)));
918 return bytes.join("");
919 };
920
921 /**
922 * Computes the 'O' field in the encryption dictionary
923 *
924 * @name processOwnerPassword
925 * @function
926 * @param {String} paddedUserPassword Byte string of padded user password
927 * @param {String} paddedOwnerPassword Byte string of padded owner password
928 * @returns {String}
929 */
930 PDFSecurity.prototype.processOwnerPassword = function(
931 paddedUserPassword,
932 paddedOwnerPassword
933 ) {
934 let key = md5Bin(paddedOwnerPassword).substr(0, 5);
935 return rc4(key, paddedUserPassword);
936 };
937
938 /**
939 * Returns an encryptor function which can take in a byte string and returns the encrypted version
940 *
941 * @name encryptor
942 * @function
943 * @param {number} objectId
944 * @param {number} generation Not sure what this is for, you can set it to 0
945 * @returns {Function}
946 * @example
947 * out("stream");
948 * encryptor = security.encryptor(object.id, 0);
949 * out(encryptor(data));
950 * out("endstream");
951 */
952 PDFSecurity.prototype.encryptor = function(objectId, generation) {
953 let key = md5Bin(
954 this.encryptionKey +
955 String.fromCharCode(
956 objectId & 0xff,
957 (objectId >> 8) & 0xff,
958 (objectId >> 16) & 0xff,
959 generation & 0xff,
960 (generation >> 8) & 0xff
961 )
962 ).substr(0, 10);
963 return function(data) {
964 return rc4(key, data);
965 };
966 };
967
968 /* eslint-disable no-console */
969
970 /**
971 * jsPDF's Internal PubSub Implementation.
972 * Backward compatible rewritten on 2014 by
973 * Diego Casorran, https://github.com/diegocr
974 *
975 * @class
976 * @name PubSub
977 * @ignore
978 */
979 function PubSub(context) {
980 if (typeof context !== "object") {
981 throw new Error(
982 "Invalid Context passed to initialize PubSub (jsPDF-module)"
983 );
984 }
985 var topics = {};
986
987 this.subscribe = function(topic, callback, once) {
988 once = once || false;
989 if (
990 typeof topic !== "string" ||
991 typeof callback !== "function" ||
992 typeof once !== "boolean"
993 ) {
994 throw new Error(
995 "Invalid arguments passed to PubSub.subscribe (jsPDF-module)"
996 );
997 }
998
999 if (!topics.hasOwnProperty(topic)) {
1000 topics[topic] = {};
1001 }
1002
1003 var token = Math.random().toString(35);
1004 topics[topic][token] = [callback, !!once];
1005
1006 return token;
1007 };
1008
1009 this.unsubscribe = function(token) {
1010 for (var topic in topics) {
1011 if (topics[topic][token]) {
1012 delete topics[topic][token];
1013 if (Object.keys(topics[topic]).length === 0) {
1014 delete topics[topic];
1015 }
1016 return true;
1017 }
1018 }
1019 return false;
1020 };
1021
1022 this.publish = function(topic) {
1023 if (topics.hasOwnProperty(topic)) {
1024 var args = Array.prototype.slice.call(arguments, 1),
1025 tokens = [];
1026
1027 for (var token in topics[topic]) {
1028 var sub = topics[topic][token];
1029 try {
1030 sub[0].apply(context, args);
1031 } catch (ex) {
1032 if (globalObject.console) {
1033 console.error("jsPDF PubSub Error", ex.message, ex);
1034 }
1035 }
1036 if (sub[1]) tokens.push(token);
1037 }
1038 if (tokens.length) tokens.forEach(this.unsubscribe);
1039 }
1040 };
1041
1042 this.getTopics = function() {
1043 return topics;
1044 };
1045 }
1046
1047 function GState(parameters) {
1048 if (!(this instanceof GState)) {
1049 return new GState(parameters);
1050 }
1051
1052 /**
1053 * @name GState#opacity
1054 * @type {any}
1055 */
1056 /**
1057 * @name GState#stroke-opacity
1058 * @type {any}
1059 */
1060 var supported = "opacity,stroke-opacity".split(",");
1061 for (var p in parameters) {
1062 if (parameters.hasOwnProperty(p) && supported.indexOf(p) >= 0) {
1063 this[p] = parameters[p];
1064 }
1065 }
1066 /**
1067 * @name GState#id
1068 * @type {string}
1069 */
1070 this.id = ""; // set by addGState()
1071 /**
1072 * @name GState#objectNumber
1073 * @type {number}
1074 */
1075 this.objectNumber = -1; // will be set by putGState()
1076 }
1077
1078 GState.prototype.equals = function equals(other) {
1079 var ignore = "id,objectNumber,equals";
1080 var p;
1081 if (!other || typeof other !== typeof this) return false;
1082 var count = 0;
1083 for (p in this) {
1084 if (ignore.indexOf(p) >= 0) continue;
1085 if (this.hasOwnProperty(p) && !other.hasOwnProperty(p)) return false;
1086 if (this[p] !== other[p]) return false;
1087 count++;
1088 }
1089 for (p in other) {
1090 if (other.hasOwnProperty(p) && ignore.indexOf(p) < 0) count--;
1091 }
1092 return count === 0;
1093 };
1094
1095 function Pattern(gState, matrix) {
1096 this.gState = gState;
1097 this.matrix = matrix;
1098
1099 this.id = ""; // set by addPattern()
1100 this.objectNumber = -1; // will be set by putPattern()
1101 }
1102
1103 function ShadingPattern(type, coords, colors, gState, matrix) {
1104 if (!(this instanceof ShadingPattern)) {
1105 return new ShadingPattern(type, coords, colors, gState, matrix);
1106 }
1107
1108 // see putPattern() for information how they are realized
1109 this.type = type === "axial" ? 2 : 3;
1110 this.coords = coords;
1111 this.colors = colors;
1112
1113 Pattern.call(this, gState, matrix);
1114 }
1115
1116 function TilingPattern(boundingBox, xStep, yStep, gState, matrix) {
1117 if (!(this instanceof TilingPattern)) {
1118 return new TilingPattern(boundingBox, xStep, yStep, gState, matrix);
1119 }
1120
1121 this.boundingBox = boundingBox;
1122 this.xStep = xStep;
1123 this.yStep = yStep;
1124
1125 this.stream = ""; // set by endTilingPattern();
1126
1127 this.cloneIndex = 0;
1128
1129 Pattern.call(this, gState, matrix);
1130 }
1131
1132 /**
1133 * Creates new jsPDF document object instance.
1134 * @name jsPDF
1135 * @class
1136 * @param {Object} [options] - Collection of settings initializing the jsPDF-instance
1137 * @param {string} [options.orientation=portrait] - Orientation of the first page. Possible values are "portrait" or "landscape" (or shortcuts "p" or "l").<br />
1138 * @param {string} [options.unit=mm] Measurement unit (base unit) to be used when coordinates are specified.<br />
1139 * Possible values are "pt" (points), "mm", "cm", "m", "in" or "px". Note that in order to get the correct scaling for "px"
1140 * units, you need to enable the hotfix "px_scaling" by setting options.hotfixes = ["px_scaling"].
1141 * @param {string/Array} [options.format=a4] The format of the first page. Can be:<ul><li>a0 - a10</li><li>b0 - b10</li><li>c0 - c10</li><li>dl</li><li>letter</li><li>government-letter</li><li>legal</li><li>junior-legal</li><li>ledger</li><li>tabloid</li><li>credit-card</li></ul><br />
1142 * Default is "a4". If you want to use your own format just pass instead of one of the above predefined formats the size as an number-array, e.g. [595.28, 841.89]
1143 * @param {boolean} [options.putOnlyUsedFonts=false] Only put fonts into the PDF, which were used.
1144 * @param {boolean} [options.compress=false] Compress the generated PDF.
1145 * @param {number} [options.precision=16] Precision of the element-positions.
1146 * @param {number} [options.userUnit=1.0] Not to be confused with the base unit. Please inform yourself before you use it.
1147 * @param {string[]} [options.hotfixes] An array of strings to enable hotfixes such as correct pixel scaling.
1148 * @param {Object} [options.encryption]
1149 * @param {string} [options.encryption.userPassword] Password for the user bound by the given permissions list.
1150 * @param {string} [options.encryption.ownerPassword] Both userPassword and ownerPassword should be set for proper authentication.
1151 * @param {string[]} [options.encryption.userPermissions] Array of permissions "print", "modify", "copy", "annot-forms", accessible by the user.
1152 * @param {number|"smart"} [options.floatPrecision=16]
1153 * @returns {jsPDF} jsPDF-instance
1154 * @description
1155 * ```
1156 * {
1157 * orientation: 'p',
1158 * unit: 'mm',
1159 * format: 'a4',
1160 * putOnlyUsedFonts:true,
1161 * floatPrecision: 16 // or "smart", default is 16
1162 * }
1163 * ```
1164 *
1165 * @constructor
1166 */
1167 function jsPDF(options) {
1168 var orientation = typeof arguments[0] === "string" ? arguments[0] : "p";
1169 var unit = arguments[1];
1170 var format = arguments[2];
1171 var compressPdf = arguments[3];
1172 var filters = [];
1173 var userUnit = 1.0;
1174 var precision;
1175 var floatPrecision = 16;
1176 var defaultPathOperation = "S";
1177 var encryptionOptions = null;
1178
1179 options = options || {};
1180
1181 if (typeof options === "object") {
1182 orientation = options.orientation;
1183 unit = options.unit || unit;
1184 format = options.format || format;
1185 compressPdf = options.compress || options.compressPdf || compressPdf;
1186 encryptionOptions = options.encryption || null;
1187 if (encryptionOptions !== null) {
1188 encryptionOptions.userPassword = encryptionOptions.userPassword || "";
1189 encryptionOptions.ownerPassword = encryptionOptions.ownerPassword || "";
1190 encryptionOptions.userPermissions =
1191 encryptionOptions.userPermissions || [];
1192 }
1193 userUnit =
1194 typeof options.userUnit === "number" ? Math.abs(options.userUnit) : 1.0;
1195 if (typeof options.precision !== "undefined") {
1196 precision = options.precision;
1197 }
1198 if (typeof options.floatPrecision !== "undefined") {
1199 floatPrecision = options.floatPrecision;
1200 }
1201 defaultPathOperation = options.defaultPathOperation || "S";
1202 }
1203
1204 filters =
1205 options.filters || (compressPdf === true ? ["FlateEncode"] : filters);
1206
1207 unit = unit || "mm";
1208 orientation = ("" + (orientation || "P")).toLowerCase();
1209 var putOnlyUsedFonts = options.putOnlyUsedFonts || false;
1210 var usedFonts = {};
1211
1212 var API = {
1213 internal: {},
1214 __private__: {}
1215 };
1216
1217 API.__private__.PubSub = PubSub;
1218
1219 var pdfVersion = "1.3";
1220 var getPdfVersion = (API.__private__.getPdfVersion = function() {
1221 return pdfVersion;
1222 });
1223
1224 API.__private__.setPdfVersion = function(value) {
1225 pdfVersion = value;
1226 };
1227
1228 // Size in pt of various paper formats
1229 var pageFormats = {
1230 a0: [2383.94, 3370.39],
1231 a1: [1683.78, 2383.94],
1232 a2: [1190.55, 1683.78],
1233 a3: [841.89, 1190.55],
1234 a4: [595.28, 841.89],
1235 a5: [419.53, 595.28],
1236 a6: [297.64, 419.53],
1237 a7: [209.76, 297.64],
1238 a8: [147.4, 209.76],
1239 a9: [104.88, 147.4],
1240 a10: [73.7, 104.88],
1241 b0: [2834.65, 4008.19],
1242 b1: [2004.09, 2834.65],
1243 b2: [1417.32, 2004.09],
1244 b3: [1000.63, 1417.32],
1245 b4: [708.66, 1000.63],
1246 b5: [498.9, 708.66],
1247 b6: [354.33, 498.9],
1248 b7: [249.45, 354.33],
1249 b8: [175.75, 249.45],
1250 b9: [124.72, 175.75],
1251 b10: [87.87, 124.72],
1252 c0: [2599.37, 3676.54],
1253 c1: [1836.85, 2599.37],
1254 c2: [1298.27, 1836.85],
1255 c3: [918.43, 1298.27],
1256 c4: [649.13, 918.43],
1257 c5: [459.21, 649.13],
1258 c6: [323.15, 459.21],
1259 c7: [229.61, 323.15],
1260 c8: [161.57, 229.61],
1261 c9: [113.39, 161.57],
1262 c10: [79.37, 113.39],
1263 dl: [311.81, 623.62],
1264 letter: [612, 792],
1265 "government-letter": [576, 756],
1266 legal: [612, 1008],
1267 "junior-legal": [576, 360],
1268 ledger: [1224, 792],
1269 tabloid: [792, 1224],
1270 "credit-card": [153, 243]
1271 };
1272
1273 API.__private__.getPageFormats = function() {
1274 return pageFormats;
1275 };
1276
1277 var getPageFormat = (API.__private__.getPageFormat = function(value) {
1278 return pageFormats[value];
1279 });
1280
1281 format = format || "a4";
1282
1283 var ApiMode = {
1284 COMPAT: "compat",
1285 ADVANCED: "advanced"
1286 };
1287 var apiMode = ApiMode.COMPAT;
1288
1289 function advancedAPI() {
1290 // prepend global change of basis matrix
1291 // (Now, instead of converting every coordinate to the pdf coordinate system, we apply a matrix
1292 // that does this job for us (however, texts, images and similar objects must be drawn bottom up))
1293 this.saveGraphicsState();
1294 out(
1295 new Matrix(
1296 scaleFactor,
1297 0,
1298 0,
1299 -scaleFactor,
1300 0,
1301 getPageHeight() * scaleFactor
1302 ).toString() + " cm"
1303 );
1304 this.setFontSize(this.getFontSize() / scaleFactor);
1305
1306 // The default in MrRio's implementation is "S" (stroke), whereas the default in the yWorks implementation
1307 // was "n" (none). Although this has nothing to do with transforms, we should use the API switch here.
1308 defaultPathOperation = "n";
1309
1310 apiMode = ApiMode.ADVANCED;
1311 }
1312
1313 function compatAPI() {
1314 this.restoreGraphicsState();
1315 defaultPathOperation = "S";
1316 apiMode = ApiMode.COMPAT;
1317 }
1318
1319 /**
1320 * @function combineFontStyleAndFontWeight
1321 * @param {string} fontStyle Fontstyle or variant. Example: "italic".
1322 * @param {number | string} fontWeight Weight of the Font. Example: "normal" | 400
1323 * @returns {string}
1324 * @private
1325 */
1326 var combineFontStyleAndFontWeight = function(fontStyle, fontWeight) {
1327 if (
1328 (fontStyle == "bold" && fontWeight == "normal") ||
1329 (fontStyle == "bold" && fontWeight == 400) ||
1330 (fontStyle == "normal" && fontWeight == "italic") ||
1331 (fontStyle == "bold" && fontWeight == "italic")
1332 ) {
1333 throw new Error("Invalid Combination of fontweight and fontstyle");
1334 }
1335 if (fontWeight && fontStyle !== fontWeight) {
1336 //if fontstyle is normal and fontweight is normal too no need to append the font-weight
1337 fontStyle =
1338 fontWeight == 400
1339 ? fontStyle == "italic"
1340 ? "italic"
1341 : "normal"
1342 : fontWeight == 700 && fontStyle !== "italic"
1343 ? "bold"
1344 : fontStyle + "" + fontWeight;
1345 }
1346 return fontStyle;
1347 };
1348
1349 /**
1350 * @callback ApiSwitchBody
1351 * @param {jsPDF} pdf
1352 */
1353
1354 /**
1355 * For compatibility reasons jsPDF offers two API modes which differ in the way they convert between the the usual
1356 * screen coordinates and the PDF coordinate system.
1357 * - "compat": Offers full compatibility across all plugins but does not allow arbitrary transforms
1358 * - "advanced": Allows arbitrary transforms and more advanced features like pattern fills. Some plugins might
1359 * not support this mode, though.
1360 * Initial mode is "compat".
1361 *
1362 * You can either provide a callback to the body argument, which means that jsPDF will automatically switch back to
1363 * the original API mode afterwards; or you can omit the callback and switch back manually using {@link compatAPI}.
1364 *
1365 * Note, that the calls to {@link saveGraphicsState} and {@link restoreGraphicsState} need to be balanced within the
1366 * callback or between calls of this method and its counterpart {@link compatAPI}. Calls to {@link beginFormObject}
1367 * or {@link beginTilingPattern} need to be closed by their counterparts before switching back to "compat" API mode.
1368 *
1369 * @param {ApiSwitchBody=} body When provided, this callback will be called after the API mode has been switched.
1370 * The API mode will be switched back automatically afterwards.
1371 * @returns {jsPDF}
1372 * @memberof jsPDF#
1373 * @name advancedAPI
1374 */
1375 API.advancedAPI = function(body) {
1376 var doSwitch = apiMode === ApiMode.COMPAT;
1377
1378 if (doSwitch) {
1379 advancedAPI.call(this);
1380 }
1381
1382 if (typeof body !== "function") {
1383 return this;
1384 }
1385
1386 body(this);
1387
1388 if (doSwitch) {
1389 compatAPI.call(this);
1390 }
1391
1392 return this;
1393 };
1394
1395 /**
1396 * Switches to "compat" API mode. See {@link advancedAPI} for more details.
1397 *
1398 * @param {ApiSwitchBody=} body When provided, this callback will be called after the API mode has been switched.
1399 * The API mode will be switched back automatically afterwards.
1400 * @return {jsPDF}
1401 * @memberof jsPDF#
1402 * @name compatApi
1403 */
1404 API.compatAPI = function(body) {
1405 var doSwitch = apiMode === ApiMode.ADVANCED;
1406
1407 if (doSwitch) {
1408 compatAPI.call(this);
1409 }
1410
1411 if (typeof body !== "function") {
1412 return this;
1413 }
1414
1415 body(this);
1416
1417 if (doSwitch) {
1418 advancedAPI.call(this);
1419 }
1420
1421 return this;
1422 };
1423
1424 /**
1425 * @return {boolean} True iff the current API mode is "advanced". See {@link advancedAPI}.
1426 * @memberof jsPDF#
1427 * @name isAdvancedAPI
1428 */
1429 API.isAdvancedAPI = function() {
1430 return apiMode === ApiMode.ADVANCED;
1431 };
1432
1433 var advancedApiModeTrap = function(methodName) {
1434 if (apiMode !== ApiMode.ADVANCED) {
1435 throw new Error(
1436 methodName +
1437 " is only available in 'advanced' API mode. " +
1438 "You need to call advancedAPI() first."
1439 );
1440 }
1441 };
1442
1443 var roundToPrecision = (API.roundToPrecision = API.__private__.roundToPrecision = function(
1444 number,
1445 parmPrecision
1446 ) {
1447 var tmpPrecision = precision || parmPrecision;
1448 if (isNaN(number) || isNaN(tmpPrecision)) {
1449 throw new Error("Invalid argument passed to jsPDF.roundToPrecision");
1450 }
1451 return number.toFixed(tmpPrecision).replace(/0+$/, "");
1452 });
1453
1454 // high precision float
1455 var hpf;
1456 if (typeof floatPrecision === "number") {
1457 hpf = API.hpf = API.__private__.hpf = function(number) {
1458 if (isNaN(number)) {
1459 throw new Error("Invalid argument passed to jsPDF.hpf");
1460 }
1461 return roundToPrecision(number, floatPrecision);
1462 };
1463 } else if (floatPrecision === "smart") {
1464 hpf = API.hpf = API.__private__.hpf = function(number) {
1465 if (isNaN(number)) {
1466 throw new Error("Invalid argument passed to jsPDF.hpf");
1467 }
1468 if (number > -1 && number < 1) {
1469 return roundToPrecision(number, 16);
1470 } else {
1471 return roundToPrecision(number, 5);
1472 }
1473 };
1474 } else {
1475 hpf = API.hpf = API.__private__.hpf = function(number) {
1476 if (isNaN(number)) {
1477 throw new Error("Invalid argument passed to jsPDF.hpf");
1478 }
1479 return roundToPrecision(number, 16);
1480 };
1481 }
1482 var f2 = (API.f2 = API.__private__.f2 = function(number) {
1483 if (isNaN(number)) {
1484 throw new Error("Invalid argument passed to jsPDF.f2");
1485 }
1486 return roundToPrecision(number, 2);
1487 });
1488
1489 var f3 = (API.__private__.f3 = function(number) {
1490 if (isNaN(number)) {
1491 throw new Error("Invalid argument passed to jsPDF.f3");
1492 }
1493 return roundToPrecision(number, 3);
1494 });
1495
1496 var scale = (API.scale = API.__private__.scale = function(number) {
1497 if (isNaN(number)) {
1498 throw new Error("Invalid argument passed to jsPDF.scale");
1499 }
1500 if (apiMode === ApiMode.COMPAT) {
1501 return number * scaleFactor;
1502 } else if (apiMode === ApiMode.ADVANCED) {
1503 return number;
1504 }
1505 });
1506
1507 var transformY = function(y) {
1508 if (apiMode === ApiMode.COMPAT) {
1509 return getPageHeight() - y;
1510 } else if (apiMode === ApiMode.ADVANCED) {
1511 return y;
1512 }
1513 };
1514
1515 var transformScaleY = function(y) {
1516 return scale(transformY(y));
1517 };
1518
1519 /**
1520 * @name setPrecision
1521 * @memberof jsPDF#
1522 * @function
1523 * @instance
1524 * @param {string} precision
1525 * @returns {jsPDF}
1526 */
1527 API.__private__.setPrecision = API.setPrecision = function(value) {
1528 if (typeof parseInt(value, 10) === "number") {
1529 precision = parseInt(value, 10);
1530 }
1531 };
1532
1533 var fileId = "00000000000000000000000000000000";
1534
1535 var getFileId = (API.__private__.getFileId = function() {
1536 return fileId;
1537 });
1538
1539 var setFileId = (API.__private__.setFileId = function(value) {
1540 if (typeof value !== "undefined" && /^[a-fA-F0-9]{32}$/.test(value)) {
1541 fileId = value.toUpperCase();
1542 } else {
1543 fileId = fileId
1544 .split("")
1545 .map(function() {
1546 return "ABCDEF0123456789".charAt(Math.floor(Math.random() * 16));
1547 })
1548 .join("");
1549 }
1550
1551 if (encryptionOptions !== null) {
1552 encryption = new PDFSecurity(
1553 encryptionOptions.userPermissions,
1554 encryptionOptions.userPassword,
1555 encryptionOptions.ownerPassword,
1556 fileId
1557 );
1558 }
1559 return fileId;
1560 });
1561
1562 /**
1563 * @name setFileId
1564 * @memberof jsPDF#
1565 * @function
1566 * @instance
1567 * @param {string} value GUID.
1568 * @returns {jsPDF}
1569 */
1570 API.setFileId = function(value) {
1571 setFileId(value);
1572 return this;
1573 };
1574
1575 /**
1576 * @name getFileId
1577 * @memberof jsPDF#
1578 * @function
1579 * @instance
1580 *
1581 * @returns {string} GUID.
1582 */
1583 API.getFileId = function() {
1584 return getFileId();
1585 };
1586
1587 var creationDate;
1588
1589 var convertDateToPDFDate = (API.__private__.convertDateToPDFDate = function(
1590 parmDate
1591 ) {
1592 var result = "";
1593 var tzoffset = parmDate.getTimezoneOffset(),
1594 tzsign = tzoffset < 0 ? "+" : "-",
1595 tzhour = Math.floor(Math.abs(tzoffset / 60)),
1596 tzmin = Math.abs(tzoffset % 60),
1597 timeZoneString = [tzsign, padd2(tzhour), "'", padd2(tzmin), "'"].join("");
1598
1599 result = [
1600 "D:",
1601 parmDate.getFullYear(),
1602 padd2(parmDate.getMonth() + 1),
1603 padd2(parmDate.getDate()),
1604 padd2(parmDate.getHours()),
1605 padd2(parmDate.getMinutes()),
1606 padd2(parmDate.getSeconds()),
1607 timeZoneString
1608 ].join("");
1609 return result;
1610 });
1611
1612 var convertPDFDateToDate = (API.__private__.convertPDFDateToDate = function(
1613 parmPDFDate
1614 ) {
1615 var year = parseInt(parmPDFDate.substr(2, 4), 10);
1616 var month = parseInt(parmPDFDate.substr(6, 2), 10) - 1;
1617 var date = parseInt(parmPDFDate.substr(8, 2), 10);
1618 var hour = parseInt(parmPDFDate.substr(10, 2), 10);
1619 var minutes = parseInt(parmPDFDate.substr(12, 2), 10);
1620 var seconds = parseInt(parmPDFDate.substr(14, 2), 10);
1621 // var timeZoneHour = parseInt(parmPDFDate.substr(16, 2), 10);
1622 // var timeZoneMinutes = parseInt(parmPDFDate.substr(20, 2), 10);
1623
1624 var resultingDate = new Date(year, month, date, hour, minutes, seconds, 0);
1625 return resultingDate;
1626 });
1627
1628 var setCreationDate = (API.__private__.setCreationDate = function(date) {
1629 var tmpCreationDateString;
1630 var regexPDFCreationDate = /^D:(20[0-2][0-9]|203[0-7]|19[7-9][0-9])(0[0-9]|1[0-2])([0-2][0-9]|3[0-1])(0[0-9]|1[0-9]|2[0-3])(0[0-9]|[1-5][0-9])(0[0-9]|[1-5][0-9])(\+0[0-9]|\+1[0-4]|-0[0-9]|-1[0-1])'(0[0-9]|[1-5][0-9])'?$/;
1631 if (typeof date === "undefined") {
1632 date = new Date();
1633 }
1634
1635 if (date instanceof Date) {
1636 tmpCreationDateString = convertDateToPDFDate(date);
1637 } else if (regexPDFCreationDate.test(date)) {
1638 tmpCreationDateString = date;
1639 } else {
1640 throw new Error("Invalid argument passed to jsPDF.setCreationDate");
1641 }
1642 creationDate = tmpCreationDateString;
1643 return creationDate;
1644 });
1645
1646 var getCreationDate = (API.__private__.getCreationDate = function(type) {
1647 var result = creationDate;
1648 if (type === "jsDate") {
1649 result = convertPDFDateToDate(creationDate);
1650 }
1651 return result;
1652 });
1653
1654 /**
1655 * @name setCreationDate
1656 * @memberof jsPDF#
1657 * @function
1658 * @instance
1659 * @param {Object} date
1660 * @returns {jsPDF}
1661 */
1662 API.setCreationDate = function(date) {
1663 setCreationDate(date);
1664 return this;
1665 };
1666
1667 /**
1668 * @name getCreationDate
1669 * @memberof jsPDF#
1670 * @function
1671 * @instance
1672 * @param {Object} type
1673 * @returns {Object}
1674 */
1675 API.getCreationDate = function(type) {
1676 return getCreationDate(type);
1677 };
1678
1679 var padd2 = (API.__private__.padd2 = function(number) {
1680 return ("0" + parseInt(number)).slice(-2);
1681 });
1682
1683 var padd2Hex = (API.__private__.padd2Hex = function(hexString) {
1684 hexString = hexString.toString();
1685 return ("00" + hexString).substr(hexString.length);
1686 });
1687
1688 var objectNumber = 0; // 'n' Current object number
1689 var offsets = []; // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes.
1690 var content = [];
1691 var contentLength = 0;
1692 var additionalObjects = [];
1693
1694 var pages = [];
1695 var currentPage;
1696 var hasCustomDestination = false;
1697 var outputDestination = content;
1698
1699 var resetDocument = function() {
1700 //reset fields relevant for objectNumber generation and xref.
1701 objectNumber = 0;
1702 contentLength = 0;
1703 content = [];
1704 offsets = [];
1705 additionalObjects = [];
1706
1707 rootDictionaryObjId = newObjectDeferred();
1708 resourceDictionaryObjId = newObjectDeferred();
1709 };
1710
1711 API.__private__.setCustomOutputDestination = function(destination) {
1712 hasCustomDestination = true;
1713 outputDestination = destination;
1714 };
1715 var setOutputDestination = function(destination) {
1716 if (!hasCustomDestination) {
1717 outputDestination = destination;
1718 }
1719 };
1720
1721 API.__private__.resetCustomOutputDestination = function() {
1722 hasCustomDestination = false;
1723 outputDestination = content;
1724 };
1725
1726 var out = (API.__private__.out = function(string) {
1727 string = string.toString();
1728 contentLength += string.length + 1;
1729 outputDestination.push(string);
1730
1731 return outputDestination;
1732 });
1733
1734 var write = (API.__private__.write = function(value) {
1735 return out(
1736 arguments.length === 1
1737 ? value.toString()
1738 : Array.prototype.join.call(arguments, " ")
1739 );
1740 });
1741
1742 var getArrayBuffer = (API.__private__.getArrayBuffer = function(data) {
1743 var len = data.length,
1744 ab = new ArrayBuffer(len),
1745 u8 = new Uint8Array(ab);
1746
1747 while (len--) u8[len] = data.charCodeAt(len);
1748 return ab;
1749 });
1750
1751 var standardFonts = [
1752 ["Helvetica", "helvetica", "normal", "WinAnsiEncoding"],
1753 ["Helvetica-Bold", "helvetica", "bold", "WinAnsiEncoding"],
1754 ["Helvetica-Oblique", "helvetica", "italic", "WinAnsiEncoding"],
1755 ["Helvetica-BoldOblique", "helvetica", "bolditalic", "WinAnsiEncoding"],
1756 ["Courier", "courier", "normal", "WinAnsiEncoding"],
1757 ["Courier-Bold", "courier", "bold", "WinAnsiEncoding"],
1758 ["Courier-Oblique", "courier", "italic", "WinAnsiEncoding"],
1759 ["Courier-BoldOblique", "courier", "bolditalic", "WinAnsiEncoding"],
1760 ["Times-Roman", "times", "normal", "WinAnsiEncoding"],
1761 ["Times-Bold", "times", "bold", "WinAnsiEncoding"],
1762 ["Times-Italic", "times", "italic", "WinAnsiEncoding"],
1763 ["Times-BoldItalic", "times", "bolditalic", "WinAnsiEncoding"],
1764 ["ZapfDingbats", "zapfdingbats", "normal", null],
1765 ["Symbol", "symbol", "normal", null]
1766 ];
1767
1768 API.__private__.getStandardFonts = function() {
1769 return standardFonts;
1770 };
1771
1772 var activeFontSize = options.fontSize || 16;
1773
1774 /**
1775 * Sets font size for upcoming text elements.
1776 *
1777 * @param {number} size Font size in points.
1778 * @function
1779 * @instance
1780 * @returns {jsPDF}
1781 * @memberof jsPDF#
1782 * @name setFontSize
1783 */
1784 API.__private__.setFontSize = API.setFontSize = function(size) {
1785 if (apiMode === ApiMode.ADVANCED) {
1786 activeFontSize = size / scaleFactor;
1787 } else {
1788 activeFontSize = size;
1789 }
1790 return this;
1791 };
1792
1793 /**
1794 * Gets the fontsize for upcoming text elements.
1795 *
1796 * @function
1797 * @instance
1798 * @returns {number}
1799 * @memberof jsPDF#
1800 * @name getFontSize
1801 */
1802 var getFontSize = (API.__private__.getFontSize = API.getFontSize = function() {
1803 if (apiMode === ApiMode.COMPAT) {
1804 return activeFontSize;
1805 } else {
1806 return activeFontSize * scaleFactor;
1807 }
1808 });
1809
1810 var R2L = options.R2L || false;
1811
1812 /**
1813 * Set value of R2L functionality.
1814 *
1815 * @param {boolean} value
1816 * @function
1817 * @instance
1818 * @returns {jsPDF} jsPDF-instance
1819 * @memberof jsPDF#
1820 * @name setR2L
1821 */
1822 API.__private__.setR2L = API.setR2L = function(value) {
1823 R2L = value;
1824 return this;
1825 };
1826
1827 /**
1828 * Get value of R2L functionality.
1829 *
1830 * @function
1831 * @instance
1832 * @returns {boolean} jsPDF-instance
1833 * @memberof jsPDF#
1834 * @name getR2L
1835 */
1836 API.__private__.getR2L = API.getR2L = function() {
1837 return R2L;
1838 };
1839
1840 var zoomMode; // default: 1;
1841
1842 var setZoomMode = (API.__private__.setZoomMode = function(zoom) {
1843 var validZoomModes = [
1844 undefined,
1845 null,
1846 "fullwidth",
1847 "fullheight",
1848 "fullpage",
1849 "original"
1850 ];
1851
1852 if (/^\d*\.?\d*%$/.test(zoom)) {
1853 zoomMode = zoom;
1854 } else if (!isNaN(zoom)) {
1855 zoomMode = parseInt(zoom, 10);
1856 } else if (validZoomModes.indexOf(zoom) !== -1) {
1857 zoomMode = zoom;
1858 } else {
1859 throw new Error(
1860 'zoom must be Integer (e.g. 2), a percentage Value (e.g. 300%) or fullwidth, fullheight, fullpage, original. "' +
1861 zoom +
1862 '" is not recognized.'
1863 );
1864 }
1865 });
1866
1867 API.__private__.getZoomMode = function() {
1868 return zoomMode;
1869 };
1870
1871 var pageMode; // default: 'UseOutlines';
1872 var setPageMode = (API.__private__.setPageMode = function(pmode) {
1873 var validPageModes = [
1874 undefined,
1875 null,
1876 "UseNone",
1877 "UseOutlines",
1878 "UseThumbs",
1879 "FullScreen"
1880 ];
1881
1882 if (validPageModes.indexOf(pmode) == -1) {
1883 throw new Error(
1884 'Page mode must be one of UseNone, UseOutlines, UseThumbs, or FullScreen. "' +
1885 pmode +
1886 '" is not recognized.'
1887 );
1888 }
1889 pageMode = pmode;
1890 });
1891
1892 API.__private__.getPageMode = function() {
1893 return pageMode;
1894 };
1895
1896 var layoutMode; // default: 'continuous';
1897 var setLayoutMode = (API.__private__.setLayoutMode = function(layout) {
1898 var validLayoutModes = [
1899 undefined,
1900 null,
1901 "continuous",
1902 "single",
1903 "twoleft",
1904 "tworight",
1905 "two"
1906 ];
1907
1908 if (validLayoutModes.indexOf(layout) == -1) {
1909 throw new Error(
1910 'Layout mode must be one of continuous, single, twoleft, tworight. "' +
1911 layout +
1912 '" is not recognized.'
1913 );
1914 }
1915 layoutMode = layout;
1916 });
1917
1918 API.__private__.getLayoutMode = function() {
1919 return layoutMode;
1920 };
1921
1922 /**
1923 * Set the display mode options of the page like zoom and layout.
1924 *
1925 * @name setDisplayMode
1926 * @memberof jsPDF#
1927 * @function
1928 * @instance
1929 * @param {integer|String} zoom You can pass an integer or percentage as
1930 * a string. 2 will scale the document up 2x, '200%' will scale up by the
1931 * same amount. You can also set it to 'fullwidth', 'fullheight',
1932 * 'fullpage', or 'original'.
1933 *
1934 * Only certain PDF readers support this, such as Adobe Acrobat.
1935 *
1936 * @param {string} layout Layout mode can be: 'continuous' - this is the
1937 * default continuous scroll. 'single' - the single page mode only shows one
1938 * page at a time. 'twoleft' - two column left mode, first page starts on
1939 * the left, and 'tworight' - pages are laid out in two columns, with the
1940 * first page on the right. This would be used for books.
1941 * @param {string} pmode 'UseOutlines' - it shows the
1942 * outline of the document on the left. 'UseThumbs' - shows thumbnails along
1943 * the left. 'FullScreen' - prompts the user to enter fullscreen mode.
1944 *
1945 * @returns {jsPDF}
1946 */
1947 API.__private__.setDisplayMode = API.setDisplayMode = function(
1948 zoom,
1949 layout,
1950 pmode
1951 ) {
1952 setZoomMode(zoom);
1953 setLayoutMode(layout);
1954 setPageMode(pmode);
1955 return this;
1956 };
1957
1958 var documentProperties = {
1959 title: "",
1960 subject: "",
1961 author: "",
1962 keywords: "",
1963 creator: ""
1964 };
1965
1966 API.__private__.getDocumentProperty = function(key) {
1967 if (Object.keys(documentProperties).indexOf(key) === -1) {
1968 throw new Error("Invalid argument passed to jsPDF.getDocumentProperty");
1969 }
1970 return documentProperties[key];
1971 };
1972
1973 API.__private__.getDocumentProperties = function() {
1974 return documentProperties;
1975 };
1976
1977 /**
1978 * Adds a properties to the PDF document.
1979 *
1980 * @param {Object} A property_name-to-property_value object structure.
1981 * @function
1982 * @instance
1983 * @returns {jsPDF}
1984 * @memberof jsPDF#
1985 * @name setDocumentProperties
1986 */
1987 API.__private__.setDocumentProperties = API.setProperties = API.setDocumentProperties = function(
1988 properties
1989 ) {
1990 // copying only those properties we can render.
1991 for (var property in documentProperties) {
1992 if (documentProperties.hasOwnProperty(property) && properties[property]) {
1993 documentProperties[property] = properties[property];
1994 }
1995 }
1996 return this;
1997 };
1998
1999 API.__private__.setDocumentProperty = function(key, value) {
2000 if (Object.keys(documentProperties).indexOf(key) === -1) {
2001 throw new Error("Invalid arguments passed to jsPDF.setDocumentProperty");
2002 }
2003 return (documentProperties[key] = value);
2004 };
2005
2006 var fonts = {}; // collection of font objects, where key is fontKey - a dynamically created label for a given font.
2007 var fontmap = {}; // mapping structure fontName > fontStyle > font key - performance layer. See addFont()
2008 var activeFontKey; // will be string representing the KEY of the font as combination of fontName + fontStyle
2009 var fontStateStack = []; //
2010 var patterns = {}; // collection of pattern objects
2011 var patternMap = {}; // see fonts
2012 var gStates = {}; // collection of graphic state objects
2013 var gStatesMap = {}; // see fonts
2014 var activeGState = null;
2015 var scaleFactor; // Scale factor
2016 var page = 0;
2017 var pagesContext = [];
2018 var events = new PubSub(API);
2019 var hotfixes = options.hotfixes || [];
2020
2021 var renderTargets = {};
2022 var renderTargetMap = {};
2023 var renderTargetStack = [];
2024 var pageX;
2025 var pageY;
2026 var pageMatrix; // only used for FormObjects
2027
2028 /**
2029 * A matrix object for 2D homogenous transformations: <br>
2030 * | a b 0 | <br>
2031 * | c d 0 | <br>
2032 * | e f 1 | <br>
2033 * pdf multiplies matrices righthand: v' = v x m1 x m2 x ...
2034 *
2035 * @class
2036 * @name Matrix
2037 * @param {number} sx
2038 * @param {number} shy
2039 * @param {number} shx
2040 * @param {number} sy
2041 * @param {number} tx
2042 * @param {number} ty
2043 * @constructor
2044 */
2045 var Matrix = function(sx, shy, shx, sy, tx, ty) {
2046 if (!(this instanceof Matrix)) {
2047 return new Matrix(sx, shy, shx, sy, tx, ty);
2048 }
2049
2050 if (isNaN(sx)) sx = 1;
2051 if (isNaN(shy)) shy = 0;
2052 if (isNaN(shx)) shx = 0;
2053 if (isNaN(sy)) sy = 1;
2054 if (isNaN(tx)) tx = 0;
2055 if (isNaN(ty)) ty = 0;
2056
2057 this._matrix = [sx, shy, shx, sy, tx, ty];
2058 };
2059
2060 /**
2061 * @name sx
2062 * @memberof Matrix#
2063 */
2064 Object.defineProperty(Matrix.prototype, "sx", {
2065 get: function() {
2066 return this._matrix[0];
2067 },
2068 set: function(value) {
2069 this._matrix[0] = value;
2070 }
2071 });
2072
2073 /**
2074 * @name shy
2075 * @memberof Matrix#
2076 */
2077 Object.defineProperty(Matrix.prototype, "shy", {
2078 get: function() {
2079 return this._matrix[1];
2080 },
2081 set: function(value) {
2082 this._matrix[1] = value;
2083 }
2084 });
2085
2086 /**
2087 * @name shx
2088 * @memberof Matrix#
2089 */
2090 Object.defineProperty(Matrix.prototype, "shx", {
2091 get: function() {
2092 return this._matrix[2];
2093 },
2094 set: function(value) {
2095 this._matrix[2] = value;
2096 }
2097 });
2098
2099 /**
2100 * @name sy
2101 * @memberof Matrix#
2102 */
2103 Object.defineProperty(Matrix.prototype, "sy", {
2104 get: function() {
2105 return this._matrix[3];
2106 },
2107 set: function(value) {
2108 this._matrix[3] = value;
2109 }
2110 });
2111
2112 /**
2113 * @name tx
2114 * @memberof Matrix#
2115 */
2116 Object.defineProperty(Matrix.prototype, "tx", {
2117 get: function() {
2118 return this._matrix[4];
2119 },
2120 set: function(value) {
2121 this._matrix[4] = value;
2122 }
2123 });
2124
2125 /**
2126 * @name ty
2127 * @memberof Matrix#
2128 */
2129 Object.defineProperty(Matrix.prototype, "ty", {
2130 get: function() {
2131 return this._matrix[5];
2132 },
2133 set: function(value) {
2134 this._matrix[5] = value;
2135 }
2136 });
2137
2138 Object.defineProperty(Matrix.prototype, "a", {
2139 get: function() {
2140 return this._matrix[0];
2141 },
2142 set: function(value) {
2143 this._matrix[0] = value;
2144 }
2145 });
2146
2147 Object.defineProperty(Matrix.prototype, "b", {
2148 get: function() {
2149 return this._matrix[1];
2150 },
2151 set: function(value) {
2152 this._matrix[1] = value;
2153 }
2154 });
2155
2156 Object.defineProperty(Matrix.prototype, "c", {
2157 get: function() {
2158 return this._matrix[2];
2159 },
2160 set: function(value) {
2161 this._matrix[2] = value;
2162 }
2163 });
2164
2165 Object.defineProperty(Matrix.prototype, "d", {
2166 get: function() {
2167 return this._matrix[3];
2168 },
2169 set: function(value) {
2170 this._matrix[3] = value;
2171 }
2172 });
2173
2174 Object.defineProperty(Matrix.prototype, "e", {
2175 get: function() {
2176 return this._matrix[4];
2177 },
2178 set: function(value) {
2179 this._matrix[4] = value;
2180 }
2181 });
2182
2183 Object.defineProperty(Matrix.prototype, "f", {
2184 get: function() {
2185 return this._matrix[5];
2186 },
2187 set: function(value) {
2188 this._matrix[5] = value;
2189 }
2190 });
2191
2192 /**
2193 * @name rotation
2194 * @memberof Matrix#
2195 */
2196 Object.defineProperty(Matrix.prototype, "rotation", {
2197 get: function() {
2198 return Math.atan2(this.shx, this.sx);
2199 }
2200 });
2201
2202 /**
2203 * @name scaleX
2204 * @memberof Matrix#
2205 */
2206 Object.defineProperty(Matrix.prototype, "scaleX", {
2207 get: function() {
2208 return this.decompose().scale.sx;
2209 }
2210 });
2211
2212 /**
2213 * @name scaleY
2214 * @memberof Matrix#
2215 */
2216 Object.defineProperty(Matrix.prototype, "scaleY", {
2217 get: function() {
2218 return this.decompose().scale.sy;
2219 }
2220 });
2221
2222 /**
2223 * @name isIdentity
2224 * @memberof Matrix#
2225 */
2226 Object.defineProperty(Matrix.prototype, "isIdentity", {
2227 get: function() {
2228 if (this.sx !== 1) {
2229 return false;
2230 }
2231 if (this.shy !== 0) {
2232 return false;
2233 }
2234 if (this.shx !== 0) {
2235 return false;
2236 }
2237 if (this.sy !== 1) {
2238 return false;
2239 }
2240 if (this.tx !== 0) {
2241 return false;
2242 }
2243 if (this.ty !== 0) {
2244 return false;
2245 }
2246 return true;
2247 }
2248 });
2249
2250 /**
2251 * Join the Matrix Values to a String
2252 *
2253 * @function join
2254 * @param {string} separator Specifies a string to separate each pair of adjacent elements of the array. The separator is converted to a string if necessary. If omitted, the array elements are separated with a comma (","). If separator is an empty string, all elements are joined without any characters in between them.
2255 * @returns {string} A string with all array elements joined.
2256 * @memberof Matrix#
2257 */
2258 Matrix.prototype.join = function(separator) {
2259 return [this.sx, this.shy, this.shx, this.sy, this.tx, this.ty]
2260 .map(hpf)
2261 .join(separator);
2262 };
2263
2264 /**
2265 * Multiply the matrix with given Matrix
2266 *
2267 * @function multiply
2268 * @param matrix
2269 * @returns {Matrix}
2270 * @memberof Matrix#
2271 */
2272 Matrix.prototype.multiply = function(matrix) {
2273 var sx = matrix.sx * this.sx + matrix.shy * this.shx;
2274 var shy = matrix.sx * this.shy + matrix.shy * this.sy;
2275 var shx = matrix.shx * this.sx + matrix.sy * this.shx;
2276 var sy = matrix.shx * this.shy + matrix.sy * this.sy;
2277 var tx = matrix.tx * this.sx + matrix.ty * this.shx + this.tx;
2278 var ty = matrix.tx * this.shy + matrix.ty * this.sy + this.ty;
2279
2280 return new Matrix(sx, shy, shx, sy, tx, ty);
2281 };
2282
2283 /**
2284 * @function decompose
2285 * @memberof Matrix#
2286 */
2287 Matrix.prototype.decompose = function() {
2288 var a = this.sx;
2289 var b = this.shy;
2290 var c = this.shx;
2291 var d = this.sy;
2292 var e = this.tx;
2293 var f = this.ty;
2294
2295 var scaleX = Math.sqrt(a * a + b * b);
2296 a /= scaleX;
2297 b /= scaleX;
2298
2299 var shear = a * c + b * d;
2300 c -= a * shear;
2301 d -= b * shear;
2302
2303 var scaleY = Math.sqrt(c * c + d * d);
2304 c /= scaleY;
2305 d /= scaleY;
2306 shear /= scaleY;
2307
2308 if (a * d < b * c) {
2309 a = -a;
2310 b = -b;
2311 shear = -shear;
2312 scaleX = -scaleX;
2313 }
2314
2315 return {
2316 scale: new Matrix(scaleX, 0, 0, scaleY, 0, 0),
2317 translate: new Matrix(1, 0, 0, 1, e, f),
2318 rotate: new Matrix(a, b, -b, a, 0, 0),
2319 skew: new Matrix(1, 0, shear, 1, 0, 0)
2320 };
2321 };
2322
2323 /**
2324 * @function toString
2325 * @memberof Matrix#
2326 */
2327 Matrix.prototype.toString = function(parmPrecision) {
2328 return this.join(" ");
2329 };
2330
2331 /**
2332 * @function inversed
2333 * @memberof Matrix#
2334 */
2335 Matrix.prototype.inversed = function() {
2336 var a = this.sx,
2337 b = this.shy,
2338 c = this.shx,
2339 d = this.sy,
2340 e = this.tx,
2341 f = this.ty;
2342
2343 var quot = 1 / (a * d - b * c);
2344
2345 var aInv = d * quot;
2346 var bInv = -b * quot;
2347 var cInv = -c * quot;
2348 var dInv = a * quot;
2349 var eInv = -aInv * e - cInv * f;
2350 var fInv = -bInv * e - dInv * f;
2351
2352 return new Matrix(aInv, bInv, cInv, dInv, eInv, fInv);
2353 };
2354
2355 /**
2356 * @function applyToPoint
2357 * @memberof Matrix#
2358 */
2359 Matrix.prototype.applyToPoint = function(pt) {
2360 var x = pt.x * this.sx + pt.y * this.shx + this.tx;
2361 var y = pt.x * this.shy + pt.y * this.sy + this.ty;
2362 return new Point(x, y);
2363 };
2364
2365 /**
2366 * @function applyToRectangle
2367 * @memberof Matrix#
2368 */
2369 Matrix.prototype.applyToRectangle = function(rect) {
2370 var pt1 = this.applyToPoint(rect);
2371 var pt2 = this.applyToPoint(new Point(rect.x + rect.w, rect.y + rect.h));
2372 return new Rectangle(pt1.x, pt1.y, pt2.x - pt1.x, pt2.y - pt1.y);
2373 };
2374
2375 /**
2376 * Clone the Matrix
2377 *
2378 * @function clone
2379 * @memberof Matrix#
2380 * @name clone
2381 * @instance
2382 */
2383 Matrix.prototype.clone = function() {
2384 var sx = this.sx;
2385 var shy = this.shy;
2386 var shx = this.shx;
2387 var sy = this.sy;
2388 var tx = this.tx;
2389 var ty = this.ty;
2390
2391 return new Matrix(sx, shy, shx, sy, tx, ty);
2392 };
2393
2394 API.Matrix = Matrix;
2395
2396 /**
2397 * Multiplies two matrices. (see {@link Matrix})
2398 * @param {Matrix} m1
2399 * @param {Matrix} m2
2400 * @memberof jsPDF#
2401 * @name matrixMult
2402 */
2403 var matrixMult = (API.matrixMult = function(m1, m2) {
2404 return m2.multiply(m1);
2405 });
2406
2407 /**
2408 * The identity matrix (equivalent to new Matrix(1, 0, 0, 1, 0, 0)).
2409 * @type {Matrix}
2410 * @memberof! jsPDF#
2411 * @name identityMatrix
2412 */
2413 var identityMatrix = new Matrix(1, 0, 0, 1, 0, 0);
2414 API.unitMatrix = API.identityMatrix = identityMatrix;
2415
2416 /**
2417 * Adds a new pattern for later use.
2418 * @param {String} key The key by it can be referenced later. The keys must be unique!
2419 * @param {API.Pattern} pattern The pattern
2420 */
2421 var addPattern = function(key, pattern) {
2422 // only add it if it is not already present (the keys provided by the user must be unique!)
2423 if (patternMap[key]) return;
2424
2425 var prefix = pattern instanceof ShadingPattern ? "Sh" : "P";
2426 var patternKey = prefix + (Object.keys(patterns).length + 1).toString(10);
2427 pattern.id = patternKey;
2428
2429 patternMap[key] = patternKey;
2430 patterns[patternKey] = pattern;
2431
2432 events.publish("addPattern", pattern);
2433 };
2434
2435 /**
2436 * A pattern describing a shading pattern.
2437 *
2438 * Only available in "advanced" API mode.
2439 *
2440 * @param {String} type One of "axial" or "radial"
2441 * @param {Array<Number>} coords Either [x1, y1, x2, y2] for "axial" type describing the two interpolation points
2442 * or [x1, y1, r, x2, y2, r2] for "radial" describing inner and the outer circle.
2443 * @param {Array<Object>} colors An array of objects with the fields "offset" and "color". "offset" describes
2444 * the offset in parameter space [0, 1]. "color" is an array of length 3 describing RGB values in [0, 255].
2445 * @param {GState=} gState An additional graphics state that gets applied to the pattern (optional).
2446 * @param {Matrix=} matrix A matrix that describes the transformation between the pattern coordinate system
2447 * and the use coordinate system (optional).
2448 * @constructor
2449 * @extends API.Pattern
2450 */
2451 API.ShadingPattern = ShadingPattern;
2452
2453 /**
2454 * A PDF Tiling pattern.
2455 *
2456 * Only available in "advanced" API mode.
2457 *
2458 * @param {Array.<Number>} boundingBox The bounding box at which one pattern cell gets clipped.
2459 * @param {Number} xStep Horizontal spacing between pattern cells.
2460 * @param {Number} yStep Vertical spacing between pattern cells.
2461 * @param {API.GState=} gState An additional graphics state that gets applied to the pattern (optional).
2462 * @param {Matrix=} matrix A matrix that describes the transformation between the pattern coordinate system
2463 * and the use coordinate system (optional).
2464 * @constructor
2465 * @extends API.Pattern
2466 */
2467 API.TilingPattern = TilingPattern;
2468
2469 /**
2470 * Adds a new {@link API.ShadingPattern} for later use. Only available in "advanced" API mode.
2471 * @param {String} key
2472 * @param {Pattern} pattern
2473 * @function
2474 * @returns {jsPDF}
2475 * @memberof jsPDF#
2476 * @name addPattern
2477 */
2478 API.addShadingPattern = function(key, pattern) {
2479 advancedApiModeTrap("addShadingPattern()");
2480
2481 addPattern(key, pattern);
2482 return this;
2483 };
2484
2485 /**
2486 * Begins a new tiling pattern. All subsequent render calls are drawn to this pattern until {@link API.endTilingPattern}
2487 * gets called. Only available in "advanced" API mode.
2488 * @param {API.Pattern} pattern
2489 * @memberof jsPDF#
2490 * @name beginTilingPattern
2491 */
2492 API.beginTilingPattern = function(pattern) {
2493 advancedApiModeTrap("beginTilingPattern()");
2494
2495 beginNewRenderTarget(
2496 pattern.boundingBox[0],
2497 pattern.boundingBox[1],
2498 pattern.boundingBox[2] - pattern.boundingBox[0],
2499 pattern.boundingBox[3] - pattern.boundingBox[1],
2500 pattern.matrix
2501 );
2502 };
2503
2504 /**
2505 * Ends a tiling pattern and sets the render target to the one active before {@link API.beginTilingPattern} has been called.
2506 *
2507 * Only available in "advanced" API mode.
2508 *
2509 * @param {string} key A unique key that is used to reference this pattern at later use.
2510 * @param {API.Pattern} pattern The pattern to end.
2511 * @memberof jsPDF#
2512 * @name endTilingPattern
2513 */
2514 API.endTilingPattern = function(key, pattern) {
2515 advancedApiModeTrap("endTilingPattern()");
2516
2517 // retrieve the stream
2518 pattern.stream = pages[currentPage].join("\n");
2519
2520 addPattern(key, pattern);
2521
2522 events.publish("endTilingPattern", pattern);
2523
2524 // restore state from stack
2525 renderTargetStack.pop().restore();
2526 };
2527
2528 var newObject = (API.__private__.newObject = function() {
2529 var oid = newObjectDeferred();
2530 newObjectDeferredBegin(oid, true);
2531 return oid;
2532 });
2533
2534 // Does not output the object. The caller must call newObjectDeferredBegin(oid) before outputing any data
2535 var newObjectDeferred = (API.__private__.newObjectDeferred = function() {
2536 objectNumber++;
2537 offsets[objectNumber] = function() {
2538 return contentLength;
2539 };
2540 return objectNumber;
2541 });
2542
2543 var newObjectDeferredBegin = function(oid, doOutput) {
2544 doOutput = typeof doOutput === "boolean" ? doOutput : false;
2545 offsets[oid] = contentLength;
2546 if (doOutput) {
2547 out(oid + " 0 obj");
2548 }
2549 return oid;
2550 };
2551 // Does not output the object until after the pages have been output.
2552 // Returns an object containing the objectId and content.
2553 // All pages have been added so the object ID can be estimated to start right after.
2554 // This does not modify the current objectNumber; It must be updated after the newObjects are output.
2555 var newAdditionalObject = (API.__private__.newAdditionalObject = function() {
2556 var objId = newObjectDeferred();
2557 var obj = {
2558 objId: objId,
2559 content: ""
2560 };
2561 additionalObjects.push(obj);
2562 return obj;
2563 });
2564
2565 var rootDictionaryObjId = newObjectDeferred();
2566 var resourceDictionaryObjId = newObjectDeferred();
2567
2568 /////////////////////
2569 // Private functions
2570 /////////////////////
2571
2572 var decodeColorString = (API.__private__.decodeColorString = function(color) {
2573 var colorEncoded = color.split(" ");
2574 if (
2575 colorEncoded.length === 2 &&
2576 (colorEncoded[1] === "g" || colorEncoded[1] === "G")
2577 ) {
2578 // convert grayscale value to rgb so that it can be converted to hex for consistency
2579 var floatVal = parseFloat(colorEncoded[0]);
2580 colorEncoded = [floatVal, floatVal, floatVal, "r"];
2581 } else if (
2582 colorEncoded.length === 5 &&
2583 (colorEncoded[4] === "k" || colorEncoded[4] === "K")
2584 ) {
2585 // convert CMYK values to rbg so that it can be converted to hex for consistency
2586 var red = (1.0 - colorEncoded[0]) * (1.0 - colorEncoded[3]);
2587 var green = (1.0 - colorEncoded[1]) * (1.0 - colorEncoded[3]);
2588 var blue = (1.0 - colorEncoded[2]) * (1.0 - colorEncoded[3]);
2589
2590 colorEncoded = [red, green, blue, "r"];
2591 }
2592 var colorAsRGB = "#";
2593 for (var i = 0; i < 3; i++) {
2594 colorAsRGB += (
2595 "0" + Math.floor(parseFloat(colorEncoded[i]) * 255).toString(16)
2596 ).slice(-2);
2597 }
2598 return colorAsRGB;
2599 });
2600
2601 var encodeColorString = (API.__private__.encodeColorString = function(
2602 options
2603 ) {
2604 var color;
2605
2606 if (typeof options === "string") {
2607 options = {
2608 ch1: options
2609 };
2610 }
2611 var ch1 = options.ch1;
2612 var ch2 = options.ch2;
2613 var ch3 = options.ch3;
2614 var ch4 = options.ch4;
2615 var letterArray =
2616 options.pdfColorType === "draw" ? ["G", "RG", "K"] : ["g", "rg", "k"];
2617
2618 if (typeof ch1 === "string" && ch1.charAt(0) !== "#") {
2619 var rgbColor = new RGBColor(ch1);
2620 if (rgbColor.ok) {
2621 ch1 = rgbColor.toHex();
2622 } else if (!/^\d*\.?\d*$/.test(ch1)) {
2623 throw new Error(
2624 'Invalid color "' + ch1 + '" passed to jsPDF.encodeColorString.'
2625 );
2626 }
2627 }
2628 //convert short rgb to long form
2629 if (typeof ch1 === "string" && /^#[0-9A-Fa-f]{3}$/.test(ch1)) {
2630 ch1 = "#" + ch1[1] + ch1[1] + ch1[2] + ch1[2] + ch1[3] + ch1[3];
2631 }
2632
2633 if (typeof ch1 === "string" && /^#[0-9A-Fa-f]{6}$/.test(ch1)) {
2634 var hex = parseInt(ch1.substr(1), 16);
2635 ch1 = (hex >> 16) & 255;
2636 ch2 = (hex >> 8) & 255;
2637 ch3 = hex & 255;
2638 }
2639
2640 if (
2641 typeof ch2 === "undefined" ||
2642 (typeof ch4 === "undefined" && ch1 === ch2 && ch2 === ch3)
2643 ) {
2644 // Gray color space.
2645 if (typeof ch1 === "string") {
2646 color = ch1 + " " + letterArray[0];
2647 } else {
2648 switch (options.precision) {
2649 case 2:
2650 color = f2(ch1 / 255) + " " + letterArray[0];
2651 break;
2652 case 3:
2653 default:
2654 color = f3(ch1 / 255) + " " + letterArray[0];
2655 }
2656 }
2657 } else if (typeof ch4 === "undefined" || typeof ch4 === "object") {
2658 // assume RGBA
2659 if (ch4 && !isNaN(ch4.a)) {
2660 //TODO Implement transparency.
2661 //WORKAROUND use white for now, if transparent, otherwise handle as rgb
2662 if (ch4.a === 0) {
2663 color = ["1.", "1.", "1.", letterArray[1]].join(" ");
2664 return color;
2665 }
2666 }
2667 // assume RGB
2668 if (typeof ch1 === "string") {
2669 color = [ch1, ch2, ch3, letterArray[1]].join(" ");
2670 } else {
2671 switch (options.precision) {
2672 case 2:
2673 color = [
2674 f2(ch1 / 255),
2675 f2(ch2 / 255),
2676 f2(ch3 / 255),
2677 letterArray[1]
2678 ].join(" ");
2679 break;
2680 default:
2681 case 3:
2682 color = [
2683 f3(ch1 / 255),
2684 f3(ch2 / 255),
2685 f3(ch3 / 255),
2686 letterArray[1]
2687 ].join(" ");
2688 }
2689 }
2690 } else {
2691 // assume CMYK
2692 if (typeof ch1 === "string") {
2693 color = [ch1, ch2, ch3, ch4, letterArray[2]].join(" ");
2694 } else {
2695 switch (options.precision) {
2696 case 2:
2697 color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), letterArray[2]].join(
2698 " "
2699 );
2700 break;
2701 case 3:
2702 default:
2703 color = [f3(ch1), f3(ch2), f3(ch3), f3(ch4), letterArray[2]].join(
2704 " "
2705 );
2706 }
2707 }
2708 }
2709 return color;
2710 });
2711
2712 var getFilters = (API.__private__.getFilters = function() {
2713 return filters;
2714 });
2715
2716 var putStream = (API.__private__.putStream = function(options) {
2717 options = options || {};
2718 var data = options.data || "";
2719 var filters = options.filters || getFilters();
2720 var alreadyAppliedFilters = options.alreadyAppliedFilters || [];
2721 var addLength1 = options.addLength1 || false;
2722 var valueOfLength1 = data.length;
2723 var objectId = options.objectId;
2724 var encryptor = function(data) {
2725 return data;
2726 };
2727 if (encryptionOptions !== null && typeof objectId == "undefined") {
2728 throw new Error(
2729 "ObjectId must be passed to putStream for file encryption"
2730 );
2731 }
2732 if (encryptionOptions !== null) {
2733 encryptor = encryption.encryptor(objectId, 0);
2734 }
2735
2736 var processedData = {};
2737 if (filters === true) {
2738 filters = ["FlateEncode"];
2739 }
2740 var keyValues = options.additionalKeyValues || [];
2741 if (typeof jsPDF.API.processDataByFilters !== "undefined") {
2742 processedData = jsPDF.API.processDataByFilters(data, filters);
2743 } else {
2744 processedData = { data: data, reverseChain: [] };
2745 }
2746 var filterAsString =
2747 processedData.reverseChain +
2748 (Array.isArray(alreadyAppliedFilters)
2749 ? alreadyAppliedFilters.join(" ")
2750 : alreadyAppliedFilters.toString());
2751
2752 if (processedData.data.length !== 0) {
2753 keyValues.push({
2754 key: "Length",
2755 value: processedData.data.length
2756 });
2757 if (addLength1 === true) {
2758 keyValues.push({
2759 key: "Length1",
2760 value: valueOfLength1
2761 });
2762 }
2763 }
2764
2765 if (filterAsString.length != 0) {
2766 if (filterAsString.split("/").length - 1 === 1) {
2767 keyValues.push({
2768 key: "Filter",
2769 value: filterAsString
2770 });
2771 } else {
2772 keyValues.push({
2773 key: "Filter",
2774 value: "[" + filterAsString + "]"
2775 });
2776
2777 for (var j = 0; j < keyValues.length; j += 1) {
2778 if (keyValues[j].key === "DecodeParms") {
2779 var decodeParmsArray = [];
2780
2781 for (
2782 var i = 0;
2783 i < processedData.reverseChain.split("/").length - 1;
2784 i += 1
2785 ) {
2786 decodeParmsArray.push("null");
2787 }
2788
2789 decodeParmsArray.push(keyValues[j].value);
2790 keyValues[j].value = "[" + decodeParmsArray.join(" ") + "]";
2791 }
2792 }
2793 }
2794 }
2795
2796 out("<<");
2797 for (var k = 0; k < keyValues.length; k++) {
2798 out("/" + keyValues[k].key + " " + keyValues[k].value);
2799 }
2800 out(">>");
2801 if (processedData.data.length !== 0) {
2802 out("stream");
2803 out(encryptor(processedData.data));
2804 out("endstream");
2805 }
2806 });
2807
2808 var putPage = (API.__private__.putPage = function(page) {
2809 var pageNumber = page.number;
2810 var data = page.data;
2811 var pageObjectNumber = page.objId;
2812 var pageContentsObjId = page.contentsObjId;
2813
2814 newObjectDeferredBegin(pageObjectNumber, true);
2815 out("<</Type /Page");
2816 out("/Parent " + page.rootDictionaryObjId + " 0 R");
2817 out("/Resources " + page.resourceDictionaryObjId + " 0 R");
2818 out(
2819 "/MediaBox [" +
2820 parseFloat(hpf(page.mediaBox.bottomLeftX)) +
2821 " " +
2822 parseFloat(hpf(page.mediaBox.bottomLeftY)) +
2823 " " +
2824 hpf(page.mediaBox.topRightX) +
2825 " " +
2826 hpf(page.mediaBox.topRightY) +
2827 "]"
2828 );
2829 if (page.cropBox !== null) {
2830 out(
2831 "/CropBox [" +
2832 hpf(page.cropBox.bottomLeftX) +
2833 " " +
2834 hpf(page.cropBox.bottomLeftY) +
2835 " " +
2836 hpf(page.cropBox.topRightX) +
2837 " " +
2838 hpf(page.cropBox.topRightY) +
2839 "]"
2840 );
2841 }
2842
2843 if (page.bleedBox !== null) {
2844 out(
2845 "/BleedBox [" +
2846 hpf(page.bleedBox.bottomLeftX) +
2847 " " +
2848 hpf(page.bleedBox.bottomLeftY) +
2849 " " +
2850 hpf(page.bleedBox.topRightX) +
2851 " " +
2852 hpf(page.bleedBox.topRightY) +
2853 "]"
2854 );
2855 }
2856
2857 if (page.trimBox !== null) {
2858 out(
2859 "/TrimBox [" +
2860 hpf(page.trimBox.bottomLeftX) +
2861 " " +
2862 hpf(page.trimBox.bottomLeftY) +
2863 " " +
2864 hpf(page.trimBox.topRightX) +
2865 " " +
2866 hpf(page.trimBox.topRightY) +
2867 "]"
2868 );
2869 }
2870
2871 if (page.artBox !== null) {
2872 out(
2873 "/ArtBox [" +
2874 hpf(page.artBox.bottomLeftX) +
2875 " " +
2876 hpf(page.artBox.bottomLeftY) +
2877 " " +
2878 hpf(page.artBox.topRightX) +
2879 " " +
2880 hpf(page.artBox.topRightY) +
2881 "]"
2882 );
2883 }
2884
2885 if (typeof page.userUnit === "number" && page.userUnit !== 1.0) {
2886 out("/UserUnit " + page.userUnit);
2887 }
2888
2889 events.publish("putPage", {
2890 objId: pageObjectNumber,
2891 pageContext: pagesContext[pageNumber],
2892 pageNumber: pageNumber,
2893 page: data
2894 });
2895 out("/Contents " + pageContentsObjId + " 0 R");
2896 out(">>");
2897 out("endobj");
2898 // Page content
2899 var pageContent = data.join("\n");
2900
2901 if (apiMode === ApiMode.ADVANCED) {
2902 // if the user forgot to switch back to COMPAT mode, we must balance the graphics stack again
2903 pageContent += "\nQ";
2904 }
2905
2906 newObjectDeferredBegin(pageContentsObjId, true);
2907 putStream({
2908 data: pageContent,
2909 filters: getFilters(),
2910 objectId: pageContentsObjId
2911 });
2912 out("endobj");
2913 return pageObjectNumber;
2914 });
2915
2916 var putPages = (API.__private__.putPages = function() {
2917 var n,
2918 i,
2919 pageObjectNumbers = [];
2920
2921 for (n = 1; n <= page; n++) {
2922 pagesContext[n].objId = newObjectDeferred();
2923 pagesContext[n].contentsObjId = newObjectDeferred();
2924 }
2925
2926 for (n = 1; n <= page; n++) {
2927 pageObjectNumbers.push(
2928 putPage({
2929 number: n,
2930 data: pages[n],
2931 objId: pagesContext[n].objId,
2932 contentsObjId: pagesContext[n].contentsObjId,
2933 mediaBox: pagesContext[n].mediaBox,
2934 cropBox: pagesContext[n].cropBox,
2935 bleedBox: pagesContext[n].bleedBox,
2936 trimBox: pagesContext[n].trimBox,
2937 artBox: pagesContext[n].artBox,
2938 userUnit: pagesContext[n].userUnit,
2939 rootDictionaryObjId: rootDictionaryObjId,
2940 resourceDictionaryObjId: resourceDictionaryObjId
2941 })
2942 );
2943 }
2944 newObjectDeferredBegin(rootDictionaryObjId, true);
2945 out("<</Type /Pages");
2946 var kids = "/Kids [";
2947 for (i = 0; i < page; i++) {
2948 kids += pageObjectNumbers[i] + " 0 R ";
2949 }
2950 out(kids + "]");
2951 out("/Count " + page);
2952 out(">>");
2953 out("endobj");
2954 events.publish("postPutPages");
2955 });
2956
2957 var putFont = function(font) {
2958 var pdfEscapeWithNeededParanthesis = function(text, flags) {
2959 var addParanthesis = text.indexOf(" ") !== -1; // no space in string
2960 return addParanthesis
2961 ? "(" + pdfEscape(text, flags) + ")"
2962 : pdfEscape(text, flags);
2963 };
2964
2965 events.publish("putFont", {
2966 font: font,
2967 out: out,
2968 newObject: newObject,
2969 putStream: putStream,
2970 pdfEscapeWithNeededParanthesis: pdfEscapeWithNeededParanthesis
2971 });
2972
2973 if (font.isAlreadyPutted !== true) {
2974 font.objectNumber = newObject();
2975 out("<<");
2976 out("/Type /Font");
2977 out("/BaseFont /" + pdfEscapeWithNeededParanthesis(font.postScriptName));
2978 out("/Subtype /Type1");
2979 if (typeof font.encoding === "string") {
2980 out("/Encoding /" + font.encoding);
2981 }
2982 out("/FirstChar 32");
2983 out("/LastChar 255");
2984 out(">>");
2985 out("endobj");
2986 }
2987 };
2988
2989 var putFonts = function() {
2990 for (var fontKey in fonts) {
2991 if (fonts.hasOwnProperty(fontKey)) {
2992 if (
2993 putOnlyUsedFonts === false ||
2994 (putOnlyUsedFonts === true && usedFonts.hasOwnProperty(fontKey))
2995 ) {
2996 putFont(fonts[fontKey]);
2997 }
2998 }
2999 }
3000 };
3001
3002 var putXObject = function(xObject) {
3003 xObject.objectNumber = newObject();
3004
3005 var options = [];
3006 options.push({ key: "Type", value: "/XObject" });
3007 options.push({ key: "Subtype", value: "/Form" });
3008 options.push({
3009 key: "BBox",
3010 value:
3011 "[" +
3012 [
3013 hpf(xObject.x),
3014 hpf(xObject.y),
3015 hpf(xObject.x + xObject.width),
3016 hpf(xObject.y + xObject.height)
3017 ].join(" ") +
3018 "]"
3019 });
3020 options.push({
3021 key: "Matrix",
3022 value: "[" + xObject.matrix.toString() + "]"
3023 });
3024 // TODO: /Resources
3025
3026 var stream = xObject.pages[1].join("\n");
3027 putStream({
3028 data: stream,
3029 additionalKeyValues: options,
3030 objectId: xObject.objectNumber
3031 });
3032 out("endobj");
3033 };
3034
3035 var putXObjects = function() {
3036 for (var xObjectKey in renderTargets) {
3037 if (renderTargets.hasOwnProperty(xObjectKey)) {
3038 putXObject(renderTargets[xObjectKey]);
3039 }
3040 }
3041 };
3042
3043 var interpolateAndEncodeRGBStream = function(colors, numberSamples) {
3044 var tValues = [];
3045 var t;
3046 var dT = 1.0 / (numberSamples - 1);
3047 for (t = 0.0; t < 1.0; t += dT) {
3048 tValues.push(t);
3049 }
3050 tValues.push(1.0);
3051 // add first and last control point if not present
3052 if (colors[0].offset != 0.0) {
3053 var c0 = {
3054 offset: 0.0,
3055 color: colors[0].color
3056 };
3057 colors.unshift(c0);
3058 }
3059 if (colors[colors.length - 1].offset != 1.0) {
3060 var c1 = {
3061 offset: 1.0,
3062 color: colors[colors.length - 1].color
3063 };
3064 colors.push(c1);
3065 }
3066 var out = "";
3067 var index = 0;
3068
3069 for (var i = 0; i < tValues.length; i++) {
3070 t = tValues[i];
3071 while (t > colors[index + 1].offset) index++;
3072 var a = colors[index].offset;
3073 var b = colors[index + 1].offset;
3074 var d = (t - a) / (b - a);
3075
3076 var aColor = colors[index].color;
3077 var bColor = colors[index + 1].color;
3078
3079 out +=
3080 padd2Hex(Math.round((1 - d) * aColor[0] + d * bColor[0]).toString(16)) +
3081 padd2Hex(Math.round((1 - d) * aColor[1] + d * bColor[1]).toString(16)) +
3082 padd2Hex(Math.round((1 - d) * aColor[2] + d * bColor[2]).toString(16));
3083 }
3084 return out.trim();
3085 };
3086
3087 var putShadingPattern = function(pattern, numberSamples) {
3088 /*
3089 Axial patterns shade between the two points specified in coords, radial patterns between the inner
3090 and outer circle.
3091 The user can specify an array (colors) that maps t-Values in [0, 1] to RGB colors. These are now
3092 interpolated to equidistant samples and written to pdf as a sample (type 0) function.
3093 */
3094 // The number of color samples that should be used to describe the shading.
3095 // The higher, the more accurate the gradient will be.
3096 numberSamples || (numberSamples = 21);
3097 var funcObjectNumber = newObject();
3098 var stream = interpolateAndEncodeRGBStream(pattern.colors, numberSamples);
3099
3100 var options = [];
3101 options.push({ key: "FunctionType", value: "0" });
3102 options.push({ key: "Domain", value: "[0.0 1.0]" });
3103 options.push({ key: "Size", value: "[" + numberSamples + "]" });
3104 options.push({ key: "BitsPerSample", value: "8" });
3105 options.push({ key: "Range", value: "[0.0 1.0 0.0 1.0 0.0 1.0]" });
3106 options.push({ key: "Decode", value: "[0.0 1.0 0.0 1.0 0.0 1.0]" });
3107
3108 putStream({
3109 data: stream,
3110 additionalKeyValues: options,
3111 alreadyAppliedFilters: ["/ASCIIHexDecode"],
3112 objectId: funcObjectNumber
3113 });
3114 out("endobj");
3115
3116 pattern.objectNumber = newObject();
3117 out("<< /ShadingType " + pattern.type);
3118 out("/ColorSpace /DeviceRGB");
3119 var coords =
3120 "/Coords [" +
3121 hpf(parseFloat(pattern.coords[0])) +
3122 " " + // x1
3123 hpf(parseFloat(pattern.coords[1])) +
3124 " "; // y1
3125 if (pattern.type === 2) {
3126 // axial
3127 coords +=
3128 hpf(parseFloat(pattern.coords[2])) +
3129 " " + // x2
3130 hpf(parseFloat(pattern.coords[3])); // y2
3131 } else {
3132 // radial
3133 coords +=
3134 hpf(parseFloat(pattern.coords[2])) +
3135 " " + // r1
3136 hpf(parseFloat(pattern.coords[3])) +
3137 " " + // x2
3138 hpf(parseFloat(pattern.coords[4])) +
3139 " " + // y2
3140 hpf(parseFloat(pattern.coords[5])); // r2
3141 }
3142 coords += "]";
3143 out(coords);
3144
3145 if (pattern.matrix) {
3146 out("/Matrix [" + pattern.matrix.toString() + "]");
3147 }
3148 out("/Function " + funcObjectNumber + " 0 R");
3149 out("/Extend [true true]");
3150 out(">>");
3151 out("endobj");
3152 };
3153
3154 var putTilingPattern = function(pattern, deferredResourceDictionaryIds) {
3155 var resourcesObjectId = newObjectDeferred();
3156 var patternObjectId = newObject();
3157
3158 deferredResourceDictionaryIds.push({
3159 resourcesOid: resourcesObjectId,
3160 objectOid: patternObjectId
3161 });
3162
3163 pattern.objectNumber = patternObjectId;
3164 var options = [];
3165 options.push({ key: "Type", value: "/Pattern" });
3166 options.push({ key: "PatternType", value: "1" }); // tiling pattern
3167 options.push({ key: "PaintType", value: "1" }); // colored tiling pattern
3168 options.push({ key: "TilingType", value: "1" }); // constant spacing
3169 options.push({
3170 key: "BBox",
3171 value: "[" + pattern.boundingBox.map(hpf).join(" ") + "]"
3172 });
3173 options.push({ key: "XStep", value: hpf(pattern.xStep) });
3174 options.push({ key: "YStep", value: hpf(pattern.yStep) });
3175 options.push({ key: "Resources", value: resourcesObjectId + " 0 R" });
3176 if (pattern.matrix) {
3177 options.push({
3178 key: "Matrix",
3179 value: "[" + pattern.matrix.toString() + "]"
3180 });
3181 }
3182
3183 putStream({
3184 data: pattern.stream,
3185 additionalKeyValues: options,
3186 objectId: pattern.objectNumber
3187 });
3188 out("endobj");
3189 };
3190
3191 var putPatterns = function(deferredResourceDictionaryIds) {
3192 var patternKey;
3193 for (patternKey in patterns) {
3194 if (patterns.hasOwnProperty(patternKey)) {
3195 if (patterns[patternKey] instanceof ShadingPattern) {
3196 putShadingPattern(patterns[patternKey]);
3197 } else if (patterns[patternKey] instanceof TilingPattern) {
3198 putTilingPattern(patterns[patternKey], deferredResourceDictionaryIds);
3199 }
3200 }
3201 }
3202 };
3203
3204 var putGState = function(gState) {
3205 gState.objectNumber = newObject();
3206 out("<<");
3207 for (var p in gState) {
3208 switch (p) {
3209 case "opacity":
3210 out("/ca " + f2(gState[p]));
3211 break;
3212 case "stroke-opacity":
3213 out("/CA " + f2(gState[p]));
3214 break;
3215 }
3216 }
3217 out(">>");
3218 out("endobj");
3219 };
3220
3221 var putGStates = function() {
3222 var gStateKey;
3223 for (gStateKey in gStates) {
3224 if (gStates.hasOwnProperty(gStateKey)) {
3225 putGState(gStates[gStateKey]);
3226 }
3227 }
3228 };
3229
3230 var putXobjectDict = function() {
3231 out("/XObject <<");
3232 for (var xObjectKey in renderTargets) {
3233 if (
3234 renderTargets.hasOwnProperty(xObjectKey) &&
3235 renderTargets[xObjectKey].objectNumber >= 0
3236 ) {
3237 out(
3238 "/" +
3239 xObjectKey +
3240 " " +
3241 renderTargets[xObjectKey].objectNumber +
3242 " 0 R"
3243 );
3244 }
3245 }
3246
3247 // Loop through images, or other data objects
3248 events.publish("putXobjectDict");
3249 out(">>");
3250 };
3251
3252 var putEncryptionDict = function() {
3253 encryption.oid = newObject();
3254 out("<<");
3255 out("/Filter /Standard");
3256 out("/V " + encryption.v);
3257 out("/R " + encryption.r);
3258 out("/U <" + encryption.toHexString(encryption.U) + ">");
3259 out("/O <" + encryption.toHexString(encryption.O) + ">");
3260 out("/P " + encryption.P);
3261 out(">>");
3262 out("endobj");
3263 };
3264
3265 var putFontDict = function() {
3266 out("/Font <<");
3267
3268 for (var fontKey in fonts) {
3269 if (fonts.hasOwnProperty(fontKey)) {
3270 if (
3271 putOnlyUsedFonts === false ||
3272 (putOnlyUsedFonts === true && usedFonts.hasOwnProperty(fontKey))
3273 ) {
3274 out("/" + fontKey + " " + fonts[fontKey].objectNumber + " 0 R");
3275 }
3276 }
3277 }
3278 out(">>");
3279 };
3280
3281 var putShadingPatternDict = function() {
3282 if (Object.keys(patterns).length > 0) {
3283 out("/Shading <<");
3284 for (var patternKey in patterns) {
3285 if (
3286 patterns.hasOwnProperty(patternKey) &&
3287 patterns[patternKey] instanceof ShadingPattern &&
3288 patterns[patternKey].objectNumber >= 0
3289 ) {
3290 out(
3291 "/" + patternKey + " " + patterns[patternKey].objectNumber + " 0 R"
3292 );
3293 }
3294 }
3295
3296 events.publish("putShadingPatternDict");
3297 out(">>");
3298 }
3299 };
3300
3301 var putTilingPatternDict = function(objectOid) {
3302 if (Object.keys(patterns).length > 0) {
3303 out("/Pattern <<");
3304 for (var patternKey in patterns) {
3305 if (
3306 patterns.hasOwnProperty(patternKey) &&
3307 patterns[patternKey] instanceof API.TilingPattern &&
3308 patterns[patternKey].objectNumber >= 0 &&
3309 patterns[patternKey].objectNumber < objectOid // prevent cyclic dependencies
3310 ) {
3311 out(
3312 "/" + patternKey + " " + patterns[patternKey].objectNumber + " 0 R"
3313 );
3314 }
3315 }
3316 events.publish("putTilingPatternDict");
3317 out(">>");
3318 }
3319 };
3320
3321 var putGStatesDict = function() {
3322 if (Object.keys(gStates).length > 0) {
3323 var gStateKey;
3324 out("/ExtGState <<");
3325 for (gStateKey in gStates) {
3326 if (
3327 gStates.hasOwnProperty(gStateKey) &&
3328 gStates[gStateKey].objectNumber >= 0
3329 ) {
3330 out("/" + gStateKey + " " + gStates[gStateKey].objectNumber + " 0 R");
3331 }
3332 }
3333
3334 events.publish("putGStateDict");
3335 out(">>");
3336 }
3337 };
3338
3339 var putResourceDictionary = function(objectIds) {
3340 newObjectDeferredBegin(objectIds.resourcesOid, true);
3341 out("<<");
3342 out("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]");
3343 putFontDict();
3344 putShadingPatternDict();
3345 putTilingPatternDict(objectIds.objectOid);
3346 putGStatesDict();
3347 putXobjectDict();
3348 out(">>");
3349 out("endobj");
3350 };
3351
3352 var putResources = function() {
3353 // FormObjects, Patterns etc. might use other FormObjects/Patterns/Images
3354 // which means their resource dictionaries must contain the already resolved
3355 // object ids. For this reason we defer the serialization of the resource
3356 // dicts until all objects have been serialized and have object ids.
3357 //
3358 // In order to prevent cyclic dependencies (which Adobe Reader doesn't like),
3359 // we only put all oids that are smaller than the oid of the object the
3360 // resource dict belongs to. This is correct behavior, since the streams
3361 // may only use other objects that have already been defined and thus appear
3362 // earlier in their respective collection.
3363 // Currently, this only affects tiling patterns, but a (more) correct
3364 // implementation of FormObjects would also define their own resource dicts.
3365 var deferredResourceDictionaryIds = [];
3366
3367 putFonts();
3368 putGStates();
3369 putXObjects();
3370 putPatterns(deferredResourceDictionaryIds);
3371
3372 events.publish("putResources");
3373 deferredResourceDictionaryIds.forEach(putResourceDictionary);
3374 putResourceDictionary({
3375 resourcesOid: resourceDictionaryObjId,
3376 objectOid: Number.MAX_SAFE_INTEGER // output all objects
3377 });
3378 events.publish("postPutResources");
3379 };
3380
3381 var putAdditionalObjects = function() {
3382 events.publish("putAdditionalObjects");
3383 for (var i = 0; i < additionalObjects.length; i++) {
3384 var obj = additionalObjects[i];
3385 newObjectDeferredBegin(obj.objId, true);
3386 out(obj.content);
3387 out("endobj");
3388 }
3389 events.publish("postPutAdditionalObjects");
3390 };
3391
3392 var addFontToFontDictionary = function(font) {
3393 fontmap[font.fontName] = fontmap[font.fontName] || {};
3394 fontmap[font.fontName][font.fontStyle] = font.id;
3395 };
3396
3397 var addFont = function(
3398 postScriptName,
3399 fontName,
3400 fontStyle,
3401 encoding,
3402 isStandardFont
3403 ) {
3404 var font = {
3405 id: "F" + (Object.keys(fonts).length + 1).toString(10),
3406 postScriptName: postScriptName,
3407 fontName: fontName,
3408 fontStyle: fontStyle,
3409 encoding: encoding,
3410 isStandardFont: isStandardFont || false,
3411 metadata: {}
3412 };
3413
3414 events.publish("addFont", {
3415 font: font,
3416 instance: this
3417 });
3418
3419 fonts[font.id] = font;
3420 addFontToFontDictionary(font);
3421 return font.id;
3422 };
3423
3424 var addFonts = function(arrayOfFonts) {
3425 for (var i = 0, l = standardFonts.length; i < l; i++) {
3426 var fontKey = addFont.call(
3427 this,
3428 arrayOfFonts[i][0],
3429 arrayOfFonts[i][1],
3430 arrayOfFonts[i][2],
3431 standardFonts[i][3],
3432 true
3433 );
3434
3435 if (putOnlyUsedFonts === false) {
3436 usedFonts[fontKey] = true;
3437 }
3438 // adding aliases for standard fonts, this time matching the capitalization
3439 var parts = arrayOfFonts[i][0].split("-");
3440 addFontToFontDictionary({
3441 id: fontKey,
3442 fontName: parts[0],
3443 fontStyle: parts[1] || ""
3444 });
3445 }
3446 events.publish("addFonts", {
3447 fonts: fonts,
3448 dictionary: fontmap
3449 });
3450 };
3451
3452 var SAFE = function __safeCall(fn) {
3453 fn.foo = function __safeCallWrapper() {
3454 try {
3455 return fn.apply(this, arguments);
3456 } catch (e) {
3457 var stack = e.stack || "";
3458 if (~stack.indexOf(" at ")) stack = stack.split(" at ")[1];
3459 var m =
3460 "Error in function " +
3461 stack.split("\n")[0].split("<")[0] +
3462 ": " +
3463 e.message;
3464 if (globalObject.console) {
3465 globalObject.console.error(m, e);
3466 if (globalObject.alert) alert(m);
3467 } else {
3468 throw new Error(m);
3469 }
3470 }
3471 };
3472 fn.foo.bar = fn;
3473 return fn.foo;
3474 };
3475
3476 var to8bitStream = function(text, flags) {
3477 /**
3478 * PDF 1.3 spec:
3479 * "For text strings encoded in Unicode, the first two bytes must be 254 followed by
3480 * 255, representing the Unicode byte order marker, U+FEFF. (This sequence conflicts
3481 * with the PDFDocEncoding character sequence thorn ydieresis, which is unlikely
3482 * to be a meaningful beginning of a word or phrase.) The remainder of the
3483 * string consists of Unicode character codes, according to the UTF-16 encoding
3484 * specified in the Unicode standard, version 2.0. Commonly used Unicode values
3485 * are represented as 2 bytes per character, with the high-order byte appearing first
3486 * in the string."
3487 *
3488 * In other words, if there are chars in a string with char code above 255, we
3489 * recode the string to UCS2 BE - string doubles in length and BOM is prepended.
3490 *
3491 * HOWEVER!
3492 * Actual *content* (body) text (as opposed to strings used in document properties etc)
3493 * does NOT expect BOM. There, it is treated as a literal GID (Glyph ID)
3494 *
3495 * Because of Adobe's focus on "you subset your fonts!" you are not supposed to have
3496 * a font that maps directly Unicode (UCS2 / UTF16BE) code to font GID, but you could
3497 * fudge it with "Identity-H" encoding and custom CIDtoGID map that mimics Unicode
3498 * code page. There, however, all characters in the stream are treated as GIDs,
3499 * including BOM, which is the reason we need to skip BOM in content text (i.e. that
3500 * that is tied to a font).
3501 *
3502 * To signal this "special" PDFEscape / to8bitStream handling mode,
3503 * API.text() function sets (unless you overwrite it with manual values
3504 * given to API.text(.., flags) )
3505 * flags.autoencode = true
3506 * flags.noBOM = true
3507 *
3508 * ===================================================================================
3509 * `flags` properties relied upon:
3510 * .sourceEncoding = string with encoding label.
3511 * "Unicode" by default. = encoding of the incoming text.
3512 * pass some non-existing encoding name
3513 * (ex: 'Do not touch my strings! I know what I am doing.')
3514 * to make encoding code skip the encoding step.
3515 * .outputEncoding = Either valid PDF encoding name
3516 * (must be supported by jsPDF font metrics, otherwise no encoding)
3517 * or a JS object, where key = sourceCharCode, value = outputCharCode
3518 * missing keys will be treated as: sourceCharCode === outputCharCode
3519 * .noBOM
3520 * See comment higher above for explanation for why this is important
3521 * .autoencode
3522 * See comment higher above for explanation for why this is important
3523 */
3524
3525 var i,
3526 l,
3527 sourceEncoding,
3528 encodingBlock,
3529 outputEncoding,
3530 newtext,
3531 isUnicode,
3532 ch,
3533 bch;
3534
3535 flags = flags || {};
3536 sourceEncoding = flags.sourceEncoding || "Unicode";
3537 outputEncoding = flags.outputEncoding;
3538
3539 // This 'encoding' section relies on font metrics format
3540 // attached to font objects by, among others,
3541 // "Willow Systems' standard_font_metrics plugin"
3542 // see jspdf.plugin.standard_font_metrics.js for format
3543 // of the font.metadata.encoding Object.
3544 // It should be something like
3545 // .encoding = {'codePages':['WinANSI....'], 'WinANSI...':{code:code, ...}}
3546 // .widths = {0:width, code:width, ..., 'fof':divisor}
3547 // .kerning = {code:{previous_char_code:shift, ..., 'fof':-divisor},...}
3548 if (
3549 (flags.autoencode || outputEncoding) &&
3550 fonts[activeFontKey].metadata &&
3551 fonts[activeFontKey].metadata[sourceEncoding] &&
3552 fonts[activeFontKey].metadata[sourceEncoding].encoding
3553 ) {
3554 encodingBlock = fonts[activeFontKey].metadata[sourceEncoding].encoding;
3555
3556 // each font has default encoding. Some have it clearly defined.
3557 if (!outputEncoding && fonts[activeFontKey].encoding) {
3558 outputEncoding = fonts[activeFontKey].encoding;
3559 }
3560
3561 // Hmmm, the above did not work? Let's try again, in different place.
3562 if (!outputEncoding && encodingBlock.codePages) {
3563 outputEncoding = encodingBlock.codePages[0]; // let's say, first one is the default
3564 }
3565
3566 if (typeof outputEncoding === "string") {
3567 outputEncoding = encodingBlock[outputEncoding];
3568 }
3569 // we want output encoding to be a JS Object, where
3570 // key = sourceEncoding's character code and
3571 // value = outputEncoding's character code.
3572 if (outputEncoding) {
3573 isUnicode = false;
3574 newtext = [];
3575 for (i = 0, l = text.length; i < l; i++) {
3576 ch = outputEncoding[text.charCodeAt(i)];
3577 if (ch) {
3578 newtext.push(String.fromCharCode(ch));
3579 } else {
3580 newtext.push(text[i]);
3581 }
3582
3583 // since we are looping over chars anyway, might as well
3584 // check for residual unicodeness
3585 if (newtext[i].charCodeAt(0) >> 8) {
3586 /* more than 255 */
3587 isUnicode = true;
3588 }
3589 }
3590 text = newtext.join("");
3591 }
3592 }
3593
3594 i = text.length;
3595 // isUnicode may be set to false above. Hence the triple-equal to undefined
3596 while (isUnicode === undefined && i !== 0) {
3597 if (text.charCodeAt(i - 1) >> 8) {
3598 /* more than 255 */
3599 isUnicode = true;
3600 }
3601 i--;
3602 }
3603 if (!isUnicode) {
3604 return text;
3605 }
3606
3607 newtext = flags.noBOM ? [] : [254, 255];
3608 for (i = 0, l = text.length; i < l; i++) {
3609 ch = text.charCodeAt(i);
3610 bch = ch >> 8; // divide by 256
3611 if (bch >> 8) {
3612 /* something left after dividing by 256 second time */
3613 throw new Error(
3614 "Character at position " +
3615 i +
3616 " of string '" +
3617 text +
3618 "' exceeds 16bits. Cannot be encoded into UCS-2 BE"
3619 );
3620 }
3621 newtext.push(bch);
3622 newtext.push(ch - (bch << 8));
3623 }
3624 return String.fromCharCode.apply(undefined, newtext);
3625 };
3626
3627 var pdfEscape = (API.__private__.pdfEscape = API.pdfEscape = function(
3628 text,
3629 flags
3630 ) {
3631 /**
3632 * Replace '/', '(', and ')' with pdf-safe versions
3633 *
3634 * Doing to8bitStream does NOT make this PDF display unicode text. For that
3635 * we also need to reference a unicode font and embed it - royal pain in the rear.
3636 *
3637 * There is still a benefit to to8bitStream - PDF simply cannot handle 16bit chars,
3638 * which JavaScript Strings are happy to provide. So, while we still cannot display
3639 * 2-byte characters property, at least CONDITIONALLY converting (entire string containing)
3640 * 16bit chars to (USC-2-BE) 2-bytes per char + BOM streams we ensure that entire PDF
3641 * is still parseable.
3642 * This will allow immediate support for unicode in document properties strings.
3643 */
3644 return to8bitStream(text, flags)
3645 .replace(/\\/g, "\\\\")
3646 .replace(/\(/g, "\\(")
3647 .replace(/\)/g, "\\)");
3648 });
3649
3650 var beginPage = (API.__private__.beginPage = function(format) {
3651 pages[++page] = [];
3652 pagesContext[page] = {
3653 objId: 0,
3654 contentsObjId: 0,
3655 userUnit: Number(userUnit),
3656 artBox: null,
3657 bleedBox: null,
3658 cropBox: null,
3659 trimBox: null,
3660 mediaBox: {
3661 bottomLeftX: 0,
3662 bottomLeftY: 0,
3663 topRightX: Number(format[0]),
3664 topRightY: Number(format[1])
3665 }
3666 };
3667 _setPage(page);
3668 setOutputDestination(pages[currentPage]);
3669 });
3670
3671 var _addPage = function(parmFormat, parmOrientation) {
3672 var dimensions, width, height;
3673
3674 orientation = parmOrientation || orientation;
3675
3676 if (typeof parmFormat === "string") {
3677 dimensions = getPageFormat(parmFormat.toLowerCase());
3678 if (Array.isArray(dimensions)) {
3679 width = dimensions[0];
3680 height = dimensions[1];
3681 }
3682 }
3683
3684 if (Array.isArray(parmFormat)) {
3685 width = parmFormat[0] * scaleFactor;
3686 height = parmFormat[1] * scaleFactor;
3687 }
3688
3689 if (isNaN(width)) {
3690 width = format[0];
3691 height = format[1];
3692 }
3693
3694 if (width > 14400 || height > 14400) {
3695 console.warn(
3696 "A page in a PDF can not be wider or taller than 14400 userUnit. jsPDF limits the width/height to 14400"
3697 );
3698 width = Math.min(14400, width);
3699 height = Math.min(14400, height);
3700 }
3701
3702 format = [width, height];
3703
3704 switch (orientation.substr(0, 1)) {
3705 case "l":
3706 if (height > width) {
3707 format = [height, width];
3708 }
3709 break;
3710 case "p":
3711 if (width > height) {
3712 format = [height, width];
3713 }
3714 break;
3715 }
3716
3717 beginPage(format);
3718
3719 // Set line width
3720 setLineWidth(lineWidth);
3721 // Set draw color
3722 out(strokeColor);
3723 // resurrecting non-default line caps, joins
3724 if (lineCapID !== 0) {
3725 out(lineCapID + " J");
3726 }
3727 if (lineJoinID !== 0) {
3728 out(lineJoinID + " j");
3729 }
3730 events.publish("addPage", {
3731 pageNumber: page
3732 });
3733 };
3734
3735 var _deletePage = function(n) {
3736 if (n > 0 && n <= page) {
3737 pages.splice(n, 1);
3738 pagesContext.splice(n, 1);
3739 page--;
3740 if (currentPage > page) {
3741 currentPage = page;
3742 }
3743 this.setPage(currentPage);
3744 }
3745 };
3746
3747 var _setPage = function(n) {
3748 if (n > 0 && n <= page) {
3749 currentPage = n;
3750 }
3751 };
3752
3753 var getNumberOfPages = (API.__private__.getNumberOfPages = API.getNumberOfPages = function() {
3754 return pages.length - 1;
3755 });
3756
3757 /**
3758 * Returns a document-specific font key - a label assigned to a
3759 * font name + font type combination at the time the font was added
3760 * to the font inventory.
3761 *
3762 * Font key is used as label for the desired font for a block of text
3763 * to be added to the PDF document stream.
3764 * @private
3765 * @function
3766 * @param fontName {string} can be undefined on "falthy" to indicate "use current"
3767 * @param fontStyle {string} can be undefined on "falthy" to indicate "use current"
3768 * @returns {string} Font key.
3769 * @ignore
3770 */
3771 var getFont = function(fontName, fontStyle, options) {
3772 var key = undefined,
3773 fontNameLowerCase;
3774 options = options || {};
3775
3776 fontName =
3777 fontName !== undefined ? fontName : fonts[activeFontKey].fontName;
3778 fontStyle =
3779 fontStyle !== undefined ? fontStyle : fonts[activeFontKey].fontStyle;
3780 fontNameLowerCase = fontName.toLowerCase();
3781
3782 if (
3783 fontmap[fontNameLowerCase] !== undefined &&
3784 fontmap[fontNameLowerCase][fontStyle] !== undefined
3785 ) {
3786 key = fontmap[fontNameLowerCase][fontStyle];
3787 } else if (
3788 fontmap[fontName] !== undefined &&
3789 fontmap[fontName][fontStyle] !== undefined
3790 ) {
3791 key = fontmap[fontName][fontStyle];
3792 } else {
3793 if (options.disableWarning === false) {
3794 console.warn(
3795 "Unable to look up font label for font '" +
3796 fontName +
3797 "', '" +
3798 fontStyle +
3799 "'. Refer to getFontList() for available fonts."
3800 );
3801 }
3802 }
3803
3804 if (!key && !options.noFallback) {
3805 key = fontmap["times"][fontStyle];
3806 if (key == null) {
3807 key = fontmap["times"]["normal"];
3808 }
3809 }
3810 return key;
3811 };
3812
3813 var putInfo = (API.__private__.putInfo = function() {
3814 var objectId = newObject();
3815 var encryptor = function(data) {
3816 return data;
3817 };
3818 if (encryptionOptions !== null) {
3819 encryptor = encryption.encryptor(objectId, 0);
3820 }
3821 out("<<");
3822 out("/Producer (" + pdfEscape(encryptor("jsPDF " + jsPDF.version)) + ")");
3823 for (var key in documentProperties) {
3824 if (documentProperties.hasOwnProperty(key) && documentProperties[key]) {
3825 out(
3826 "/" +
3827 key.substr(0, 1).toUpperCase() +
3828 key.substr(1) +
3829 " (" +
3830 pdfEscape(encryptor(documentProperties[key])) +
3831 ")"
3832 );
3833 }
3834 }
3835 out("/CreationDate (" + pdfEscape(encryptor(creationDate)) + ")");
3836 out(">>");
3837 out("endobj");
3838 });
3839
3840 var putCatalog = (API.__private__.putCatalog = function(options) {
3841 options = options || {};
3842 var tmpRootDictionaryObjId =
3843 options.rootDictionaryObjId || rootDictionaryObjId;
3844 newObject();
3845 out("<<");
3846 out("/Type /Catalog");
3847 out("/Pages " + tmpRootDictionaryObjId + " 0 R");
3848 // PDF13ref Section 7.2.1
3849 if (!zoomMode) zoomMode = "fullwidth";
3850 switch (zoomMode) {
3851 case "fullwidth":
3852 out("/OpenAction [3 0 R /FitH null]");
3853 break;
3854 case "fullheight":
3855 out("/OpenAction [3 0 R /FitV null]");
3856 break;
3857 case "fullpage":
3858 out("/OpenAction [3 0 R /Fit]");
3859 break;
3860 case "original":
3861 out("/OpenAction [3 0 R /XYZ null null 1]");
3862 break;
3863 default:
3864 var pcn = "" + zoomMode;
3865 if (pcn.substr(pcn.length - 1) === "%")
3866 zoomMode = parseInt(zoomMode) / 100;
3867 if (typeof zoomMode === "number") {
3868 out("/OpenAction [3 0 R /XYZ null null " + f2(zoomMode) + "]");
3869 }
3870 }
3871 if (!layoutMode) layoutMode = "continuous";
3872 switch (layoutMode) {
3873 case "continuous":
3874 out("/PageLayout /OneColumn");
3875 break;
3876 case "single":
3877 out("/PageLayout /SinglePage");
3878 break;
3879 case "two":
3880 case "twoleft":
3881 out("/PageLayout /TwoColumnLeft");
3882 break;
3883 case "tworight":
3884 out("/PageLayout /TwoColumnRight");
3885 break;
3886 }
3887 if (pageMode) {
3888 /**
3889 * A name object specifying how the document should be displayed when opened:
3890 * UseNone : Neither document outline nor thumbnail images visible -- DEFAULT
3891 * UseOutlines : Document outline visible
3892 * UseThumbs : Thumbnail images visible
3893 * FullScreen : Full-screen mode, with no menu bar, window controls, or any other window visible
3894 */
3895 out("/PageMode /" + pageMode);
3896 }
3897 events.publish("putCatalog");
3898 out(">>");
3899 out("endobj");
3900 });
3901
3902 var putTrailer = (API.__private__.putTrailer = function() {
3903 out("trailer");
3904 out("<<");
3905 out("/Size " + (objectNumber + 1));
3906 // Root and Info must be the last and second last objects written respectively
3907 out("/Root " + objectNumber + " 0 R");
3908 out("/Info " + (objectNumber - 1) + " 0 R");
3909 if (encryptionOptions !== null) {
3910 out("/Encrypt " + encryption.oid + " 0 R");
3911 }
3912 out("/ID [ <" + fileId + "> <" + fileId + "> ]");
3913 out(">>");
3914 });
3915
3916 var putHeader = (API.__private__.putHeader = function() {
3917 out("%PDF-" + pdfVersion);
3918 out("%\xBA\xDF\xAC\xE0");
3919 });
3920
3921 var putXRef = (API.__private__.putXRef = function() {
3922 var p = "0000000000";
3923
3924 out("xref");
3925 out("0 " + (objectNumber + 1));
3926 out("0000000000 65535 f ");
3927 for (var i = 1; i <= objectNumber; i++) {
3928 var offset = offsets[i];
3929 if (typeof offset === "function") {
3930 out((p + offsets[i]()).slice(-10) + " 00000 n ");
3931 } else {
3932 if (typeof offsets[i] !== "undefined") {
3933 out((p + offsets[i]).slice(-10) + " 00000 n ");
3934 } else {
3935 out("0000000000 00000 n ");
3936 }
3937 }
3938 }
3939 });
3940
3941 var buildDocument = (API.__private__.buildDocument = function() {
3942 resetDocument();
3943 setOutputDestination(content);
3944
3945 events.publish("buildDocument");
3946
3947 putHeader();
3948 putPages();
3949 putAdditionalObjects();
3950 putResources();
3951 if (encryptionOptions !== null) putEncryptionDict();
3952 putInfo();
3953 putCatalog();
3954
3955 var offsetOfXRef = contentLength;
3956 putXRef();
3957 putTrailer();
3958 out("startxref");
3959 out("" + offsetOfXRef);
3960 out("%%EOF");
3961
3962 setOutputDestination(pages[currentPage]);
3963
3964 return content.join("\n");
3965 });
3966
3967 var getBlob = (API.__private__.getBlob = function(data) {
3968 return new Blob([getArrayBuffer(data)], {
3969 type: "application/pdf"
3970 });
3971 });
3972
3973 /**
3974 * Generates the PDF document.
3975 *
3976 * If `type` argument is undefined, output is raw body of resulting PDF returned as a string.
3977 *
3978 * @param {string} type A string identifying one of the possible output types. Possible values are 'arraybuffer', 'blob', 'bloburi'/'bloburl', 'datauristring'/'dataurlstring', 'datauri'/'dataurl', 'dataurlnewwindow', 'pdfobjectnewwindow', 'pdfjsnewwindow'.
3979 * @param {Object} options An object providing some additional signalling to PDF generator. Possible options are 'filename'.
3980 *
3981 * @function
3982 * @instance
3983 * @returns {jsPDF}
3984 * @memberof jsPDF#
3985 * @name output
3986 */
3987 var output = (API.output = API.__private__.output = SAFE(function output(
3988 type,
3989 options
3990 ) {
3991 options = options || {};
3992
3993 if (typeof options === "string") {
3994 options = {
3995 filename: options
3996 };
3997 } else {
3998 options.filename = options.filename || "generated.pdf";
3999 }
4000
4001 switch (type) {
4002 case undefined:
4003 return buildDocument();
4004 case "save":
4005 API.save(options.filename);
4006 break;
4007 case "arraybuffer":
4008 return getArrayBuffer(buildDocument());
4009 case "blob":
4010 return getBlob(buildDocument());
4011 case "bloburi":
4012 case "bloburl":
4013 // Developer is responsible of calling revokeObjectURL
4014 if (
4015 typeof globalObject.URL !== "undefined" &&
4016 typeof globalObject.URL.createObjectURL === "function"
4017 ) {
4018 return (
4019 (globalObject.URL &&
4020 globalObject.URL.createObjectURL(getBlob(buildDocument()))) ||
4021 void 0
4022 );
4023 } else {
4024 console.warn(
4025 "bloburl is not supported by your system, because URL.createObjectURL is not supported by your browser."
4026 );
4027 }
4028 break;
4029 case "datauristring":
4030 case "dataurlstring":
4031 var dataURI = "";
4032 var pdfDocument = buildDocument();
4033 try {
4034 dataURI = btoa(pdfDocument);
4035 } catch (e) {
4036 dataURI = btoa(unescape(encodeURIComponent(pdfDocument)));
4037 }
4038 return (
4039 "data:application/pdf;filename=" +
4040 options.filename +
4041 ";base64," +
4042 dataURI
4043 );
4044 case "pdfobjectnewwindow":
4045 if (
4046 Object.prototype.toString.call(globalObject) === "[object Window]"
4047 ) {
4048 var pdfObjectUrl =
4049 options.pdfObjectUrl ||
4050 "https://cdnjs.cloudflare.com/ajax/libs/pdfobject/2.1.1/pdfobject.min.js";
4051 var htmlForNewWindow =
4052 "<html>" +
4053 '<style>html, body { padding: 0; margin: 0; } iframe { width: 100%; height: 100%; border: 0;} </style><body><script src="' +
4054 pdfObjectUrl +
4055 '"></script><script >PDFObject.embed("' +
4056 this.output("dataurlstring") +
4057 '", ' +
4058 JSON.stringify(options) +
4059 ");</script></body></html>";
4060 var nW = globalObject.open();
4061
4062 if (nW !== null) {
4063 nW.document.write(htmlForNewWindow);
4064 }
4065 return nW;
4066 } else {
4067 throw new Error(
4068 "The option pdfobjectnewwindow just works in a browser-environment."
4069 );
4070 }
4071 case "pdfjsnewwindow":
4072 if (
4073 Object.prototype.toString.call(globalObject) === "[object Window]"
4074 ) {
4075 var pdfJsUrl = options.pdfJsUrl || "examples/PDF.js/web/viewer.html";
4076 var htmlForPDFjsNewWindow =
4077 "<html>" +
4078 "<style>html, body { padding: 0; margin: 0; } iframe { width: 100%; height: 100%; border: 0;} </style>" +
4079 '<body><iframe id="pdfViewer" src="' +
4080 pdfJsUrl +
4081 "?file=&downloadName=" +
4082 options.filename +
4083 '" width="500px" height="400px" />' +
4084 "</body></html>";
4085 var PDFjsNewWindow = globalObject.open();
4086
4087 if (PDFjsNewWindow !== null) {
4088 PDFjsNewWindow.document.write(htmlForPDFjsNewWindow);
4089 var scope = this;
4090 PDFjsNewWindow.document.documentElement.querySelector(
4091 "#pdfViewer"
4092 ).onload = function() {
4093 PDFjsNewWindow.document.title = options.filename;
4094 PDFjsNewWindow.document.documentElement
4095 .querySelector("#pdfViewer")
4096 .contentWindow.PDFViewerApplication.open(
4097 scope.output("bloburl")
4098 );
4099 };
4100 }
4101 return PDFjsNewWindow;
4102 } else {
4103 throw new Error(
4104 "The option pdfjsnewwindow just works in a browser-environment."
4105 );
4106 }
4107 case "dataurlnewwindow":
4108 if (
4109 Object.prototype.toString.call(globalObject) === "[object Window]"
4110 ) {
4111 var htmlForDataURLNewWindow =
4112 "<html>" +
4113 "<style>html, body { padding: 0; margin: 0; } iframe { width: 100%; height: 100%; border: 0;} </style>" +
4114 "<body>" +
4115 '<iframe src="' +
4116 this.output("datauristring", options) +
4117 '"></iframe>' +
4118 "</body></html>";
4119 var dataURLNewWindow = globalObject.open();
4120 if (dataURLNewWindow !== null) {
4121 dataURLNewWindow.document.write(htmlForDataURLNewWindow);
4122 dataURLNewWindow.document.title = options.filename;
4123 }
4124 if (dataURLNewWindow || typeof safari === "undefined")
4125 return dataURLNewWindow;
4126 } else {
4127 throw new Error(
4128 "The option dataurlnewwindow just works in a browser-environment."
4129 );
4130 }
4131 break;
4132 case "datauri":
4133 case "dataurl":
4134 return (globalObject.document.location.href = this.output(
4135 "datauristring",
4136 options
4137 ));
4138 default:
4139 return null;
4140 }
4141 }));
4142
4143 /**
4144 * Used to see if a supplied hotfix was requested when the pdf instance was created.
4145 * @param {string} hotfixName - The name of the hotfix to check.
4146 * @returns {boolean}
4147 */
4148 var hasHotfix = function(hotfixName) {
4149 return (
4150 Array.isArray(hotfixes) === true && hotfixes.indexOf(hotfixName) > -1
4151 );
4152 };
4153
4154 switch (unit) {
4155 case "pt":
4156 scaleFactor = 1;
4157 break;
4158 case "mm":
4159 scaleFactor = 72 / 25.4;
4160 break;
4161 case "cm":
4162 scaleFactor = 72 / 2.54;
4163 break;
4164 case "in":
4165 scaleFactor = 72;
4166 break;
4167 case "px":
4168 if (hasHotfix("px_scaling") == true) {
4169 scaleFactor = 72 / 96;
4170 } else {
4171 scaleFactor = 96 / 72;
4172 }
4173 break;
4174 case "pc":
4175 scaleFactor = 12;
4176 break;
4177 case "em":
4178 scaleFactor = 12;
4179 break;
4180 case "ex":
4181 scaleFactor = 6;
4182 break;
4183 default:
4184 throw new Error("Invalid unit: " + unit);
4185 }
4186
4187 var encryption = null;
4188 setCreationDate();
4189 setFileId();
4190
4191 var getEncryptor = function(objectId) {
4192 if (encryptionOptions !== null) {
4193 return encryption.encryptor(objectId, 0);
4194 }
4195 return function(data) {
4196 return data;
4197 };
4198 };
4199
4200 //---------------------------------------
4201 // Public API
4202
4203 var getPageInfo = (API.__private__.getPageInfo = API.getPageInfo = function(
4204 pageNumberOneBased
4205 ) {
4206 if (isNaN(pageNumberOneBased) || pageNumberOneBased % 1 !== 0) {
4207 throw new Error("Invalid argument passed to jsPDF.getPageInfo");
4208 }
4209 var objId = pagesContext[pageNumberOneBased].objId;
4210 return {
4211 objId: objId,
4212 pageNumber: pageNumberOneBased,
4213 pageContext: pagesContext[pageNumberOneBased]
4214 };
4215 });
4216
4217 var getPageInfoByObjId = (API.__private__.getPageInfoByObjId = function(
4218 objId
4219 ) {
4220 if (isNaN(objId) || objId % 1 !== 0) {
4221 throw new Error("Invalid argument passed to jsPDF.getPageInfoByObjId");
4222 }
4223 for (var pageNumber in pagesContext) {
4224 if (pagesContext[pageNumber].objId === objId) {
4225 break;
4226 }
4227 }
4228 return getPageInfo(pageNumber);
4229 });
4230
4231 var getCurrentPageInfo = (API.__private__.getCurrentPageInfo = API.getCurrentPageInfo = function() {
4232 return {
4233 objId: pagesContext[currentPage].objId,
4234 pageNumber: currentPage,
4235 pageContext: pagesContext[currentPage]
4236 };
4237 });
4238
4239 /**
4240 * Adds (and transfers the focus to) new page to the PDF document.
4241 * @param format {String/Array} The format of the new page. Can be: <ul><li>a0 - a10</li><li>b0 - b10</li><li>c0 - c10</li><li>dl</li><li>letter</li><li>government-letter</li><li>legal</li><li>junior-legal</li><li>ledger</li><li>tabloid</li><li>credit-card</li></ul><br />
4242 * Default is "a4". If you want to use your own format just pass instead of one of the above predefined formats the size as an number-array, e.g. [595.28, 841.89]
4243 * @param orientation {string} Orientation of the new page. Possible values are "portrait" or "landscape" (or shortcuts "p" (Default), "l").
4244 * @function
4245 * @instance
4246 * @returns {jsPDF}
4247 *
4248 * @memberof jsPDF#
4249 * @name addPage
4250 */
4251 API.addPage = function() {
4252 _addPage.apply(this, arguments);
4253 return this;
4254 };
4255 /**
4256 * Adds (and transfers the focus to) new page to the PDF document.
4257 * @function
4258 * @instance
4259 * @returns {jsPDF}
4260 *
4261 * @memberof jsPDF#
4262 * @name setPage
4263 * @param {number} page Switch the active page to the page number specified (indexed starting at 1).
4264 * @example
4265 * doc = jsPDF()
4266 * doc.addPage()
4267 * doc.addPage()
4268 * doc.text('I am on page 3', 10, 10)
4269 * doc.setPage(1)
4270 * doc.text('I am on page 1', 10, 10)
4271 */
4272 API.setPage = function() {
4273 _setPage.apply(this, arguments);
4274 setOutputDestination.call(this, pages[currentPage]);
4275 return this;
4276 };
4277
4278 /**
4279 * @name insertPage
4280 * @memberof jsPDF#
4281 *
4282 * @function
4283 * @instance
4284 * @param {Object} beforePage
4285 * @returns {jsPDF}
4286 */
4287 API.insertPage = function(beforePage) {
4288 this.addPage();
4289 this.movePage(currentPage, beforePage);
4290 return this;
4291 };
4292
4293 /**
4294 * @name movePage
4295 * @memberof jsPDF#
4296 * @function
4297 * @instance
4298 * @param {number} targetPage
4299 * @param {number} beforePage
4300 * @returns {jsPDF}
4301 */
4302 API.movePage = function(targetPage, beforePage) {
4303 var tmpPages, tmpPagesContext;
4304 if (targetPage > beforePage) {
4305 tmpPages = pages[targetPage];
4306 tmpPagesContext = pagesContext[targetPage];
4307 for (var i = targetPage; i > beforePage; i--) {
4308 pages[i] = pages[i - 1];
4309 pagesContext[i] = pagesContext[i - 1];
4310 }
4311 pages[beforePage] = tmpPages;
4312 pagesContext[beforePage] = tmpPagesContext;
4313 this.setPage(beforePage);
4314 } else if (targetPage < beforePage) {
4315 tmpPages = pages[targetPage];
4316 tmpPagesContext = pagesContext[targetPage];
4317 for (var j = targetPage; j < beforePage; j++) {
4318 pages[j] = pages[j + 1];
4319 pagesContext[j] = pagesContext[j + 1];
4320 }
4321 pages[beforePage] = tmpPages;
4322 pagesContext[beforePage] = tmpPagesContext;
4323 this.setPage(beforePage);
4324 }
4325 return this;
4326 };
4327
4328 /**
4329 * Deletes a page from the PDF.
4330 * @name deletePage
4331 * @memberof jsPDF#
4332 * @function
4333 * @param {number} targetPage
4334 * @instance
4335 * @returns {jsPDF}
4336 */
4337 API.deletePage = function() {
4338 _deletePage.apply(this, arguments);
4339 return this;
4340 };
4341
4342 /**
4343 * Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings.
4344 *
4345 * @function
4346 * @instance
4347 * @param {String|Array} text String or array of strings to be added to the page. Each line is shifted one line down per font, spacing settings declared before this call.
4348 * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page.
4349 * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page.
4350 * @param {Object} [options] - Collection of settings signaling how the text must be encoded.
4351 * @param {string} [options.align=left] - The alignment of the text, possible values: left, center, right, justify.
4352 * @param {string} [options.baseline=alphabetic] - Sets text baseline used when drawing the text, possible values: alphabetic, ideographic, bottom, top, middle, hanging
4353 * @param {number|Matrix} [options.angle=0] - Rotate the text clockwise or counterclockwise. Expects the angle in degree.
4354 * @param {number} [options.rotationDirection=1] - Direction of the rotation. 0 = clockwise, 1 = counterclockwise.
4355 * @param {number} [options.charSpace=0] - The space between each letter.
4356 * @param {number} [options.lineHeightFactor=1.15] - The lineheight of each line.
4357 * @param {Object} [options.flags] - Flags for to8bitStream.
4358 * @param {boolean} [options.flags.noBOM=true] - Don't add BOM to Unicode-text.
4359 * @param {boolean} [options.flags.autoencode=true] - Autoencode the Text.
4360 * @param {number} [options.maxWidth=0] - Split the text by given width, 0 = no split.
4361 * @param {string} [options.renderingMode=fill] - Set how the text should be rendered, possible values: fill, stroke, fillThenStroke, invisible, fillAndAddForClipping, strokeAndAddPathForClipping, fillThenStrokeAndAddToPathForClipping, addToPathForClipping.
4362 * @param {boolean} [options.isInputVisual] - Option for the BidiEngine
4363 * @param {boolean} [options.isOutputVisual] - Option for the BidiEngine
4364 * @param {boolean} [options.isInputRtl] - Option for the BidiEngine
4365 * @param {boolean} [options.isOutputRtl] - Option for the BidiEngine
4366 * @param {boolean} [options.isSymmetricSwapping] - Option for the BidiEngine
4367 * @param {number|Matrix} transform If transform is a number the text will be rotated by this value around the anchor set by x and y.
4368 *
4369 * If it is a Matrix, this matrix gets directly applied to the text, which allows shearing
4370 * effects etc.; the x and y offsets are then applied AFTER the coordinate system has been established by this
4371 * matrix. This means passing a rotation matrix that is equivalent to some rotation angle will in general yield a
4372 * DIFFERENT result. A matrix is only allowed in "advanced" API mode.
4373 * @returns {jsPDF}
4374 * @memberof jsPDF#
4375 * @name text
4376 */
4377 API.__private__.text = API.text = function(text, x, y, options, transform) {
4378 /*
4379 * Inserts something like this into PDF
4380 * BT
4381 * /F1 16 Tf % Font name + size
4382 * 16 TL % How many units down for next line in multiline text
4383 * 0 g % color
4384 * 28.35 813.54 Td % position
4385 * (line one) Tj
4386 * T* (line two) Tj
4387 * T* (line three) Tj
4388 * ET
4389 */
4390 options = options || {};
4391 var scope = options.scope || this;
4392 var payload, da, angle, align, charSpace, maxWidth, flags;
4393
4394 // Pre-August-2012 the order of arguments was function(x, y, text, flags)
4395 // in effort to make all calls have similar signature like
4396 // function(data, coordinates... , miscellaneous)
4397 // this method had its args flipped.
4398 // code below allows backward compatibility with old arg order.
4399 if (
4400 typeof text === "number" &&
4401 typeof x === "number" &&
4402 (typeof y === "string" || Array.isArray(y))
4403 ) {
4404 var tmp = y;
4405 y = x;
4406 x = text;
4407 text = tmp;
4408 }
4409
4410 var transformationMatrix;
4411
4412 if (arguments[3] instanceof Matrix === false) {
4413 flags = arguments[3];
4414 angle = arguments[4];
4415 align = arguments[5];
4416
4417 if (typeof flags !== "object" || flags === null) {
4418 if (typeof angle === "string") {
4419 align = angle;
4420 angle = null;
4421 }
4422 if (typeof flags === "string") {
4423 align = flags;
4424 flags = null;
4425 }
4426 if (typeof flags === "number") {
4427 angle = flags;
4428 flags = null;
4429 }
4430 options = {
4431 flags: flags,
4432 angle: angle,
4433 align: align
4434 };
4435 }
4436 } else {
4437 advancedApiModeTrap(
4438 "The transform parameter of text() with a Matrix value"
4439 );
4440 transformationMatrix = transform;
4441 }
4442
4443 if (isNaN(x) || isNaN(y) || typeof text === "undefined" || text === null) {
4444 throw new Error("Invalid arguments passed to jsPDF.text");
4445 }
4446
4447 if (text.length === 0) {
4448 return scope;
4449 }
4450
4451 var xtra = "";
4452 var isHex = false;
4453 var lineHeight =
4454 typeof options.lineHeightFactor === "number"
4455 ? options.lineHeightFactor
4456 : lineHeightFactor;
4457 var scaleFactor = scope.internal.scaleFactor;
4458
4459 function ESC(s) {
4460 s = s.split("\t").join(Array(options.TabLen || 9).join(" "));
4461 return pdfEscape(s, flags);
4462 }
4463
4464 function transformTextToSpecialArray(text) {
4465 //we don't want to destroy original text array, so cloning it
4466 var sa = text.concat();
4467 var da = [];
4468 var len = sa.length;
4469 var curDa;
4470 //we do array.join('text that must not be PDFescaped")
4471 //thus, pdfEscape each component separately
4472 while (len--) {
4473 curDa = sa.shift();
4474 if (typeof curDa === "string") {
4475 da.push(curDa);
4476 } else {
4477 if (
4478 Array.isArray(text) &&
4479 (curDa.length === 1 ||
4480 (curDa[1] === undefined && curDa[2] === undefined))
4481 ) {
4482 da.push(curDa[0]);
4483 } else {
4484 da.push([curDa[0], curDa[1], curDa[2]]);
4485 }
4486 }
4487 }
4488 return da;
4489 }
4490
4491 function processTextByFunction(text, processingFunction) {
4492 var result;
4493 if (typeof text === "string") {
4494 result = processingFunction(text)[0];
4495 } else if (Array.isArray(text)) {
4496 //we don't want to destroy original text array, so cloning it
4497 var sa = text.concat();
4498 var da = [];
4499 var len = sa.length;
4500 var curDa;
4501 var tmpResult;
4502 //we do array.join('text that must not be PDFescaped")
4503 //thus, pdfEscape each component separately
4504 while (len--) {
4505 curDa = sa.shift();
4506 if (typeof curDa === "string") {
4507 da.push(processingFunction(curDa)[0]);
4508 } else if (Array.isArray(curDa) && typeof curDa[0] === "string") {
4509 tmpResult = processingFunction(curDa[0], curDa[1], curDa[2]);
4510 da.push([tmpResult[0], tmpResult[1], tmpResult[2]]);
4511 }
4512 }
4513 result = da;
4514 }
4515 return result;
4516 }
4517
4518 //Check if text is of type String
4519 var textIsOfTypeString = false;
4520 var tmpTextIsOfTypeString = true;
4521
4522 if (typeof text === "string") {
4523 textIsOfTypeString = true;
4524 } else if (Array.isArray(text)) {
4525 //we don't want to destroy original text array, so cloning it
4526 var sa = text.concat();
4527 da = [];
4528 var len = sa.length;
4529 var curDa;
4530 //we do array.join('text that must not be PDFescaped")
4531 //thus, pdfEscape each component separately
4532 while (len--) {
4533 curDa = sa.shift();
4534 if (
4535 typeof curDa !== "string" ||
4536 (Array.isArray(curDa) && typeof curDa[0] !== "string")
4537 ) {
4538 tmpTextIsOfTypeString = false;
4539 }
4540 }
4541 textIsOfTypeString = tmpTextIsOfTypeString;
4542 }
4543 if (textIsOfTypeString === false) {
4544 throw new Error(
4545 'Type of text must be string or Array. "' +
4546 text +
4547 '" is not recognized.'
4548 );
4549 }
4550
4551 //If there are any newlines in text, we assume
4552 //the user wanted to print multiple lines, so break the
4553 //text up into an array. If the text is already an array,
4554 //we assume the user knows what they are doing.
4555 //Convert text into an array anyway to simplify
4556 //later code.
4557
4558 if (typeof text === "string") {
4559 if (text.match(/[\r?\n]/)) {
4560 text = text.split(/\r\n|\r|\n/g);
4561 } else {
4562 text = [text];
4563 }
4564 }
4565
4566 //baseline
4567 var height = activeFontSize / scope.internal.scaleFactor;
4568 var descent = height * (lineHeightFactor - 1);
4569 switch (options.baseline) {
4570 case "bottom":
4571 y -= descent;
4572 break;
4573 case "top":
4574 y += height - descent;
4575 break;
4576 case "hanging":
4577 y += height - 2 * descent;
4578 break;
4579 case "middle":
4580 y += height / 2 - descent;
4581 break;
4582 }
4583
4584 //multiline
4585 maxWidth = options.maxWidth || 0;
4586
4587 if (maxWidth > 0) {
4588 if (typeof text === "string") {
4589 text = scope.splitTextToSize(text, maxWidth);
4590 } else if (Object.prototype.toString.call(text) === "[object Array]") {
4591 text = text.reduce(function(acc, textLine) {
4592 return acc.concat(scope.splitTextToSize(textLine, maxWidth));
4593 }, []);
4594 }
4595 }
4596
4597 //creating Payload-Object to make text byRef
4598 payload = {
4599 text: text,
4600 x: x,
4601 y: y,
4602 options: options,
4603 mutex: {
4604 pdfEscape: pdfEscape,
4605 activeFontKey: activeFontKey,
4606 fonts: fonts,
4607 activeFontSize: activeFontSize
4608 }
4609 };
4610 events.publish("preProcessText", payload);
4611
4612 text = payload.text;
4613 options = payload.options;
4614
4615 //angle
4616 angle = options.angle;
4617
4618 if (
4619 transformationMatrix instanceof Matrix === false &&
4620 angle &&
4621 typeof angle === "number"
4622 ) {
4623 angle *= Math.PI / 180;
4624
4625 if (options.rotationDirection === 0) {
4626 angle = -angle;
4627 }
4628
4629 if (apiMode === ApiMode.ADVANCED) {
4630 angle = -angle;
4631 }
4632
4633 var c = Math.cos(angle);
4634 var s = Math.sin(angle);
4635 transformationMatrix = new Matrix(c, s, -s, c, 0, 0);
4636 } else if (angle && angle instanceof Matrix) {
4637 transformationMatrix = angle;
4638 }
4639
4640 if (apiMode === ApiMode.ADVANCED && !transformationMatrix) {
4641 transformationMatrix = identityMatrix;
4642 }
4643
4644 //charSpace
4645
4646 charSpace = options.charSpace || activeCharSpace;
4647
4648 if (typeof charSpace !== "undefined") {
4649 xtra += hpf(scale(charSpace)) + " Tc\n";
4650 this.setCharSpace(this.getCharSpace() || 0);
4651 }
4652
4653 //lang
4654
4655 var lang = options.lang;
4656
4657 //renderingMode
4658 var renderingMode = -1;
4659 var parmRenderingMode =
4660 typeof options.renderingMode !== "undefined"
4661 ? options.renderingMode
4662 : options.stroke;
4663 var pageContext = scope.internal.getCurrentPageInfo().pageContext;
4664
4665 switch (parmRenderingMode) {
4666 case 0:
4667 case false:
4668 case "fill":
4669 renderingMode = 0;
4670 break;
4671 case 1:
4672 case true:
4673 case "stroke":
4674 renderingMode = 1;
4675 break;
4676 case 2:
4677 case "fillThenStroke":
4678 renderingMode = 2;
4679 break;
4680 case 3:
4681 case "invisible":
4682 renderingMode = 3;
4683 break;
4684 case 4:
4685 case "fillAndAddForClipping":
4686 renderingMode = 4;
4687 break;
4688 case 5:
4689 case "strokeAndAddPathForClipping":
4690 renderingMode = 5;
4691 break;
4692 case 6:
4693 case "fillThenStrokeAndAddToPathForClipping":
4694 renderingMode = 6;
4695 break;
4696 case 7:
4697 case "addToPathForClipping":
4698 renderingMode = 7;
4699 break;
4700 }
4701
4702 var usedRenderingMode =
4703 typeof pageContext.usedRenderingMode !== "undefined"
4704 ? pageContext.usedRenderingMode
4705 : -1;
4706
4707 //if the coder wrote it explicitly to use a specific
4708 //renderingMode, then use it
4709 if (renderingMode !== -1) {
4710 xtra += renderingMode + " Tr\n";
4711 //otherwise check if we used the rendering Mode already
4712 //if so then set the rendering Mode...
4713 } else if (usedRenderingMode !== -1) {
4714 xtra += "0 Tr\n";
4715 }
4716
4717 if (renderingMode !== -1) {
4718 pageContext.usedRenderingMode = renderingMode;
4719 }
4720
4721 //align
4722 align = options.align || "left";
4723 var leading = activeFontSize * lineHeight;
4724 var pageWidth = scope.internal.pageSize.getWidth();
4725 var activeFont = fonts[activeFontKey];
4726 charSpace = options.charSpace || activeCharSpace;
4727 maxWidth = options.maxWidth || 0;
4728
4729 var lineWidths;
4730 flags = Object.assign({ autoencode: true, noBOM: true }, options.flags);
4731
4732 var wordSpacingPerLine = [];
4733
4734 if (Object.prototype.toString.call(text) === "[object Array]") {
4735 da = transformTextToSpecialArray(text);
4736 var newY;
4737 if (align !== "left") {
4738 lineWidths = da.map(function(v) {
4739 return (
4740 (scope.getStringUnitWidth(v, {
4741 font: activeFont,
4742 charSpace: charSpace,
4743 fontSize: activeFontSize,
4744 doKerning: false
4745 }) *
4746 activeFontSize) /
4747 scaleFactor
4748 );
4749 });
4750 }
4751 //The first line uses the "main" Td setting,
4752 //and the subsequent lines are offset by the
4753 //previous line's x coordinate.
4754 var prevWidth = 0;
4755 var newX;
4756 if (align === "right") {
4757 //The passed in x coordinate defines the
4758 //rightmost point of the text.
4759 x -= lineWidths[0];
4760 text = [];
4761 len = da.length;
4762 for (var i = 0; i < len; i++) {
4763 if (i === 0) {
4764 newX = getHorizontalCoordinate(x);
4765 newY = getVerticalCoordinate(y);
4766 } else {
4767 newX = scale(prevWidth - lineWidths[i]);
4768 newY = -leading;
4769 }
4770 text.push([da[i], newX, newY]);
4771 prevWidth = lineWidths[i];
4772 }
4773 } else if (align === "center") {
4774 //The passed in x coordinate defines
4775 //the center point.
4776 x -= lineWidths[0] / 2;
4777 text = [];
4778 len = da.length;
4779 for (var j = 0; j < len; j++) {
4780 if (j === 0) {
4781 newX = getHorizontalCoordinate(x);
4782 newY = getVerticalCoordinate(y);
4783 } else {
4784 newX = scale((prevWidth - lineWidths[j]) / 2);
4785 newY = -leading;
4786 }
4787 text.push([da[j], newX, newY]);
4788 prevWidth = lineWidths[j];
4789 }
4790 } else if (align === "left") {
4791 text = [];
4792 len = da.length;
4793 for (var h = 0; h < len; h++) {
4794 text.push(da[h]);
4795 }
4796 } else if (align === "justify") {
4797 text = [];
4798 len = da.length;
4799 maxWidth = maxWidth !== 0 ? maxWidth : pageWidth;
4800
4801 for (var l = 0; l < len; l++) {
4802 newY = l === 0 ? getVerticalCoordinate(y) : -leading;
4803 newX = l === 0 ? getHorizontalCoordinate(x) : 0;
4804 if (l < len - 1) {
4805 wordSpacingPerLine.push(
4806 hpf(
4807 scale(
4808 (maxWidth - lineWidths[l]) / (da[l].split(" ").length - 1)
4809 )
4810 )
4811 );
4812 }
4813 text.push([da[l], newX, newY]);
4814 }
4815 } else {
4816 throw new Error(
4817 'Unrecognized alignment option, use "left", "center", "right" or "justify".'
4818 );
4819 }
4820 }
4821
4822 //R2L
4823 var doReversing = typeof options.R2L === "boolean" ? options.R2L : R2L;
4824 if (doReversing === true) {
4825 text = processTextByFunction(text, function(text, posX, posY) {
4826 return [
4827 text
4828 .split("")
4829 .reverse()
4830 .join(""),
4831 posX,
4832 posY
4833 ];
4834 });
4835 }
4836
4837 //creating Payload-Object to make text byRef
4838 payload = {
4839 text: text,
4840 x: x,
4841 y: y,
4842 options: options,
4843 mutex: {
4844 pdfEscape: pdfEscape,
4845 activeFontKey: activeFontKey,
4846 fonts: fonts,
4847 activeFontSize: activeFontSize
4848 }
4849 };
4850 events.publish("postProcessText", payload);
4851
4852 text = payload.text;
4853 isHex = payload.mutex.isHex || false;
4854
4855 //Escaping
4856 var activeFontEncoding = fonts[activeFontKey].encoding;
4857
4858 if (
4859 activeFontEncoding === "WinAnsiEncoding" ||
4860 activeFontEncoding === "StandardEncoding"
4861 ) {
4862 text = processTextByFunction(text, function(text, posX, posY) {
4863 return [ESC(text), posX, posY];
4864 });
4865 }
4866
4867 da = transformTextToSpecialArray(text);
4868
4869 text = [];
4870 var STRING = 0;
4871 var ARRAY = 1;
4872 var variant = Array.isArray(da[0]) ? ARRAY : STRING;
4873 var posX;
4874 var posY;
4875 var content;
4876 var wordSpacing = "";
4877
4878 var generatePosition = function(
4879 parmPosX,
4880 parmPosY,
4881 parmTransformationMatrix
4882 ) {
4883 var position = "";
4884 if (parmTransformationMatrix instanceof Matrix) {
4885 // It is kind of more intuitive to apply a plain rotation around the text anchor set by x and y
4886 // but when the user supplies an arbitrary transformation matrix, the x and y offsets should be applied
4887 // in the coordinate system established by this matrix
4888 if (typeof options.angle === "number") {
4889 parmTransformationMatrix = matrixMult(
4890 parmTransformationMatrix,
4891 new Matrix(1, 0, 0, 1, parmPosX, parmPosY)
4892 );
4893 } else {
4894 parmTransformationMatrix = matrixMult(
4895 new Matrix(1, 0, 0, 1, parmPosX, parmPosY),
4896 parmTransformationMatrix
4897 );
4898 }
4899
4900 if (apiMode === ApiMode.ADVANCED) {
4901 parmTransformationMatrix = matrixMult(
4902 new Matrix(1, 0, 0, -1, 0, 0),
4903 parmTransformationMatrix
4904 );
4905 }
4906
4907 position = parmTransformationMatrix.join(" ") + " Tm\n";
4908 } else {
4909 position = hpf(parmPosX) + " " + hpf(parmPosY) + " Td\n";
4910 }
4911 return position;
4912 };
4913
4914 for (var lineIndex = 0; lineIndex < da.length; lineIndex++) {
4915 wordSpacing = "";
4916
4917 switch (variant) {
4918 case ARRAY:
4919 content =
4920 (isHex ? "<" : "(") + da[lineIndex][0] + (isHex ? ">" : ")");
4921 posX = parseFloat(da[lineIndex][1]);
4922 posY = parseFloat(da[lineIndex][2]);
4923 break;
4924 case STRING:
4925 content = (isHex ? "<" : "(") + da[lineIndex] + (isHex ? ">" : ")");
4926 posX = getHorizontalCoordinate(x);
4927 posY = getVerticalCoordinate(y);
4928 break;
4929 }
4930
4931 if (
4932 typeof wordSpacingPerLine !== "undefined" &&
4933 typeof wordSpacingPerLine[lineIndex] !== "undefined"
4934 ) {
4935 wordSpacing = wordSpacingPerLine[lineIndex] + " Tw\n";
4936 }
4937
4938 if (lineIndex === 0) {
4939 text.push(
4940 wordSpacing +
4941 generatePosition(posX, posY, transformationMatrix) +
4942 content
4943 );
4944 } else if (variant === STRING) {
4945 text.push(wordSpacing + content);
4946 } else if (variant === ARRAY) {
4947 text.push(
4948 wordSpacing +
4949 generatePosition(posX, posY, transformationMatrix) +
4950 content
4951 );
4952 }
4953 }
4954
4955 text = variant === STRING ? text.join(" Tj\nT* ") : text.join(" Tj\n");
4956 text += " Tj\n";
4957
4958 var result = "BT\n/";
4959 result += activeFontKey + " " + activeFontSize + " Tf\n"; // font face, style, size
4960 result += hpf(activeFontSize * lineHeight) + " TL\n"; // line spacing
4961 result += textColor + "\n";
4962 result += xtra;
4963 result += text;
4964 result += "ET";
4965
4966 out(result);
4967 usedFonts[activeFontKey] = true;
4968 return scope;
4969 };
4970
4971 // PDF supports these path painting and clip path operators:
4972 //
4973 // S - stroke
4974 // s - close/stroke
4975 // f (F) - fill non-zero
4976 // f* - fill evenodd
4977 // B - fill stroke nonzero
4978 // B* - fill stroke evenodd
4979 // b - close fill stroke nonzero
4980 // b* - close fill stroke evenodd
4981 // n - nothing (consume path)
4982 // W - clip nonzero
4983 // W* - clip evenodd
4984 //
4985 // In order to keep the API small, we omit the close-and-fill/stroke operators and provide a separate close()
4986 // method.
4987 /**
4988 *
4989 * @name clip
4990 * @function
4991 * @instance
4992 * @param {string} rule Only possible value is 'evenodd'
4993 * @returns {jsPDF}
4994 * @memberof jsPDF#
4995 * @description All .clip() after calling drawing ops with a style argument of null.
4996 */
4997 var clip = (API.__private__.clip = API.clip = function(rule) {
4998 // Call .clip() after calling drawing ops with a style argument of null
4999 // W is the PDF clipping op
5000 if ("evenodd" === rule) {
5001 out("W*");
5002 } else {
5003 out("W");
5004 }
5005 return this;
5006 });
5007
5008 /**
5009 * @name clipEvenOdd
5010 * @function
5011 * @instance
5012 * @returns {jsPDF}
5013 * @memberof jsPDF#
5014 * @description Modify the current clip path by intersecting it with the current path using the even-odd rule. Note
5015 * that this will NOT consume the current path. In order to only use this path for clipping call
5016 * {@link API.discardPath} afterwards.
5017 */
5018 API.clipEvenOdd = function() {
5019 return clip("evenodd");
5020 };
5021
5022 /**
5023 * Consumes the current path without any effect. Mainly used in combination with {@link clip} or
5024 * {@link clipEvenOdd}. The PDF "n" operator.
5025 * @name discardPath
5026 * @function
5027 * @instance
5028 * @returns {jsPDF}
5029 * @memberof jsPDF#
5030 */
5031 API.__private__.discardPath = API.discardPath = function() {
5032 out("n");
5033 return this;
5034 };
5035
5036 var isValidStyle = (API.__private__.isValidStyle = function(style) {
5037 var validStyleVariants = [
5038 undefined,
5039 null,
5040 "S",
5041 "D",
5042 "F",
5043 "DF",
5044 "FD",
5045 "f",
5046 "f*",
5047 "B",
5048 "B*",
5049 "n"
5050 ];
5051 var result = false;
5052 if (validStyleVariants.indexOf(style) !== -1) {
5053 result = true;
5054 }
5055 return result;
5056 });
5057
5058 API.__private__.setDefaultPathOperation = API.setDefaultPathOperation = function(
5059 operator
5060 ) {
5061 if (isValidStyle(operator)) {
5062 defaultPathOperation = operator;
5063 }
5064 return this;
5065 };
5066
5067 var getStyle = (API.__private__.getStyle = API.getStyle = function(style) {
5068 // see path-painting operators in PDF spec
5069 var op = defaultPathOperation; // stroke
5070
5071 switch (style) {
5072 case "D":
5073 case "S":
5074 op = "S"; // stroke
5075 break;
5076 case "F":
5077 op = "f"; // fill
5078 break;
5079 case "FD":
5080 case "DF":
5081 op = "B";
5082 break;
5083 case "f":
5084 case "f*":
5085 case "B":
5086 case "B*":
5087 /*
5088 Allow direct use of these PDF path-painting operators:
5089 - f fill using nonzero winding number rule
5090 - f* fill using even-odd rule
5091 - B fill then stroke with fill using non-zero winding number rule
5092 - B* fill then stroke with fill using even-odd rule
5093 */
5094 op = style;
5095 break;
5096 }
5097 return op;
5098 });
5099
5100 /**
5101 * Close the current path. The PDF "h" operator.
5102 * @name close
5103 * @function
5104 * @instance
5105 * @returns {jsPDF}
5106 * @memberof jsPDF#
5107 */
5108 var close = (API.close = function() {
5109 out("h");
5110 return this;
5111 });
5112
5113 /**
5114 * Stroke the path. The PDF "S" operator.
5115 * @name stroke
5116 * @function
5117 * @instance
5118 * @returns {jsPDF}
5119 * @memberof jsPDF#
5120 */
5121 API.stroke = function() {
5122 out("S");
5123 return this;
5124 };
5125
5126 /**
5127 * Fill the current path using the nonzero winding number rule. If a pattern is provided, the path will be filled
5128 * with this pattern, otherwise with the current fill color. Equivalent to the PDF "f" operator.
5129 * @name fill
5130 * @function
5131 * @instance
5132 * @param {PatternData=} pattern If provided the path will be filled with this pattern
5133 * @returns {jsPDF}
5134 * @memberof jsPDF#
5135 */
5136 API.fill = function(pattern) {
5137 fillWithOptionalPattern("f", pattern);
5138 return this;
5139 };
5140
5141 /**
5142 * Fill the current path using the even-odd rule. The PDF f* operator.
5143 * @see API.fill
5144 * @name fillEvenOdd
5145 * @function
5146 * @instance
5147 * @param {PatternData=} pattern If provided the path will be filled with this pattern
5148 * @returns {jsPDF}
5149 * @memberof jsPDF#
5150 */
5151 API.fillEvenOdd = function(pattern) {
5152 fillWithOptionalPattern("f*", pattern);
5153 return this;
5154 };
5155
5156 /**
5157 * Fill using the nonzero winding number rule and then stroke the current Path. The PDF "B" operator.
5158 * @see API.fill
5159 * @name fillStroke
5160 * @function
5161 * @instance
5162 * @param {PatternData=} pattern If provided the path will be stroked with this pattern
5163 * @returns {jsPDF}
5164 * @memberof jsPDF#
5165 */
5166 API.fillStroke = function(pattern) {
5167 fillWithOptionalPattern("B", pattern);
5168 return this;
5169 };
5170
5171 /**
5172 * Fill using the even-odd rule and then stroke the current Path. The PDF "B" operator.
5173 * @see API.fill
5174 * @name fillStrokeEvenOdd
5175 * @function
5176 * @instance
5177 * @param {PatternData=} pattern If provided the path will be fill-stroked with this pattern
5178 * @returns {jsPDF}
5179 * @memberof jsPDF#
5180 */
5181 API.fillStrokeEvenOdd = function(pattern) {
5182 fillWithOptionalPattern("B*", pattern);
5183 return this;
5184 };
5185
5186 var fillWithOptionalPattern = function(style, pattern) {
5187 if (typeof pattern === "object") {
5188 fillWithPattern(pattern, style);
5189 } else {
5190 out(style);
5191 }
5192 };
5193
5194 var putStyle = function(style) {
5195 if (
5196 style === null ||
5197 (apiMode === ApiMode.ADVANCED && style === undefined)
5198 ) {
5199 return;
5200 }
5201
5202 style = getStyle(style);
5203
5204 // stroking / filling / both the path
5205 out(style);
5206 };
5207
5208 function cloneTilingPattern(patternKey, boundingBox, xStep, yStep, matrix) {
5209 var clone = new TilingPattern(
5210 boundingBox || this.boundingBox,
5211 xStep || this.xStep,
5212 yStep || this.yStep,
5213 this.gState,
5214 matrix || this.matrix
5215 );
5216 clone.stream = this.stream;
5217 var key = patternKey + "$$" + this.cloneIndex++ + "$$";
5218 addPattern(key, clone);
5219 return clone;
5220 }
5221
5222 var fillWithPattern = function(patternData, style) {
5223 var patternId = patternMap[patternData.key];
5224 var pattern = patterns[patternId];
5225
5226 if (pattern instanceof ShadingPattern) {
5227 out("q");
5228
5229 out(clipRuleFromStyle(style));
5230
5231 if (pattern.gState) {
5232 API.setGState(pattern.gState);
5233 }
5234 out(patternData.matrix.toString() + " cm");
5235 out("/" + patternId + " sh");
5236 out("Q");
5237 } else if (pattern instanceof TilingPattern) {
5238 // pdf draws patterns starting at the bottom left corner and they are not affected by the global transformation,
5239 // so we must flip them
5240 var matrix = new Matrix(1, 0, 0, -1, 0, getPageHeight());
5241
5242 if (patternData.matrix) {
5243 matrix = matrix.multiply(patternData.matrix || identityMatrix);
5244 // we cannot apply a matrix to the pattern on use so we must abuse the pattern matrix and create new instances
5245 // for each use
5246 patternId = cloneTilingPattern.call(
5247 pattern,
5248 patternData.key,
5249 patternData.boundingBox,
5250 patternData.xStep,
5251 patternData.yStep,
5252 matrix
5253 ).id;
5254 }
5255
5256 out("q");
5257 out("/Pattern cs");
5258 out("/" + patternId + " scn");
5259
5260 if (pattern.gState) {
5261 API.setGState(pattern.gState);
5262 }
5263
5264 out(style);
5265 out("Q");
5266 }
5267 };
5268
5269 var clipRuleFromStyle = function(style) {
5270 switch (style) {
5271 case "f":
5272 case "F":
5273 return "W n";
5274 case "f*":
5275 return "W* n";
5276 case "B":
5277 return "W S";
5278 case "B*":
5279 return "W* S";
5280
5281 // these two are for compatibility reasons (in the past, calling any primitive method with a shading pattern
5282 // and "n"/"S" as style would still fill/fill and stroke the path)
5283 case "S":
5284 return "W S";
5285 case "n":
5286 return "W n";
5287 }
5288 };
5289
5290 /**
5291 * Begin a new subpath by moving the current point to coordinates (x, y). The PDF "m" operator.
5292 * @param {number} x
5293 * @param {number} y
5294 * @name moveTo
5295 * @function
5296 * @instance
5297 * @memberof jsPDF#
5298 * @returns {jsPDF}
5299 */
5300 var moveTo = (API.moveTo = function(x, y) {
5301 out(hpf(scale(x)) + " " + hpf(transformScaleY(y)) + " m");
5302 return this;
5303 });
5304
5305 /**
5306 * Append a straight line segment from the current point to the point (x, y). The PDF "l" operator.
5307 * @param {number} x
5308 * @param {number} y
5309 * @memberof jsPDF#
5310 * @name lineTo
5311 * @function
5312 * @instance
5313 * @memberof jsPDF#
5314 * @returns {jsPDF}
5315 */
5316 var lineTo = (API.lineTo = function(x, y) {
5317 out(hpf(scale(x)) + " " + hpf(transformScaleY(y)) + " l");
5318 return this;
5319 });
5320
5321 /**
5322 * Append a cubic Bézier curve to the current path. The curve shall extend from the current point to the point
5323 * (x3, y3), using (x1, y1) and (x2, y2) as Bézier control points. The new current point shall be (x3, x3).
5324 * @param {number} x1
5325 * @param {number} y1
5326 * @param {number} x2
5327 * @param {number} y2
5328 * @param {number} x3
5329 * @param {number} y3
5330 * @memberof jsPDF#
5331 * @name curveTo
5332 * @function
5333 * @instance
5334 * @memberof jsPDF#
5335 * @returns {jsPDF}
5336 */
5337 var curveTo = (API.curveTo = function(x1, y1, x2, y2, x3, y3) {
5338 out(
5339 [
5340 hpf(scale(x1)),
5341 hpf(transformScaleY(y1)),
5342 hpf(scale(x2)),
5343 hpf(transformScaleY(y2)),
5344 hpf(scale(x3)),
5345 hpf(transformScaleY(y3)),
5346 "c"
5347 ].join(" ")
5348 );
5349 return this;
5350 });
5351
5352 /**
5353 * Draw a line on the current page.
5354 *
5355 * @name line
5356 * @function
5357 * @instance
5358 * @param {number} x1
5359 * @param {number} y1
5360 * @param {number} x2
5361 * @param {number} y2
5362 * @param {string} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument. default: 'S'
5363 * @returns {jsPDF}
5364 * @memberof jsPDF#
5365 */
5366 API.__private__.line = API.line = function(x1, y1, x2, y2, style) {
5367 if (
5368 isNaN(x1) ||
5369 isNaN(y1) ||
5370 isNaN(x2) ||
5371 isNaN(y2) ||
5372 !isValidStyle(style)
5373 ) {
5374 throw new Error("Invalid arguments passed to jsPDF.line");
5375 }
5376 if (apiMode === ApiMode.COMPAT) {
5377 return this.lines([[x2 - x1, y2 - y1]], x1, y1, [1, 1], style || "S");
5378 } else {
5379 return this.lines([[x2 - x1, y2 - y1]], x1, y1, [1, 1]).stroke();
5380 }
5381 };
5382
5383 /**
5384 * @typedef {Object} PatternData
5385 * {Matrix|undefined} matrix
5386 * {Number|undefined} xStep
5387 * {Number|undefined} yStep
5388 * {Array.<Number>|undefined} boundingBox
5389 */
5390
5391 /**
5392 * Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates.
5393 * All data points in `lines` are relative to last line origin.
5394 * `x`, `y` become x1,y1 for first line / curve in the set.
5395 * For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point.
5396 * For bezier curves you need to specify [x2,y2,x3,y3,x4,y4] - vectors to control points 1, 2, ending point. All vectors are against the start of the curve - x1,y1.
5397 *
5398 * @example .lines([[2,2],[-2,2],[1,1,2,2,3,3],[2,1]], 212,110, [1,1], 'F', false) // line, line, bezier curve, line
5399 * @param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves).
5400 * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
5401 * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
5402 * @param {number} scale (Defaults to [1.0,1.0]) x,y Scaling factor for all vectors. Elements can be any floating number Sub-one makes drawing smaller. Over-one grows the drawing. Negative flips the direction.
5403 * @param {string=} style A string specifying the painting style or null. Valid styles include:
5404 * 'S' [default] - stroke,
5405 * 'F' - fill,
5406 * and 'DF' (or 'FD') - fill then stroke.
5407 * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
5408 * method calls. The last drawing method call used to define the shape should not have a null style argument.
5409 *
5410 * In "advanced" API mode this parameter is deprecated.
5411 * @param {Boolean=} closed If true, the path is closed with a straight line from the end of the last curve to the starting point.
5412 * @function
5413 * @instance
5414 * @returns {jsPDF}
5415 * @memberof jsPDF#
5416 * @name lines
5417 */
5418 API.__private__.lines = API.lines = function(
5419 lines,
5420 x,
5421 y,
5422 scale,
5423 style,
5424 closed
5425 ) {
5426 var scalex, scaley, i, l, leg, x2, y2, x3, y3, x4, y4, tmp;
5427
5428 // Pre-August-2012 the order of arguments was function(x, y, lines, scale, style)
5429 // in effort to make all calls have similar signature like
5430 // function(content, coordinateX, coordinateY , miscellaneous)
5431 // this method had its args flipped.
5432 // code below allows backward compatibility with old arg order.
5433 if (typeof lines === "number") {
5434 tmp = y;
5435 y = x;
5436 x = lines;
5437 lines = tmp;
5438 }
5439
5440 scale = scale || [1, 1];
5441 closed = closed || false;
5442
5443 if (
5444 isNaN(x) ||
5445 isNaN(y) ||
5446 !Array.isArray(lines) ||
5447 !Array.isArray(scale) ||
5448 !isValidStyle(style) ||
5449 typeof closed !== "boolean"
5450 ) {
5451 throw new Error("Invalid arguments passed to jsPDF.lines");
5452 }
5453
5454 // starting point
5455 moveTo(x, y);
5456
5457 scalex = scale[0];
5458 scaley = scale[1];
5459 l = lines.length;
5460 //, x2, y2 // bezier only. In page default measurement "units", *after* scaling
5461 //, x3, y3 // bezier only. In page default measurement "units", *after* scaling
5462 // ending point for all, lines and bezier. . In page default measurement "units", *after* scaling
5463 x4 = x; // last / ending point = starting point for first item.
5464 y4 = y; // last / ending point = starting point for first item.
5465
5466 for (i = 0; i < l; i++) {
5467 leg = lines[i];
5468 if (leg.length === 2) {
5469 // simple line
5470 x4 = leg[0] * scalex + x4; // here last x4 was prior ending point
5471 y4 = leg[1] * scaley + y4; // here last y4 was prior ending point
5472 lineTo(x4, y4);
5473 } else {
5474 // bezier curve
5475 x2 = leg[0] * scalex + x4; // here last x4 is prior ending point
5476 y2 = leg[1] * scaley + y4; // here last y4 is prior ending point
5477 x3 = leg[2] * scalex + x4; // here last x4 is prior ending point
5478 y3 = leg[3] * scaley + y4; // here last y4 is prior ending point
5479 x4 = leg[4] * scalex + x4; // here last x4 was prior ending point
5480 y4 = leg[5] * scaley + y4; // here last y4 was prior ending point
5481 curveTo(x2, y2, x3, y3, x4, y4);
5482 }
5483 }
5484
5485 if (closed) {
5486 close();
5487 }
5488
5489 putStyle(style);
5490 return this;
5491 };
5492
5493 /**
5494 * Similar to {@link API.lines} but all coordinates are interpreted as absolute coordinates instead of relative.
5495 * @param {Array<Object>} lines An array of {op: operator, c: coordinates} object, where op is one of "m" (move to), "l" (line to)
5496 * "c" (cubic bezier curve) and "h" (close (sub)path)). c is an array of coordinates. "m" and "l" expect two, "c"
5497 * six and "h" an empty array (or undefined).
5498 * @function
5499 * @returns {jsPDF}
5500 * @memberof jsPDF#
5501 * @name path
5502 */
5503 API.path = function(lines) {
5504 for (var i = 0; i < lines.length; i++) {
5505 var leg = lines[i];
5506 var coords = leg.c;
5507 switch (leg.op) {
5508 case "m":
5509 moveTo(coords[0], coords[1]);
5510 break;
5511 case "l":
5512 lineTo(coords[0], coords[1]);
5513 break;
5514 case "c":
5515 curveTo.apply(this, coords);
5516 break;
5517 case "h":
5518 close();
5519 break;
5520 }
5521 }
5522
5523 return this;
5524 };
5525
5526 /**
5527 * Adds a rectangle to PDF.
5528 *
5529 * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
5530 * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
5531 * @param {number} w Width (in units declared at inception of PDF document)
5532 * @param {number} h Height (in units declared at inception of PDF document)
5533 * @param {string=} style A string specifying the painting style or null. Valid styles include:
5534 * 'S' [default] - stroke,
5535 * 'F' - fill,
5536 * and 'DF' (or 'FD') - fill then stroke.
5537 * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
5538 * method calls. The last drawing method call used to define the shape should not have a null style argument.
5539 *
5540 * In "advanced" API mode this parameter is deprecated.
5541 * @function
5542 * @instance
5543 * @returns {jsPDF}
5544 * @memberof jsPDF#
5545 * @name rect
5546 */
5547 API.__private__.rect = API.rect = function(x, y, w, h, style) {
5548 if (isNaN(x) || isNaN(y) || isNaN(w) || isNaN(h) || !isValidStyle(style)) {
5549 throw new Error("Invalid arguments passed to jsPDF.rect");
5550 }
5551 if (apiMode === ApiMode.COMPAT) {
5552 h = -h;
5553 }
5554
5555 out(
5556 [
5557 hpf(scale(x)),
5558 hpf(transformScaleY(y)),
5559 hpf(scale(w)),
5560 hpf(scale(h)),
5561 "re"
5562 ].join(" ")
5563 );
5564
5565 putStyle(style);
5566 return this;
5567 };
5568
5569 /**
5570 * Adds a triangle to PDF.
5571 *
5572 * @param {number} x1 Coordinate (in units declared at inception of PDF document) against left edge of the page
5573 * @param {number} y1 Coordinate (in units declared at inception of PDF document) against upper edge of the page
5574 * @param {number} x2 Coordinate (in units declared at inception of PDF document) against left edge of the page
5575 * @param {number} y2 Coordinate (in units declared at inception of PDF document) against upper edge of the page
5576 * @param {number} x3 Coordinate (in units declared at inception of PDF document) against left edge of the page
5577 * @param {number} y3 Coordinate (in units declared at inception of PDF document) against upper edge of the page
5578 * @param {string=} style A string specifying the painting style or null. Valid styles include:
5579 * 'S' [default] - stroke,
5580 * 'F' - fill,
5581 * and 'DF' (or 'FD') - fill then stroke.
5582 * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
5583 * method calls. The last drawing method call used to define the shape should not have a null style argument.
5584 *
5585 * In "advanced" API mode this parameter is deprecated.
5586 * @function
5587 * @instance
5588 * @returns {jsPDF}
5589 * @memberof jsPDF#
5590 * @name triangle
5591 */
5592 API.__private__.triangle = API.triangle = function(
5593 x1,
5594 y1,
5595 x2,
5596 y2,
5597 x3,
5598 y3,
5599 style
5600 ) {
5601 if (
5602 isNaN(x1) ||
5603 isNaN(y1) ||
5604 isNaN(x2) ||
5605 isNaN(y2) ||
5606 isNaN(x3) ||
5607 isNaN(y3) ||
5608 !isValidStyle(style)
5609 ) {
5610 throw new Error("Invalid arguments passed to jsPDF.triangle");
5611 }
5612 this.lines(
5613 [
5614 [x2 - x1, y2 - y1], // vector to point 2
5615 [x3 - x2, y3 - y2], // vector to point 3
5616 [x1 - x3, y1 - y3] // closing vector back to point 1
5617 ],
5618 x1,
5619 y1, // start of path
5620 [1, 1],
5621 style,
5622 true
5623 );
5624 return this;
5625 };
5626
5627 /**
5628 * Adds a rectangle with rounded corners to PDF.
5629 *
5630 * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
5631 * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
5632 * @param {number} w Width (in units declared at inception of PDF document)
5633 * @param {number} h Height (in units declared at inception of PDF document)
5634 * @param {number} rx Radius along x axis (in units declared at inception of PDF document)
5635 * @param {number} ry Radius along y axis (in units declared at inception of PDF document)
5636 * @param {string=} style A string specifying the painting style or null. Valid styles include:
5637 * 'S' [default] - stroke,
5638 * 'F' - fill,
5639 * and 'DF' (or 'FD') - fill then stroke.
5640 * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
5641 * method calls. The last drawing method call used to define the shape should not have a null style argument.
5642 *
5643 * In "advanced" API mode this parameter is deprecated.
5644 * @function
5645 * @instance
5646 * @returns {jsPDF}
5647 * @memberof jsPDF#
5648 * @name roundedRect
5649 */
5650 API.__private__.roundedRect = API.roundedRect = function(
5651 x,
5652 y,
5653 w,
5654 h,
5655 rx,
5656 ry,
5657 style
5658 ) {
5659 if (
5660 isNaN(x) ||
5661 isNaN(y) ||
5662 isNaN(w) ||
5663 isNaN(h) ||
5664 isNaN(rx) ||
5665 isNaN(ry) ||
5666 !isValidStyle(style)
5667 ) {
5668 throw new Error("Invalid arguments passed to jsPDF.roundedRect");
5669 }
5670 var MyArc = (4 / 3) * (Math.SQRT2 - 1);
5671
5672 rx = Math.min(rx, w * 0.5);
5673 ry = Math.min(ry, h * 0.5);
5674
5675 this.lines(
5676 [
5677 [w - 2 * rx, 0],
5678 [rx * MyArc, 0, rx, ry - ry * MyArc, rx, ry],
5679 [0, h - 2 * ry],
5680 [0, ry * MyArc, -(rx * MyArc), ry, -rx, ry],
5681 [-w + 2 * rx, 0],
5682 [-(rx * MyArc), 0, -rx, -(ry * MyArc), -rx, -ry],
5683 [0, -h + 2 * ry],
5684 [0, -(ry * MyArc), rx * MyArc, -ry, rx, -ry]
5685 ],
5686 x + rx,
5687 y, // start of path
5688 [1, 1],
5689 style,
5690 true
5691 );
5692 return this;
5693 };
5694
5695 /**
5696 * Adds an ellipse to PDF.
5697 *
5698 * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
5699 * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
5700 * @param {number} rx Radius along x axis (in units declared at inception of PDF document)
5701 * @param {number} ry Radius along y axis (in units declared at inception of PDF document)
5702 * @param {string=} style A string specifying the painting style or null. Valid styles include:
5703 * 'S' [default] - stroke,
5704 * 'F' - fill,
5705 * and 'DF' (or 'FD') - fill then stroke.
5706 * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
5707 * method calls. The last drawing method call used to define the shape should not have a null style argument.
5708 *
5709 * In "advanced" API mode this parameter is deprecated.
5710 * @function
5711 * @instance
5712 * @returns {jsPDF}
5713 * @memberof jsPDF#
5714 * @name ellipse
5715 */
5716 API.__private__.ellipse = API.ellipse = function(x, y, rx, ry, style) {
5717 if (
5718 isNaN(x) ||
5719 isNaN(y) ||
5720 isNaN(rx) ||
5721 isNaN(ry) ||
5722 !isValidStyle(style)
5723 ) {
5724 throw new Error("Invalid arguments passed to jsPDF.ellipse");
5725 }
5726 var lx = (4 / 3) * (Math.SQRT2 - 1) * rx,
5727 ly = (4 / 3) * (Math.SQRT2 - 1) * ry;
5728
5729 moveTo(x + rx, y);
5730 curveTo(x + rx, y - ly, x + lx, y - ry, x, y - ry);
5731 curveTo(x - lx, y - ry, x - rx, y - ly, x - rx, y);
5732 curveTo(x - rx, y + ly, x - lx, y + ry, x, y + ry);
5733 curveTo(x + lx, y + ry, x + rx, y + ly, x + rx, y);
5734
5735 putStyle(style);
5736 return this;
5737 };
5738
5739 /**
5740 * Adds an circle to PDF.
5741 *
5742 * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
5743 * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
5744 * @param {number} r Radius (in units declared at inception of PDF document)
5745 * @param {string=} style A string specifying the painting style or null. Valid styles include:
5746 * 'S' [default] - stroke,
5747 * 'F' - fill,
5748 * and 'DF' (or 'FD') - fill then stroke.
5749 * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
5750 * method calls. The last drawing method call used to define the shape should not have a null style argument.
5751 *
5752 * In "advanced" API mode this parameter is deprecated.
5753 * @function
5754 * @instance
5755 * @returns {jsPDF}
5756 * @memberof jsPDF#
5757 * @name circle
5758 */
5759 API.__private__.circle = API.circle = function(x, y, r, style) {
5760 if (isNaN(x) || isNaN(y) || isNaN(r) || !isValidStyle(style)) {
5761 throw new Error("Invalid arguments passed to jsPDF.circle");
5762 }
5763 return this.ellipse(x, y, r, r, style);
5764 };
5765
5766 /**
5767 * Sets text font face, variant for upcoming text elements.
5768 * See output of jsPDF.getFontList() for possible font names, styles.
5769 *
5770 * @param {string} fontName Font name or family. Example: "times".
5771 * @param {string} fontStyle Font style or variant. Example: "italic".
5772 * @param {number | string} fontWeight Weight of the Font. Example: "normal" | 400
5773 * @function
5774 * @instance
5775 * @returns {jsPDF}
5776 * @memberof jsPDF#
5777 * @name setFont
5778 */
5779 API.setFont = function(fontName, fontStyle, fontWeight) {
5780 if (fontWeight) {
5781 fontStyle = combineFontStyleAndFontWeight(fontStyle, fontWeight);
5782 }
5783 activeFontKey = getFont(fontName, fontStyle, {
5784 disableWarning: false
5785 });
5786 return this;
5787 };
5788
5789 /**
5790 * Gets text font face, variant for upcoming text elements.
5791 *
5792 * @function
5793 * @instance
5794 * @returns {Object}
5795 * @memberof jsPDF#
5796 * @name getFont
5797 */
5798 var getFontEntry = (API.__private__.getFont = API.getFont = function() {
5799 return fonts[getFont.apply(API, arguments)];
5800 });
5801
5802 /**
5803 * Returns an object - a tree of fontName to fontStyle relationships available to
5804 * active PDF document.
5805 *
5806 * @public
5807 * @function
5808 * @instance
5809 * @returns {Object} Like {'times':['normal', 'italic', ... ], 'arial':['normal', 'bold', ... ], ... }
5810 * @memberof jsPDF#
5811 * @name getFontList
5812 */
5813 API.__private__.getFontList = API.getFontList = function() {
5814 var list = {},
5815 fontName,
5816 fontStyle;
5817
5818 for (fontName in fontmap) {
5819 if (fontmap.hasOwnProperty(fontName)) {
5820 list[fontName] = [];
5821 for (fontStyle in fontmap[fontName]) {
5822 if (fontmap[fontName].hasOwnProperty(fontStyle)) {
5823 list[fontName].push(fontStyle);
5824 }
5825 }
5826 }
5827 }
5828 return list;
5829 };
5830
5831 /**
5832 * Add a custom font to the current instance.
5833 *
5834 * @param {string} postScriptName PDF specification full name for the font.
5835 * @param {string} id PDF-document-instance-specific label assinged to the font.
5836 * @param {string} fontStyle Style of the Font.
5837 * @param {number | string} fontWeight Weight of the Font.
5838 * @param {Object} encoding Encoding_name-to-Font_metrics_object mapping.
5839 * @function
5840 * @instance
5841 * @memberof jsPDF#
5842 * @name addFont
5843 * @returns {string} fontId
5844 */
5845 API.addFont = function(
5846 postScriptName,
5847 fontName,
5848 fontStyle,
5849 fontWeight,
5850 encoding
5851 ) {
5852 var encodingOptions = [
5853 "StandardEncoding",
5854 "MacRomanEncoding",
5855 "Identity-H",
5856 "WinAnsiEncoding"
5857 ];
5858 if (arguments[3] && encodingOptions.indexOf(arguments[3]) !== -1) {
5859 //IE 11 fix
5860 encoding = arguments[3];
5861 } else if (arguments[3] && encodingOptions.indexOf(arguments[3]) == -1) {
5862 fontStyle = combineFontStyleAndFontWeight(fontStyle, fontWeight);
5863 }
5864 encoding = encoding || "Identity-H";
5865 return addFont.call(this, postScriptName, fontName, fontStyle, encoding);
5866 };
5867
5868 var lineWidth = options.lineWidth || 0.200025; // 2mm
5869 /**
5870 * Sets line width for upcoming lines.
5871 *
5872 * @param {number} width Line width (in units declared at inception of PDF document).
5873 * @function
5874 * @instance
5875 * @returns {jsPDF}
5876 * @memberof jsPDF#
5877 * @name setLineWidth
5878 */
5879 var setLineWidth = (API.__private__.setLineWidth = API.setLineWidth = function(
5880 width
5881 ) {
5882 out(hpf(scale(width)) + " w");
5883 return this;
5884 });
5885
5886 /**
5887 * Sets the dash pattern for upcoming lines.
5888 *
5889 * To reset the settings simply call the method without any parameters.
5890 * @param {Array<number>} dashArray An array containing 0-2 numbers. The first number sets the length of the
5891 * dashes, the second number the length of the gaps. If the second number is missing, the gaps are considered
5892 * to be as long as the dashes. An empty array means solid, unbroken lines.
5893 * @param {number} dashPhase The phase lines start with.
5894 * @function
5895 * @instance
5896 * @returns {jsPDF}
5897 * @memberof jsPDF#
5898 * @name setLineDashPattern
5899 */
5900 API.__private__.setLineDash = jsPDF.API.setLineDash = jsPDF.API.setLineDashPattern = function(
5901 dashArray,
5902 dashPhase
5903 ) {
5904 dashArray = dashArray || [];
5905 dashPhase = dashPhase || 0;
5906
5907 if (isNaN(dashPhase) || !Array.isArray(dashArray)) {
5908 throw new Error("Invalid arguments passed to jsPDF.setLineDash");
5909 }
5910
5911 dashArray = dashArray
5912 .map(function(x) {
5913 return hpf(scale(x));
5914 })
5915 .join(" ");
5916 dashPhase = hpf(scale(dashPhase));
5917
5918 out("[" + dashArray + "] " + dashPhase + " d");
5919 return this;
5920 };
5921
5922 var lineHeightFactor;
5923
5924 var getLineHeight = (API.__private__.getLineHeight = API.getLineHeight = function() {
5925 return activeFontSize * lineHeightFactor;
5926 });
5927
5928 API.__private__.getLineHeight = API.getLineHeight = function() {
5929 return activeFontSize * lineHeightFactor;
5930 };
5931
5932 /**
5933 * Sets the LineHeightFactor of proportion.
5934 *
5935 * @param {number} value LineHeightFactor value. Default: 1.15.
5936 * @function
5937 * @instance
5938 * @returns {jsPDF}
5939 * @memberof jsPDF#
5940 * @name setLineHeightFactor
5941 */
5942 var setLineHeightFactor = (API.__private__.setLineHeightFactor = API.setLineHeightFactor = function(
5943 value
5944 ) {
5945 value = value || 1.15;
5946 if (typeof value === "number") {
5947 lineHeightFactor = value;
5948 }
5949 return this;
5950 });
5951
5952 /**
5953 * Gets the LineHeightFactor, default: 1.15.
5954 *
5955 * @function
5956 * @instance
5957 * @returns {number} lineHeightFactor
5958 * @memberof jsPDF#
5959 * @name getLineHeightFactor
5960 */
5961 var getLineHeightFactor = (API.__private__.getLineHeightFactor = API.getLineHeightFactor = function() {
5962 return lineHeightFactor;
5963 });
5964
5965 setLineHeightFactor(options.lineHeight);
5966
5967 var getHorizontalCoordinate = (API.__private__.getHorizontalCoordinate = function(
5968 value
5969 ) {
5970 return scale(value);
5971 });
5972
5973 var getVerticalCoordinate = (API.__private__.getVerticalCoordinate = function(
5974 value
5975 ) {
5976 if (apiMode === ApiMode.ADVANCED) {
5977 return value;
5978 } else {
5979 var pageHeight =
5980 pagesContext[currentPage].mediaBox.topRightY -
5981 pagesContext[currentPage].mediaBox.bottomLeftY;
5982 return pageHeight - scale(value);
5983 }
5984 });
5985
5986 var getHorizontalCoordinateString = (API.__private__.getHorizontalCoordinateString = API.getHorizontalCoordinateString = function(
5987 value
5988 ) {
5989 return hpf(getHorizontalCoordinate(value));
5990 });
5991
5992 var getVerticalCoordinateString = (API.__private__.getVerticalCoordinateString = API.getVerticalCoordinateString = function(
5993 value
5994 ) {
5995 return hpf(getVerticalCoordinate(value));
5996 });
5997
5998 var strokeColor = options.strokeColor || "0 G";
5999
6000 /**
6001 * Gets the stroke color for upcoming elements.
6002 *
6003 * @function
6004 * @instance
6005 * @returns {string} colorAsHex
6006 * @memberof jsPDF#
6007 * @name getDrawColor
6008 */
6009 API.__private__.getStrokeColor = API.getDrawColor = function() {
6010 return decodeColorString(strokeColor);
6011 };
6012
6013 /**
6014 * Sets the stroke color for upcoming elements.
6015 *
6016 * Depending on the number of arguments given, Gray, RGB, or CMYK
6017 * color space is implied.
6018 *
6019 * When only ch1 is given, "Gray" color space is implied and it
6020 * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
6021 * if values are communicated as String types, or in range from 0 (black)
6022 * to 255 (white) if communicated as Number type.
6023 * The RGB-like 0-255 range is provided for backward compatibility.
6024 *
6025 * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
6026 * value must be in the range from 0.00 (minimum intensity) to to 1.00
6027 * (max intensity) if values are communicated as String types, or
6028 * from 0 (min intensity) to to 255 (max intensity) if values are communicated
6029 * as Number types.
6030 * The RGB-like 0-255 range is provided for backward compatibility.
6031 *
6032 * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
6033 * value must be a in the range from 0.00 (0% concentration) to to
6034 * 1.00 (100% concentration)
6035 *
6036 * Because JavaScript treats fixed point numbers badly (rounds to
6037 * floating point nearest to binary representation) it is highly advised to
6038 * communicate the fractional numbers as String types, not JavaScript Number type.
6039 *
6040 * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF'.
6041 * @param {Number} ch2 Color channel value.
6042 * @param {Number} ch3 Color channel value.
6043 * @param {Number} ch4 Color channel value.
6044 *
6045 * @function
6046 * @instance
6047 * @returns {jsPDF}
6048 * @memberof jsPDF#
6049 * @name setDrawColor
6050 */
6051 API.__private__.setStrokeColor = API.setDrawColor = function(
6052 ch1,
6053 ch2,
6054 ch3,
6055 ch4
6056 ) {
6057 var options = {
6058 ch1: ch1,
6059 ch2: ch2,
6060 ch3: ch3,
6061 ch4: ch4,
6062 pdfColorType: "draw",
6063 precision: 2
6064 };
6065
6066 strokeColor = encodeColorString(options);
6067 out(strokeColor);
6068 return this;
6069 };
6070
6071 var fillColor = options.fillColor || "0 g";
6072
6073 /**
6074 * Gets the fill color for upcoming elements.
6075 *
6076 * @function
6077 * @instance
6078 * @returns {string} colorAsHex
6079 * @memberof jsPDF#
6080 * @name getFillColor
6081 */
6082 API.__private__.getFillColor = API.getFillColor = function() {
6083 return decodeColorString(fillColor);
6084 };
6085
6086 /**
6087 * Sets the fill color for upcoming elements.
6088 *
6089 * Depending on the number of arguments given, Gray, RGB, or CMYK
6090 * color space is implied.
6091 *
6092 * When only ch1 is given, "Gray" color space is implied and it
6093 * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
6094 * if values are communicated as String types, or in range from 0 (black)
6095 * to 255 (white) if communicated as Number type.
6096 * The RGB-like 0-255 range is provided for backward compatibility.
6097 *
6098 * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
6099 * value must be in the range from 0.00 (minimum intensity) to to 1.00
6100 * (max intensity) if values are communicated as String types, or
6101 * from 0 (min intensity) to to 255 (max intensity) if values are communicated
6102 * as Number types.
6103 * The RGB-like 0-255 range is provided for backward compatibility.
6104 *
6105 * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
6106 * value must be a in the range from 0.00 (0% concentration) to to
6107 * 1.00 (100% concentration)
6108 *
6109 * Because JavaScript treats fixed point numbers badly (rounds to
6110 * floating point nearest to binary representation) it is highly advised to
6111 * communicate the fractional numbers as String types, not JavaScript Number type.
6112 *
6113 * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF'.
6114 * @param {Number} ch2 Color channel value.
6115 * @param {Number} ch3 Color channel value.
6116 * @param {Number} ch4 Color channel value.
6117 *
6118 * @function
6119 * @instance
6120 * @returns {jsPDF}
6121 * @memberof jsPDF#
6122 * @name setFillColor
6123 */
6124 API.__private__.setFillColor = API.setFillColor = function(
6125 ch1,
6126 ch2,
6127 ch3,
6128 ch4
6129 ) {
6130 var options = {
6131 ch1: ch1,
6132 ch2: ch2,
6133 ch3: ch3,
6134 ch4: ch4,
6135 pdfColorType: "fill",
6136 precision: 2
6137 };
6138
6139 fillColor = encodeColorString(options);
6140 out(fillColor);
6141 return this;
6142 };
6143
6144 var textColor = options.textColor || "0 g";
6145 /**
6146 * Gets the text color for upcoming elements.
6147 *
6148 * @function
6149 * @instance
6150 * @returns {string} colorAsHex
6151 * @memberof jsPDF#
6152 * @name getTextColor
6153 */
6154 var getTextColor = (API.__private__.getTextColor = API.getTextColor = function() {
6155 return decodeColorString(textColor);
6156 });
6157 /**
6158 * Sets the text color for upcoming elements.
6159 *
6160 * Depending on the number of arguments given, Gray, RGB, or CMYK
6161 * color space is implied.
6162 *
6163 * When only ch1 is given, "Gray" color space is implied and it
6164 * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
6165 * if values are communicated as String types, or in range from 0 (black)
6166 * to 255 (white) if communicated as Number type.
6167 * The RGB-like 0-255 range is provided for backward compatibility.
6168 *
6169 * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
6170 * value must be in the range from 0.00 (minimum intensity) to to 1.00
6171 * (max intensity) if values are communicated as String types, or
6172 * from 0 (min intensity) to to 255 (max intensity) if values are communicated
6173 * as Number types.
6174 * The RGB-like 0-255 range is provided for backward compatibility.
6175 *
6176 * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
6177 * value must be a in the range from 0.00 (0% concentration) to to
6178 * 1.00 (100% concentration)
6179 *
6180 * Because JavaScript treats fixed point numbers badly (rounds to
6181 * floating point nearest to binary representation) it is highly advised to
6182 * communicate the fractional numbers as String types, not JavaScript Number type.
6183 *
6184 * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF'.
6185 * @param {Number} ch2 Color channel value.
6186 * @param {Number} ch3 Color channel value.
6187 * @param {Number} ch4 Color channel value.
6188 *
6189 * @function
6190 * @instance
6191 * @returns {jsPDF}
6192 * @memberof jsPDF#
6193 * @name setTextColor
6194 */
6195 API.__private__.setTextColor = API.setTextColor = function(
6196 ch1,
6197 ch2,
6198 ch3,
6199 ch4
6200 ) {
6201 var options = {
6202 ch1: ch1,
6203 ch2: ch2,
6204 ch3: ch3,
6205 ch4: ch4,
6206 pdfColorType: "text",
6207 precision: 3
6208 };
6209 textColor = encodeColorString(options);
6210
6211 return this;
6212 };
6213
6214 var activeCharSpace = options.charSpace;
6215
6216 /**
6217 * Get global value of CharSpace.
6218 *
6219 * @function
6220 * @instance
6221 * @returns {number} charSpace
6222 * @memberof jsPDF#
6223 * @name getCharSpace
6224 */
6225 var getCharSpace = (API.__private__.getCharSpace = API.getCharSpace = function() {
6226 return parseFloat(activeCharSpace || 0);
6227 });
6228
6229 /**
6230 * Set global value of CharSpace.
6231 *
6232 * @param {number} charSpace
6233 * @function
6234 * @instance
6235 * @returns {jsPDF} jsPDF-instance
6236 * @memberof jsPDF#
6237 * @name setCharSpace
6238 */
6239 API.__private__.setCharSpace = API.setCharSpace = function(charSpace) {
6240 if (isNaN(charSpace)) {
6241 throw new Error("Invalid argument passed to jsPDF.setCharSpace");
6242 }
6243 activeCharSpace = charSpace;
6244 return this;
6245 };
6246
6247 var lineCapID = 0;
6248 /**
6249 * Is an Object providing a mapping from human-readable to
6250 * integer flag values designating the varieties of line cap
6251 * and join styles.
6252 *
6253 * @memberof jsPDF#
6254 * @name CapJoinStyles
6255 */
6256 API.CapJoinStyles = {
6257 0: 0,
6258 butt: 0,
6259 but: 0,
6260 miter: 0,
6261 1: 1,
6262 round: 1,
6263 rounded: 1,
6264 circle: 1,
6265 2: 2,
6266 projecting: 2,
6267 project: 2,
6268 square: 2,
6269 bevel: 2
6270 };
6271
6272 /**
6273 * Sets the line cap styles.
6274 * See {jsPDF.CapJoinStyles} for variants.
6275 *
6276 * @param {String|Number} style A string or number identifying the type of line cap.
6277 * @function
6278 * @instance
6279 * @returns {jsPDF}
6280 * @memberof jsPDF#
6281 * @name setLineCap
6282 */
6283 API.__private__.setLineCap = API.setLineCap = function(style) {
6284 var id = API.CapJoinStyles[style];
6285 if (id === undefined) {
6286 throw new Error(
6287 "Line cap style of '" +
6288 style +
6289 "' is not recognized. See or extend .CapJoinStyles property for valid styles"
6290 );
6291 }
6292 lineCapID = id;
6293 out(id + " J");
6294
6295 return this;
6296 };
6297
6298 var lineJoinID = 0;
6299 /**
6300 * Sets the line join styles.
6301 * See {jsPDF.CapJoinStyles} for variants.
6302 *
6303 * @param {String|Number} style A string or number identifying the type of line join.
6304 * @function
6305 * @instance
6306 * @returns {jsPDF}
6307 * @memberof jsPDF#
6308 * @name setLineJoin
6309 */
6310 API.__private__.setLineJoin = API.setLineJoin = function(style) {
6311 var id = API.CapJoinStyles[style];
6312 if (id === undefined) {
6313 throw new Error(
6314 "Line join style of '" +
6315 style +
6316 "' is not recognized. See or extend .CapJoinStyles property for valid styles"
6317 );
6318 }
6319 lineJoinID = id;
6320 out(id + " j");
6321
6322 return this;
6323 };
6324 /**
6325 * Sets the miterLimit property, which effects the maximum miter length.
6326 *
6327 * @param {number} length The length of the miter
6328 * @function
6329 * @instance
6330 * @returns {jsPDF}
6331 * @memberof jsPDF#
6332 * @name setLineMiterLimit
6333 */
6334 API.__private__.setLineMiterLimit = API.__private__.setMiterLimit = API.setLineMiterLimit = API.setMiterLimit = function(
6335 length
6336 ) {
6337 length = length || 0;
6338 if (isNaN(length)) {
6339 throw new Error("Invalid argument passed to jsPDF.setLineMiterLimit");
6340 }
6341 out(hpf(scale(length)) + " M");
6342
6343 return this;
6344 };
6345
6346 /**
6347 * An object representing a pdf graphics state.
6348 * @class GState
6349 */
6350
6351 /**
6352 *
6353 * @param parameters A parameter object that contains all properties this graphics state wants to set.
6354 * Supported are: opacity, stroke-opacity
6355 * @constructor
6356 */
6357 API.GState = GState;
6358
6359 /**
6360 * Sets a either previously added {@link GState} (via {@link addGState}) or a new {@link GState}.
6361 * @param {String|GState} gState If type is string, a previously added GState is used, if type is GState
6362 * it will be added before use.
6363 * @function
6364 * @returns {jsPDF}
6365 * @memberof jsPDF#
6366 * @name setGState
6367 */
6368 API.setGState = function(gState) {
6369 if (typeof gState === "string") {
6370 gState = gStates[gStatesMap[gState]];
6371 } else {
6372 gState = addGState(null, gState);
6373 }
6374
6375 if (!gState.equals(activeGState)) {
6376 out("/" + gState.id + " gs");
6377 activeGState = gState;
6378 }
6379 };
6380
6381 /**
6382 * Adds a new Graphics State. Duplicates are automatically eliminated.
6383 * @param {String} key Might also be null, if no later reference to this gState is needed
6384 * @param {Object} gState The gState object
6385 */
6386 var addGState = function(key, gState) {
6387 // only add it if it is not already present (the keys provided by the user must be unique!)
6388 if (key && gStatesMap[key]) return;
6389 var duplicate = false;
6390 for (var s in gStates) {
6391 if (gStates.hasOwnProperty(s)) {
6392 if (gStates[s].equals(gState)) {
6393 duplicate = true;
6394 break;
6395 }
6396 }
6397 }
6398
6399 if (duplicate) {
6400 gState = gStates[s];
6401 } else {
6402 var gStateKey = "GS" + (Object.keys(gStates).length + 1).toString(10);
6403 gStates[gStateKey] = gState;
6404 gState.id = gStateKey;
6405 }
6406
6407 // several user keys may point to the same GState object
6408 key && (gStatesMap[key] = gState.id);
6409
6410 events.publish("addGState", gState);
6411
6412 return gState;
6413 };
6414
6415 /**
6416 * Adds a new {@link GState} for later use. See {@link setGState}.
6417 * @param {String} key
6418 * @param {GState} gState
6419 * @function
6420 * @instance
6421 * @returns {jsPDF}
6422 *
6423 * @memberof jsPDF#
6424 * @name addGState
6425 */
6426 API.addGState = function(key, gState) {
6427 addGState(key, gState);
6428 return this;
6429 };
6430
6431 /**
6432 * Saves the current graphics state ("pushes it on the stack"). It can be restored by {@link restoreGraphicsState}
6433 * later. Here, the general pdf graphics state is meant, also including the current transformation matrix,
6434 * fill and stroke colors etc.
6435 * @function
6436 * @returns {jsPDF}
6437 * @memberof jsPDF#
6438 * @name saveGraphicsState
6439 */
6440 API.saveGraphicsState = function() {
6441 out("q");
6442 // as we cannot set font key and size independently we must keep track of both
6443 fontStateStack.push({
6444 key: activeFontKey,
6445 size: activeFontSize,
6446 color: textColor
6447 });
6448 return this;
6449 };
6450
6451 /**
6452 * Restores a previously saved graphics state saved by {@link saveGraphicsState} ("pops the stack").
6453 * @function
6454 * @returns {jsPDF}
6455 * @memberof jsPDF#
6456 * @name restoreGraphicsState
6457 */
6458 API.restoreGraphicsState = function() {
6459 out("Q");
6460
6461 // restore previous font state
6462 var fontState = fontStateStack.pop();
6463 activeFontKey = fontState.key;
6464 activeFontSize = fontState.size;
6465 textColor = fontState.color;
6466
6467 activeGState = null;
6468
6469 return this;
6470 };
6471
6472 /**
6473 * Appends this matrix to the left of all previously applied matrices.
6474 *
6475 * @param {Matrix} matrix
6476 * @function
6477 * @returns {jsPDF}
6478 * @memberof jsPDF#
6479 * @name setCurrentTransformationMatrix
6480 */
6481 API.setCurrentTransformationMatrix = function(matrix) {
6482 out(matrix.toString() + " cm");
6483 return this;
6484 };
6485
6486 /**
6487 * Inserts a debug comment into the generated pdf.
6488 * @function
6489 * @instance
6490 * @param {String} text
6491 * @returns {jsPDF}
6492 * @memberof jsPDF#
6493 * @name comment
6494 */
6495 API.comment = function(text) {
6496 out("#" + text);
6497 return this;
6498 };
6499
6500 /**
6501 * Point
6502 */
6503 var Point = function(x, y) {
6504 var _x = x || 0;
6505 Object.defineProperty(this, "x", {
6506 enumerable: true,
6507 get: function() {
6508 return _x;
6509 },
6510 set: function(value) {
6511 if (!isNaN(value)) {
6512 _x = parseFloat(value);
6513 }
6514 }
6515 });
6516
6517 var _y = y || 0;
6518 Object.defineProperty(this, "y", {
6519 enumerable: true,
6520 get: function() {
6521 return _y;
6522 },
6523 set: function(value) {
6524 if (!isNaN(value)) {
6525 _y = parseFloat(value);
6526 }
6527 }
6528 });
6529
6530 var _type = "pt";
6531 Object.defineProperty(this, "type", {
6532 enumerable: true,
6533 get: function() {
6534 return _type;
6535 },
6536 set: function(value) {
6537 _type = value.toString();
6538 }
6539 });
6540 return this;
6541 };
6542
6543 /**
6544 * Rectangle
6545 */
6546 var Rectangle = function(x, y, w, h) {
6547 Point.call(this, x, y);
6548 this.type = "rect";
6549
6550 var _w = w || 0;
6551 Object.defineProperty(this, "w", {
6552 enumerable: true,
6553 get: function() {
6554 return _w;
6555 },
6556 set: function(value) {
6557 if (!isNaN(value)) {
6558 _w = parseFloat(value);
6559 }
6560 }
6561 });
6562
6563 var _h = h || 0;
6564 Object.defineProperty(this, "h", {
6565 enumerable: true,
6566 get: function() {
6567 return _h;
6568 },
6569 set: function(value) {
6570 if (!isNaN(value)) {
6571 _h = parseFloat(value);
6572 }
6573 }
6574 });
6575
6576 return this;
6577 };
6578
6579 /**
6580 * FormObject/RenderTarget
6581 */
6582
6583 var RenderTarget = function() {
6584 this.page = page;
6585 this.currentPage = currentPage;
6586 this.pages = pages.slice(0);
6587 this.pagesContext = pagesContext.slice(0);
6588 this.x = pageX;
6589 this.y = pageY;
6590 this.matrix = pageMatrix;
6591 this.width = getPageWidth(currentPage);
6592 this.height = getPageHeight(currentPage);
6593 this.outputDestination = outputDestination;
6594
6595 this.id = ""; // set by endFormObject()
6596 this.objectNumber = -1; // will be set by putXObject()
6597 };
6598
6599 RenderTarget.prototype.restore = function() {
6600 page = this.page;
6601 currentPage = this.currentPage;
6602 pagesContext = this.pagesContext;
6603 pages = this.pages;
6604 pageX = this.x;
6605 pageY = this.y;
6606 pageMatrix = this.matrix;
6607 setPageWidth(currentPage, this.width);
6608 setPageHeight(currentPage, this.height);
6609 outputDestination = this.outputDestination;
6610 };
6611
6612 var beginNewRenderTarget = function(x, y, width, height, matrix) {
6613 // save current state
6614 renderTargetStack.push(new RenderTarget());
6615
6616 // clear pages
6617 page = currentPage = 0;
6618 pages = [];
6619 pageX = x;
6620 pageY = y;
6621
6622 pageMatrix = matrix;
6623
6624 beginPage([width, height]);
6625 };
6626
6627 var endFormObject = function(key) {
6628 // only add it if it is not already present (the keys provided by the user must be unique!)
6629 if (renderTargetMap[key]) return;
6630
6631 // save the created xObject
6632 var newXObject = new RenderTarget();
6633
6634 var xObjectId = "Xo" + (Object.keys(renderTargets).length + 1).toString(10);
6635 newXObject.id = xObjectId;
6636
6637 renderTargetMap[key] = xObjectId;
6638 renderTargets[xObjectId] = newXObject;
6639
6640 events.publish("addFormObject", newXObject);
6641
6642 // restore state from stack
6643 renderTargetStack.pop().restore();
6644 };
6645
6646 /**
6647 * Starts a new pdf form object, which means that all consequent draw calls target a new independent object
6648 * until {@link endFormObject} is called. The created object can be referenced and drawn later using
6649 * {@link doFormObject}. Nested form objects are possible.
6650 * x, y, width, height set the bounding box that is used to clip the content.
6651 *
6652 * @param {number} x
6653 * @param {number} y
6654 * @param {number} width
6655 * @param {number} height
6656 * @param {Matrix} matrix The matrix that will be applied to convert the form objects coordinate system to
6657 * the parent's.
6658 * @function
6659 * @returns {jsPDF}
6660 * @memberof jsPDF#
6661 * @name beginFormObject
6662 */
6663 API.beginFormObject = function(x, y, width, height, matrix) {
6664 // The user can set the output target to a new form object. Nested form objects are possible.
6665 // Currently, they use the resource dictionary of the surrounding stream. This should be changed, as
6666 // the PDF-Spec states:
6667 // "In PDF 1.2 and later versions, form XObjects may be independent of the content streams in which
6668 // they appear, and this is strongly recommended although not requiredIn PDF 1.2 and later versions,
6669 // form XObjects may be independent of the content streams in which they appear, and this is strongly
6670 // recommended although not required"
6671 beginNewRenderTarget(x, y, width, height, matrix);
6672 return this;
6673 };
6674
6675 /**
6676 * Completes and saves the form object.
6677 * @param {String} key The key by which this form object can be referenced.
6678 * @function
6679 * @returns {jsPDF}
6680 * @memberof jsPDF#
6681 * @name endFormObject
6682 */
6683 API.endFormObject = function(key) {
6684 endFormObject(key);
6685 return this;
6686 };
6687
6688 /**
6689 * Draws the specified form object by referencing to the respective pdf XObject created with
6690 * {@link API.beginFormObject} and {@link endFormObject}.
6691 * The location is determined by matrix.
6692 *
6693 * @param {String} key The key to the form object.
6694 * @param {Matrix} matrix The matrix applied before drawing the form object.
6695 * @function
6696 * @returns {jsPDF}
6697 * @memberof jsPDF#
6698 * @name doFormObject
6699 */
6700 API.doFormObject = function(key, matrix) {
6701 var xObject = renderTargets[renderTargetMap[key]];
6702 out("q");
6703 out(matrix.toString() + " cm");
6704 out("/" + xObject.id + " Do");
6705 out("Q");
6706 return this;
6707 };
6708
6709 /**
6710 * Returns the form object specified by key.
6711 * @param key {String}
6712 * @returns {{x: number, y: number, width: number, height: number, matrix: Matrix}}
6713 * @function
6714 * @returns {jsPDF}
6715 * @memberof jsPDF#
6716 * @name getFormObject
6717 */
6718 API.getFormObject = function(key) {
6719 var xObject = renderTargets[renderTargetMap[key]];
6720 return {
6721 x: xObject.x,
6722 y: xObject.y,
6723 width: xObject.width,
6724 height: xObject.height,
6725 matrix: xObject.matrix
6726 };
6727 };
6728
6729 /**
6730 * Saves as PDF document. An alias of jsPDF.output('save', 'filename.pdf').
6731 * Uses FileSaver.js-method saveAs.
6732 *
6733 * @memberof jsPDF#
6734 * @name save
6735 * @function
6736 * @instance
6737 * @param {string} filename The filename including extension.
6738 * @param {Object} options An Object with additional options, possible options: 'returnPromise'.
6739 * @returns {jsPDF|Promise} jsPDF-instance */
6740 API.save = function(filename, options) {
6741 filename = filename || "generated.pdf";
6742
6743 options = options || {};
6744 options.returnPromise = options.returnPromise || false;
6745
6746 if (options.returnPromise === false) {
6747 saveAs(getBlob(buildDocument()), filename);
6748 if (typeof saveAs.unload === "function") {
6749 if (globalObject.setTimeout) {
6750 setTimeout(saveAs.unload, 911);
6751 }
6752 }
6753 return this;
6754 } else {
6755 return new Promise(function(resolve, reject) {
6756 try {
6757 var result = saveAs(getBlob(buildDocument()), filename);
6758 if (typeof saveAs.unload === "function") {
6759 if (globalObject.setTimeout) {
6760 setTimeout(saveAs.unload, 911);
6761 }
6762 }
6763 resolve(result);
6764 } catch (e) {
6765 reject(e.message);
6766 }
6767 });
6768 }
6769
6770 };
6771
6772 // applying plugins (more methods) ON TOP of built-in API.
6773 // this is intentional as we allow plugins to override
6774 // built-ins
6775 for (var plugin in jsPDF.API) {
6776 if (jsPDF.API.hasOwnProperty(plugin)) {
6777 if (plugin === "events" && jsPDF.API.events.length) {
6778 (function(events, newEvents) {
6779 // jsPDF.API.events is a JS Array of Arrays
6780 // where each Array is a pair of event name, handler
6781 // Events were added by plugins to the jsPDF instantiator.
6782 // These are always added to the new instance and some ran
6783 // during instantiation.
6784 var eventname, handler_and_args, i;
6785
6786 for (i = newEvents.length - 1; i !== -1; i--) {
6787 // subscribe takes 3 args: 'topic', function, runonce_flag
6788 // if undefined, runonce is false.
6789 // users can attach callback directly,
6790 // or they can attach an array with [callback, runonce_flag]
6791 // that's what the "apply" magic is for below.
6792 eventname = newEvents[i][0];
6793 handler_and_args = newEvents[i][1];
6794 events.subscribe.apply(
6795 events,
6796 [eventname].concat(
6797 typeof handler_and_args === "function"
6798 ? [handler_and_args]
6799 : handler_and_args
6800 )
6801 );
6802 }
6803 })(events, jsPDF.API.events);
6804 } else {
6805 API[plugin] = jsPDF.API[plugin];
6806 }
6807 }
6808 }
6809
6810 var getPageWidth = (API.getPageWidth = function(pageNumber) {
6811 pageNumber = pageNumber || currentPage;
6812 return (
6813 (pagesContext[pageNumber].mediaBox.topRightX -
6814 pagesContext[pageNumber].mediaBox.bottomLeftX) /
6815 scaleFactor
6816 );
6817 });
6818
6819 var setPageWidth = (API.setPageWidth = function(pageNumber, value) {
6820 pagesContext[pageNumber].mediaBox.topRightX =
6821 value * scaleFactor + pagesContext[pageNumber].mediaBox.bottomLeftX;
6822 });
6823
6824 var getPageHeight = (API.getPageHeight = function(pageNumber) {
6825 pageNumber = pageNumber || currentPage;
6826 return (
6827 (pagesContext[pageNumber].mediaBox.topRightY -
6828 pagesContext[pageNumber].mediaBox.bottomLeftY) /
6829 scaleFactor
6830 );
6831 });
6832
6833 var setPageHeight = (API.setPageHeight = function(pageNumber, value) {
6834 pagesContext[pageNumber].mediaBox.topRightY =
6835 value * scaleFactor + pagesContext[pageNumber].mediaBox.bottomLeftY;
6836 });
6837
6838 /**
6839 * Object exposing internal API to plugins
6840 * @public
6841 * @ignore
6842 */
6843 API.internal = {
6844 pdfEscape: pdfEscape,
6845 getStyle: getStyle,
6846 getFont: getFontEntry,
6847 getFontSize: getFontSize,
6848 getCharSpace: getCharSpace,
6849 getTextColor: getTextColor,
6850 getLineHeight: getLineHeight,
6851 getLineHeightFactor: getLineHeightFactor,
6852 write: write,
6853 getHorizontalCoordinate: getHorizontalCoordinate,
6854 getVerticalCoordinate: getVerticalCoordinate,
6855 getCoordinateString: getHorizontalCoordinateString,
6856 getVerticalCoordinateString: getVerticalCoordinateString,
6857 collections: {},
6858 newObject: newObject,
6859 newAdditionalObject: newAdditionalObject,
6860 newObjectDeferred: newObjectDeferred,
6861 newObjectDeferredBegin: newObjectDeferredBegin,
6862 getFilters: getFilters,
6863 putStream: putStream,
6864 events: events,
6865 scaleFactor: scaleFactor,
6866 pageSize: {
6867 getWidth: function() {
6868 return getPageWidth(currentPage);
6869 },
6870 setWidth: function(value) {
6871 setPageWidth(currentPage, value);
6872 },
6873 getHeight: function() {
6874 return getPageHeight(currentPage);
6875 },
6876 setHeight: function(value) {
6877 setPageHeight(currentPage, value);
6878 }
6879 },
6880 encryptionOptions: encryptionOptions,
6881 encryption: encryption,
6882 getEncryptor: getEncryptor,
6883 output: output,
6884 getNumberOfPages: getNumberOfPages,
6885 pages: pages,
6886 out: out,
6887 f2: f2,
6888 f3: f3,
6889 getPageInfo: getPageInfo,
6890 getPageInfoByObjId: getPageInfoByObjId,
6891 getCurrentPageInfo: getCurrentPageInfo,
6892 getPDFVersion: getPdfVersion,
6893 Point: Point,
6894 Rectangle: Rectangle,
6895 Matrix: Matrix,
6896 hasHotfix: hasHotfix //Expose the hasHotfix check so plugins can also check them.
6897 };
6898
6899 Object.defineProperty(API.internal.pageSize, "width", {
6900 get: function() {
6901 return getPageWidth(currentPage);
6902 },
6903 set: function(value) {
6904 setPageWidth(currentPage, value);
6905 },
6906 enumerable: true,
6907 configurable: true
6908 });
6909 Object.defineProperty(API.internal.pageSize, "height", {
6910 get: function() {
6911 return getPageHeight(currentPage);
6912 },
6913 set: function(value) {
6914 setPageHeight(currentPage, value);
6915 },
6916 enumerable: true,
6917 configurable: true
6918 });
6919
6920 //////////////////////////////////////////////////////
6921 // continuing initialization of jsPDF Document object
6922 //////////////////////////////////////////////////////
6923 // Add the first page automatically
6924 addFonts.call(API, standardFonts);
6925 activeFontKey = "F1";
6926 _addPage(format, orientation);
6927
6928 events.publish("initialized");
6929 return API;
6930 }
6931
6932 /**
6933 * jsPDF.API is a STATIC property of jsPDF class.
6934 * jsPDF.API is an object you can add methods and properties to.
6935 * The methods / properties you add will show up in new jsPDF objects.
6936 *
6937 * One property is prepopulated. It is the 'events' Object. Plugin authors can add topics,
6938 * callbacks to this object. These will be reassigned to all new instances of jsPDF.
6939 *
6940 * @static
6941 * @public
6942 * @memberof jsPDF#
6943 * @name API
6944 *
6945 * @example
6946 * jsPDF.API.mymethod = function(){
6947 * // 'this' will be ref to internal API object. see jsPDF source
6948 * // , so you can refer to built-in methods like so:
6949 * // this.line(....)
6950 * // this.text(....)
6951 * }
6952 * var pdfdoc = new jsPDF()
6953 * pdfdoc.mymethod() // <- !!!!!!
6954 */
6955 jsPDF.API = {
6956 events: []
6957 };
6958 /**
6959 * The version of jsPDF.
6960 * @name version
6961 * @type {string}
6962 * @memberof jsPDF#
6963 */
6964 jsPDF.version = "2.3.0";
6965
6966 /* global jsPDF */
6967
6968 var jsPDFAPI = jsPDF.API;
6969 var scaleFactor = 1;
6970
6971 var pdfEscape = function(value) {
6972 return value
6973 .replace(/\\/g, "\\\\")
6974 .replace(/\(/g, "\\(")
6975 .replace(/\)/g, "\\)");
6976 };
6977 var pdfUnescape = function(value) {
6978 return value
6979 .replace(/\\\\/g, "\\")
6980 .replace(/\\\(/g, "(")
6981 .replace(/\\\)/g, ")");
6982 };
6983
6984 var f2 = function(number) {
6985 return number.toFixed(2); // Ie, %.2f
6986 };
6987
6988 var f5 = function(number) {
6989 return number.toFixed(5); // Ie, %.2f
6990 };
6991
6992 jsPDFAPI.__acroform__ = {};
6993 var inherit = function(child, parent) {
6994 child.prototype = Object.create(parent.prototype);
6995 child.prototype.constructor = child;
6996 };
6997
6998 var scale = function(x) {
6999 return x * scaleFactor;
7000 };
7001
7002 var createFormXObject = function(formObject) {
7003 var xobj = new AcroFormXObject();
7004 var height = AcroFormAppearance.internal.getHeight(formObject) || 0;
7005 var width = AcroFormAppearance.internal.getWidth(formObject) || 0;
7006 xobj.BBox = [0, 0, Number(f2(width)), Number(f2(height))];
7007 return xobj;
7008 };
7009
7010 /**
7011 * Bit-Operations
7012 */
7013 var setBit = (jsPDFAPI.__acroform__.setBit = function(number, bitPosition) {
7014 number = number || 0;
7015 bitPosition = bitPosition || 0;
7016
7017 if (isNaN(number) || isNaN(bitPosition)) {
7018 throw new Error(
7019 "Invalid arguments passed to jsPDF.API.__acroform__.setBit"
7020 );
7021 }
7022 var bitMask = 1 << bitPosition;
7023
7024 number |= bitMask;
7025
7026 return number;
7027 });
7028
7029 var clearBit = (jsPDFAPI.__acroform__.clearBit = function(number, bitPosition) {
7030 number = number || 0;
7031 bitPosition = bitPosition || 0;
7032
7033 if (isNaN(number) || isNaN(bitPosition)) {
7034 throw new Error(
7035 "Invalid arguments passed to jsPDF.API.__acroform__.clearBit"
7036 );
7037 }
7038 var bitMask = 1 << bitPosition;
7039
7040 number &= ~bitMask;
7041
7042 return number;
7043 });
7044
7045 var getBit = (jsPDFAPI.__acroform__.getBit = function(number, bitPosition) {
7046 if (isNaN(number) || isNaN(bitPosition)) {
7047 throw new Error(
7048 "Invalid arguments passed to jsPDF.API.__acroform__.getBit"
7049 );
7050 }
7051 return (number & (1 << bitPosition)) === 0 ? 0 : 1;
7052 });
7053
7054 /*
7055 * Ff starts counting the bit position at 1 and not like javascript at 0
7056 */
7057 var getBitForPdf = (jsPDFAPI.__acroform__.getBitForPdf = function(
7058 number,
7059 bitPosition
7060 ) {
7061 if (isNaN(number) || isNaN(bitPosition)) {
7062 throw new Error(
7063 "Invalid arguments passed to jsPDF.API.__acroform__.getBitForPdf"
7064 );
7065 }
7066 return getBit(number, bitPosition - 1);
7067 });
7068
7069 var setBitForPdf = (jsPDFAPI.__acroform__.setBitForPdf = function(
7070 number,
7071 bitPosition
7072 ) {
7073 if (isNaN(number) || isNaN(bitPosition)) {
7074 throw new Error(
7075 "Invalid arguments passed to jsPDF.API.__acroform__.setBitForPdf"
7076 );
7077 }
7078 return setBit(number, bitPosition - 1);
7079 });
7080
7081 var clearBitForPdf = (jsPDFAPI.__acroform__.clearBitForPdf = function(
7082 number,
7083 bitPosition
7084 ) {
7085 if (isNaN(number) || isNaN(bitPosition)) {
7086 throw new Error(
7087 "Invalid arguments passed to jsPDF.API.__acroform__.clearBitForPdf"
7088 );
7089 }
7090 return clearBit(number, bitPosition - 1);
7091 });
7092
7093 var calculateCoordinates = (jsPDFAPI.__acroform__.calculateCoordinates = function(
7094 args,
7095 scope
7096 ) {
7097 var getHorizontalCoordinate = scope.internal.getHorizontalCoordinate;
7098 var getVerticalCoordinate = scope.internal.getVerticalCoordinate;
7099 var x = args[0];
7100 var y = args[1];
7101 var w = args[2];
7102 var h = args[3];
7103
7104 var coordinates = {};
7105
7106 coordinates.lowerLeft_X = getHorizontalCoordinate(x) || 0;
7107 coordinates.lowerLeft_Y = getVerticalCoordinate(y + h) || 0;
7108 coordinates.upperRight_X = getHorizontalCoordinate(x + w) || 0;
7109 coordinates.upperRight_Y = getVerticalCoordinate(y) || 0;
7110
7111 return [
7112 Number(f2(coordinates.lowerLeft_X)),
7113 Number(f2(coordinates.lowerLeft_Y)),
7114 Number(f2(coordinates.upperRight_X)),
7115 Number(f2(coordinates.upperRight_Y))
7116 ];
7117 });
7118
7119 var calculateAppearanceStream = function(formObject) {
7120 if (formObject.appearanceStreamContent) {
7121 return formObject.appearanceStreamContent;
7122 }
7123
7124 if (!formObject.V && !formObject.DV) {
7125 return;
7126 }
7127
7128 // else calculate it
7129
7130 var stream = [];
7131 var text = formObject._V || formObject.DV;
7132 var calcRes = calculateX(formObject, text);
7133 var fontKey = formObject.scope.internal.getFont(
7134 formObject.fontName,
7135 formObject.fontStyle
7136 ).id;
7137
7138 //PDF 32000-1:2008, page 444
7139 stream.push("/Tx BMC");
7140 stream.push("q");
7141 stream.push("BT"); // Begin Text
7142 stream.push(formObject.scope.__private__.encodeColorString(formObject.color));
7143 stream.push("/" + fontKey + " " + f2(calcRes.fontSize) + " Tf");
7144 stream.push("1 0 0 1 0 0 Tm"); // Transformation Matrix
7145 stream.push(calcRes.text);
7146 stream.push("ET"); // End Text
7147 stream.push("Q");
7148 stream.push("EMC");
7149
7150 var appearanceStreamContent = createFormXObject(formObject);
7151 appearanceStreamContent.scope = formObject.scope;
7152 appearanceStreamContent.stream = stream.join("\n");
7153 return appearanceStreamContent;
7154 };
7155
7156 var calculateX = function(formObject, text) {
7157 var maxFontSize =
7158 formObject.fontSize === 0 ? formObject.maxFontSize : formObject.fontSize;
7159 var returnValue = {
7160 text: "",
7161 fontSize: ""
7162 };
7163 // Remove Brackets
7164 text = text.substr(0, 1) == "(" ? text.substr(1) : text;
7165 text =
7166 text.substr(text.length - 1) == ")"
7167 ? text.substr(0, text.length - 1)
7168 : text;
7169 // split into array of words
7170 var textSplit = text.split(" ");
7171
7172 var fontSize = maxFontSize; // The Starting fontSize (The Maximum)
7173 var lineSpacing = 2;
7174 var borderPadding = 2;
7175
7176 var height = AcroFormAppearance.internal.getHeight(formObject) || 0;
7177 height = height < 0 ? -height : height;
7178 var width = AcroFormAppearance.internal.getWidth(formObject) || 0;
7179 width = width < 0 ? -width : width;
7180
7181 var isSmallerThanWidth = function(i, lastLine, fontSize) {
7182 if (i + 1 < textSplit.length) {
7183 var tmp = lastLine + " " + textSplit[i + 1];
7184 var TextWidth = calculateFontSpace(tmp, formObject, fontSize).width;
7185 var FieldWidth = width - 2 * borderPadding;
7186 return TextWidth <= FieldWidth;
7187 } else {
7188 return false;
7189 }
7190 };
7191
7192 fontSize++;
7193 FontSize: while (fontSize > 0) {
7194 text = "";
7195 fontSize--;
7196 var textHeight = calculateFontSpace("3", formObject, fontSize).height;
7197 var startY = formObject.multiline
7198 ? height - fontSize
7199 : (height - textHeight) / 2;
7200 startY += lineSpacing;
7201 var startX;
7202
7203 var lastY = startY;
7204 var firstWordInLine = 0,
7205 lastWordInLine = 0;
7206 var lastLength;
7207
7208 if (fontSize <= 0) {
7209 // In case, the Text doesn't fit at all
7210 fontSize = 12;
7211 text = "(...) Tj\n";
7212 text +=
7213 "% Width of Text: " +
7214 calculateFontSpace(text, formObject, fontSize).width +
7215 ", FieldWidth:" +
7216 width +
7217 "\n";
7218 break;
7219 }
7220
7221 var lastLine = "";
7222 var lineCount = 0;
7223 Line: for (var i in textSplit) {
7224 if (textSplit.hasOwnProperty(i)) {
7225 lastLine += textSplit[i] + " ";
7226 // Remove last blank
7227 lastLine =
7228 lastLine.substr(lastLine.length - 1) == " "
7229 ? lastLine.substr(0, lastLine.length - 1)
7230 : lastLine;
7231 var key = parseInt(i);
7232 var nextLineIsSmaller = isSmallerThanWidth(key, lastLine, fontSize);
7233 var isLastWord = i >= textSplit.length - 1;
7234 if (nextLineIsSmaller && !isLastWord) {
7235 lastLine += " ";
7236 continue; // Line
7237 } else if (!nextLineIsSmaller && !isLastWord) {
7238 if (!formObject.multiline) {
7239 continue FontSize;
7240 } else {
7241 if (
7242 (textHeight + lineSpacing) * (lineCount + 2) + lineSpacing >
7243 height
7244 ) {
7245 // If the Text is higher than the
7246 // FieldObject
7247 continue FontSize;
7248 }
7249 lastWordInLine = key;
7250 // go on
7251 }
7252 } else if (isLastWord) {
7253 lastWordInLine = key;
7254 } else {
7255 if (
7256 formObject.multiline &&
7257 (textHeight + lineSpacing) * (lineCount + 2) + lineSpacing > height
7258 ) {
7259 // If the Text is higher than the FieldObject
7260 continue FontSize;
7261 }
7262 }
7263
7264 var line = "";
7265
7266 for (var x = firstWordInLine; x <= lastWordInLine; x++) {
7267 line += textSplit[x] + " ";
7268 }
7269
7270 // Remove last blank
7271 line =
7272 line.substr(line.length - 1) == " "
7273 ? line.substr(0, line.length - 1)
7274 : line;
7275 // lastLength -= blankSpace.width;
7276 lastLength = calculateFontSpace(line, formObject, fontSize).width;
7277
7278 // Calculate startX
7279 switch (formObject.textAlign) {
7280 case "right":
7281 startX = width - lastLength - borderPadding;
7282 break;
7283 case "center":
7284 startX = (width - lastLength) / 2;
7285 break;
7286 case "left":
7287 default:
7288 startX = borderPadding;
7289 break;
7290 }
7291 text += f2(startX) + " " + f2(lastY) + " Td\n";
7292 text += "(" + pdfEscape(line) + ") Tj\n";
7293 // reset X in PDF
7294 text += -f2(startX) + " 0 Td\n";
7295
7296 // After a Line, adjust y position
7297 lastY = -(fontSize + lineSpacing);
7298
7299 // Reset for next iteration step
7300 lastLength = 0;
7301 firstWordInLine = lastWordInLine + 1;
7302 lineCount++;
7303
7304 lastLine = "";
7305 continue Line;
7306 }
7307 }
7308 break;
7309 }
7310
7311 returnValue.text = text;
7312 returnValue.fontSize = fontSize;
7313
7314 return returnValue;
7315 };
7316
7317 /**
7318 * Small workaround for calculating the TextMetric approximately.
7319 *
7320 * @param text
7321 * @param fontsize
7322 * @returns {TextMetrics} (Has Height and Width)
7323 */
7324 var calculateFontSpace = function(text, formObject, fontSize) {
7325 var font = formObject.scope.internal.getFont(
7326 formObject.fontName,
7327 formObject.fontStyle
7328 );
7329 var width =
7330 formObject.scope.getStringUnitWidth(text, {
7331 font: font,
7332 fontSize: parseFloat(fontSize),
7333 charSpace: 0
7334 }) * parseFloat(fontSize);
7335 var height =
7336 formObject.scope.getStringUnitWidth("3", {
7337 font: font,
7338 fontSize: parseFloat(fontSize),
7339 charSpace: 0
7340 }) *
7341 parseFloat(fontSize) *
7342 1.5;
7343 return { height: height, width: width };
7344 };
7345
7346 var acroformPluginTemplate = {
7347 fields: [],
7348 xForms: [],
7349 /**
7350 * acroFormDictionaryRoot contains information about the AcroForm
7351 * Dictionary 0: The Event-Token, the AcroFormDictionaryCallback has
7352 * 1: The Object ID of the Root
7353 */
7354 acroFormDictionaryRoot: null,
7355 /**
7356 * After the PDF gets evaluated, the reference to the root has to be
7357 * reset, this indicates, whether the root has already been printed
7358 * out
7359 */
7360 printedOut: false,
7361 internal: null,
7362 isInitialized: false
7363 };
7364
7365 var annotReferenceCallback = function(scope) {
7366 //set objId to undefined and force it to get a new objId on buildDocument
7367 scope.internal.acroformPlugin.acroFormDictionaryRoot.objId = undefined;
7368 var fields = scope.internal.acroformPlugin.acroFormDictionaryRoot.Fields;
7369 for (var i in fields) {
7370 if (fields.hasOwnProperty(i)) {
7371 var formObject = fields[i];
7372 //set objId to undefined and force it to get a new objId on buildDocument
7373 formObject.objId = undefined;
7374 // add Annot Reference!
7375 if (formObject.hasAnnotation) {
7376 // If theres an Annotation Widget in the Form Object, put the
7377 // Reference in the /Annot array
7378 createAnnotationReference(formObject, scope);
7379 }
7380 }
7381 }
7382 };
7383
7384 var putForm = function(formObject) {
7385 if (formObject.scope.internal.acroformPlugin.printedOut) {
7386 formObject.scope.internal.acroformPlugin.printedOut = false;
7387 formObject.scope.internal.acroformPlugin.acroFormDictionaryRoot = null;
7388 }
7389 formObject.scope.internal.acroformPlugin.acroFormDictionaryRoot.Fields.push(
7390 formObject
7391 );
7392 };
7393 /**
7394 * Create the Reference to the widgetAnnotation, so that it gets referenced
7395 * in the Annot[] int the+ (Requires the Annotation Plugin)
7396 */
7397 var createAnnotationReference = function(object, scope) {
7398 var options = {
7399 type: "reference",
7400 object: object
7401 };
7402 var findEntry = function(entry) {
7403 return entry.type === options.type && entry.object === options.object;
7404 };
7405 if (
7406 scope.internal
7407 .getPageInfo(object.page)
7408 .pageContext.annotations.find(findEntry) === undefined
7409 ) {
7410 scope.internal
7411 .getPageInfo(object.page)
7412 .pageContext.annotations.push(options);
7413 }
7414 };
7415
7416 // Callbacks
7417
7418 var putCatalogCallback = function(scope) {
7419 // Put reference to AcroForm to DocumentCatalog
7420 if (
7421 typeof scope.internal.acroformPlugin.acroFormDictionaryRoot !== "undefined"
7422 ) {
7423 // for safety, shouldn't normally be the case
7424 scope.internal.write(
7425 "/AcroForm " +
7426 scope.internal.acroformPlugin.acroFormDictionaryRoot.objId +
7427 " " +
7428 0 +
7429 " R"
7430 );
7431 } else {
7432 throw new Error("putCatalogCallback: Root missing.");
7433 }
7434 };
7435
7436 /**
7437 * Adds /Acroform X 0 R to Document Catalog, and creates the AcroForm
7438 * Dictionary
7439 */
7440 var AcroFormDictionaryCallback = function(scope) {
7441 // Remove event
7442 scope.internal.events.unsubscribe(
7443 scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID
7444 );
7445 delete scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID;
7446 scope.internal.acroformPlugin.printedOut = true;
7447 };
7448
7449 /**
7450 * Creates the single Fields and writes them into the Document
7451 *
7452 * If fieldArray is set, use the fields that are inside it instead of the
7453 * fields from the AcroRoot (for the FormXObjects...)
7454 */
7455 var createFieldCallback = function(fieldArray, scope) {
7456 var standardFields = !fieldArray;
7457
7458 if (!fieldArray) {
7459 // in case there is no fieldArray specified, we want to print out
7460 // the Fields of the AcroForm
7461 // Print out Root
7462 scope.internal.newObjectDeferredBegin(
7463 scope.internal.acroformPlugin.acroFormDictionaryRoot.objId,
7464 true
7465 );
7466 scope.internal.acroformPlugin.acroFormDictionaryRoot.putStream();
7467 }
7468
7469 fieldArray =
7470 fieldArray || scope.internal.acroformPlugin.acroFormDictionaryRoot.Kids;
7471
7472 for (var i in fieldArray) {
7473 if (fieldArray.hasOwnProperty(i)) {
7474 var fieldObject = fieldArray[i];
7475 var keyValueList = [];
7476 var oldRect = fieldObject.Rect;
7477
7478 if (fieldObject.Rect) {
7479 fieldObject.Rect = calculateCoordinates(fieldObject.Rect, scope);
7480 }
7481
7482 // Start Writing the Object
7483 scope.internal.newObjectDeferredBegin(fieldObject.objId, true);
7484
7485 fieldObject.DA = AcroFormAppearance.createDefaultAppearanceStream(
7486 fieldObject
7487 );
7488
7489 if (
7490 typeof fieldObject === "object" &&
7491 typeof fieldObject.getKeyValueListForStream === "function"
7492 ) {
7493 keyValueList = fieldObject.getKeyValueListForStream();
7494 }
7495
7496 fieldObject.Rect = oldRect;
7497
7498 if (
7499 fieldObject.hasAppearanceStream &&
7500 !fieldObject.appearanceStreamContent
7501 ) {
7502 // Calculate Appearance
7503 var appearance = calculateAppearanceStream(fieldObject);
7504 keyValueList.push({ key: "AP", value: "<</N " + appearance + ">>" });
7505
7506 scope.internal.acroformPlugin.xForms.push(appearance);
7507 }
7508
7509 // Assume AppearanceStreamContent is a Array with N,R,D (at least
7510 // one of them!)
7511 if (fieldObject.appearanceStreamContent) {
7512 var appearanceStreamString = "";
7513 // Iterate over N,R and D
7514 for (var k in fieldObject.appearanceStreamContent) {
7515 if (fieldObject.appearanceStreamContent.hasOwnProperty(k)) {
7516 var value = fieldObject.appearanceStreamContent[k];
7517 appearanceStreamString += "/" + k + " ";
7518 appearanceStreamString += "<<";
7519 if (Object.keys(value).length >= 1 || Array.isArray(value)) {
7520 // appearanceStream is an Array or Object!
7521 for (var i in value) {
7522 if (value.hasOwnProperty(i)) {
7523 var obj = value[i];
7524 if (typeof obj === "function") {
7525 // if Function is referenced, call it in order
7526 // to get the FormXObject
7527 obj = obj.call(scope, fieldObject);
7528 }
7529 appearanceStreamString += "/" + i + " " + obj + " ";
7530
7531 // In case the XForm is already used, e.g. OffState
7532 // of CheckBoxes, don't add it
7533 if (!(scope.internal.acroformPlugin.xForms.indexOf(obj) >= 0))
7534 scope.internal.acroformPlugin.xForms.push(obj);
7535 }
7536 }
7537 } else {
7538 obj = value;
7539 if (typeof obj === "function") {
7540 // if Function is referenced, call it in order to
7541 // get the FormXObject
7542 obj = obj.call(scope, fieldObject);
7543 }
7544 appearanceStreamString += "/" + i + " " + obj;
7545 if (!(scope.internal.acroformPlugin.xForms.indexOf(obj) >= 0))
7546 scope.internal.acroformPlugin.xForms.push(obj);
7547 }
7548 appearanceStreamString += ">>";
7549 }
7550 }
7551
7552 // appearance stream is a normal Object..
7553 keyValueList.push({
7554 key: "AP",
7555 value: "<<\n" + appearanceStreamString + ">>"
7556 });
7557 }
7558
7559 scope.internal.putStream({
7560 additionalKeyValues: keyValueList,
7561 objectId: fieldObject.objId
7562 });
7563
7564 scope.internal.out("endobj");
7565 }
7566 }
7567 if (standardFields) {
7568 createXFormObjectCallback(scope.internal.acroformPlugin.xForms, scope);
7569 }
7570 };
7571
7572 var createXFormObjectCallback = function(fieldArray, scope) {
7573 for (var i in fieldArray) {
7574 if (fieldArray.hasOwnProperty(i)) {
7575 var key = i;
7576 var fieldObject = fieldArray[i];
7577 // Start Writing the Object
7578 scope.internal.newObjectDeferredBegin(fieldObject.objId, true);
7579
7580 if (
7581 typeof fieldObject === "object" &&
7582 typeof fieldObject.putStream === "function"
7583 ) {
7584 fieldObject.putStream();
7585 }
7586 delete fieldArray[key];
7587 }
7588 }
7589 };
7590
7591 var initializeAcroForm = function(scope, formObject) {
7592 formObject.scope = scope;
7593 if (
7594 scope.internal !== undefined &&
7595 (scope.internal.acroformPlugin === undefined ||
7596 scope.internal.acroformPlugin.isInitialized === false)
7597 ) {
7598 AcroFormField.FieldNum = 0;
7599 scope.internal.acroformPlugin = JSON.parse(
7600 JSON.stringify(acroformPluginTemplate)
7601 );
7602 if (scope.internal.acroformPlugin.acroFormDictionaryRoot) {
7603 throw new Error("Exception while creating AcroformDictionary");
7604 }
7605 scaleFactor = scope.internal.scaleFactor;
7606 // The Object Number of the AcroForm Dictionary
7607 scope.internal.acroformPlugin.acroFormDictionaryRoot = new AcroFormDictionary();
7608 scope.internal.acroformPlugin.acroFormDictionaryRoot.scope = scope;
7609
7610 // add Callback for creating the AcroForm Dictionary
7611 scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID = scope.internal.events.subscribe(
7612 "postPutResources",
7613 function() {
7614 AcroFormDictionaryCallback(scope);
7615 }
7616 );
7617
7618 scope.internal.events.subscribe("buildDocument", function() {
7619 annotReferenceCallback(scope);
7620 }); // buildDocument
7621
7622 // Register event, that is triggered when the DocumentCatalog is
7623 // written, in order to add /AcroForm
7624
7625 scope.internal.events.subscribe("putCatalog", function() {
7626 putCatalogCallback(scope);
7627 });
7628
7629 // Register event, that creates all Fields
7630 scope.internal.events.subscribe("postPutPages", function(fieldArray) {
7631 createFieldCallback(fieldArray, scope);
7632 });
7633
7634 scope.internal.acroformPlugin.isInitialized = true;
7635 }
7636 };
7637
7638 //PDF 32000-1:2008, page 26, 7.3.6
7639 var arrayToPdfArray = (jsPDFAPI.__acroform__.arrayToPdfArray = function(
7640 array,
7641 objId,
7642 scope
7643 ) {
7644 var encryptor = function(data) {
7645 return data;
7646 };
7647 if (Array.isArray(array)) {
7648 var content = "[";
7649 for (var i = 0; i < array.length; i++) {
7650 if (i !== 0) {
7651 content += " ";
7652 }
7653 switch (typeof array[i]) {
7654 case "boolean":
7655 case "number":
7656 case "object":
7657 content += array[i].toString();
7658 break;
7659 case "string":
7660 if (array[i].substr(0, 1) !== "/") {
7661 if (typeof objId !== "undefined" && scope)
7662 encryptor = scope.internal.getEncryptor(objId);
7663 content += "(" + pdfEscape(encryptor(array[i].toString())) + ")";
7664 } else {
7665 content += array[i].toString();
7666 }
7667 break;
7668 }
7669 }
7670 content += "]";
7671 return content;
7672 }
7673 throw new Error(
7674 "Invalid argument passed to jsPDF.__acroform__.arrayToPdfArray"
7675 );
7676 });
7677 function getMatches(string, regex, index) {
7678 index || (index = 1); // default to the first capturing group
7679 var matches = [];
7680 var match;
7681 while ((match = regex.exec(string))) {
7682 matches.push(match[index]);
7683 }
7684 return matches;
7685 }
7686 var pdfArrayToStringArray = function(array) {
7687 var result = [];
7688 if (typeof array === "string") {
7689 result = getMatches(array, /\((.*?)\)/g);
7690 }
7691 return result;
7692 };
7693
7694 var toPdfString = function(string, objId, scope) {
7695 var encryptor = function(data) {
7696 return data;
7697 };
7698 if (typeof objId !== "undefined" && scope)
7699 encryptor = scope.internal.getEncryptor(objId);
7700 string = string || "";
7701 string.toString();
7702 string = "(" + pdfEscape(encryptor(string)) + ")";
7703 return string;
7704 };
7705
7706 // ##########################
7707 // Classes
7708 // ##########################
7709
7710 /**
7711 * @class AcroFormPDFObject
7712 * @classdesc A AcroFormPDFObject
7713 */
7714 var AcroFormPDFObject = function() {
7715 this._objId = undefined;
7716 this._scope = undefined;
7717
7718 /**
7719 * @name AcroFormPDFObject#objId
7720 * @type {any}
7721 */
7722 Object.defineProperty(this, "objId", {
7723 get: function() {
7724 if (typeof this._objId === "undefined") {
7725 if (typeof this.scope === "undefined") {
7726 return undefined;
7727 }
7728 this._objId = this.scope.internal.newObjectDeferred();
7729 }
7730 return this._objId;
7731 },
7732 set: function(value) {
7733 this._objId = value;
7734 }
7735 });
7736 Object.defineProperty(this, "scope", {
7737 value: this._scope,
7738 writable: true
7739 });
7740 };
7741
7742 /**
7743 * @function AcroFormPDFObject.toString
7744 */
7745 AcroFormPDFObject.prototype.toString = function() {
7746 return this.objId + " 0 R";
7747 };
7748
7749 AcroFormPDFObject.prototype.putStream = function() {
7750 var keyValueList = this.getKeyValueListForStream();
7751 this.scope.internal.putStream({
7752 data: this.stream,
7753 additionalKeyValues: keyValueList,
7754 objectId: this.objId
7755 });
7756 this.scope.internal.out("endobj");
7757 };
7758
7759 /**
7760 * Returns an key-value-List of all non-configurable Variables from the Object
7761 *
7762 * @name getKeyValueListForStream
7763 * @returns {string}
7764 */
7765 AcroFormPDFObject.prototype.getKeyValueListForStream = function() {
7766 var keyValueList = [];
7767 var keys = Object.getOwnPropertyNames(this).filter(function(key) {
7768 return (
7769 key != "content" &&
7770 key != "appearanceStreamContent" &&
7771 key != "scope" &&
7772 key != "objId" &&
7773 key.substring(0, 1) != "_"
7774 );
7775 });
7776
7777 for (var i in keys) {
7778 if (Object.getOwnPropertyDescriptor(this, keys[i]).configurable === false) {
7779 var key = keys[i];
7780 var value = this[key];
7781
7782 if (value) {
7783 if (Array.isArray(value)) {
7784 keyValueList.push({
7785 key: key,
7786 value: arrayToPdfArray(value, this.objId, this.scope)
7787 });
7788 } else if (value instanceof AcroFormPDFObject) {
7789 // In case it is a reference to another PDFObject,
7790 // take the reference number
7791 value.scope = this.scope;
7792 keyValueList.push({ key: key, value: value.objId + " 0 R" });
7793 } else if (typeof value !== "function") {
7794 keyValueList.push({ key: key, value: value });
7795 }
7796 }
7797 }
7798 }
7799 return keyValueList;
7800 };
7801
7802 var AcroFormXObject = function() {
7803 AcroFormPDFObject.call(this);
7804
7805 Object.defineProperty(this, "Type", {
7806 value: "/XObject",
7807 configurable: false,
7808 writable: true
7809 });
7810
7811 Object.defineProperty(this, "Subtype", {
7812 value: "/Form",
7813 configurable: false,
7814 writable: true
7815 });
7816
7817 Object.defineProperty(this, "FormType", {
7818 value: 1,
7819 configurable: false,
7820 writable: true
7821 });
7822
7823 var _BBox = [];
7824 Object.defineProperty(this, "BBox", {
7825 configurable: false,
7826 get: function() {
7827 return _BBox;
7828 },
7829 set: function(value) {
7830 _BBox = value;
7831 }
7832 });
7833
7834 Object.defineProperty(this, "Resources", {
7835 value: "2 0 R",
7836 configurable: false,
7837 writable: true
7838 });
7839
7840 var _stream;
7841 Object.defineProperty(this, "stream", {
7842 enumerable: false,
7843 configurable: true,
7844 set: function(value) {
7845 _stream = value.trim();
7846 },
7847 get: function() {
7848 if (_stream) {
7849 return _stream;
7850 } else {
7851 return null;
7852 }
7853 }
7854 });
7855 };
7856
7857 inherit(AcroFormXObject, AcroFormPDFObject);
7858
7859 var AcroFormDictionary = function() {
7860 AcroFormPDFObject.call(this);
7861
7862 var _Kids = [];
7863
7864 Object.defineProperty(this, "Kids", {
7865 enumerable: false,
7866 configurable: true,
7867 get: function() {
7868 if (_Kids.length > 0) {
7869 return _Kids;
7870 } else {
7871 return undefined;
7872 }
7873 }
7874 });
7875 Object.defineProperty(this, "Fields", {
7876 enumerable: false,
7877 configurable: false,
7878 get: function() {
7879 return _Kids;
7880 }
7881 });
7882
7883 // Default Appearance
7884 var _DA;
7885 Object.defineProperty(this, "DA", {
7886 enumerable: false,
7887 configurable: false,
7888 get: function() {
7889 if (!_DA) {
7890 return undefined;
7891 }
7892 var encryptor = function(data) {
7893 return data;
7894 };
7895 if (this.scope) encryptor = this.scope.internal.getEncryptor(this.objId);
7896 return "(" + pdfEscape(encryptor(_DA)) + ")";
7897 },
7898 set: function(value) {
7899 _DA = value;
7900 }
7901 });
7902 };
7903
7904 inherit(AcroFormDictionary, AcroFormPDFObject);
7905
7906 /**
7907 * The Field Object contains the Variables, that every Field needs
7908 *
7909 * @class AcroFormField
7910 * @classdesc An AcroForm FieldObject
7911 */
7912 var AcroFormField = function() {
7913 AcroFormPDFObject.call(this);
7914
7915 //Annotation-Flag See Table 165
7916 var _F = 4;
7917 Object.defineProperty(this, "F", {
7918 enumerable: false,
7919 configurable: false,
7920 get: function() {
7921 return _F;
7922 },
7923 set: function(value) {
7924 if (!isNaN(value)) {
7925 _F = value;
7926 } else {
7927 throw new Error(
7928 'Invalid value "' + value + '" for attribute F supplied.'
7929 );
7930 }
7931 }
7932 });
7933
7934 /**
7935 * (PDF 1.2) If set, print the annotation when the page is printed. If clear, never print the annotation, regardless of wether is is displayed on the screen.
7936 * NOTE 2 This can be useful for annotations representing interactive pushbuttons, which would serve no meaningful purpose on the printed page.
7937 *
7938 * @name AcroFormField#showWhenPrinted
7939 * @default true
7940 * @type {boolean}
7941 */
7942 Object.defineProperty(this, "showWhenPrinted", {
7943 enumerable: true,
7944 configurable: true,
7945 get: function() {
7946 return Boolean(getBitForPdf(_F, 3));
7947 },
7948 set: function(value) {
7949 if (Boolean(value) === true) {
7950 this.F = setBitForPdf(_F, 3);
7951 } else {
7952 this.F = clearBitForPdf(_F, 3);
7953 }
7954 }
7955 });
7956
7957 var _Ff = 0;
7958 Object.defineProperty(this, "Ff", {
7959 enumerable: false,
7960 configurable: false,
7961 get: function() {
7962 return _Ff;
7963 },
7964 set: function(value) {
7965 if (!isNaN(value)) {
7966 _Ff = value;
7967 } else {
7968 throw new Error(
7969 'Invalid value "' + value + '" for attribute Ff supplied.'
7970 );
7971 }
7972 }
7973 });
7974
7975 var _Rect = [];
7976 Object.defineProperty(this, "Rect", {
7977 enumerable: false,
7978 configurable: false,
7979 get: function() {
7980 if (_Rect.length === 0) {
7981 return undefined;
7982 }
7983 return _Rect;
7984 },
7985 set: function(value) {
7986 if (typeof value !== "undefined") {
7987 _Rect = value;
7988 } else {
7989 _Rect = [];
7990 }
7991 }
7992 });
7993
7994 /**
7995 * The x-position of the field.
7996 *
7997 * @name AcroFormField#x
7998 * @default null
7999 * @type {number}
8000 */
8001 Object.defineProperty(this, "x", {
8002 enumerable: true,
8003 configurable: true,
8004 get: function() {
8005 if (!_Rect || isNaN(_Rect[0])) {
8006 return 0;
8007 }
8008 return _Rect[0];
8009 },
8010 set: function(value) {
8011 _Rect[0] = value;
8012 }
8013 });
8014
8015 /**
8016 * The y-position of the field.
8017 *
8018 * @name AcroFormField#y
8019 * @default null
8020 * @type {number}
8021 */
8022 Object.defineProperty(this, "y", {
8023 enumerable: true,
8024 configurable: true,
8025 get: function() {
8026 if (!_Rect || isNaN(_Rect[1])) {
8027 return 0;
8028 }
8029 return _Rect[1];
8030 },
8031 set: function(value) {
8032 _Rect[1] = value;
8033 }
8034 });
8035
8036 /**
8037 * The width of the field.
8038 *
8039 * @name AcroFormField#width
8040 * @default null
8041 * @type {number}
8042 */
8043 Object.defineProperty(this, "width", {
8044 enumerable: true,
8045 configurable: true,
8046 get: function() {
8047 if (!_Rect || isNaN(_Rect[2])) {
8048 return 0;
8049 }
8050 return _Rect[2];
8051 },
8052 set: function(value) {
8053 _Rect[2] = value;
8054 }
8055 });
8056
8057 /**
8058 * The height of the field.
8059 *
8060 * @name AcroFormField#height
8061 * @default null
8062 * @type {number}
8063 */
8064 Object.defineProperty(this, "height", {
8065 enumerable: true,
8066 configurable: true,
8067 get: function() {
8068 if (!_Rect || isNaN(_Rect[3])) {
8069 return 0;
8070 }
8071 return _Rect[3];
8072 },
8073 set: function(value) {
8074 _Rect[3] = value;
8075 }
8076 });
8077
8078 var _FT = "";
8079 Object.defineProperty(this, "FT", {
8080 enumerable: true,
8081 configurable: false,
8082 get: function() {
8083 return _FT;
8084 },
8085 set: function(value) {
8086 switch (value) {
8087 case "/Btn":
8088 case "/Tx":
8089 case "/Ch":
8090 case "/Sig":
8091 _FT = value;
8092 break;
8093 default:
8094 throw new Error(
8095 'Invalid value "' + value + '" for attribute FT supplied.'
8096 );
8097 }
8098 }
8099 });
8100
8101 var _T = null;
8102
8103 Object.defineProperty(this, "T", {
8104 enumerable: true,
8105 configurable: false,
8106 get: function() {
8107 if (!_T || _T.length < 1) {
8108 // In case of a Child from a Radio´Group, you don't need a FieldName
8109 if (this instanceof AcroFormChildClass) {
8110 return undefined;
8111 }
8112 _T = "FieldObject" + AcroFormField.FieldNum++;
8113 }
8114 var encryptor = function(data) {
8115 return data;
8116 };
8117 if (this.scope) encryptor = this.scope.internal.getEncryptor(this.objId);
8118 return "(" + pdfEscape(encryptor(_T)) + ")";
8119 },
8120 set: function(value) {
8121 _T = value.toString();
8122 }
8123 });
8124
8125 /**
8126 * (Optional) The partial field name (see 12.7.3.2, “Field Names”).
8127 *
8128 * @name AcroFormField#fieldName
8129 * @default null
8130 * @type {string}
8131 */
8132 Object.defineProperty(this, "fieldName", {
8133 configurable: true,
8134 enumerable: true,
8135 get: function() {
8136 return _T;
8137 },
8138 set: function(value) {
8139 _T = value;
8140 }
8141 });
8142
8143 var _fontName = "helvetica";
8144 /**
8145 * The fontName of the font to be used.
8146 *
8147 * @name AcroFormField#fontName
8148 * @default 'helvetica'
8149 * @type {string}
8150 */
8151 Object.defineProperty(this, "fontName", {
8152 enumerable: true,
8153 configurable: true,
8154 get: function() {
8155 return _fontName;
8156 },
8157 set: function(value) {
8158 _fontName = value;
8159 }
8160 });
8161
8162 var _fontStyle = "normal";
8163 /**
8164 * The fontStyle of the font to be used.
8165 *
8166 * @name AcroFormField#fontStyle
8167 * @default 'normal'
8168 * @type {string}
8169 */
8170 Object.defineProperty(this, "fontStyle", {
8171 enumerable: true,
8172 configurable: true,
8173 get: function() {
8174 return _fontStyle;
8175 },
8176 set: function(value) {
8177 _fontStyle = value;
8178 }
8179 });
8180
8181 var _fontSize = 0;
8182 /**
8183 * The fontSize of the font to be used.
8184 *
8185 * @name AcroFormField#fontSize
8186 * @default 0 (for auto)
8187 * @type {number}
8188 */
8189 Object.defineProperty(this, "fontSize", {
8190 enumerable: true,
8191 configurable: true,
8192 get: function() {
8193 return _fontSize;
8194 },
8195 set: function(value) {
8196 _fontSize = value;
8197 }
8198 });
8199
8200 var _maxFontSize = undefined;
8201 /**
8202 * The maximum fontSize of the font to be used.
8203 *
8204 * @name AcroFormField#maxFontSize
8205 * @default 0 (for auto)
8206 * @type {number}
8207 */
8208 Object.defineProperty(this, "maxFontSize", {
8209 enumerable: true,
8210 configurable: true,
8211 get: function() {
8212 if (_maxFontSize === undefined) {
8213 // use the old default value here - the value is some kind of random as it depends on the scaleFactor (user unit)
8214 // ("50" is transformed to the "user space" but then used in "pdf space")
8215 return 50 / scaleFactor;
8216 } else {
8217 return _maxFontSize;
8218 }
8219 },
8220 set: function(value) {
8221 _maxFontSize = value;
8222 }
8223 });
8224
8225 var _color = "black";
8226 /**
8227 * The color of the text
8228 *
8229 * @name AcroFormField#color
8230 * @default 'black'
8231 * @type {string|rgba}
8232 */
8233 Object.defineProperty(this, "color", {
8234 enumerable: true,
8235 configurable: true,
8236 get: function() {
8237 return _color;
8238 },
8239 set: function(value) {
8240 _color = value;
8241 }
8242 });
8243
8244 var _DA = "/F1 0 Tf 0 g";
8245 // Defines the default appearance (Needed for variable Text)
8246 Object.defineProperty(this, "DA", {
8247 enumerable: true,
8248 configurable: false,
8249 get: function() {
8250 if (
8251 !_DA ||
8252 this instanceof AcroFormChildClass ||
8253 this instanceof AcroFormTextField
8254 ) {
8255 return undefined;
8256 }
8257 return toPdfString(_DA, this.objId, this.scope);
8258 },
8259 set: function(value) {
8260 value = value.toString();
8261 _DA = value;
8262 }
8263 });
8264
8265 var _DV = null;
8266 Object.defineProperty(this, "DV", {
8267 enumerable: false,
8268 configurable: false,
8269 get: function() {
8270 if (!_DV) {
8271 return undefined;
8272 }
8273 if (this instanceof AcroFormButton === false) {
8274 return toPdfString(_DV, this.objId, this.scope);
8275 }
8276 return _DV;
8277 },
8278 set: function(value) {
8279 value = value.toString();
8280 if (this instanceof AcroFormButton === false) {
8281 if (value.substr(0, 1) === "(") {
8282 _DV = pdfUnescape(value.substr(1, value.length - 2));
8283 } else {
8284 _DV = pdfUnescape(value);
8285 }
8286 } else {
8287 _DV = value;
8288 }
8289 }
8290 });
8291
8292 /**
8293 * (Optional; inheritable) The default value to which the field reverts when a reset-form action is executed (see 12.7.5.3, “Reset-Form Action”). The format of this value is the same as that of value.
8294 *
8295 * @name AcroFormField#defaultValue
8296 * @default null
8297 * @type {any}
8298 */
8299 Object.defineProperty(this, "defaultValue", {
8300 enumerable: true,
8301 configurable: true,
8302 get: function() {
8303 if (this instanceof AcroFormButton === true) {
8304 return pdfUnescape(_DV.substr(1, _DV.length - 1));
8305 } else {
8306 return _DV;
8307 }
8308 },
8309 set: function(value) {
8310 value = value.toString();
8311 if (this instanceof AcroFormButton === true) {
8312 _DV = "/" + value;
8313 } else {
8314 _DV = value;
8315 }
8316 }
8317 });
8318
8319 var _V = null;
8320 Object.defineProperty(this, "_V", {
8321 enumerable: false,
8322 configurable: false,
8323 get: function() {
8324 if (!_V) {
8325 return undefined;
8326 }
8327 return _V;
8328 },
8329 set: function(value) {
8330 this.V = value;
8331 }
8332 });
8333 Object.defineProperty(this, "V", {
8334 enumerable: false,
8335 configurable: false,
8336 get: function() {
8337 if (!_V) {
8338 return undefined;
8339 }
8340 if (this instanceof AcroFormButton === false) {
8341 return toPdfString(_V, this.objId, this.scope);
8342 }
8343 return _V;
8344 },
8345 set: function(value) {
8346 value = value.toString();
8347 if (this instanceof AcroFormButton === false) {
8348 if (value.substr(0, 1) === "(") {
8349 _V = pdfUnescape(value.substr(1, value.length - 2));
8350 } else {
8351 _V = pdfUnescape(value);
8352 }
8353 } else {
8354 _V = value;
8355 }
8356 }
8357 });
8358
8359 /**
8360 * (Optional; inheritable) The field’s value, whose format varies depending on the field type. See the descriptions of individual field types for further information.
8361 *
8362 * @name AcroFormField#value
8363 * @default null
8364 * @type {any}
8365 */
8366 Object.defineProperty(this, "value", {
8367 enumerable: true,
8368 configurable: true,
8369 get: function() {
8370 if (this instanceof AcroFormButton === true) {
8371 return pdfUnescape(_V.substr(1, _V.length - 1));
8372 } else {
8373 return _V;
8374 }
8375 },
8376 set: function(value) {
8377 value = value.toString();
8378 if (this instanceof AcroFormButton === true) {
8379 _V = "/" + value;
8380 } else {
8381 _V = value;
8382 }
8383 }
8384 });
8385
8386 /**
8387 * Check if field has annotations
8388 *
8389 * @name AcroFormField#hasAnnotation
8390 * @readonly
8391 * @type {boolean}
8392 */
8393 Object.defineProperty(this, "hasAnnotation", {
8394 enumerable: true,
8395 configurable: true,
8396 get: function() {
8397 return this.Rect;
8398 }
8399 });
8400
8401 Object.defineProperty(this, "Type", {
8402 enumerable: true,
8403 configurable: false,
8404 get: function() {
8405 return this.hasAnnotation ? "/Annot" : null;
8406 }
8407 });
8408
8409 Object.defineProperty(this, "Subtype", {
8410 enumerable: true,
8411 configurable: false,
8412 get: function() {
8413 return this.hasAnnotation ? "/Widget" : null;
8414 }
8415 });
8416
8417 var _hasAppearanceStream = false;
8418 /**
8419 * true if field has an appearanceStream
8420 *
8421 * @name AcroFormField#hasAppearanceStream
8422 * @readonly
8423 * @type {boolean}
8424 */
8425 Object.defineProperty(this, "hasAppearanceStream", {
8426 enumerable: true,
8427 configurable: true,
8428 get: function() {
8429 return _hasAppearanceStream;
8430 },
8431 set: function(value) {
8432 value = Boolean(value);
8433 _hasAppearanceStream = value;
8434 }
8435 });
8436
8437 /**
8438 * The page on which the AcroFormField is placed
8439 *
8440 * @name AcroFormField#page
8441 * @type {number}
8442 */
8443 var _page;
8444 Object.defineProperty(this, "page", {
8445 enumerable: true,
8446 configurable: true,
8447 get: function() {
8448 if (!_page) {
8449 return undefined;
8450 }
8451 return _page;
8452 },
8453 set: function(value) {
8454 _page = value;
8455 }
8456 });
8457
8458 /**
8459 * If set, the user may not change the value of the field. Any associated widget annotations will not interact with the user; that is, they will not respond to mouse clicks or change their appearance in response to mouse motions. This flag is useful for fields whose values are computed or imported from a database.
8460 *
8461 * @name AcroFormField#readOnly
8462 * @default false
8463 * @type {boolean}
8464 */
8465 Object.defineProperty(this, "readOnly", {
8466 enumerable: true,
8467 configurable: true,
8468 get: function() {
8469 return Boolean(getBitForPdf(this.Ff, 1));
8470 },
8471 set: function(value) {
8472 if (Boolean(value) === true) {
8473 this.Ff = setBitForPdf(this.Ff, 1);
8474 } else {
8475 this.Ff = clearBitForPdf(this.Ff, 1);
8476 }
8477 }
8478 });
8479
8480 /**
8481 * If set, the field shall have a value at the time it is exported by a submitform action (see 12.7.5.2, “Submit-Form Action”).
8482 *
8483 * @name AcroFormField#required
8484 * @default false
8485 * @type {boolean}
8486 */
8487 Object.defineProperty(this, "required", {
8488 enumerable: true,
8489 configurable: true,
8490 get: function() {
8491 return Boolean(getBitForPdf(this.Ff, 2));
8492 },
8493 set: function(value) {
8494 if (Boolean(value) === true) {
8495 this.Ff = setBitForPdf(this.Ff, 2);
8496 } else {
8497 this.Ff = clearBitForPdf(this.Ff, 2);
8498 }
8499 }
8500 });
8501
8502 /**
8503 * If set, the field shall not be exported by a submit-form action (see 12.7.5.2, “Submit-Form Action”)
8504 *
8505 * @name AcroFormField#noExport
8506 * @default false
8507 * @type {boolean}
8508 */
8509 Object.defineProperty(this, "noExport", {
8510 enumerable: true,
8511 configurable: true,
8512 get: function() {
8513 return Boolean(getBitForPdf(this.Ff, 3));
8514 },
8515 set: function(value) {
8516 if (Boolean(value) === true) {
8517 this.Ff = setBitForPdf(this.Ff, 3);
8518 } else {
8519 this.Ff = clearBitForPdf(this.Ff, 3);
8520 }
8521 }
8522 });
8523
8524 var _Q = null;
8525 Object.defineProperty(this, "Q", {
8526 enumerable: true,
8527 configurable: false,
8528 get: function() {
8529 if (_Q === null) {
8530 return undefined;
8531 }
8532 return _Q;
8533 },
8534 set: function(value) {
8535 if ([0, 1, 2].indexOf(value) !== -1) {
8536 _Q = value;
8537 } else {
8538 throw new Error(
8539 'Invalid value "' + value + '" for attribute Q supplied.'
8540 );
8541 }
8542 }
8543 });
8544
8545 /**
8546 * (Optional; inheritable) A code specifying the form of quadding (justification) that shall be used in displaying the text:
8547 * 'left', 'center', 'right'
8548 *
8549 * @name AcroFormField#textAlign
8550 * @default 'left'
8551 * @type {string}
8552 */
8553 Object.defineProperty(this, "textAlign", {
8554 get: function() {
8555 var result;
8556 switch (_Q) {
8557 case 0:
8558 default:
8559 result = "left";
8560 break;
8561 case 1:
8562 result = "center";
8563 break;
8564 case 2:
8565 result = "right";
8566 break;
8567 }
8568 return result;
8569 },
8570 configurable: true,
8571 enumerable: true,
8572 set: function(value) {
8573 switch (value) {
8574 case "right":
8575 case 2:
8576 _Q = 2;
8577 break;
8578 case "center":
8579 case 1:
8580 _Q = 1;
8581 break;
8582 case "left":
8583 case 0:
8584 default:
8585 _Q = 0;
8586 }
8587 }
8588 });
8589 };
8590
8591 inherit(AcroFormField, AcroFormPDFObject);
8592
8593 /**
8594 * @class AcroFormChoiceField
8595 * @extends AcroFormField
8596 */
8597 var AcroFormChoiceField = function() {
8598 AcroFormField.call(this);
8599 // Field Type = Choice Field
8600 this.FT = "/Ch";
8601 // options
8602 this.V = "()";
8603
8604 this.fontName = "zapfdingbats";
8605 // Top Index
8606 var _TI = 0;
8607
8608 Object.defineProperty(this, "TI", {
8609 enumerable: true,
8610 configurable: false,
8611 get: function() {
8612 return _TI;
8613 },
8614 set: function(value) {
8615 _TI = value;
8616 }
8617 });
8618
8619 /**
8620 * (Optional) For scrollable list boxes, the top index (the index in the Opt array of the first option visible in the list). Default value: 0.
8621 *
8622 * @name AcroFormChoiceField#topIndex
8623 * @default 0
8624 * @type {number}
8625 */
8626 Object.defineProperty(this, "topIndex", {
8627 enumerable: true,
8628 configurable: true,
8629 get: function() {
8630 return _TI;
8631 },
8632 set: function(value) {
8633 _TI = value;
8634 }
8635 });
8636
8637 var _Opt = [];
8638 Object.defineProperty(this, "Opt", {
8639 enumerable: true,
8640 configurable: false,
8641 get: function() {
8642 return arrayToPdfArray(_Opt, this.objId, this.scope);
8643 },
8644 set: function(value) {
8645 _Opt = pdfArrayToStringArray(value);
8646 }
8647 });
8648
8649 /**
8650 * @memberof AcroFormChoiceField
8651 * @name getOptions
8652 * @function
8653 * @instance
8654 * @returns {array} array of Options
8655 */
8656 this.getOptions = function() {
8657 return _Opt;
8658 };
8659
8660 /**
8661 * @memberof AcroFormChoiceField
8662 * @name setOptions
8663 * @function
8664 * @instance
8665 * @param {array} value
8666 */
8667 this.setOptions = function(value) {
8668 _Opt = value;
8669 if (this.sort) {
8670 _Opt.sort();
8671 }
8672 };
8673
8674 /**
8675 * @memberof AcroFormChoiceField
8676 * @name addOption
8677 * @function
8678 * @instance
8679 * @param {string} value
8680 */
8681 this.addOption = function(value) {
8682 value = value || "";
8683 value = value.toString();
8684 _Opt.push(value);
8685 if (this.sort) {
8686 _Opt.sort();
8687 }
8688 };
8689
8690 /**
8691 * @memberof AcroFormChoiceField
8692 * @name removeOption
8693 * @function
8694 * @instance
8695 * @param {string} value
8696 * @param {boolean} allEntries (default: false)
8697 */
8698 this.removeOption = function(value, allEntries) {
8699 allEntries = allEntries || false;
8700 value = value || "";
8701 value = value.toString();
8702
8703 while (_Opt.indexOf(value) !== -1) {
8704 _Opt.splice(_Opt.indexOf(value), 1);
8705 if (allEntries === false) {
8706 break;
8707 }
8708 }
8709 };
8710
8711 /**
8712 * If set, the field is a combo box; if clear, the field is a list box.
8713 *
8714 * @name AcroFormChoiceField#combo
8715 * @default false
8716 * @type {boolean}
8717 */
8718 Object.defineProperty(this, "combo", {
8719 enumerable: true,
8720 configurable: true,
8721 get: function() {
8722 return Boolean(getBitForPdf(this.Ff, 18));
8723 },
8724 set: function(value) {
8725 if (Boolean(value) === true) {
8726 this.Ff = setBitForPdf(this.Ff, 18);
8727 } else {
8728 this.Ff = clearBitForPdf(this.Ff, 18);
8729 }
8730 }
8731 });
8732
8733 /**
8734 * If set, the combo box shall include an editable text box as well as a drop-down list; if clear, it shall include only a drop-down list. This flag shall be used only if the Combo flag is set.
8735 *
8736 * @name AcroFormChoiceField#edit
8737 * @default false
8738 * @type {boolean}
8739 */
8740 Object.defineProperty(this, "edit", {
8741 enumerable: true,
8742 configurable: true,
8743 get: function() {
8744 return Boolean(getBitForPdf(this.Ff, 19));
8745 },
8746 set: function(value) {
8747 //PDF 32000-1:2008, page 444
8748 if (this.combo === true) {
8749 if (Boolean(value) === true) {
8750 this.Ff = setBitForPdf(this.Ff, 19);
8751 } else {
8752 this.Ff = clearBitForPdf(this.Ff, 19);
8753 }
8754 }
8755 }
8756 });
8757
8758 /**
8759 * If set, the field’s option items shall be sorted alphabetically. This flag is intended for use by writers, not by readers. Conforming readers shall display the options in the order in which they occur in the Opt array (see Table 231).
8760 *
8761 * @name AcroFormChoiceField#sort
8762 * @default false
8763 * @type {boolean}
8764 */
8765 Object.defineProperty(this, "sort", {
8766 enumerable: true,
8767 configurable: true,
8768 get: function() {
8769 return Boolean(getBitForPdf(this.Ff, 20));
8770 },
8771 set: function(value) {
8772 if (Boolean(value) === true) {
8773 this.Ff = setBitForPdf(this.Ff, 20);
8774 _Opt.sort();
8775 } else {
8776 this.Ff = clearBitForPdf(this.Ff, 20);
8777 }
8778 }
8779 });
8780
8781 /**
8782 * (PDF 1.4) If set, more than one of the field’s option items may be selected simultaneously; if clear, at most one item shall be selected
8783 *
8784 * @name AcroFormChoiceField#multiSelect
8785 * @default false
8786 * @type {boolean}
8787 */
8788 Object.defineProperty(this, "multiSelect", {
8789 enumerable: true,
8790 configurable: true,
8791 get: function() {
8792 return Boolean(getBitForPdf(this.Ff, 22));
8793 },
8794 set: function(value) {
8795 if (Boolean(value) === true) {
8796 this.Ff = setBitForPdf(this.Ff, 22);
8797 } else {
8798 this.Ff = clearBitForPdf(this.Ff, 22);
8799 }
8800 }
8801 });
8802
8803 /**
8804 * (PDF 1.4) If set, text entered in the field shall not be spellchecked. This flag shall not be used unless the Combo and Edit flags are both set.
8805 *
8806 * @name AcroFormChoiceField#doNotSpellCheck
8807 * @default false
8808 * @type {boolean}
8809 */
8810 Object.defineProperty(this, "doNotSpellCheck", {
8811 enumerable: true,
8812 configurable: true,
8813 get: function() {
8814 return Boolean(getBitForPdf(this.Ff, 23));
8815 },
8816 set: function(value) {
8817 if (Boolean(value) === true) {
8818 this.Ff = setBitForPdf(this.Ff, 23);
8819 } else {
8820 this.Ff = clearBitForPdf(this.Ff, 23);
8821 }
8822 }
8823 });
8824
8825 /**
8826 * (PDF 1.5) If set, the new value shall be committed as soon as a selection is made (commonly with the pointing device). In this case, supplying a value for a field involves three actions: selecting the field for fill-in, selecting a choice for the fill-in value, and leaving that field, which finalizes or “commits” the data choice and triggers any actions associated with the entry or changing of this data. If this flag is on, then processing does not wait for leaving the field action to occur, but immediately proceeds to the third step.
8827 * This option enables applications to perform an action once a selection is made, without requiring the user to exit the field. If clear, the new value is not committed until the user exits the field.
8828 *
8829 * @name AcroFormChoiceField#commitOnSelChange
8830 * @default false
8831 * @type {boolean}
8832 */
8833 Object.defineProperty(this, "commitOnSelChange", {
8834 enumerable: true,
8835 configurable: true,
8836 get: function() {
8837 return Boolean(getBitForPdf(this.Ff, 27));
8838 },
8839 set: function(value) {
8840 if (Boolean(value) === true) {
8841 this.Ff = setBitForPdf(this.Ff, 27);
8842 } else {
8843 this.Ff = clearBitForPdf(this.Ff, 27);
8844 }
8845 }
8846 });
8847
8848 this.hasAppearanceStream = false;
8849 };
8850 inherit(AcroFormChoiceField, AcroFormField);
8851
8852 /**
8853 * @class AcroFormListBox
8854 * @extends AcroFormChoiceField
8855 * @extends AcroFormField
8856 */
8857 var AcroFormListBox = function() {
8858 AcroFormChoiceField.call(this);
8859 this.fontName = "helvetica";
8860
8861 //PDF 32000-1:2008, page 444
8862 this.combo = false;
8863 };
8864 inherit(AcroFormListBox, AcroFormChoiceField);
8865
8866 /**
8867 * @class AcroFormComboBox
8868 * @extends AcroFormListBox
8869 * @extends AcroFormChoiceField
8870 * @extends AcroFormField
8871 */
8872 var AcroFormComboBox = function() {
8873 AcroFormListBox.call(this);
8874 this.combo = true;
8875 };
8876 inherit(AcroFormComboBox, AcroFormListBox);
8877
8878 /**
8879 * @class AcroFormEditBox
8880 * @extends AcroFormComboBox
8881 * @extends AcroFormListBox
8882 * @extends AcroFormChoiceField
8883 * @extends AcroFormField
8884 */
8885 var AcroFormEditBox = function() {
8886 AcroFormComboBox.call(this);
8887 this.edit = true;
8888 };
8889 inherit(AcroFormEditBox, AcroFormComboBox);
8890
8891 /**
8892 * @class AcroFormButton
8893 * @extends AcroFormField
8894 */
8895 var AcroFormButton = function() {
8896 AcroFormField.call(this);
8897 this.FT = "/Btn";
8898
8899 /**
8900 * (Radio buttons only) If set, exactly one radio button shall be selected at all times; selecting the currently selected button has no effect. If clear, clicking the selected button deselects it, leaving no button selected.
8901 *
8902 * @name AcroFormButton#noToggleToOff
8903 * @type {boolean}
8904 */
8905 Object.defineProperty(this, "noToggleToOff", {
8906 enumerable: true,
8907 configurable: true,
8908 get: function() {
8909 return Boolean(getBitForPdf(this.Ff, 15));
8910 },
8911 set: function(value) {
8912 if (Boolean(value) === true) {
8913 this.Ff = setBitForPdf(this.Ff, 15);
8914 } else {
8915 this.Ff = clearBitForPdf(this.Ff, 15);
8916 }
8917 }
8918 });
8919
8920 /**
8921 * If set, the field is a set of radio buttons; if clear, the field is a checkbox. This flag may be set only if the Pushbutton flag is clear.
8922 *
8923 * @name AcroFormButton#radio
8924 * @type {boolean}
8925 */
8926 Object.defineProperty(this, "radio", {
8927 enumerable: true,
8928 configurable: true,
8929 get: function() {
8930 return Boolean(getBitForPdf(this.Ff, 16));
8931 },
8932 set: function(value) {
8933 if (Boolean(value) === true) {
8934 this.Ff = setBitForPdf(this.Ff, 16);
8935 } else {
8936 this.Ff = clearBitForPdf(this.Ff, 16);
8937 }
8938 }
8939 });
8940
8941 /**
8942 * If set, the field is a pushbutton that does not retain a permanent value.
8943 *
8944 * @name AcroFormButton#pushButton
8945 * @type {boolean}
8946 */
8947 Object.defineProperty(this, "pushButton", {
8948 enumerable: true,
8949 configurable: true,
8950 get: function() {
8951 return Boolean(getBitForPdf(this.Ff, 17));
8952 },
8953 set: function(value) {
8954 if (Boolean(value) === true) {
8955 this.Ff = setBitForPdf(this.Ff, 17);
8956 } else {
8957 this.Ff = clearBitForPdf(this.Ff, 17);
8958 }
8959 }
8960 });
8961
8962 /**
8963 * (PDF 1.5) If set, a group of radio buttons within a radio button field that use the same value for the on state will turn on and off in unison; that is if one is checked, they are all checked. If clear, the buttons are mutually exclusive (the same behavior as HTML radio buttons).
8964 *
8965 * @name AcroFormButton#radioIsUnison
8966 * @type {boolean}
8967 */
8968 Object.defineProperty(this, "radioIsUnison", {
8969 enumerable: true,
8970 configurable: true,
8971 get: function() {
8972 return Boolean(getBitForPdf(this.Ff, 26));
8973 },
8974 set: function(value) {
8975 if (Boolean(value) === true) {
8976 this.Ff = setBitForPdf(this.Ff, 26);
8977 } else {
8978 this.Ff = clearBitForPdf(this.Ff, 26);
8979 }
8980 }
8981 });
8982
8983 var _MK = {};
8984 Object.defineProperty(this, "MK", {
8985 enumerable: false,
8986 configurable: false,
8987 get: function() {
8988 var encryptor = function(data) {
8989 return data;
8990 };
8991 if (this.scope) encryptor = this.scope.internal.getEncryptor(this.objId);
8992 if (Object.keys(_MK).length !== 0) {
8993 var result = [];
8994 result.push("<<");
8995 var key;
8996 for (key in _MK) {
8997 result.push("/" + key + " (" + pdfEscape(encryptor(_MK[key])) + ")");
8998 }
8999 result.push(">>");
9000 return result.join("\n");
9001 }
9002 return undefined;
9003 },
9004 set: function(value) {
9005 if (typeof value === "object") {
9006 _MK = value;
9007 }
9008 }
9009 });
9010
9011 /**
9012 * From the PDF reference:
9013 * (Optional, button fields only) The widget annotation's normal caption which shall be displayed when it is not interacting with the user.
9014 * Unlike the remaining entries listed in this Table which apply only to widget annotations associated with pushbutton fields (see Pushbuttons in 12.7.4.2, "Button Fields"), the CA entry may be used with any type of button field, including check boxes (see Check Boxes in 12.7.4.2, "Button Fields") and radio buttons (Radio Buttons in 12.7.4.2, "Button Fields").
9015 *
9016 * - '8' = Cross,
9017 * - 'l' = Circle,
9018 * - '' = nothing
9019 * @name AcroFormButton#caption
9020 * @type {string}
9021 */
9022 Object.defineProperty(this, "caption", {
9023 enumerable: true,
9024 configurable: true,
9025 get: function() {
9026 return _MK.CA || "";
9027 },
9028 set: function(value) {
9029 if (typeof value === "string") {
9030 _MK.CA = value;
9031 }
9032 }
9033 });
9034
9035 var _AS;
9036 Object.defineProperty(this, "AS", {
9037 enumerable: false,
9038 configurable: false,
9039 get: function() {
9040 return _AS;
9041 },
9042 set: function(value) {
9043 _AS = value;
9044 }
9045 });
9046
9047 /**
9048 * (Required if the appearance dictionary AP contains one or more subdictionaries; PDF 1.2) The annotation's appearance state, which selects the applicable appearance stream from an appearance subdictionary (see Section 12.5.5, "Appearance Streams")
9049 *
9050 * @name AcroFormButton#appearanceState
9051 * @type {any}
9052 */
9053 Object.defineProperty(this, "appearanceState", {
9054 enumerable: true,
9055 configurable: true,
9056 get: function() {
9057 return _AS.substr(1, _AS.length - 1);
9058 },
9059 set: function(value) {
9060 _AS = "/" + value;
9061 }
9062 });
9063 };
9064 inherit(AcroFormButton, AcroFormField);
9065
9066 /**
9067 * @class AcroFormPushButton
9068 * @extends AcroFormButton
9069 * @extends AcroFormField
9070 */
9071 var AcroFormPushButton = function() {
9072 AcroFormButton.call(this);
9073 this.pushButton = true;
9074 };
9075 inherit(AcroFormPushButton, AcroFormButton);
9076
9077 /**
9078 * @class AcroFormRadioButton
9079 * @extends AcroFormButton
9080 * @extends AcroFormField
9081 */
9082 var AcroFormRadioButton = function() {
9083 AcroFormButton.call(this);
9084 this.radio = true;
9085 this.pushButton = false;
9086
9087 var _Kids = [];
9088 Object.defineProperty(this, "Kids", {
9089 enumerable: true,
9090 configurable: false,
9091 get: function() {
9092 return _Kids;
9093 },
9094 set: function(value) {
9095 if (typeof value !== "undefined") {
9096 _Kids = value;
9097 } else {
9098 _Kids = [];
9099 }
9100 }
9101 });
9102 };
9103 inherit(AcroFormRadioButton, AcroFormButton);
9104
9105 /**
9106 * The Child class of a RadioButton (the radioGroup) -> The single Buttons
9107 *
9108 * @class AcroFormChildClass
9109 * @extends AcroFormField
9110 * @ignore
9111 */
9112 var AcroFormChildClass = function() {
9113 AcroFormField.call(this);
9114
9115 var _parent;
9116 Object.defineProperty(this, "Parent", {
9117 enumerable: false,
9118 configurable: false,
9119 get: function() {
9120 return _parent;
9121 },
9122 set: function(value) {
9123 _parent = value;
9124 }
9125 });
9126
9127 var _optionName;
9128 Object.defineProperty(this, "optionName", {
9129 enumerable: false,
9130 configurable: true,
9131 get: function() {
9132 return _optionName;
9133 },
9134 set: function(value) {
9135 _optionName = value;
9136 }
9137 });
9138
9139 var _MK = {};
9140 Object.defineProperty(this, "MK", {
9141 enumerable: false,
9142 configurable: false,
9143 get: function() {
9144 var encryptor = function(data) {
9145 return data;
9146 };
9147 if (this.scope) encryptor = this.scope.internal.getEncryptor(this.objId);
9148 var result = [];
9149 result.push("<<");
9150 var key;
9151 for (key in _MK) {
9152 result.push("/" + key + " (" + pdfEscape(encryptor(_MK[key])) + ")");
9153 }
9154 result.push(">>");
9155 return result.join("\n");
9156 },
9157 set: function(value) {
9158 if (typeof value === "object") {
9159 _MK = value;
9160 }
9161 }
9162 });
9163
9164 /**
9165 * From the PDF reference:
9166 * (Optional, button fields only) The widget annotation's normal caption which shall be displayed when it is not interacting with the user.
9167 * Unlike the remaining entries listed in this Table which apply only to widget annotations associated with pushbutton fields (see Pushbuttons in 12.7.4.2, "Button Fields"), the CA entry may be used with any type of button field, including check boxes (see Check Boxes in 12.7.4.2, "Button Fields") and radio buttons (Radio Buttons in 12.7.4.2, "Button Fields").
9168 *
9169 * - '8' = Cross,
9170 * - 'l' = Circle,
9171 * - '' = nothing
9172 * @name AcroFormButton#caption
9173 * @type {string}
9174 */
9175 Object.defineProperty(this, "caption", {
9176 enumerable: true,
9177 configurable: true,
9178 get: function() {
9179 return _MK.CA || "";
9180 },
9181 set: function(value) {
9182 if (typeof value === "string") {
9183 _MK.CA = value;
9184 }
9185 }
9186 });
9187
9188 var _AS;
9189 Object.defineProperty(this, "AS", {
9190 enumerable: false,
9191 configurable: false,
9192 get: function() {
9193 return _AS;
9194 },
9195 set: function(value) {
9196 _AS = value;
9197 }
9198 });
9199
9200 /**
9201 * (Required if the appearance dictionary AP contains one or more subdictionaries; PDF 1.2) The annotation's appearance state, which selects the applicable appearance stream from an appearance subdictionary (see Section 12.5.5, "Appearance Streams")
9202 *
9203 * @name AcroFormButton#appearanceState
9204 * @type {any}
9205 */
9206 Object.defineProperty(this, "appearanceState", {
9207 enumerable: true,
9208 configurable: true,
9209 get: function() {
9210 return _AS.substr(1, _AS.length - 1);
9211 },
9212 set: function(value) {
9213 _AS = "/" + value;
9214 }
9215 });
9216 this.caption = "l";
9217 this.appearanceState = "Off";
9218 // todo: set AppearanceType as variable that can be set from the
9219 // outside...
9220 this._AppearanceType = AcroFormAppearance.RadioButton.Circle;
9221 // The Default appearanceType is the Circle
9222 this.appearanceStreamContent = this._AppearanceType.createAppearanceStream(
9223 this.optionName
9224 );
9225 };
9226 inherit(AcroFormChildClass, AcroFormField);
9227
9228 AcroFormRadioButton.prototype.setAppearance = function(appearance) {
9229 if (!("createAppearanceStream" in appearance && "getCA" in appearance)) {
9230 throw new Error(
9231 "Couldn't assign Appearance to RadioButton. Appearance was Invalid!"
9232 );
9233 }
9234 for (var objId in this.Kids) {
9235 if (this.Kids.hasOwnProperty(objId)) {
9236 var child = this.Kids[objId];
9237 child.appearanceStreamContent = appearance.createAppearanceStream(
9238 child.optionName
9239 );
9240 child.caption = appearance.getCA();
9241 }
9242 }
9243 };
9244
9245 AcroFormRadioButton.prototype.createOption = function(name) {
9246 // Create new Child for RadioGroup
9247 var child = new AcroFormChildClass();
9248 child.Parent = this;
9249 child.optionName = name;
9250 // Add to Parent
9251 this.Kids.push(child);
9252
9253 addField.call(this.scope, child);
9254
9255 return child;
9256 };
9257
9258 /**
9259 * @class AcroFormCheckBox
9260 * @extends AcroFormButton
9261 * @extends AcroFormField
9262 */
9263 var AcroFormCheckBox = function() {
9264 AcroFormButton.call(this);
9265
9266 this.fontName = "zapfdingbats";
9267 this.caption = "3";
9268 this.appearanceState = "On";
9269 this.value = "On";
9270 this.textAlign = "center";
9271 this.appearanceStreamContent = AcroFormAppearance.CheckBox.createAppearanceStream();
9272 };
9273 inherit(AcroFormCheckBox, AcroFormButton);
9274
9275 /**
9276 * @class AcroFormTextField
9277 * @extends AcroFormField
9278 */
9279 var AcroFormTextField = function() {
9280 AcroFormField.call(this);
9281 this.FT = "/Tx";
9282
9283 /**
9284 * If set, the field may contain multiple lines of text; if clear, the field’s text shall be restricted to a single line.
9285 *
9286 * @name AcroFormTextField#multiline
9287 * @type {boolean}
9288 */
9289 Object.defineProperty(this, "multiline", {
9290 enumerable: true,
9291 configurable: true,
9292 get: function() {
9293 return Boolean(getBitForPdf(this.Ff, 13));
9294 },
9295 set: function(value) {
9296 if (Boolean(value) === true) {
9297 this.Ff = setBitForPdf(this.Ff, 13);
9298 } else {
9299 this.Ff = clearBitForPdf(this.Ff, 13);
9300 }
9301 }
9302 });
9303
9304 /**
9305 * (PDF 1.4) If set, the text entered in the field represents the pathname of a file whose contents shall be submitted as the value of the field.
9306 *
9307 * @name AcroFormTextField#fileSelect
9308 * @type {boolean}
9309 */
9310 Object.defineProperty(this, "fileSelect", {
9311 enumerable: true,
9312 configurable: true,
9313 get: function() {
9314 return Boolean(getBitForPdf(this.Ff, 21));
9315 },
9316 set: function(value) {
9317 if (Boolean(value) === true) {
9318 this.Ff = setBitForPdf(this.Ff, 21);
9319 } else {
9320 this.Ff = clearBitForPdf(this.Ff, 21);
9321 }
9322 }
9323 });
9324
9325 /**
9326 * (PDF 1.4) If set, text entered in the field shall not be spell-checked.
9327 *
9328 * @name AcroFormTextField#doNotSpellCheck
9329 * @type {boolean}
9330 */
9331 Object.defineProperty(this, "doNotSpellCheck", {
9332 enumerable: true,
9333 configurable: true,
9334 get: function() {
9335 return Boolean(getBitForPdf(this.Ff, 23));
9336 },
9337 set: function(value) {
9338 if (Boolean(value) === true) {
9339 this.Ff = setBitForPdf(this.Ff, 23);
9340 } else {
9341 this.Ff = clearBitForPdf(this.Ff, 23);
9342 }
9343 }
9344 });
9345
9346 /**
9347 * (PDF 1.4) If set, the field shall not scroll (horizontally for single-line fields, vertically for multiple-line fields) to accommodate more text than fits within its annotation rectangle. Once the field is full, no further text shall be accepted for interactive form filling; for noninteractive form filling, the filler should take care not to add more character than will visibly fit in the defined area.
9348 *
9349 * @name AcroFormTextField#doNotScroll
9350 * @type {boolean}
9351 */
9352 Object.defineProperty(this, "doNotScroll", {
9353 enumerable: true,
9354 configurable: true,
9355 get: function() {
9356 return Boolean(getBitForPdf(this.Ff, 24));
9357 },
9358 set: function(value) {
9359 if (Boolean(value) === true) {
9360 this.Ff = setBitForPdf(this.Ff, 24);
9361 } else {
9362 this.Ff = clearBitForPdf(this.Ff, 24);
9363 }
9364 }
9365 });
9366
9367 /**
9368 * (PDF 1.5) May be set only if the MaxLen entry is present in the text field dictionary (see Table 229) and if the Multiline, Password, and FileSelect flags are clear. If set, the field shall be automatically divided into as many equally spaced positions, or combs, as the value of MaxLen, and the text is laid out into those combs.
9369 *
9370 * @name AcroFormTextField#comb
9371 * @type {boolean}
9372 */
9373 Object.defineProperty(this, "comb", {
9374 enumerable: true,
9375 configurable: true,
9376 get: function() {
9377 return Boolean(getBitForPdf(this.Ff, 25));
9378 },
9379 set: function(value) {
9380 if (Boolean(value) === true) {
9381 this.Ff = setBitForPdf(this.Ff, 25);
9382 } else {
9383 this.Ff = clearBitForPdf(this.Ff, 25);
9384 }
9385 }
9386 });
9387
9388 /**
9389 * (PDF 1.5) If set, the value of this field shall be a rich text string (see 12.7.3.4, “Rich Text Strings”). If the field has a value, the RV entry of the field dictionary (Table 222) shall specify the rich text string.
9390 *
9391 * @name AcroFormTextField#richText
9392 * @type {boolean}
9393 */
9394 Object.defineProperty(this, "richText", {
9395 enumerable: true,
9396 configurable: true,
9397 get: function() {
9398 return Boolean(getBitForPdf(this.Ff, 26));
9399 },
9400 set: function(value) {
9401 if (Boolean(value) === true) {
9402 this.Ff = setBitForPdf(this.Ff, 26);
9403 } else {
9404 this.Ff = clearBitForPdf(this.Ff, 26);
9405 }
9406 }
9407 });
9408
9409 var _MaxLen = null;
9410 Object.defineProperty(this, "MaxLen", {
9411 enumerable: true,
9412 configurable: false,
9413 get: function() {
9414 return _MaxLen;
9415 },
9416 set: function(value) {
9417 _MaxLen = value;
9418 }
9419 });
9420
9421 /**
9422 * (Optional; inheritable) The maximum length of the field’s text, in characters.
9423 *
9424 * @name AcroFormTextField#maxLength
9425 * @type {number}
9426 */
9427 Object.defineProperty(this, "maxLength", {
9428 enumerable: true,
9429 configurable: true,
9430 get: function() {
9431 return _MaxLen;
9432 },
9433 set: function(value) {
9434 if (Number.isInteger(value)) {
9435 _MaxLen = value;
9436 }
9437 }
9438 });
9439
9440 Object.defineProperty(this, "hasAppearanceStream", {
9441 enumerable: true,
9442 configurable: true,
9443 get: function() {
9444 return this.V || this.DV;
9445 }
9446 });
9447 };
9448 inherit(AcroFormTextField, AcroFormField);
9449
9450 /**
9451 * @class AcroFormPasswordField
9452 * @extends AcroFormTextField
9453 * @extends AcroFormField
9454 */
9455 var AcroFormPasswordField = function() {
9456 AcroFormTextField.call(this);
9457
9458 /**
9459 * If set, the field is intended for entering a secure password that should not be echoed visibly to the screen. Characters typed from the keyboard shall instead be echoed in some unreadable form, such as asterisks or bullet characters.
9460 * NOTE To protect password confidentiality, readers should never store the value of the text field in the PDF file if this flag is set.
9461 *
9462 * @name AcroFormTextField#password
9463 * @type {boolean}
9464 */
9465 Object.defineProperty(this, "password", {
9466 enumerable: true,
9467 configurable: true,
9468 get: function() {
9469 return Boolean(getBitForPdf(this.Ff, 14));
9470 },
9471 set: function(value) {
9472 if (Boolean(value) === true) {
9473 this.Ff = setBitForPdf(this.Ff, 14);
9474 } else {
9475 this.Ff = clearBitForPdf(this.Ff, 14);
9476 }
9477 }
9478 });
9479 this.password = true;
9480 };
9481 inherit(AcroFormPasswordField, AcroFormTextField);
9482
9483 // Contains Methods for creating standard appearances
9484 var AcroFormAppearance = {
9485 CheckBox: {
9486 createAppearanceStream: function() {
9487 var appearance = {
9488 N: {
9489 On: AcroFormAppearance.CheckBox.YesNormal
9490 },
9491 D: {
9492 On: AcroFormAppearance.CheckBox.YesPushDown,
9493 Off: AcroFormAppearance.CheckBox.OffPushDown
9494 }
9495 };
9496
9497 return appearance;
9498 },
9499 /**
9500 * Returns the standard On Appearance for a CheckBox
9501 *
9502 * @returns {AcroFormXObject}
9503 */
9504 YesPushDown: function(formObject) {
9505 var xobj = createFormXObject(formObject);
9506 xobj.scope = formObject.scope;
9507 var stream = [];
9508 var fontKey = formObject.scope.internal.getFont(
9509 formObject.fontName,
9510 formObject.fontStyle
9511 ).id;
9512 var encodedColor = formObject.scope.__private__.encodeColorString(
9513 formObject.color
9514 );
9515 var calcRes = calculateX(formObject, formObject.caption);
9516 stream.push("0.749023 g");
9517 stream.push(
9518 "0 0 " +
9519 f2(AcroFormAppearance.internal.getWidth(formObject)) +
9520 " " +
9521 f2(AcroFormAppearance.internal.getHeight(formObject)) +
9522 " re"
9523 );
9524 stream.push("f");
9525 stream.push("BMC");
9526 stream.push("q");
9527 stream.push("0 0 1 rg");
9528 stream.push(
9529 "/" + fontKey + " " + f2(calcRes.fontSize) + " Tf " + encodedColor
9530 );
9531 stream.push("BT");
9532 stream.push(calcRes.text);
9533 stream.push("ET");
9534 stream.push("Q");
9535 stream.push("EMC");
9536 xobj.stream = stream.join("\n");
9537 return xobj;
9538 },
9539
9540 YesNormal: function(formObject) {
9541 var xobj = createFormXObject(formObject);
9542 xobj.scope = formObject.scope;
9543 var fontKey = formObject.scope.internal.getFont(
9544 formObject.fontName,
9545 formObject.fontStyle
9546 ).id;
9547 var encodedColor = formObject.scope.__private__.encodeColorString(
9548 formObject.color
9549 );
9550 var stream = [];
9551 var height = AcroFormAppearance.internal.getHeight(formObject);
9552 var width = AcroFormAppearance.internal.getWidth(formObject);
9553 var calcRes = calculateX(formObject, formObject.caption);
9554 stream.push("1 g");
9555 stream.push("0 0 " + f2(width) + " " + f2(height) + " re");
9556 stream.push("f");
9557 stream.push("q");
9558 stream.push("0 0 1 rg");
9559 stream.push("0 0 " + f2(width - 1) + " " + f2(height - 1) + " re");
9560 stream.push("W");
9561 stream.push("n");
9562 stream.push("0 g");
9563 stream.push("BT");
9564 stream.push(
9565 "/" + fontKey + " " + f2(calcRes.fontSize) + " Tf " + encodedColor
9566 );
9567 stream.push(calcRes.text);
9568 stream.push("ET");
9569 stream.push("Q");
9570 xobj.stream = stream.join("\n");
9571 return xobj;
9572 },
9573
9574 /**
9575 * Returns the standard Off Appearance for a CheckBox
9576 *
9577 * @returns {AcroFormXObject}
9578 */
9579 OffPushDown: function(formObject) {
9580 var xobj = createFormXObject(formObject);
9581 xobj.scope = formObject.scope;
9582 var stream = [];
9583 stream.push("0.749023 g");
9584 stream.push(
9585 "0 0 " +
9586 f2(AcroFormAppearance.internal.getWidth(formObject)) +
9587 " " +
9588 f2(AcroFormAppearance.internal.getHeight(formObject)) +
9589 " re"
9590 );
9591 stream.push("f");
9592 xobj.stream = stream.join("\n");
9593 return xobj;
9594 }
9595 },
9596
9597 RadioButton: {
9598 Circle: {
9599 createAppearanceStream: function(name) {
9600 var appearanceStreamContent = {
9601 D: {
9602 Off: AcroFormAppearance.RadioButton.Circle.OffPushDown
9603 },
9604 N: {}
9605 };
9606 appearanceStreamContent.N[name] =
9607 AcroFormAppearance.RadioButton.Circle.YesNormal;
9608 appearanceStreamContent.D[name] =
9609 AcroFormAppearance.RadioButton.Circle.YesPushDown;
9610 return appearanceStreamContent;
9611 },
9612 getCA: function() {
9613 return "l";
9614 },
9615
9616 YesNormal: function(formObject) {
9617 var xobj = createFormXObject(formObject);
9618 xobj.scope = formObject.scope;
9619 var stream = [];
9620 // Make the Radius of the Circle relative to min(height, width) of formObject
9621 var DotRadius =
9622 AcroFormAppearance.internal.getWidth(formObject) <=
9623 AcroFormAppearance.internal.getHeight(formObject)
9624 ? AcroFormAppearance.internal.getWidth(formObject) / 4
9625 : AcroFormAppearance.internal.getHeight(formObject) / 4;
9626 // The Borderpadding...
9627 DotRadius = Number((DotRadius * 0.9).toFixed(5));
9628 var c = AcroFormAppearance.internal.Bezier_C;
9629 var DotRadiusBezier = Number((DotRadius * c).toFixed(5));
9630 /*
9631 * The Following is a Circle created with Bezier-Curves.
9632 */
9633 stream.push("q");
9634 stream.push(
9635 "1 0 0 1 " +
9636 f5(AcroFormAppearance.internal.getWidth(formObject) / 2) +
9637 " " +
9638 f5(AcroFormAppearance.internal.getHeight(formObject) / 2) +
9639 " cm"
9640 );
9641 stream.push(DotRadius + " 0 m");
9642 stream.push(
9643 DotRadius +
9644 " " +
9645 DotRadiusBezier +
9646 " " +
9647 DotRadiusBezier +
9648 " " +
9649 DotRadius +
9650 " 0 " +
9651 DotRadius +
9652 " c"
9653 );
9654 stream.push(
9655 "-" +
9656 DotRadiusBezier +
9657 " " +
9658 DotRadius +
9659 " -" +
9660 DotRadius +
9661 " " +
9662 DotRadiusBezier +
9663 " -" +
9664 DotRadius +
9665 " 0 c"
9666 );
9667 stream.push(
9668 "-" +
9669 DotRadius +
9670 " -" +
9671 DotRadiusBezier +
9672 " -" +
9673 DotRadiusBezier +
9674 " -" +
9675 DotRadius +
9676 " 0 -" +
9677 DotRadius +
9678 " c"
9679 );
9680 stream.push(
9681 DotRadiusBezier +
9682 " -" +
9683 DotRadius +
9684 " " +
9685 DotRadius +
9686 " -" +
9687 DotRadiusBezier +
9688 " " +
9689 DotRadius +
9690 " 0 c"
9691 );
9692 stream.push("f");
9693 stream.push("Q");
9694 xobj.stream = stream.join("\n");
9695 return xobj;
9696 },
9697 YesPushDown: function(formObject) {
9698 var xobj = createFormXObject(formObject);
9699 xobj.scope = formObject.scope;
9700 var stream = [];
9701 var DotRadius =
9702 AcroFormAppearance.internal.getWidth(formObject) <=
9703 AcroFormAppearance.internal.getHeight(formObject)
9704 ? AcroFormAppearance.internal.getWidth(formObject) / 4
9705 : AcroFormAppearance.internal.getHeight(formObject) / 4;
9706 // The Borderpadding...
9707 DotRadius = Number((DotRadius * 0.9).toFixed(5));
9708 // Save results for later use; no need to waste
9709 // processor ticks on doing math
9710 var k = Number((DotRadius * 2).toFixed(5));
9711 var kc = Number((k * AcroFormAppearance.internal.Bezier_C).toFixed(5));
9712 var dc = Number(
9713 (DotRadius * AcroFormAppearance.internal.Bezier_C).toFixed(5)
9714 );
9715
9716 stream.push("0.749023 g");
9717 stream.push("q");
9718 stream.push(
9719 "1 0 0 1 " +
9720 f5(AcroFormAppearance.internal.getWidth(formObject) / 2) +
9721 " " +
9722 f5(AcroFormAppearance.internal.getHeight(formObject) / 2) +
9723 " cm"
9724 );
9725 stream.push(k + " 0 m");
9726 stream.push(k + " " + kc + " " + kc + " " + k + " 0 " + k + " c");
9727 stream.push(
9728 "-" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c"
9729 );
9730 stream.push(
9731 "-" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c"
9732 );
9733 stream.push(kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c");
9734 stream.push("f");
9735 stream.push("Q");
9736 stream.push("0 g");
9737 stream.push("q");
9738 stream.push(
9739 "1 0 0 1 " +
9740 f5(AcroFormAppearance.internal.getWidth(formObject) / 2) +
9741 " " +
9742 f5(AcroFormAppearance.internal.getHeight(formObject) / 2) +
9743 " cm"
9744 );
9745 stream.push(DotRadius + " 0 m");
9746 stream.push(
9747 "" +
9748 DotRadius +
9749 " " +
9750 dc +
9751 " " +
9752 dc +
9753 " " +
9754 DotRadius +
9755 " 0 " +
9756 DotRadius +
9757 " c"
9758 );
9759 stream.push(
9760 "-" +
9761 dc +
9762 " " +
9763 DotRadius +
9764 " -" +
9765 DotRadius +
9766 " " +
9767 dc +
9768 " -" +
9769 DotRadius +
9770 " 0 c"
9771 );
9772 stream.push(
9773 "-" +
9774 DotRadius +
9775 " -" +
9776 dc +
9777 " -" +
9778 dc +
9779 " -" +
9780 DotRadius +
9781 " 0 -" +
9782 DotRadius +
9783 " c"
9784 );
9785 stream.push(
9786 dc +
9787 " -" +
9788 DotRadius +
9789 " " +
9790 DotRadius +
9791 " -" +
9792 dc +
9793 " " +
9794 DotRadius +
9795 " 0 c"
9796 );
9797 stream.push("f");
9798 stream.push("Q");
9799 xobj.stream = stream.join("\n");
9800 return xobj;
9801 },
9802 OffPushDown: function(formObject) {
9803 var xobj = createFormXObject(formObject);
9804 xobj.scope = formObject.scope;
9805 var stream = [];
9806 var DotRadius =
9807 AcroFormAppearance.internal.getWidth(formObject) <=
9808 AcroFormAppearance.internal.getHeight(formObject)
9809 ? AcroFormAppearance.internal.getWidth(formObject) / 4
9810 : AcroFormAppearance.internal.getHeight(formObject) / 4;
9811 // The Borderpadding...
9812 DotRadius = Number((DotRadius * 0.9).toFixed(5));
9813 // Save results for later use; no need to waste
9814 // processor ticks on doing math
9815 var k = Number((DotRadius * 2).toFixed(5));
9816 var kc = Number((k * AcroFormAppearance.internal.Bezier_C).toFixed(5));
9817
9818 stream.push("0.749023 g");
9819 stream.push("q");
9820 stream.push(
9821 "1 0 0 1 " +
9822 f5(AcroFormAppearance.internal.getWidth(formObject) / 2) +
9823 " " +
9824 f5(AcroFormAppearance.internal.getHeight(formObject) / 2) +
9825 " cm"
9826 );
9827 stream.push(k + " 0 m");
9828 stream.push(k + " " + kc + " " + kc + " " + k + " 0 " + k + " c");
9829 stream.push(
9830 "-" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c"
9831 );
9832 stream.push(
9833 "-" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c"
9834 );
9835 stream.push(kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c");
9836 stream.push("f");
9837 stream.push("Q");
9838 xobj.stream = stream.join("\n");
9839 return xobj;
9840 }
9841 },
9842
9843 Cross: {
9844 /**
9845 * Creates the Actual AppearanceDictionary-References
9846 *
9847 * @param {string} name
9848 * @returns {Object}
9849 * @ignore
9850 */
9851 createAppearanceStream: function(name) {
9852 var appearanceStreamContent = {
9853 D: {
9854 Off: AcroFormAppearance.RadioButton.Cross.OffPushDown
9855 },
9856 N: {}
9857 };
9858 appearanceStreamContent.N[name] =
9859 AcroFormAppearance.RadioButton.Cross.YesNormal;
9860 appearanceStreamContent.D[name] =
9861 AcroFormAppearance.RadioButton.Cross.YesPushDown;
9862 return appearanceStreamContent;
9863 },
9864 getCA: function() {
9865 return "8";
9866 },
9867
9868 YesNormal: function(formObject) {
9869 var xobj = createFormXObject(formObject);
9870 xobj.scope = formObject.scope;
9871 var stream = [];
9872 var cross = AcroFormAppearance.internal.calculateCross(formObject);
9873 stream.push("q");
9874 stream.push(
9875 "1 1 " +
9876 f2(AcroFormAppearance.internal.getWidth(formObject) - 2) +
9877 " " +
9878 f2(AcroFormAppearance.internal.getHeight(formObject) - 2) +
9879 " re"
9880 );
9881 stream.push("W");
9882 stream.push("n");
9883 stream.push(f2(cross.x1.x) + " " + f2(cross.x1.y) + " m");
9884 stream.push(f2(cross.x2.x) + " " + f2(cross.x2.y) + " l");
9885 stream.push(f2(cross.x4.x) + " " + f2(cross.x4.y) + " m");
9886 stream.push(f2(cross.x3.x) + " " + f2(cross.x3.y) + " l");
9887 stream.push("s");
9888 stream.push("Q");
9889 xobj.stream = stream.join("\n");
9890 return xobj;
9891 },
9892 YesPushDown: function(formObject) {
9893 var xobj = createFormXObject(formObject);
9894 xobj.scope = formObject.scope;
9895 var cross = AcroFormAppearance.internal.calculateCross(formObject);
9896 var stream = [];
9897 stream.push("0.749023 g");
9898 stream.push(
9899 "0 0 " +
9900 f2(AcroFormAppearance.internal.getWidth(formObject)) +
9901 " " +
9902 f2(AcroFormAppearance.internal.getHeight(formObject)) +
9903 " re"
9904 );
9905 stream.push("f");
9906 stream.push("q");
9907 stream.push(
9908 "1 1 " +
9909 f2(AcroFormAppearance.internal.getWidth(formObject) - 2) +
9910 " " +
9911 f2(AcroFormAppearance.internal.getHeight(formObject) - 2) +
9912 " re"
9913 );
9914 stream.push("W");
9915 stream.push("n");
9916 stream.push(f2(cross.x1.x) + " " + f2(cross.x1.y) + " m");
9917 stream.push(f2(cross.x2.x) + " " + f2(cross.x2.y) + " l");
9918 stream.push(f2(cross.x4.x) + " " + f2(cross.x4.y) + " m");
9919 stream.push(f2(cross.x3.x) + " " + f2(cross.x3.y) + " l");
9920 stream.push("s");
9921 stream.push("Q");
9922 xobj.stream = stream.join("\n");
9923 return xobj;
9924 },
9925 OffPushDown: function(formObject) {
9926 var xobj = createFormXObject(formObject);
9927 xobj.scope = formObject.scope;
9928 var stream = [];
9929 stream.push("0.749023 g");
9930 stream.push(
9931 "0 0 " +
9932 f2(AcroFormAppearance.internal.getWidth(formObject)) +
9933 " " +
9934 f2(AcroFormAppearance.internal.getHeight(formObject)) +
9935 " re"
9936 );
9937 stream.push("f");
9938 xobj.stream = stream.join("\n");
9939 return xobj;
9940 }
9941 }
9942 },
9943
9944 /**
9945 * Returns the standard Appearance
9946 *
9947 * @returns {AcroFormXObject}
9948 */
9949 createDefaultAppearanceStream: function(formObject) {
9950 // Set Helvetica to Standard Font (size: auto)
9951 // Color: Black
9952 var fontKey = formObject.scope.internal.getFont(
9953 formObject.fontName,
9954 formObject.fontStyle
9955 ).id;
9956 var encodedColor = formObject.scope.__private__.encodeColorString(
9957 formObject.color
9958 );
9959 var fontSize = formObject.fontSize;
9960 var result = "/" + fontKey + " " + fontSize + " Tf " + encodedColor;
9961 return result;
9962 }
9963 };
9964
9965 AcroFormAppearance.internal = {
9966 Bezier_C: 0.551915024494,
9967
9968 calculateCross: function(formObject) {
9969 var width = AcroFormAppearance.internal.getWidth(formObject);
9970 var height = AcroFormAppearance.internal.getHeight(formObject);
9971 var a = Math.min(width, height);
9972
9973 var cross = {
9974 x1: {
9975 // upperLeft
9976 x: (width - a) / 2,
9977 y: (height - a) / 2 + a // height - borderPadding
9978 },
9979 x2: {
9980 // lowerRight
9981 x: (width - a) / 2 + a,
9982 y: (height - a) / 2 // borderPadding
9983 },
9984 x3: {
9985 // lowerLeft
9986 x: (width - a) / 2,
9987 y: (height - a) / 2 // borderPadding
9988 },
9989 x4: {
9990 // upperRight
9991 x: (width - a) / 2 + a,
9992 y: (height - a) / 2 + a // height - borderPadding
9993 }
9994 };
9995
9996 return cross;
9997 }
9998 };
9999 AcroFormAppearance.internal.getWidth = function(formObject) {
10000 var result = 0;
10001 if (typeof formObject === "object") {
10002 result = scale(formObject.Rect[2]);
10003 }
10004 return result;
10005 };
10006 AcroFormAppearance.internal.getHeight = function(formObject) {
10007 var result = 0;
10008 if (typeof formObject === "object") {
10009 result = scale(formObject.Rect[3]);
10010 }
10011 return result;
10012 };
10013
10014 // Public:
10015
10016 /**
10017 * Add an AcroForm-Field to the jsPDF-instance
10018 *
10019 * @name addField
10020 * @function
10021 * @instance
10022 * @param {Object} fieldObject
10023 * @returns {jsPDF}
10024 */
10025 var addField = (jsPDFAPI.addField = function(fieldObject) {
10026 initializeAcroForm(this, fieldObject);
10027
10028 if (fieldObject instanceof AcroFormField) {
10029 putForm(fieldObject);
10030 } else {
10031 throw new Error("Invalid argument passed to jsPDF.addField.");
10032 }
10033 fieldObject.page = fieldObject.scope.internal.getCurrentPageInfo().pageNumber;
10034 return this;
10035 });
10036
10037 jsPDFAPI.AcroFormChoiceField = AcroFormChoiceField;
10038 jsPDFAPI.AcroFormListBox = AcroFormListBox;
10039 jsPDFAPI.AcroFormComboBox = AcroFormComboBox;
10040 jsPDFAPI.AcroFormEditBox = AcroFormEditBox;
10041 jsPDFAPI.AcroFormButton = AcroFormButton;
10042 jsPDFAPI.AcroFormPushButton = AcroFormPushButton;
10043 jsPDFAPI.AcroFormRadioButton = AcroFormRadioButton;
10044 jsPDFAPI.AcroFormCheckBox = AcroFormCheckBox;
10045 jsPDFAPI.AcroFormTextField = AcroFormTextField;
10046 jsPDFAPI.AcroFormPasswordField = AcroFormPasswordField;
10047 jsPDFAPI.AcroFormAppearance = AcroFormAppearance;
10048
10049 jsPDFAPI.AcroForm = {
10050 ChoiceField: AcroFormChoiceField,
10051 ListBox: AcroFormListBox,
10052 ComboBox: AcroFormComboBox,
10053 EditBox: AcroFormEditBox,
10054 Button: AcroFormButton,
10055 PushButton: AcroFormPushButton,
10056 RadioButton: AcroFormRadioButton,
10057 CheckBox: AcroFormCheckBox,
10058 TextField: AcroFormTextField,
10059 PasswordField: AcroFormPasswordField,
10060 Appearance: AcroFormAppearance
10061 };
10062
10063 jsPDF.AcroForm = {
10064 ChoiceField: AcroFormChoiceField,
10065 ListBox: AcroFormListBox,
10066 ComboBox: AcroFormComboBox,
10067 EditBox: AcroFormEditBox,
10068 Button: AcroFormButton,
10069 PushButton: AcroFormPushButton,
10070 RadioButton: AcroFormRadioButton,
10071 CheckBox: AcroFormCheckBox,
10072 TextField: AcroFormTextField,
10073 PasswordField: AcroFormPasswordField,
10074 Appearance: AcroFormAppearance
10075 };
10076
10077 var AcroForm = jsPDF.AcroForm;
10078
10079 /** @license
10080 * jsPDF addImage plugin
10081 * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/
10082 * 2013 Chris Dowling, https://github.com/gingerchris
10083 * 2013 Trinh Ho, https://github.com/ineedfat
10084 * 2013 Edwin Alejandro Perez, https://github.com/eaparango
10085 * 2013 Norah Smith, https://github.com/burnburnrocket
10086 * 2014 Diego Casorran, https://github.com/diegocr
10087 * 2014 James Robb, https://github.com/jamesbrobb
10088 *
10089 * Permission is hereby granted, free of charge, to any person obtaining
10090 * a copy of this software and associated documentation files (the
10091 * "Software"), to deal in the Software without restriction, including
10092 * without limitation the rights to use, copy, modify, merge, publish,
10093 * distribute, sublicense, and/or sell copies of the Software, and to
10094 * permit persons to whom the Software is furnished to do so, subject to
10095 * the following conditions:
10096 *
10097 * The above copyright notice and this permission notice shall be
10098 * included in all copies or substantial portions of the Software.
10099 *
10100 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
10101 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10102 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
10103 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
10104 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
10105 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
10106 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10107 */
10108
10109 (function(jsPDFAPI) {
10110
10111 var namespace = "addImage_";
10112 jsPDFAPI.__addimage__ = {};
10113
10114 var UNKNOWN = "UNKNOWN";
10115
10116 var imageFileTypeHeaders = {
10117 PNG: [[0x89, 0x50, 0x4e, 0x47]],
10118 TIFF: [
10119 [0x4d, 0x4d, 0x00, 0x2a], //Motorola
10120 [0x49, 0x49, 0x2a, 0x00] //Intel
10121 ],
10122 JPEG: [
10123 [
10124 0xff,
10125 0xd8,
10126 0xff,
10127 0xe0,
10128 undefined,
10129 undefined,
10130 0x4a,
10131 0x46,
10132 0x49,
10133 0x46,
10134 0x00
10135 ], //JFIF
10136 [
10137 0xff,
10138 0xd8,
10139 0xff,
10140 0xe1,
10141 undefined,
10142 undefined,
10143 0x45,
10144 0x78,
10145 0x69,
10146 0x66,
10147 0x00,
10148 0x00
10149 ], //Exif
10150 [0xff, 0xd8, 0xff, 0xdb], //JPEG RAW
10151 [0xff, 0xd8, 0xff, 0xee] //EXIF RAW
10152 ],
10153 JPEG2000: [[0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20]],
10154 GIF87a: [[0x47, 0x49, 0x46, 0x38, 0x37, 0x61]],
10155 GIF89a: [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61]],
10156 WEBP: [
10157 [
10158 0x52,
10159 0x49,
10160 0x46,
10161 0x46,
10162 undefined,
10163 undefined,
10164 undefined,
10165 undefined,
10166 0x57,
10167 0x45,
10168 0x42,
10169 0x50
10170 ]
10171 ],
10172 BMP: [
10173 [0x42, 0x4d], //BM - Windows 3.1x, 95, NT, ... etc.
10174 [0x42, 0x41], //BA - OS/2 struct bitmap array
10175 [0x43, 0x49], //CI - OS/2 struct color icon
10176 [0x43, 0x50], //CP - OS/2 const color pointer
10177 [0x49, 0x43], //IC - OS/2 struct icon
10178 [0x50, 0x54] //PT - OS/2 pointer
10179 ]
10180 };
10181
10182 /**
10183 * Recognize filetype of Image by magic-bytes
10184 *
10185 * https://en.wikipedia.org/wiki/List_of_file_signatures
10186 *
10187 * @name getImageFileTypeByImageData
10188 * @public
10189 * @function
10190 * @param {string|arraybuffer} imageData imageData as binary String or arraybuffer
10191 * @param {string} format format of file if filetype-recognition fails, e.g. 'JPEG'
10192 *
10193 * @returns {string} filetype of Image
10194 */
10195 var getImageFileTypeByImageData = (jsPDFAPI.__addimage__.getImageFileTypeByImageData = function(
10196 imageData,
10197 fallbackFormat
10198 ) {
10199 fallbackFormat = fallbackFormat || UNKNOWN;
10200 var i;
10201 var j;
10202 var result = UNKNOWN;
10203 var headerSchemata;
10204 var compareResult;
10205 var fileType;
10206
10207 if (isArrayBufferView(imageData)) {
10208 for (fileType in imageFileTypeHeaders) {
10209 headerSchemata = imageFileTypeHeaders[fileType];
10210 for (i = 0; i < headerSchemata.length; i += 1) {
10211 compareResult = true;
10212 for (j = 0; j < headerSchemata[i].length; j += 1) {
10213 if (headerSchemata[i][j] === undefined) {
10214 continue;
10215 }
10216 if (headerSchemata[i][j] !== imageData[j]) {
10217 compareResult = false;
10218 break;
10219 }
10220 }
10221 if (compareResult === true) {
10222 result = fileType;
10223 break;
10224 }
10225 }
10226 }
10227 } else {
10228 for (fileType in imageFileTypeHeaders) {
10229 headerSchemata = imageFileTypeHeaders[fileType];
10230 for (i = 0; i < headerSchemata.length; i += 1) {
10231 compareResult = true;
10232 for (j = 0; j < headerSchemata[i].length; j += 1) {
10233 if (headerSchemata[i][j] === undefined) {
10234 continue;
10235 }
10236 if (headerSchemata[i][j] !== imageData.charCodeAt(j)) {
10237 compareResult = false;
10238 break;
10239 }
10240 }
10241 if (compareResult === true) {
10242 result = fileType;
10243 break;
10244 }
10245 }
10246 }
10247 }
10248
10249 if (result === UNKNOWN && fallbackFormat !== UNKNOWN) {
10250 result = fallbackFormat;
10251 }
10252 return result;
10253 });
10254
10255 // Image functionality ported from pdf.js
10256 var putImage = function(image) {
10257 var out = this.internal.write;
10258 var putStream = this.internal.putStream;
10259 var getFilters = this.internal.getFilters;
10260
10261 var filter = getFilters();
10262 while (filter.indexOf("FlateEncode") !== -1) {
10263 filter.splice(filter.indexOf("FlateEncode"), 1);
10264 }
10265
10266 image.objectId = this.internal.newObject();
10267
10268 var additionalKeyValues = [];
10269 additionalKeyValues.push({ key: "Type", value: "/XObject" });
10270 additionalKeyValues.push({ key: "Subtype", value: "/Image" });
10271 additionalKeyValues.push({ key: "Width", value: image.width });
10272 additionalKeyValues.push({ key: "Height", value: image.height });
10273
10274 if (image.colorSpace === color_spaces.INDEXED) {
10275 additionalKeyValues.push({
10276 key: "ColorSpace",
10277 value:
10278 "[/Indexed /DeviceRGB " +
10279 // if an indexed png defines more than one colour with transparency, we've created a sMask
10280 (image.palette.length / 3 - 1) +
10281 " " +
10282 ("sMask" in image && typeof image.sMask !== "undefined"
10283 ? image.objectId + 2
10284 : image.objectId + 1) +
10285 " 0 R]"
10286 });
10287 } else {
10288 additionalKeyValues.push({
10289 key: "ColorSpace",
10290 value: "/" + image.colorSpace
10291 });
10292 if (image.colorSpace === color_spaces.DEVICE_CMYK) {
10293 additionalKeyValues.push({ key: "Decode", value: "[1 0 1 0 1 0 1 0]" });
10294 }
10295 }
10296 additionalKeyValues.push({
10297 key: "BitsPerComponent",
10298 value: image.bitsPerComponent
10299 });
10300 if (
10301 "decodeParameters" in image &&
10302 typeof image.decodeParameters !== "undefined"
10303 ) {
10304 additionalKeyValues.push({
10305 key: "DecodeParms",
10306 value: "<<" + image.decodeParameters + ">>"
10307 });
10308 }
10309 if ("transparency" in image && Array.isArray(image.transparency)) {
10310 var transparency = "",
10311 i = 0,
10312 len = image.transparency.length;
10313 for (; i < len; i++)
10314 transparency +=
10315 image.transparency[i] + " " + image.transparency[i] + " ";
10316
10317 additionalKeyValues.push({
10318 key: "Mask",
10319 value: "[" + transparency + "]"
10320 });
10321 }
10322 if (typeof image.sMask !== "undefined") {
10323 additionalKeyValues.push({
10324 key: "SMask",
10325 value: image.objectId + 1 + " 0 R"
10326 });
10327 }
10328
10329 var alreadyAppliedFilters =
10330 typeof image.filter !== "undefined" ? ["/" + image.filter] : undefined;
10331
10332 putStream({
10333 data: image.data,
10334 additionalKeyValues: additionalKeyValues,
10335 alreadyAppliedFilters: alreadyAppliedFilters,
10336 objectId: image.objectId
10337 });
10338
10339 out("endobj");
10340
10341 // Soft mask
10342 if ("sMask" in image && typeof image.sMask !== "undefined") {
10343 var decodeParameters =
10344 "/Predictor " +
10345 image.predictor +
10346 " /Colors 1 /BitsPerComponent " +
10347 image.bitsPerComponent +
10348 " /Columns " +
10349 image.width;
10350 var sMask = {
10351 width: image.width,
10352 height: image.height,
10353 colorSpace: "DeviceGray",
10354 bitsPerComponent: image.bitsPerComponent,
10355 decodeParameters: decodeParameters,
10356 data: image.sMask
10357 };
10358 if ("filter" in image) {
10359 sMask.filter = image.filter;
10360 }
10361 putImage.call(this, sMask);
10362 }
10363
10364 //Palette
10365 if (image.colorSpace === color_spaces.INDEXED) {
10366 var objId = this.internal.newObject();
10367 //out('<< /Filter / ' + img['f'] +' /Length ' + img['pal'].length + '>>');
10368 //putStream(zlib.compress(img['pal']));
10369 putStream({
10370 data: arrayBufferToBinaryString(new Uint8Array(image.palette)),
10371 objectId: objId
10372 });
10373 out("endobj");
10374 }
10375 };
10376 var putResourcesCallback = function() {
10377 var images = this.internal.collections[namespace + "images"];
10378 for (var i in images) {
10379 putImage.call(this, images[i]);
10380 }
10381 };
10382 var putXObjectsDictCallback = function() {
10383 var images = this.internal.collections[namespace + "images"],
10384 out = this.internal.write,
10385 image;
10386 for (var i in images) {
10387 image = images[i];
10388 out("/I" + image.index, image.objectId, "0", "R");
10389 }
10390 };
10391
10392 var checkCompressValue = function(value) {
10393 if (value && typeof value === "string") value = value.toUpperCase();
10394 return value in jsPDFAPI.image_compression ? value : image_compression.NONE;
10395 };
10396
10397 var initialize = function() {
10398 if (!this.internal.collections[namespace + "images"]) {
10399 this.internal.collections[namespace + "images"] = {};
10400 this.internal.events.subscribe("putResources", putResourcesCallback);
10401 this.internal.events.subscribe("putXobjectDict", putXObjectsDictCallback);
10402 }
10403 };
10404
10405 var getImages = function() {
10406 var images = this.internal.collections[namespace + "images"];
10407 initialize.call(this);
10408 return images;
10409 };
10410 var getImageIndex = function() {
10411 return Object.keys(this.internal.collections[namespace + "images"]).length;
10412 };
10413 var notDefined = function(value) {
10414 return typeof value === "undefined" || value === null || value.length === 0;
10415 };
10416 var generateAliasFromImageData = function(imageData) {
10417 if (typeof imageData === "string" || isArrayBufferView(imageData)) {
10418 return sHashCode(imageData);
10419 }
10420
10421 return null;
10422 };
10423
10424 var isImageTypeSupported = function(type) {
10425 return typeof jsPDFAPI["process" + type.toUpperCase()] === "function";
10426 };
10427
10428 var isDOMElement = function(object) {
10429 return typeof object === "object" && object.nodeType === 1;
10430 };
10431
10432 var getImageDataFromElement = function(element, format) {
10433 //if element is an image which uses data url definition, just return the dataurl
10434 if (element.nodeName === "IMG" && element.hasAttribute("src")) {
10435 var src = "" + element.getAttribute("src");
10436
10437 //is base64 encoded dataUrl, directly process it
10438 if (src.indexOf("data:image/") === 0) {
10439 return atob(
10440 unescape(src)
10441 .split("base64,")
10442 .pop()
10443 );
10444 }
10445
10446 //it is probably an url, try to load it
10447 var tmpImageData = jsPDFAPI.loadFile(src, true);
10448 if (tmpImageData !== undefined) {
10449 return tmpImageData;
10450 }
10451 }
10452
10453 if (element.nodeName === "CANVAS") {
10454 var mimeType;
10455 switch (format) {
10456 case "PNG":
10457 mimeType = "image/png";
10458 break;
10459 case "WEBP":
10460 mimeType = "image/webp";
10461 break;
10462 case "JPEG":
10463 case "JPG":
10464 default:
10465 mimeType = "image/jpeg";
10466 break;
10467 }
10468 return atob(
10469 element
10470 .toDataURL(mimeType, 1.0)
10471 .split("base64,")
10472 .pop()
10473 );
10474 }
10475 };
10476
10477 var checkImagesForAlias = function(alias) {
10478 var images = this.internal.collections[namespace + "images"];
10479 if (images) {
10480 for (var e in images) {
10481 if (alias === images[e].alias) {
10482 return images[e];
10483 }
10484 }
10485 }
10486 };
10487
10488 var determineWidthAndHeight = function(width, height, image) {
10489 if (!width && !height) {
10490 width = -96;
10491 height = -96;
10492 }
10493 if (width < 0) {
10494 width = (-1 * image.width * 72) / width / this.internal.scaleFactor;
10495 }
10496 if (height < 0) {
10497 height = (-1 * image.height * 72) / height / this.internal.scaleFactor;
10498 }
10499 if (width === 0) {
10500 width = (height * image.width) / image.height;
10501 }
10502 if (height === 0) {
10503 height = (width * image.height) / image.width;
10504 }
10505
10506 return [width, height];
10507 };
10508
10509 var writeImageToPDF = function(x, y, width, height, image, rotation) {
10510 var dims = determineWidthAndHeight.call(this, width, height, image),
10511 coord = this.internal.getCoordinateString,
10512 vcoord = this.internal.getVerticalCoordinateString;
10513
10514 var images = getImages.call(this);
10515
10516 width = dims[0];
10517 height = dims[1];
10518 images[image.index] = image;
10519
10520 if (rotation) {
10521 rotation *= Math.PI / 180;
10522 var c = Math.cos(rotation);
10523 var s = Math.sin(rotation);
10524 //like in pdf Reference do it 4 digits instead of 2
10525 var f4 = function(number) {
10526 return number.toFixed(4);
10527 };
10528 var rotationTransformationMatrix = [
10529 f4(c),
10530 f4(s),
10531 f4(s * -1),
10532 f4(c),
10533 0,
10534 0,
10535 "cm"
10536 ];
10537 }
10538 this.internal.write("q"); //Save graphics state
10539 if (rotation) {
10540 this.internal.write(
10541 [1, "0", "0", 1, coord(x), vcoord(y + height), "cm"].join(" ")
10542 ); //Translate
10543 this.internal.write(rotationTransformationMatrix.join(" ")); //Rotate
10544 this.internal.write(
10545 [coord(width), "0", "0", coord(height), "0", "0", "cm"].join(" ")
10546 ); //Scale
10547 } else {
10548 this.internal.write(
10549 [
10550 coord(width),
10551 "0",
10552 "0",
10553 coord(height),
10554 coord(x),
10555 vcoord(y + height),
10556 "cm"
10557 ].join(" ")
10558 ); //Translate and Scale
10559 }
10560
10561 if (this.isAdvancedAPI()) {
10562 // draw image bottom up when in "advanced" API mode
10563 this.internal.write([1, 0, 0, -1, 0, 0, "cm"].join(" "));
10564 }
10565
10566 this.internal.write("/I" + image.index + " Do"); //Paint Image
10567 this.internal.write("Q"); //Restore graphics state
10568 };
10569
10570 /**
10571 * COLOR SPACES
10572 */
10573 var color_spaces = (jsPDFAPI.color_spaces = {
10574 DEVICE_RGB: "DeviceRGB",
10575 DEVICE_GRAY: "DeviceGray",
10576 DEVICE_CMYK: "DeviceCMYK",
10577 CAL_GREY: "CalGray",
10578 CAL_RGB: "CalRGB",
10579 LAB: "Lab",
10580 ICC_BASED: "ICCBased",
10581 INDEXED: "Indexed",
10582 PATTERN: "Pattern",
10583 SEPARATION: "Separation",
10584 DEVICE_N: "DeviceN"
10585 });
10586
10587 /**
10588 * DECODE METHODS
10589 */
10590 jsPDFAPI.decode = {
10591 DCT_DECODE: "DCTDecode",
10592 FLATE_DECODE: "FlateDecode",
10593 LZW_DECODE: "LZWDecode",
10594 JPX_DECODE: "JPXDecode",
10595 JBIG2_DECODE: "JBIG2Decode",
10596 ASCII85_DECODE: "ASCII85Decode",
10597 ASCII_HEX_DECODE: "ASCIIHexDecode",
10598 RUN_LENGTH_DECODE: "RunLengthDecode",
10599 CCITT_FAX_DECODE: "CCITTFaxDecode"
10600 };
10601
10602 /**
10603 * IMAGE COMPRESSION TYPES
10604 */
10605 var image_compression = (jsPDFAPI.image_compression = {
10606 NONE: "NONE",
10607 FAST: "FAST",
10608 MEDIUM: "MEDIUM",
10609 SLOW: "SLOW"
10610 });
10611
10612 /**
10613 * @name sHashCode
10614 * @function
10615 * @param {string} data
10616 * @returns {string}
10617 */
10618 var sHashCode = (jsPDFAPI.__addimage__.sHashCode = function(data) {
10619 var hash = 0,
10620 i,
10621 len;
10622
10623 if (typeof data === "string") {
10624 len = data.length;
10625 for (i = 0; i < len; i++) {
10626 hash = (hash << 5) - hash + data.charCodeAt(i);
10627 hash |= 0; // Convert to 32bit integer
10628 }
10629 } else if (isArrayBufferView(data)) {
10630 len = data.byteLength / 2;
10631 for (i = 0; i < len; i++) {
10632 hash = (hash << 5) - hash + data[i];
10633 hash |= 0; // Convert to 32bit integer
10634 }
10635 }
10636 return hash;
10637 });
10638
10639 /**
10640 * Validates if given String is a valid Base64-String
10641 *
10642 * @name validateStringAsBase64
10643 * @public
10644 * @function
10645 * @param {String} possible Base64-String
10646 *
10647 * @returns {boolean}
10648 */
10649 var validateStringAsBase64 = (jsPDFAPI.__addimage__.validateStringAsBase64 = function(
10650 possibleBase64String
10651 ) {
10652 possibleBase64String = possibleBase64String || "";
10653 possibleBase64String.toString().trim();
10654
10655 var result = true;
10656
10657 if (possibleBase64String.length === 0) {
10658 result = false;
10659 }
10660
10661 if (possibleBase64String.length % 4 !== 0) {
10662 result = false;
10663 }
10664
10665 if (
10666 /^[A-Za-z0-9+/]+$/.test(
10667 possibleBase64String.substr(0, possibleBase64String.length - 2)
10668 ) === false
10669 ) {
10670 result = false;
10671 }
10672
10673 if (
10674 /^[A-Za-z0-9/][A-Za-z0-9+/]|[A-Za-z0-9+/]=|==$/.test(
10675 possibleBase64String.substr(-2)
10676 ) === false
10677 ) {
10678 result = false;
10679 }
10680 return result;
10681 });
10682
10683 /**
10684 * Strips out and returns info from a valid base64 data URI
10685 *
10686 * @name extractImageFromDataUrl
10687 * @function
10688 * @param {string} dataUrl a valid data URI of format 'data:[<MIME-type>][;base64],<data>'
10689 * @returns {Array}an Array containing the following
10690 * [0] the complete data URI
10691 * [1] <MIME-type>
10692 * [2] format - the second part of the mime-type i.e 'png' in 'image/png'
10693 * [4] <data>
10694 */
10695 var extractImageFromDataUrl = (jsPDFAPI.__addimage__.extractImageFromDataUrl = function(
10696 dataUrl
10697 ) {
10698 dataUrl = dataUrl || "";
10699 var dataUrlParts = dataUrl.split("base64,");
10700 var result = null;
10701
10702 if (dataUrlParts.length === 2) {
10703 var extractedInfo = /^data:(\w*\/\w*);*(charset=[\w=-]*)*;*$/.exec(
10704 dataUrlParts[0]
10705 );
10706 if (Array.isArray(extractedInfo)) {
10707 result = {
10708 mimeType: extractedInfo[1],
10709 charset: extractedInfo[2],
10710 data: dataUrlParts[1]
10711 };
10712 }
10713 }
10714 return result;
10715 });
10716
10717 /**
10718 * Check to see if ArrayBuffer is supported
10719 *
10720 * @name supportsArrayBuffer
10721 * @function
10722 * @returns {boolean}
10723 */
10724 var supportsArrayBuffer = (jsPDFAPI.__addimage__.supportsArrayBuffer = function() {
10725 return (
10726 typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"
10727 );
10728 });
10729
10730 /**
10731 * Tests supplied object to determine if ArrayBuffer
10732 *
10733 * @name isArrayBuffer
10734 * @function
10735 * @param {Object} object an Object
10736 *
10737 * @returns {boolean}
10738 */
10739 jsPDFAPI.__addimage__.isArrayBuffer = function(object) {
10740 return supportsArrayBuffer() && object instanceof ArrayBuffer;
10741 };
10742
10743 /**
10744 * Tests supplied object to determine if it implements the ArrayBufferView (TypedArray) interface
10745 *
10746 * @name isArrayBufferView
10747 * @function
10748 * @param {Object} object an Object
10749 * @returns {boolean}
10750 */
10751 var isArrayBufferView = (jsPDFAPI.__addimage__.isArrayBufferView = function(
10752 object
10753 ) {
10754 return (
10755 supportsArrayBuffer() &&
10756 typeof Uint32Array !== "undefined" &&
10757 (object instanceof Int8Array ||
10758 object instanceof Uint8Array ||
10759 (typeof Uint8ClampedArray !== "undefined" &&
10760 object instanceof Uint8ClampedArray) ||
10761 object instanceof Int16Array ||
10762 object instanceof Uint16Array ||
10763 object instanceof Int32Array ||
10764 object instanceof Uint32Array ||
10765 object instanceof Float32Array ||
10766 object instanceof Float64Array)
10767 );
10768 });
10769
10770 /**
10771 * Convert Binary String to ArrayBuffer
10772 *
10773 * @name binaryStringToUint8Array
10774 * @public
10775 * @function
10776 * @param {string} BinaryString with ImageData
10777 * @returns {Uint8Array}
10778 */
10779 var binaryStringToUint8Array = (jsPDFAPI.__addimage__.binaryStringToUint8Array = function(
10780 binary_string
10781 ) {
10782 var len = binary_string.length;
10783 var bytes = new Uint8Array(len);
10784 for (var i = 0; i < len; i++) {
10785 bytes[i] = binary_string.charCodeAt(i);
10786 }
10787 return bytes;
10788 });
10789
10790 /**
10791 * Convert the Buffer to a Binary String
10792 *
10793 * @name arrayBufferToBinaryString
10794 * @public
10795 * @function
10796 * @param {ArrayBuffer} ArrayBuffer with ImageData
10797 *
10798 * @returns {String}
10799 */
10800 var arrayBufferToBinaryString = (jsPDFAPI.__addimage__.arrayBufferToBinaryString = function(
10801 buffer
10802 ) {
10803 try {
10804 return atob(btoa(String.fromCharCode.apply(null, buffer)));
10805 } catch (e) {
10806 if (
10807 typeof Uint8Array !== "undefined" &&
10808 typeof Uint8Array.prototype.reduce !== "undefined"
10809 ) {
10810 return new Uint8Array(buffer)
10811 .reduce(function(data, byte) {
10812 return data.push(String.fromCharCode(byte)), data;
10813 }, [])
10814 .join("");
10815 }
10816 }
10817 });
10818
10819 /**
10820 * Adds an Image to the PDF.
10821 *
10822 * @name addImage
10823 * @public
10824 * @function
10825 * @param {string|HTMLImageElement|HTMLCanvasElement|Uint8Array} imageData imageData as base64 encoded DataUrl or Image-HTMLElement or Canvas-HTMLElement
10826 * @param {string} format format of file if filetype-recognition fails or in case of a Canvas-Element needs to be specified (default for Canvas is JPEG), e.g. 'JPEG', 'PNG', 'WEBP'
10827 * @param {number} x x Coordinate (in units declared at inception of PDF document) against left edge of the page
10828 * @param {number} y y Coordinate (in units declared at inception of PDF document) against upper edge of the page
10829 * @param {number} width width of the image (in units declared at inception of PDF document)
10830 * @param {number} height height of the Image (in units declared at inception of PDF document)
10831 * @param {string} alias alias of the image (if used multiple times)
10832 * @param {string} compression compression of the generated JPEG, can have the values 'NONE', 'FAST', 'MEDIUM' and 'SLOW'
10833 * @param {number} rotation rotation of the image in degrees (0-359)
10834 *
10835 * @returns jsPDF
10836 */
10837 jsPDFAPI.addImage = function() {
10838 var imageData, format, x, y, w, h, alias, compression, rotation;
10839
10840 imageData = arguments[0];
10841 if (typeof arguments[1] === "number") {
10842 format = UNKNOWN;
10843 x = arguments[1];
10844 y = arguments[2];
10845 w = arguments[3];
10846 h = arguments[4];
10847 alias = arguments[5];
10848 compression = arguments[6];
10849 rotation = arguments[7];
10850 } else {
10851 format = arguments[1];
10852 x = arguments[2];
10853 y = arguments[3];
10854 w = arguments[4];
10855 h = arguments[5];
10856 alias = arguments[6];
10857 compression = arguments[7];
10858 rotation = arguments[8];
10859 }
10860
10861 if (
10862 typeof imageData === "object" &&
10863 !isDOMElement(imageData) &&
10864 "imageData" in imageData
10865 ) {
10866 var options = imageData;
10867
10868 imageData = options.imageData;
10869 format = options.format || format || UNKNOWN;
10870 x = options.x || x || 0;
10871 y = options.y || y || 0;
10872 w = options.w || options.width || w;
10873 h = options.h || options.height || h;
10874 alias = options.alias || alias;
10875 compression = options.compression || compression;
10876 rotation = options.rotation || options.angle || rotation;
10877 }
10878
10879 //If compression is not explicitly set, determine if we should use compression
10880 var filter = this.internal.getFilters();
10881 if (compression === undefined && filter.indexOf("FlateEncode") !== -1) {
10882 compression = "SLOW";
10883 }
10884
10885 if (isNaN(x) || isNaN(y)) {
10886 throw new Error("Invalid coordinates passed to jsPDF.addImage");
10887 }
10888
10889 initialize.call(this);
10890
10891 var image = processImageData.call(
10892 this,
10893 imageData,
10894 format,
10895 alias,
10896 compression
10897 );
10898
10899 writeImageToPDF.call(this, x, y, w, h, image, rotation);
10900
10901 return this;
10902 };
10903
10904 var processImageData = function(imageData, format, alias, compression) {
10905 var result, dataAsBinaryString;
10906
10907 if (
10908 typeof imageData === "string" &&
10909 getImageFileTypeByImageData(imageData) === UNKNOWN
10910 ) {
10911 imageData = unescape(imageData);
10912 var tmpImageData = convertBase64ToBinaryString(imageData, false);
10913
10914 if (tmpImageData !== "") {
10915 imageData = tmpImageData;
10916 } else {
10917 tmpImageData = jsPDFAPI.loadFile(imageData, true);
10918 if (tmpImageData !== undefined) {
10919 imageData = tmpImageData;
10920 }
10921 }
10922 }
10923
10924 if (isDOMElement(imageData)) {
10925 imageData = getImageDataFromElement(imageData, format);
10926 }
10927
10928 format = getImageFileTypeByImageData(imageData, format);
10929 if (!isImageTypeSupported(format)) {
10930 throw new Error(
10931 "addImage does not support files of type '" +
10932 format +
10933 "', please ensure that a plugin for '" +
10934 format +
10935 "' support is added."
10936 );
10937 }
10938
10939 // now do the heavy lifting
10940
10941 if (notDefined(alias)) {
10942 alias = generateAliasFromImageData(imageData);
10943 }
10944 result = checkImagesForAlias.call(this, alias);
10945
10946 if (!result) {
10947 if (supportsArrayBuffer()) {
10948 // no need to convert if imageData is already uint8array
10949 if (!(imageData instanceof Uint8Array)) {
10950 dataAsBinaryString = imageData;
10951 imageData = binaryStringToUint8Array(imageData);
10952 }
10953 }
10954
10955 result = this["process" + format.toUpperCase()](
10956 imageData,
10957 getImageIndex.call(this),
10958 alias,
10959 checkCompressValue(compression),
10960 dataAsBinaryString
10961 );
10962 }
10963
10964 if (!result) {
10965 throw new Error("An unknown error occurred whilst processing the image.");
10966 }
10967 return result;
10968 };
10969
10970 /**
10971 * @name convertBase64ToBinaryString
10972 * @function
10973 * @param {string} stringData
10974 * @returns {string} binary string
10975 */
10976 var convertBase64ToBinaryString = (jsPDFAPI.__addimage__.convertBase64ToBinaryString = function(
10977 stringData,
10978 throwError
10979 ) {
10980 throwError = typeof throwError === "boolean" ? throwError : true;
10981 var base64Info;
10982 var imageData = "";
10983 var rawData;
10984
10985 if (typeof stringData === "string") {
10986 base64Info = extractImageFromDataUrl(stringData);
10987 rawData = base64Info !== null ? base64Info.data : stringData;
10988
10989 try {
10990 imageData = atob(rawData);
10991 } catch (e) {
10992 if (throwError) {
10993 if (!validateStringAsBase64(rawData)) {
10994 throw new Error(
10995 "Supplied Data is not a valid base64-String jsPDF.convertBase64ToBinaryString "
10996 );
10997 } else {
10998 throw new Error(
10999 "atob-Error in jsPDF.convertBase64ToBinaryString " + e.message
11000 );
11001 }
11002 }
11003 }
11004 }
11005 return imageData;
11006 });
11007
11008 /**
11009 * @name getImageProperties
11010 * @function
11011 * @param {Object} imageData
11012 * @returns {Object}
11013 */
11014 jsPDFAPI.getImageProperties = function(imageData) {
11015 var image;
11016 var tmpImageData = "";
11017 var format;
11018
11019 if (isDOMElement(imageData)) {
11020 imageData = getImageDataFromElement(imageData);
11021 }
11022
11023 if (
11024 typeof imageData === "string" &&
11025 getImageFileTypeByImageData(imageData) === UNKNOWN
11026 ) {
11027 tmpImageData = convertBase64ToBinaryString(imageData, false);
11028
11029 if (tmpImageData === "") {
11030 tmpImageData = jsPDFAPI.loadFile(imageData) || "";
11031 }
11032 imageData = tmpImageData;
11033 }
11034
11035 format = getImageFileTypeByImageData(imageData);
11036 if (!isImageTypeSupported(format)) {
11037 throw new Error(
11038 "addImage does not support files of type '" +
11039 format +
11040 "', please ensure that a plugin for '" +
11041 format +
11042 "' support is added."
11043 );
11044 }
11045
11046 if (supportsArrayBuffer() && !(imageData instanceof Uint8Array)) {
11047 imageData = binaryStringToUint8Array(imageData);
11048 }
11049
11050 image = this["process" + format.toUpperCase()](imageData);
11051
11052 if (!image) {
11053 throw new Error("An unknown error occurred whilst processing the image");
11054 }
11055
11056 image.fileType = format;
11057
11058 return image;
11059 };
11060 })(jsPDF.API);
11061
11062 /**
11063 * @license
11064 * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv
11065 *
11066 * Licensed under the MIT License.
11067 * http://opensource.org/licenses/mit-license
11068 */
11069
11070 (function(jsPDFAPI) {
11071
11072 var notEmpty = function(obj) {
11073 if (typeof obj != "undefined") {
11074 if (obj != "") {
11075 return true;
11076 }
11077 }
11078 };
11079
11080 jsPDF.API.events.push([
11081 "addPage",
11082 function(addPageData) {
11083 var pageInfo = this.internal.getPageInfo(addPageData.pageNumber);
11084 pageInfo.pageContext.annotations = [];
11085 }
11086 ]);
11087
11088 jsPDFAPI.events.push([
11089 "putPage",
11090 function(putPageData) {
11091 var getHorizontalCoordinateString = this.internal.getCoordinateString;
11092 var getVerticalCoordinateString = this.internal
11093 .getVerticalCoordinateString;
11094 var pageInfo = this.internal.getPageInfoByObjId(putPageData.objId);
11095 var pageAnnos = putPageData.pageContext.annotations;
11096
11097 var anno, rect, line;
11098 var found = false;
11099 for (var a = 0; a < pageAnnos.length && !found; a++) {
11100 anno = pageAnnos[a];
11101 switch (anno.type) {
11102 case "link":
11103 if (
11104 notEmpty(anno.options.url) ||
11105 notEmpty(anno.options.pageNumber)
11106 ) {
11107 found = true;
11108 }
11109 break;
11110 case "reference":
11111 case "text":
11112 case "freetext":
11113 found = true;
11114 break;
11115 }
11116 }
11117 if (found == false) {
11118 return;
11119 }
11120
11121 this.internal.write("/Annots [");
11122 for (var i = 0; i < pageAnnos.length; i++) {
11123 anno = pageAnnos[i];
11124 var escape = this.internal.pdfEscape;
11125 var encryptor = this.internal.getEncryptor(putPageData.objId);
11126
11127 switch (anno.type) {
11128 case "reference":
11129 // References to Widget Annotations (for AcroForm Fields)
11130 this.internal.write(" " + anno.object.objId + " 0 R ");
11131 break;
11132 case "text":
11133 // Create a an object for both the text and the popup
11134 var objText = this.internal.newAdditionalObject();
11135 var objPopup = this.internal.newAdditionalObject();
11136 var encryptorText = this.internal.getEncryptor(objText.objId);
11137
11138 var title = anno.title || "Note";
11139 rect =
11140 "/Rect [" +
11141 getHorizontalCoordinateString(anno.bounds.x) +
11142 " " +
11143 getVerticalCoordinateString(anno.bounds.y + anno.bounds.h) +
11144 " " +
11145 getHorizontalCoordinateString(anno.bounds.x + anno.bounds.w) +
11146 " " +
11147 getVerticalCoordinateString(anno.bounds.y) +
11148 "] ";
11149
11150 line =
11151 "<</Type /Annot /Subtype /" +
11152 "Text" +
11153 " " +
11154 rect +
11155 "/Contents (" +
11156 escape(encryptorText(anno.contents)) +
11157 ")";
11158 line += " /Popup " + objPopup.objId + " 0 R";
11159 line += " /P " + pageInfo.objId + " 0 R";
11160 line += " /T (" + escape(encryptorText(title)) + ") >>";
11161 objText.content = line;
11162
11163 var parent = objText.objId + " 0 R";
11164 var popoff = 30;
11165 rect =
11166 "/Rect [" +
11167 getHorizontalCoordinateString(anno.bounds.x + popoff) +
11168 " " +
11169 getVerticalCoordinateString(anno.bounds.y + anno.bounds.h) +
11170 " " +
11171 getHorizontalCoordinateString(
11172 anno.bounds.x + anno.bounds.w + popoff
11173 ) +
11174 " " +
11175 getVerticalCoordinateString(anno.bounds.y) +
11176 "] ";
11177 line =
11178 "<</Type /Annot /Subtype /" +
11179 "Popup" +
11180 " " +
11181 rect +
11182 " /Parent " +
11183 parent;
11184 if (anno.open) {
11185 line += " /Open true";
11186 }
11187 line += " >>";
11188 objPopup.content = line;
11189
11190 this.internal.write(objText.objId, "0 R", objPopup.objId, "0 R");
11191
11192 break;
11193 case "freetext":
11194 rect =
11195 "/Rect [" +
11196 getHorizontalCoordinateString(anno.bounds.x) +
11197 " " +
11198 getVerticalCoordinateString(anno.bounds.y) +
11199 " " +
11200 getHorizontalCoordinateString(anno.bounds.x + anno.bounds.w) +
11201 " " +
11202 getVerticalCoordinateString(anno.bounds.y + anno.bounds.h) +
11203 "] ";
11204 var color = anno.color || "#000000";
11205 line =
11206 "<</Type /Annot /Subtype /" +
11207 "FreeText" +
11208 " " +
11209 rect +
11210 "/Contents (" +
11211 escape(encryptor(anno.contents)) +
11212 ")";
11213 line +=
11214 " /DS(font: Helvetica,sans-serif 12.0pt; text-align:left; color:#" +
11215 color +
11216 ")";
11217 line += " /Border [0 0 0]";
11218 line += " >>";
11219 this.internal.write(line);
11220 break;
11221 case "link":
11222 if (anno.options.name) {
11223 var loc = this.annotations._nameMap[anno.options.name];
11224 anno.options.pageNumber = loc.page;
11225 anno.options.top = loc.y;
11226 } else {
11227 if (!anno.options.top) {
11228 anno.options.top = 0;
11229 }
11230 }
11231
11232 rect =
11233 "/Rect [" +
11234 anno.finalBounds.x +
11235 " " +
11236 anno.finalBounds.y +
11237 " " +
11238 anno.finalBounds.w +
11239 " " +
11240 anno.finalBounds.h +
11241 "] ";
11242
11243 line = "";
11244 if (anno.options.url) {
11245 line =
11246 "<</Type /Annot /Subtype /Link " +
11247 rect +
11248 "/Border [0 0 0] /A <</S /URI /URI (" +
11249 escape(encryptor(anno.options.url)) +
11250 ") >>";
11251 } else if (anno.options.pageNumber) {
11252 // first page is 0
11253 var info = this.internal.getPageInfo(anno.options.pageNumber);
11254 line =
11255 "<</Type /Annot /Subtype /Link " +
11256 rect +
11257 "/Border [0 0 0] /Dest [" +
11258 info.objId +
11259 " 0 R";
11260 anno.options.magFactor = anno.options.magFactor || "XYZ";
11261 switch (anno.options.magFactor) {
11262 case "Fit":
11263 line += " /Fit]";
11264 break;
11265 case "FitH":
11266 line += " /FitH " + anno.options.top + "]";
11267 break;
11268 case "FitV":
11269 anno.options.left = anno.options.left || 0;
11270 line += " /FitV " + anno.options.left + "]";
11271 break;
11272 case "XYZ":
11273 default:
11274 var top = getVerticalCoordinateString(anno.options.top);
11275 anno.options.left = anno.options.left || 0;
11276 // 0 or null zoom will not change zoom factor
11277 if (typeof anno.options.zoom === "undefined") {
11278 anno.options.zoom = 0;
11279 }
11280 line +=
11281 " /XYZ " +
11282 anno.options.left +
11283 " " +
11284 top +
11285 " " +
11286 anno.options.zoom +
11287 "]";
11288 break;
11289 }
11290 }
11291
11292 if (line != "") {
11293 line += " >>";
11294 this.internal.write(line);
11295 }
11296 break;
11297 }
11298 }
11299 this.internal.write("]");
11300 }
11301 ]);
11302
11303 /**
11304 * @name createAnnotation
11305 * @function
11306 * @param {Object} options
11307 */
11308 jsPDFAPI.createAnnotation = function(options) {
11309 var pageInfo = this.internal.getCurrentPageInfo();
11310 switch (options.type) {
11311 case "link":
11312 this.link(
11313 options.bounds.x,
11314 options.bounds.y,
11315 options.bounds.w,
11316 options.bounds.h,
11317 options
11318 );
11319 break;
11320 case "text":
11321 case "freetext":
11322 pageInfo.pageContext.annotations.push(options);
11323 break;
11324 }
11325 };
11326
11327 /**
11328 * Create a link
11329 *
11330 * valid options
11331 * <li> pageNumber or url [required]
11332 * <p>If pageNumber is specified, top and zoom may also be specified</p>
11333 * @name link
11334 * @function
11335 * @param {number} x
11336 * @param {number} y
11337 * @param {number} w
11338 * @param {number} h
11339 * @param {Object} options
11340 */
11341 jsPDFAPI.link = function(x, y, w, h, options) {
11342 var pageInfo = this.internal.getCurrentPageInfo();
11343 var getHorizontalCoordinateString = this.internal.getCoordinateString;
11344 var getVerticalCoordinateString = this.internal.getVerticalCoordinateString;
11345
11346 pageInfo.pageContext.annotations.push({
11347 finalBounds: {
11348 x: getHorizontalCoordinateString(x),
11349 y: getVerticalCoordinateString(y),
11350 w: getHorizontalCoordinateString(x + w),
11351 h: getVerticalCoordinateString(y + h)
11352 },
11353 options: options,
11354 type: "link"
11355 });
11356 };
11357
11358 /**
11359 * Currently only supports single line text.
11360 * Returns the width of the text/link
11361 *
11362 * @name textWithLink
11363 * @function
11364 * @param {string} text
11365 * @param {number} x
11366 * @param {number} y
11367 * @param {Object} options
11368 * @returns {number} width the width of the text/link
11369 */
11370 jsPDFAPI.textWithLink = function(text, x, y, options) {
11371 var width = this.getTextWidth(text);
11372 var height = this.internal.getLineHeight() / this.internal.scaleFactor;
11373 this.text(text, x, y, options);
11374 //TODO We really need the text baseline height to do this correctly.
11375 // Or ability to draw text on top, bottom, center, or baseline.
11376 y += height * 0.2;
11377 //handle x position based on the align option
11378 if (options.align === "center") {
11379 x = x - width / 2; //since starting from center move the x position by half of text width
11380 }
11381 if (options.align === "right") {
11382 x = x - width;
11383 }
11384 this.link(x, y - height, width, height, options);
11385 return width;
11386 };
11387
11388 //TODO move into external library
11389 /**
11390 * @name getTextWidth
11391 * @function
11392 * @param {string} text
11393 * @returns {number} txtWidth
11394 */
11395 jsPDFAPI.getTextWidth = function(text) {
11396 var fontSize = this.internal.getFontSize();
11397 var txtWidth =
11398 (this.getStringUnitWidth(text) * fontSize) / this.internal.scaleFactor;
11399 return txtWidth;
11400 };
11401
11402 return this;
11403 })(jsPDF.API);
11404
11405 /**
11406 * @license
11407 * Copyright (c) 2017 Aras Abbasi
11408 *
11409 * Licensed under the MIT License.
11410 * http://opensource.org/licenses/mit-license
11411 */
11412
11413 /**
11414 * jsPDF arabic parser PlugIn
11415 *
11416 * @name arabic
11417 * @module
11418 */
11419 (function(jsPDFAPI) {
11420
11421 /**
11422 * Arabic shape substitutions: char code => (isolated, final, initial, medial).
11423 * Arabic Substition A
11424 */
11425 var arabicSubstitionA = {
11426 0x0621: [0xfe80], // ARABIC LETTER HAMZA
11427 0x0622: [0xfe81, 0xfe82], // ARABIC LETTER ALEF WITH MADDA ABOVE
11428 0x0623: [0xfe83, 0xfe84], // ARABIC LETTER ALEF WITH HAMZA ABOVE
11429 0x0624: [0xfe85, 0xfe86], // ARABIC LETTER WAW WITH HAMZA ABOVE
11430 0x0625: [0xfe87, 0xfe88], // ARABIC LETTER ALEF WITH HAMZA BELOW
11431 0x0626: [0xfe89, 0xfe8a, 0xfe8b, 0xfe8c], // ARABIC LETTER YEH WITH HAMZA ABOVE
11432 0x0627: [0xfe8d, 0xfe8e], // ARABIC LETTER ALEF
11433 0x0628: [0xfe8f, 0xfe90, 0xfe91, 0xfe92], // ARABIC LETTER BEH
11434 0x0629: [0xfe93, 0xfe94], // ARABIC LETTER TEH MARBUTA
11435 0x062a: [0xfe95, 0xfe96, 0xfe97, 0xfe98], // ARABIC LETTER TEH
11436 0x062b: [0xfe99, 0xfe9a, 0xfe9b, 0xfe9c], // ARABIC LETTER THEH
11437 0x062c: [0xfe9d, 0xfe9e, 0xfe9f, 0xfea0], // ARABIC LETTER JEEM
11438 0x062d: [0xfea1, 0xfea2, 0xfea3, 0xfea4], // ARABIC LETTER HAH
11439 0x062e: [0xfea5, 0xfea6, 0xfea7, 0xfea8], // ARABIC LETTER KHAH
11440 0x062f: [0xfea9, 0xfeaa], // ARABIC LETTER DAL
11441 0x0630: [0xfeab, 0xfeac], // ARABIC LETTER THAL
11442 0x0631: [0xfead, 0xfeae], // ARABIC LETTER REH
11443 0x0632: [0xfeaf, 0xfeb0], // ARABIC LETTER ZAIN
11444 0x0633: [0xfeb1, 0xfeb2, 0xfeb3, 0xfeb4], // ARABIC LETTER SEEN
11445 0x0634: [0xfeb5, 0xfeb6, 0xfeb7, 0xfeb8], // ARABIC LETTER SHEEN
11446 0x0635: [0xfeb9, 0xfeba, 0xfebb, 0xfebc], // ARABIC LETTER SAD
11447 0x0636: [0xfebd, 0xfebe, 0xfebf, 0xfec0], // ARABIC LETTER DAD
11448 0x0637: [0xfec1, 0xfec2, 0xfec3, 0xfec4], // ARABIC LETTER TAH
11449 0x0638: [0xfec5, 0xfec6, 0xfec7, 0xfec8], // ARABIC LETTER ZAH
11450 0x0639: [0xfec9, 0xfeca, 0xfecb, 0xfecc], // ARABIC LETTER AIN
11451 0x063a: [0xfecd, 0xfece, 0xfecf, 0xfed0], // ARABIC LETTER GHAIN
11452 0x0641: [0xfed1, 0xfed2, 0xfed3, 0xfed4], // ARABIC LETTER FEH
11453 0x0642: [0xfed5, 0xfed6, 0xfed7, 0xfed8], // ARABIC LETTER QAF
11454 0x0643: [0xfed9, 0xfeda, 0xfedb, 0xfedc], // ARABIC LETTER KAF
11455 0x0644: [0xfedd, 0xfede, 0xfedf, 0xfee0], // ARABIC LETTER LAM
11456 0x0645: [0xfee1, 0xfee2, 0xfee3, 0xfee4], // ARABIC LETTER MEEM
11457 0x0646: [0xfee5, 0xfee6, 0xfee7, 0xfee8], // ARABIC LETTER NOON
11458 0x0647: [0xfee9, 0xfeea, 0xfeeb, 0xfeec], // ARABIC LETTER HEH
11459 0x0648: [0xfeed, 0xfeee], // ARABIC LETTER WAW
11460 0x0649: [0xfeef, 0xfef0, 64488, 64489], // ARABIC LETTER ALEF MAKSURA
11461 0x064a: [0xfef1, 0xfef2, 0xfef3, 0xfef4], // ARABIC LETTER YEH
11462 0x0671: [0xfb50, 0xfb51], // ARABIC LETTER ALEF WASLA
11463 0x0677: [0xfbdd], // ARABIC LETTER U WITH HAMZA ABOVE
11464 0x0679: [0xfb66, 0xfb67, 0xfb68, 0xfb69], // ARABIC LETTER TTEH
11465 0x067a: [0xfb5e, 0xfb5f, 0xfb60, 0xfb61], // ARABIC LETTER TTEHEH
11466 0x067b: [0xfb52, 0xfb53, 0xfb54, 0xfb55], // ARABIC LETTER BEEH
11467 0x067e: [0xfb56, 0xfb57, 0xfb58, 0xfb59], // ARABIC LETTER PEH
11468 0x067f: [0xfb62, 0xfb63, 0xfb64, 0xfb65], // ARABIC LETTER TEHEH
11469 0x0680: [0xfb5a, 0xfb5b, 0xfb5c, 0xfb5d], // ARABIC LETTER BEHEH
11470 0x0683: [0xfb76, 0xfb77, 0xfb78, 0xfb79], // ARABIC LETTER NYEH
11471 0x0684: [0xfb72, 0xfb73, 0xfb74, 0xfb75], // ARABIC LETTER DYEH
11472 0x0686: [0xfb7a, 0xfb7b, 0xfb7c, 0xfb7d], // ARABIC LETTER TCHEH
11473 0x0687: [0xfb7e, 0xfb7f, 0xfb80, 0xfb81], // ARABIC LETTER TCHEHEH
11474 0x0688: [0xfb88, 0xfb89], // ARABIC LETTER DDAL
11475 0x068c: [0xfb84, 0xfb85], // ARABIC LETTER DAHAL
11476 0x068d: [0xfb82, 0xfb83], // ARABIC LETTER DDAHAL
11477 0x068e: [0xfb86, 0xfb87], // ARABIC LETTER DUL
11478 0x0691: [0xfb8c, 0xfb8d], // ARABIC LETTER RREH
11479 0x0698: [0xfb8a, 0xfb8b], // ARABIC LETTER JEH
11480 0x06a4: [0xfb6a, 0xfb6b, 0xfb6c, 0xfb6d], // ARABIC LETTER VEH
11481 0x06a6: [0xfb6e, 0xfb6f, 0xfb70, 0xfb71], // ARABIC LETTER PEHEH
11482 0x06a9: [0xfb8e, 0xfb8f, 0xfb90, 0xfb91], // ARABIC LETTER KEHEH
11483 0x06ad: [0xfbd3, 0xfbd4, 0xfbd5, 0xfbd6], // ARABIC LETTER NG
11484 0x06af: [0xfb92, 0xfb93, 0xfb94, 0xfb95], // ARABIC LETTER GAF
11485 0x06b1: [0xfb9a, 0xfb9b, 0xfb9c, 0xfb9d], // ARABIC LETTER NGOEH
11486 0x06b3: [0xfb96, 0xfb97, 0xfb98, 0xfb99], // ARABIC LETTER GUEH
11487 0x06ba: [0xfb9e, 0xfb9f], // ARABIC LETTER NOON GHUNNA
11488 0x06bb: [0xfba0, 0xfba1, 0xfba2, 0xfba3], // ARABIC LETTER RNOON
11489 0x06be: [0xfbaa, 0xfbab, 0xfbac, 0xfbad], // ARABIC LETTER HEH DOACHASHMEE
11490 0x06c0: [0xfba4, 0xfba5], // ARABIC LETTER HEH WITH YEH ABOVE
11491 0x06c1: [0xfba6, 0xfba7, 0xfba8, 0xfba9], // ARABIC LETTER HEH GOAL
11492 0x06c5: [0xfbe0, 0xfbe1], // ARABIC LETTER KIRGHIZ OE
11493 0x06c6: [0xfbd9, 0xfbda], // ARABIC LETTER OE
11494 0x06c7: [0xfbd7, 0xfbd8], // ARABIC LETTER U
11495 0x06c8: [0xfbdb, 0xfbdc], // ARABIC LETTER YU
11496 0x06c9: [0xfbe2, 0xfbe3], // ARABIC LETTER KIRGHIZ YU
11497 0x06cb: [0xfbde, 0xfbdf], // ARABIC LETTER VE
11498 0x06cc: [0xfbfc, 0xfbfd, 0xfbfe, 0xfbff], // ARABIC LETTER FARSI YEH
11499 0x06d0: [0xfbe4, 0xfbe5, 0xfbe6, 0xfbe7], //ARABIC LETTER E
11500 0x06d2: [0xfbae, 0xfbaf], // ARABIC LETTER YEH BARREE
11501 0x06d3: [0xfbb0, 0xfbb1] // ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
11502 };
11503
11504 /*
11505 var ligaturesSubstitutionA = {
11506 0xFBEA: []// ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM
11507 };
11508 */
11509
11510 var ligatures = {
11511 0xfedf: {
11512 0xfe82: 0xfef5, // ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
11513 0xfe84: 0xfef7, // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
11514 0xfe88: 0xfef9, // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM
11515 0xfe8e: 0xfefb // ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
11516 },
11517 0xfee0: {
11518 0xfe82: 0xfef6, // ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
11519 0xfe84: 0xfef8, // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
11520 0xfe88: 0xfefa, // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM
11521 0xfe8e: 0xfefc // ARABIC LIGATURE LAM WITH ALEF FINAL FORM
11522 },
11523 0xfe8d: { 0xfedf: { 0xfee0: { 0xfeea: 0xfdf2 } } }, // ALLAH
11524 0x0651: {
11525 0x064c: 0xfc5e, // Shadda + Dammatan
11526 0x064d: 0xfc5f, // Shadda + Kasratan
11527 0x064e: 0xfc60, // Shadda + Fatha
11528 0x064f: 0xfc61, // Shadda + Damma
11529 0x0650: 0xfc62 // Shadda + Kasra
11530 }
11531 };
11532
11533 var arabic_diacritics = {
11534 1612: 64606, // Shadda + Dammatan
11535 1613: 64607, // Shadda + Kasratan
11536 1614: 64608, // Shadda + Fatha
11537 1615: 64609, // Shadda + Damma
11538 1616: 64610 // Shadda + Kasra
11539 };
11540
11541 var alfletter = [1570, 1571, 1573, 1575];
11542
11543 var noChangeInForm = -1;
11544 var isolatedForm = 0;
11545 var finalForm = 1;
11546 var initialForm = 2;
11547 var medialForm = 3;
11548
11549 jsPDFAPI.__arabicParser__ = {};
11550
11551 //private
11552 var isInArabicSubstitutionA = (jsPDFAPI.__arabicParser__.isInArabicSubstitutionA = function(
11553 letter
11554 ) {
11555 return typeof arabicSubstitionA[letter.charCodeAt(0)] !== "undefined";
11556 });
11557
11558 var isArabicLetter = (jsPDFAPI.__arabicParser__.isArabicLetter = function(
11559 letter
11560 ) {
11561 return (
11562 typeof letter === "string" &&
11563 /^[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]+$/.test(
11564 letter
11565 )
11566 );
11567 });
11568
11569 var isArabicEndLetter = (jsPDFAPI.__arabicParser__.isArabicEndLetter = function(
11570 letter
11571 ) {
11572 return (
11573 isArabicLetter(letter) &&
11574 isInArabicSubstitutionA(letter) &&
11575 arabicSubstitionA[letter.charCodeAt(0)].length <= 2
11576 );
11577 });
11578
11579 var isArabicAlfLetter = (jsPDFAPI.__arabicParser__.isArabicAlfLetter = function(
11580 letter
11581 ) {
11582 return (
11583 isArabicLetter(letter) && alfletter.indexOf(letter.charCodeAt(0)) >= 0
11584 );
11585 });
11586
11587 jsPDFAPI.__arabicParser__.arabicLetterHasIsolatedForm = function(letter) {
11588 return (
11589 isArabicLetter(letter) &&
11590 isInArabicSubstitutionA(letter) &&
11591 arabicSubstitionA[letter.charCodeAt(0)].length >= 1
11592 );
11593 };
11594
11595 var arabicLetterHasFinalForm = (jsPDFAPI.__arabicParser__.arabicLetterHasFinalForm = function(
11596 letter
11597 ) {
11598 return (
11599 isArabicLetter(letter) &&
11600 isInArabicSubstitutionA(letter) &&
11601 arabicSubstitionA[letter.charCodeAt(0)].length >= 2
11602 );
11603 });
11604
11605 jsPDFAPI.__arabicParser__.arabicLetterHasInitialForm = function(letter) {
11606 return (
11607 isArabicLetter(letter) &&
11608 isInArabicSubstitutionA(letter) &&
11609 arabicSubstitionA[letter.charCodeAt(0)].length >= 3
11610 );
11611 };
11612
11613 var arabicLetterHasMedialForm = (jsPDFAPI.__arabicParser__.arabicLetterHasMedialForm = function(
11614 letter
11615 ) {
11616 return (
11617 isArabicLetter(letter) &&
11618 isInArabicSubstitutionA(letter) &&
11619 arabicSubstitionA[letter.charCodeAt(0)].length == 4
11620 );
11621 });
11622
11623 var resolveLigatures = (jsPDFAPI.__arabicParser__.resolveLigatures = function(
11624 letters
11625 ) {
11626 var i = 0;
11627 var tmpLigatures = ligatures;
11628 var result = "";
11629 var effectedLetters = 0;
11630
11631 for (i = 0; i < letters.length; i += 1) {
11632 if (typeof tmpLigatures[letters.charCodeAt(i)] !== "undefined") {
11633 effectedLetters++;
11634 tmpLigatures = tmpLigatures[letters.charCodeAt(i)];
11635
11636 if (typeof tmpLigatures === "number") {
11637 result += String.fromCharCode(tmpLigatures);
11638 tmpLigatures = ligatures;
11639 effectedLetters = 0;
11640 }
11641 if (i === letters.length - 1) {
11642 tmpLigatures = ligatures;
11643 result += letters.charAt(i - (effectedLetters - 1));
11644 i = i - (effectedLetters - 1);
11645 effectedLetters = 0;
11646 }
11647 } else {
11648 tmpLigatures = ligatures;
11649 result += letters.charAt(i - effectedLetters);
11650 i = i - effectedLetters;
11651 effectedLetters = 0;
11652 }
11653 }
11654
11655 return result;
11656 });
11657
11658 jsPDFAPI.__arabicParser__.isArabicDiacritic = function(letter) {
11659 return (
11660 letter !== undefined &&
11661 arabic_diacritics[letter.charCodeAt(0)] !== undefined
11662 );
11663 };
11664
11665 var getCorrectForm = (jsPDFAPI.__arabicParser__.getCorrectForm = function(
11666 currentChar,
11667 beforeChar,
11668 nextChar
11669 ) {
11670 if (!isArabicLetter(currentChar)) {
11671 return -1;
11672 }
11673
11674 if (isInArabicSubstitutionA(currentChar) === false) {
11675 return noChangeInForm;
11676 }
11677 if (
11678 !arabicLetterHasFinalForm(currentChar) ||
11679 (!isArabicLetter(beforeChar) && !isArabicLetter(nextChar)) ||
11680 (!isArabicLetter(nextChar) && isArabicEndLetter(beforeChar)) ||
11681 (isArabicEndLetter(currentChar) && !isArabicLetter(beforeChar)) ||
11682 (isArabicEndLetter(currentChar) && isArabicAlfLetter(beforeChar)) ||
11683 (isArabicEndLetter(currentChar) && isArabicEndLetter(beforeChar))
11684 ) {
11685 return isolatedForm;
11686 }
11687
11688 if (
11689 arabicLetterHasMedialForm(currentChar) &&
11690 isArabicLetter(beforeChar) &&
11691 !isArabicEndLetter(beforeChar) &&
11692 isArabicLetter(nextChar) &&
11693 arabicLetterHasFinalForm(nextChar)
11694 ) {
11695 return medialForm;
11696 }
11697
11698 if (isArabicEndLetter(currentChar) || !isArabicLetter(nextChar)) {
11699 return finalForm;
11700 }
11701 return initialForm;
11702 });
11703
11704 /**
11705 * @name processArabic
11706 * @function
11707 * @param {string} text
11708 * @returns {string}
11709 */
11710 var parseArabic = function(text) {
11711 text = text || "";
11712
11713 var result = "";
11714 var i = 0;
11715 var j = 0;
11716 var position = 0;
11717 var currentLetter = "";
11718 var prevLetter = "";
11719 var nextLetter = "";
11720
11721 var words = text.split("\\s+");
11722 var newWords = [];
11723 for (i = 0; i < words.length; i += 1) {
11724 newWords.push("");
11725 for (j = 0; j < words[i].length; j += 1) {
11726 currentLetter = words[i][j];
11727 prevLetter = words[i][j - 1];
11728 nextLetter = words[i][j + 1];
11729 if (isArabicLetter(currentLetter)) {
11730 position = getCorrectForm(currentLetter, prevLetter, nextLetter);
11731 if (position !== -1) {
11732 newWords[i] += String.fromCharCode(
11733 arabicSubstitionA[currentLetter.charCodeAt(0)][position]
11734 );
11735 } else {
11736 newWords[i] += currentLetter;
11737 }
11738 } else {
11739 newWords[i] += currentLetter;
11740 }
11741 }
11742
11743 newWords[i] = resolveLigatures(newWords[i]);
11744 }
11745 result = newWords.join(" ");
11746
11747 return result;
11748 };
11749
11750 var processArabic = (jsPDFAPI.__arabicParser__.processArabic = jsPDFAPI.processArabic = function() {
11751 var text =
11752 typeof arguments[0] === "string" ? arguments[0] : arguments[0].text;
11753 var tmpText = [];
11754 var result;
11755
11756 if (Array.isArray(text)) {
11757 var i = 0;
11758 tmpText = [];
11759 for (i = 0; i < text.length; i += 1) {
11760 if (Array.isArray(text[i])) {
11761 tmpText.push([parseArabic(text[i][0]), text[i][1], text[i][2]]);
11762 } else {
11763 tmpText.push([parseArabic(text[i])]);
11764 }
11765 }
11766 result = tmpText;
11767 } else {
11768 result = parseArabic(text);
11769 }
11770 if (typeof arguments[0] === "string") {
11771 return result;
11772 } else {
11773 arguments[0].text = result;
11774 return arguments[0];
11775 }
11776 });
11777
11778 jsPDFAPI.events.push(["preProcessText", processArabic]);
11779 })(jsPDF.API);
11780
11781 /** @license
11782 * jsPDF Autoprint Plugin
11783 *
11784 * Licensed under the MIT License.
11785 * http://opensource.org/licenses/mit-license
11786 */
11787
11788 /**
11789 * @name autoprint
11790 * @module
11791 */
11792 (function(jsPDFAPI) {
11793
11794 /**
11795 * Makes the PDF automatically open the print-Dialog when opened in a PDF-viewer.
11796 *
11797 * @name autoPrint
11798 * @function
11799 * @param {Object} options (optional) Set the attribute variant to 'non-conform' (default) or 'javascript' to activate different methods of automatic printing when opening in a PDF-viewer .
11800 * @returns {jsPDF}
11801 * @example
11802 * var doc = new jsPDF();
11803 * doc.text(10, 10, 'This is a test');
11804 * doc.autoPrint({variant: 'non-conform'});
11805 * doc.save('autoprint.pdf');
11806 */
11807 jsPDFAPI.autoPrint = function(options) {
11808 var refAutoPrintTag;
11809 options = options || {};
11810 options.variant = options.variant || "non-conform";
11811
11812 switch (options.variant) {
11813 case "javascript":
11814 //https://github.com/Rob--W/pdf.js/commit/c676ecb5a0f54677b9f3340c3ef2cf42225453bb
11815 this.addJS("print({});");
11816 break;
11817 case "non-conform":
11818 default:
11819 this.internal.events.subscribe("postPutResources", function() {
11820 refAutoPrintTag = this.internal.newObject();
11821 this.internal.out("<<");
11822 this.internal.out("/S /Named");
11823 this.internal.out("/Type /Action");
11824 this.internal.out("/N /Print");
11825 this.internal.out(">>");
11826 this.internal.out("endobj");
11827 });
11828
11829 this.internal.events.subscribe("putCatalog", function() {
11830 this.internal.out("/OpenAction " + refAutoPrintTag + " 0 R");
11831 });
11832 break;
11833 }
11834 return this;
11835 };
11836 })(jsPDF.API);
11837
11838 /**
11839 * @license
11840 * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv
11841 *
11842 * Licensed under the MIT License.
11843 * http://opensource.org/licenses/mit-license
11844 */
11845
11846 /**
11847 * jsPDF Canvas PlugIn
11848 * This plugin mimics the HTML5 Canvas
11849 *
11850 * The goal is to provide a way for current canvas users to print directly to a PDF.
11851 * @name canvas
11852 * @module
11853 */
11854 (function(jsPDFAPI) {
11855
11856 /**
11857 * @class Canvas
11858 * @classdesc A Canvas Wrapper for jsPDF
11859 */
11860 var Canvas = function() {
11861 var jsPdfInstance = undefined;
11862 Object.defineProperty(this, "pdf", {
11863 get: function() {
11864 return jsPdfInstance;
11865 },
11866 set: function(value) {
11867 jsPdfInstance = value;
11868 }
11869 });
11870
11871 var _width = 150;
11872 /**
11873 * The height property is a positive integer reflecting the height HTML attribute of the <canvas> element interpreted in CSS pixels. When the attribute is not specified, or if it is set to an invalid value, like a negative, the default value of 150 is used.
11874 * This is one of the two properties, the other being width, that controls the size of the canvas.
11875 *
11876 * @name width
11877 */
11878 Object.defineProperty(this, "width", {
11879 get: function() {
11880 return _width;
11881 },
11882 set: function(value) {
11883 if (isNaN(value) || Number.isInteger(value) === false || value < 0) {
11884 _width = 150;
11885 } else {
11886 _width = value;
11887 }
11888 if (this.getContext("2d").pageWrapXEnabled) {
11889 this.getContext("2d").pageWrapX = _width + 1;
11890 }
11891 }
11892 });
11893
11894 var _height = 300;
11895 /**
11896 * The width property is a positive integer reflecting the width HTML attribute of the <canvas> element interpreted in CSS pixels. When the attribute is not specified, or if it is set to an invalid value, like a negative, the default value of 300 is used.
11897 * This is one of the two properties, the other being height, that controls the size of the canvas.
11898 *
11899 * @name height
11900 */
11901 Object.defineProperty(this, "height", {
11902 get: function() {
11903 return _height;
11904 },
11905 set: function(value) {
11906 if (isNaN(value) || Number.isInteger(value) === false || value < 0) {
11907 _height = 300;
11908 } else {
11909 _height = value;
11910 }
11911 if (this.getContext("2d").pageWrapYEnabled) {
11912 this.getContext("2d").pageWrapY = _height + 1;
11913 }
11914 }
11915 });
11916
11917 var _childNodes = [];
11918 Object.defineProperty(this, "childNodes", {
11919 get: function() {
11920 return _childNodes;
11921 },
11922 set: function(value) {
11923 _childNodes = value;
11924 }
11925 });
11926
11927 var _style = {};
11928 Object.defineProperty(this, "style", {
11929 get: function() {
11930 return _style;
11931 },
11932 set: function(value) {
11933 _style = value;
11934 }
11935 });
11936
11937 Object.defineProperty(this, "parentNode", {});
11938 };
11939
11940 /**
11941 * The getContext() method returns a drawing context on the canvas, or null if the context identifier is not supported.
11942 *
11943 * @name getContext
11944 * @function
11945 * @param {string} contextType Is a String containing the context identifier defining the drawing context associated to the canvas. Possible value is "2d", leading to the creation of a Context2D object representing a two-dimensional rendering context.
11946 * @param {object} contextAttributes
11947 */
11948 Canvas.prototype.getContext = function(contextType, contextAttributes) {
11949 contextType = contextType || "2d";
11950 var key;
11951
11952 if (contextType !== "2d") {
11953 return null;
11954 }
11955 for (key in contextAttributes) {
11956 if (this.pdf.context2d.hasOwnProperty(key)) {
11957 this.pdf.context2d[key] = contextAttributes[key];
11958 }
11959 }
11960 this.pdf.context2d._canvas = this;
11961 return this.pdf.context2d;
11962 };
11963
11964 /**
11965 * The toDataURL() method is just a stub to throw an error if accidently called.
11966 *
11967 * @name toDataURL
11968 * @function
11969 */
11970 Canvas.prototype.toDataURL = function() {
11971 throw new Error("toDataURL is not implemented.");
11972 };
11973
11974 jsPDFAPI.events.push([
11975 "initialized",
11976 function() {
11977 this.canvas = new Canvas();
11978 this.canvas.pdf = this;
11979 }
11980 ]);
11981
11982 return this;
11983 })(jsPDF.API);
11984
11985 /**
11986 * @license
11987 * ====================================================================
11988 * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
11989 * 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br
11990 * 2013 Lee Driscoll, https://github.com/lsdriscoll
11991 * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
11992 * 2014 James Hall, james@parall.ax
11993 * 2014 Diego Casorran, https://github.com/diegocr
11994 *
11995 * Permission is hereby granted, free of charge, to any person obtaining
11996 * a copy of this software and associated documentation files (the
11997 * "Software"), to deal in the Software without restriction, including
11998 * without limitation the rights to use, copy, modify, merge, publish,
11999 * distribute, sublicense, and/or sell copies of the Software, and to
12000 * permit persons to whom the Software is furnished to do so, subject to
12001 * the following conditions:
12002 *
12003 * The above copyright notice and this permission notice shall be
12004 * included in all copies or substantial portions of the Software.
12005 *
12006 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12007 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12008 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
12009 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
12010 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
12011 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
12012 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12013 * ====================================================================
12014 */
12015
12016 /**
12017 * @name cell
12018 * @module
12019 */
12020 (function(jsPDFAPI) {
12021
12022 var NO_MARGINS = { left: 0, top: 0, bottom: 0, right: 0 };
12023
12024 var px2pt = (0.264583 * 72) / 25.4;
12025 var printingHeaderRow = false;
12026
12027 var _initialize = function() {
12028 if (typeof this.internal.__cell__ === "undefined") {
12029 this.internal.__cell__ = {};
12030 this.internal.__cell__.padding = 3;
12031 this.internal.__cell__.headerFunction = undefined;
12032 this.internal.__cell__.margins = Object.assign({}, NO_MARGINS);
12033 this.internal.__cell__.margins.width = this.getPageWidth();
12034 _reset.call(this);
12035 }
12036 };
12037
12038 var _reset = function() {
12039 this.internal.__cell__.lastCell = new Cell();
12040 this.internal.__cell__.pages = 1;
12041 };
12042
12043 var Cell = function() {
12044 var _x = arguments[0];
12045 Object.defineProperty(this, "x", {
12046 enumerable: true,
12047 get: function() {
12048 return _x;
12049 },
12050 set: function(value) {
12051 _x = value;
12052 }
12053 });
12054 var _y = arguments[1];
12055 Object.defineProperty(this, "y", {
12056 enumerable: true,
12057 get: function() {
12058 return _y;
12059 },
12060 set: function(value) {
12061 _y = value;
12062 }
12063 });
12064 var _width = arguments[2];
12065 Object.defineProperty(this, "width", {
12066 enumerable: true,
12067 get: function() {
12068 return _width;
12069 },
12070 set: function(value) {
12071 _width = value;
12072 }
12073 });
12074 var _height = arguments[3];
12075 Object.defineProperty(this, "height", {
12076 enumerable: true,
12077 get: function() {
12078 return _height;
12079 },
12080 set: function(value) {
12081 _height = value;
12082 }
12083 });
12084 var _text = arguments[4];
12085 Object.defineProperty(this, "text", {
12086 enumerable: true,
12087 get: function() {
12088 return _text;
12089 },
12090 set: function(value) {
12091 _text = value;
12092 }
12093 });
12094 var _lineNumber = arguments[5];
12095 Object.defineProperty(this, "lineNumber", {
12096 enumerable: true,
12097 get: function() {
12098 return _lineNumber;
12099 },
12100 set: function(value) {
12101 _lineNumber = value;
12102 }
12103 });
12104 var _align = arguments[6];
12105 Object.defineProperty(this, "align", {
12106 enumerable: true,
12107 get: function() {
12108 return _align;
12109 },
12110 set: function(value) {
12111 _align = value;
12112 }
12113 });
12114
12115 return this;
12116 };
12117
12118 Cell.prototype.clone = function() {
12119 return new Cell(
12120 this.x,
12121 this.y,
12122 this.width,
12123 this.height,
12124 this.text,
12125 this.lineNumber,
12126 this.align
12127 );
12128 };
12129
12130 Cell.prototype.toArray = function() {
12131 return [
12132 this.x,
12133 this.y,
12134 this.width,
12135 this.height,
12136 this.text,
12137 this.lineNumber,
12138 this.align
12139 ];
12140 };
12141
12142 /**
12143 * @name setHeaderFunction
12144 * @function
12145 * @param {function} func
12146 */
12147 jsPDFAPI.setHeaderFunction = function(func) {
12148 _initialize.call(this);
12149 this.internal.__cell__.headerFunction =
12150 typeof func === "function" ? func : undefined;
12151 return this;
12152 };
12153
12154 /**
12155 * @name getTextDimensions
12156 * @function
12157 * @param {string} txt
12158 * @returns {Object} dimensions
12159 */
12160 jsPDFAPI.getTextDimensions = function(text, options) {
12161 _initialize.call(this);
12162 options = options || {};
12163 var fontSize = options.fontSize || this.getFontSize();
12164 var font = options.font || this.getFont();
12165 var scaleFactor = options.scaleFactor || this.internal.scaleFactor;
12166 var width = 0;
12167 var amountOfLines = 0;
12168 var height = 0;
12169 var tempWidth = 0;
12170
12171 if (!Array.isArray(text) && typeof text !== "string") {
12172 if (typeof text === "number") {
12173 text = String(text);
12174 } else {
12175 throw new Error(
12176 "getTextDimensions expects text-parameter to be of type String or type Number or an Array of Strings."
12177 );
12178 }
12179 }
12180
12181 const maxWidth = options.maxWidth;
12182 if (maxWidth > 0) {
12183 if (typeof text === "string") {
12184 text = this.splitTextToSize(text, maxWidth);
12185 } else if (Object.prototype.toString.call(text) === "[object Array]") {
12186 text = text.reduce(function(acc, textLine) {
12187 return acc.concat(scope.splitTextToSize(textLine, maxWidth));
12188 }, []);
12189 }
12190 } else {
12191 // Without the else clause, it will not work if you do not pass along maxWidth
12192 text = Array.isArray(text) ? text : [text];
12193 }
12194
12195 for (var i = 0; i < text.length; i++) {
12196 tempWidth = this.getStringUnitWidth(text[i], { font: font }) * fontSize;
12197 if (width < tempWidth) {
12198 width = tempWidth;
12199 }
12200 }
12201
12202 if (width !== 0) {
12203 amountOfLines = text.length;
12204 }
12205
12206 width = width / scaleFactor;
12207 height = Math.max(
12208 (amountOfLines * fontSize * this.getLineHeightFactor() -
12209 fontSize * (this.getLineHeightFactor() - 1)) /
12210 scaleFactor,
12211 0
12212 );
12213 return { w: width, h: height };
12214 };
12215
12216 /**
12217 * @name cellAddPage
12218 * @function
12219 */
12220 jsPDFAPI.cellAddPage = function() {
12221 _initialize.call(this);
12222
12223 this.addPage();
12224
12225 var margins = this.internal.__cell__.margins || NO_MARGINS;
12226 this.internal.__cell__.lastCell = new Cell(
12227 margins.left,
12228 margins.top,
12229 undefined,
12230 undefined
12231 );
12232 this.internal.__cell__.pages += 1;
12233
12234 return this;
12235 };
12236
12237 /**
12238 * @name cell
12239 * @function
12240 * @param {number} x
12241 * @param {number} y
12242 * @param {number} width
12243 * @param {number} height
12244 * @param {string} text
12245 * @param {number} lineNumber lineNumber
12246 * @param {string} align
12247 * @return {jsPDF} jsPDF-instance
12248 */
12249 var cell = (jsPDFAPI.cell = function() {
12250 var currentCell;
12251
12252 if (arguments[0] instanceof Cell) {
12253 currentCell = arguments[0];
12254 } else {
12255 currentCell = new Cell(
12256 arguments[0],
12257 arguments[1],
12258 arguments[2],
12259 arguments[3],
12260 arguments[4],
12261 arguments[5]
12262 );
12263 }
12264 _initialize.call(this);
12265 var lastCell = this.internal.__cell__.lastCell;
12266 var padding = this.internal.__cell__.padding;
12267 var margins = this.internal.__cell__.margins || NO_MARGINS;
12268 var tableHeaderRow = this.internal.__cell__.tableHeaderRow;
12269 var printHeaders = this.internal.__cell__.printHeaders;
12270 // If this is not the first cell, we must change its position
12271 if (typeof lastCell.lineNumber !== "undefined") {
12272 if (lastCell.lineNumber === currentCell.lineNumber) {
12273 //Same line
12274 currentCell.x = (lastCell.x || 0) + (lastCell.width || 0);
12275 currentCell.y = lastCell.y || 0;
12276 } else {
12277 //New line
12278 if (
12279 lastCell.y + lastCell.height + currentCell.height + margins.bottom >
12280 this.getPageHeight()
12281 ) {
12282 this.cellAddPage();
12283 currentCell.y = margins.top;
12284 if (printHeaders && tableHeaderRow) {
12285 this.printHeaderRow(currentCell.lineNumber, true);
12286 currentCell.y += tableHeaderRow[0].height;
12287 }
12288 } else {
12289 currentCell.y = lastCell.y + lastCell.height || currentCell.y;
12290 }
12291 }
12292 }
12293
12294 if (typeof currentCell.text[0] !== "undefined") {
12295 this.rect(
12296 currentCell.x,
12297 currentCell.y,
12298 currentCell.width,
12299 currentCell.height,
12300 printingHeaderRow === true ? "FD" : undefined
12301 );
12302 if (currentCell.align === "right") {
12303 this.text(
12304 currentCell.text,
12305 currentCell.x + currentCell.width - padding,
12306 currentCell.y + padding,
12307 { align: "right", baseline: "top" }
12308 );
12309 } else if (currentCell.align === "center") {
12310 this.text(
12311 currentCell.text,
12312 currentCell.x + currentCell.width / 2,
12313 currentCell.y + padding,
12314 {
12315 align: "center",
12316 baseline: "top",
12317 maxWidth: currentCell.width - padding - padding
12318 }
12319 );
12320 } else {
12321 this.text(
12322 currentCell.text,
12323 currentCell.x + padding,
12324 currentCell.y + padding,
12325 {
12326 align: "left",
12327 baseline: "top",
12328 maxWidth: currentCell.width - padding - padding
12329 }
12330 );
12331 }
12332 }
12333 this.internal.__cell__.lastCell = currentCell;
12334 return this;
12335 });
12336
12337 /**
12338 * Create a table from a set of data.
12339 * @name table
12340 * @function
12341 * @param {Integer} [x] : left-position for top-left corner of table
12342 * @param {Integer} [y] top-position for top-left corner of table
12343 * @param {Object[]} [data] An array of objects containing key-value pairs corresponding to a row of data.
12344 * @param {String[]} [headers] Omit or null to auto-generate headers at a performance cost
12345
12346 * @param {Object} [config.printHeaders] True to print column headers at the top of every page
12347 * @param {Object} [config.autoSize] True to dynamically set the column widths to match the widest cell value
12348 * @param {Object} [config.margins] margin values for left, top, bottom, and width
12349 * @param {Object} [config.fontSize] Integer fontSize to use (optional)
12350 * @param {Object} [config.padding] cell-padding in pt to use (optional)
12351 * @param {Object} [config.headerBackgroundColor] default is #c8c8c8 (optional)
12352 * @returns {jsPDF} jsPDF-instance
12353 */
12354
12355 jsPDFAPI.table = function(x, y, data, headers, config) {
12356 _initialize.call(this);
12357 if (!data) {
12358 throw new Error("No data for PDF table.");
12359 }
12360
12361 config = config || {};
12362
12363 var headerNames = [],
12364 headerLabels = [],
12365 headerAligns = [],
12366 i,
12367 columnMatrix = {},
12368 columnWidths = {},
12369 column,
12370 columnMinWidths = [],
12371 j,
12372 tableHeaderConfigs = [],
12373 //set up defaults. If a value is provided in config, defaults will be overwritten:
12374 autoSize = config.autoSize || false,
12375 printHeaders = config.printHeaders === false ? false : true,
12376 fontSize =
12377 config.css && typeof config.css["font-size"] !== "undefined"
12378 ? config.css["font-size"] * 16
12379 : config.fontSize || 12,
12380 margins =
12381 config.margins ||
12382 Object.assign({ width: this.getPageWidth() }, NO_MARGINS),
12383 padding = typeof config.padding === "number" ? config.padding : 3,
12384 headerBackgroundColor = config.headerBackgroundColor || "#c8c8c8";
12385
12386 _reset.call(this);
12387
12388 this.internal.__cell__.printHeaders = printHeaders;
12389 this.internal.__cell__.margins = margins;
12390 this.internal.__cell__.table_font_size = fontSize;
12391 this.internal.__cell__.padding = padding;
12392 this.internal.__cell__.headerBackgroundColor = headerBackgroundColor;
12393 this.setFontSize(fontSize);
12394
12395 // Set header values
12396 if (headers === undefined || headers === null) {
12397 // No headers defined so we derive from data
12398 headerNames = Object.keys(data[0]);
12399 headerLabels = headerNames;
12400 headerAligns = headerNames.map(function() {
12401 return "left";
12402 });
12403 } else if (Array.isArray(headers) && typeof headers[0] === "object") {
12404 headerNames = headers.map(function(header) {
12405 return header.name;
12406 });
12407 headerLabels = headers.map(function(header) {
12408 return header.prompt || header.name || "";
12409 });
12410 headerAligns = headers.map(function(header) {
12411 return header.align || "left";
12412 });
12413 // Split header configs into names and prompts
12414 for (i = 0; i < headers.length; i += 1) {
12415 columnWidths[headers[i].name] = headers[i].width * px2pt;
12416 }
12417 } else if (Array.isArray(headers) && typeof headers[0] === "string") {
12418 headerNames = headers;
12419 headerLabels = headerNames;
12420 headerAligns = headerNames.map(function() {
12421 return "left";
12422 });
12423 }
12424
12425 if (autoSize) {
12426 var headerName;
12427 for (i = 0; i < headerNames.length; i += 1) {
12428 headerName = headerNames[i];
12429
12430 // Create a matrix of columns e.g., {column_title: [row1_Record, row2_Record]}
12431
12432 columnMatrix[headerName] = data.map(function(rec) {
12433 return rec[headerName];
12434 });
12435
12436 // get header width
12437 this.setFont(undefined, "bold");
12438 columnMinWidths.push(
12439 this.getTextDimensions(headerLabels[i], {
12440 fontSize: this.internal.__cell__.table_font_size,
12441 scaleFactor: this.internal.scaleFactor
12442 }).w
12443 );
12444 column = columnMatrix[headerName];
12445
12446 // get cell widths
12447 this.setFont(undefined, "normal");
12448 for (j = 0; j < column.length; j += 1) {
12449 columnMinWidths.push(
12450 this.getTextDimensions(column[j], {
12451 fontSize: this.internal.__cell__.table_font_size,
12452 scaleFactor: this.internal.scaleFactor
12453 }).w
12454 );
12455 }
12456
12457 // get final column width
12458 columnWidths[headerName] =
12459 Math.max.apply(null, columnMinWidths) + padding + padding;
12460
12461 //have to reset
12462 columnMinWidths = [];
12463 }
12464 }
12465
12466 // -- Construct the table
12467
12468 if (printHeaders) {
12469 var row = {};
12470 for (i = 0; i < headerNames.length; i += 1) {
12471 row[headerNames[i]] = {};
12472 row[headerNames[i]].text = headerLabels[i];
12473 row[headerNames[i]].align = headerAligns[i];
12474 }
12475
12476 var rowHeight = calculateLineHeight.call(this, row, columnWidths);
12477
12478 // Construct the header row
12479 tableHeaderConfigs = headerNames.map(function(value) {
12480 return new Cell(
12481 x,
12482 y,
12483 columnWidths[value],
12484 rowHeight,
12485 row[value].text,
12486 undefined,
12487 row[value].align
12488 );
12489 });
12490
12491 // Store the table header config
12492 this.setTableHeaderRow(tableHeaderConfigs);
12493
12494 // Print the header for the start of the table
12495 this.printHeaderRow(1, false);
12496 }
12497
12498 // Construct the data rows
12499
12500 var align = headers.reduce(function(pv, cv) {
12501 pv[cv.name] = cv.align;
12502 return pv;
12503 }, {});
12504 for (i = 0; i < data.length; i += 1) {
12505 var lineHeight = calculateLineHeight.call(this, data[i], columnWidths);
12506
12507 for (j = 0; j < headerNames.length; j += 1) {
12508 cell.call(
12509 this,
12510 new Cell(
12511 x,
12512 y,
12513 columnWidths[headerNames[j]],
12514 lineHeight,
12515 data[i][headerNames[j]],
12516 i + 2,
12517 align[headerNames[j]]
12518 )
12519 );
12520 }
12521 }
12522 this.internal.__cell__.table_x = x;
12523 this.internal.__cell__.table_y = y;
12524 return this;
12525 };
12526
12527 /**
12528 * Calculate the height for containing the highest column
12529 *
12530 * @name calculateLineHeight
12531 * @function
12532 * @param {Object[]} model is the line of data we want to calculate the height of
12533 * @param {Integer[]} columnWidths is size of each column
12534 * @returns {number} lineHeight
12535 * @private
12536 */
12537 var calculateLineHeight = function calculateLineHeight(model, columnWidths) {
12538 var padding = this.internal.__cell__.padding;
12539 var fontSize = this.internal.__cell__.table_font_size;
12540 var scaleFactor = this.internal.scaleFactor;
12541
12542 return Object.keys(model)
12543 .map(function(key) {
12544 var value = model[key];
12545 return this.splitTextToSize(
12546 value.hasOwnProperty("text") ? value.text : value,
12547 columnWidths[key] - padding - padding
12548 );
12549 }, this)
12550 .map(function(value) {
12551 return (
12552 (this.getLineHeightFactor() * value.length * fontSize) / scaleFactor +
12553 padding +
12554 padding
12555 );
12556 }, this)
12557 .reduce(function(pv, cv) {
12558 return Math.max(pv, cv);
12559 }, 0);
12560 };
12561
12562 /**
12563 * Store the config for outputting a table header
12564 *
12565 * @name setTableHeaderRow
12566 * @function
12567 * @param {Object[]} config
12568 * An array of cell configs that would define a header row: Each config matches the config used by jsPDFAPI.cell
12569 * except the lineNumber parameter is excluded
12570 */
12571 jsPDFAPI.setTableHeaderRow = function(config) {
12572 _initialize.call(this);
12573 this.internal.__cell__.tableHeaderRow = config;
12574 };
12575
12576 /**
12577 * Output the store header row
12578 *
12579 * @name printHeaderRow
12580 * @function
12581 * @param {number} lineNumber The line number to output the header at
12582 * @param {boolean} new_page
12583 */
12584 jsPDFAPI.printHeaderRow = function(lineNumber, new_page) {
12585 _initialize.call(this);
12586 if (!this.internal.__cell__.tableHeaderRow) {
12587 throw new Error("Property tableHeaderRow does not exist.");
12588 }
12589
12590 var tableHeaderCell;
12591
12592 printingHeaderRow = true;
12593 if (typeof this.internal.__cell__.headerFunction === "function") {
12594 var position = this.internal.__cell__.headerFunction(
12595 this,
12596 this.internal.__cell__.pages
12597 );
12598 this.internal.__cell__.lastCell = new Cell(
12599 position[0],
12600 position[1],
12601 position[2],
12602 position[3],
12603 undefined,
12604 -1
12605 );
12606 }
12607 this.setFont(undefined, "bold");
12608
12609 var tempHeaderConf = [];
12610 for (var i = 0; i < this.internal.__cell__.tableHeaderRow.length; i += 1) {
12611 tableHeaderCell = this.internal.__cell__.tableHeaderRow[i].clone();
12612 if (new_page) {
12613 tableHeaderCell.y = this.internal.__cell__.margins.top || 0;
12614 tempHeaderConf.push(tableHeaderCell);
12615 }
12616 tableHeaderCell.lineNumber = lineNumber;
12617 this.setFillColor(this.internal.__cell__.headerBackgroundColor);
12618 cell.call(this, tableHeaderCell);
12619 }
12620 if (tempHeaderConf.length > 0) {
12621 this.setTableHeaderRow(tempHeaderConf);
12622 }
12623 this.setFont(undefined, "normal");
12624 printingHeaderRow = false;
12625 };
12626 })(jsPDF.API);
12627
12628 function toLookup(arr) {
12629 return arr.reduce(function(lookup, name, index) {
12630 lookup[name] = index;
12631
12632 return lookup;
12633 }, {});
12634 }
12635
12636 var fontStyleOrder = {
12637 italic: ["italic", "oblique", "normal"],
12638 oblique: ["oblique", "italic", "normal"],
12639 normal: ["normal", "oblique", "italic"]
12640 };
12641
12642 var fontStretchOrder = [
12643 "ultra-condensed",
12644 "extra-condensed",
12645 "condensed",
12646 "semi-condensed",
12647 "normal",
12648 "semi-expanded",
12649 "expanded",
12650 "extra-expanded",
12651 "ultra-expanded"
12652 ];
12653
12654 // For a given font-stretch value, we need to know where to start our search
12655 // from in the fontStretchOrder list.
12656 var fontStretchLookup = toLookup(fontStretchOrder);
12657
12658 var fontWeights = [100, 200, 300, 400, 500, 600, 700, 800, 900];
12659 var fontWeightsLookup = toLookup(fontWeights);
12660
12661 function normalizeFontStretch(stretch) {
12662 stretch = stretch || "normal";
12663
12664 return typeof fontStretchLookup[stretch] === "number" ? stretch : "normal";
12665 }
12666
12667 function normalizeFontStyle(style) {
12668 style = style || "normal";
12669
12670 return fontStyleOrder[style] ? style : "normal";
12671 }
12672
12673 function normalizeFontWeight(weight) {
12674 if (!weight) {
12675 return 400;
12676 }
12677
12678 if (typeof weight === "number") {
12679 // Ignore values which aren't valid font-weights.
12680 return weight >= 100 && weight <= 900 && weight % 100 === 0 ? weight : 400;
12681 }
12682
12683 if (/^\d00$/.test(weight)) {
12684 return parseInt(weight);
12685 }
12686
12687 switch (weight) {
12688 case "bold":
12689 return 700;
12690
12691 case "normal":
12692 default:
12693 return 400;
12694 }
12695 }
12696
12697 function normalizeFontFace(fontFace) {
12698 var family = fontFace.family.replace(/"|'/g, "").toLowerCase();
12699
12700 var style = normalizeFontStyle(fontFace.style);
12701 var weight = normalizeFontWeight(fontFace.weight);
12702 var stretch = normalizeFontStretch(fontFace.stretch);
12703
12704 return {
12705 family: family,
12706 style: style,
12707 weight: weight,
12708 stretch: stretch,
12709 src: fontFace.src || [],
12710
12711 // The ref property maps this font-face to the font
12712 // added by the .addFont() method.
12713 ref: fontFace.ref || {
12714 name: family,
12715 style: [stretch, style, weight].join(" ")
12716 }
12717 };
12718 }
12719
12720 /**
12721 * Turns a list of font-faces into a map, for easier lookup when resolving
12722 * fonts.
12723 * @private
12724 */
12725 function buildFontFaceMap(fontFaces) {
12726 var map = {};
12727
12728 for (var i = 0; i < fontFaces.length; ++i) {
12729 var normalized = normalizeFontFace(fontFaces[i]);
12730
12731 var name = normalized.family;
12732 var stretch = normalized.stretch;
12733 var style = normalized.style;
12734 var weight = normalized.weight;
12735
12736 map[name] = map[name] || {};
12737
12738 map[name][stretch] = map[name][stretch] || {};
12739 map[name][stretch][style] = map[name][stretch][style] || {};
12740 map[name][stretch][style][weight] = normalized;
12741 }
12742
12743 return map;
12744 }
12745
12746 /**
12747 * Searches a map of stretches, weights, etc. in the given direction and
12748 * then, if no match has been found, in the opposite directions.
12749 *
12750 * @param {Object.<string, any>} matchingSet A map of the various font variations.
12751 * @param {any[]} order The order of the different variations
12752 * @param {number} pivot The starting point of the search in the order list.
12753 * @param {number} dir The initial direction of the search (desc = -1, asc = 1)
12754 * @private
12755 */
12756
12757 function searchFromPivot(matchingSet, order, pivot, dir) {
12758 var i;
12759
12760 for (i = pivot; i >= 0 && i < order.length; i += dir) {
12761 if (matchingSet[order[i]]) {
12762 return matchingSet[order[i]];
12763 }
12764 }
12765
12766 for (i = pivot; i >= 0 && i < order.length; i -= dir) {
12767 if (matchingSet[order[i]]) {
12768 return matchingSet[order[i]];
12769 }
12770 }
12771 }
12772
12773 function resolveFontStretch(stretch, matchingSet) {
12774 if (matchingSet[stretch]) {
12775 return matchingSet[stretch];
12776 }
12777
12778 var pivot = fontStretchLookup[stretch];
12779
12780 // If the font-stretch value is normal or more condensed, we want to
12781 // start with a descending search, otherwise we should do ascending.
12782 var dir = pivot <= fontStretchLookup["normal"] ? -1 : 1;
12783 var match = searchFromPivot(matchingSet, fontStretchOrder, pivot, dir);
12784
12785 if (!match) {
12786 // Since a font-family cannot exist without having at least one stretch value
12787 // we should never reach this point.
12788 throw new Error(
12789 "Could not find a matching font-stretch value for " + stretch
12790 );
12791 }
12792
12793 return match;
12794 }
12795
12796 function resolveFontStyle(fontStyle, matchingSet) {
12797 if (matchingSet[fontStyle]) {
12798 return matchingSet[fontStyle];
12799 }
12800
12801 var ordering = fontStyleOrder[fontStyle];
12802
12803 for (var i = 0; i < ordering.length; ++i) {
12804 if (matchingSet[ordering[i]]) {
12805 return matchingSet[ordering[i]];
12806 }
12807 }
12808
12809 // Since a font-family cannot exist without having at least one style value
12810 // we should never reach this point.
12811 throw new Error("Could not find a matching font-style for " + fontStyle);
12812 }
12813
12814 function resolveFontWeight(weight, matchingSet) {
12815 if (matchingSet[weight]) {
12816 return matchingSet[weight];
12817 }
12818
12819 if (weight === 400 && matchingSet[500]) {
12820 return matchingSet[500];
12821 }
12822
12823 if (weight === 500 && matchingSet[400]) {
12824 return matchingSet[400];
12825 }
12826
12827 var pivot = fontWeightsLookup[weight];
12828
12829 // If the font-stretch value is normal or more condensed, we want to
12830 // start with a descending search, otherwise we should do ascending.
12831 var dir = weight < 400 ? -1 : 1;
12832 var match = searchFromPivot(matchingSet, fontWeights, pivot, dir);
12833
12834 if (!match) {
12835 // Since a font-family cannot exist without having at least one stretch value
12836 // we should never reach this point.
12837 throw new Error(
12838 "Could not find a matching font-weight for value " + weight
12839 );
12840 }
12841
12842 return match;
12843 }
12844
12845 var defaultGenericFontFamilies = {
12846 "sans-serif": "helvetica",
12847 fixed: "courier",
12848 monospace: "courier",
12849 terminal: "courier",
12850 cursive: "times",
12851 fantasy: "times",
12852 serif: "times"
12853 };
12854
12855 var systemFonts = {
12856 caption: "times",
12857 icon: "times",
12858 menu: "times",
12859 "message-box": "times",
12860 "small-caption": "times",
12861 "status-bar": "times"
12862 };
12863
12864 function ruleToString(rule) {
12865 return [rule.stretch, rule.style, rule.weight, rule.family].join(" ");
12866 }
12867
12868 function resolveFontFace(fontFaceMap, rules, opts) {
12869 opts = opts || {};
12870
12871 var defaultFontFamily = opts.defaultFontFamily || "times";
12872 var genericFontFamilies = Object.assign(
12873 {},
12874 defaultGenericFontFamilies,
12875 opts.genericFontFamilies || {}
12876 );
12877
12878 var rule = null;
12879 var matches = null;
12880
12881 for (var i = 0; i < rules.length; ++i) {
12882 rule = normalizeFontFace(rules[i]);
12883
12884 if (genericFontFamilies[rule.family]) {
12885 rule.family = genericFontFamilies[rule.family];
12886 }
12887
12888 if (fontFaceMap.hasOwnProperty(rule.family)) {
12889 matches = fontFaceMap[rule.family];
12890
12891 break;
12892 }
12893 }
12894
12895 // Always fallback to a known font family.
12896 matches = matches || fontFaceMap[defaultFontFamily];
12897
12898 if (!matches) {
12899 // At this point we should definitiely have a font family, but if we
12900 // don't there is something wrong with our configuration
12901 throw new Error(
12902 "Could not find a font-family for the rule '" +
12903 ruleToString(rule) +
12904 "' and default family '" +
12905 defaultFontFamily +
12906 "'."
12907 );
12908 }
12909
12910 matches = resolveFontStretch(rule.stretch, matches);
12911 matches = resolveFontStyle(rule.style, matches);
12912 matches = resolveFontWeight(rule.weight, matches);
12913
12914 if (!matches) {
12915 // We should've fount
12916 throw new Error(
12917 "Failed to resolve a font for the rule '" + ruleToString(rule) + "'."
12918 );
12919 }
12920
12921 return matches;
12922 }
12923
12924 function eatWhiteSpace(input) {
12925 return input.trimLeft();
12926 }
12927
12928 function parseQuotedFontFamily(input, quote) {
12929 var index = 0;
12930
12931 while (index < input.length) {
12932 var current = input.charAt(index);
12933
12934 if (current === quote) {
12935 return [input.substring(0, index), input.substring(index + 1)];
12936 }
12937
12938 index += 1;
12939 }
12940
12941 // Unexpected end of input
12942 return null;
12943 }
12944
12945 function parseNonQuotedFontFamily(input) {
12946 // It implements part of the identifier parser here: https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
12947 //
12948 // NOTE: This parser pretty much ignores escaped identifiers and that there is a thing called unicode.
12949 //
12950 // Breakdown of regexp:
12951 // -[a-z_] - when identifier starts with a hyphen, you're not allowed to have another hyphen or a digit
12952 // [a-z_] - allow a-z and underscore at beginning of input
12953 // [a-z0-9_-]* - after that, anything goes
12954 var match = input.match(/^(-[a-z_]|[a-z_])[a-z0-9_-]*/i);
12955
12956 // non quoted value contains illegal characters
12957 if (match === null) {
12958 return null;
12959 }
12960
12961 return [match[0], input.substring(match[0].length)];
12962 }
12963
12964 var defaultFont = ["times"];
12965
12966 function parseFontFamily(input) {
12967 var result = [];
12968 var ch, parsed;
12969 var remaining = input.trim();
12970
12971 if (remaining === "") {
12972 return defaultFont;
12973 }
12974
12975 if (remaining in systemFonts) {
12976 return [systemFonts[remaining]];
12977 }
12978
12979 while (remaining !== "") {
12980 parsed = null;
12981 remaining = eatWhiteSpace(remaining);
12982 ch = remaining.charAt(0);
12983
12984 switch (ch) {
12985 case '"':
12986 case "'":
12987 parsed = parseQuotedFontFamily(remaining.substring(1), ch);
12988 break;
12989
12990 default:
12991 parsed = parseNonQuotedFontFamily(remaining);
12992 break;
12993 }
12994
12995 if (parsed === null) {
12996 return defaultFont;
12997 }
12998
12999 result.push(parsed[0]);
13000
13001 remaining = eatWhiteSpace(parsed[1]);
13002
13003 // We expect end of input or a comma separator here
13004 if (remaining !== "" && remaining.charAt(0) !== ",") {
13005 return defaultFont;
13006 }
13007
13008 remaining = remaining.replace(/^,/, "");
13009 }
13010
13011 return result;
13012 }
13013
13014 /* eslint-disable no-fallthrough */
13015
13016 /**
13017 * This plugin mimics the HTML5 CanvasRenderingContext2D.
13018 *
13019 * The goal is to provide a way for current canvas implementations to print directly to a PDF.
13020 *
13021 * @name context2d
13022 * @module
13023 */
13024 (function(jsPDFAPI) {
13025 var ContextLayer = function(ctx) {
13026 ctx = ctx || {};
13027 this.isStrokeTransparent = ctx.isStrokeTransparent || false;
13028 this.strokeOpacity = ctx.strokeOpacity || 1;
13029 this.strokeStyle = ctx.strokeStyle || "#000000";
13030 this.fillStyle = ctx.fillStyle || "#000000";
13031 this.isFillTransparent = ctx.isFillTransparent || false;
13032 this.fillOpacity = ctx.fillOpacity || 1;
13033 this.font = ctx.font || "10px sans-serif";
13034 this.textBaseline = ctx.textBaseline || "alphabetic";
13035 this.textAlign = ctx.textAlign || "left";
13036 this.lineWidth = ctx.lineWidth || 1;
13037 this.lineJoin = ctx.lineJoin || "miter";
13038 this.lineCap = ctx.lineCap || "butt";
13039 this.path = ctx.path || [];
13040 this.transform =
13041 typeof ctx.transform !== "undefined"
13042 ? ctx.transform.clone()
13043 : new Matrix();
13044 this.globalCompositeOperation = ctx.globalCompositeOperation || "normal";
13045 this.globalAlpha = ctx.globalAlpha || 1.0;
13046 this.clip_path = ctx.clip_path || [];
13047 this.currentPoint = ctx.currentPoint || new Point();
13048 this.miterLimit = ctx.miterLimit || 10.0;
13049 this.lastPoint = ctx.lastPoint || new Point();
13050
13051 this.ignoreClearRect =
13052 typeof ctx.ignoreClearRect === "boolean" ? ctx.ignoreClearRect : true;
13053 return this;
13054 };
13055
13056 //stub
13057 var f2,
13058 getHorizontalCoordinateString,
13059 getVerticalCoordinateString,
13060 getHorizontalCoordinate,
13061 getVerticalCoordinate,
13062 Point,
13063 Rectangle,
13064 Matrix,
13065 _ctx;
13066 jsPDFAPI.events.push([
13067 "initialized",
13068 function() {
13069 this.context2d = new Context2D(this);
13070
13071 f2 = this.internal.f2;
13072 getHorizontalCoordinateString = this.internal.getCoordinateString;
13073 getVerticalCoordinateString = this.internal.getVerticalCoordinateString;
13074 getHorizontalCoordinate = this.internal.getHorizontalCoordinate;
13075 getVerticalCoordinate = this.internal.getVerticalCoordinate;
13076 Point = this.internal.Point;
13077 Rectangle = this.internal.Rectangle;
13078 Matrix = this.internal.Matrix;
13079 _ctx = new ContextLayer();
13080 }
13081 ]);
13082
13083 var Context2D = function(pdf) {
13084 Object.defineProperty(this, "canvas", {
13085 get: function() {
13086 return { parentNode: false, style: false };
13087 }
13088 });
13089
13090 var _pdf = pdf;
13091 Object.defineProperty(this, "pdf", {
13092 get: function() {
13093 return _pdf;
13094 }
13095 });
13096
13097 var _pageWrapXEnabled = false;
13098 /**
13099 * @name pageWrapXEnabled
13100 * @type {boolean}
13101 * @default false
13102 */
13103 Object.defineProperty(this, "pageWrapXEnabled", {
13104 get: function() {
13105 return _pageWrapXEnabled;
13106 },
13107 set: function(value) {
13108 _pageWrapXEnabled = Boolean(value);
13109 }
13110 });
13111
13112 var _pageWrapYEnabled = false;
13113 /**
13114 * @name pageWrapYEnabled
13115 * @type {boolean}
13116 * @default true
13117 */
13118 Object.defineProperty(this, "pageWrapYEnabled", {
13119 get: function() {
13120 return _pageWrapYEnabled;
13121 },
13122 set: function(value) {
13123 _pageWrapYEnabled = Boolean(value);
13124 }
13125 });
13126
13127 var _posX = 0;
13128 /**
13129 * @name posX
13130 * @type {number}
13131 * @default 0
13132 */
13133 Object.defineProperty(this, "posX", {
13134 get: function() {
13135 return _posX;
13136 },
13137 set: function(value) {
13138 if (!isNaN(value)) {
13139 _posX = value;
13140 }
13141 }
13142 });
13143
13144 var _posY = 0;
13145 /**
13146 * @name posY
13147 * @type {number}
13148 * @default 0
13149 */
13150 Object.defineProperty(this, "posY", {
13151 get: function() {
13152 return _posY;
13153 },
13154 set: function(value) {
13155 if (!isNaN(value)) {
13156 _posY = value;
13157 }
13158 }
13159 });
13160
13161 var _autoPaging = false;
13162 /**
13163 * @name autoPaging
13164 * @type {boolean}
13165 * @default true
13166 */
13167 Object.defineProperty(this, "autoPaging", {
13168 get: function() {
13169 return _autoPaging;
13170 },
13171 set: function(value) {
13172 _autoPaging = Boolean(value);
13173 }
13174 });
13175
13176 var lastBreak = 0;
13177 /**
13178 * @name lastBreak
13179 * @type {number}
13180 * @default 0
13181 */
13182 Object.defineProperty(this, "lastBreak", {
13183 get: function() {
13184 return lastBreak;
13185 },
13186 set: function(value) {
13187 lastBreak = value;
13188 }
13189 });
13190
13191 var pageBreaks = [];
13192 /**
13193 * Y Position of page breaks.
13194 * @name pageBreaks
13195 * @type {number}
13196 * @default 0
13197 */
13198 Object.defineProperty(this, "pageBreaks", {
13199 get: function() {
13200 return pageBreaks;
13201 },
13202 set: function(value) {
13203 pageBreaks = value;
13204 }
13205 });
13206
13207 /**
13208 * @name ctx
13209 * @type {object}
13210 * @default {}
13211 */
13212 Object.defineProperty(this, "ctx", {
13213 get: function() {
13214 return _ctx;
13215 },
13216 set: function(value) {
13217 if (value instanceof ContextLayer) {
13218 _ctx = value;
13219 }
13220 }
13221 });
13222
13223 /**
13224 * @name path
13225 * @type {array}
13226 * @default []
13227 */
13228 Object.defineProperty(this, "path", {
13229 get: function() {
13230 return _ctx.path;
13231 },
13232 set: function(value) {
13233 _ctx.path = value;
13234 }
13235 });
13236
13237 /**
13238 * @name ctxStack
13239 * @type {array}
13240 * @default []
13241 */
13242 var _ctxStack = [];
13243 Object.defineProperty(this, "ctxStack", {
13244 get: function() {
13245 return _ctxStack;
13246 },
13247 set: function(value) {
13248 _ctxStack = value;
13249 }
13250 });
13251
13252 /**
13253 * Sets or returns the color, gradient, or pattern used to fill the drawing
13254 *
13255 * @name fillStyle
13256 * @default #000000
13257 * @property {(color|gradient|pattern)} value The color of the drawing. Default value is #000000<br />
13258 * A gradient object (linear or radial) used to fill the drawing (not supported by context2d)<br />
13259 * A pattern object to use to fill the drawing (not supported by context2d)
13260 */
13261 Object.defineProperty(this, "fillStyle", {
13262 get: function() {
13263 return this.ctx.fillStyle;
13264 },
13265 set: function(value) {
13266 var rgba;
13267 rgba = getRGBA(value);
13268
13269 this.ctx.fillStyle = rgba.style;
13270 this.ctx.isFillTransparent = rgba.a === 0;
13271 this.ctx.fillOpacity = rgba.a;
13272
13273 this.pdf.setFillColor(rgba.r, rgba.g, rgba.b, { a: rgba.a });
13274 this.pdf.setTextColor(rgba.r, rgba.g, rgba.b, { a: rgba.a });
13275 }
13276 });
13277
13278 /**
13279 * Sets or returns the color, gradient, or pattern used for strokes
13280 *
13281 * @name strokeStyle
13282 * @default #000000
13283 * @property {color} color A CSS color value that indicates the stroke color of the drawing. Default value is #000000 (not supported by context2d)
13284 * @property {gradient} gradient A gradient object (linear or radial) used to create a gradient stroke (not supported by context2d)
13285 * @property {pattern} pattern A pattern object used to create a pattern stroke (not supported by context2d)
13286 */
13287 Object.defineProperty(this, "strokeStyle", {
13288 get: function() {
13289 return this.ctx.strokeStyle;
13290 },
13291 set: function(value) {
13292 var rgba = getRGBA(value);
13293
13294 this.ctx.strokeStyle = rgba.style;
13295 this.ctx.isStrokeTransparent = rgba.a === 0;
13296 this.ctx.strokeOpacity = rgba.a;
13297
13298 if (rgba.a === 0) {
13299 this.pdf.setDrawColor(255, 255, 255);
13300 } else if (rgba.a === 1) {
13301 this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b);
13302 } else {
13303 this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b);
13304 }
13305 }
13306 });
13307
13308 /**
13309 * Sets or returns the style of the end caps for a line
13310 *
13311 * @name lineCap
13312 * @default butt
13313 * @property {(butt|round|square)} lineCap butt A flat edge is added to each end of the line <br/>
13314 * round A rounded end cap is added to each end of the line<br/>
13315 * square A square end cap is added to each end of the line<br/>
13316 */
13317 Object.defineProperty(this, "lineCap", {
13318 get: function() {
13319 return this.ctx.lineCap;
13320 },
13321 set: function(value) {
13322 if (["butt", "round", "square"].indexOf(value) !== -1) {
13323 this.ctx.lineCap = value;
13324 this.pdf.setLineCap(value);
13325 }
13326 }
13327 });
13328
13329 /**
13330 * Sets or returns the current line width
13331 *
13332 * @name lineWidth
13333 * @default 1
13334 * @property {number} lineWidth The current line width, in pixels
13335 */
13336 Object.defineProperty(this, "lineWidth", {
13337 get: function() {
13338 return this.ctx.lineWidth;
13339 },
13340 set: function(value) {
13341 if (!isNaN(value)) {
13342 this.ctx.lineWidth = value;
13343 this.pdf.setLineWidth(value);
13344 }
13345 }
13346 });
13347
13348 /**
13349 * Sets or returns the type of corner created, when two lines meet
13350 */
13351 Object.defineProperty(this, "lineJoin", {
13352 get: function() {
13353 return this.ctx.lineJoin;
13354 },
13355 set: function(value) {
13356 if (["bevel", "round", "miter"].indexOf(value) !== -1) {
13357 this.ctx.lineJoin = value;
13358 this.pdf.setLineJoin(value);
13359 }
13360 }
13361 });
13362
13363 /**
13364 * A number specifying the miter limit ratio in coordinate space units. Zero, negative, Infinity, and NaN values are ignored. The default value is 10.0.
13365 *
13366 * @name miterLimit
13367 * @default 10
13368 */
13369 Object.defineProperty(this, "miterLimit", {
13370 get: function() {
13371 return this.ctx.miterLimit;
13372 },
13373 set: function(value) {
13374 if (!isNaN(value)) {
13375 this.ctx.miterLimit = value;
13376 this.pdf.setMiterLimit(value);
13377 }
13378 }
13379 });
13380
13381 Object.defineProperty(this, "textBaseline", {
13382 get: function() {
13383 return this.ctx.textBaseline;
13384 },
13385 set: function(value) {
13386 this.ctx.textBaseline = value;
13387 }
13388 });
13389
13390 Object.defineProperty(this, "textAlign", {
13391 get: function() {
13392 return this.ctx.textAlign;
13393 },
13394 set: function(value) {
13395 if (["right", "end", "center", "left", "start"].indexOf(value) !== -1) {
13396 this.ctx.textAlign = value;
13397 }
13398 }
13399 });
13400
13401 var _fontFaceMap = null;
13402
13403 function getFontFaceMap(pdf, fontFaces) {
13404 if (_fontFaceMap === null) {
13405 var fontMap = pdf.getFontList();
13406
13407 var convertedFontFaces = convertToFontFaces(fontMap);
13408
13409 _fontFaceMap = buildFontFaceMap(convertedFontFaces.concat(fontFaces));
13410 }
13411
13412 return _fontFaceMap;
13413 }
13414
13415 function convertToFontFaces(fontMap) {
13416 var fontFaces = [];
13417
13418 Object.keys(fontMap).forEach(function(family) {
13419 var styles = fontMap[family];
13420
13421 styles.forEach(function(style) {
13422 var fontFace = null;
13423
13424 switch (style) {
13425 case "bold":
13426 fontFace = {
13427 family: family,
13428 weight: "bold"
13429 };
13430 break;
13431
13432 case "italic":
13433 fontFace = {
13434 family: family,
13435 style: "italic"
13436 };
13437 break;
13438
13439 case "bolditalic":
13440 fontFace = {
13441 family: family,
13442 weight: "bold",
13443 style: "italic"
13444 };
13445 break;
13446
13447 case "":
13448 case "normal":
13449 fontFace = {
13450 family: family
13451 };
13452 break;
13453 }
13454
13455 // If font-face is still null here, it is a font with some styling we don't recognize and
13456 // cannot map or it is a font added via the fontFaces option of .html().
13457 if (fontFace !== null) {
13458 fontFace.ref = {
13459 name: family,
13460 style: style
13461 };
13462
13463 fontFaces.push(fontFace);
13464 }
13465 });
13466 });
13467
13468 return fontFaces;
13469 }
13470
13471 var _fontFaces = null;
13472 /**
13473 * A map of available font-faces, as passed in the options of
13474 * .html(). If set a limited implementation of the font style matching
13475 * algorithm defined by https://www.w3.org/TR/css-fonts-3/#font-matching-algorithm
13476 * will be used. If not set it will fallback to previous behavior.
13477 */
13478
13479 Object.defineProperty(this, "fontFaces", {
13480 get: function() {
13481 return _fontFaces;
13482 },
13483 set: function(value) {
13484 _fontFaceMap = null;
13485 _fontFaces = value;
13486 }
13487 });
13488
13489 Object.defineProperty(this, "font", {
13490 get: function() {
13491 return this.ctx.font;
13492 },
13493 set: function(value) {
13494 this.ctx.font = value;
13495 var rx, matches;
13496
13497 //source: https://stackoverflow.com/a/10136041
13498 // eslint-disable-next-line no-useless-escape
13499 rx = /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-_,\"\'\sa-z]+?)\s*$/i;
13500 matches = rx.exec(value);
13501 if (matches !== null) {
13502 var fontStyle = matches[1];
13503 var fontVariant = matches[2];
13504 var fontWeight = matches[3];
13505 var fontSize = matches[4];
13506 var lineHeight = matches[5];
13507 var fontFamily = matches[6];
13508 } else {
13509 return;
13510 }
13511 var rxFontSize = /^([.\d]+)((?:%|in|[cem]m|ex|p[ctx]))$/i;
13512 var fontSizeUnit = rxFontSize.exec(fontSize)[2];
13513
13514 if ("px" === fontSizeUnit) {
13515 fontSize = Math.floor(
13516 parseFloat(fontSize) * this.pdf.internal.scaleFactor
13517 );
13518 } else if ("em" === fontSizeUnit) {
13519 fontSize = Math.floor(parseFloat(fontSize) * this.pdf.getFontSize());
13520 } else {
13521 fontSize = Math.floor(
13522 parseFloat(fontSize) * this.pdf.internal.scaleFactor
13523 );
13524 }
13525
13526 this.pdf.setFontSize(fontSize);
13527 var parts = parseFontFamily(fontFamily);
13528
13529 if (this.fontFaces) {
13530 var fontFaceMap = getFontFaceMap(this.pdf, this.fontFaces);
13531
13532 var rules = parts.map(function(ff) {
13533 return {
13534 family: ff,
13535 stretch: "normal", // TODO: Extract font-stretch from font rule (perhaps write proper parser for it?)
13536 weight: fontWeight,
13537 style: fontStyle
13538 };
13539 });
13540
13541 var font = resolveFontFace(fontFaceMap, rules);
13542 this.pdf.setFont(font.ref.name, font.ref.style);
13543 return;
13544 }
13545
13546 var style = "";
13547 if (
13548 fontWeight === "bold" ||
13549 parseInt(fontWeight, 10) >= 700 ||
13550 fontStyle === "bold"
13551 ) {
13552 style = "bold";
13553 }
13554
13555 if (fontStyle === "italic") {
13556 style += "italic";
13557 }
13558
13559 if (style.length === 0) {
13560 style = "normal";
13561 }
13562 var jsPdfFontName = "";
13563
13564 var fallbackFonts = {
13565 arial: "Helvetica",
13566 Arial: "Helvetica",
13567 verdana: "Helvetica",
13568 Verdana: "Helvetica",
13569 helvetica: "Helvetica",
13570 Helvetica: "Helvetica",
13571 "sans-serif": "Helvetica",
13572 fixed: "Courier",
13573 monospace: "Courier",
13574 terminal: "Courier",
13575 cursive: "Times",
13576 fantasy: "Times",
13577 serif: "Times"
13578 };
13579
13580 for (var i = 0; i < parts.length; i++) {
13581 if (
13582 this.pdf.internal.getFont(parts[i], style, {
13583 noFallback: true,
13584 disableWarning: true
13585 }) !== undefined
13586 ) {
13587 jsPdfFontName = parts[i];
13588 break;
13589 } else if (
13590 style === "bolditalic" &&
13591 this.pdf.internal.getFont(parts[i], "bold", {
13592 noFallback: true,
13593 disableWarning: true
13594 }) !== undefined
13595 ) {
13596 jsPdfFontName = parts[i];
13597 style = "bold";
13598 } else if (
13599 this.pdf.internal.getFont(parts[i], "normal", {
13600 noFallback: true,
13601 disableWarning: true
13602 }) !== undefined
13603 ) {
13604 jsPdfFontName = parts[i];
13605 style = "normal";
13606 break;
13607 }
13608 }
13609 if (jsPdfFontName === "") {
13610 for (var j = 0; j < parts.length; j++) {
13611 if (fallbackFonts[parts[j]]) {
13612 jsPdfFontName = fallbackFonts[parts[j]];
13613 break;
13614 }
13615 }
13616 }
13617 jsPdfFontName = jsPdfFontName === "" ? "Times" : jsPdfFontName;
13618 this.pdf.setFont(jsPdfFontName, style);
13619 }
13620 });
13621
13622 Object.defineProperty(this, "globalCompositeOperation", {
13623 get: function() {
13624 return this.ctx.globalCompositeOperation;
13625 },
13626 set: function(value) {
13627 this.ctx.globalCompositeOperation = value;
13628 }
13629 });
13630
13631 Object.defineProperty(this, "globalAlpha", {
13632 get: function() {
13633 return this.ctx.globalAlpha;
13634 },
13635 set: function(value) {
13636 this.ctx.globalAlpha = value;
13637 }
13638 });
13639
13640 // Not HTML API
13641 Object.defineProperty(this, "ignoreClearRect", {
13642 get: function() {
13643 return this.ctx.ignoreClearRect;
13644 },
13645 set: function(value) {
13646 this.ctx.ignoreClearRect = Boolean(value);
13647 }
13648 });
13649 };
13650
13651 Context2D.prototype.fill = function() {
13652 pathPreProcess.call(this, "fill", false);
13653 };
13654
13655 /**
13656 * Actually draws the path you have defined
13657 *
13658 * @name stroke
13659 * @function
13660 * @description The stroke() method actually draws the path you have defined with all those moveTo() and lineTo() methods. The default color is black.
13661 */
13662 Context2D.prototype.stroke = function() {
13663 pathPreProcess.call(this, "stroke", false);
13664 };
13665
13666 /**
13667 * Begins a path, or resets the current
13668 *
13669 * @name beginPath
13670 * @function
13671 * @description The beginPath() method begins a path, or resets the current path.
13672 */
13673 Context2D.prototype.beginPath = function() {
13674 this.path = [
13675 {
13676 type: "begin"
13677 }
13678 ];
13679 };
13680
13681 /**
13682 * Moves the path to the specified point in the canvas, without creating a line
13683 *
13684 * @name moveTo
13685 * @function
13686 * @param x {Number} The x-coordinate of where to move the path to
13687 * @param y {Number} The y-coordinate of where to move the path to
13688 */
13689 Context2D.prototype.moveTo = function(x, y) {
13690 if (isNaN(x) || isNaN(y)) {
13691 console.error("jsPDF.context2d.moveTo: Invalid arguments", arguments);
13692 throw new Error("Invalid arguments passed to jsPDF.context2d.moveTo");
13693 }
13694
13695 var pt = this.ctx.transform.applyToPoint(new Point(x, y));
13696
13697 this.path.push({
13698 type: "mt",
13699 x: pt.x,
13700 y: pt.y
13701 });
13702 this.ctx.lastPoint = new Point(x, y);
13703 };
13704
13705 /**
13706 * Creates a path from the current point back to the starting point
13707 *
13708 * @name closePath
13709 * @function
13710 * @description The closePath() method creates a path from the current point back to the starting point.
13711 */
13712 Context2D.prototype.closePath = function() {
13713 var pathBegin = new Point(0, 0);
13714 var i = 0;
13715 for (i = this.path.length - 1; i !== -1; i--) {
13716 if (this.path[i].type === "begin") {
13717 if (
13718 typeof this.path[i + 1] === "object" &&
13719 typeof this.path[i + 1].x === "number"
13720 ) {
13721 pathBegin = new Point(this.path[i + 1].x, this.path[i + 1].y);
13722 this.path.push({
13723 type: "lt",
13724 x: pathBegin.x,
13725 y: pathBegin.y
13726 });
13727 break;
13728 }
13729 }
13730 }
13731 if (
13732 typeof this.path[i + 2] === "object" &&
13733 typeof this.path[i + 2].x === "number"
13734 ) {
13735 this.path.push(JSON.parse(JSON.stringify(this.path[i + 2])));
13736 }
13737 this.path.push({
13738 type: "close"
13739 });
13740 this.ctx.lastPoint = new Point(pathBegin.x, pathBegin.y);
13741 };
13742
13743 /**
13744 * Adds a new point and creates a line to that point from the last specified point in the canvas
13745 *
13746 * @name lineTo
13747 * @function
13748 * @param x The x-coordinate of where to create the line to
13749 * @param y The y-coordinate of where to create the line to
13750 * @description The lineTo() method adds a new point and creates a line TO that point FROM the last specified point in the canvas (this method does not draw the line).
13751 */
13752 Context2D.prototype.lineTo = function(x, y) {
13753 if (isNaN(x) || isNaN(y)) {
13754 console.error("jsPDF.context2d.lineTo: Invalid arguments", arguments);
13755 throw new Error("Invalid arguments passed to jsPDF.context2d.lineTo");
13756 }
13757
13758 var pt = this.ctx.transform.applyToPoint(new Point(x, y));
13759
13760 this.path.push({
13761 type: "lt",
13762 x: pt.x,
13763 y: pt.y
13764 });
13765 this.ctx.lastPoint = new Point(pt.x, pt.y);
13766 };
13767
13768 /**
13769 * Clips a region of any shape and size from the original canvas
13770 *
13771 * @name clip
13772 * @function
13773 * @description The clip() method clips a region of any shape and size from the original canvas.
13774 */
13775 Context2D.prototype.clip = function() {
13776 this.ctx.clip_path = JSON.parse(JSON.stringify(this.path));
13777 pathPreProcess.call(this, null, true);
13778 };
13779
13780 /**
13781 * Creates a cubic Bézier curve
13782 *
13783 * @name quadraticCurveTo
13784 * @function
13785 * @param cpx {Number} The x-coordinate of the Bézier control point
13786 * @param cpy {Number} The y-coordinate of the Bézier control point
13787 * @param x {Number} The x-coordinate of the ending point
13788 * @param y {Number} The y-coordinate of the ending point
13789 * @description The quadraticCurveTo() method adds a point to the current path by using the specified control points that represent a quadratic Bézier curve.<br /><br /> A quadratic Bézier curve requires two points. The first point is a control point that is used in the quadratic Bézier calculation and the second point is the ending point for the curve. The starting point for the curve is the last point in the current path. If a path does not exist, use the beginPath() and moveTo() methods to define a starting point.
13790 */
13791 Context2D.prototype.quadraticCurveTo = function(cpx, cpy, x, y) {
13792 if (isNaN(x) || isNaN(y) || isNaN(cpx) || isNaN(cpy)) {
13793 console.error(
13794 "jsPDF.context2d.quadraticCurveTo: Invalid arguments",
13795 arguments
13796 );
13797 throw new Error(
13798 "Invalid arguments passed to jsPDF.context2d.quadraticCurveTo"
13799 );
13800 }
13801
13802 var pt0 = this.ctx.transform.applyToPoint(new Point(x, y));
13803 var pt1 = this.ctx.transform.applyToPoint(new Point(cpx, cpy));
13804
13805 this.path.push({
13806 type: "qct",
13807 x1: pt1.x,
13808 y1: pt1.y,
13809 x: pt0.x,
13810 y: pt0.y
13811 });
13812 this.ctx.lastPoint = new Point(pt0.x, pt0.y);
13813 };
13814
13815 /**
13816 * Creates a cubic Bézier curve
13817 *
13818 * @name bezierCurveTo
13819 * @function
13820 * @param cp1x {Number} The x-coordinate of the first Bézier control point
13821 * @param cp1y {Number} The y-coordinate of the first Bézier control point
13822 * @param cp2x {Number} The x-coordinate of the second Bézier control point
13823 * @param cp2y {Number} The y-coordinate of the second Bézier control point
13824 * @param x {Number} The x-coordinate of the ending point
13825 * @param y {Number} The y-coordinate of the ending point
13826 * @description The bezierCurveTo() method adds a point to the current path by using the specified control points that represent a cubic Bézier curve. <br /><br />A cubic bezier curve requires three points. The first two points are control points that are used in the cubic Bézier calculation and the last point is the ending point for the curve. The starting point for the curve is the last point in the current path. If a path does not exist, use the beginPath() and moveTo() methods to define a starting point.
13827 */
13828 Context2D.prototype.bezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) {
13829 if (
13830 isNaN(x) ||
13831 isNaN(y) ||
13832 isNaN(cp1x) ||
13833 isNaN(cp1y) ||
13834 isNaN(cp2x) ||
13835 isNaN(cp2y)
13836 ) {
13837 console.error(
13838 "jsPDF.context2d.bezierCurveTo: Invalid arguments",
13839 arguments
13840 );
13841 throw new Error(
13842 "Invalid arguments passed to jsPDF.context2d.bezierCurveTo"
13843 );
13844 }
13845 var pt0 = this.ctx.transform.applyToPoint(new Point(x, y));
13846 var pt1 = this.ctx.transform.applyToPoint(new Point(cp1x, cp1y));
13847 var pt2 = this.ctx.transform.applyToPoint(new Point(cp2x, cp2y));
13848
13849 this.path.push({
13850 type: "bct",
13851 x1: pt1.x,
13852 y1: pt1.y,
13853 x2: pt2.x,
13854 y2: pt2.y,
13855 x: pt0.x,
13856 y: pt0.y
13857 });
13858 this.ctx.lastPoint = new Point(pt0.x, pt0.y);
13859 };
13860
13861 /**
13862 * Creates an arc/curve (used to create circles, or parts of circles)
13863 *
13864 * @name arc
13865 * @function
13866 * @param x {Number} The x-coordinate of the center of the circle
13867 * @param y {Number} The y-coordinate of the center of the circle
13868 * @param radius {Number} The radius of the circle
13869 * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle)
13870 * @param endAngle {Number} The ending angle, in radians
13871 * @param counterclockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise.
13872 * @description The arc() method creates an arc/curve (used to create circles, or parts of circles).
13873 */
13874 Context2D.prototype.arc = function(
13875 x,
13876 y,
13877 radius,
13878 startAngle,
13879 endAngle,
13880 counterclockwise
13881 ) {
13882 if (
13883 isNaN(x) ||
13884 isNaN(y) ||
13885 isNaN(radius) ||
13886 isNaN(startAngle) ||
13887 isNaN(endAngle)
13888 ) {
13889 console.error("jsPDF.context2d.arc: Invalid arguments", arguments);
13890 throw new Error("Invalid arguments passed to jsPDF.context2d.arc");
13891 }
13892 counterclockwise = Boolean(counterclockwise);
13893
13894 if (!this.ctx.transform.isIdentity) {
13895 var xpt = this.ctx.transform.applyToPoint(new Point(x, y));
13896 x = xpt.x;
13897 y = xpt.y;
13898
13899 var x_radPt = this.ctx.transform.applyToPoint(new Point(0, radius));
13900 var x_radPt0 = this.ctx.transform.applyToPoint(new Point(0, 0));
13901 radius = Math.sqrt(
13902 Math.pow(x_radPt.x - x_radPt0.x, 2) +
13903 Math.pow(x_radPt.y - x_radPt0.y, 2)
13904 );
13905 }
13906 if (Math.abs(endAngle - startAngle) >= 2 * Math.PI) {
13907 startAngle = 0;
13908 endAngle = 2 * Math.PI;
13909 }
13910
13911 this.path.push({
13912 type: "arc",
13913 x: x,
13914 y: y,
13915 radius: radius,
13916 startAngle: startAngle,
13917 endAngle: endAngle,
13918 counterclockwise: counterclockwise
13919 });
13920 // this.ctx.lastPoint(new Point(pt.x,pt.y));
13921 };
13922
13923 /**
13924 * Creates an arc/curve between two tangents
13925 *
13926 * @name arcTo
13927 * @function
13928 * @param x1 {Number} The x-coordinate of the first tangent
13929 * @param y1 {Number} The y-coordinate of the first tangent
13930 * @param x2 {Number} The x-coordinate of the second tangent
13931 * @param y2 {Number} The y-coordinate of the second tangent
13932 * @param radius The radius of the arc
13933 * @description The arcTo() method creates an arc/curve between two tangents on the canvas.
13934 */
13935 // eslint-disable-next-line no-unused-vars
13936 Context2D.prototype.arcTo = function(x1, y1, x2, y2, radius) {
13937 throw new Error("arcTo not implemented.");
13938 };
13939
13940 /**
13941 * Creates a rectangle
13942 *
13943 * @name rect
13944 * @function
13945 * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
13946 * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
13947 * @param w {Number} The width of the rectangle, in pixels
13948 * @param h {Number} The height of the rectangle, in pixels
13949 * @description The rect() method creates a rectangle.
13950 */
13951 Context2D.prototype.rect = function(x, y, w, h) {
13952 if (isNaN(x) || isNaN(y) || isNaN(w) || isNaN(h)) {
13953 console.error("jsPDF.context2d.rect: Invalid arguments", arguments);
13954 throw new Error("Invalid arguments passed to jsPDF.context2d.rect");
13955 }
13956 this.moveTo(x, y);
13957 this.lineTo(x + w, y);
13958 this.lineTo(x + w, y + h);
13959 this.lineTo(x, y + h);
13960 this.lineTo(x, y);
13961 this.lineTo(x + w, y);
13962 this.lineTo(x, y);
13963 };
13964
13965 /**
13966 * Draws a "filled" rectangle
13967 *
13968 * @name fillRect
13969 * @function
13970 * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
13971 * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
13972 * @param w {Number} The width of the rectangle, in pixels
13973 * @param h {Number} The height of the rectangle, in pixels
13974 * @description The fillRect() method draws a "filled" rectangle. The default color of the fill is black.
13975 */
13976 Context2D.prototype.fillRect = function(x, y, w, h) {
13977 if (isNaN(x) || isNaN(y) || isNaN(w) || isNaN(h)) {
13978 console.error("jsPDF.context2d.fillRect: Invalid arguments", arguments);
13979 throw new Error("Invalid arguments passed to jsPDF.context2d.fillRect");
13980 }
13981 if (isFillTransparent.call(this)) {
13982 return;
13983 }
13984 var tmp = {};
13985 if (this.lineCap !== "butt") {
13986 tmp.lineCap = this.lineCap;
13987 this.lineCap = "butt";
13988 }
13989 if (this.lineJoin !== "miter") {
13990 tmp.lineJoin = this.lineJoin;
13991 this.lineJoin = "miter";
13992 }
13993
13994 this.beginPath();
13995 this.rect(x, y, w, h);
13996 this.fill();
13997
13998 if (tmp.hasOwnProperty("lineCap")) {
13999 this.lineCap = tmp.lineCap;
14000 }
14001 if (tmp.hasOwnProperty("lineJoin")) {
14002 this.lineJoin = tmp.lineJoin;
14003 }
14004 };
14005
14006 /**
14007 * Draws a rectangle (no fill)
14008 *
14009 * @name strokeRect
14010 * @function
14011 * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
14012 * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
14013 * @param w {Number} The width of the rectangle, in pixels
14014 * @param h {Number} The height of the rectangle, in pixels
14015 * @description The strokeRect() method draws a rectangle (no fill). The default color of the stroke is black.
14016 */
14017 Context2D.prototype.strokeRect = function strokeRect(x, y, w, h) {
14018 if (isNaN(x) || isNaN(y) || isNaN(w) || isNaN(h)) {
14019 console.error("jsPDF.context2d.strokeRect: Invalid arguments", arguments);
14020 throw new Error("Invalid arguments passed to jsPDF.context2d.strokeRect");
14021 }
14022 if (isStrokeTransparent.call(this)) {
14023 return;
14024 }
14025 this.beginPath();
14026 this.rect(x, y, w, h);
14027 this.stroke();
14028 };
14029
14030 /**
14031 * Clears the specified pixels within a given rectangle
14032 *
14033 * @name clearRect
14034 * @function
14035 * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
14036 * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
14037 * @param w {Number} The width of the rectangle to clear, in pixels
14038 * @param h {Number} The height of the rectangle to clear, in pixels
14039 * @description We cannot clear PDF commands that were already written to PDF, so we use white instead. <br />
14040 * As a special case, read a special flag (ignoreClearRect) and do nothing if it is set.
14041 * This results in all calls to clearRect() to do nothing, and keep the canvas transparent.
14042 * This flag is stored in the save/restore context and is managed the same way as other drawing states.
14043 *
14044 */
14045 Context2D.prototype.clearRect = function(x, y, w, h) {
14046 if (isNaN(x) || isNaN(y) || isNaN(w) || isNaN(h)) {
14047 console.error("jsPDF.context2d.clearRect: Invalid arguments", arguments);
14048 throw new Error("Invalid arguments passed to jsPDF.context2d.clearRect");
14049 }
14050 if (this.ignoreClearRect) {
14051 return;
14052 }
14053
14054 this.fillStyle = "#ffffff";
14055 this.fillRect(x, y, w, h);
14056 };
14057
14058 /**
14059 * Saves the state of the current context
14060 *
14061 * @name save
14062 * @function
14063 */
14064 Context2D.prototype.save = function(doStackPush) {
14065 doStackPush = typeof doStackPush === "boolean" ? doStackPush : true;
14066 var tmpPageNumber = this.pdf.internal.getCurrentPageInfo().pageNumber;
14067 for (var i = 0; i < this.pdf.internal.getNumberOfPages(); i++) {
14068 this.pdf.setPage(i + 1);
14069 this.pdf.internal.out("q");
14070 }
14071 this.pdf.setPage(tmpPageNumber);
14072
14073 if (doStackPush) {
14074 this.ctx.fontSize = this.pdf.internal.getFontSize();
14075 var ctx = new ContextLayer(this.ctx);
14076 this.ctxStack.push(this.ctx);
14077 this.ctx = ctx;
14078 }
14079 };
14080
14081 /**
14082 * Returns previously saved path state and attributes
14083 *
14084 * @name restore
14085 * @function
14086 */
14087 Context2D.prototype.restore = function(doStackPop) {
14088 doStackPop = typeof doStackPop === "boolean" ? doStackPop : true;
14089 var tmpPageNumber = this.pdf.internal.getCurrentPageInfo().pageNumber;
14090 for (var i = 0; i < this.pdf.internal.getNumberOfPages(); i++) {
14091 this.pdf.setPage(i + 1);
14092 this.pdf.internal.out("Q");
14093 }
14094 this.pdf.setPage(tmpPageNumber);
14095
14096 if (doStackPop && this.ctxStack.length !== 0) {
14097 this.ctx = this.ctxStack.pop();
14098 this.fillStyle = this.ctx.fillStyle;
14099 this.strokeStyle = this.ctx.strokeStyle;
14100 this.font = this.ctx.font;
14101 this.lineCap = this.ctx.lineCap;
14102 this.lineWidth = this.ctx.lineWidth;
14103 this.lineJoin = this.ctx.lineJoin;
14104 }
14105 };
14106
14107 /**
14108 * @name toDataURL
14109 * @function
14110 */
14111 Context2D.prototype.toDataURL = function() {
14112 throw new Error("toDataUrl not implemented.");
14113 };
14114
14115 //helper functions
14116
14117 /**
14118 * Get the decimal values of r, g, b and a
14119 *
14120 * @name getRGBA
14121 * @function
14122 * @private
14123 * @ignore
14124 */
14125 var getRGBA = function(style) {
14126 var rxRgb = /rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/;
14127 var rxRgba = /rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/;
14128 var rxTransparent = /transparent|rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*0+\s*\)/;
14129
14130 var r, g, b, a;
14131
14132 if (style.isCanvasGradient === true) {
14133 style = style.getColor();
14134 }
14135
14136 if (!style) {
14137 return { r: 0, g: 0, b: 0, a: 0, style: style };
14138 }
14139
14140 if (rxTransparent.test(style)) {
14141 r = 0;
14142 g = 0;
14143 b = 0;
14144 a = 0;
14145 } else {
14146 var matches = rxRgb.exec(style);
14147 if (matches !== null) {
14148 r = parseInt(matches[1]);
14149 g = parseInt(matches[2]);
14150 b = parseInt(matches[3]);
14151 a = 1;
14152 } else {
14153 matches = rxRgba.exec(style);
14154 if (matches !== null) {
14155 r = parseInt(matches[1]);
14156 g = parseInt(matches[2]);
14157 b = parseInt(matches[3]);
14158 a = parseFloat(matches[4]);
14159 } else {
14160 a = 1;
14161
14162 if (typeof style === "string" && style.charAt(0) !== "#") {
14163 var rgbColor = new RGBColor(style);
14164 if (rgbColor.ok) {
14165 style = rgbColor.toHex();
14166 } else {
14167 style = "#000000";
14168 }
14169 }
14170
14171 if (style.length === 4) {
14172 r = style.substring(1, 2);
14173 r += r;
14174 g = style.substring(2, 3);
14175 g += g;
14176 b = style.substring(3, 4);
14177 b += b;
14178 } else {
14179 r = style.substring(1, 3);
14180 g = style.substring(3, 5);
14181 b = style.substring(5, 7);
14182 }
14183 r = parseInt(r, 16);
14184 g = parseInt(g, 16);
14185 b = parseInt(b, 16);
14186 }
14187 }
14188 }
14189 return { r: r, g: g, b: b, a: a, style: style };
14190 };
14191
14192 /**
14193 * @name isFillTransparent
14194 * @function
14195 * @private
14196 * @ignore
14197 * @returns {Boolean}
14198 */
14199 var isFillTransparent = function() {
14200 return this.ctx.isFillTransparent || this.globalAlpha == 0;
14201 };
14202
14203 /**
14204 * @name isStrokeTransparent
14205 * @function
14206 * @private
14207 * @ignore
14208 * @returns {Boolean}
14209 */
14210 var isStrokeTransparent = function() {
14211 return Boolean(this.ctx.isStrokeTransparent || this.globalAlpha == 0);
14212 };
14213
14214 /**
14215 * Draws "filled" text on the canvas
14216 *
14217 * @name fillText
14218 * @function
14219 * @param text {String} Specifies the text that will be written on the canvas
14220 * @param x {Number} The x coordinate where to start painting the text (relative to the canvas)
14221 * @param y {Number} The y coordinate where to start painting the text (relative to the canvas)
14222 * @param maxWidth {Number} Optional. The maximum allowed width of the text, in pixels
14223 * @description The fillText() method draws filled text on the canvas. The default color of the text is black.
14224 */
14225 Context2D.prototype.fillText = function(text, x, y, maxWidth) {
14226 if (isNaN(x) || isNaN(y) || typeof text !== "string") {
14227 console.error("jsPDF.context2d.fillText: Invalid arguments", arguments);
14228 throw new Error("Invalid arguments passed to jsPDF.context2d.fillText");
14229 }
14230 maxWidth = isNaN(maxWidth) ? undefined : maxWidth;
14231 if (isFillTransparent.call(this)) {
14232 return;
14233 }
14234
14235 y = getBaseline.call(this, y);
14236 var degs = rad2deg(this.ctx.transform.rotation);
14237
14238 // We only use X axis as scale hint
14239 var scale = this.ctx.transform.scaleX;
14240
14241 putText.call(this, {
14242 text: text,
14243 x: x,
14244 y: y,
14245 scale: scale,
14246 angle: degs,
14247 align: this.textAlign,
14248 maxWidth: maxWidth
14249 });
14250 };
14251
14252 /**
14253 * Draws text on the canvas (no fill)
14254 *
14255 * @name strokeText
14256 * @function
14257 * @param text {String} Specifies the text that will be written on the canvas
14258 * @param x {Number} The x coordinate where to start painting the text (relative to the canvas)
14259 * @param y {Number} The y coordinate where to start painting the text (relative to the canvas)
14260 * @param maxWidth {Number} Optional. The maximum allowed width of the text, in pixels
14261 * @description The strokeText() method draws text (with no fill) on the canvas. The default color of the text is black.
14262 */
14263 Context2D.prototype.strokeText = function(text, x, y, maxWidth) {
14264 if (isNaN(x) || isNaN(y) || typeof text !== "string") {
14265 console.error("jsPDF.context2d.strokeText: Invalid arguments", arguments);
14266 throw new Error("Invalid arguments passed to jsPDF.context2d.strokeText");
14267 }
14268 if (isStrokeTransparent.call(this)) {
14269 return;
14270 }
14271
14272 maxWidth = isNaN(maxWidth) ? undefined : maxWidth;
14273 y = getBaseline.call(this, y);
14274
14275 var degs = rad2deg(this.ctx.transform.rotation);
14276 var scale = this.ctx.transform.scaleX;
14277
14278 putText.call(this, {
14279 text: text,
14280 x: x,
14281 y: y,
14282 scale: scale,
14283 renderingMode: "stroke",
14284 angle: degs,
14285 align: this.textAlign,
14286 maxWidth: maxWidth
14287 });
14288 };
14289
14290 /**
14291 * Returns an object that contains the width of the specified text
14292 *
14293 * @name measureText
14294 * @function
14295 * @param text {String} The text to be measured
14296 * @description The measureText() method returns an object that contains the width of the specified text, in pixels.
14297 * @returns {Number}
14298 */
14299 Context2D.prototype.measureText = function(text) {
14300 if (typeof text !== "string") {
14301 console.error(
14302 "jsPDF.context2d.measureText: Invalid arguments",
14303 arguments
14304 );
14305 throw new Error(
14306 "Invalid arguments passed to jsPDF.context2d.measureText"
14307 );
14308 }
14309 var pdf = this.pdf;
14310 var k = this.pdf.internal.scaleFactor;
14311
14312 var fontSize = pdf.internal.getFontSize();
14313 var txtWidth =
14314 (pdf.getStringUnitWidth(text) * fontSize) / pdf.internal.scaleFactor;
14315 txtWidth *= Math.round(((k * 96) / 72) * 10000) / 10000;
14316
14317 var TextMetrics = function(options) {
14318 options = options || {};
14319 var _width = options.width || 0;
14320 Object.defineProperty(this, "width", {
14321 get: function() {
14322 return _width;
14323 }
14324 });
14325 return this;
14326 };
14327 return new TextMetrics({ width: txtWidth });
14328 };
14329
14330 //Transformations
14331
14332 /**
14333 * Scales the current drawing bigger or smaller
14334 *
14335 * @name scale
14336 * @function
14337 * @param scalewidth {Number} Scales the width of the current drawing (1=100%, 0.5=50%, 2=200%, etc.)
14338 * @param scaleheight {Number} Scales the height of the current drawing (1=100%, 0.5=50%, 2=200%, etc.)
14339 * @description The scale() method scales the current drawing, bigger or smaller.
14340 */
14341 Context2D.prototype.scale = function(scalewidth, scaleheight) {
14342 if (isNaN(scalewidth) || isNaN(scaleheight)) {
14343 console.error("jsPDF.context2d.scale: Invalid arguments", arguments);
14344 throw new Error("Invalid arguments passed to jsPDF.context2d.scale");
14345 }
14346 var matrix = new Matrix(scalewidth, 0.0, 0.0, scaleheight, 0.0, 0.0);
14347 this.ctx.transform = this.ctx.transform.multiply(matrix);
14348 };
14349
14350 /**
14351 * Rotates the current drawing
14352 *
14353 * @name rotate
14354 * @function
14355 * @param angle {Number} The rotation angle, in radians.
14356 * @description To calculate from degrees to radians: degrees*Math.PI/180. <br />
14357 * Example: to rotate 5 degrees, specify the following: 5*Math.PI/180
14358 */
14359 Context2D.prototype.rotate = function(angle) {
14360 if (isNaN(angle)) {
14361 console.error("jsPDF.context2d.rotate: Invalid arguments", arguments);
14362 throw new Error("Invalid arguments passed to jsPDF.context2d.rotate");
14363 }
14364 var matrix = new Matrix(
14365 Math.cos(angle),
14366 Math.sin(angle),
14367 -Math.sin(angle),
14368 Math.cos(angle),
14369 0.0,
14370 0.0
14371 );
14372 this.ctx.transform = this.ctx.transform.multiply(matrix);
14373 };
14374
14375 /**
14376 * Remaps the (0,0) position on the canvas
14377 *
14378 * @name translate
14379 * @function
14380 * @param x {Number} The value to add to horizontal (x) coordinates
14381 * @param y {Number} The value to add to vertical (y) coordinates
14382 * @description The translate() method remaps the (0,0) position on the canvas.
14383 */
14384 Context2D.prototype.translate = function(x, y) {
14385 if (isNaN(x) || isNaN(y)) {
14386 console.error("jsPDF.context2d.translate: Invalid arguments", arguments);
14387 throw new Error("Invalid arguments passed to jsPDF.context2d.translate");
14388 }
14389 var matrix = new Matrix(1.0, 0.0, 0.0, 1.0, x, y);
14390 this.ctx.transform = this.ctx.transform.multiply(matrix);
14391 };
14392
14393 /**
14394 * Replaces the current transformation matrix for the drawing
14395 *
14396 * @name transform
14397 * @function
14398 * @param a {Number} Horizontal scaling
14399 * @param b {Number} Horizontal skewing
14400 * @param c {Number} Vertical skewing
14401 * @param d {Number} Vertical scaling
14402 * @param e {Number} Horizontal moving
14403 * @param f {Number} Vertical moving
14404 * @description Each object on the canvas has a current transformation matrix.<br /><br />The transform() method replaces the current transformation matrix. It multiplies the current transformation matrix with the matrix described by:<br /><br /><br /><br />a c e<br /><br />b d f<br /><br />0 0 1<br /><br />In other words, the transform() method lets you scale, rotate, move, and skew the current context.
14405 */
14406 Context2D.prototype.transform = function(a, b, c, d, e, f) {
14407 if (isNaN(a) || isNaN(b) || isNaN(c) || isNaN(d) || isNaN(e) || isNaN(f)) {
14408 console.error("jsPDF.context2d.transform: Invalid arguments", arguments);
14409 throw new Error("Invalid arguments passed to jsPDF.context2d.transform");
14410 }
14411 var matrix = new Matrix(a, b, c, d, e, f);
14412 this.ctx.transform = this.ctx.transform.multiply(matrix);
14413 };
14414
14415 /**
14416 * Resets the current transform to the identity matrix. Then runs transform()
14417 *
14418 * @name setTransform
14419 * @function
14420 * @param a {Number} Horizontal scaling
14421 * @param b {Number} Horizontal skewing
14422 * @param c {Number} Vertical skewing
14423 * @param d {Number} Vertical scaling
14424 * @param e {Number} Horizontal moving
14425 * @param f {Number} Vertical moving
14426 * @description Each object on the canvas has a current transformation matrix. <br /><br />The setTransform() method resets the current transform to the identity matrix, and then runs transform() with the same arguments.<br /><br />In other words, the setTransform() method lets you scale, rotate, move, and skew the current context.
14427 */
14428 Context2D.prototype.setTransform = function(a, b, c, d, e, f) {
14429 a = isNaN(a) ? 1 : a;
14430 b = isNaN(b) ? 0 : b;
14431 c = isNaN(c) ? 0 : c;
14432 d = isNaN(d) ? 1 : d;
14433 e = isNaN(e) ? 0 : e;
14434 f = isNaN(f) ? 0 : f;
14435 this.ctx.transform = new Matrix(a, b, c, d, e, f);
14436 };
14437
14438 /**
14439 * Draws an image, canvas, or video onto the canvas
14440 *
14441 * @function
14442 * @param img {} Specifies the image, canvas, or video element to use
14443 * @param sx {Number} Optional. The x coordinate where to start clipping
14444 * @param sy {Number} Optional. The y coordinate where to start clipping
14445 * @param swidth {Number} Optional. The width of the clipped image
14446 * @param sheight {Number} Optional. The height of the clipped image
14447 * @param x {Number} The x coordinate where to place the image on the canvas
14448 * @param y {Number} The y coordinate where to place the image on the canvas
14449 * @param width {Number} Optional. The width of the image to use (stretch or reduce the image)
14450 * @param height {Number} Optional. The height of the image to use (stretch or reduce the image)
14451 */
14452 Context2D.prototype.drawImage = function(
14453 img,
14454 sx,
14455 sy,
14456 swidth,
14457 sheight,
14458 x,
14459 y,
14460 width,
14461 height
14462 ) {
14463 var imageProperties = this.pdf.getImageProperties(img);
14464 var factorX = 1;
14465 var factorY = 1;
14466
14467 var clipFactorX = 1;
14468 var clipFactorY = 1;
14469
14470 if (typeof swidth !== "undefined" && typeof width !== "undefined") {
14471 clipFactorX = width / swidth;
14472 clipFactorY = height / sheight;
14473 factorX = ((imageProperties.width / swidth) * width) / swidth;
14474 factorY = ((imageProperties.height / sheight) * height) / sheight;
14475 }
14476
14477 //is sx and sy are set and x and y not, set x and y with values of sx and sy
14478 if (typeof x === "undefined") {
14479 x = sx;
14480 y = sy;
14481 sx = 0;
14482 sy = 0;
14483 }
14484
14485 if (typeof swidth !== "undefined" && typeof width === "undefined") {
14486 width = swidth;
14487 height = sheight;
14488 }
14489 if (typeof swidth === "undefined" && typeof width === "undefined") {
14490 width = imageProperties.width;
14491 height = imageProperties.height;
14492 }
14493
14494 var decomposedTransformationMatrix = this.ctx.transform.decompose();
14495 var angle = rad2deg(decomposedTransformationMatrix.rotate.shx);
14496 var matrix = new Matrix();
14497 matrix = matrix.multiply(decomposedTransformationMatrix.translate);
14498 matrix = matrix.multiply(decomposedTransformationMatrix.skew);
14499 matrix = matrix.multiply(decomposedTransformationMatrix.scale);
14500 var xRect = matrix.applyToRectangle(
14501 new Rectangle(
14502 x - sx * clipFactorX,
14503 y - sy * clipFactorY,
14504 swidth * factorX,
14505 sheight * factorY
14506 )
14507 );
14508 var pageArray = getPagesByPath.call(this, xRect);
14509 var pages = [];
14510 for (var ii = 0; ii < pageArray.length; ii += 1) {
14511 if (pages.indexOf(pageArray[ii]) === -1) {
14512 pages.push(pageArray[ii]);
14513 }
14514 }
14515
14516 sortPages(pages);
14517
14518 var clipPath;
14519 if (this.autoPaging) {
14520 var min = pages[0];
14521 var max = pages[pages.length - 1];
14522 for (var i = min; i < max + 1; i++) {
14523 this.pdf.setPage(i);
14524
14525 if (this.ctx.clip_path.length !== 0) {
14526 var tmpPaths = this.path;
14527 clipPath = JSON.parse(JSON.stringify(this.ctx.clip_path));
14528 this.path = pathPositionRedo(
14529 clipPath,
14530 this.posX,
14531 -1 * this.pdf.internal.pageSize.height * (i - 1) + this.posY
14532 );
14533 drawPaths.call(this, "fill", true);
14534 this.path = tmpPaths;
14535 }
14536 var tmpRect = JSON.parse(JSON.stringify(xRect));
14537 tmpRect = pathPositionRedo(
14538 [tmpRect],
14539 this.posX,
14540 -1 * this.pdf.internal.pageSize.height * (i - 1) + this.posY
14541 )[0];
14542 this.pdf.addImage(
14543 img,
14544 "JPEG",
14545 tmpRect.x,
14546 tmpRect.y,
14547 tmpRect.w,
14548 tmpRect.h,
14549 null,
14550 null,
14551 angle
14552 );
14553 }
14554 } else {
14555 this.pdf.addImage(
14556 img,
14557 "JPEG",
14558 xRect.x,
14559 xRect.y,
14560 xRect.w,
14561 xRect.h,
14562 null,
14563 null,
14564 angle
14565 );
14566 }
14567 };
14568
14569 var getPagesByPath = function(path, pageWrapX, pageWrapY) {
14570 var result = [];
14571 pageWrapX = pageWrapX || this.pdf.internal.pageSize.width;
14572 pageWrapY = pageWrapY || this.pdf.internal.pageSize.height;
14573
14574 switch (path.type) {
14575 default:
14576 case "mt":
14577 case "lt":
14578 result.push(Math.floor((path.y + this.posY) / pageWrapY) + 1);
14579 break;
14580 case "arc":
14581 result.push(
14582 Math.floor((path.y + this.posY - path.radius) / pageWrapY) + 1
14583 );
14584 result.push(
14585 Math.floor((path.y + this.posY + path.radius) / pageWrapY) + 1
14586 );
14587 break;
14588 case "qct":
14589 var rectOfQuadraticCurve = getQuadraticCurveBoundary(
14590 this.ctx.lastPoint.x,
14591 this.ctx.lastPoint.y,
14592 path.x1,
14593 path.y1,
14594 path.x,
14595 path.y
14596 );
14597 result.push(Math.floor(rectOfQuadraticCurve.y / pageWrapY) + 1);
14598 result.push(
14599 Math.floor(
14600 (rectOfQuadraticCurve.y + rectOfQuadraticCurve.h) / pageWrapY
14601 ) + 1
14602 );
14603 break;
14604 case "bct":
14605 var rectOfBezierCurve = getBezierCurveBoundary(
14606 this.ctx.lastPoint.x,
14607 this.ctx.lastPoint.y,
14608 path.x1,
14609 path.y1,
14610 path.x2,
14611 path.y2,
14612 path.x,
14613 path.y
14614 );
14615 result.push(Math.floor(rectOfBezierCurve.y / pageWrapY) + 1);
14616 result.push(
14617 Math.floor((rectOfBezierCurve.y + rectOfBezierCurve.h) / pageWrapY) +
14618 1
14619 );
14620 break;
14621 case "rect":
14622 result.push(Math.floor((path.y + this.posY) / pageWrapY) + 1);
14623 result.push(Math.floor((path.y + path.h + this.posY) / pageWrapY) + 1);
14624 }
14625
14626 for (var i = 0; i < result.length; i += 1) {
14627 while (this.pdf.internal.getNumberOfPages() < result[i]) {
14628 addPage.call(this);
14629 }
14630 }
14631 return result;
14632 };
14633
14634 var addPage = function() {
14635 var fillStyle = this.fillStyle;
14636 var strokeStyle = this.strokeStyle;
14637 var font = this.font;
14638 var lineCap = this.lineCap;
14639 var lineWidth = this.lineWidth;
14640 var lineJoin = this.lineJoin;
14641 this.pdf.addPage();
14642 this.fillStyle = fillStyle;
14643 this.strokeStyle = strokeStyle;
14644 this.font = font;
14645 this.lineCap = lineCap;
14646 this.lineWidth = lineWidth;
14647 this.lineJoin = lineJoin;
14648 };
14649
14650 var pathPositionRedo = function(paths, x, y) {
14651 for (var i = 0; i < paths.length; i++) {
14652 switch (paths[i].type) {
14653 case "bct":
14654 paths[i].x2 += x;
14655 paths[i].y2 += y;
14656 case "qct":
14657 paths[i].x1 += x;
14658 paths[i].y1 += y;
14659 case "mt":
14660 case "lt":
14661 case "arc":
14662 default:
14663 paths[i].x += x;
14664 paths[i].y += y;
14665 }
14666 }
14667 return paths;
14668 };
14669
14670 var sortPages = function(pages) {
14671 return pages.sort(function(a, b) {
14672 return a - b;
14673 });
14674 };
14675
14676 var pathPreProcess = function(rule, isClip) {
14677 var fillStyle = this.fillStyle;
14678 var strokeStyle = this.strokeStyle;
14679 var lineCap = this.lineCap;
14680 var oldLineWidth = this.lineWidth;
14681 var lineWidth = oldLineWidth * this.ctx.transform.scaleX;
14682 var lineJoin = this.lineJoin;
14683
14684 var origPath = JSON.parse(JSON.stringify(this.path));
14685 var xPath = JSON.parse(JSON.stringify(this.path));
14686 var clipPath;
14687 var tmpPath;
14688 var pages = [];
14689
14690 for (var i = 0; i < xPath.length; i++) {
14691 if (typeof xPath[i].x !== "undefined") {
14692 var page = getPagesByPath.call(this, xPath[i]);
14693
14694 for (var ii = 0; ii < page.length; ii += 1) {
14695 if (pages.indexOf(page[ii]) === -1) {
14696 pages.push(page[ii]);
14697 }
14698 }
14699 }
14700 }
14701
14702 for (var j = 0; j < pages.length; j++) {
14703 while (this.pdf.internal.getNumberOfPages() < pages[j]) {
14704 addPage.call(this);
14705 }
14706 }
14707 sortPages(pages);
14708
14709 if (this.autoPaging) {
14710 var min = pages[0];
14711 var max = pages[pages.length - 1];
14712 for (var k = min; k < max + 1; k++) {
14713 this.pdf.setPage(k);
14714
14715 this.fillStyle = fillStyle;
14716 this.strokeStyle = strokeStyle;
14717 this.lineCap = lineCap;
14718 this.lineWidth = lineWidth;
14719 this.lineJoin = lineJoin;
14720
14721 if (this.ctx.clip_path.length !== 0) {
14722 var tmpPaths = this.path;
14723 clipPath = JSON.parse(JSON.stringify(this.ctx.clip_path));
14724 this.path = pathPositionRedo(
14725 clipPath,
14726 this.posX,
14727 -1 * this.pdf.internal.pageSize.height * (k - 1) + this.posY
14728 );
14729 drawPaths.call(this, rule, true);
14730 this.path = tmpPaths;
14731 }
14732 tmpPath = JSON.parse(JSON.stringify(origPath));
14733 this.path = pathPositionRedo(
14734 tmpPath,
14735 this.posX,
14736 -1 * this.pdf.internal.pageSize.height * (k - 1) + this.posY
14737 );
14738 if (isClip === false || k === 0) {
14739 drawPaths.call(this, rule, isClip);
14740 }
14741 this.lineWidth = oldLineWidth;
14742 }
14743 } else {
14744 this.lineWidth = lineWidth;
14745 drawPaths.call(this, rule, isClip);
14746 this.lineWidth = oldLineWidth;
14747 }
14748 this.path = origPath;
14749 };
14750
14751 /**
14752 * Processes the paths
14753 *
14754 * @function
14755 * @param rule {String}
14756 * @param isClip {Boolean}
14757 * @private
14758 * @ignore
14759 */
14760 var drawPaths = function(rule, isClip) {
14761 if (rule === "stroke" && !isClip && isStrokeTransparent.call(this)) {
14762 return;
14763 }
14764
14765 if (rule !== "stroke" && !isClip && isFillTransparent.call(this)) {
14766 return;
14767 }
14768
14769 var moves = [];
14770
14771 //var alpha = (this.ctx.fillOpacity < 1) ? this.ctx.fillOpacity : this.ctx.globalAlpha;
14772 var delta;
14773 var xPath = this.path;
14774 for (var i = 0; i < xPath.length; i++) {
14775 var pt = xPath[i];
14776
14777 switch (pt.type) {
14778 case "begin":
14779 moves.push({
14780 begin: true
14781 });
14782 break;
14783
14784 case "close":
14785 moves.push({
14786 close: true
14787 });
14788 break;
14789
14790 case "mt":
14791 moves.push({
14792 start: pt,
14793 deltas: [],
14794 abs: []
14795 });
14796 break;
14797
14798 case "lt":
14799 var iii = moves.length;
14800 if (!isNaN(xPath[i - 1].x)) {
14801 delta = [pt.x - xPath[i - 1].x, pt.y - xPath[i - 1].y];
14802 if (iii > 0) {
14803 for (iii; iii >= 0; iii--) {
14804 if (
14805 moves[iii - 1].close !== true &&
14806 moves[iii - 1].begin !== true
14807 ) {
14808 moves[iii - 1].deltas.push(delta);
14809 moves[iii - 1].abs.push(pt);
14810 break;
14811 }
14812 }
14813 }
14814 }
14815 break;
14816
14817 case "bct":
14818 delta = [
14819 pt.x1 - xPath[i - 1].x,
14820 pt.y1 - xPath[i - 1].y,
14821 pt.x2 - xPath[i - 1].x,
14822 pt.y2 - xPath[i - 1].y,
14823 pt.x - xPath[i - 1].x,
14824 pt.y - xPath[i - 1].y
14825 ];
14826 moves[moves.length - 1].deltas.push(delta);
14827 break;
14828
14829 case "qct":
14830 var x1 = xPath[i - 1].x + (2.0 / 3.0) * (pt.x1 - xPath[i - 1].x);
14831 var y1 = xPath[i - 1].y + (2.0 / 3.0) * (pt.y1 - xPath[i - 1].y);
14832 var x2 = pt.x + (2.0 / 3.0) * (pt.x1 - pt.x);
14833 var y2 = pt.y + (2.0 / 3.0) * (pt.y1 - pt.y);
14834 var x3 = pt.x;
14835 var y3 = pt.y;
14836 delta = [
14837 x1 - xPath[i - 1].x,
14838 y1 - xPath[i - 1].y,
14839 x2 - xPath[i - 1].x,
14840 y2 - xPath[i - 1].y,
14841 x3 - xPath[i - 1].x,
14842 y3 - xPath[i - 1].y
14843 ];
14844 moves[moves.length - 1].deltas.push(delta);
14845 break;
14846
14847 case "arc":
14848 moves.push({
14849 deltas: [],
14850 abs: [],
14851 arc: true
14852 });
14853
14854 if (Array.isArray(moves[moves.length - 1].abs)) {
14855 moves[moves.length - 1].abs.push(pt);
14856 }
14857 break;
14858 }
14859 }
14860 var style;
14861 if (!isClip) {
14862 if (rule === "stroke") {
14863 style = "stroke";
14864 } else {
14865 style = "fill";
14866 }
14867 } else {
14868 style = null;
14869 }
14870
14871 for (var k = 0; k < moves.length; k++) {
14872 if (moves[k].arc) {
14873 var arcs = moves[k].abs;
14874
14875 for (var ii = 0; ii < arcs.length; ii++) {
14876 var arc = arcs[ii];
14877
14878 if (arc.type === "arc") {
14879 drawArc.call(
14880 this,
14881 arc.x,
14882 arc.y,
14883 arc.radius,
14884 arc.startAngle,
14885 arc.endAngle,
14886 arc.counterclockwise,
14887 undefined,
14888 isClip
14889 );
14890 } else {
14891 drawLine.call(this, arc.x, arc.y);
14892 }
14893 }
14894 putStyle.call(this, style);
14895 this.pdf.internal.out("h");
14896 }
14897 if (!moves[k].arc) {
14898 if (moves[k].close !== true && moves[k].begin !== true) {
14899 var x = moves[k].start.x;
14900 var y = moves[k].start.y;
14901 drawLines.call(this, moves[k].deltas, x, y);
14902 }
14903 }
14904 }
14905
14906 if (style) {
14907 putStyle.call(this, style);
14908 }
14909 if (isClip) {
14910 doClip.call(this);
14911 }
14912 };
14913
14914 var getBaseline = function(y) {
14915 var height =
14916 this.pdf.internal.getFontSize() / this.pdf.internal.scaleFactor;
14917 var descent = height * (this.pdf.internal.getLineHeightFactor() - 1);
14918 switch (this.ctx.textBaseline) {
14919 case "bottom":
14920 return y - descent;
14921 case "top":
14922 return y + height - descent;
14923 case "hanging":
14924 return y + height - 2 * descent;
14925 case "middle":
14926 return y + height / 2 - descent;
14927 case "ideographic":
14928 // TODO not implemented
14929 return y;
14930 case "alphabetic":
14931 default:
14932 return y;
14933 }
14934 };
14935
14936 Context2D.prototype.createLinearGradient = function createLinearGradient() {
14937 var canvasGradient = function canvasGradient() {};
14938
14939 canvasGradient.colorStops = [];
14940 canvasGradient.addColorStop = function(offset, color) {
14941 this.colorStops.push([offset, color]);
14942 };
14943
14944 canvasGradient.getColor = function() {
14945 if (this.colorStops.length === 0) {
14946 return "#000000";
14947 }
14948
14949 return this.colorStops[0][1];
14950 };
14951
14952 canvasGradient.isCanvasGradient = true;
14953 return canvasGradient;
14954 };
14955 Context2D.prototype.createPattern = function createPattern() {
14956 return this.createLinearGradient();
14957 };
14958 Context2D.prototype.createRadialGradient = function createRadialGradient() {
14959 return this.createLinearGradient();
14960 };
14961
14962 /**
14963 *
14964 * @param x Edge point X
14965 * @param y Edge point Y
14966 * @param r Radius
14967 * @param a1 start angle
14968 * @param a2 end angle
14969 * @param counterclockwise
14970 * @param style
14971 * @param isClip
14972 */
14973 var drawArc = function(x, y, r, a1, a2, counterclockwise, style, isClip) {
14974 var curves = createArc.call(this, r, a1, a2, counterclockwise);
14975
14976 for (var i = 0; i < curves.length; i++) {
14977 var curve = curves[i];
14978 if ( i === 0) {
14979 doMove.call(this, curve.x1 + x, curve.y1 + y);
14980 }
14981 drawCurve.call(
14982 this,
14983 x,
14984 y,
14985 curve.x2,
14986 curve.y2,
14987 curve.x3,
14988 curve.y3,
14989 curve.x4,
14990 curve.y4
14991 );
14992 }
14993
14994 if (!isClip) {
14995 putStyle.call(this, style);
14996 } else {
14997 doClip.call(this);
14998 }
14999 };
15000
15001 var putStyle = function(style) {
15002 switch (style) {
15003 case "stroke":
15004 this.pdf.internal.out("S");
15005 break;
15006 case "fill":
15007 this.pdf.internal.out("f");
15008 break;
15009 }
15010 };
15011
15012 var doClip = function() {
15013 this.pdf.clip();
15014 this.pdf.discardPath();
15015 };
15016
15017 var doMove = function(x, y) {
15018 this.pdf.internal.out(
15019 getHorizontalCoordinateString(x) +
15020 " " +
15021 getVerticalCoordinateString(y) +
15022 " m"
15023 );
15024 };
15025
15026 var putText = function(options) {
15027 var textAlign;
15028 switch (options.align) {
15029 case "right":
15030 case "end":
15031 textAlign = "right";
15032 break;
15033 case "center":
15034 textAlign = "center";
15035 break;
15036 case "left":
15037 case "start":
15038 default:
15039 textAlign = "left";
15040 break;
15041 }
15042
15043 var pt = this.ctx.transform.applyToPoint(new Point(options.x, options.y));
15044 var decomposedTransformationMatrix = this.ctx.transform.decompose();
15045 var matrix = new Matrix();
15046 matrix = matrix.multiply(decomposedTransformationMatrix.translate);
15047 matrix = matrix.multiply(decomposedTransformationMatrix.skew);
15048 matrix = matrix.multiply(decomposedTransformationMatrix.scale);
15049
15050 var textDimensions = this.pdf.getTextDimensions(options.text);
15051 var textRect = this.ctx.transform.applyToRectangle(
15052 new Rectangle(options.x, options.y, textDimensions.w, textDimensions.h)
15053 );
15054 var textXRect = matrix.applyToRectangle(
15055 new Rectangle(
15056 options.x,
15057 options.y - textDimensions.h,
15058 textDimensions.w,
15059 textDimensions.h
15060 )
15061 );
15062 var pageArray = getPagesByPath.call(this, textXRect);
15063 var pages = [];
15064 for (var ii = 0; ii < pageArray.length; ii += 1) {
15065 if (pages.indexOf(pageArray[ii]) === -1) {
15066 pages.push(pageArray[ii]);
15067 }
15068 }
15069
15070 sortPages(pages);
15071
15072 var clipPath, oldSize, oldLineWidth;
15073 if (this.autoPaging === true) {
15074 var min = pages[0];
15075 var max = pages[pages.length - 1];
15076 for (var i = min; i < max + 1; i++) {
15077 this.pdf.setPage(i);
15078
15079 if (this.ctx.clip_path.length !== 0) {
15080 var tmpPaths = this.path;
15081 clipPath = JSON.parse(JSON.stringify(this.ctx.clip_path));
15082 this.path = pathPositionRedo(
15083 clipPath,
15084 this.posX,
15085 -1 * this.pdf.internal.pageSize.height * (i - 1) + this.posY
15086 );
15087 drawPaths.call(this, "fill", true);
15088 this.path = tmpPaths;
15089 }
15090 var tmpRect = JSON.parse(JSON.stringify(textRect));
15091 tmpRect = pathPositionRedo(
15092 [tmpRect],
15093 this.posX,
15094 -1 * this.pdf.internal.pageSize.height * (i - 1) + this.posY
15095 )[0];
15096
15097 if (options.scale >= 0.01) {
15098 oldSize = this.pdf.internal.getFontSize();
15099 this.pdf.setFontSize(oldSize * options.scale);
15100 oldLineWidth = this.lineWidth;
15101 this.lineWidth = oldLineWidth * options.scale;
15102 }
15103 this.pdf.text(options.text, tmpRect.x, tmpRect.y, {
15104 angle: options.angle,
15105 align: textAlign,
15106 renderingMode: options.renderingMode,
15107 maxWidth: options.maxWidth
15108 });
15109
15110 if (options.scale >= 0.01) {
15111 this.pdf.setFontSize(oldSize);
15112 this.lineWidth = oldLineWidth;
15113 }
15114 }
15115 } else {
15116 if (options.scale >= 0.01) {
15117 oldSize = this.pdf.internal.getFontSize();
15118 this.pdf.setFontSize(oldSize * options.scale);
15119 oldLineWidth = this.lineWidth;
15120 this.lineWidth = oldLineWidth * options.scale;
15121 }
15122 this.pdf.text(options.text, pt.x + this.posX, pt.y + this.posY, {
15123 angle: options.angle,
15124 align: textAlign,
15125 renderingMode: options.renderingMode,
15126 maxWidth: options.maxWidth
15127 });
15128
15129 if (options.scale >= 0.01) {
15130 this.pdf.setFontSize(oldSize);
15131 this.lineWidth = oldLineWidth;
15132 }
15133 }
15134 };
15135
15136 var drawLine = function(x, y, prevX, prevY) {
15137 prevX = prevX || 0;
15138 prevY = prevY || 0;
15139
15140 this.pdf.internal.out(
15141 getHorizontalCoordinateString(x + prevX) +
15142 " " +
15143 getVerticalCoordinateString(y + prevY) +
15144 " l"
15145 );
15146 };
15147
15148 var drawLines = function(lines, x, y) {
15149 return this.pdf.lines(lines, x, y, null, null);
15150 };
15151
15152 var drawCurve = function(x, y, x1, y1, x2, y2, x3, y3) {
15153 this.pdf.internal.out(
15154 [
15155 f2(getHorizontalCoordinate(x1 + x)),
15156 f2(getVerticalCoordinate(y1 + y)),
15157 f2(getHorizontalCoordinate(x2 + x)),
15158 f2(getVerticalCoordinate(y2 + y)),
15159 f2(getHorizontalCoordinate(x3 + x)),
15160 f2(getVerticalCoordinate(y3 + y)),
15161 "c"
15162 ].join(" ")
15163 );
15164 };
15165
15166 /**
15167 * Return a array of objects that represent bezier curves which approximate the circular arc centered at the origin, from startAngle to endAngle (radians) with the specified radius.
15168 *
15169 * Each bezier curve is an object with four points, where x1,y1 and x4,y4 are the arc's end points and x2,y2 and x3,y3 are the cubic bezier's control points.
15170 * @function createArc
15171 */
15172 var createArc = function(radius, startAngle, endAngle, anticlockwise) {
15173 var EPSILON = 0.00001; // Roughly 1/1000th of a degree, see below
15174 var twoPi = Math.PI * 2;
15175 var halfPi = Math.PI / 2.0;
15176
15177 while (startAngle > endAngle) {
15178 startAngle = startAngle - twoPi;
15179 }
15180 var totalAngle = Math.abs(endAngle - startAngle);
15181 if (totalAngle < twoPi) {
15182 if (anticlockwise) {
15183 totalAngle = twoPi - totalAngle;
15184 }
15185 }
15186
15187 // Compute the sequence of arc curves, up to PI/2 at a time.
15188 var curves = [];
15189
15190 // clockwise or counterclockwise
15191 var sgn = anticlockwise ? -1 : +1;
15192
15193 var a1 = startAngle;
15194 for (; totalAngle > EPSILON; ) {
15195 var remain = sgn * Math.min(totalAngle, halfPi);
15196 var a2 = a1 + remain;
15197 curves.push(createSmallArc.call(this, radius, a1, a2));
15198 totalAngle -= Math.abs(a2 - a1);
15199 a1 = a2;
15200 }
15201
15202 return curves;
15203 };
15204
15205 /**
15206 * Cubic bezier approximation of a circular arc centered at the origin, from (radians) a1 to a2, where a2-a1 < pi/2. The arc's radius is r.
15207 *
15208 * Returns an object with four points, where x1,y1 and x4,y4 are the arc's end points and x2,y2 and x3,y3 are the cubic bezier's control points.
15209 *
15210 * This algorithm is based on the approach described in: A. Riškus, "Approximation of a Cubic Bezier Curve by Circular Arcs and Vice Versa," Information Technology and Control, 35(4), 2006 pp. 371-378.
15211 */
15212 var createSmallArc = function(r, a1, a2) {
15213 var a = (a2 - a1) / 2.0;
15214
15215 var x4 = r * Math.cos(a);
15216 var y4 = r * Math.sin(a);
15217 var x1 = x4;
15218 var y1 = -y4;
15219
15220 var q1 = x1 * x1 + y1 * y1;
15221 var q2 = q1 + x1 * x4 + y1 * y4;
15222 var k2 = ((4 / 3) * (Math.sqrt(2 * q1 * q2) - q2)) / (x1 * y4 - y1 * x4);
15223
15224 var x2 = x1 - k2 * y1;
15225 var y2 = y1 + k2 * x1;
15226 var x3 = x2;
15227 var y3 = -y2;
15228
15229 var ar = a + a1;
15230 var cos_ar = Math.cos(ar);
15231 var sin_ar = Math.sin(ar);
15232
15233 return {
15234 x1: r * Math.cos(a1),
15235 y1: r * Math.sin(a1),
15236 x2: x2 * cos_ar - y2 * sin_ar,
15237 y2: x2 * sin_ar + y2 * cos_ar,
15238 x3: x3 * cos_ar - y3 * sin_ar,
15239 y3: x3 * sin_ar + y3 * cos_ar,
15240 x4: r * Math.cos(a2),
15241 y4: r * Math.sin(a2)
15242 };
15243 };
15244
15245 var rad2deg = function(value) {
15246 return (value * 180) / Math.PI;
15247 };
15248
15249 var getQuadraticCurveBoundary = function(sx, sy, cpx, cpy, ex, ey) {
15250 var midX1 = sx + (cpx - sx) * 0.5;
15251 var midY1 = sy + (cpy - sy) * 0.5;
15252 var midX2 = ex + (cpx - ex) * 0.5;
15253 var midY2 = ey + (cpy - ey) * 0.5;
15254 var resultX1 = Math.min(sx, ex, midX1, midX2);
15255 var resultX2 = Math.max(sx, ex, midX1, midX2);
15256 var resultY1 = Math.min(sy, ey, midY1, midY2);
15257 var resultY2 = Math.max(sy, ey, midY1, midY2);
15258 return new Rectangle(
15259 resultX1,
15260 resultY1,
15261 resultX2 - resultX1,
15262 resultY2 - resultY1
15263 );
15264 };
15265
15266 //De Casteljau algorithm
15267 var getBezierCurveBoundary = function(ax, ay, bx, by, cx, cy, dx, dy) {
15268 var tobx = bx - ax;
15269 var toby = by - ay;
15270 var tocx = cx - bx;
15271 var tocy = cy - by;
15272 var todx = dx - cx;
15273 var tody = dy - cy;
15274 var precision = 40;
15275 var d,
15276 i,
15277 px,
15278 py,
15279 qx,
15280 qy,
15281 rx,
15282 ry,
15283 tx,
15284 ty,
15285 sx,
15286 sy,
15287 x,
15288 y,
15289 minx,
15290 miny,
15291 maxx,
15292 maxy,
15293 toqx,
15294 toqy,
15295 torx,
15296 tory,
15297 totx,
15298 toty;
15299 for (i = 0; i < precision + 1; i++) {
15300 d = i / precision;
15301 px = ax + d * tobx;
15302 py = ay + d * toby;
15303 qx = bx + d * tocx;
15304 qy = by + d * tocy;
15305 rx = cx + d * todx;
15306 ry = cy + d * tody;
15307 toqx = qx - px;
15308 toqy = qy - py;
15309 torx = rx - qx;
15310 tory = ry - qy;
15311
15312 sx = px + d * toqx;
15313 sy = py + d * toqy;
15314 tx = qx + d * torx;
15315 ty = qy + d * tory;
15316 totx = tx - sx;
15317 toty = ty - sy;
15318
15319 x = sx + d * totx;
15320 y = sy + d * toty;
15321 if (i == 0) {
15322 minx = x;
15323 miny = y;
15324 maxx = x;
15325 maxy = y;
15326 } else {
15327 minx = Math.min(minx, x);
15328 miny = Math.min(miny, y);
15329 maxx = Math.max(maxx, x);
15330 maxy = Math.max(maxy, y);
15331 }
15332 }
15333 return new Rectangle(
15334 Math.round(minx),
15335 Math.round(miny),
15336 Math.round(maxx - minx),
15337 Math.round(maxy - miny)
15338 );
15339 };
15340 })(jsPDF.API);
15341
15342 // DEFLATE is a complex format; to read this code, you should probably check the RFC first:
15343 // https://tools.ietf.org/html/rfc1951
15344 // You may also wish to take a look at the guide I made about this program:
15345 // https://gist.github.com/101arrowz/253f31eb5abc3d9275ab943003ffecad
15346 // Much of the following code is similar to that of UZIP.js:
15347 // https://github.com/photopea/UZIP.js
15348 // Many optimizations have been made, so the bundle size is ultimately smaller but performance is similar.
15349 // Sometimes 0 will appear where -1 would be more appropriate. This is because using a uint
15350 // is better for memory in most engines (I *think*).
15351 // Mediocre shim
15352 var Worker;
15353 try {
15354 Worker = require('worker_threads').Worker;
15355 }
15356 catch (e) {
15357 }
15358
15359 // aliases for shorter compressed code (most minifers don't do this)
15360 var u8 = Uint8Array, u16 = Uint16Array, u32 = Uint32Array;
15361 // fixed length extra bits
15362 var fleb = new u8([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, /* unused */ 0, 0, /* impossible */ 0]);
15363 // fixed distance extra bits
15364 // see fleb note
15365 var fdeb = new u8([0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, /* unused */ 0, 0]);
15366 // code length index map
15367 var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
15368 // get base, reverse index map from extra bits
15369 var freb = function (eb, start) {
15370 var b = new u16(31);
15371 for (var i = 0; i < 31; ++i) {
15372 b[i] = start += 1 << eb[i - 1];
15373 }
15374 // numbers here are at max 18 bits
15375 var r = new u32(b[30]);
15376 for (var i = 1; i < 30; ++i) {
15377 for (var j = b[i]; j < b[i + 1]; ++j) {
15378 r[j] = ((j - b[i]) << 5) | i;
15379 }
15380 }
15381 return [b, r];
15382 };
15383 var _a = freb(fleb, 2), fl = _a[0], revfl = _a[1];
15384 // we can ignore the fact that the other numbers are wrong; they never happen anyway
15385 fl[28] = 258, revfl[258] = 28;
15386 var _b = freb(fdeb, 0), fd = _b[0], revfd = _b[1];
15387 // map of value to reverse (assuming 16 bits)
15388 var rev = new u16(32768);
15389 for (var i = 0; i < 32768; ++i) {
15390 // reverse table algorithm from SO
15391 var x = ((i & 0xAAAA) >>> 1) | ((i & 0x5555) << 1);
15392 x = ((x & 0xCCCC) >>> 2) | ((x & 0x3333) << 2);
15393 x = ((x & 0xF0F0) >>> 4) | ((x & 0x0F0F) << 4);
15394 rev[i] = (((x & 0xFF00) >>> 8) | ((x & 0x00FF) << 8)) >>> 1;
15395 }
15396 // create huffman tree from u8 "map": index -> code length for code index
15397 // mb (max bits) must be at most 15
15398 // TODO: optimize/split up?
15399 var hMap = (function (cd, mb, r) {
15400 var s = cd.length;
15401 // index
15402 var i = 0;
15403 // u16 "map": index -> # of codes with bit length = index
15404 var l = new u16(mb);
15405 // length of cd must be 288 (total # of codes)
15406 for (; i < s; ++i)
15407 ++l[cd[i] - 1];
15408 // u16 "map": index -> minimum code for bit length = index
15409 var le = new u16(mb);
15410 for (i = 0; i < mb; ++i) {
15411 le[i] = (le[i - 1] + l[i - 1]) << 1;
15412 }
15413 var co;
15414 if (r) {
15415 // u16 "map": index -> number of actual bits, symbol for code
15416 co = new u16(1 << mb);
15417 // bits to remove for reverser
15418 var rvb = 15 - mb;
15419 for (i = 0; i < s; ++i) {
15420 // ignore 0 lengths
15421 if (cd[i]) {
15422 // num encoding both symbol and bits read
15423 var sv = (i << 4) | cd[i];
15424 // free bits
15425 var r_1 = mb - cd[i];
15426 // start value
15427 var v = le[cd[i] - 1]++ << r_1;
15428 // m is end value
15429 for (var m = v | ((1 << r_1) - 1); v <= m; ++v) {
15430 // every 16 bit value starting with the code yields the same result
15431 co[rev[v] >>> rvb] = sv;
15432 }
15433 }
15434 }
15435 }
15436 else {
15437 co = new u16(s);
15438 for (i = 0; i < s; ++i)
15439 co[i] = rev[le[cd[i] - 1]++] >>> (15 - cd[i]);
15440 }
15441 return co;
15442 });
15443 // fixed length tree
15444 var flt = new u8(288);
15445 for (var i = 0; i < 144; ++i)
15446 flt[i] = 8;
15447 for (var i = 144; i < 256; ++i)
15448 flt[i] = 9;
15449 for (var i = 256; i < 280; ++i)
15450 flt[i] = 7;
15451 for (var i = 280; i < 288; ++i)
15452 flt[i] = 8;
15453 // fixed distance tree
15454 var fdt = new u8(32);
15455 for (var i = 0; i < 32; ++i)
15456 fdt[i] = 5;
15457 // fixed length map
15458 var flm = /*#__PURE__*/ hMap(flt, 9, 0), flrm = /*#__PURE__*/ hMap(flt, 9, 1);
15459 // fixed distance map
15460 var fdm = /*#__PURE__*/ hMap(fdt, 5, 0), fdrm = /*#__PURE__*/ hMap(fdt, 5, 1);
15461 // find max of array
15462 var max = function (a) {
15463 var m = a[0];
15464 for (var i = 1; i < a.length; ++i) {
15465 if (a[i] > m)
15466 m = a[i];
15467 }
15468 return m;
15469 };
15470 // read d, starting at bit p and mask with m
15471 var bits = function (d, p, m) {
15472 var o = (p / 8) >> 0;
15473 return ((d[o] | (d[o + 1] << 8)) >>> (p & 7)) & m;
15474 };
15475 // read d, starting at bit p continuing for at least 16 bits
15476 var bits16 = function (d, p) {
15477 var o = (p / 8) >> 0;
15478 return ((d[o] | (d[o + 1] << 8) | (d[o + 2] << 16)) >>> (p & 7));
15479 };
15480 // get end of byte
15481 var shft = function (p) { return ((p / 8) >> 0) + (p & 7 && 1); };
15482 // typed array slice - allows garbage collector to free original reference,
15483 // while being more compatible than .slice
15484 var slc = function (v, s, e) {
15485 if (s == null || s < 0)
15486 s = 0;
15487 if (e == null || e > v.length)
15488 e = v.length;
15489 // can't use .constructor in case user-supplied
15490 var n = new (v instanceof u16 ? u16 : v instanceof u32 ? u32 : u8)(e - s);
15491 n.set(v.subarray(s, e));
15492 return n;
15493 };
15494 // expands raw DEFLATE data
15495 var inflt = function (dat, buf, st) {
15496 // source length
15497 var sl = dat.length;
15498 // have to estimate size
15499 var noBuf = !buf || st;
15500 // no state
15501 var noSt = !st || st.i;
15502 if (!st)
15503 st = {};
15504 // Assumes roughly 33% compression ratio average
15505 if (!buf)
15506 buf = new u8(sl * 3);
15507 // ensure buffer can fit at least l elements
15508 var cbuf = function (l) {
15509 var bl = buf.length;
15510 // need to increase size to fit
15511 if (l > bl) {
15512 // Double or set to necessary, whichever is greater
15513 var nbuf = new u8(Math.max(bl * 2, l));
15514 nbuf.set(buf);
15515 buf = nbuf;
15516 }
15517 };
15518 // last chunk bitpos bytes
15519 var final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;
15520 // total bits
15521 var tbts = sl * 8;
15522 do {
15523 if (!lm) {
15524 // BFINAL - this is only 1 when last chunk is next
15525 st.f = final = bits(dat, pos, 1);
15526 // type: 0 = no compression, 1 = fixed huffman, 2 = dynamic huffman
15527 var type = bits(dat, pos + 1, 3);
15528 pos += 3;
15529 if (!type) {
15530 // go to end of byte boundary
15531 var s = shft(pos) + 4, l = dat[s - 4] | (dat[s - 3] << 8), t = s + l;
15532 if (t > sl) {
15533 if (noSt)
15534 throw 'unexpected EOF';
15535 break;
15536 }
15537 // ensure size
15538 if (noBuf)
15539 cbuf(bt + l);
15540 // Copy over uncompressed data
15541 buf.set(dat.subarray(s, t), bt);
15542 // Get new bitpos, update byte count
15543 st.b = bt += l, st.p = pos = t * 8;
15544 continue;
15545 }
15546 else if (type == 1)
15547 lm = flrm, dm = fdrm, lbt = 9, dbt = 5;
15548 else if (type == 2) {
15549 // literal lengths
15550 var hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;
15551 var tl = hLit + bits(dat, pos + 5, 31) + 1;
15552 pos += 14;
15553 // length+distance tree
15554 var ldt = new u8(tl);
15555 // code length tree
15556 var clt = new u8(19);
15557 for (var i = 0; i < hcLen; ++i) {
15558 // use index map to get real code
15559 clt[clim[i]] = bits(dat, pos + i * 3, 7);
15560 }
15561 pos += hcLen * 3;
15562 // code lengths bits
15563 var clb = max(clt), clbmsk = (1 << clb) - 1;
15564 if (!noSt && pos + tl * (clb + 7) > tbts)
15565 break;
15566 // code lengths map
15567 var clm = hMap(clt, clb, 1);
15568 for (var i = 0; i < tl;) {
15569 var r = clm[bits(dat, pos, clbmsk)];
15570 // bits read
15571 pos += r & 15;
15572 // symbol
15573 var s = r >>> 4;
15574 // code length to copy
15575 if (s < 16) {
15576 ldt[i++] = s;
15577 }
15578 else {
15579 // copy count
15580 var c = 0, n = 0;
15581 if (s == 16)
15582 n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i - 1];
15583 else if (s == 17)
15584 n = 3 + bits(dat, pos, 7), pos += 3;
15585 else if (s == 18)
15586 n = 11 + bits(dat, pos, 127), pos += 7;
15587 while (n--)
15588 ldt[i++] = c;
15589 }
15590 }
15591 // length tree distance tree
15592 var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
15593 // max length bits
15594 lbt = max(lt);
15595 // max dist bits
15596 dbt = max(dt);
15597 lm = hMap(lt, lbt, 1);
15598 dm = hMap(dt, dbt, 1);
15599 }
15600 else
15601 throw 'invalid block type';
15602 if (pos > tbts)
15603 throw 'unexpected EOF';
15604 }
15605 // Make sure the buffer can hold this + the largest possible addition
15606 // Maximum chunk size (practically, theoretically infinite) is 2^17;
15607 if (noBuf)
15608 cbuf(bt + 131072);
15609 var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;
15610 var mxa = lbt + dbt + 18;
15611 while (noSt || pos + mxa < tbts) {
15612 // bits read, code
15613 var c = lm[bits16(dat, pos) & lms], sym = c >>> 4;
15614 pos += c & 15;
15615 if (pos > tbts)
15616 throw 'unexpected EOF';
15617 if (!c)
15618 throw 'invalid length/literal';
15619 if (sym < 256)
15620 buf[bt++] = sym;
15621 else if (sym == 256) {
15622 lm = null;
15623 break;
15624 }
15625 else {
15626 var add = sym - 254;
15627 // no extra bits needed if less
15628 if (sym > 264) {
15629 // index
15630 var i = sym - 257, b = fleb[i];
15631 add = bits(dat, pos, (1 << b) - 1) + fl[i];
15632 pos += b;
15633 }
15634 // dist
15635 var d = dm[bits16(dat, pos) & dms], dsym = d >>> 4;
15636 if (!d)
15637 throw 'invalid distance';
15638 pos += d & 15;
15639 var dt = fd[dsym];
15640 if (dsym > 3) {
15641 var b = fdeb[dsym];
15642 dt += bits16(dat, pos) & ((1 << b) - 1), pos += b;
15643 }
15644 if (pos > tbts)
15645 throw 'unexpected EOF';
15646 if (noBuf)
15647 cbuf(bt + 131072);
15648 var end = bt + add;
15649 for (; bt < end; bt += 4) {
15650 buf[bt] = buf[bt - dt];
15651 buf[bt + 1] = buf[bt + 1 - dt];
15652 buf[bt + 2] = buf[bt + 2 - dt];
15653 buf[bt + 3] = buf[bt + 3 - dt];
15654 }
15655 bt = end;
15656 }
15657 }
15658 st.l = lm, st.p = pos, st.b = bt;
15659 if (lm)
15660 final = 1, st.m = lbt, st.d = dm, st.n = dbt;
15661 } while (!final);
15662 return bt == buf.length ? buf : slc(buf, 0, bt);
15663 };
15664 // starting at p, write the minimum number of bits that can hold v to d
15665 var wbits = function (d, p, v) {
15666 v <<= p & 7;
15667 var o = (p / 8) >> 0;
15668 d[o] |= v;
15669 d[o + 1] |= v >>> 8;
15670 };
15671 // starting at p, write the minimum number of bits (>8) that can hold v to d
15672 var wbits16 = function (d, p, v) {
15673 v <<= p & 7;
15674 var o = (p / 8) >> 0;
15675 d[o] |= v;
15676 d[o + 1] |= v >>> 8;
15677 d[o + 2] |= v >>> 16;
15678 };
15679 // creates code lengths from a frequency table
15680 var hTree = function (d, mb) {
15681 // Need extra info to make a tree
15682 var t = [];
15683 for (var i = 0; i < d.length; ++i) {
15684 if (d[i])
15685 t.push({ s: i, f: d[i] });
15686 }
15687 var s = t.length;
15688 var t2 = t.slice();
15689 if (!s)
15690 return [new u8(0), 0];
15691 if (s == 1) {
15692 var v = new u8(t[0].s + 1);
15693 v[t[0].s] = 1;
15694 return [v, 1];
15695 }
15696 t.sort(function (a, b) { return a.f - b.f; });
15697 // after i2 reaches last ind, will be stopped
15698 // freq must be greater than largest possible number of symbols
15699 t.push({ s: -1, f: 25001 });
15700 var l = t[0], r = t[1], i0 = 0, i1 = 1, i2 = 2;
15701 t[0] = { s: -1, f: l.f + r.f, l: l, r: r };
15702 // efficient algorithm from UZIP.js
15703 // i0 is lookbehind, i2 is lookahead - after processing two low-freq
15704 // symbols that combined have high freq, will start processing i2 (high-freq,
15705 // non-composite) symbols instead
15706 // see https://reddit.com/r/photopea/comments/ikekht/uzipjs_questions/
15707 while (i1 != s - 1) {
15708 l = t[t[i0].f < t[i2].f ? i0++ : i2++];
15709 r = t[i0 != i1 && t[i0].f < t[i2].f ? i0++ : i2++];
15710 t[i1++] = { s: -1, f: l.f + r.f, l: l, r: r };
15711 }
15712 var maxSym = t2[0].s;
15713 for (var i = 1; i < s; ++i) {
15714 if (t2[i].s > maxSym)
15715 maxSym = t2[i].s;
15716 }
15717 // code lengths
15718 var tr = new u16(maxSym + 1);
15719 // max bits in tree
15720 var mbt = ln(t[i1 - 1], tr, 0);
15721 if (mbt > mb) {
15722 // more algorithms from UZIP.js
15723 // TODO: find out how this code works (debt)
15724 // ind debt
15725 var i = 0, dt = 0;
15726 // left cost
15727 var lft = mbt - mb, cst = 1 << lft;
15728 t2.sort(function (a, b) { return tr[b.s] - tr[a.s] || a.f - b.f; });
15729 for (; i < s; ++i) {
15730 var i2_1 = t2[i].s;
15731 if (tr[i2_1] > mb) {
15732 dt += cst - (1 << (mbt - tr[i2_1]));
15733 tr[i2_1] = mb;
15734 }
15735 else
15736 break;
15737 }
15738 dt >>>= lft;
15739 while (dt > 0) {
15740 var i2_2 = t2[i].s;
15741 if (tr[i2_2] < mb)
15742 dt -= 1 << (mb - tr[i2_2]++ - 1);
15743 else
15744 ++i;
15745 }
15746 for (; i >= 0 && dt; --i) {
15747 var i2_3 = t2[i].s;
15748 if (tr[i2_3] == mb) {
15749 --tr[i2_3];
15750 ++dt;
15751 }
15752 }
15753 mbt = mb;
15754 }
15755 return [new u8(tr), mbt];
15756 };
15757 // get the max length and assign length codes
15758 var ln = function (n, l, d) {
15759 return n.s == -1
15760 ? Math.max(ln(n.l, l, d + 1), ln(n.r, l, d + 1))
15761 : (l[n.s] = d);
15762 };
15763 // length codes generation
15764 var lc = function (c) {
15765 var s = c.length;
15766 // Note that the semicolon was intentional
15767 while (s && !c[--s])
15768 ;
15769 var cl = new u16(++s);
15770 // ind num streak
15771 var cli = 0, cln = c[0], cls = 1;
15772 var w = function (v) { cl[cli++] = v; };
15773 for (var i = 1; i <= s; ++i) {
15774 if (c[i] == cln && i != s)
15775 ++cls;
15776 else {
15777 if (!cln && cls > 2) {
15778 for (; cls > 138; cls -= 138)
15779 w(32754);
15780 if (cls > 2) {
15781 w(cls > 10 ? ((cls - 11) << 5) | 28690 : ((cls - 3) << 5) | 12305);
15782 cls = 0;
15783 }
15784 }
15785 else if (cls > 3) {
15786 w(cln), --cls;
15787 for (; cls > 6; cls -= 6)
15788 w(8304);
15789 if (cls > 2)
15790 w(((cls - 3) << 5) | 8208), cls = 0;
15791 }
15792 while (cls--)
15793 w(cln);
15794 cls = 1;
15795 cln = c[i];
15796 }
15797 }
15798 return [cl.subarray(0, cli), s];
15799 };
15800 // calculate the length of output from tree, code lengths
15801 var clen = function (cf, cl) {
15802 var l = 0;
15803 for (var i = 0; i < cl.length; ++i)
15804 l += cf[i] * cl[i];
15805 return l;
15806 };
15807 // writes a fixed block
15808 // returns the new bit pos
15809 var wfblk = function (out, pos, dat) {
15810 // no need to write 00 as type: TypedArray defaults to 0
15811 var s = dat.length;
15812 var o = shft(pos + 2);
15813 out[o] = s & 255;
15814 out[o + 1] = s >>> 8;
15815 out[o + 2] = out[o] ^ 255;
15816 out[o + 3] = out[o + 1] ^ 255;
15817 for (var i = 0; i < s; ++i)
15818 out[o + i + 4] = dat[i];
15819 return (o + 4 + s) * 8;
15820 };
15821 // writes a block
15822 var wblk = function (dat, out, final, syms, lf, df, eb, li, bs, bl, p) {
15823 wbits(out, p++, final);
15824 ++lf[256];
15825 var _a = hTree(lf, 15), dlt = _a[0], mlb = _a[1];
15826 var _b = hTree(df, 15), ddt = _b[0], mdb = _b[1];
15827 var _c = lc(dlt), lclt = _c[0], nlc = _c[1];
15828 var _d = lc(ddt), lcdt = _d[0], ndc = _d[1];
15829 var lcfreq = new u16(19);
15830 for (var i = 0; i < lclt.length; ++i)
15831 lcfreq[lclt[i] & 31]++;
15832 for (var i = 0; i < lcdt.length; ++i)
15833 lcfreq[lcdt[i] & 31]++;
15834 var _e = hTree(lcfreq, 7), lct = _e[0], mlcb = _e[1];
15835 var nlcc = 19;
15836 for (; nlcc > 4 && !lct[clim[nlcc - 1]]; --nlcc)
15837 ;
15838 var flen = (bl + 5) << 3;
15839 var ftlen = clen(lf, flt) + clen(df, fdt) + eb;
15840 var dtlen = clen(lf, dlt) + clen(df, ddt) + eb + 14 + 3 * nlcc + clen(lcfreq, lct) + (2 * lcfreq[16] + 3 * lcfreq[17] + 7 * lcfreq[18]);
15841 if (flen <= ftlen && flen <= dtlen)
15842 return wfblk(out, p, dat.subarray(bs, bs + bl));
15843 var lm, ll, dm, dl;
15844 wbits(out, p, 1 + (dtlen < ftlen)), p += 2;
15845 if (dtlen < ftlen) {
15846 lm = hMap(dlt, mlb, 0), ll = dlt, dm = hMap(ddt, mdb, 0), dl = ddt;
15847 var llm = hMap(lct, mlcb, 0);
15848 wbits(out, p, nlc - 257);
15849 wbits(out, p + 5, ndc - 1);
15850 wbits(out, p + 10, nlcc - 4);
15851 p += 14;
15852 for (var i = 0; i < nlcc; ++i)
15853 wbits(out, p + 3 * i, lct[clim[i]]);
15854 p += 3 * nlcc;
15855 var lcts = [lclt, lcdt];
15856 for (var it = 0; it < 2; ++it) {
15857 var clct = lcts[it];
15858 for (var i = 0; i < clct.length; ++i) {
15859 var len = clct[i] & 31;
15860 wbits(out, p, llm[len]), p += lct[len];
15861 if (len > 15)
15862 wbits(out, p, (clct[i] >>> 5) & 127), p += clct[i] >>> 12;
15863 }
15864 }
15865 }
15866 else {
15867 lm = flm, ll = flt, dm = fdm, dl = fdt;
15868 }
15869 for (var i = 0; i < li; ++i) {
15870 if (syms[i] > 255) {
15871 var len = (syms[i] >>> 18) & 31;
15872 wbits16(out, p, lm[len + 257]), p += ll[len + 257];
15873 if (len > 7)
15874 wbits(out, p, (syms[i] >>> 23) & 31), p += fleb[len];
15875 var dst = syms[i] & 31;
15876 wbits16(out, p, dm[dst]), p += dl[dst];
15877 if (dst > 3)
15878 wbits16(out, p, (syms[i] >>> 5) & 8191), p += fdeb[dst];
15879 }
15880 else {
15881 wbits16(out, p, lm[syms[i]]), p += ll[syms[i]];
15882 }
15883 }
15884 wbits16(out, p, lm[256]);
15885 return p + ll[256];
15886 };
15887 // deflate options (nice << 13) | chain
15888 var deo = /*#__PURE__*/ new u32([65540, 131080, 131088, 131104, 262176, 1048704, 1048832, 2114560, 2117632]);
15889 // empty
15890 var et = /*#__PURE__*/ new u8(0);
15891 // compresses data into a raw DEFLATE buffer
15892 var dflt = function (dat, lvl, plvl, pre, post, lst) {
15893 var s = dat.length;
15894 var o = new u8(pre + s + 5 * (1 + Math.floor(s / 7000)) + post);
15895 // writing to this writes to the output buffer
15896 var w = o.subarray(pre, o.length - post);
15897 var pos = 0;
15898 if (!lvl || s < 8) {
15899 for (var i = 0; i <= s; i += 65535) {
15900 // end
15901 var e = i + 65535;
15902 if (e < s) {
15903 // write full block
15904 pos = wfblk(w, pos, dat.subarray(i, e));
15905 }
15906 else {
15907 // write final block
15908 w[i] = lst;
15909 pos = wfblk(w, pos, dat.subarray(i, s));
15910 }
15911 }
15912 }
15913 else {
15914 var opt = deo[lvl - 1];
15915 var n = opt >>> 13, c = opt & 8191;
15916 var msk_1 = (1 << plvl) - 1;
15917 // prev 2-byte val map curr 2-byte val map
15918 var prev = new u16(32768), head = new u16(msk_1 + 1);
15919 var bs1_1 = Math.ceil(plvl / 3), bs2_1 = 2 * bs1_1;
15920 var hsh = function (i) { return (dat[i] ^ (dat[i + 1] << bs1_1) ^ (dat[i + 2] << bs2_1)) & msk_1; };
15921 // 24576 is an arbitrary number of maximum symbols per block
15922 // 424 buffer for last block
15923 var syms = new u32(25000);
15924 // length/literal freq distance freq
15925 var lf = new u16(288), df = new u16(32);
15926 // l/lcnt exbits index l/lind waitdx bitpos
15927 var lc_1 = 0, eb = 0, i = 0, li = 0, wi = 0, bs = 0;
15928 for (; i < s; ++i) {
15929 // hash value
15930 var hv = hsh(i);
15931 // index mod 32768
15932 var imod = i & 32767;
15933 // previous index with this value
15934 var pimod = head[hv];
15935 prev[imod] = pimod;
15936 head[hv] = imod;
15937 // We always should modify head and prev, but only add symbols if
15938 // this data is not yet processed ("wait" for wait index)
15939 if (wi <= i) {
15940 // bytes remaining
15941 var rem = s - i;
15942 if ((lc_1 > 7000 || li > 24576) && rem > 423) {
15943 pos = wblk(dat, w, 0, syms, lf, df, eb, li, bs, i - bs, pos);
15944 li = lc_1 = eb = 0, bs = i;
15945 for (var j = 0; j < 286; ++j)
15946 lf[j] = 0;
15947 for (var j = 0; j < 30; ++j)
15948 df[j] = 0;
15949 }
15950 // len dist chain
15951 var l = 2, d = 0, ch_1 = c, dif = (imod - pimod) & 32767;
15952 if (rem > 2 && hv == hsh(i - dif)) {
15953 var maxn = Math.min(n, rem) - 1;
15954 var maxd = Math.min(32767, i);
15955 // max possible length
15956 // not capped at dif because decompressors implement "rolling" index population
15957 var ml = Math.min(258, rem);
15958 while (dif <= maxd && --ch_1 && imod != pimod) {
15959 if (dat[i + l] == dat[i + l - dif]) {
15960 var nl = 0;
15961 for (; nl < ml && dat[i + nl] == dat[i + nl - dif]; ++nl)
15962 ;
15963 if (nl > l) {
15964 l = nl, d = dif;
15965 // break out early when we reach "nice" (we are satisfied enough)
15966 if (nl > maxn)
15967 break;
15968 // now, find the rarest 2-byte sequence within this
15969 // length of literals and search for that instead.
15970 // Much faster than just using the start
15971 var mmd = Math.min(dif, nl - 2);
15972 var md = 0;
15973 for (var j = 0; j < mmd; ++j) {
15974 var ti = (i - dif + j + 32768) & 32767;
15975 var pti = prev[ti];
15976 var cd = (ti - pti + 32768) & 32767;
15977 if (cd > md)
15978 md = cd, pimod = ti;
15979 }
15980 }
15981 }
15982 // check the previous match
15983 imod = pimod, pimod = prev[imod];
15984 dif += (imod - pimod + 32768) & 32767;
15985 }
15986 }
15987 // d will be nonzero only when a match was found
15988 if (d) {
15989 // store both dist and len data in one Uint32
15990 // Make sure this is recognized as a len/dist with 28th bit (2^28)
15991 syms[li++] = 268435456 | (revfl[l] << 18) | revfd[d];
15992 var lin = revfl[l] & 31, din = revfd[d] & 31;
15993 eb += fleb[lin] + fdeb[din];
15994 ++lf[257 + lin];
15995 ++df[din];
15996 wi = i + l;
15997 ++lc_1;
15998 }
15999 else {
16000 syms[li++] = dat[i];
16001 ++lf[dat[i]];
16002 }
16003 }
16004 }
16005 pos = wblk(dat, w, lst, syms, lf, df, eb, li, bs, i - bs, pos);
16006 // this is the easiest way to avoid needing to maintain state
16007 if (!lst)
16008 pos = wfblk(w, pos, et);
16009 }
16010 return slc(o, 0, pre + shft(pos) + post);
16011 };
16012 // Alder32
16013 var adler = function () {
16014 var a = 1, b = 0;
16015 return {
16016 p: function (d) {
16017 // closures have awful performance
16018 var n = a, m = b;
16019 var l = d.length;
16020 for (var i = 0; i != l;) {
16021 var e = Math.min(i + 5552, l);
16022 for (; i < e; ++i)
16023 n += d[i], m += n;
16024 n %= 65521, m %= 65521;
16025 }
16026 a = n, b = m;
16027 },
16028 d: function () { return ((a >>> 8) << 16 | (b & 255) << 8 | (b >>> 8)) + ((a & 255) << 23) * 2; }
16029 };
16030 };
16031 // deflate with opts
16032 var dopt = function (dat, opt, pre, post, st) {
16033 return dflt(dat, opt.level == null ? 6 : opt.level, opt.mem == null ? Math.ceil(Math.max(8, Math.min(13, Math.log(dat.length))) * 1.5) : (12 + opt.mem), pre, post, !st);
16034 };
16035 // write bytes
16036 var wbytes = function (d, b, v) {
16037 for (; v; ++b)
16038 d[b] = v, v >>>= 8;
16039 };
16040 // zlib header
16041 var zlh = function (c, o) {
16042 var lv = o.level, fl = lv == 0 ? 0 : lv < 6 ? 1 : lv == 9 ? 3 : 2;
16043 c[0] = 120, c[1] = (fl << 6) | (fl ? (32 - 2 * fl) : 1);
16044 };
16045 // zlib valid
16046 var zlv = function (d) {
16047 if ((d[0] & 15) != 8 || (d[0] >>> 4) > 7 || ((d[0] << 8 | d[1]) % 31))
16048 throw 'invalid zlib data';
16049 if (d[1] & 32)
16050 throw 'invalid zlib data: preset dictionaries not supported';
16051 };
16052 /**
16053 * Compress data with Zlib
16054 * @param data The data to compress
16055 * @param opts The compression options
16056 * @returns The zlib-compressed version of the data
16057 */
16058 function zlibSync(data, opts) {
16059 if (opts === void 0) { opts = {}; }
16060 var a = adler();
16061 a.p(data);
16062 var d = dopt(data, opts, 2, 4);
16063 return zlh(d, opts), wbytes(d, d.length - 4, a.d()), d;
16064 }
16065 /**
16066 * Expands Zlib data
16067 * @param data The data to decompress
16068 * @param out Where to write the data. Saves memory if you know the decompressed size and provide an output buffer of that length.
16069 * @returns The decompressed version of the data
16070 */
16071 function unzlibSync(data, out) {
16072 return inflt((zlv(data), data.subarray(2, -4)), out);
16073 }
16074
16075 /**
16076 * @license
16077 * jsPDF filters PlugIn
16078 * Copyright (c) 2014 Aras Abbasi
16079 *
16080 * Licensed under the MIT License.
16081 * http://opensource.org/licenses/mit-license
16082 */
16083
16084 (function(jsPDFAPI) {
16085
16086 var ASCII85Encode = function(a) {
16087 var b, c, d, e, f, g, h, i, j, k;
16088 // eslint-disable-next-line no-control-regex
16089 for (
16090 !/[^\x00-\xFF]/.test(a),
16091 b = "\x00\x00\x00\x00".slice(a.length % 4 || 4),
16092 a += b,
16093 c = [],
16094 d = 0,
16095 e = a.length;
16096 e > d;
16097 d += 4
16098 )
16099 (f =
16100 (a.charCodeAt(d) << 24) +
16101 (a.charCodeAt(d + 1) << 16) +
16102 (a.charCodeAt(d + 2) << 8) +
16103 a.charCodeAt(d + 3)),
16104 0 !== f
16105 ? ((k = f % 85),
16106 (f = (f - k) / 85),
16107 (j = f % 85),
16108 (f = (f - j) / 85),
16109 (i = f % 85),
16110 (f = (f - i) / 85),
16111 (h = f % 85),
16112 (f = (f - h) / 85),
16113 (g = f % 85),
16114 c.push(g + 33, h + 33, i + 33, j + 33, k + 33))
16115 : c.push(122);
16116 return (
16117 (function(a, b) {
16118 for (var c = b; c > 0; c--) a.pop();
16119 })(c, b.length),
16120 String.fromCharCode.apply(String, c) + "~>"
16121 );
16122 };
16123
16124 var ASCII85Decode = function(a) {
16125 var c,
16126 d,
16127 e,
16128 f,
16129 g,
16130 h = String,
16131 l = "length",
16132 w = 255,
16133 x = "charCodeAt",
16134 y = "slice",
16135 z = "replace";
16136 for (
16137 "~>" === a[y](-2),
16138 a = a[y](0, -2)
16139 [z](/\s/g, "")
16140 [z]("z", "!!!!!"),
16141 c = "uuuuu"[y](a[l] % 5 || 5),
16142 a += c,
16143 e = [],
16144 f = 0,
16145 g = a[l];
16146 g > f;
16147 f += 5
16148 )
16149 (d =
16150 52200625 * (a[x](f) - 33) +
16151 614125 * (a[x](f + 1) - 33) +
16152 7225 * (a[x](f + 2) - 33) +
16153 85 * (a[x](f + 3) - 33) +
16154 (a[x](f + 4) - 33)),
16155 e.push(w & (d >> 24), w & (d >> 16), w & (d >> 8), w & d);
16156 return (
16157 (function(a, b) {
16158 for (var c = b; c > 0; c--) a.pop();
16159 })(e, c[l]),
16160 h.fromCharCode.apply(h, e)
16161 );
16162 };
16163
16164 var ASCIIHexEncode = function(value) {
16165 return (
16166 value
16167 .split("")
16168 .map(function(value) {
16169 return ("0" + value.charCodeAt().toString(16)).slice(-2);
16170 })
16171 .join("") + ">"
16172 );
16173 };
16174
16175 var ASCIIHexDecode = function(value) {
16176 var regexCheckIfHex = new RegExp(/^([0-9A-Fa-f]{2})+$/);
16177 value = value.replace(/\s/g, "");
16178 if (value.indexOf(">") !== -1) {
16179 value = value.substr(0, value.indexOf(">"));
16180 }
16181 if (value.length % 2) {
16182 value += "0";
16183 }
16184 if (regexCheckIfHex.test(value) === false) {
16185 return "";
16186 }
16187 var result = "";
16188 for (var i = 0; i < value.length; i += 2) {
16189 result += String.fromCharCode("0x" + (value[i] + value[i + 1]));
16190 }
16191 return result;
16192 };
16193 /*
16194 var FlatePredictors = {
16195 None: 1,
16196 TIFF: 2,
16197 PNG_None: 10,
16198 PNG_Sub: 11,
16199 PNG_Up: 12,
16200 PNG_Average: 13,
16201 PNG_Paeth: 14,
16202 PNG_Optimum: 15
16203 };
16204 */
16205
16206 var FlateEncode = function(data) {
16207 var arr = new Uint8Array(data.length);
16208 var i = data.length;
16209 while (i--) {
16210 arr[i] = data.charCodeAt(i);
16211 }
16212 arr = zlibSync(arr);
16213 data = arr.reduce(function(data, byte) {
16214 return data + String.fromCharCode(byte);
16215 }, "");
16216 return data;
16217 };
16218
16219 jsPDFAPI.processDataByFilters = function(origData, filterChain) {
16220 var i = 0;
16221 var data = origData || "";
16222 var reverseChain = [];
16223 filterChain = filterChain || [];
16224
16225 if (typeof filterChain === "string") {
16226 filterChain = [filterChain];
16227 }
16228
16229 for (i = 0; i < filterChain.length; i += 1) {
16230 switch (filterChain[i]) {
16231 case "ASCII85Decode":
16232 case "/ASCII85Decode":
16233 data = ASCII85Decode(data);
16234 reverseChain.push("/ASCII85Encode");
16235 break;
16236 case "ASCII85Encode":
16237 case "/ASCII85Encode":
16238 data = ASCII85Encode(data);
16239 reverseChain.push("/ASCII85Decode");
16240 break;
16241 case "ASCIIHexDecode":
16242 case "/ASCIIHexDecode":
16243 data = ASCIIHexDecode(data);
16244 reverseChain.push("/ASCIIHexEncode");
16245 break;
16246 case "ASCIIHexEncode":
16247 case "/ASCIIHexEncode":
16248 data = ASCIIHexEncode(data);
16249 reverseChain.push("/ASCIIHexDecode");
16250 break;
16251 case "FlateEncode":
16252 case "/FlateEncode":
16253 data = FlateEncode(data);
16254 reverseChain.push("/FlateDecode");
16255 break;
16256 default:
16257 throw new Error(
16258 'The filter: "' + filterChain[i] + '" is not implemented'
16259 );
16260 }
16261 }
16262
16263 return { data: data, reverseChain: reverseChain.reverse().join(" ") };
16264 };
16265 })(jsPDF.API);
16266
16267 /**
16268 * @license
16269 * jsPDF fileloading PlugIn
16270 * Copyright (c) 2018 Aras Abbasi (aras.abbasi@gmail.com)
16271 *
16272 * Licensed under the MIT License.
16273 * http://opensource.org/licenses/mit-license
16274 */
16275
16276 /**
16277 * @name fileloading
16278 * @module
16279 */
16280 (function(jsPDFAPI) {
16281
16282 /**
16283 * @name loadFile
16284 * @function
16285 * @param {string} url
16286 * @param {boolean} sync
16287 * @param {function} callback
16288 * @returns {string|undefined} result
16289 */
16290 jsPDFAPI.loadFile = function(url, sync, callback) {
16291 return browserRequest(url, sync, callback);
16292
16293 };
16294
16295 /**
16296 * @name loadImageFile
16297 * @function
16298 * @param {string} path
16299 * @param {boolean} sync
16300 * @param {function} callback
16301 */
16302 jsPDFAPI.loadImageFile = jsPDFAPI.loadFile;
16303
16304 function browserRequest(url, sync, callback) {
16305 sync = sync === false ? false : true;
16306 callback = typeof callback === "function" ? callback : function() {};
16307 var result = undefined;
16308
16309 var xhr = function(url, sync, callback) {
16310 var request = new XMLHttpRequest();
16311 var i = 0;
16312
16313 var sanitizeUnicode = function(data) {
16314 var dataLength = data.length;
16315 var charArray = [];
16316 var StringFromCharCode = String.fromCharCode;
16317
16318 //Transform Unicode to ASCII
16319 for (i = 0; i < dataLength; i += 1) {
16320 charArray.push(StringFromCharCode(data.charCodeAt(i) & 0xff));
16321 }
16322 return charArray.join("");
16323 };
16324
16325 request.open("GET", url, !sync);
16326 // XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
16327 request.overrideMimeType("text/plain; charset=x-user-defined");
16328
16329 if (sync === false) {
16330 request.onload = function() {
16331 if (request.status === 200) {
16332 callback(sanitizeUnicode(this.responseText));
16333 } else {
16334 callback(undefined);
16335 }
16336 };
16337 }
16338 request.send(null);
16339
16340 if (sync && request.status === 200) {
16341 return sanitizeUnicode(request.responseText);
16342 }
16343 };
16344 try {
16345 result = xhr(url, sync, callback);
16346 // eslint-disable-next-line no-empty
16347 } catch (e) {}
16348 return result;
16349 }
16350 })(jsPDF.API);
16351
16352 /**
16353 * @license
16354 * Copyright (c) 2018 Erik Koopmans
16355 * Released under the MIT License.
16356 *
16357 * Licensed under the MIT License.
16358 * http://opensource.org/licenses/mit-license
16359 */
16360
16361 /**
16362 * jsPDF html PlugIn
16363 *
16364 * @name html
16365 * @module
16366 */
16367 (function(jsPDFAPI) {
16368
16369 function loadHtml2Canvas() {
16370 return (function() {
16371 if (globalObject["html2canvas"]) {
16372 return Promise.resolve(globalObject["html2canvas"]);
16373 }
16374
16375
16376 if (typeof exports === "object" && typeof module !== "undefined") {
16377 return new Promise(function(resolve, reject) {
16378 try {
16379 resolve(require("html2canvas"));
16380 } catch (e) {
16381 reject(e);
16382 }
16383 });
16384 }
16385 if (typeof define === "function" && define.amd) {
16386 return new Promise(function(resolve, reject) {
16387 try {
16388 require(["html2canvas"], resolve);
16389 } catch (e) {
16390 reject(e);
16391 }
16392 });
16393 }
16394 return Promise.reject(new Error("Could not load html2canvas"));
16395 })()
16396 .catch(function(e) {
16397 return Promise.reject(new Error("Could not load html2canvas: " + e));
16398 })
16399 .then(function(html2canvas) {
16400 return html2canvas.default ? html2canvas.default : html2canvas;
16401 });
16402 }
16403
16404 function loadDomPurify() {
16405 return (function() {
16406 if (globalObject["DOMPurify"]) {
16407 return Promise.resolve(globalObject["DOMPurify"]);
16408 }
16409
16410
16411 if (typeof exports === "object" && typeof module !== "undefined") {
16412 return new Promise(function(resolve, reject) {
16413 try {
16414 resolve(require("dompurify"));
16415 } catch (e) {
16416 reject(e);
16417 }
16418 });
16419 }
16420 if (typeof define === "function" && define.amd) {
16421 return new Promise(function(resolve, reject) {
16422 try {
16423 require(["dompurify"], resolve);
16424 } catch (e) {
16425 reject(e);
16426 }
16427 });
16428 }
16429 return Promise.reject(new Error("Could not load dompurify"));
16430 })()
16431 .catch(function(e) {
16432 return Promise.reject(new Error("Could not load dompurify: " + e));
16433 })
16434 .then(function(dompurify) {
16435 return dompurify.default ? dompurify.default : dompurify;
16436 });
16437 }
16438
16439 /**
16440 * Determine the type of a variable/object.
16441 *
16442 * @private
16443 * @ignore
16444 */
16445 var objType = function(obj) {
16446 var type = typeof obj;
16447 if (type === "undefined") return "undefined";
16448 else if (type === "string" || obj instanceof String) return "string";
16449 else if (type === "number" || obj instanceof Number) return "number";
16450 else if (type === "function" || obj instanceof Function) return "function";
16451 else if (!!obj && obj.constructor === Array) return "array";
16452 else if (obj && obj.nodeType === 1) return "element";
16453 else if (type === "object") return "object";
16454 else return "unknown";
16455 };
16456
16457 /**
16458 * Create an HTML element with optional className, innerHTML, and style.
16459 *
16460 * @private
16461 * @ignore
16462 */
16463 var createElement = function(tagName, opt) {
16464 var el = document.createElement(tagName);
16465 if (opt.className) el.className = opt.className;
16466 if (opt.innerHTML && opt.dompurify) {
16467 el.innerHTML = opt.dompurify.sanitize(opt.innerHTML);
16468 }
16469 for (var key in opt.style) {
16470 el.style[key] = opt.style[key];
16471 }
16472 return el;
16473 };
16474
16475 /**
16476 * Deep-clone a node and preserve contents/properties.
16477 *
16478 * @private
16479 * @ignore
16480 */
16481 var cloneNode = function(node, javascriptEnabled) {
16482 // Recursively clone the node.
16483 var clone =
16484 node.nodeType === 3
16485 ? document.createTextNode(node.nodeValue)
16486 : node.cloneNode(false);
16487 for (var child = node.firstChild; child; child = child.nextSibling) {
16488 if (
16489 javascriptEnabled === true ||
16490 child.nodeType !== 1 ||
16491 child.nodeName !== "SCRIPT"
16492 ) {
16493 clone.appendChild(cloneNode(child, javascriptEnabled));
16494 }
16495 }
16496
16497 if (node.nodeType === 1) {
16498 // Preserve contents/properties of special nodes.
16499 if (node.nodeName === "CANVAS") {
16500 clone.width = node.width;
16501 clone.height = node.height;
16502 clone.getContext("2d").drawImage(node, 0, 0);
16503 } else if (node.nodeName === "TEXTAREA" || node.nodeName === "SELECT") {
16504 clone.value = node.value;
16505 }
16506
16507 // Preserve the node's scroll position when it loads.
16508 clone.addEventListener(
16509 "load",
16510 function() {
16511 clone.scrollTop = node.scrollTop;
16512 clone.scrollLeft = node.scrollLeft;
16513 },
16514 true
16515 );
16516 }
16517
16518 // Return the cloned node.
16519 return clone;
16520 };
16521
16522 /* ----- CONSTRUCTOR ----- */
16523
16524 var Worker = function Worker(opt) {
16525 // Create the root parent for the proto chain, and the starting Worker.
16526 var root = Object.assign(
16527 Worker.convert(Promise.resolve()),
16528 JSON.parse(JSON.stringify(Worker.template))
16529 );
16530 var self = Worker.convert(Promise.resolve(), root);
16531
16532 // Set progress, optional settings, and return.
16533 self = self.setProgress(1, Worker, 1, [Worker]);
16534 self = self.set(opt);
16535 return self;
16536 };
16537
16538 // Boilerplate for subclassing Promise.
16539 Worker.prototype = Object.create(Promise.prototype);
16540 Worker.prototype.constructor = Worker;
16541
16542 // Converts/casts promises into Workers.
16543 Worker.convert = function convert(promise, inherit) {
16544 // Uses prototypal inheritance to receive changes made to ancestors' properties.
16545 promise.__proto__ = inherit || Worker.prototype;
16546 return promise;
16547 };
16548
16549 Worker.template = {
16550 prop: {
16551 src: null,
16552 container: null,
16553 overlay: null,
16554 canvas: null,
16555 img: null,
16556 pdf: null,
16557 pageSize: null,
16558 callback: function() {}
16559 },
16560 progress: {
16561 val: 0,
16562 state: null,
16563 n: 0,
16564 stack: []
16565 },
16566 opt: {
16567 filename: "file.pdf",
16568 margin: [0, 0, 0, 0],
16569 enableLinks: true,
16570 x: 0,
16571 y: 0,
16572 html2canvas: {},
16573 jsPDF: {},
16574 backgroundColor: "transparent"
16575 }
16576 };
16577
16578 /* ----- FROM / TO ----- */
16579
16580 Worker.prototype.from = function from(src, type) {
16581 function getType(src) {
16582 switch (objType(src)) {
16583 case "string":
16584 return "string";
16585 case "element":
16586 return src.nodeName.toLowerCase() === "canvas" ? "canvas" : "element";
16587 default:
16588 return "unknown";
16589 }
16590 }
16591
16592 return this.then(function from_main() {
16593 type = type || getType(src);
16594 switch (type) {
16595 case "string":
16596 return this.then(loadDomPurify).then(function(dompurify) {
16597 return this.set({
16598 src: createElement("div", {
16599 innerHTML: src,
16600 dompurify: dompurify
16601 })
16602 });
16603 });
16604 case "element":
16605 return this.set({ src: src });
16606 case "canvas":
16607 return this.set({ canvas: src });
16608 case "img":
16609 return this.set({ img: src });
16610 default:
16611 return this.error("Unknown source type.");
16612 }
16613 });
16614 };
16615
16616 Worker.prototype.to = function to(target) {
16617 // Route the 'to' request to the appropriate method.
16618 switch (target) {
16619 case "container":
16620 return this.toContainer();
16621 case "canvas":
16622 return this.toCanvas();
16623 case "img":
16624 return this.toImg();
16625 case "pdf":
16626 return this.toPdf();
16627 default:
16628 return this.error("Invalid target.");
16629 }
16630 };
16631
16632 Worker.prototype.toContainer = function toContainer() {
16633 // Set up function prerequisites.
16634 var prereqs = [
16635 function checkSrc() {
16636 return (
16637 this.prop.src || this.error("Cannot duplicate - no source HTML.")
16638 );
16639 },
16640 function checkPageSize() {
16641 return this.prop.pageSize || this.setPageSize();
16642 }
16643 ];
16644 return this.thenList(prereqs).then(function toContainer_main() {
16645 // Define the CSS styles for the container and its overlay parent.
16646 var overlayCSS = {
16647 position: "fixed",
16648 overflow: "hidden",
16649 zIndex: 1000,
16650 left: "-100000px",
16651 right: 0,
16652 bottom: 0,
16653 top: 0
16654 };
16655 var containerCSS = {
16656 position: "relative",
16657 display: "inline-block",
16658 width:
16659 Math.max(
16660 this.prop.src.clientWidth,
16661 this.prop.src.scrollWidth,
16662 this.prop.src.offsetWidth
16663 ) + "px",
16664 left: 0,
16665 right: 0,
16666 top: 0,
16667 margin: "auto",
16668 backgroundColor: this.opt.backgroundColor
16669 }; // Set the overlay to hidden (could be changed in the future to provide a print preview).
16670
16671 var source = cloneNode(
16672 this.prop.src,
16673 this.opt.html2canvas.javascriptEnabled
16674 );
16675
16676 if (source.tagName === "BODY") {
16677 containerCSS.height =
16678 Math.max(
16679 document.body.scrollHeight,
16680 document.body.offsetHeight,
16681 document.documentElement.clientHeight,
16682 document.documentElement.scrollHeight,
16683 document.documentElement.offsetHeight
16684 ) + "px";
16685 }
16686
16687 this.prop.overlay = createElement("div", {
16688 className: "html2pdf__overlay",
16689 style: overlayCSS
16690 });
16691 this.prop.container = createElement("div", {
16692 className: "html2pdf__container",
16693 style: containerCSS
16694 });
16695 this.prop.container.appendChild(source);
16696 this.prop.container.firstChild.appendChild(
16697 createElement("div", {
16698 style: {
16699 clear: "both",
16700 border: "0 none transparent",
16701 margin: 0,
16702 padding: 0,
16703 height: 0
16704 }
16705 })
16706 );
16707 this.prop.container.style.float = "none";
16708 this.prop.overlay.appendChild(this.prop.container);
16709 document.body.appendChild(this.prop.overlay);
16710 this.prop.container.firstChild.style.position = "relative";
16711 this.prop.container.height =
16712 Math.max(
16713 this.prop.container.firstChild.clientHeight,
16714 this.prop.container.firstChild.scrollHeight,
16715 this.prop.container.firstChild.offsetHeight
16716 ) + "px";
16717 });
16718 };
16719
16720 Worker.prototype.toCanvas = function toCanvas() {
16721 // Set up function prerequisites.
16722 var prereqs = [
16723 function checkContainer() {
16724 return (
16725 document.body.contains(this.prop.container) || this.toContainer()
16726 );
16727 }
16728 ];
16729
16730 // Fulfill prereqs then create the canvas.
16731 return this.thenList(prereqs)
16732 .then(loadHtml2Canvas)
16733 .then(function toCanvas_main(html2canvas) {
16734 // Handle old-fashioned 'onrendered' argument.
16735 var options = Object.assign({}, this.opt.html2canvas);
16736 delete options.onrendered;
16737
16738 return html2canvas(this.prop.container, options);
16739 })
16740 .then(function toCanvas_post(canvas) {
16741 // Handle old-fashioned 'onrendered' argument.
16742 var onRendered = this.opt.html2canvas.onrendered || function() {};
16743 onRendered(canvas);
16744
16745 this.prop.canvas = canvas;
16746 document.body.removeChild(this.prop.overlay);
16747 });
16748 };
16749
16750 Worker.prototype.toContext2d = function toContext2d() {
16751 // Set up function prerequisites.
16752 var prereqs = [
16753 function checkContainer() {
16754 return (
16755 document.body.contains(this.prop.container) || this.toContainer()
16756 );
16757 }
16758 ];
16759
16760 // Fulfill prereqs then create the canvas.
16761 return this.thenList(prereqs)
16762 .then(loadHtml2Canvas)
16763 .then(function toContext2d_main(html2canvas) {
16764 // Handle old-fashioned 'onrendered' argument.
16765
16766 var pdf = this.opt.jsPDF;
16767 var fontFaces = this.opt.fontFaces;
16768 var options = Object.assign(
16769 {
16770 async: true,
16771 allowTaint: true,
16772 scale: 1,
16773 scrollX: this.opt.scrollX || 0,
16774 scrollY: this.opt.scrollY || 0,
16775 backgroundColor: "#ffffff",
16776 imageTimeout: 15000,
16777 logging: true,
16778 proxy: null,
16779 removeContainer: true,
16780 foreignObjectRendering: false,
16781 useCORS: false
16782 },
16783 this.opt.html2canvas
16784 );
16785 delete options.onrendered;
16786
16787 pdf.context2d.autoPaging = true;
16788 pdf.context2d.posX = this.opt.x;
16789 pdf.context2d.posY = this.opt.y;
16790 pdf.context2d.fontFaces = fontFaces;
16791
16792 if (fontFaces) {
16793 for (var i = 0; i < fontFaces.length; ++i) {
16794 var font = fontFaces[i];
16795 var src = font.src.find(function(src) {
16796 return src.format === "truetype";
16797 });
16798
16799 if (src) {
16800 pdf.addFont(src.url, font.ref.name, font.ref.style);
16801 }
16802 }
16803 }
16804
16805 options.windowHeight = options.windowHeight || 0;
16806 options.windowHeight =
16807 options.windowHeight == 0
16808 ? Math.max(
16809 this.prop.container.clientHeight,
16810 this.prop.container.scrollHeight,
16811 this.prop.container.offsetHeight
16812 )
16813 : options.windowHeight;
16814
16815 return html2canvas(this.prop.container, options);
16816 })
16817 .then(function toContext2d_post(canvas) {
16818 // Handle old-fashioned 'onrendered' argument.
16819 var onRendered = this.opt.html2canvas.onrendered || function() {};
16820 onRendered(canvas);
16821
16822 this.prop.canvas = canvas;
16823 document.body.removeChild(this.prop.overlay);
16824 });
16825 };
16826
16827 Worker.prototype.toImg = function toImg() {
16828 // Set up function prerequisites.
16829 var prereqs = [
16830 function checkCanvas() {
16831 return this.prop.canvas || this.toCanvas();
16832 }
16833 ];
16834
16835 // Fulfill prereqs then create the image.
16836 return this.thenList(prereqs).then(function toImg_main() {
16837 var imgData = this.prop.canvas.toDataURL(
16838 "image/" + this.opt.image.type,
16839 this.opt.image.quality
16840 );
16841 this.prop.img = document.createElement("img");
16842 this.prop.img.src = imgData;
16843 });
16844 };
16845
16846 Worker.prototype.toPdf = function toPdf() {
16847 // Set up function prerequisites.
16848 var prereqs = [
16849 function checkContext2d() {
16850 return this.toContext2d();
16851 }
16852 //function checkCanvas() { return this.prop.canvas || this.toCanvas(); }
16853 ];
16854
16855 // Fulfill prereqs then create the image.
16856 return this.thenList(prereqs).then(function toPdf_main() {
16857 // Create local copies of frequently used properties.
16858 this.prop.pdf = this.prop.pdf || this.opt.jsPDF;
16859 });
16860 };
16861
16862 /* ----- OUTPUT / SAVE ----- */
16863
16864 Worker.prototype.output = function output(type, options, src) {
16865 // Redirect requests to the correct function (outputPdf / outputImg).
16866 src = src || "pdf";
16867 if (src.toLowerCase() === "img" || src.toLowerCase() === "image") {
16868 return this.outputImg(type, options);
16869 } else {
16870 return this.outputPdf(type, options);
16871 }
16872 };
16873
16874 Worker.prototype.outputPdf = function outputPdf(type, options) {
16875 // Set up function prerequisites.
16876 var prereqs = [
16877 function checkPdf() {
16878 return this.prop.pdf || this.toPdf();
16879 }
16880 ];
16881
16882 // Fulfill prereqs then perform the appropriate output.
16883 return this.thenList(prereqs).then(function outputPdf_main() {
16884 /* Currently implemented output types:
16885 * https://rawgit.com/MrRio/jsPDF/master/docs/jspdf.js.html#line992
16886 * save(options), arraybuffer, blob, bloburi/bloburl,
16887 * datauristring/dataurlstring, dataurlnewwindow, datauri/dataurl
16888 */
16889 return this.prop.pdf.output(type, options);
16890 });
16891 };
16892
16893 Worker.prototype.outputImg = function outputImg(type) {
16894 // Set up function prerequisites.
16895 var prereqs = [
16896 function checkImg() {
16897 return this.prop.img || this.toImg();
16898 }
16899 ];
16900
16901 // Fulfill prereqs then perform the appropriate output.
16902 return this.thenList(prereqs).then(function outputImg_main() {
16903 switch (type) {
16904 case undefined:
16905 case "img":
16906 return this.prop.img;
16907 case "datauristring":
16908 case "dataurlstring":
16909 return this.prop.img.src;
16910 case "datauri":
16911 case "dataurl":
16912 return (document.location.href = this.prop.img.src);
16913 default:
16914 throw 'Image output type "' + type + '" is not supported.';
16915 }
16916 });
16917 };
16918
16919 Worker.prototype.save = function save(filename) {
16920 // Set up function prerequisites.
16921 var prereqs = [
16922 function checkPdf() {
16923 return this.prop.pdf || this.toPdf();
16924 }
16925 ];
16926
16927 // Fulfill prereqs, update the filename (if provided), and save the PDF.
16928 return this.thenList(prereqs)
16929 .set(filename ? { filename: filename } : null)
16930 .then(function save_main() {
16931 this.prop.pdf.save(this.opt.filename);
16932 });
16933 };
16934
16935 Worker.prototype.doCallback = function doCallback() {
16936 // Set up function prerequisites.
16937 var prereqs = [
16938 function checkPdf() {
16939 return this.prop.pdf || this.toPdf();
16940 }
16941 ];
16942
16943 // Fulfill prereqs, update the filename (if provided), and save the PDF.
16944 return this.thenList(prereqs).then(function doCallback_main() {
16945 this.prop.callback(this.prop.pdf);
16946 });
16947 };
16948
16949 /* ----- SET / GET ----- */
16950
16951 Worker.prototype.set = function set(opt) {
16952 // TODO: Implement ordered pairs?
16953
16954 // Silently ignore invalid or empty input.
16955 if (objType(opt) !== "object") {
16956 return this;
16957 }
16958
16959 // Build an array of setter functions to queue.
16960 var fns = Object.keys(opt || {}).map(function(key) {
16961 if (key in Worker.template.prop) {
16962 // Set pre-defined properties.
16963 return function set_prop() {
16964 this.prop[key] = opt[key];
16965 };
16966 } else {
16967 switch (key) {
16968 case "margin":
16969 return this.setMargin.bind(this, opt.margin);
16970 case "jsPDF":
16971 return function set_jsPDF() {
16972 this.opt.jsPDF = opt.jsPDF;
16973 return this.setPageSize();
16974 };
16975 case "pageSize":
16976 return this.setPageSize.bind(this, opt.pageSize);
16977 default:
16978 // Set any other properties in opt.
16979 return function set_opt() {
16980 this.opt[key] = opt[key];
16981 };
16982 }
16983 }
16984 }, this);
16985
16986 // Set properties within the promise chain.
16987 return this.then(function set_main() {
16988 return this.thenList(fns);
16989 });
16990 };
16991
16992 Worker.prototype.get = function get(key, cbk) {
16993 return this.then(function get_main() {
16994 // Fetch the requested property, either as a predefined prop or in opt.
16995 var val = key in Worker.template.prop ? this.prop[key] : this.opt[key];
16996 return cbk ? cbk(val) : val;
16997 });
16998 };
16999
17000 Worker.prototype.setMargin = function setMargin(margin) {
17001 return this.then(function setMargin_main() {
17002 // Parse the margin property.
17003 switch (objType(margin)) {
17004 case "number":
17005 margin = [margin, margin, margin, margin];
17006 // eslint-disable-next-line no-fallthrough
17007 case "array":
17008 if (margin.length === 2) {
17009 margin = [margin[0], margin[1], margin[0], margin[1]];
17010 }
17011 if (margin.length === 4) {
17012 break;
17013 }
17014 // eslint-disable-next-line no-fallthrough
17015 default:
17016 return this.error("Invalid margin array.");
17017 }
17018
17019 // Set the margin property, then update pageSize.
17020 this.opt.margin = margin;
17021 }).then(this.setPageSize);
17022 };
17023
17024 Worker.prototype.setPageSize = function setPageSize(pageSize) {
17025 function toPx(val, k) {
17026 return Math.floor(((val * k) / 72) * 96);
17027 }
17028
17029 return this.then(function setPageSize_main() {
17030 // Retrieve page-size based on jsPDF settings, if not explicitly provided.
17031 pageSize = pageSize || jsPDF.getPageSize(this.opt.jsPDF);
17032
17033 // Add 'inner' field if not present.
17034 if (!pageSize.hasOwnProperty("inner")) {
17035 pageSize.inner = {
17036 width: pageSize.width - this.opt.margin[1] - this.opt.margin[3],
17037 height: pageSize.height - this.opt.margin[0] - this.opt.margin[2]
17038 };
17039 pageSize.inner.px = {
17040 width: toPx(pageSize.inner.width, pageSize.k),
17041 height: toPx(pageSize.inner.height, pageSize.k)
17042 };
17043 pageSize.inner.ratio = pageSize.inner.height / pageSize.inner.width;
17044 }
17045
17046 // Attach pageSize to this.
17047 this.prop.pageSize = pageSize;
17048 });
17049 };
17050
17051 Worker.prototype.setProgress = function setProgress(val, state, n, stack) {
17052 // Immediately update all progress values.
17053 if (val != null) this.progress.val = val;
17054 if (state != null) this.progress.state = state;
17055 if (n != null) this.progress.n = n;
17056 if (stack != null) this.progress.stack = stack;
17057 this.progress.ratio = this.progress.val / this.progress.state;
17058
17059 // Return this for command chaining.
17060 return this;
17061 };
17062
17063 Worker.prototype.updateProgress = function updateProgress(
17064 val,
17065 state,
17066 n,
17067 stack
17068 ) {
17069 // Immediately update all progress values, using setProgress.
17070 return this.setProgress(
17071 val ? this.progress.val + val : null,
17072 state ? state : null,
17073 n ? this.progress.n + n : null,
17074 stack ? this.progress.stack.concat(stack) : null
17075 );
17076 };
17077
17078 /* ----- PROMISE MAPPING ----- */
17079
17080 Worker.prototype.then = function then(onFulfilled, onRejected) {
17081 // Wrap `this` for encapsulation.
17082 var self = this;
17083
17084 return this.thenCore(onFulfilled, onRejected, function then_main(
17085 onFulfilled,
17086 onRejected
17087 ) {
17088 // Update progress while queuing, calling, and resolving `then`.
17089 self.updateProgress(null, null, 1, [onFulfilled]);
17090 return Promise.prototype.then
17091 .call(this, function then_pre(val) {
17092 self.updateProgress(null, onFulfilled);
17093 return val;
17094 })
17095 .then(onFulfilled, onRejected)
17096 .then(function then_post(val) {
17097 self.updateProgress(1);
17098 return val;
17099 });
17100 });
17101 };
17102
17103 Worker.prototype.thenCore = function thenCore(
17104 onFulfilled,
17105 onRejected,
17106 thenBase
17107 ) {
17108 // Handle optional thenBase parameter.
17109 thenBase = thenBase || Promise.prototype.then;
17110
17111 // Wrap `this` for encapsulation and bind it to the promise handlers.
17112 var self = this;
17113 if (onFulfilled) {
17114 onFulfilled = onFulfilled.bind(self);
17115 }
17116 if (onRejected) {
17117 onRejected = onRejected.bind(self);
17118 }
17119
17120 // Cast self into a Promise to avoid polyfills recursively defining `then`.
17121 var isNative =
17122 Promise.toString().indexOf("[native code]") !== -1 &&
17123 Promise.name === "Promise";
17124 var selfPromise = isNative
17125 ? self
17126 : Worker.convert(Object.assign({}, self), Promise.prototype);
17127
17128 // Return the promise, after casting it into a Worker and preserving props.
17129 var returnVal = thenBase.call(selfPromise, onFulfilled, onRejected);
17130 return Worker.convert(returnVal, self.__proto__);
17131 };
17132
17133 Worker.prototype.thenExternal = function thenExternal(
17134 onFulfilled,
17135 onRejected
17136 ) {
17137 // Call `then` and return a standard promise (exits the Worker chain).
17138 return Promise.prototype.then.call(this, onFulfilled, onRejected);
17139 };
17140
17141 Worker.prototype.thenList = function thenList(fns) {
17142 // Queue a series of promise 'factories' into the promise chain.
17143 var self = this;
17144 fns.forEach(function thenList_forEach(fn) {
17145 self = self.thenCore(fn);
17146 });
17147 return self;
17148 };
17149
17150 Worker.prototype["catch"] = function(onRejected) {
17151 // Bind `this` to the promise handler, call `catch`, and return a Worker.
17152 if (onRejected) {
17153 onRejected = onRejected.bind(this);
17154 }
17155 var returnVal = Promise.prototype["catch"].call(this, onRejected);
17156 return Worker.convert(returnVal, this);
17157 };
17158
17159 Worker.prototype.catchExternal = function catchExternal(onRejected) {
17160 // Call `catch` and return a standard promise (exits the Worker chain).
17161 return Promise.prototype["catch"].call(this, onRejected);
17162 };
17163
17164 Worker.prototype.error = function error(msg) {
17165 // Throw the error in the Promise chain.
17166 return this.then(function error_main() {
17167 throw new Error(msg);
17168 });
17169 };
17170
17171 /* ----- ALIASES ----- */
17172
17173 Worker.prototype.using = Worker.prototype.set;
17174 Worker.prototype.saveAs = Worker.prototype.save;
17175 Worker.prototype.export = Worker.prototype.output;
17176 Worker.prototype.run = Worker.prototype.then;
17177
17178 // Get dimensions of a PDF page, as determined by jsPDF.
17179 jsPDF.getPageSize = function(orientation, unit, format) {
17180 // Decode options object
17181 if (typeof orientation === "object") {
17182 var options = orientation;
17183 orientation = options.orientation;
17184 unit = options.unit || unit;
17185 format = options.format || format;
17186 }
17187
17188 // Default options
17189 unit = unit || "mm";
17190 format = format || "a4";
17191 orientation = ("" + (orientation || "P")).toLowerCase();
17192 var format_as_string = ("" + format).toLowerCase();
17193
17194 // Size in pt of various paper formats
17195 var pageFormats = {
17196 a0: [2383.94, 3370.39],
17197 a1: [1683.78, 2383.94],
17198 a2: [1190.55, 1683.78],
17199 a3: [841.89, 1190.55],
17200 a4: [595.28, 841.89],
17201 a5: [419.53, 595.28],
17202 a6: [297.64, 419.53],
17203 a7: [209.76, 297.64],
17204 a8: [147.4, 209.76],
17205 a9: [104.88, 147.4],
17206 a10: [73.7, 104.88],
17207 b0: [2834.65, 4008.19],
17208 b1: [2004.09, 2834.65],
17209 b2: [1417.32, 2004.09],
17210 b3: [1000.63, 1417.32],
17211 b4: [708.66, 1000.63],
17212 b5: [498.9, 708.66],
17213 b6: [354.33, 498.9],
17214 b7: [249.45, 354.33],
17215 b8: [175.75, 249.45],
17216 b9: [124.72, 175.75],
17217 b10: [87.87, 124.72],
17218 c0: [2599.37, 3676.54],
17219 c1: [1836.85, 2599.37],
17220 c2: [1298.27, 1836.85],
17221 c3: [918.43, 1298.27],
17222 c4: [649.13, 918.43],
17223 c5: [459.21, 649.13],
17224 c6: [323.15, 459.21],
17225 c7: [229.61, 323.15],
17226 c8: [161.57, 229.61],
17227 c9: [113.39, 161.57],
17228 c10: [79.37, 113.39],
17229 dl: [311.81, 623.62],
17230 letter: [612, 792],
17231 "government-letter": [576, 756],
17232 legal: [612, 1008],
17233 "junior-legal": [576, 360],
17234 ledger: [1224, 792],
17235 tabloid: [792, 1224],
17236 "credit-card": [153, 243]
17237 };
17238
17239 var k;
17240 // Unit conversion
17241 switch (unit) {
17242 case "pt":
17243 k = 1;
17244 break;
17245 case "mm":
17246 k = 72 / 25.4;
17247 break;
17248 case "cm":
17249 k = 72 / 2.54;
17250 break;
17251 case "in":
17252 k = 72;
17253 break;
17254 case "px":
17255 k = 72 / 96;
17256 break;
17257 case "pc":
17258 k = 12;
17259 break;
17260 case "em":
17261 k = 12;
17262 break;
17263 case "ex":
17264 k = 6;
17265 break;
17266 default:
17267 throw "Invalid unit: " + unit;
17268 }
17269 var pageHeight = 0;
17270 var pageWidth = 0;
17271
17272 // Dimensions are stored as user units and converted to points on output
17273 if (pageFormats.hasOwnProperty(format_as_string)) {
17274 pageHeight = pageFormats[format_as_string][1] / k;
17275 pageWidth = pageFormats[format_as_string][0] / k;
17276 } else {
17277 try {
17278 pageHeight = format[1];
17279 pageWidth = format[0];
17280 } catch (err) {
17281 throw new Error("Invalid format: " + format);
17282 }
17283 }
17284
17285 var tmp;
17286 // Handle page orientation
17287 if (orientation === "p" || orientation === "portrait") {
17288 orientation = "p";
17289 if (pageWidth > pageHeight) {
17290 tmp = pageWidth;
17291 pageWidth = pageHeight;
17292 pageHeight = tmp;
17293 }
17294 } else if (orientation === "l" || orientation === "landscape") {
17295 orientation = "l";
17296 if (pageHeight > pageWidth) {
17297 tmp = pageWidth;
17298 pageWidth = pageHeight;
17299 pageHeight = tmp;
17300 }
17301 } else {
17302 throw "Invalid orientation: " + orientation;
17303 }
17304
17305 // Return information (k is the unit conversion ratio from pts)
17306 var info = {
17307 width: pageWidth,
17308 height: pageHeight,
17309 unit: unit,
17310 k: k,
17311 orientation: orientation
17312 };
17313 return info;
17314 };
17315
17316 /**
17317 * @typedef FontFace
17318 *
17319 * The font-face type implements an interface similar to that of the font-face CSS rule,
17320 * and is used by jsPDF to match fonts when the font property of CanvasRenderingContext2D
17321 * is updated.
17322 *
17323 * All properties expect values similar to those in the font-face CSS rule. A difference
17324 * is the font-family, which do not need to be enclosed in double-quotes when containing
17325 * spaces like in CSS.
17326 *
17327 * @property {string} family The name of the font-family.
17328 * @property {string|undefined} style The style that this font-face defines, e.g. 'italic'.
17329 * @property {string|number|undefined} weight The weight of the font, either as a string or a number (400, 500, 600, e.g.)
17330 * @property {string|undefined} stretch The stretch of the font, e.g. condensed, normal, expanded.
17331 * @property {Object[]} src A list of URLs from where fonts of various formats can be fetched.
17332 * @property {string} [src] url A URL to a font of a specific format.
17333 * @property {string} [src] format Format of the font referenced by the URL.
17334 */
17335
17336 /**
17337 * Generate a PDF from an HTML element or string using.
17338 *
17339 * @name html
17340 * @function
17341 * @param {HTMLElement|string} source The source HTMLElement or a string containing HTML.
17342 * @param {Object} [options] Collection of settings
17343 * @param {function} [options.callback] The mandatory callback-function gets as first parameter the current jsPDF instance
17344 * @param {number|array} [options.margin] Array of margins [left, bottom, right, top]
17345 * @param {string} [options.filename] name of the file
17346 * @param {HTMLOptionImage} [options.image] image settings when converting HTML to image
17347 * @param {Html2CanvasOptions} [options.html2canvas] html2canvas options
17348 * @param {FontFace[]} [options.fontFaces] A list of font-faces to match when resolving fonts. Fonts will be added to the PDF based on the specified URL. If omitted, the font match algorithm falls back to old algorithm.
17349 * @param {jsPDF} [options.jsPDF] jsPDF instance
17350 * @param {number} [options.x] x position on the PDF document
17351 * @param {number} [options.y] y position on the PDF document
17352 *
17353 * @example
17354 * var doc = new jsPDF();
17355 *
17356 * doc.html(document.body, {
17357 * callback: function (doc) {
17358 * doc.save();
17359 * },
17360 * x: 10,
17361 * y: 10
17362 * });
17363 */
17364 jsPDFAPI.html = function(src, options) {
17365
17366 options = options || {};
17367 options.callback = options.callback || function() {};
17368 options.html2canvas = options.html2canvas || {};
17369 options.html2canvas.canvas = options.html2canvas.canvas || this.canvas;
17370 options.jsPDF = options.jsPDF || this;
17371 options.fontFaces = options.fontFaces
17372 ? options.fontFaces.map(normalizeFontFace)
17373 : null;
17374
17375 // Create a new worker with the given options.
17376 var worker = new Worker(options);
17377
17378 if (!options.worker) {
17379 // If worker is not set to true, perform the traditional 'simple' operation.
17380 return worker.from(src).doCallback();
17381 } else {
17382 // Otherwise, return the worker for new Promise-based operation.
17383 return worker;
17384 }
17385 };
17386 })(jsPDF.API);
17387
17388 /**
17389 * @license
17390 * ====================================================================
17391 * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
17392 *
17393 * Permission is hereby granted, free of charge, to any person obtaining
17394 * a copy of this software and associated documentation files (the
17395 * "Software"), to deal in the Software without restriction, including
17396 * without limitation the rights to use, copy, modify, merge, publish,
17397 * distribute, sublicense, and/or sell copies of the Software, and to
17398 * permit persons to whom the Software is furnished to do so, subject to
17399 * the following conditions:
17400 *
17401 * The above copyright notice and this permission notice shall be
17402 * included in all copies or substantial portions of the Software.
17403 *
17404 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17405 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17406 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17407 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
17408 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17409 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
17410 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17411 * ====================================================================
17412 */
17413
17414 /**
17415 * jsPDF JavaScript plugin
17416 *
17417 * @name javascript
17418 * @module
17419 */
17420 (function(jsPDFAPI) {
17421 var jsNamesObj, jsJsObj, text;
17422 /**
17423 * @name addJS
17424 * @function
17425 * @param {string} javascript The javascript to be embedded into the PDF-file.
17426 * @returns {jsPDF}
17427 */
17428 jsPDFAPI.addJS = function(javascript) {
17429 text = javascript;
17430 this.internal.events.subscribe("postPutResources", function() {
17431 jsNamesObj = this.internal.newObject();
17432 this.internal.out("<<");
17433 this.internal.out("/Names [(EmbeddedJS) " + (jsNamesObj + 1) + " 0 R]");
17434 this.internal.out(">>");
17435 this.internal.out("endobj");
17436
17437 jsJsObj = this.internal.newObject();
17438 this.internal.out("<<");
17439 this.internal.out("/S /JavaScript");
17440 this.internal.out("/JS (" + text + ")");
17441 this.internal.out(">>");
17442 this.internal.out("endobj");
17443 });
17444 this.internal.events.subscribe("putCatalog", function() {
17445 if (jsNamesObj !== undefined && jsJsObj !== undefined) {
17446 this.internal.out("/Names <</JavaScript " + jsNamesObj + " 0 R>>");
17447 }
17448 });
17449 return this;
17450 };
17451 })(jsPDF.API);
17452
17453 /**
17454 * @license
17455 * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv
17456 *
17457 * Licensed under the MIT License.
17458 * http://opensource.org/licenses/mit-license
17459 */
17460
17461 /**
17462 * jsPDF Outline PlugIn
17463 *
17464 * Generates a PDF Outline
17465 * @name outline
17466 * @module
17467 */
17468 (function(jsPDFAPI) {
17469
17470 var namesOid;
17471 //var destsGoto = [];
17472
17473 jsPDFAPI.events.push([
17474 "postPutResources",
17475 function() {
17476 var pdf = this;
17477 var rx = /^(\d+) 0 obj$/;
17478
17479 // Write action goto objects for each page
17480 // this.outline.destsGoto = [];
17481 // for (var i = 0; i < totalPages; i++) {
17482 // var id = pdf.internal.newObject();
17483 // this.outline.destsGoto.push(id);
17484 // pdf.internal.write("<</D[" + (i * 2 + 3) + " 0 R /XYZ null
17485 // null null]/S/GoTo>> endobj");
17486 // }
17487 //
17488 // for (var i = 0; i < dests.length; i++) {
17489 // pdf.internal.write("(page_" + (i + 1) + ")" + dests[i] + " 0
17490 // R");
17491 // }
17492 //
17493 if (this.outline.root.children.length > 0) {
17494 var lines = pdf.outline.render().split(/\r\n/);
17495 for (var i = 0; i < lines.length; i++) {
17496 var line = lines[i];
17497 var m = rx.exec(line);
17498 if (m != null) {
17499 var oid = m[1];
17500 pdf.internal.newObjectDeferredBegin(oid, false);
17501 }
17502 pdf.internal.write(line);
17503 }
17504 }
17505
17506 // This code will write named destination for each page reference
17507 // (page_1, etc)
17508 if (this.outline.createNamedDestinations) {
17509 var totalPages = this.internal.pages.length;
17510 // WARNING: this assumes jsPDF starts on page 3 and pageIDs
17511 // follow 5, 7, 9, etc
17512 // Write destination objects for each page
17513 var dests = [];
17514 for (var i = 0; i < totalPages; i++) {
17515 var id = pdf.internal.newObject();
17516 dests.push(id);
17517 var info = pdf.internal.getPageInfo(i + 1);
17518 pdf.internal.write(
17519 "<< /D[" + info.objId + " 0 R /XYZ null null null]>> endobj"
17520 );
17521 }
17522
17523 // assign a name for each destination
17524 var names2Oid = pdf.internal.newObject();
17525 pdf.internal.write("<< /Names [ ");
17526 for (var i = 0; i < dests.length; i++) {
17527 pdf.internal.write("(page_" + (i + 1) + ")" + dests[i] + " 0 R");
17528 }
17529 pdf.internal.write(" ] >>", "endobj");
17530
17531 // var kids = pdf.internal.newObject();
17532 // pdf.internal.write('<< /Kids [ ' + names2Oid + ' 0 R');
17533 // pdf.internal.write(' ] >>', 'endobj');
17534
17535 namesOid = pdf.internal.newObject();
17536 pdf.internal.write("<< /Dests " + names2Oid + " 0 R");
17537 pdf.internal.write(">>", "endobj");
17538 }
17539 }
17540 ]);
17541
17542 jsPDFAPI.events.push([
17543 "putCatalog",
17544 function() {
17545 var pdf = this;
17546 if (pdf.outline.root.children.length > 0) {
17547 pdf.internal.write(
17548 "/Outlines",
17549 this.outline.makeRef(this.outline.root)
17550 );
17551 if (this.outline.createNamedDestinations) {
17552 pdf.internal.write("/Names " + namesOid + " 0 R");
17553 }
17554 // Open with Bookmarks showing
17555 // pdf.internal.write("/PageMode /UseOutlines");
17556 }
17557 }
17558 ]);
17559
17560 jsPDFAPI.events.push([
17561 "initialized",
17562 function() {
17563 var pdf = this;
17564
17565 pdf.outline = {
17566 createNamedDestinations: false,
17567 root: {
17568 children: []
17569 }
17570 };
17571
17572 /**
17573 * Options: pageNumber
17574 */
17575 pdf.outline.add = function(parent, title, options) {
17576 var item = {
17577 title: title,
17578 options: options,
17579 children: []
17580 };
17581 if (parent == null) {
17582 parent = this.root;
17583 }
17584 parent.children.push(item);
17585 return item;
17586 };
17587
17588 pdf.outline.render = function() {
17589 this.ctx = {};
17590 this.ctx.val = "";
17591 this.ctx.pdf = pdf;
17592
17593 this.genIds_r(this.root);
17594 this.renderRoot(this.root);
17595 this.renderItems(this.root);
17596
17597 return this.ctx.val;
17598 };
17599
17600 pdf.outline.genIds_r = function(node) {
17601 node.id = pdf.internal.newObjectDeferred();
17602 for (var i = 0; i < node.children.length; i++) {
17603 this.genIds_r(node.children[i]);
17604 }
17605 };
17606
17607 pdf.outline.renderRoot = function(node) {
17608 this.objStart(node);
17609 this.line("/Type /Outlines");
17610 if (node.children.length > 0) {
17611 this.line("/First " + this.makeRef(node.children[0]));
17612 this.line(
17613 "/Last " + this.makeRef(node.children[node.children.length - 1])
17614 );
17615 }
17616 this.line(
17617 "/Count " +
17618 this.count_r(
17619 {
17620 count: 0
17621 },
17622 node
17623 )
17624 );
17625 this.objEnd();
17626 };
17627
17628 pdf.outline.renderItems = function(node) {
17629 var getVerticalCoordinateString = this.ctx.pdf.internal
17630 .getVerticalCoordinateString;
17631 for (var i = 0; i < node.children.length; i++) {
17632 var item = node.children[i];
17633 this.objStart(item);
17634
17635 this.line("/Title " + this.makeString(item.title));
17636
17637 this.line("/Parent " + this.makeRef(node));
17638 if (i > 0) {
17639 this.line("/Prev " + this.makeRef(node.children[i - 1]));
17640 }
17641 if (i < node.children.length - 1) {
17642 this.line("/Next " + this.makeRef(node.children[i + 1]));
17643 }
17644 if (item.children.length > 0) {
17645 this.line("/First " + this.makeRef(item.children[0]));
17646 this.line(
17647 "/Last " + this.makeRef(item.children[item.children.length - 1])
17648 );
17649 }
17650
17651 var count = (this.count = this.count_r(
17652 {
17653 count: 0
17654 },
17655 item
17656 ));
17657 if (count > 0) {
17658 this.line("/Count " + count);
17659 }
17660
17661 if (item.options) {
17662 if (item.options.pageNumber) {
17663 // Explicit Destination
17664 //WARNING this assumes page ids are 3,5,7, etc.
17665 var info = pdf.internal.getPageInfo(item.options.pageNumber);
17666 this.line(
17667 "/Dest " +
17668 "[" +
17669 info.objId +
17670 " 0 R /XYZ 0 " +
17671 getVerticalCoordinateString(0) +
17672 " 0]"
17673 );
17674 // this line does not work on all clients (pageNumber instead of page ref)
17675 //this.line('/Dest ' + '[' + (item.options.pageNumber - 1) + ' /XYZ 0 ' + this.ctx.pdf.internal.pageSize.getHeight() + ' 0]');
17676
17677 // Named Destination
17678 // this.line('/Dest (page_' + (item.options.pageNumber) + ')');
17679
17680 // Action Destination
17681 // var id = pdf.internal.newObject();
17682 // pdf.internal.write('<</D[' + (item.options.pageNumber - 1) + ' /XYZ null null null]/S/GoTo>> endobj');
17683 // this.line('/A ' + id + ' 0 R' );
17684 }
17685 }
17686 this.objEnd();
17687 }
17688 for (var z = 0; z < node.children.length; z++) {
17689 this.renderItems(node.children[z]);
17690 }
17691 };
17692
17693 pdf.outline.line = function(text) {
17694 this.ctx.val += text + "\r\n";
17695 };
17696
17697 pdf.outline.makeRef = function(node) {
17698 return node.id + " 0 R";
17699 };
17700
17701 pdf.outline.makeString = function(val) {
17702 return "(" + pdf.internal.pdfEscape(val) + ")";
17703 };
17704
17705 pdf.outline.objStart = function(node) {
17706 this.ctx.val += "\r\n" + node.id + " 0 obj" + "\r\n<<\r\n";
17707 };
17708
17709 pdf.outline.objEnd = function() {
17710 this.ctx.val += ">> \r\n" + "endobj" + "\r\n";
17711 };
17712
17713 pdf.outline.count_r = function(ctx, node) {
17714 for (var i = 0; i < node.children.length; i++) {
17715 ctx.count++;
17716 this.count_r(ctx, node.children[i]);
17717 }
17718 return ctx.count;
17719 };
17720 }
17721 ]);
17722
17723 return this;
17724 })(jsPDF.API);
17725
17726 /**
17727 * @license
17728 *
17729 * Licensed under the MIT License.
17730 * http://opensource.org/licenses/mit-license
17731 */
17732
17733 /**
17734 * jsPDF jpeg Support PlugIn
17735 *
17736 * @name jpeg_support
17737 * @module
17738 */
17739 (function(jsPDFAPI) {
17740
17741 /**
17742 * 0xc0 (SOF) Huffman - Baseline DCT
17743 * 0xc1 (SOF) Huffman - Extended sequential DCT
17744 * 0xc2 Progressive DCT (SOF2)
17745 * 0xc3 Spatial (sequential) lossless (SOF3)
17746 * 0xc4 Differential sequential DCT (SOF5)
17747 * 0xc5 Differential progressive DCT (SOF6)
17748 * 0xc6 Differential spatial (SOF7)
17749 * 0xc7
17750 */
17751 var markers = [0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7];
17752
17753 //takes a string imgData containing the raw bytes of
17754 //a jpeg image and returns [width, height]
17755 //Algorithm from: http://www.64lines.com/jpeg-width-height
17756 var getJpegInfo = function(imgData) {
17757 var width, height, numcomponents;
17758 var blockLength = imgData.charCodeAt(4) * 256 + imgData.charCodeAt(5);
17759 var len = imgData.length;
17760 var result = { width: 0, height: 0, numcomponents: 1 };
17761 for (var i = 4; i < len; i += 2) {
17762 i += blockLength;
17763 if (markers.indexOf(imgData.charCodeAt(i + 1)) !== -1) {
17764 height = imgData.charCodeAt(i + 5) * 256 + imgData.charCodeAt(i + 6);
17765 width = imgData.charCodeAt(i + 7) * 256 + imgData.charCodeAt(i + 8);
17766 numcomponents = imgData.charCodeAt(i + 9);
17767 result = { width: width, height: height, numcomponents: numcomponents };
17768 break;
17769 } else {
17770 blockLength =
17771 imgData.charCodeAt(i + 2) * 256 + imgData.charCodeAt(i + 3);
17772 }
17773 }
17774 return result;
17775 };
17776
17777 /**
17778 * @ignore
17779 */
17780 jsPDFAPI.processJPEG = function(
17781 data,
17782 index,
17783 alias,
17784 compression,
17785 dataAsBinaryString,
17786 colorSpace
17787 ) {
17788 var filter = this.decode.DCT_DECODE,
17789 bpc = 8,
17790 dims,
17791 result = null;
17792
17793 if (
17794 typeof data === "string" ||
17795 this.__addimage__.isArrayBuffer(data) ||
17796 this.__addimage__.isArrayBufferView(data)
17797 ) {
17798 // if we already have a stored binary string rep use that
17799 data = dataAsBinaryString || data;
17800 data = this.__addimage__.isArrayBuffer(data)
17801 ? new Uint8Array(data)
17802 : data;
17803 data = this.__addimage__.isArrayBufferView(data)
17804 ? this.__addimage__.arrayBufferToBinaryString(data)
17805 : data;
17806
17807 dims = getJpegInfo(data);
17808 switch (dims.numcomponents) {
17809 case 1:
17810 colorSpace = this.color_spaces.DEVICE_GRAY;
17811 break;
17812 case 4:
17813 colorSpace = this.color_spaces.DEVICE_CMYK;
17814 break;
17815 case 3:
17816 colorSpace = this.color_spaces.DEVICE_RGB;
17817 break;
17818 }
17819
17820 result = {
17821 data: data,
17822 width: dims.width,
17823 height: dims.height,
17824 colorSpace: colorSpace,
17825 bitsPerComponent: bpc,
17826 filter: filter,
17827 index: index,
17828 alias: alias
17829 };
17830 }
17831 return result;
17832 };
17833 })(jsPDF.API);
17834
17835 // Generated by CoffeeScript 1.4.0
17836
17837 var PNG = (function() {
17838 var APNG_BLEND_OP_SOURCE,
17839 APNG_DISPOSE_OP_BACKGROUND,
17840 APNG_DISPOSE_OP_PREVIOUS,
17841 makeImage,
17842 scratchCanvas,
17843 scratchCtx;
17844
17845 APNG_DISPOSE_OP_BACKGROUND = 1;
17846
17847 APNG_DISPOSE_OP_PREVIOUS = 2;
17848
17849 APNG_BLEND_OP_SOURCE = 0;
17850
17851 function PNG(data) {
17852 var chunkSize,
17853 colors,
17854 palLen,
17855 delayDen,
17856 delayNum,
17857 frame,
17858 i,
17859 index,
17860 key,
17861 section,
17862 palShort,
17863 text,
17864 _i,
17865 _j,
17866 _ref;
17867 this.data = data;
17868 this.pos = 8;
17869 this.palette = [];
17870 this.imgData = [];
17871 this.transparency = {};
17872 this.animation = null;
17873 this.text = {};
17874 frame = null;
17875 while (true) {
17876 chunkSize = this.readUInt32();
17877 section = function() {
17878 var _i, _results;
17879 _results = [];
17880 for (i = _i = 0; _i < 4; i = ++_i) {
17881 _results.push(String.fromCharCode(this.data[this.pos++]));
17882 }
17883 return _results;
17884 }
17885 .call(this)
17886 .join("");
17887 switch (section) {
17888 case "IHDR":
17889 this.width = this.readUInt32();
17890 this.height = this.readUInt32();
17891 this.bits = this.data[this.pos++];
17892 this.colorType = this.data[this.pos++];
17893 this.compressionMethod = this.data[this.pos++];
17894 this.filterMethod = this.data[this.pos++];
17895 this.interlaceMethod = this.data[this.pos++];
17896 break;
17897 case "acTL":
17898 this.animation = {
17899 numFrames: this.readUInt32(),
17900 numPlays: this.readUInt32() || Infinity,
17901 frames: []
17902 };
17903 break;
17904 case "PLTE":
17905 this.palette = this.read(chunkSize);
17906 break;
17907 case "fcTL":
17908 if (frame) {
17909 this.animation.frames.push(frame);
17910 }
17911 this.pos += 4;
17912 frame = {
17913 width: this.readUInt32(),
17914 height: this.readUInt32(),
17915 xOffset: this.readUInt32(),
17916 yOffset: this.readUInt32()
17917 };
17918 delayNum = this.readUInt16();
17919 delayDen = this.readUInt16() || 100;
17920 frame.delay = (1000 * delayNum) / delayDen;
17921 frame.disposeOp = this.data[this.pos++];
17922 frame.blendOp = this.data[this.pos++];
17923 frame.data = [];
17924 break;
17925 case "IDAT":
17926 case "fdAT":
17927 if (section === "fdAT") {
17928 this.pos += 4;
17929 chunkSize -= 4;
17930 }
17931 data = (frame != null ? frame.data : void 0) || this.imgData;
17932 for (
17933 i = _i = 0;
17934 0 <= chunkSize ? _i < chunkSize : _i > chunkSize;
17935 i = 0 <= chunkSize ? ++_i : --_i
17936 ) {
17937 data.push(this.data[this.pos++]);
17938 }
17939 break;
17940 case "tRNS":
17941 this.transparency = {};
17942 switch (this.colorType) {
17943 case 3:
17944 palLen = this.palette.length / 3;
17945 this.transparency.indexed = this.read(chunkSize);
17946 if (this.transparency.indexed.length > palLen)
17947 throw new Error("More transparent colors than palette size");
17948 /*
17949 * According to the PNG spec trns should be increased to the same size as palette if shorter
17950 */
17951 //palShort = 255 - this.transparency.indexed.length;
17952 palShort = palLen - this.transparency.indexed.length;
17953 if (palShort > 0) {
17954 for (
17955 i = _j = 0;
17956 0 <= palShort ? _j < palShort : _j > palShort;
17957 i = 0 <= palShort ? ++_j : --_j
17958 ) {
17959 this.transparency.indexed.push(255);
17960 }
17961 }
17962 break;
17963 case 0:
17964 this.transparency.grayscale = this.read(chunkSize)[0];
17965 break;
17966 case 2:
17967 this.transparency.rgb = this.read(chunkSize);
17968 }
17969 break;
17970 case "tEXt":
17971 text = this.read(chunkSize);
17972 index = text.indexOf(0);
17973 key = String.fromCharCode.apply(String, text.slice(0, index));
17974 this.text[key] = String.fromCharCode.apply(
17975 String,
17976 text.slice(index + 1)
17977 );
17978 break;
17979 case "IEND":
17980 if (frame) {
17981 this.animation.frames.push(frame);
17982 }
17983 this.colors = function() {
17984 switch (this.colorType) {
17985 case 0:
17986 case 3:
17987 case 4:
17988 return 1;
17989 case 2:
17990 case 6:
17991 return 3;
17992 }
17993 }.call(this);
17994 this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6;
17995 colors = this.colors + (this.hasAlphaChannel ? 1 : 0);
17996 this.pixelBitlength = this.bits * colors;
17997 this.colorSpace = function() {
17998 switch (this.colors) {
17999 case 1:
18000 return "DeviceGray";
18001 case 3:
18002 return "DeviceRGB";
18003 }
18004 }.call(this);
18005 this.imgData = new Uint8Array(this.imgData);
18006 return;
18007 default:
18008 this.pos += chunkSize;
18009 }
18010 this.pos += 4;
18011 if (this.pos > this.data.length) {
18012 throw new Error("Incomplete or corrupt PNG file");
18013 }
18014 }
18015 }
18016
18017 PNG.prototype.read = function(bytes) {
18018 var i, _i, _results;
18019 _results = [];
18020 for (
18021 i = _i = 0;
18022 0 <= bytes ? _i < bytes : _i > bytes;
18023 i = 0 <= bytes ? ++_i : --_i
18024 ) {
18025 _results.push(this.data[this.pos++]);
18026 }
18027 return _results;
18028 };
18029
18030 PNG.prototype.readUInt32 = function() {
18031 var b1, b2, b3, b4;
18032 b1 = this.data[this.pos++] << 24;
18033 b2 = this.data[this.pos++] << 16;
18034 b3 = this.data[this.pos++] << 8;
18035 b4 = this.data[this.pos++];
18036 return b1 | b2 | b3 | b4;
18037 };
18038
18039 PNG.prototype.readUInt16 = function() {
18040 var b1, b2;
18041 b1 = this.data[this.pos++] << 8;
18042 b2 = this.data[this.pos++];
18043 return b1 | b2;
18044 };
18045
18046 PNG.prototype.decodePixels = function(data) {
18047 var pixelBytes = this.pixelBitlength / 8;
18048 var fullPixels = new Uint8Array(this.width * this.height * pixelBytes);
18049 var pos = 0;
18050 var _this = this;
18051
18052 if (data == null) {
18053 data = this.imgData;
18054 }
18055 if (data.length === 0) {
18056 return new Uint8Array(0);
18057 }
18058
18059 data = unzlibSync(data);
18060 function pass(x0, y0, dx, dy) {
18061 var abyte,
18062 c,
18063 col,
18064 i,
18065 left,
18066 length,
18067 p,
18068 pa,
18069 paeth,
18070 pb,
18071 pc,
18072 pixels,
18073 row,
18074 scanlineLength,
18075 upper,
18076 upperLeft,
18077 _i,
18078 _j,
18079 _k,
18080 _l,
18081 _m;
18082 var w = Math.ceil((_this.width - x0) / dx),
18083 h = Math.ceil((_this.height - y0) / dy);
18084 var isFull = _this.width == w && _this.height == h;
18085 scanlineLength = pixelBytes * w;
18086 pixels = isFull ? fullPixels : new Uint8Array(scanlineLength * h);
18087 length = data.length;
18088 row = 0;
18089 c = 0;
18090 while (row < h && pos < length) {
18091 switch (data[pos++]) {
18092 case 0:
18093 for (i = _i = 0; _i < scanlineLength; i = _i += 1) {
18094 pixels[c++] = data[pos++];
18095 }
18096 break;
18097 case 1:
18098 for (i = _j = 0; _j < scanlineLength; i = _j += 1) {
18099 abyte = data[pos++];
18100 left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
18101 pixels[c++] = (abyte + left) % 256;
18102 }
18103 break;
18104 case 2:
18105 for (i = _k = 0; _k < scanlineLength; i = _k += 1) {
18106 abyte = data[pos++];
18107 col = (i - (i % pixelBytes)) / pixelBytes;
18108 upper =
18109 row &&
18110 pixels[
18111 (row - 1) * scanlineLength +
18112 col * pixelBytes +
18113 (i % pixelBytes)
18114 ];
18115 pixels[c++] = (upper + abyte) % 256;
18116 }
18117 break;
18118 case 3:
18119 for (i = _l = 0; _l < scanlineLength; i = _l += 1) {
18120 abyte = data[pos++];
18121 col = (i - (i % pixelBytes)) / pixelBytes;
18122 left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
18123 upper =
18124 row &&
18125 pixels[
18126 (row - 1) * scanlineLength +
18127 col * pixelBytes +
18128 (i % pixelBytes)
18129 ];
18130 pixels[c++] = (abyte + Math.floor((left + upper) / 2)) % 256;
18131 }
18132 break;
18133 case 4:
18134 for (i = _m = 0; _m < scanlineLength; i = _m += 1) {
18135 abyte = data[pos++];
18136 col = (i - (i % pixelBytes)) / pixelBytes;
18137 left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
18138 if (row === 0) {
18139 upper = upperLeft = 0;
18140 } else {
18141 upper =
18142 pixels[
18143 (row - 1) * scanlineLength +
18144 col * pixelBytes +
18145 (i % pixelBytes)
18146 ];
18147 upperLeft =
18148 col &&
18149 pixels[
18150 (row - 1) * scanlineLength +
18151 (col - 1) * pixelBytes +
18152 (i % pixelBytes)
18153 ];
18154 }
18155 p = left + upper - upperLeft;
18156 pa = Math.abs(p - left);
18157 pb = Math.abs(p - upper);
18158 pc = Math.abs(p - upperLeft);
18159 if (pa <= pb && pa <= pc) {
18160 paeth = left;
18161 } else if (pb <= pc) {
18162 paeth = upper;
18163 } else {
18164 paeth = upperLeft;
18165 }
18166 pixels[c++] = (abyte + paeth) % 256;
18167 }
18168 break;
18169 default:
18170 throw new Error("Invalid filter algorithm: " + data[pos - 1]);
18171 }
18172 if (!isFull) {
18173 var fullPos = ((y0 + row * dy) * _this.width + x0) * pixelBytes;
18174 var partPos = row * scanlineLength;
18175 for (i = 0; i < w; i += 1) {
18176 for (var j = 0; j < pixelBytes; j += 1)
18177 fullPixels[fullPos++] = pixels[partPos++];
18178 fullPos += (dx - 1) * pixelBytes;
18179 }
18180 }
18181 row++;
18182 }
18183 }
18184 if (_this.interlaceMethod == 1) {
18185 /*
18186 1 6 4 6 2 6 4 6
18187 7 7 7 7 7 7 7 7
18188 5 6 5 6 5 6 5 6
18189 7 7 7 7 7 7 7 7
18190 3 6 4 6 3 6 4 6
18191 7 7 7 7 7 7 7 7
18192 5 6 5 6 5 6 5 6
18193 7 7 7 7 7 7 7 7
18194 */
18195 pass(0, 0, 8, 8); // 1
18196 /* NOTE these seem to follow the pattern:
18197 * pass(x, 0, 2*x, 2*x);
18198 * pass(0, x, x, 2*x);
18199 * with x being 4, 2, 1.
18200 */
18201 pass(4, 0, 8, 8); // 2
18202 pass(0, 4, 4, 8); // 3
18203
18204 pass(2, 0, 4, 4); // 4
18205 pass(0, 2, 2, 4); // 5
18206
18207 pass(1, 0, 2, 2); // 6
18208 pass(0, 1, 1, 2); // 7
18209 } else {
18210 pass(0, 0, 1, 1);
18211 }
18212 return fullPixels;
18213 };
18214
18215 PNG.prototype.decodePalette = function() {
18216 var c, i, length, palette, pos, ret, transparency, _i, _ref, _ref1;
18217 palette = this.palette;
18218 transparency = this.transparency.indexed || [];
18219 ret = new Uint8Array((transparency.length || 0) + palette.length);
18220 pos = 0;
18221 length = palette.length;
18222 c = 0;
18223 for (i = _i = 0, _ref = length; _i < _ref; i = _i += 3) {
18224 ret[pos++] = palette[i];
18225 ret[pos++] = palette[i + 1];
18226 ret[pos++] = palette[i + 2];
18227 ret[pos++] = (_ref1 = transparency[c++]) != null ? _ref1 : 255;
18228 }
18229 return ret;
18230 };
18231
18232 PNG.prototype.copyToImageData = function(imageData, pixels) {
18233 var alpha, colors, data, i, input, j, k, length, palette, v, _ref;
18234 colors = this.colors;
18235 palette = null;
18236 alpha = this.hasAlphaChannel;
18237 if (this.palette.length) {
18238 palette =
18239 (_ref = this._decodedPalette) != null
18240 ? _ref
18241 : (this._decodedPalette = this.decodePalette());
18242 colors = 4;
18243 alpha = true;
18244 }
18245 data = imageData.data || imageData;
18246 length = data.length;
18247 input = palette || pixels;
18248 i = j = 0;
18249 if (colors === 1) {
18250 while (i < length) {
18251 k = palette ? pixels[i / 4] * 4 : j;
18252 v = input[k++];
18253 data[i++] = v;
18254 data[i++] = v;
18255 data[i++] = v;
18256 data[i++] = alpha ? input[k++] : 255;
18257 j = k;
18258 }
18259 } else {
18260 while (i < length) {
18261 k = palette ? pixels[i / 4] * 4 : j;
18262 data[i++] = input[k++];
18263 data[i++] = input[k++];
18264 data[i++] = input[k++];
18265 data[i++] = alpha ? input[k++] : 255;
18266 j = k;
18267 }
18268 }
18269 };
18270
18271 PNG.prototype.decode = function() {
18272 var ret;
18273 ret = new Uint8Array(this.width * this.height * 4);
18274 this.copyToImageData(ret, this.decodePixels());
18275 return ret;
18276 };
18277
18278 var hasBrowserCanvas = function() {
18279 if (Object.prototype.toString.call(globalObject) === "[object Window]") {
18280 try {
18281 scratchCanvas = globalObject.document.createElement("canvas");
18282 scratchCtx = scratchCanvas.getContext("2d");
18283 } catch (e) {
18284 return false;
18285 }
18286 return true;
18287 }
18288 return false;
18289 };
18290
18291 hasBrowserCanvas();
18292
18293 makeImage = function(imageData) {
18294 if (hasBrowserCanvas() === true) {
18295 var img;
18296 scratchCtx.width = imageData.width;
18297 scratchCtx.height = imageData.height;
18298 scratchCtx.clearRect(0, 0, imageData.width, imageData.height);
18299 scratchCtx.putImageData(imageData, 0, 0);
18300 img = new Image();
18301 img.src = scratchCanvas.toDataURL();
18302 return img;
18303 }
18304 throw new Error("This method requires a Browser with Canvas-capability.");
18305 };
18306
18307 PNG.prototype.decodeFrames = function(ctx) {
18308 var frame, i, imageData, pixels, _i, _len, _ref, _results;
18309 if (!this.animation) {
18310 return;
18311 }
18312 _ref = this.animation.frames;
18313 _results = [];
18314 for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
18315 frame = _ref[i];
18316 imageData = ctx.createImageData(frame.width, frame.height);
18317 pixels = this.decodePixels(new Uint8Array(frame.data));
18318 this.copyToImageData(imageData, pixels);
18319 frame.imageData = imageData;
18320 _results.push((frame.image = makeImage(imageData)));
18321 }
18322 return _results;
18323 };
18324
18325 PNG.prototype.renderFrame = function(ctx, number) {
18326 var frame, frames, prev;
18327 frames = this.animation.frames;
18328 frame = frames[number];
18329 prev = frames[number - 1];
18330 if (number === 0) {
18331 ctx.clearRect(0, 0, this.width, this.height);
18332 }
18333 if (
18334 (prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_BACKGROUND
18335 ) {
18336 ctx.clearRect(prev.xOffset, prev.yOffset, prev.width, prev.height);
18337 } else if (
18338 (prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_PREVIOUS
18339 ) {
18340 ctx.putImageData(prev.imageData, prev.xOffset, prev.yOffset);
18341 }
18342 if (frame.blendOp === APNG_BLEND_OP_SOURCE) {
18343 ctx.clearRect(frame.xOffset, frame.yOffset, frame.width, frame.height);
18344 }
18345 return ctx.drawImage(frame.image, frame.xOffset, frame.yOffset);
18346 };
18347
18348 PNG.prototype.animate = function(ctx) {
18349 var doFrame,
18350 frameNumber,
18351 frames,
18352 numFrames,
18353 numPlays,
18354 _ref,
18355 _this = this;
18356 frameNumber = 0;
18357 (_ref = this.animation),
18358 (numFrames = _ref.numFrames),
18359 (frames = _ref.frames),
18360 (numPlays = _ref.numPlays);
18361 return (doFrame = function() {
18362 var f, frame;
18363 f = frameNumber++ % numFrames;
18364 frame = frames[f];
18365 _this.renderFrame(ctx, f);
18366 if (numFrames > 1 && frameNumber / numFrames < numPlays) {
18367 return (_this.animation._timeout = setTimeout(doFrame, frame.delay));
18368 }
18369 })();
18370 };
18371
18372 PNG.prototype.stopAnimation = function() {
18373 var _ref;
18374 return clearTimeout(
18375 (_ref = this.animation) != null ? _ref._timeout : void 0
18376 );
18377 };
18378
18379 PNG.prototype.render = function(canvas) {
18380 var ctx, data;
18381 if (canvas._png) {
18382 canvas._png.stopAnimation();
18383 }
18384 canvas._png = this;
18385 canvas.width = this.width;
18386 canvas.height = this.height;
18387 ctx = canvas.getContext("2d");
18388 if (this.animation) {
18389 this.decodeFrames(ctx);
18390 return this.animate(ctx);
18391 } else {
18392 data = ctx.createImageData(this.width, this.height);
18393 this.copyToImageData(data, this.decodePixels());
18394 return ctx.putImageData(data, 0, 0);
18395 }
18396 };
18397
18398 return PNG;
18399 })();
18400
18401 /**
18402 * @license
18403 *
18404 * Copyright (c) 2014 James Robb, https://github.com/jamesbrobb
18405 *
18406 * Permission is hereby granted, free of charge, to any person obtaining
18407 * a copy of this software and associated documentation files (the
18408 * "Software"), to deal in the Software without restriction, including
18409 * without limitation the rights to use, copy, modify, merge, publish,
18410 * distribute, sublicense, and/or sell copies of the Software, and to
18411 * permit persons to whom the Software is furnished to do so, subject to
18412 * the following conditions:
18413 *
18414 * The above copyright notice and this permission notice shall be
18415 * included in all copies or substantial portions of the Software.
18416 *
18417 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18418 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18419 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18420 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18421 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18422 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18423 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18424 * ====================================================================
18425 */
18426
18427 /**
18428 * jsPDF PNG PlugIn
18429 * @name png_support
18430 * @module
18431 */
18432 (function(jsPDFAPI) {
18433
18434 /*
18435 * @see http://www.w3.org/TR/PNG-Chunks.html
18436 *
18437 Color Allowed Interpretation
18438 Type Bit Depths
18439
18440 0 1,2,4,8,16 Each pixel is a grayscale sample.
18441
18442 2 8,16 Each pixel is an R,G,B triple.
18443
18444 3 1,2,4,8 Each pixel is a palette index;
18445 a PLTE chunk must appear.
18446
18447 4 8,16 Each pixel is a grayscale sample,
18448 followed by an alpha sample.
18449
18450 6 8,16 Each pixel is an R,G,B triple,
18451 followed by an alpha sample.
18452 */
18453
18454 /*
18455 * PNG filter method types
18456 *
18457 * @see http://www.w3.org/TR/PNG-Filters.html
18458 * @see http://www.libpng.org/pub/png/book/chapter09.html
18459 *
18460 * This is what the value 'Predictor' in decode params relates to
18461 *
18462 * 15 is "optimal prediction", which means the prediction algorithm can change from line to line.
18463 * In that case, you actually have to read the first byte off each line for the prediction algorthim (which should be 0-4, corresponding to PDF 10-14) and select the appropriate unprediction algorithm based on that byte.
18464 *
18465 0 None
18466 1 Sub
18467 2 Up
18468 3 Average
18469 4 Paeth
18470 */
18471
18472 var canCompress = function(value) {
18473 return value !== jsPDFAPI.image_compression.NONE && hasCompressionJS();
18474 };
18475
18476 var hasCompressionJS = function() {
18477 return typeof zlibSync === "function";
18478 };
18479 var compressBytes = function(bytes, lineLength, colorsPerPixel, compression) {
18480 var level = 4;
18481 var filter_method = filterUp;
18482
18483 switch (compression) {
18484 case jsPDFAPI.image_compression.FAST:
18485 level = 1;
18486 filter_method = filterSub;
18487 break;
18488
18489 case jsPDFAPI.image_compression.MEDIUM:
18490 level = 6;
18491 filter_method = filterAverage;
18492 break;
18493
18494 case jsPDFAPI.image_compression.SLOW:
18495 level = 9;
18496 filter_method = filterPaeth;
18497 break;
18498 }
18499
18500 bytes = applyPngFilterMethod(
18501 bytes,
18502 lineLength,
18503 colorsPerPixel,
18504 filter_method
18505 );
18506 var dat = zlibSync(bytes, { level: level });
18507 return jsPDFAPI.__addimage__.arrayBufferToBinaryString(dat);
18508 };
18509
18510 var applyPngFilterMethod = function(
18511 bytes,
18512 lineLength,
18513 colorsPerPixel,
18514 filter_method
18515 ) {
18516 var lines = bytes.length / lineLength,
18517 result = new Uint8Array(bytes.length + lines),
18518 filter_methods = getFilterMethods(),
18519 line,
18520 prevLine,
18521 offset;
18522
18523 for (var i = 0; i < lines; i += 1) {
18524 offset = i * lineLength;
18525 line = bytes.subarray(offset, offset + lineLength);
18526
18527 if (filter_method) {
18528 result.set(filter_method(line, colorsPerPixel, prevLine), offset + i);
18529 } else {
18530 var len = filter_methods.length,
18531 results = [];
18532
18533 for (var j; j < len; j += 1) {
18534 results[j] = filter_methods[j](line, colorsPerPixel, prevLine);
18535 }
18536
18537 var ind = getIndexOfSmallestSum(results.concat());
18538
18539 result.set(results[ind], offset + i);
18540 }
18541
18542 prevLine = line;
18543 }
18544
18545 return result;
18546 };
18547
18548 var filterNone = function(line) {
18549 /*var result = new Uint8Array(line.length + 1);
18550 result[0] = 0;
18551 result.set(line, 1);*/
18552
18553 var result = Array.apply([], line);
18554 result.unshift(0);
18555
18556 return result;
18557 };
18558
18559 var filterSub = function(line, colorsPerPixel) {
18560 var result = [],
18561 len = line.length,
18562 left;
18563
18564 result[0] = 1;
18565
18566 for (var i = 0; i < len; i += 1) {
18567 left = line[i - colorsPerPixel] || 0;
18568 result[i + 1] = (line[i] - left + 0x0100) & 0xff;
18569 }
18570
18571 return result;
18572 };
18573
18574 var filterUp = function(line, colorsPerPixel, prevLine) {
18575 var result = [],
18576 len = line.length,
18577 up;
18578
18579 result[0] = 2;
18580
18581 for (var i = 0; i < len; i += 1) {
18582 up = (prevLine && prevLine[i]) || 0;
18583 result[i + 1] = (line[i] - up + 0x0100) & 0xff;
18584 }
18585
18586 return result;
18587 };
18588
18589 var filterAverage = function(line, colorsPerPixel, prevLine) {
18590 var result = [],
18591 len = line.length,
18592 left,
18593 up;
18594
18595 result[0] = 3;
18596
18597 for (var i = 0; i < len; i += 1) {
18598 left = line[i - colorsPerPixel] || 0;
18599 up = (prevLine && prevLine[i]) || 0;
18600 result[i + 1] = (line[i] + 0x0100 - ((left + up) >>> 1)) & 0xff;
18601 }
18602
18603 return result;
18604 };
18605
18606 var filterPaeth = function(line, colorsPerPixel, prevLine) {
18607 var result = [],
18608 len = line.length,
18609 left,
18610 up,
18611 upLeft,
18612 paeth;
18613
18614 result[0] = 4;
18615
18616 for (var i = 0; i < len; i += 1) {
18617 left = line[i - colorsPerPixel] || 0;
18618 up = (prevLine && prevLine[i]) || 0;
18619 upLeft = (prevLine && prevLine[i - colorsPerPixel]) || 0;
18620 paeth = paethPredictor(left, up, upLeft);
18621 result[i + 1] = (line[i] - paeth + 0x0100) & 0xff;
18622 }
18623
18624 return result;
18625 };
18626
18627 var paethPredictor = function(left, up, upLeft) {
18628 if (left === up && up === upLeft) {
18629 return left;
18630 }
18631 var pLeft = Math.abs(up - upLeft),
18632 pUp = Math.abs(left - upLeft),
18633 pUpLeft = Math.abs(left + up - upLeft - upLeft);
18634 return pLeft <= pUp && pLeft <= pUpLeft
18635 ? left
18636 : pUp <= pUpLeft
18637 ? up
18638 : upLeft;
18639 };
18640
18641 var getFilterMethods = function() {
18642 return [filterNone, filterSub, filterUp, filterAverage, filterPaeth];
18643 };
18644
18645 var getIndexOfSmallestSum = function(arrays) {
18646 var sum = arrays.map(function(value) {
18647 return value.reduce(function(pv, cv) {
18648 return pv + Math.abs(cv);
18649 }, 0);
18650 });
18651 return sum.indexOf(Math.min.apply(null, sum));
18652 };
18653
18654 var getPredictorFromCompression = function(compression) {
18655 var predictor;
18656 switch (compression) {
18657 case jsPDFAPI.image_compression.FAST:
18658 predictor = 11;
18659 break;
18660
18661 case jsPDFAPI.image_compression.MEDIUM:
18662 predictor = 13;
18663 break;
18664
18665 case jsPDFAPI.image_compression.SLOW:
18666 predictor = 14;
18667 break;
18668
18669 default:
18670 predictor = 12;
18671 break;
18672 }
18673 return predictor;
18674 };
18675
18676 /**
18677 * @name processPNG
18678 * @function
18679 * @ignore
18680 */
18681 jsPDFAPI.processPNG = function(imageData, index, alias, compression) {
18682
18683 var colorSpace,
18684 filter = this.decode.FLATE_DECODE,
18685 bitsPerComponent,
18686 image,
18687 decodeParameters = "",
18688 trns,
18689 colors,
18690 pal,
18691 smask,
18692 pixels,
18693 len,
18694 alphaData,
18695 imgData,
18696 hasColors,
18697 pixel,
18698 i,
18699 n;
18700
18701 if (this.__addimage__.isArrayBuffer(imageData))
18702 imageData = new Uint8Array(imageData);
18703
18704 if (this.__addimage__.isArrayBufferView(imageData)) {
18705 image = new PNG(imageData);
18706 imageData = image.imgData;
18707 bitsPerComponent = image.bits;
18708 colorSpace = image.colorSpace;
18709 colors = image.colors;
18710
18711 /*
18712 * colorType 6 - Each pixel is an R,G,B triple, followed by an alpha sample.
18713 *
18714 * colorType 4 - Each pixel is a grayscale sample, followed by an alpha sample.
18715 *
18716 * Extract alpha to create two separate images, using the alpha as a sMask
18717 */
18718 if ([4, 6].indexOf(image.colorType) !== -1) {
18719 /*
18720 * processes 8 bit RGBA and grayscale + alpha images
18721 */
18722 if (image.bits === 8) {
18723 pixels =
18724 image.pixelBitlength == 32
18725 ? new Uint32Array(image.decodePixels().buffer)
18726 : image.pixelBitlength == 16
18727 ? new Uint16Array(image.decodePixels().buffer)
18728 : new Uint8Array(image.decodePixels().buffer);
18729 len = pixels.length;
18730 imgData = new Uint8Array(len * image.colors);
18731 alphaData = new Uint8Array(len);
18732 var pDiff = image.pixelBitlength - image.bits;
18733 i = 0;
18734 n = 0;
18735 var pbl;
18736
18737 for (; i < len; i++) {
18738 pixel = pixels[i];
18739 pbl = 0;
18740
18741 while (pbl < pDiff) {
18742 imgData[n++] = (pixel >>> pbl) & 0xff;
18743 pbl = pbl + image.bits;
18744 }
18745
18746 alphaData[i] = (pixel >>> pbl) & 0xff;
18747 }
18748 }
18749
18750 /*
18751 * processes 16 bit RGBA and grayscale + alpha images
18752 */
18753 if (image.bits === 16) {
18754 pixels = new Uint32Array(image.decodePixels().buffer);
18755 len = pixels.length;
18756 imgData = new Uint8Array(
18757 len * (32 / image.pixelBitlength) * image.colors
18758 );
18759 alphaData = new Uint8Array(len * (32 / image.pixelBitlength));
18760 hasColors = image.colors > 1;
18761 i = 0;
18762 n = 0;
18763 var a = 0;
18764
18765 while (i < len) {
18766 pixel = pixels[i++];
18767
18768 imgData[n++] = (pixel >>> 0) & 0xff;
18769
18770 if (hasColors) {
18771 imgData[n++] = (pixel >>> 16) & 0xff;
18772
18773 pixel = pixels[i++];
18774 imgData[n++] = (pixel >>> 0) & 0xff;
18775 }
18776
18777 alphaData[a++] = (pixel >>> 16) & 0xff;
18778 }
18779 bitsPerComponent = 8;
18780 }
18781
18782 if (canCompress(compression)) {
18783 imageData = compressBytes(
18784 imgData,
18785 image.width * image.colors,
18786 image.colors,
18787 compression
18788 );
18789 smask = compressBytes(alphaData, image.width, 1, compression);
18790 } else {
18791 imageData = imgData;
18792 smask = alphaData;
18793 filter = undefined;
18794 }
18795 }
18796
18797 /*
18798 * Indexed png. Each pixel is a palette index.
18799 */
18800 if (image.colorType === 3) {
18801 colorSpace = this.color_spaces.INDEXED;
18802 pal = image.palette;
18803
18804 if (image.transparency.indexed) {
18805 var trans = image.transparency.indexed;
18806 var total = 0;
18807 i = 0;
18808 len = trans.length;
18809
18810 for (; i < len; ++i) {
18811 total += trans[i];
18812 }
18813
18814 total = total / 255;
18815
18816 /*
18817 * a single color is specified as 100% transparent (0),
18818 * so we set trns to use a /Mask with that index
18819 */
18820 if (total === len - 1 && trans.indexOf(0) !== -1) {
18821 trns = [trans.indexOf(0)];
18822
18823 /*
18824 * there's more than one colour within the palette that specifies
18825 * a transparency value less than 255, so we unroll the pixels to create an image sMask
18826 */
18827 } else if (total !== len) {
18828 pixels = image.decodePixels();
18829 alphaData = new Uint8Array(pixels.length);
18830 i = 0;
18831 len = pixels.length;
18832
18833 for (; i < len; i++) {
18834 alphaData[i] = trans[pixels[i]];
18835 }
18836
18837 smask = compressBytes(alphaData, image.width, 1);
18838 }
18839 }
18840 }
18841
18842 var predictor = getPredictorFromCompression(compression);
18843
18844 if (filter === this.decode.FLATE_DECODE) {
18845 decodeParameters = "/Predictor " + predictor + " ";
18846 }
18847 decodeParameters +=
18848 "/Colors " +
18849 colors +
18850 " /BitsPerComponent " +
18851 bitsPerComponent +
18852 " /Columns " +
18853 image.width;
18854
18855 if (
18856 this.__addimage__.isArrayBuffer(imageData) ||
18857 this.__addimage__.isArrayBufferView(imageData)
18858 ) {
18859 imageData = this.__addimage__.arrayBufferToBinaryString(imageData);
18860 }
18861
18862 if (
18863 (smask && this.__addimage__.isArrayBuffer(smask)) ||
18864 this.__addimage__.isArrayBufferView(smask)
18865 ) {
18866 smask = this.__addimage__.arrayBufferToBinaryString(smask);
18867 }
18868
18869 return {
18870 alias: alias,
18871 data: imageData,
18872 index: index,
18873 filter: filter,
18874 decodeParameters: decodeParameters,
18875 transparency: trns,
18876 palette: pal,
18877 sMask: smask,
18878 predictor: predictor,
18879 width: image.width,
18880 height: image.height,
18881 bitsPerComponent: bitsPerComponent,
18882 colorSpace: colorSpace
18883 };
18884 }
18885 };
18886 })(jsPDF.API);
18887
18888 /**
18889 * @license
18890 * (c) Dean McNamee <dean@gmail.com>, 2013.
18891 *
18892 * https://github.com/deanm/omggif
18893 *
18894 * Permission is hereby granted, free of charge, to any person obtaining a copy
18895 * of this software and associated documentation files (the "Software"), to
18896 * deal in the Software without restriction, including without limitation the
18897 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18898 * sell copies of the Software, and to permit persons to whom the Software is
18899 * furnished to do so, subject to the following conditions:
18900 *
18901 * The above copyright notice and this permission notice shall be included in
18902 * all copies or substantial portions of the Software.
18903 *
18904 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18905 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18906 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18907 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18908 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18909 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18910 * IN THE SOFTWARE.
18911 *
18912 * omggif is a JavaScript implementation of a GIF 89a encoder and decoder,
18913 * including animation and compression. It does not rely on any specific
18914 * underlying system, so should run in the browser, Node, or Plask.
18915 */
18916
18917 function GifReader(buf) {
18918 var p = 0;
18919
18920 // - Header (GIF87a or GIF89a).
18921 if (
18922 buf[p++] !== 0x47 ||
18923 buf[p++] !== 0x49 ||
18924 buf[p++] !== 0x46 ||
18925 buf[p++] !== 0x38 ||
18926 ((buf[p++] + 1) & 0xfd) !== 0x38 ||
18927 buf[p++] !== 0x61
18928 ) {
18929 throw new Error("Invalid GIF 87a/89a header.");
18930 }
18931
18932 // - Logical Screen Descriptor.
18933 var width = buf[p++] | (buf[p++] << 8);
18934 var height = buf[p++] | (buf[p++] << 8);
18935 var pf0 = buf[p++]; // <Packed Fields>.
18936 var global_palette_flag = pf0 >> 7;
18937 var num_global_colors_pow2 = pf0 & 0x7;
18938 var num_global_colors = 1 << (num_global_colors_pow2 + 1);
18939 var background = buf[p++];
18940 buf[p++]; // Pixel aspect ratio (unused?).
18941
18942 var global_palette_offset = null;
18943 var global_palette_size = null;
18944
18945 if (global_palette_flag) {
18946 global_palette_offset = p;
18947 global_palette_size = num_global_colors;
18948 p += num_global_colors * 3; // Seek past palette.
18949 }
18950
18951 var no_eof = true;
18952
18953 var frames = [];
18954
18955 var delay = 0;
18956 var transparent_index = null;
18957 var disposal = 0; // 0 - No disposal specified.
18958 var loop_count = null;
18959
18960 this.width = width;
18961 this.height = height;
18962
18963 while (no_eof && p < buf.length) {
18964 switch (buf[p++]) {
18965 case 0x21: // Graphics Control Extension Block
18966 switch (buf[p++]) {
18967 case 0xff: // Application specific block
18968 // Try if it's a Netscape block (with animation loop counter).
18969 if (
18970 buf[p] !== 0x0b || // 21 FF already read, check block size.
18971 // NETSCAPE2.0
18972 (buf[p + 1] == 0x4e &&
18973 buf[p + 2] == 0x45 &&
18974 buf[p + 3] == 0x54 &&
18975 buf[p + 4] == 0x53 &&
18976 buf[p + 5] == 0x43 &&
18977 buf[p + 6] == 0x41 &&
18978 buf[p + 7] == 0x50 &&
18979 buf[p + 8] == 0x45 &&
18980 buf[p + 9] == 0x32 &&
18981 buf[p + 10] == 0x2e &&
18982 buf[p + 11] == 0x30 &&
18983 // Sub-block
18984 buf[p + 12] == 0x03 &&
18985 buf[p + 13] == 0x01 &&
18986 buf[p + 16] == 0)
18987 ) {
18988 p += 14;
18989 loop_count = buf[p++] | (buf[p++] << 8);
18990 p++; // Skip terminator.
18991 } else {
18992 // We don't know what it is, just try to get past it.
18993 p += 12;
18994 while (true) {
18995 // Seek through subblocks.
18996 var block_size = buf[p++];
18997 // Bad block size (ex: undefined from an out of bounds read).
18998 if (!(block_size >= 0)) throw Error("Invalid block size");
18999 if (block_size === 0) break; // 0 size is terminator
19000 p += block_size;
19001 }
19002 }
19003 break;
19004
19005 case 0xf9: // Graphics Control Extension
19006 if (buf[p++] !== 0x4 || buf[p + 4] !== 0)
19007 throw new Error("Invalid graphics extension block.");
19008 var pf1 = buf[p++];
19009 delay = buf[p++] | (buf[p++] << 8);
19010 transparent_index = buf[p++];
19011 if ((pf1 & 1) === 0) transparent_index = null;
19012 disposal = (pf1 >> 2) & 0x7;
19013 p++; // Skip terminator.
19014 break;
19015
19016 case 0xfe: // Comment Extension.
19017 while (true) {
19018 // Seek through subblocks.
19019 var block_size = buf[p++];
19020 // Bad block size (ex: undefined from an out of bounds read).
19021 if (!(block_size >= 0)) throw Error("Invalid block size");
19022 if (block_size === 0) break; // 0 size is terminator
19023 // console.log(buf.slice(p, p+block_size).toString('ascii'));
19024 p += block_size;
19025 }
19026 break;
19027
19028 default:
19029 throw new Error(
19030 "Unknown graphic control label: 0x" + buf[p - 1].toString(16)
19031 );
19032 }
19033 break;
19034
19035 case 0x2c: // Image Descriptor.
19036 var x = buf[p++] | (buf[p++] << 8);
19037 var y = buf[p++] | (buf[p++] << 8);
19038 var w = buf[p++] | (buf[p++] << 8);
19039 var h = buf[p++] | (buf[p++] << 8);
19040 var pf2 = buf[p++];
19041 var local_palette_flag = pf2 >> 7;
19042 var interlace_flag = (pf2 >> 6) & 1;
19043 var num_local_colors_pow2 = pf2 & 0x7;
19044 var num_local_colors = 1 << (num_local_colors_pow2 + 1);
19045 var palette_offset = global_palette_offset;
19046 var palette_size = global_palette_size;
19047 var has_local_palette = false;
19048 if (local_palette_flag) {
19049 var has_local_palette = true;
19050 palette_offset = p; // Override with local palette.
19051 palette_size = num_local_colors;
19052 p += num_local_colors * 3; // Seek past palette.
19053 }
19054
19055 var data_offset = p;
19056
19057 p++; // codesize
19058 while (true) {
19059 var block_size = buf[p++];
19060 // Bad block size (ex: undefined from an out of bounds read).
19061 if (!(block_size >= 0)) throw Error("Invalid block size");
19062 if (block_size === 0) break; // 0 size is terminator
19063 p += block_size;
19064 }
19065
19066 frames.push({
19067 x: x,
19068 y: y,
19069 width: w,
19070 height: h,
19071 has_local_palette: has_local_palette,
19072 palette_offset: palette_offset,
19073 palette_size: palette_size,
19074 data_offset: data_offset,
19075 data_length: p - data_offset,
19076 transparent_index: transparent_index,
19077 interlaced: !!interlace_flag,
19078 delay: delay,
19079 disposal: disposal
19080 });
19081 break;
19082
19083 case 0x3b: // Trailer Marker (end of file).
19084 no_eof = false;
19085 break;
19086
19087 default:
19088 throw new Error("Unknown gif block: 0x" + buf[p - 1].toString(16));
19089 }
19090 }
19091
19092 this.numFrames = function() {
19093 return frames.length;
19094 };
19095
19096 this.loopCount = function() {
19097 return loop_count;
19098 };
19099
19100 this.frameInfo = function(frame_num) {
19101 if (frame_num < 0 || frame_num >= frames.length)
19102 throw new Error("Frame index out of range.");
19103 return frames[frame_num];
19104 };
19105
19106 this.decodeAndBlitFrameBGRA = function(frame_num, pixels) {
19107 var frame = this.frameInfo(frame_num);
19108 var num_pixels = frame.width * frame.height;
19109 var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices.
19110 GifReaderLZWOutputIndexStream(
19111 buf,
19112 frame.data_offset,
19113 index_stream,
19114 num_pixels
19115 );
19116 var palette_offset = frame.palette_offset;
19117
19118 // NOTE(deanm): It seems to be much faster to compare index to 256 than
19119 // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in
19120 // the profile, not sure if it's related to using a Uint8Array.
19121 var trans = frame.transparent_index;
19122 if (trans === null) trans = 256;
19123
19124 // We are possibly just blitting to a portion of the entire frame.
19125 // That is a subrect within the framerect, so the additional pixels
19126 // must be skipped over after we finished a scanline.
19127 var framewidth = frame.width;
19128 var framestride = width - framewidth;
19129 var xleft = framewidth; // Number of subrect pixels left in scanline.
19130
19131 // Output indices of the top left and bottom right corners of the subrect.
19132 var opbeg = (frame.y * width + frame.x) * 4;
19133 var opend = ((frame.y + frame.height) * width + frame.x) * 4;
19134 var op = opbeg;
19135
19136 var scanstride = framestride * 4;
19137
19138 // Use scanstride to skip past the rows when interlacing. This is skipping
19139 // 7 rows for the first two passes, then 3 then 1.
19140 if (frame.interlaced === true) {
19141 scanstride += width * 4 * 7; // Pass 1.
19142 }
19143
19144 var interlaceskip = 8; // Tracking the row interval in the current pass.
19145
19146 for (var i = 0, il = index_stream.length; i < il; ++i) {
19147 var index = index_stream[i];
19148
19149 if (xleft === 0) {
19150 // Beginning of new scan line
19151 op += scanstride;
19152 xleft = framewidth;
19153 if (op >= opend) {
19154 // Catch the wrap to switch passes when interlacing.
19155 scanstride = framestride * 4 + width * 4 * (interlaceskip - 1);
19156 // interlaceskip / 2 * 4 is interlaceskip << 1.
19157 op = opbeg + (framewidth + framestride) * (interlaceskip << 1);
19158 interlaceskip >>= 1;
19159 }
19160 }
19161
19162 if (index === trans) {
19163 op += 4;
19164 } else {
19165 var r = buf[palette_offset + index * 3];
19166 var g = buf[palette_offset + index * 3 + 1];
19167 var b = buf[palette_offset + index * 3 + 2];
19168 pixels[op++] = b;
19169 pixels[op++] = g;
19170 pixels[op++] = r;
19171 pixels[op++] = 255;
19172 }
19173 --xleft;
19174 }
19175 };
19176
19177 // I will go to copy and paste hell one day...
19178 this.decodeAndBlitFrameRGBA = function(frame_num, pixels) {
19179 var frame = this.frameInfo(frame_num);
19180 var num_pixels = frame.width * frame.height;
19181 var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices.
19182 GifReaderLZWOutputIndexStream(
19183 buf,
19184 frame.data_offset,
19185 index_stream,
19186 num_pixels
19187 );
19188 var palette_offset = frame.palette_offset;
19189
19190 // NOTE(deanm): It seems to be much faster to compare index to 256 than
19191 // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in
19192 // the profile, not sure if it's related to using a Uint8Array.
19193 var trans = frame.transparent_index;
19194 if (trans === null) trans = 256;
19195
19196 // We are possibly just blitting to a portion of the entire frame.
19197 // That is a subrect within the framerect, so the additional pixels
19198 // must be skipped over after we finished a scanline.
19199 var framewidth = frame.width;
19200 var framestride = width - framewidth;
19201 var xleft = framewidth; // Number of subrect pixels left in scanline.
19202
19203 // Output indices of the top left and bottom right corners of the subrect.
19204 var opbeg = (frame.y * width + frame.x) * 4;
19205 var opend = ((frame.y + frame.height) * width + frame.x) * 4;
19206 var op = opbeg;
19207
19208 var scanstride = framestride * 4;
19209
19210 // Use scanstride to skip past the rows when interlacing. This is skipping
19211 // 7 rows for the first two passes, then 3 then 1.
19212 if (frame.interlaced === true) {
19213 scanstride += width * 4 * 7; // Pass 1.
19214 }
19215
19216 var interlaceskip = 8; // Tracking the row interval in the current pass.
19217
19218 for (var i = 0, il = index_stream.length; i < il; ++i) {
19219 var index = index_stream[i];
19220
19221 if (xleft === 0) {
19222 // Beginning of new scan line
19223 op += scanstride;
19224 xleft = framewidth;
19225 if (op >= opend) {
19226 // Catch the wrap to switch passes when interlacing.
19227 scanstride = framestride * 4 + width * 4 * (interlaceskip - 1);
19228 // interlaceskip / 2 * 4 is interlaceskip << 1.
19229 op = opbeg + (framewidth + framestride) * (interlaceskip << 1);
19230 interlaceskip >>= 1;
19231 }
19232 }
19233
19234 if (index === trans) {
19235 op += 4;
19236 } else {
19237 var r = buf[palette_offset + index * 3];
19238 var g = buf[palette_offset + index * 3 + 1];
19239 var b = buf[palette_offset + index * 3 + 2];
19240 pixels[op++] = r;
19241 pixels[op++] = g;
19242 pixels[op++] = b;
19243 pixels[op++] = 255;
19244 }
19245 --xleft;
19246 }
19247 };
19248 }
19249
19250 function GifReaderLZWOutputIndexStream(code_stream, p, output, output_length) {
19251 var min_code_size = code_stream[p++];
19252
19253 var clear_code = 1 << min_code_size;
19254 var eoi_code = clear_code + 1;
19255 var next_code = eoi_code + 1;
19256
19257 var cur_code_size = min_code_size + 1; // Number of bits per code.
19258 // NOTE: This shares the same name as the encoder, but has a different
19259 // meaning here. Here this masks each code coming from the code stream.
19260 var code_mask = (1 << cur_code_size) - 1;
19261 var cur_shift = 0;
19262 var cur = 0;
19263
19264 var op = 0; // Output pointer.
19265
19266 var subblock_size = code_stream[p++];
19267
19268 // TODO(deanm): Would using a TypedArray be any faster? At least it would
19269 // solve the fast mode / backing store uncertainty.
19270 // var code_table = Array(4096);
19271 var code_table = new Int32Array(4096); // Can be signed, we only use 20 bits.
19272
19273 var prev_code = null; // Track code-1.
19274
19275 while (true) {
19276 // Read up to two bytes, making sure we always 12-bits for max sized code.
19277 while (cur_shift < 16) {
19278 if (subblock_size === 0) break; // No more data to be read.
19279
19280 cur |= code_stream[p++] << cur_shift;
19281 cur_shift += 8;
19282
19283 if (subblock_size === 1) {
19284 // Never let it get to 0 to hold logic above.
19285 subblock_size = code_stream[p++]; // Next subblock.
19286 } else {
19287 --subblock_size;
19288 }
19289 }
19290
19291 // TODO(deanm): We should never really get here, we should have received
19292 // and EOI.
19293 if (cur_shift < cur_code_size) break;
19294
19295 var code = cur & code_mask;
19296 cur >>= cur_code_size;
19297 cur_shift -= cur_code_size;
19298
19299 // TODO(deanm): Maybe should check that the first code was a clear code,
19300 // at least this is what you're supposed to do. But actually our encoder
19301 // now doesn't emit a clear code first anyway.
19302 if (code === clear_code) {
19303 // We don't actually have to clear the table. This could be a good idea
19304 // for greater error checking, but we don't really do any anyway. We
19305 // will just track it with next_code and overwrite old entries.
19306
19307 next_code = eoi_code + 1;
19308 cur_code_size = min_code_size + 1;
19309 code_mask = (1 << cur_code_size) - 1;
19310
19311 // Don't update prev_code ?
19312 prev_code = null;
19313 continue;
19314 } else if (code === eoi_code) {
19315 break;
19316 }
19317
19318 // We have a similar situation as the decoder, where we want to store
19319 // variable length entries (code table entries), but we want to do in a
19320 // faster manner than an array of arrays. The code below stores sort of a
19321 // linked list within the code table, and then "chases" through it to
19322 // construct the dictionary entries. When a new entry is created, just the
19323 // last byte is stored, and the rest (prefix) of the entry is only
19324 // referenced by its table entry. Then the code chases through the
19325 // prefixes until it reaches a single byte code. We have to chase twice,
19326 // first to compute the length, and then to actually copy the data to the
19327 // output (backwards, since we know the length). The alternative would be
19328 // storing something in an intermediate stack, but that doesn't make any
19329 // more sense. I implemented an approach where it also stored the length
19330 // in the code table, although it's a bit tricky because you run out of
19331 // bits (12 + 12 + 8), but I didn't measure much improvements (the table
19332 // entries are generally not the long). Even when I created benchmarks for
19333 // very long table entries the complexity did not seem worth it.
19334 // The code table stores the prefix entry in 12 bits and then the suffix
19335 // byte in 8 bits, so each entry is 20 bits.
19336
19337 var chase_code = code < next_code ? code : prev_code;
19338
19339 // Chase what we will output, either {CODE} or {CODE-1}.
19340 var chase_length = 0;
19341 var chase = chase_code;
19342 while (chase > clear_code) {
19343 chase = code_table[chase] >> 8;
19344 ++chase_length;
19345 }
19346
19347 var k = chase;
19348
19349 var op_end = op + chase_length + (chase_code !== code ? 1 : 0);
19350 if (op_end > output_length) {
19351 console.log("Warning, gif stream longer than expected.");
19352 return;
19353 }
19354
19355 // Already have the first byte from the chase, might as well write it fast.
19356 output[op++] = k;
19357
19358 op += chase_length;
19359 var b = op; // Track pointer, writing backwards.
19360
19361 if (chase_code !== code)
19362 // The case of emitting {CODE-1} + k.
19363 output[op++] = k;
19364
19365 chase = chase_code;
19366 while (chase_length--) {
19367 chase = code_table[chase];
19368 output[--b] = chase & 0xff; // Write backwards.
19369 chase >>= 8; // Pull down to the prefix code.
19370 }
19371
19372 if (prev_code !== null && next_code < 4096) {
19373 code_table[next_code++] = (prev_code << 8) | k;
19374 // TODO(deanm): Figure out this clearing vs code growth logic better. I
19375 // have an feeling that it should just happen somewhere else, for now it
19376 // is awkward between when we grow past the max and then hit a clear code.
19377 // For now just check if we hit the max 12-bits (then a clear code should
19378 // follow, also of course encoded in 12-bits).
19379 if (next_code >= code_mask + 1 && cur_code_size < 12) {
19380 ++cur_code_size;
19381 code_mask = (code_mask << 1) | 1;
19382 }
19383 }
19384
19385 prev_code = code;
19386 }
19387
19388 if (op !== output_length) {
19389 console.log("Warning, gif stream shorter than expected.");
19390 }
19391
19392 return output;
19393 }
19394
19395 /**
19396 * @license
19397 Copyright (c) 2008, Adobe Systems Incorporated
19398 All rights reserved.
19399
19400 Redistribution and use in source and binary forms, with or without
19401 modification, are permitted provided that the following conditions are
19402 met:
19403
19404 * Redistributions of source code must retain the above copyright notice,
19405 this list of conditions and the following disclaimer.
19406
19407 * Redistributions in binary form must reproduce the above copyright
19408 notice, this list of conditions and the following disclaimer in the
19409 documentation and/or other materials provided with the distribution.
19410
19411 * Neither the name of Adobe Systems Incorporated nor the names of its
19412 contributors may be used to endorse or promote products derived from
19413 this software without specific prior written permission.
19414
19415 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
19416 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19417 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19418 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19419 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19420 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19421 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19422 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19423 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
19424 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19425 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19426 */
19427 /*
19428 JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009
19429
19430 Basic GUI blocking jpeg encoder
19431 */
19432
19433 function JPEGEncoder(quality) {
19434 var ffloor = Math.floor;
19435 var YTable = new Array(64);
19436 var UVTable = new Array(64);
19437 var fdtbl_Y = new Array(64);
19438 var fdtbl_UV = new Array(64);
19439 var YDC_HT;
19440 var UVDC_HT;
19441 var YAC_HT;
19442 var UVAC_HT;
19443
19444 var bitcode = new Array(65535);
19445 var category = new Array(65535);
19446 var outputfDCTQuant = new Array(64);
19447 var DU = new Array(64);
19448 var byteout = [];
19449 var bytenew = 0;
19450 var bytepos = 7;
19451
19452 var YDU = new Array(64);
19453 var UDU = new Array(64);
19454 var VDU = new Array(64);
19455 var clt = new Array(256);
19456 var RGB_YUV_TABLE = new Array(2048);
19457 var currentQuality;
19458
19459 var ZigZag = [
19460 0,
19461 1,
19462 5,
19463 6,
19464 14,
19465 15,
19466 27,
19467 28,
19468 2,
19469 4,
19470 7,
19471 13,
19472 16,
19473 26,
19474 29,
19475 42,
19476 3,
19477 8,
19478 12,
19479 17,
19480 25,
19481 30,
19482 41,
19483 43,
19484 9,
19485 11,
19486 18,
19487 24,
19488 31,
19489 40,
19490 44,
19491 53,
19492 10,
19493 19,
19494 23,
19495 32,
19496 39,
19497 45,
19498 52,
19499 54,
19500 20,
19501 22,
19502 33,
19503 38,
19504 46,
19505 51,
19506 55,
19507 60,
19508 21,
19509 34,
19510 37,
19511 47,
19512 50,
19513 56,
19514 59,
19515 61,
19516 35,
19517 36,
19518 48,
19519 49,
19520 57,
19521 58,
19522 62,
19523 63
19524 ];
19525
19526 var std_dc_luminance_nrcodes = [
19527 0,
19528 0,
19529 1,
19530 5,
19531 1,
19532 1,
19533 1,
19534 1,
19535 1,
19536 1,
19537 0,
19538 0,
19539 0,
19540 0,
19541 0,
19542 0,
19543 0
19544 ];
19545 var std_dc_luminance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
19546 var std_ac_luminance_nrcodes = [
19547 0,
19548 0,
19549 2,
19550 1,
19551 3,
19552 3,
19553 2,
19554 4,
19555 3,
19556 5,
19557 5,
19558 4,
19559 4,
19560 0,
19561 0,
19562 1,
19563 0x7d
19564 ];
19565 var std_ac_luminance_values = [
19566 0x01,
19567 0x02,
19568 0x03,
19569 0x00,
19570 0x04,
19571 0x11,
19572 0x05,
19573 0x12,
19574 0x21,
19575 0x31,
19576 0x41,
19577 0x06,
19578 0x13,
19579 0x51,
19580 0x61,
19581 0x07,
19582 0x22,
19583 0x71,
19584 0x14,
19585 0x32,
19586 0x81,
19587 0x91,
19588 0xa1,
19589 0x08,
19590 0x23,
19591 0x42,
19592 0xb1,
19593 0xc1,
19594 0x15,
19595 0x52,
19596 0xd1,
19597 0xf0,
19598 0x24,
19599 0x33,
19600 0x62,
19601 0x72,
19602 0x82,
19603 0x09,
19604 0x0a,
19605 0x16,
19606 0x17,
19607 0x18,
19608 0x19,
19609 0x1a,
19610 0x25,
19611 0x26,
19612 0x27,
19613 0x28,
19614 0x29,
19615 0x2a,
19616 0x34,
19617 0x35,
19618 0x36,
19619 0x37,
19620 0x38,
19621 0x39,
19622 0x3a,
19623 0x43,
19624 0x44,
19625 0x45,
19626 0x46,
19627 0x47,
19628 0x48,
19629 0x49,
19630 0x4a,
19631 0x53,
19632 0x54,
19633 0x55,
19634 0x56,
19635 0x57,
19636 0x58,
19637 0x59,
19638 0x5a,
19639 0x63,
19640 0x64,
19641 0x65,
19642 0x66,
19643 0x67,
19644 0x68,
19645 0x69,
19646 0x6a,
19647 0x73,
19648 0x74,
19649 0x75,
19650 0x76,
19651 0x77,
19652 0x78,
19653 0x79,
19654 0x7a,
19655 0x83,
19656 0x84,
19657 0x85,
19658 0x86,
19659 0x87,
19660 0x88,
19661 0x89,
19662 0x8a,
19663 0x92,
19664 0x93,
19665 0x94,
19666 0x95,
19667 0x96,
19668 0x97,
19669 0x98,
19670 0x99,
19671 0x9a,
19672 0xa2,
19673 0xa3,
19674 0xa4,
19675 0xa5,
19676 0xa6,
19677 0xa7,
19678 0xa8,
19679 0xa9,
19680 0xaa,
19681 0xb2,
19682 0xb3,
19683 0xb4,
19684 0xb5,
19685 0xb6,
19686 0xb7,
19687 0xb8,
19688 0xb9,
19689 0xba,
19690 0xc2,
19691 0xc3,
19692 0xc4,
19693 0xc5,
19694 0xc6,
19695 0xc7,
19696 0xc8,
19697 0xc9,
19698 0xca,
19699 0xd2,
19700 0xd3,
19701 0xd4,
19702 0xd5,
19703 0xd6,
19704 0xd7,
19705 0xd8,
19706 0xd9,
19707 0xda,
19708 0xe1,
19709 0xe2,
19710 0xe3,
19711 0xe4,
19712 0xe5,
19713 0xe6,
19714 0xe7,
19715 0xe8,
19716 0xe9,
19717 0xea,
19718 0xf1,
19719 0xf2,
19720 0xf3,
19721 0xf4,
19722 0xf5,
19723 0xf6,
19724 0xf7,
19725 0xf8,
19726 0xf9,
19727 0xfa
19728 ];
19729
19730 var std_dc_chrominance_nrcodes = [
19731 0,
19732 0,
19733 3,
19734 1,
19735 1,
19736 1,
19737 1,
19738 1,
19739 1,
19740 1,
19741 1,
19742 1,
19743 0,
19744 0,
19745 0,
19746 0,
19747 0
19748 ];
19749 var std_dc_chrominance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
19750 var std_ac_chrominance_nrcodes = [
19751 0,
19752 0,
19753 2,
19754 1,
19755 2,
19756 4,
19757 4,
19758 3,
19759 4,
19760 7,
19761 5,
19762 4,
19763 4,
19764 0,
19765 1,
19766 2,
19767 0x77
19768 ];
19769 var std_ac_chrominance_values = [
19770 0x00,
19771 0x01,
19772 0x02,
19773 0x03,
19774 0x11,
19775 0x04,
19776 0x05,
19777 0x21,
19778 0x31,
19779 0x06,
19780 0x12,
19781 0x41,
19782 0x51,
19783 0x07,
19784 0x61,
19785 0x71,
19786 0x13,
19787 0x22,
19788 0x32,
19789 0x81,
19790 0x08,
19791 0x14,
19792 0x42,
19793 0x91,
19794 0xa1,
19795 0xb1,
19796 0xc1,
19797 0x09,
19798 0x23,
19799 0x33,
19800 0x52,
19801 0xf0,
19802 0x15,
19803 0x62,
19804 0x72,
19805 0xd1,
19806 0x0a,
19807 0x16,
19808 0x24,
19809 0x34,
19810 0xe1,
19811 0x25,
19812 0xf1,
19813 0x17,
19814 0x18,
19815 0x19,
19816 0x1a,
19817 0x26,
19818 0x27,
19819 0x28,
19820 0x29,
19821 0x2a,
19822 0x35,
19823 0x36,
19824 0x37,
19825 0x38,
19826 0x39,
19827 0x3a,
19828 0x43,
19829 0x44,
19830 0x45,
19831 0x46,
19832 0x47,
19833 0x48,
19834 0x49,
19835 0x4a,
19836 0x53,
19837 0x54,
19838 0x55,
19839 0x56,
19840 0x57,
19841 0x58,
19842 0x59,
19843 0x5a,
19844 0x63,
19845 0x64,
19846 0x65,
19847 0x66,
19848 0x67,
19849 0x68,
19850 0x69,
19851 0x6a,
19852 0x73,
19853 0x74,
19854 0x75,
19855 0x76,
19856 0x77,
19857 0x78,
19858 0x79,
19859 0x7a,
19860 0x82,
19861 0x83,
19862 0x84,
19863 0x85,
19864 0x86,
19865 0x87,
19866 0x88,
19867 0x89,
19868 0x8a,
19869 0x92,
19870 0x93,
19871 0x94,
19872 0x95,
19873 0x96,
19874 0x97,
19875 0x98,
19876 0x99,
19877 0x9a,
19878 0xa2,
19879 0xa3,
19880 0xa4,
19881 0xa5,
19882 0xa6,
19883 0xa7,
19884 0xa8,
19885 0xa9,
19886 0xaa,
19887 0xb2,
19888 0xb3,
19889 0xb4,
19890 0xb5,
19891 0xb6,
19892 0xb7,
19893 0xb8,
19894 0xb9,
19895 0xba,
19896 0xc2,
19897 0xc3,
19898 0xc4,
19899 0xc5,
19900 0xc6,
19901 0xc7,
19902 0xc8,
19903 0xc9,
19904 0xca,
19905 0xd2,
19906 0xd3,
19907 0xd4,
19908 0xd5,
19909 0xd6,
19910 0xd7,
19911 0xd8,
19912 0xd9,
19913 0xda,
19914 0xe2,
19915 0xe3,
19916 0xe4,
19917 0xe5,
19918 0xe6,
19919 0xe7,
19920 0xe8,
19921 0xe9,
19922 0xea,
19923 0xf2,
19924 0xf3,
19925 0xf4,
19926 0xf5,
19927 0xf6,
19928 0xf7,
19929 0xf8,
19930 0xf9,
19931 0xfa
19932 ];
19933
19934 function initQuantTables(sf) {
19935 var YQT = [
19936 16,
19937 11,
19938 10,
19939 16,
19940 24,
19941 40,
19942 51,
19943 61,
19944 12,
19945 12,
19946 14,
19947 19,
19948 26,
19949 58,
19950 60,
19951 55,
19952 14,
19953 13,
19954 16,
19955 24,
19956 40,
19957 57,
19958 69,
19959 56,
19960 14,
19961 17,
19962 22,
19963 29,
19964 51,
19965 87,
19966 80,
19967 62,
19968 18,
19969 22,
19970 37,
19971 56,
19972 68,
19973 109,
19974 103,
19975 77,
19976 24,
19977 35,
19978 55,
19979 64,
19980 81,
19981 104,
19982 113,
19983 92,
19984 49,
19985 64,
19986 78,
19987 87,
19988 103,
19989 121,
19990 120,
19991 101,
19992 72,
19993 92,
19994 95,
19995 98,
19996 112,
19997 100,
19998 103,
19999 99
20000 ];
20001
20002 for (var i = 0; i < 64; i++) {
20003 var t = ffloor((YQT[i] * sf + 50) / 100);
20004 t = Math.min(Math.max(t, 1), 255);
20005 YTable[ZigZag[i]] = t;
20006 }
20007 var UVQT = [
20008 17,
20009 18,
20010 24,
20011 47,
20012 99,
20013 99,
20014 99,
20015 99,
20016 18,
20017 21,
20018 26,
20019 66,
20020 99,
20021 99,
20022 99,
20023 99,
20024 24,
20025 26,
20026 56,
20027 99,
20028 99,
20029 99,
20030 99,
20031 99,
20032 47,
20033 66,
20034 99,
20035 99,
20036 99,
20037 99,
20038 99,
20039 99,
20040 99,
20041 99,
20042 99,
20043 99,
20044 99,
20045 99,
20046 99,
20047 99,
20048 99,
20049 99,
20050 99,
20051 99,
20052 99,
20053 99,
20054 99,
20055 99,
20056 99,
20057 99,
20058 99,
20059 99,
20060 99,
20061 99,
20062 99,
20063 99,
20064 99,
20065 99,
20066 99,
20067 99,
20068 99,
20069 99,
20070 99,
20071 99
20072 ];
20073 for (var j = 0; j < 64; j++) {
20074 var u = ffloor((UVQT[j] * sf + 50) / 100);
20075 u = Math.min(Math.max(u, 1), 255);
20076 UVTable[ZigZag[j]] = u;
20077 }
20078 var aasf = [
20079 1.0,
20080 1.387039845,
20081 1.306562965,
20082 1.175875602,
20083 1.0,
20084 0.785694958,
20085 0.5411961,
20086 0.275899379
20087 ];
20088 var k = 0;
20089 for (var row = 0; row < 8; row++) {
20090 for (var col = 0; col < 8; col++) {
20091 fdtbl_Y[k] = 1.0 / (YTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0);
20092 fdtbl_UV[k] = 1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0);
20093 k++;
20094 }
20095 }
20096 }
20097
20098 function computeHuffmanTbl(nrcodes, std_table) {
20099 var codevalue = 0;
20100 var pos_in_table = 0;
20101 var HT = new Array();
20102 for (var k = 1; k <= 16; k++) {
20103 for (var j = 1; j <= nrcodes[k]; j++) {
20104 HT[std_table[pos_in_table]] = [];
20105 HT[std_table[pos_in_table]][0] = codevalue;
20106 HT[std_table[pos_in_table]][1] = k;
20107 pos_in_table++;
20108 codevalue++;
20109 }
20110 codevalue *= 2;
20111 }
20112 return HT;
20113 }
20114
20115 function initHuffmanTbl() {
20116 YDC_HT = computeHuffmanTbl(
20117 std_dc_luminance_nrcodes,
20118 std_dc_luminance_values
20119 );
20120 UVDC_HT = computeHuffmanTbl(
20121 std_dc_chrominance_nrcodes,
20122 std_dc_chrominance_values
20123 );
20124 YAC_HT = computeHuffmanTbl(
20125 std_ac_luminance_nrcodes,
20126 std_ac_luminance_values
20127 );
20128 UVAC_HT = computeHuffmanTbl(
20129 std_ac_chrominance_nrcodes,
20130 std_ac_chrominance_values
20131 );
20132 }
20133
20134 function initCategoryNumber() {
20135 var nrlower = 1;
20136 var nrupper = 2;
20137 for (var cat = 1; cat <= 15; cat++) {
20138 //Positive numbers
20139 for (var nr = nrlower; nr < nrupper; nr++) {
20140 category[32767 + nr] = cat;
20141 bitcode[32767 + nr] = [];
20142 bitcode[32767 + nr][1] = cat;
20143 bitcode[32767 + nr][0] = nr;
20144 }
20145 //Negative numbers
20146 for (var nrneg = -(nrupper - 1); nrneg <= -nrlower; nrneg++) {
20147 category[32767 + nrneg] = cat;
20148 bitcode[32767 + nrneg] = [];
20149 bitcode[32767 + nrneg][1] = cat;
20150 bitcode[32767 + nrneg][0] = nrupper - 1 + nrneg;
20151 }
20152 nrlower <<= 1;
20153 nrupper <<= 1;
20154 }
20155 }
20156
20157 function initRGBYUVTable() {
20158 for (var i = 0; i < 256; i++) {
20159 RGB_YUV_TABLE[i] = 19595 * i;
20160 RGB_YUV_TABLE[(i + 256) >> 0] = 38470 * i;
20161 RGB_YUV_TABLE[(i + 512) >> 0] = 7471 * i + 0x8000;
20162 RGB_YUV_TABLE[(i + 768) >> 0] = -11059 * i;
20163 RGB_YUV_TABLE[(i + 1024) >> 0] = -21709 * i;
20164 RGB_YUV_TABLE[(i + 1280) >> 0] = 32768 * i + 0x807fff;
20165 RGB_YUV_TABLE[(i + 1536) >> 0] = -27439 * i;
20166 RGB_YUV_TABLE[(i + 1792) >> 0] = -5329 * i;
20167 }
20168 }
20169
20170 // IO functions
20171 function writeBits(bs) {
20172 var value = bs[0];
20173 var posval = bs[1] - 1;
20174 while (posval >= 0) {
20175 if (value & (1 << posval)) {
20176 bytenew |= 1 << bytepos;
20177 }
20178 posval--;
20179 bytepos--;
20180 if (bytepos < 0) {
20181 if (bytenew == 0xff) {
20182 writeByte(0xff);
20183 writeByte(0);
20184 } else {
20185 writeByte(bytenew);
20186 }
20187 bytepos = 7;
20188 bytenew = 0;
20189 }
20190 }
20191 }
20192
20193 function writeByte(value) {
20194 //byteout.push(clt[value]); // write char directly instead of converting later
20195 byteout.push(value);
20196 }
20197
20198 function writeWord(value) {
20199 writeByte((value >> 8) & 0xff);
20200 writeByte(value & 0xff);
20201 }
20202
20203 // DCT & quantization core
20204 function fDCTQuant(data, fdtbl) {
20205 var d0, d1, d2, d3, d4, d5, d6, d7;
20206 /* Pass 1: process rows. */
20207 var dataOff = 0;
20208 var i;
20209 var I8 = 8;
20210 var I64 = 64;
20211 for (i = 0; i < I8; ++i) {
20212 d0 = data[dataOff];
20213 d1 = data[dataOff + 1];
20214 d2 = data[dataOff + 2];
20215 d3 = data[dataOff + 3];
20216 d4 = data[dataOff + 4];
20217 d5 = data[dataOff + 5];
20218 d6 = data[dataOff + 6];
20219 d7 = data[dataOff + 7];
20220
20221 var tmp0 = d0 + d7;
20222 var tmp7 = d0 - d7;
20223 var tmp1 = d1 + d6;
20224 var tmp6 = d1 - d6;
20225 var tmp2 = d2 + d5;
20226 var tmp5 = d2 - d5;
20227 var tmp3 = d3 + d4;
20228 var tmp4 = d3 - d4;
20229
20230 /* Even part */
20231 var tmp10 = tmp0 + tmp3; /* phase 2 */
20232 var tmp13 = tmp0 - tmp3;
20233 var tmp11 = tmp1 + tmp2;
20234 var tmp12 = tmp1 - tmp2;
20235
20236 data[dataOff] = tmp10 + tmp11; /* phase 3 */
20237 data[dataOff + 4] = tmp10 - tmp11;
20238
20239 var z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */
20240 data[dataOff + 2] = tmp13 + z1; /* phase 5 */
20241 data[dataOff + 6] = tmp13 - z1;
20242
20243 /* Odd part */
20244 tmp10 = tmp4 + tmp5; /* phase 2 */
20245 tmp11 = tmp5 + tmp6;
20246 tmp12 = tmp6 + tmp7;
20247
20248 /* The rotator is modified from fig 4-8 to avoid extra negations. */
20249 var z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */
20250 var z2 = 0.5411961 * tmp10 + z5; /* c2-c6 */
20251 var z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */
20252 var z3 = tmp11 * 0.707106781; /* c4 */
20253
20254 var z11 = tmp7 + z3; /* phase 5 */
20255 var z13 = tmp7 - z3;
20256
20257 data[dataOff + 5] = z13 + z2; /* phase 6 */
20258 data[dataOff + 3] = z13 - z2;
20259 data[dataOff + 1] = z11 + z4;
20260 data[dataOff + 7] = z11 - z4;
20261
20262 dataOff += 8; /* advance pointer to next row */
20263 }
20264
20265 /* Pass 2: process columns. */
20266 dataOff = 0;
20267 for (i = 0; i < I8; ++i) {
20268 d0 = data[dataOff];
20269 d1 = data[dataOff + 8];
20270 d2 = data[dataOff + 16];
20271 d3 = data[dataOff + 24];
20272 d4 = data[dataOff + 32];
20273 d5 = data[dataOff + 40];
20274 d6 = data[dataOff + 48];
20275 d7 = data[dataOff + 56];
20276
20277 var tmp0p2 = d0 + d7;
20278 var tmp7p2 = d0 - d7;
20279 var tmp1p2 = d1 + d6;
20280 var tmp6p2 = d1 - d6;
20281 var tmp2p2 = d2 + d5;
20282 var tmp5p2 = d2 - d5;
20283 var tmp3p2 = d3 + d4;
20284 var tmp4p2 = d3 - d4;
20285
20286 /* Even part */
20287 var tmp10p2 = tmp0p2 + tmp3p2; /* phase 2 */
20288 var tmp13p2 = tmp0p2 - tmp3p2;
20289 var tmp11p2 = tmp1p2 + tmp2p2;
20290 var tmp12p2 = tmp1p2 - tmp2p2;
20291
20292 data[dataOff] = tmp10p2 + tmp11p2; /* phase 3 */
20293 data[dataOff + 32] = tmp10p2 - tmp11p2;
20294
20295 var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */
20296 data[dataOff + 16] = tmp13p2 + z1p2; /* phase 5 */
20297 data[dataOff + 48] = tmp13p2 - z1p2;
20298
20299 /* Odd part */
20300 tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */
20301 tmp11p2 = tmp5p2 + tmp6p2;
20302 tmp12p2 = tmp6p2 + tmp7p2;
20303
20304 /* The rotator is modified from fig 4-8 to avoid extra negations. */
20305 var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */
20306 var z2p2 = 0.5411961 * tmp10p2 + z5p2; /* c2-c6 */
20307 var z4p2 = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */
20308 var z3p2 = tmp11p2 * 0.707106781; /* c4 */
20309
20310 var z11p2 = tmp7p2 + z3p2; /* phase 5 */
20311 var z13p2 = tmp7p2 - z3p2;
20312
20313 data[dataOff + 40] = z13p2 + z2p2; /* phase 6 */
20314 data[dataOff + 24] = z13p2 - z2p2;
20315 data[dataOff + 8] = z11p2 + z4p2;
20316 data[dataOff + 56] = z11p2 - z4p2;
20317
20318 dataOff++; /* advance pointer to next column */
20319 }
20320
20321 // Quantize/descale the coefficients
20322 var fDCTQuant;
20323 for (i = 0; i < I64; ++i) {
20324 // Apply the quantization and scaling factor & Round to nearest integer
20325 fDCTQuant = data[i] * fdtbl[i];
20326 outputfDCTQuant[i] =
20327 fDCTQuant > 0.0 ? (fDCTQuant + 0.5) | 0 : (fDCTQuant - 0.5) | 0;
20328 //outputfDCTQuant[i] = fround(fDCTQuant);
20329 }
20330 return outputfDCTQuant;
20331 }
20332
20333 function writeAPP0() {
20334 writeWord(0xffe0); // marker
20335 writeWord(16); // length
20336 writeByte(0x4a); // J
20337 writeByte(0x46); // F
20338 writeByte(0x49); // I
20339 writeByte(0x46); // F
20340 writeByte(0); // = "JFIF",'\0'
20341 writeByte(1); // versionhi
20342 writeByte(1); // versionlo
20343 writeByte(0); // xyunits
20344 writeWord(1); // xdensity
20345 writeWord(1); // ydensity
20346 writeByte(0); // thumbnwidth
20347 writeByte(0); // thumbnheight
20348 }
20349
20350 function writeSOF0(width, height) {
20351 writeWord(0xffc0); // marker
20352 writeWord(17); // length, truecolor YUV JPG
20353 writeByte(8); // precision
20354 writeWord(height);
20355 writeWord(width);
20356 writeByte(3); // nrofcomponents
20357 writeByte(1); // IdY
20358 writeByte(0x11); // HVY
20359 writeByte(0); // QTY
20360 writeByte(2); // IdU
20361 writeByte(0x11); // HVU
20362 writeByte(1); // QTU
20363 writeByte(3); // IdV
20364 writeByte(0x11); // HVV
20365 writeByte(1); // QTV
20366 }
20367
20368 function writeDQT() {
20369 writeWord(0xffdb); // marker
20370 writeWord(132); // length
20371 writeByte(0);
20372 for (var i = 0; i < 64; i++) {
20373 writeByte(YTable[i]);
20374 }
20375 writeByte(1);
20376 for (var j = 0; j < 64; j++) {
20377 writeByte(UVTable[j]);
20378 }
20379 }
20380
20381 function writeDHT() {
20382 writeWord(0xffc4); // marker
20383 writeWord(0x01a2); // length
20384
20385 writeByte(0); // HTYDCinfo
20386 for (var i = 0; i < 16; i++) {
20387 writeByte(std_dc_luminance_nrcodes[i + 1]);
20388 }
20389 for (var j = 0; j <= 11; j++) {
20390 writeByte(std_dc_luminance_values[j]);
20391 }
20392
20393 writeByte(0x10); // HTYACinfo
20394 for (var k = 0; k < 16; k++) {
20395 writeByte(std_ac_luminance_nrcodes[k + 1]);
20396 }
20397 for (var l = 0; l <= 161; l++) {
20398 writeByte(std_ac_luminance_values[l]);
20399 }
20400
20401 writeByte(1); // HTUDCinfo
20402 for (var m = 0; m < 16; m++) {
20403 writeByte(std_dc_chrominance_nrcodes[m + 1]);
20404 }
20405 for (var n = 0; n <= 11; n++) {
20406 writeByte(std_dc_chrominance_values[n]);
20407 }
20408
20409 writeByte(0x11); // HTUACinfo
20410 for (var o = 0; o < 16; o++) {
20411 writeByte(std_ac_chrominance_nrcodes[o + 1]);
20412 }
20413 for (var p = 0; p <= 161; p++) {
20414 writeByte(std_ac_chrominance_values[p]);
20415 }
20416 }
20417
20418 function writeSOS() {
20419 writeWord(0xffda); // marker
20420 writeWord(12); // length
20421 writeByte(3); // nrofcomponents
20422 writeByte(1); // IdY
20423 writeByte(0); // HTY
20424 writeByte(2); // IdU
20425 writeByte(0x11); // HTU
20426 writeByte(3); // IdV
20427 writeByte(0x11); // HTV
20428 writeByte(0); // Ss
20429 writeByte(0x3f); // Se
20430 writeByte(0); // Bf
20431 }
20432
20433 function processDU(CDU, fdtbl, DC, HTDC, HTAC) {
20434 var EOB = HTAC[0x00];
20435 var M16zeroes = HTAC[0xf0];
20436 var pos;
20437 var I16 = 16;
20438 var I63 = 63;
20439 var I64 = 64;
20440 var DU_DCT = fDCTQuant(CDU, fdtbl);
20441 //ZigZag reorder
20442 for (var j = 0; j < I64; ++j) {
20443 DU[ZigZag[j]] = DU_DCT[j];
20444 }
20445 var Diff = DU[0] - DC;
20446 DC = DU[0];
20447 //Encode DC
20448 if (Diff == 0) {
20449 writeBits(HTDC[0]); // Diff might be 0
20450 } else {
20451 pos = 32767 + Diff;
20452 writeBits(HTDC[category[pos]]);
20453 writeBits(bitcode[pos]);
20454 }
20455 //Encode ACs
20456 var end0pos = 63; // was const... which is crazy
20457 while (end0pos > 0 && DU[end0pos] == 0) {
20458 end0pos--;
20459 }
20460 //end0pos = first element in reverse order !=0
20461 if (end0pos == 0) {
20462 writeBits(EOB);
20463 return DC;
20464 }
20465 var i = 1;
20466 var lng;
20467 while (i <= end0pos) {
20468 var startpos = i;
20469 while (DU[i] == 0 && i <= end0pos) {
20470 ++i;
20471 }
20472 var nrzeroes = i - startpos;
20473 if (nrzeroes >= I16) {
20474 lng = nrzeroes >> 4;
20475 for (var nrmarker = 1; nrmarker <= lng; ++nrmarker)
20476 writeBits(M16zeroes);
20477 nrzeroes = nrzeroes & 0xf;
20478 }
20479 pos = 32767 + DU[i];
20480 writeBits(HTAC[(nrzeroes << 4) + category[pos]]);
20481 writeBits(bitcode[pos]);
20482 i++;
20483 }
20484 if (end0pos != I63) {
20485 writeBits(EOB);
20486 }
20487 return DC;
20488 }
20489
20490 function initCharLookupTable() {
20491 var sfcc = String.fromCharCode;
20492 for (var i = 0; i < 256; i++) {
20493 ///// ACHTUNG // 255
20494 clt[i] = sfcc(i);
20495 }
20496 }
20497
20498 this.encode = function(
20499 image,
20500 quality // image data object
20501 ) {
20502 if (quality) setQuality(quality);
20503
20504 // Initialize bit writer
20505 byteout = new Array();
20506 bytenew = 0;
20507 bytepos = 7;
20508
20509 // Add JPEG headers
20510 writeWord(0xffd8); // SOI
20511 writeAPP0();
20512 writeDQT();
20513 writeSOF0(image.width, image.height);
20514 writeDHT();
20515 writeSOS();
20516
20517 // Encode 8x8 macroblocks
20518 var DCY = 0;
20519 var DCU = 0;
20520 var DCV = 0;
20521
20522 bytenew = 0;
20523 bytepos = 7;
20524
20525 this.encode.displayName = "_encode_";
20526
20527 var imageData = image.data;
20528 var width = image.width;
20529 var height = image.height;
20530
20531 var quadWidth = width * 4;
20532
20533 var x,
20534 y = 0;
20535 var r, g, b;
20536 var start, p, col, row, pos;
20537 while (y < height) {
20538 x = 0;
20539 while (x < quadWidth) {
20540 start = quadWidth * y + x;
20541 col = -1;
20542 row = 0;
20543
20544 for (pos = 0; pos < 64; pos++) {
20545 row = pos >> 3; // /8
20546 col = (pos & 7) * 4; // %8
20547 p = start + row * quadWidth + col;
20548
20549 if (y + row >= height) {
20550 // padding bottom
20551 p -= quadWidth * (y + 1 + row - height);
20552 }
20553
20554 if (x + col >= quadWidth) {
20555 // padding right
20556 p -= x + col - quadWidth + 4;
20557 }
20558
20559 r = imageData[p++];
20560 g = imageData[p++];
20561 b = imageData[p++];
20562
20563 /* // calculate YUV values dynamically
20564 YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80
20565 UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));
20566 VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));
20567 */
20568
20569 // use lookup table (slightly faster)
20570 YDU[pos] =
20571 ((RGB_YUV_TABLE[r] +
20572 RGB_YUV_TABLE[(g + 256) >> 0] +
20573 RGB_YUV_TABLE[(b + 512) >> 0]) >>
20574 16) -
20575 128;
20576 UDU[pos] =
20577 ((RGB_YUV_TABLE[(r + 768) >> 0] +
20578 RGB_YUV_TABLE[(g + 1024) >> 0] +
20579 RGB_YUV_TABLE[(b + 1280) >> 0]) >>
20580 16) -
20581 128;
20582 VDU[pos] =
20583 ((RGB_YUV_TABLE[(r + 1280) >> 0] +
20584 RGB_YUV_TABLE[(g + 1536) >> 0] +
20585 RGB_YUV_TABLE[(b + 1792) >> 0]) >>
20586 16) -
20587 128;
20588 }
20589
20590 DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
20591 DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
20592 DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
20593 x += 32;
20594 }
20595 y += 8;
20596 }
20597
20598 ////////////////////////////////////////////////////////////////
20599
20600 // Do the bit alignment of the EOI marker
20601 if (bytepos >= 0) {
20602 var fillbits = [];
20603 fillbits[1] = bytepos + 1;
20604 fillbits[0] = (1 << (bytepos + 1)) - 1;
20605 writeBits(fillbits);
20606 }
20607
20608 writeWord(0xffd9); //EOI
20609
20610 return new Uint8Array(byteout);
20611 };
20612
20613 function setQuality(quality) {
20614 quality = Math.min(Math.max(quality, 1), 100);
20615
20616 if (currentQuality == quality) return; // don't recalc if unchanged
20617
20618 var sf =
20619 quality < 50 ? Math.floor(5000 / quality) : Math.floor(200 - quality * 2);
20620
20621 initQuantTables(sf);
20622 currentQuality = quality;
20623 //console.log('Quality set to: '+quality +'%');
20624 }
20625
20626 function init() {
20627 quality = quality || 50;
20628 // Create tables
20629 initCharLookupTable();
20630 initHuffmanTbl();
20631 initCategoryNumber();
20632 initRGBYUVTable();
20633
20634 setQuality(quality);
20635 }
20636 init();
20637 }
20638
20639 /**
20640 * @license
20641 * Copyright (c) 2017 Aras Abbasi
20642 *
20643 * Licensed under the MIT License.
20644 * http://opensource.org/licenses/mit-license
20645 */
20646
20647 /**
20648 * jsPDF Gif Support PlugIn
20649 *
20650 * @name gif_support
20651 * @module
20652 */
20653 (function(jsPDFAPI) {
20654
20655 jsPDFAPI.processGIF89A = function(imageData, index, alias, compression) {
20656 var reader = new GifReader(imageData);
20657 var width = reader.width,
20658 height = reader.height;
20659 var qu = 100;
20660 var pixels = [];
20661
20662 reader.decodeAndBlitFrameRGBA(0, pixels);
20663 var rawImageData = {
20664 data: pixels,
20665 width: width,
20666 height: height
20667 };
20668
20669 var encoder = new JPEGEncoder(qu);
20670 var data = encoder.encode(rawImageData, qu);
20671 return jsPDFAPI.processJPEG.call(this, data, index, alias, compression);
20672 };
20673
20674 jsPDFAPI.processGIF87A = jsPDFAPI.processGIF89A;
20675 })(jsPDF.API);
20676
20677 /**
20678 * @author shaozilee
20679 *
20680 * Bmp format decoder,support 1bit 4bit 8bit 24bit bmp
20681 *
20682 */
20683
20684 function BmpDecoder(buffer, is_with_alpha) {
20685 this.pos = 0;
20686 this.buffer = buffer;
20687 this.datav = new DataView(buffer.buffer);
20688 this.is_with_alpha = !!is_with_alpha;
20689 this.bottom_up = true;
20690 this.flag =
20691 String.fromCharCode(this.buffer[0]) + String.fromCharCode(this.buffer[1]);
20692 this.pos += 2;
20693 if (["BM", "BA", "CI", "CP", "IC", "PT"].indexOf(this.flag) === -1)
20694 throw new Error("Invalid BMP File");
20695 this.parseHeader();
20696 this.parseBGR();
20697 }
20698
20699 BmpDecoder.prototype.parseHeader = function() {
20700 this.fileSize = this.datav.getUint32(this.pos, true);
20701 this.pos += 4;
20702 this.reserved = this.datav.getUint32(this.pos, true);
20703 this.pos += 4;
20704 this.offset = this.datav.getUint32(this.pos, true);
20705 this.pos += 4;
20706 this.headerSize = this.datav.getUint32(this.pos, true);
20707 this.pos += 4;
20708 this.width = this.datav.getUint32(this.pos, true);
20709 this.pos += 4;
20710 this.height = this.datav.getInt32(this.pos, true);
20711 this.pos += 4;
20712 this.planes = this.datav.getUint16(this.pos, true);
20713 this.pos += 2;
20714 this.bitPP = this.datav.getUint16(this.pos, true);
20715 this.pos += 2;
20716 this.compress = this.datav.getUint32(this.pos, true);
20717 this.pos += 4;
20718 this.rawSize = this.datav.getUint32(this.pos, true);
20719 this.pos += 4;
20720 this.hr = this.datav.getUint32(this.pos, true);
20721 this.pos += 4;
20722 this.vr = this.datav.getUint32(this.pos, true);
20723 this.pos += 4;
20724 this.colors = this.datav.getUint32(this.pos, true);
20725 this.pos += 4;
20726 this.importantColors = this.datav.getUint32(this.pos, true);
20727 this.pos += 4;
20728
20729 if (this.bitPP === 16 && this.is_with_alpha) {
20730 this.bitPP = 15;
20731 }
20732 if (this.bitPP < 15) {
20733 var len = this.colors === 0 ? 1 << this.bitPP : this.colors;
20734 this.palette = new Array(len);
20735 for (var i = 0; i < len; i++) {
20736 var blue = this.datav.getUint8(this.pos++, true);
20737 var green = this.datav.getUint8(this.pos++, true);
20738 var red = this.datav.getUint8(this.pos++, true);
20739 var quad = this.datav.getUint8(this.pos++, true);
20740 this.palette[i] = {
20741 red: red,
20742 green: green,
20743 blue: blue,
20744 quad: quad
20745 };
20746 }
20747 }
20748 if (this.height < 0) {
20749 this.height *= -1;
20750 this.bottom_up = false;
20751 }
20752 };
20753
20754 BmpDecoder.prototype.parseBGR = function() {
20755 this.pos = this.offset;
20756 try {
20757 var bitn = "bit" + this.bitPP;
20758 var len = this.width * this.height * 4;
20759 this.data = new Uint8Array(len);
20760
20761 this[bitn]();
20762 } catch (e) {
20763 console.log("bit decode error:" + e);
20764 }
20765 };
20766
20767 BmpDecoder.prototype.bit1 = function() {
20768 var xlen = Math.ceil(this.width / 8);
20769 var mode = xlen % 4;
20770 var y;
20771 for (y = this.height - 1; y >= 0; y--) {
20772 var line = this.bottom_up ? y : this.height - 1 - y;
20773 for (var x = 0; x < xlen; x++) {
20774 var b = this.datav.getUint8(this.pos++, true);
20775 var location = line * this.width * 4 + x * 8 * 4;
20776 for (var i = 0; i < 8; i++) {
20777 if (x * 8 + i < this.width) {
20778 var rgb = this.palette[(b >> (7 - i)) & 0x1];
20779 this.data[location + i * 4] = rgb.blue;
20780 this.data[location + i * 4 + 1] = rgb.green;
20781 this.data[location + i * 4 + 2] = rgb.red;
20782 this.data[location + i * 4 + 3] = 0xff;
20783 } else {
20784 break;
20785 }
20786 }
20787 }
20788
20789 if (mode !== 0) {
20790 this.pos += 4 - mode;
20791 }
20792 }
20793 };
20794
20795 BmpDecoder.prototype.bit4 = function() {
20796 var xlen = Math.ceil(this.width / 2);
20797 var mode = xlen % 4;
20798 for (var y = this.height - 1; y >= 0; y--) {
20799 var line = this.bottom_up ? y : this.height - 1 - y;
20800 for (var x = 0; x < xlen; x++) {
20801 var b = this.datav.getUint8(this.pos++, true);
20802 var location = line * this.width * 4 + x * 2 * 4;
20803
20804 var before = b >> 4;
20805 var after = b & 0x0f;
20806
20807 var rgb = this.palette[before];
20808 this.data[location] = rgb.blue;
20809 this.data[location + 1] = rgb.green;
20810 this.data[location + 2] = rgb.red;
20811 this.data[location + 3] = 0xff;
20812
20813 if (x * 2 + 1 >= this.width) break;
20814
20815 rgb = this.palette[after];
20816 this.data[location + 4] = rgb.blue;
20817 this.data[location + 4 + 1] = rgb.green;
20818 this.data[location + 4 + 2] = rgb.red;
20819 this.data[location + 4 + 3] = 0xff;
20820 }
20821
20822 if (mode !== 0) {
20823 this.pos += 4 - mode;
20824 }
20825 }
20826 };
20827
20828 BmpDecoder.prototype.bit8 = function() {
20829 var mode = this.width % 4;
20830 for (var y = this.height - 1; y >= 0; y--) {
20831 var line = this.bottom_up ? y : this.height - 1 - y;
20832 for (var x = 0; x < this.width; x++) {
20833 var b = this.datav.getUint8(this.pos++, true);
20834 var location = line * this.width * 4 + x * 4;
20835 if (b < this.palette.length) {
20836 var rgb = this.palette[b];
20837 this.data[location] = rgb.red;
20838 this.data[location + 1] = rgb.green;
20839 this.data[location + 2] = rgb.blue;
20840 this.data[location + 3] = 0xff;
20841 } else {
20842 this.data[location] = 0xff;
20843 this.data[location + 1] = 0xff;
20844 this.data[location + 2] = 0xff;
20845 this.data[location + 3] = 0xff;
20846 }
20847 }
20848 if (mode !== 0) {
20849 this.pos += 4 - mode;
20850 }
20851 }
20852 };
20853
20854 BmpDecoder.prototype.bit15 = function() {
20855 var dif_w = this.width % 3;
20856 var _11111 = parseInt("11111", 2),
20857 _1_5 = _11111;
20858 for (var y = this.height - 1; y >= 0; y--) {
20859 var line = this.bottom_up ? y : this.height - 1 - y;
20860 for (var x = 0; x < this.width; x++) {
20861 var B = this.datav.getUint16(this.pos, true);
20862 this.pos += 2;
20863 var blue = (((B & _1_5) / _1_5) * 255) | 0;
20864 var green = ((((B >> 5) & _1_5) / _1_5) * 255) | 0;
20865 var red = ((((B >> 10) & _1_5) / _1_5) * 255) | 0;
20866 var alpha = B >> 15 ? 0xff : 0x00;
20867
20868 var location = line * this.width * 4 + x * 4;
20869 this.data[location] = red;
20870 this.data[location + 1] = green;
20871 this.data[location + 2] = blue;
20872 this.data[location + 3] = alpha;
20873 }
20874 //skip extra bytes
20875 this.pos += dif_w;
20876 }
20877 };
20878
20879 BmpDecoder.prototype.bit16 = function() {
20880 var dif_w = this.width % 3;
20881 var _11111 = parseInt("11111", 2),
20882 _1_5 = _11111;
20883 var _111111 = parseInt("111111", 2),
20884 _1_6 = _111111;
20885 for (var y = this.height - 1; y >= 0; y--) {
20886 var line = this.bottom_up ? y : this.height - 1 - y;
20887 for (var x = 0; x < this.width; x++) {
20888 var B = this.datav.getUint16(this.pos, true);
20889 this.pos += 2;
20890 var alpha = 0xff;
20891 var blue = (((B & _1_5) / _1_5) * 255) | 0;
20892 var green = ((((B >> 5) & _1_6) / _1_6) * 255) | 0;
20893 var red = (((B >> 11) / _1_5) * 255) | 0;
20894
20895 var location = line * this.width * 4 + x * 4;
20896 this.data[location] = red;
20897 this.data[location + 1] = green;
20898 this.data[location + 2] = blue;
20899 this.data[location + 3] = alpha;
20900 }
20901 //skip extra bytes
20902 this.pos += dif_w;
20903 }
20904 };
20905
20906 BmpDecoder.prototype.bit24 = function() {
20907 //when height > 0
20908 for (var y = this.height - 1; y >= 0; y--) {
20909 var line = this.bottom_up ? y : this.height - 1 - y;
20910 for (var x = 0; x < this.width; x++) {
20911 var blue = this.datav.getUint8(this.pos++, true);
20912 var green = this.datav.getUint8(this.pos++, true);
20913 var red = this.datav.getUint8(this.pos++, true);
20914 var location = line * this.width * 4 + x * 4;
20915 this.data[location] = red;
20916 this.data[location + 1] = green;
20917 this.data[location + 2] = blue;
20918 this.data[location + 3] = 0xff;
20919 }
20920 //skip extra bytes
20921 this.pos += this.width % 4;
20922 }
20923 };
20924
20925 /**
20926 * add 32bit decode func
20927 * @author soubok
20928 */
20929 BmpDecoder.prototype.bit32 = function() {
20930 //when height > 0
20931 for (var y = this.height - 1; y >= 0; y--) {
20932 var line = this.bottom_up ? y : this.height - 1 - y;
20933 for (var x = 0; x < this.width; x++) {
20934 var blue = this.datav.getUint8(this.pos++, true);
20935 var green = this.datav.getUint8(this.pos++, true);
20936 var red = this.datav.getUint8(this.pos++, true);
20937 var alpha = this.datav.getUint8(this.pos++, true);
20938 var location = line * this.width * 4 + x * 4;
20939 this.data[location] = red;
20940 this.data[location + 1] = green;
20941 this.data[location + 2] = blue;
20942 this.data[location + 3] = alpha;
20943 }
20944 //skip extra bytes
20945 //this.pos += (this.width % 4);
20946 }
20947 };
20948
20949 BmpDecoder.prototype.getData = function() {
20950 return this.data;
20951 };
20952
20953 /**
20954 * @license
20955 * Copyright (c) 2018 Aras Abbasi
20956 *
20957 * Licensed under the MIT License.
20958 * http://opensource.org/licenses/mit-license
20959 */
20960
20961 /**
20962 * jsPDF bmp Support PlugIn
20963 * @name bmp_support
20964 * @module
20965 */
20966 (function(jsPDFAPI) {
20967
20968 jsPDFAPI.processBMP = function(imageData, index, alias, compression) {
20969 var reader = new BmpDecoder(imageData, false);
20970 var width = reader.width,
20971 height = reader.height;
20972 var qu = 100;
20973 var pixels = reader.getData();
20974
20975 var rawImageData = {
20976 data: pixels,
20977 width: width,
20978 height: height
20979 };
20980
20981 var encoder = new JPEGEncoder(qu);
20982 var data = encoder.encode(rawImageData, qu);
20983 return jsPDFAPI.processJPEG.call(this, data, index, alias, compression);
20984 };
20985 })(jsPDF.API);
20986
20987 function WebPDecoder(imageData) {
20988
20989 function x(F) {
20990 if (!F) throw Error("assert :P");
20991 }
20992 function fa(F, L, J) {
20993 for (var H = 0; 4 > H; H++) if (F[L + H] != J.charCodeAt(H)) return !0;
20994 return !1;
20995 }
20996 function I(F, L, J, H, Z) {
20997 for (var O = 0; O < Z; O++) F[L + O] = J[H + O];
20998 }
20999 function M(F, L, J, H) {
21000 for (var Z = 0; Z < H; Z++) F[L + Z] = J;
21001 }
21002 function V(F) {
21003 return new Int32Array(F);
21004 }
21005 function wa(F, L) {
21006 for (var J = [], H = 0; H < F; H++) J.push(new L());
21007 return J;
21008 }
21009 function wb() {
21010 function F(J, H, Z) {
21011 for (var O = Z[H], L = 0; L < O; L++) {
21012 J.push(Z.length > H + 1 ? [] : 0);
21013 if (Z.length < H + 1) break;
21014 F(J[L], H + 1, Z);
21015 }
21016 }
21017 var L = [];
21018 F(L, 0, [3, 11]);
21019 return L;
21020 }
21021 function Ed(F, L) {
21022 function J(H, O, F) {
21023 for (var Z = F[O], ma = 0; ma < Z; ma++) {
21024 H.push(F.length > O + 1 ? [] : new L());
21025 if (F.length < O + 1) break;
21026 J(H[ma], O + 1, F);
21027 }
21028 }
21029 var H = [];
21030 J(H, 0, F);
21031 return H;
21032 }
21033 WebPDecoder = function() {
21034 var self = this;
21035 function L(a, b) {
21036 for (var c = (1 << (b - 1)) >>> 0; a & c; ) c >>>= 1;
21037 return c ? (a & (c - 1)) + c : a;
21038 }
21039 function J(a, b, c, d, e) {
21040 x(!(d % c));
21041 do (d -= c), (a[b + d] = e);
21042 while (0 < d);
21043 }
21044 function H(a, b, c, d, e, f) {
21045 var g = b,
21046 h = 1 << c,
21047 k,
21048 l,
21049 m = V(16),
21050 n = V(16);
21051 x(0 != e);
21052 x(null != d);
21053 x(null != a);
21054 x(0 < c);
21055 for (l = 0; l < e; ++l) {
21056 if (15 < d[l]) return 0;
21057 ++m[d[l]];
21058 }
21059 if (m[0] == e) return 0;
21060 n[1] = 0;
21061 for (k = 1; 15 > k; ++k) {
21062 if (m[k] > 1 << k) return 0;
21063 n[k + 1] = n[k] + m[k];
21064 }
21065 for (l = 0; l < e; ++l) (k = d[l]), 0 < d[l] && (f[n[k]++] = l);
21066 if (1 == n[15])
21067 return (d = new O()), (d.g = 0), (d.value = f[0]), J(a, g, 1, h, d), h;
21068 var r = -1,
21069 q = h - 1,
21070 t = 0,
21071 v = 1,
21072 p = 1,
21073 u,
21074 w = 1 << c;
21075 l = 0;
21076 k = 1;
21077 for (e = 2; k <= c; ++k, e <<= 1) {
21078 p <<= 1;
21079 v += p;
21080 p -= m[k];
21081 if (0 > p) return 0;
21082 for (; 0 < m[k]; --m[k])
21083 (d = new O()),
21084 (d.g = k),
21085 (d.value = f[l++]),
21086 J(a, g + t, e, w, d),
21087 (t = L(t, k));
21088 }
21089 k = c + 1;
21090 for (e = 2; 15 >= k; ++k, e <<= 1) {
21091 p <<= 1;
21092 v += p;
21093 p -= m[k];
21094 if (0 > p) return 0;
21095 for (; 0 < m[k]; --m[k]) {
21096 d = new O();
21097 if ((t & q) != r) {
21098 g += w;
21099 r = k;
21100 for (u = 1 << (r - c); 15 > r; ) {
21101 u -= m[r];
21102 if (0 >= u) break;
21103 ++r;
21104 u <<= 1;
21105 }
21106 u = r - c;
21107 w = 1 << u;
21108 h += w;
21109 r = t & q;
21110 a[b + r].g = u + c;
21111 a[b + r].value = g - b - r;
21112 }
21113 d.g = k - c;
21114 d.value = f[l++];
21115 J(a, g + (t >> c), e, w, d);
21116 t = L(t, k);
21117 }
21118 }
21119 return v != 2 * n[15] - 1 ? 0 : h;
21120 }
21121 function Z(a, b, c, d, e) {
21122 x(2328 >= e);
21123 if (512 >= e) var f = V(512);
21124 else if (((f = V(e)), null == f)) return 0;
21125 return H(a, b, c, d, e, f);
21126 }
21127 function O() {
21128 this.value = this.g = 0;
21129 }
21130 function Fd() {
21131 this.value = this.g = 0;
21132 }
21133 function Ub() {
21134 this.G = wa(5, O);
21135 this.H = V(5);
21136 this.jc = this.Qb = this.qb = this.nd = 0;
21137 this.pd = wa(xb, Fd);
21138 }
21139 function ma(a, b, c, d) {
21140 x(null != a);
21141 x(null != b);
21142 x(2147483648 > d);
21143 a.Ca = 254;
21144 a.I = 0;
21145 a.b = -8;
21146 a.Ka = 0;
21147 a.oa = b;
21148 a.pa = c;
21149 a.Jd = b;
21150 a.Yc = c + d;
21151 a.Zc = 4 <= d ? c + d - 4 + 1 : c;
21152 Qa(a);
21153 }
21154 function na(a, b) {
21155 for (var c = 0; 0 < b--; ) c |= K(a, 128) << b;
21156 return c;
21157 }
21158 function ca(a, b) {
21159 var c = na(a, b);
21160 return G(a) ? -c : c;
21161 }
21162 function cb(a, b, c, d) {
21163 var e,
21164 f = 0;
21165 x(null != a);
21166 x(null != b);
21167 x(4294967288 > d);
21168 a.Sb = d;
21169 a.Ra = 0;
21170 a.u = 0;
21171 a.h = 0;
21172 4 < d && (d = 4);
21173 for (e = 0; e < d; ++e) f += b[c + e] << (8 * e);
21174 a.Ra = f;
21175 a.bb = d;
21176 a.oa = b;
21177 a.pa = c;
21178 }
21179 function Vb(a) {
21180 for (; 8 <= a.u && a.bb < a.Sb; )
21181 (a.Ra >>>= 8),
21182 (a.Ra += (a.oa[a.pa + a.bb] << (ob - 8)) >>> 0),
21183 ++a.bb,
21184 (a.u -= 8);
21185 db(a) && ((a.h = 1), (a.u = 0));
21186 }
21187 function D(a, b) {
21188 x(0 <= b);
21189 if (!a.h && b <= Gd) {
21190 var c = pb(a) & Hd[b];
21191 a.u += b;
21192 Vb(a);
21193 return c;
21194 }
21195 a.h = 1;
21196 return (a.u = 0);
21197 }
21198 function Wb() {
21199 this.b = this.Ca = this.I = 0;
21200 this.oa = [];
21201 this.pa = 0;
21202 this.Jd = [];
21203 this.Yc = 0;
21204 this.Zc = [];
21205 this.Ka = 0;
21206 }
21207 function Ra() {
21208 this.Ra = 0;
21209 this.oa = [];
21210 this.h = this.u = this.bb = this.Sb = this.pa = 0;
21211 }
21212 function pb(a) {
21213 return (a.Ra >>> (a.u & (ob - 1))) >>> 0;
21214 }
21215 function db(a) {
21216 x(a.bb <= a.Sb);
21217 return a.h || (a.bb == a.Sb && a.u > ob);
21218 }
21219 function qb(a, b) {
21220 a.u = b;
21221 a.h = db(a);
21222 }
21223 function Sa(a) {
21224 a.u >= Xb && (x(a.u >= Xb), Vb(a));
21225 }
21226 function Qa(a) {
21227 x(null != a && null != a.oa);
21228 a.pa < a.Zc
21229 ? ((a.I = (a.oa[a.pa++] | (a.I << 8)) >>> 0), (a.b += 8))
21230 : (x(null != a && null != a.oa),
21231 a.pa < a.Yc
21232 ? ((a.b += 8), (a.I = a.oa[a.pa++] | (a.I << 8)))
21233 : a.Ka
21234 ? (a.b = 0)
21235 : ((a.I <<= 8), (a.b += 8), (a.Ka = 1)));
21236 }
21237 function G(a) {
21238 return na(a, 1);
21239 }
21240 function K(a, b) {
21241 var c = a.Ca;
21242 0 > a.b && Qa(a);
21243 var d = a.b,
21244 e = (c * b) >>> 8,
21245 f = (a.I >>> d > e) + 0;
21246 f ? ((c -= e), (a.I -= ((e + 1) << d) >>> 0)) : (c = e + 1);
21247 d = c;
21248 for (e = 0; 256 <= d; ) (e += 8), (d >>= 8);
21249 d = 7 ^ (e + Id[d]);
21250 a.b -= d;
21251 a.Ca = (c << d) - 1;
21252 return f;
21253 }
21254 function ra(a, b, c) {
21255 a[b + 0] = (c >> 24) & 255;
21256 a[b + 1] = (c >> 16) & 255;
21257 a[b + 2] = (c >> 8) & 255;
21258 a[b + 3] = (c >> 0) & 255;
21259 }
21260 function Ta(a, b) {
21261 return (a[b + 0] << 0) | (a[b + 1] << 8);
21262 }
21263 function Yb(a, b) {
21264 return Ta(a, b) | (a[b + 2] << 16);
21265 }
21266 function Ha(a, b) {
21267 return Ta(a, b) | (Ta(a, b + 2) << 16);
21268 }
21269 function Zb(a, b) {
21270 var c = 1 << b;
21271 x(null != a);
21272 x(0 < b);
21273 a.X = V(c);
21274 if (null == a.X) return 0;
21275 a.Mb = 32 - b;
21276 a.Xa = b;
21277 return 1;
21278 }
21279 function $b(a, b) {
21280 x(null != a);
21281 x(null != b);
21282 x(a.Xa == b.Xa);
21283 I(b.X, 0, a.X, 0, 1 << b.Xa);
21284 }
21285 function ac() {
21286 this.X = [];
21287 this.Xa = this.Mb = 0;
21288 }
21289 function bc(a, b, c, d) {
21290 x(null != c);
21291 x(null != d);
21292 var e = c[0],
21293 f = d[0];
21294 0 == e && (e = (a * f + b / 2) / b);
21295 0 == f && (f = (b * e + a / 2) / a);
21296 if (0 >= e || 0 >= f) return 0;
21297 c[0] = e;
21298 d[0] = f;
21299 return 1;
21300 }
21301 function xa(a, b) {
21302 return (a + (1 << b) - 1) >>> b;
21303 }
21304 function yb(a, b) {
21305 return (
21306 (((((a & 4278255360) + (b & 4278255360)) >>> 0) & 4278255360) +
21307 ((((a & 16711935) + (b & 16711935)) >>> 0) & 16711935)) >>>
21308 0
21309 );
21310 }
21311 function X(a, b) {
21312 self[b] = function(b, d, e, f, g, h, k) {
21313 var c;
21314 for (c = 0; c < g; ++c) {
21315 var m = self[a](h[k + c - 1], e, f + c);
21316 h[k + c] = yb(b[d + c], m);
21317 }
21318 };
21319 }
21320 function Jd() {
21321 this.ud = this.hd = this.jd = 0;
21322 }
21323 function aa(a, b) {
21324 return ((((a ^ b) & 4278124286) >>> 1) + (a & b)) >>> 0;
21325 }
21326 function sa(a) {
21327 if (0 <= a && 256 > a) return a;
21328 if (0 > a) return 0;
21329 if (255 < a) return 255;
21330 }
21331 function eb(a, b) {
21332 return sa(a + ((a - b + 0.5) >> 1));
21333 }
21334 function Ia(a, b, c) {
21335 return Math.abs(b - c) - Math.abs(a - c);
21336 }
21337 function cc(a, b, c, d, e, f, g) {
21338 d = f[g - 1];
21339 for (c = 0; c < e; ++c) f[g + c] = d = yb(a[b + c], d);
21340 }
21341 function Kd(a, b, c, d, e) {
21342 var f;
21343 for (f = 0; f < c; ++f) {
21344 var g = a[b + f],
21345 h = (g >> 8) & 255,
21346 k = g & 16711935,
21347 k = k + ((h << 16) + h),
21348 k = k & 16711935;
21349 d[e + f] = ((g & 4278255360) + k) >>> 0;
21350 }
21351 }
21352 function dc(a, b) {
21353 b.jd = (a >> 0) & 255;
21354 b.hd = (a >> 8) & 255;
21355 b.ud = (a >> 16) & 255;
21356 }
21357 function Ld(a, b, c, d, e, f) {
21358 var g;
21359 for (g = 0; g < d; ++g) {
21360 var h = b[c + g],
21361 k = h >>> 8,
21362 l = h >>> 16,
21363 m = h,
21364 l = l + ((((a.jd << 24) >> 24) * ((k << 24) >> 24)) >>> 5),
21365 l = l & 255,
21366 m = m + ((((a.hd << 24) >> 24) * ((k << 24) >> 24)) >>> 5),
21367 m = m + ((((a.ud << 24) >> 24) * ((l << 24) >> 24)) >>> 5),
21368 m = m & 255;
21369 e[f + g] = (h & 4278255360) + (l << 16) + m;
21370 }
21371 }
21372 function ec(a, b, c, d, e) {
21373 self[b] = function(a, b, c, k, l, m, n, r, q) {
21374 for (k = n; k < r; ++k)
21375 for (n = 0; n < q; ++n) l[m++] = e(c[d(a[b++])]);
21376 };
21377 self[a] = function(a, b, h, k, l, m, n) {
21378 var f = 8 >> a.b,
21379 g = a.Ea,
21380 t = a.K[0],
21381 v = a.w;
21382 if (8 > f)
21383 for (a = (1 << a.b) - 1, v = (1 << f) - 1; b < h; ++b) {
21384 var p = 0,
21385 u;
21386 for (u = 0; u < g; ++u)
21387 u & a || (p = d(k[l++])), (m[n++] = e(t[p & v])), (p >>= f);
21388 }
21389 else self["VP8LMapColor" + c](k, l, t, v, m, n, b, h, g);
21390 };
21391 }
21392 function Md(a, b, c, d, e) {
21393 for (c = b + c; b < c; ) {
21394 var f = a[b++];
21395 d[e++] = (f >> 16) & 255;
21396 d[e++] = (f >> 8) & 255;
21397 d[e++] = (f >> 0) & 255;
21398 }
21399 }
21400 function Nd(a, b, c, d, e) {
21401 for (c = b + c; b < c; ) {
21402 var f = a[b++];
21403 d[e++] = (f >> 16) & 255;
21404 d[e++] = (f >> 8) & 255;
21405 d[e++] = (f >> 0) & 255;
21406 d[e++] = (f >> 24) & 255;
21407 }
21408 }
21409 function Od(a, b, c, d, e) {
21410 for (c = b + c; b < c; ) {
21411 var f = a[b++],
21412 g = ((f >> 16) & 240) | ((f >> 12) & 15),
21413 f = ((f >> 0) & 240) | ((f >> 28) & 15);
21414 d[e++] = g;
21415 d[e++] = f;
21416 }
21417 }
21418 function Pd(a, b, c, d, e) {
21419 for (c = b + c; b < c; ) {
21420 var f = a[b++],
21421 g = ((f >> 16) & 248) | ((f >> 13) & 7),
21422 f = ((f >> 5) & 224) | ((f >> 3) & 31);
21423 d[e++] = g;
21424 d[e++] = f;
21425 }
21426 }
21427 function Qd(a, b, c, d, e) {
21428 for (c = b + c; b < c; ) {
21429 var f = a[b++];
21430 d[e++] = (f >> 0) & 255;
21431 d[e++] = (f >> 8) & 255;
21432 d[e++] = (f >> 16) & 255;
21433 }
21434 }
21435 function fb(a, b, c, d, e, f) {
21436 if (0 == f)
21437 for (c = b + c; b < c; )
21438 (f = a[b++]),
21439 ra(
21440 d,
21441 ((f[0] >> 24) |
21442 ((f[1] >> 8) & 65280) |
21443 ((f[2] << 8) & 16711680) |
21444 (f[3] << 24)) >>>
21445 0
21446 ),
21447 (e += 32);
21448 else I(d, e, a, b, c);
21449 }
21450 function gb(a, b) {
21451 self[b][0] = self[a + "0"];
21452 self[b][1] = self[a + "1"];
21453 self[b][2] = self[a + "2"];
21454 self[b][3] = self[a + "3"];
21455 self[b][4] = self[a + "4"];
21456 self[b][5] = self[a + "5"];
21457 self[b][6] = self[a + "6"];
21458 self[b][7] = self[a + "7"];
21459 self[b][8] = self[a + "8"];
21460 self[b][9] = self[a + "9"];
21461 self[b][10] = self[a + "10"];
21462 self[b][11] = self[a + "11"];
21463 self[b][12] = self[a + "12"];
21464 self[b][13] = self[a + "13"];
21465 self[b][14] = self[a + "0"];
21466 self[b][15] = self[a + "0"];
21467 }
21468 function hb(a) {
21469 return a == zb || a == Ab || a == Ja || a == Bb;
21470 }
21471 function Rd() {
21472 this.eb = [];
21473 this.size = this.A = this.fb = 0;
21474 }
21475 function Sd() {
21476 this.y = [];
21477 this.f = [];
21478 this.ea = [];
21479 this.F = [];
21480 this.Tc = this.Ed = this.Cd = this.Fd = this.lb = this.Db = this.Ab = this.fa = this.J = this.W = this.N = this.O = 0;
21481 }
21482 function Cb() {
21483 this.Rd = this.height = this.width = this.S = 0;
21484 this.f = {};
21485 this.f.RGBA = new Rd();
21486 this.f.kb = new Sd();
21487 this.sd = null;
21488 }
21489 function Td() {
21490 this.width = [0];
21491 this.height = [0];
21492 this.Pd = [0];
21493 this.Qd = [0];
21494 this.format = [0];
21495 }
21496 function Ud() {
21497 this.Id = this.fd = this.Md = this.hb = this.ib = this.da = this.bd = this.cd = this.j = this.v = this.Da = this.Sd = this.ob = 0;
21498 }
21499 function Vd(a) {
21500 alert("todo:WebPSamplerProcessPlane");
21501 return a.T;
21502 }
21503 function Wd(a, b) {
21504 var c = a.T,
21505 d = b.ba.f.RGBA,
21506 e = d.eb,
21507 f = d.fb + a.ka * d.A,
21508 g = P[b.ba.S],
21509 h = a.y,
21510 k = a.O,
21511 l = a.f,
21512 m = a.N,
21513 n = a.ea,
21514 r = a.W,
21515 q = b.cc,
21516 t = b.dc,
21517 v = b.Mc,
21518 p = b.Nc,
21519 u = a.ka,
21520 w = a.ka + a.T,
21521 y = a.U,
21522 A = (y + 1) >> 1;
21523 0 == u
21524 ? g(h, k, null, null, l, m, n, r, l, m, n, r, e, f, null, null, y)
21525 : (g(b.ec, b.fc, h, k, q, t, v, p, l, m, n, r, e, f - d.A, e, f, y),
21526 ++c);
21527 for (; u + 2 < w; u += 2)
21528 (q = l),
21529 (t = m),
21530 (v = n),
21531 (p = r),
21532 (m += a.Rc),
21533 (r += a.Rc),
21534 (f += 2 * d.A),
21535 (k += 2 * a.fa),
21536 g(h, k - a.fa, h, k, q, t, v, p, l, m, n, r, e, f - d.A, e, f, y);
21537 k += a.fa;
21538 a.j + w < a.o
21539 ? (I(b.ec, b.fc, h, k, y),
21540 I(b.cc, b.dc, l, m, A),
21541 I(b.Mc, b.Nc, n, r, A),
21542 c--)
21543 : w & 1 ||
21544 g(
21545 h,
21546 k,
21547 null,
21548 null,
21549 l,
21550 m,
21551 n,
21552 r,
21553 l,
21554 m,
21555 n,
21556 r,
21557 e,
21558 f + d.A,
21559 null,
21560 null,
21561 y
21562 );
21563 return c;
21564 }
21565 function Xd(a, b, c) {
21566 var d = a.F,
21567 e = [a.J];
21568 if (null != d) {
21569 var f = a.U,
21570 g = b.ba.S,
21571 h = g == ya || g == Ja;
21572 b = b.ba.f.RGBA;
21573 var k = [0],
21574 l = a.ka;
21575 k[0] = a.T;
21576 a.Kb &&
21577 (0 == l ? --k[0] : (--l, (e[0] -= a.width)),
21578 a.j + a.ka + a.T == a.o && (k[0] = a.o - a.j - l));
21579 var m = b.eb,
21580 l = b.fb + l * b.A;
21581 a = fc(d, e[0], a.width, f, k, m, l + (h ? 0 : 3), b.A);
21582 x(c == k);
21583 a && hb(g) && za(m, l, h, f, k, b.A);
21584 }
21585 return 0;
21586 }
21587 function gc(a) {
21588 var b = a.ma,
21589 c = b.ba.S,
21590 d = 11 > c,
21591 e = c == Ua || c == Va || c == ya || c == Db || 12 == c || hb(c);
21592 b.memory = null;
21593 b.Ib = null;
21594 b.Jb = null;
21595 b.Nd = null;
21596 if (!hc(b.Oa, a, e ? 11 : 12)) return 0;
21597 e && hb(c) && ic();
21598 if (a.da) alert("todo:use_scaling");
21599 else {
21600 if (d) {
21601 if (((b.Ib = Vd), a.Kb)) {
21602 c = (a.U + 1) >> 1;
21603 b.memory = V(a.U + 2 * c);
21604 if (null == b.memory) return 0;
21605 b.ec = b.memory;
21606 b.fc = 0;
21607 b.cc = b.ec;
21608 b.dc = b.fc + a.U;
21609 b.Mc = b.cc;
21610 b.Nc = b.dc + c;
21611 b.Ib = Wd;
21612 ic();
21613 }
21614 } else alert("todo:EmitYUV");
21615 e && ((b.Jb = Xd), d && Aa());
21616 }
21617 if (d && !jc) {
21618 for (a = 0; 256 > a; ++a)
21619 (Yd[a] = (89858 * (a - 128) + Ba) >> Wa),
21620 (Zd[a] = -22014 * (a - 128) + Ba),
21621 ($d[a] = -45773 * (a - 128)),
21622 (ae[a] = (113618 * (a - 128) + Ba) >> Wa);
21623 for (a = ta; a < Eb; ++a)
21624 (b = (76283 * (a - 16) + Ba) >> Wa),
21625 (be[a - ta] = ga(b, 255)),
21626 (ce[a - ta] = ga((b + 8) >> 4, 15));
21627 jc = 1;
21628 }
21629 return 1;
21630 }
21631 function kc(a) {
21632 var b = a.ma,
21633 c = a.U,
21634 d = a.T;
21635 x(!(a.ka & 1));
21636 if (0 >= c || 0 >= d) return 0;
21637 c = b.Ib(a, b);
21638 null != b.Jb && b.Jb(a, b, c);
21639 b.Dc += c;
21640 return 1;
21641 }
21642 function lc(a) {
21643 a.ma.memory = null;
21644 }
21645 function mc(a, b, c, d) {
21646 if (47 != D(a, 8)) return 0;
21647 b[0] = D(a, 14) + 1;
21648 c[0] = D(a, 14) + 1;
21649 d[0] = D(a, 1);
21650 return 0 != D(a, 3) ? 0 : !a.h;
21651 }
21652 function ib(a, b) {
21653 if (4 > a) return a + 1;
21654 var c = (a - 2) >> 1;
21655 return ((2 + (a & 1)) << c) + D(b, c) + 1;
21656 }
21657 function nc(a, b) {
21658 if (120 < b) return b - 120;
21659 var c = de[b - 1],
21660 c = (c >> 4) * a + (8 - (c & 15));
21661 return 1 <= c ? c : 1;
21662 }
21663 function ua(a, b, c) {
21664 var d = pb(c);
21665 b += d & 255;
21666 var e = a[b].g - 8;
21667 0 < e &&
21668 (qb(c, c.u + 8),
21669 (d = pb(c)),
21670 (b += a[b].value),
21671 (b += d & ((1 << e) - 1)));
21672 qb(c, c.u + a[b].g);
21673 return a[b].value;
21674 }
21675 function ub(a, b, c) {
21676 c.g += a.g;
21677 c.value += (a.value << b) >>> 0;
21678 x(8 >= c.g);
21679 return a.g;
21680 }
21681 function ha(a, b, c) {
21682 var d = a.xc;
21683 b = 0 == d ? 0 : a.vc[a.md * (c >> d) + (b >> d)];
21684 x(b < a.Wb);
21685 return a.Ya[b];
21686 }
21687 function oc(a, b, c, d) {
21688 var e = a.ab,
21689 f = a.c * b,
21690 g = a.C;
21691 b = g + b;
21692 var h = c,
21693 k = d;
21694 d = a.Ta;
21695 for (c = a.Ua; 0 < e--; ) {
21696 var l = a.gc[e],
21697 m = g,
21698 n = b,
21699 r = h,
21700 q = k,
21701 k = d,
21702 h = c,
21703 t = l.Ea;
21704 x(m < n);
21705 x(n <= l.nc);
21706 switch (l.hc) {
21707 case 2:
21708 pc(r, q, (n - m) * t, k, h);
21709 break;
21710 case 0:
21711 var v = l,
21712 p = m,
21713 u = n,
21714 w = k,
21715 y = h,
21716 A = v.Ea;
21717 0 == p &&
21718 (ee(r, q, null, null, 1, w, y),
21719 cc(r, q + 1, 0, 0, A - 1, w, y + 1),
21720 (q += A),
21721 (y += A),
21722 ++p);
21723 for (
21724 var E = 1 << v.b,
21725 B = E - 1,
21726 C = xa(A, v.b),
21727 N = v.K,
21728 v = v.w + (p >> v.b) * C;
21729 p < u;
21730
21731 ) {
21732 var z = N,
21733 Q = v,
21734 S = 1;
21735 for (fe(r, q, w, y - A, 1, w, y); S < A; ) {
21736 var K = qc[(z[Q++] >> 8) & 15],
21737 D = (S & ~B) + E;
21738 D > A && (D = A);
21739 K(r, q + +S, w, y + S - A, D - S, w, y + S);
21740 S = D;
21741 }
21742 q += A;
21743 y += A;
21744 ++p;
21745 p & B || (v += C);
21746 }
21747 n != l.nc && I(k, h - t, k, h + (n - m - 1) * t, t);
21748 break;
21749 case 1:
21750 t = r;
21751 u = q;
21752 r = l.Ea;
21753 q = 1 << l.b;
21754 w = q - 1;
21755 y = r & ~w;
21756 A = r - y;
21757 p = xa(r, l.b);
21758 E = l.K;
21759 for (l = l.w + (m >> l.b) * p; m < n; ) {
21760 B = E;
21761 C = l;
21762 N = new Jd();
21763 v = u + y;
21764 for (z = u + r; u < v; )
21765 dc(B[C++], N), Fb(N, t, u, q, k, h), (u += q), (h += q);
21766 u < z &&
21767 (dc(B[C++], N), Fb(N, t, u, A, k, h), (u += A), (h += A));
21768 ++m;
21769 m & w || (l += p);
21770 }
21771 break;
21772 case 3:
21773 if (r == k && q == h && 0 < l.b) {
21774 y = (n - m) * xa(l.Ea, l.b);
21775 t = h + (n - m) * t - y;
21776 u = k;
21777 r = t;
21778 q = k;
21779 w = h;
21780 A = y;
21781 p = [];
21782 for (y = A - 1; 0 <= y; --y) p[y] = q[w + y];
21783 for (y = A - 1; 0 <= y; --y) u[r + y] = p[y];
21784 rc(l, m, n, k, t, k, h);
21785 } else rc(l, m, n, r, q, k, h);
21786 }
21787 h = d;
21788 k = c;
21789 }
21790 k != c && I(d, c, h, k, f);
21791 }
21792 function ge(a, b) {
21793 var c = a.V,
21794 d = a.Ba + a.c * a.C,
21795 e = b - a.C;
21796 x(b <= a.l.o);
21797 x(16 >= e);
21798 if (0 < e) {
21799 var f = a.l,
21800 g = a.Ta,
21801 h = a.Ua,
21802 k = f.width;
21803 oc(a, e, c, d);
21804 h = [h];
21805 c = a.C;
21806 d = b;
21807 e = h;
21808 x(c < d);
21809 x(f.v < f.va);
21810 d > f.o && (d = f.o);
21811 if (c < f.j) {
21812 var l = f.j - c,
21813 c = f.j;
21814 e[0] += l * k;
21815 }
21816 c >= d
21817 ? (c = 0)
21818 : ((e[0] += 4 * f.v),
21819 (f.ka = c - f.j),
21820 (f.U = f.va - f.v),
21821 (f.T = d - c),
21822 (c = 1));
21823 if (c) {
21824 h = h[0];
21825 c = a.ca;
21826 if (11 > c.S) {
21827 for (
21828 var m = c.f.RGBA,
21829 d = c.S,
21830 e = f.U,
21831 f = f.T,
21832 l = m.eb,
21833 n = m.A,
21834 r = f,
21835 m = m.fb + a.Ma * m.A;
21836 0 < r--;
21837
21838 ) {
21839 var q = g,
21840 t = h,
21841 v = e,
21842 p = l,
21843 u = m;
21844 switch (d) {
21845 case Ca:
21846 sc(q, t, v, p, u);
21847 break;
21848 case Ua:
21849 Gb(q, t, v, p, u);
21850 break;
21851 case zb:
21852 Gb(q, t, v, p, u);
21853 za(p, u, 0, v, 1, 0);
21854 break;
21855 case tc:
21856 uc(q, t, v, p, u);
21857 break;
21858 case Va:
21859 fb(q, t, v, p, u, 1);
21860 break;
21861 case Ab:
21862 fb(q, t, v, p, u, 1);
21863 za(p, u, 0, v, 1, 0);
21864 break;
21865 case ya:
21866 fb(q, t, v, p, u, 0);
21867 break;
21868 case Ja:
21869 fb(q, t, v, p, u, 0);
21870 za(p, u, 1, v, 1, 0);
21871 break;
21872 case Db:
21873 Hb(q, t, v, p, u);
21874 break;
21875 case Bb:
21876 Hb(q, t, v, p, u);
21877 vc(p, u, v, 1, 0);
21878 break;
21879 case wc:
21880 xc(q, t, v, p, u);
21881 break;
21882 default:
21883 x(0);
21884 }
21885 h += k;
21886 m += n;
21887 }
21888 a.Ma += f;
21889 } else alert("todo:EmitRescaledRowsYUVA");
21890 x(a.Ma <= c.height);
21891 }
21892 }
21893 a.C = b;
21894 x(a.C <= a.i);
21895 }
21896 function yc(a) {
21897 var b;
21898 if (0 < a.ua) return 0;
21899 for (b = 0; b < a.Wb; ++b) {
21900 var c = a.Ya[b].G,
21901 d = a.Ya[b].H;
21902 if (
21903 0 < c[1][d[1] + 0].g ||
21904 0 < c[2][d[2] + 0].g ||
21905 0 < c[3][d[3] + 0].g
21906 )
21907 return 0;
21908 }
21909 return 1;
21910 }
21911 function zc(a, b, c, d, e, f) {
21912 if (0 != a.Z) {
21913 var g = a.qd,
21914 h = a.rd;
21915 for (x(null != ia[a.Z]); b < c; ++b)
21916 ia[a.Z](g, h, d, e, d, e, f), (g = d), (h = e), (e += f);
21917 a.qd = g;
21918 a.rd = h;
21919 }
21920 }
21921 function Ib(a, b) {
21922 var c = a.l.ma,
21923 d = 0 == c.Z || 1 == c.Z ? a.l.j : a.C,
21924 d = a.C < d ? d : a.C;
21925 x(b <= a.l.o);
21926 if (b > d) {
21927 var e = a.l.width,
21928 f = c.ca,
21929 g = c.tb + e * d,
21930 h = a.V,
21931 k = a.Ba + a.c * d,
21932 l = a.gc;
21933 x(1 == a.ab);
21934 x(3 == l[0].hc);
21935 he(l[0], d, b, h, k, f, g);
21936 zc(c, d, b, f, g, e);
21937 }
21938 a.C = a.Ma = b;
21939 }
21940 function Jb(a, b, c, d, e, f, g) {
21941 var h = a.$ / d,
21942 k = a.$ % d,
21943 l = a.m,
21944 m = a.s,
21945 n = c + a.$,
21946 r = n;
21947 e = c + d * e;
21948 var q = c + d * f,
21949 t = 280 + m.ua,
21950 v = a.Pb ? h : 16777216,
21951 p = 0 < m.ua ? m.Wa : null,
21952 u = m.wc,
21953 w = n < q ? ha(m, k, h) : null;
21954 x(a.C < f);
21955 x(q <= e);
21956 var y = !1;
21957 a: for (;;) {
21958 for (; y || n < q; ) {
21959 var A = 0;
21960 if (h >= v) {
21961 var v = a,
21962 E = n - c;
21963 x(v.Pb);
21964 v.wd = v.m;
21965 v.xd = E;
21966 0 < v.s.ua && $b(v.s.Wa, v.s.vb);
21967 v = h + ie;
21968 }
21969 k & u || (w = ha(m, k, h));
21970 x(null != w);
21971 w.Qb && ((b[n] = w.qb), (y = !0));
21972 if (!y)
21973 if ((Sa(l), w.jc)) {
21974 var A = l,
21975 E = b,
21976 B = n,
21977 C = w.pd[pb(A) & (xb - 1)];
21978 x(w.jc);
21979 256 > C.g
21980 ? (qb(A, A.u + C.g), (E[B] = C.value), (A = 0))
21981 : (qb(A, A.u + C.g - 256), x(256 <= C.value), (A = C.value));
21982 0 == A && (y = !0);
21983 } else A = ua(w.G[0], w.H[0], l);
21984 if (l.h) break;
21985 if (y || 256 > A) {
21986 if (!y)
21987 if (w.nd) b[n] = (w.qb | (A << 8)) >>> 0;
21988 else {
21989 Sa(l);
21990 y = ua(w.G[1], w.H[1], l);
21991 Sa(l);
21992 E = ua(w.G[2], w.H[2], l);
21993 B = ua(w.G[3], w.H[3], l);
21994 if (l.h) break;
21995 b[n] = ((B << 24) | (y << 16) | (A << 8) | E) >>> 0;
21996 }
21997 y = !1;
21998 ++n;
21999 ++k;
22000 if (
22001 k >= d &&
22002 ((k = 0),
22003 ++h,
22004 null != g && h <= f && !(h % 16) && g(a, h),
22005 null != p)
22006 )
22007 for (; r < n; )
22008 (A = b[r++]),
22009 (p.X[((506832829 * A) & 4294967295) >>> p.Mb] = A);
22010 } else if (280 > A) {
22011 A = ib(A - 256, l);
22012 E = ua(w.G[4], w.H[4], l);
22013 Sa(l);
22014 E = ib(E, l);
22015 E = nc(d, E);
22016 if (l.h) break;
22017 if (n - c < E || e - n < A) break a;
22018 else for (B = 0; B < A; ++B) b[n + B] = b[n + B - E];
22019 n += A;
22020 for (k += A; k >= d; )
22021 (k -= d), ++h, null != g && h <= f && !(h % 16) && g(a, h);
22022 x(n <= e);
22023 k & u && (w = ha(m, k, h));
22024 if (null != p)
22025 for (; r < n; )
22026 (A = b[r++]),
22027 (p.X[((506832829 * A) & 4294967295) >>> p.Mb] = A);
22028 } else if (A < t) {
22029 y = A - 280;
22030 for (x(null != p); r < n; )
22031 (A = b[r++]), (p.X[((506832829 * A) & 4294967295) >>> p.Mb] = A);
22032 A = n;
22033 E = p;
22034 x(!(y >>> E.Xa));
22035 b[A] = E.X[y];
22036 y = !0;
22037 } else break a;
22038 y || x(l.h == db(l));
22039 }
22040 if (a.Pb && l.h && n < e)
22041 x(a.m.h),
22042 (a.a = 5),
22043 (a.m = a.wd),
22044 (a.$ = a.xd),
22045 0 < a.s.ua && $b(a.s.vb, a.s.Wa);
22046 else if (l.h) break a;
22047 else null != g && g(a, h > f ? f : h), (a.a = 0), (a.$ = n - c);
22048 return 1;
22049 }
22050 a.a = 3;
22051 return 0;
22052 }
22053 function Ac(a) {
22054 x(null != a);
22055 a.vc = null;
22056 a.yc = null;
22057 a.Ya = null;
22058 var b = a.Wa;
22059 null != b && (b.X = null);
22060 a.vb = null;
22061 x(null != a);
22062 }
22063 function Bc() {
22064 var a = new je();
22065 if (null == a) return null;
22066 a.a = 0;
22067 a.xb = Cc;
22068 gb("Predictor", "VP8LPredictors");
22069 gb("Predictor", "VP8LPredictors_C");
22070 gb("PredictorAdd", "VP8LPredictorsAdd");
22071 gb("PredictorAdd", "VP8LPredictorsAdd_C");
22072 pc = Kd;
22073 Fb = Ld;
22074 sc = Md;
22075 Gb = Nd;
22076 Hb = Od;
22077 xc = Pd;
22078 uc = Qd;
22079 self.VP8LMapColor32b = ke;
22080 self.VP8LMapColor8b = le;
22081 return a;
22082 }
22083 function rb(a, b, c, d, e) {
22084 var f = 1,
22085 g = [a],
22086 h = [b],
22087 k = d.m,
22088 l = d.s,
22089 m = null,
22090 n = 0;
22091 a: for (;;) {
22092 if (c)
22093 for (; f && D(k, 1); ) {
22094 var r = g,
22095 q = h,
22096 t = d,
22097 v = 1,
22098 p = t.m,
22099 u = t.gc[t.ab],
22100 w = D(p, 2);
22101 if (t.Oc & (1 << w)) f = 0;
22102 else {
22103 t.Oc |= 1 << w;
22104 u.hc = w;
22105 u.Ea = r[0];
22106 u.nc = q[0];
22107 u.K = [null];
22108 ++t.ab;
22109 x(4 >= t.ab);
22110 switch (w) {
22111 case 0:
22112 case 1:
22113 u.b = D(p, 3) + 2;
22114 v = rb(xa(u.Ea, u.b), xa(u.nc, u.b), 0, t, u.K);
22115 u.K = u.K[0];
22116 break;
22117 case 3:
22118 var y = D(p, 8) + 1,
22119 A = 16 < y ? 0 : 4 < y ? 1 : 2 < y ? 2 : 3;
22120 r[0] = xa(u.Ea, A);
22121 u.b = A;
22122 var v = rb(y, 1, 0, t, u.K),
22123 E;
22124 if ((E = v)) {
22125 var B,
22126 C = y,
22127 N = u,
22128 z = 1 << (8 >> N.b),
22129 Q = V(z);
22130 if (null == Q) E = 0;
22131 else {
22132 var S = N.K[0],
22133 K = N.w;
22134 Q[0] = N.K[0][0];
22135 for (B = 1; B < 1 * C; ++B) Q[B] = yb(S[K + B], Q[B - 1]);
22136 for (; B < 4 * z; ++B) Q[B] = 0;
22137 N.K[0] = null;
22138 N.K[0] = Q;
22139 E = 1;
22140 }
22141 }
22142 v = E;
22143 break;
22144 case 2:
22145 break;
22146 default:
22147 x(0);
22148 }
22149 f = v;
22150 }
22151 }
22152 g = g[0];
22153 h = h[0];
22154 if (f && D(k, 1) && ((n = D(k, 4)), (f = 1 <= n && 11 >= n), !f)) {
22155 d.a = 3;
22156 break a;
22157 }
22158 var H;
22159 if ((H = f))
22160 b: {
22161 var F = d,
22162 G = g,
22163 L = h,
22164 J = n,
22165 T = c,
22166 Da,
22167 ba,
22168 X = F.m,
22169 R = F.s,
22170 P = [null],
22171 U,
22172 W = 1,
22173 aa = 0,
22174 na = me[J];
22175 c: for (;;) {
22176 if (T && D(X, 1)) {
22177 var ca = D(X, 3) + 2,
22178 ga = xa(G, ca),
22179 ka = xa(L, ca),
22180 qa = ga * ka;
22181 if (!rb(ga, ka, 0, F, P)) break c;
22182 P = P[0];
22183 R.xc = ca;
22184 for (Da = 0; Da < qa; ++Da) {
22185 var ia = (P[Da] >> 8) & 65535;
22186 P[Da] = ia;
22187 ia >= W && (W = ia + 1);
22188 }
22189 }
22190 if (X.h) break c;
22191 for (ba = 0; 5 > ba; ++ba) {
22192 var Y = Dc[ba];
22193 !ba && 0 < J && (Y += 1 << J);
22194 aa < Y && (aa = Y);
22195 }
22196 var ma = wa(W * na, O);
22197 var ua = W,
22198 va = wa(ua, Ub);
22199 if (null == va) var la = null;
22200 else x(65536 >= ua), (la = va);
22201 var ha = V(aa);
22202 if (null == la || null == ha || null == ma) {
22203 F.a = 1;
22204 break c;
22205 }
22206 var pa = ma;
22207 for (Da = U = 0; Da < W; ++Da) {
22208 var ja = la[Da],
22209 da = ja.G,
22210 ea = ja.H,
22211 Fa = 0,
22212 ra = 1,
22213 Ha = 0;
22214 for (ba = 0; 5 > ba; ++ba) {
22215 Y = Dc[ba];
22216 da[ba] = pa;
22217 ea[ba] = U;
22218 !ba && 0 < J && (Y += 1 << J);
22219 d: {
22220 var sa,
22221 za = Y,
22222 ta = F,
22223 oa = ha,
22224 db = pa,
22225 eb = U,
22226 Ia = 0,
22227 Ka = ta.m,
22228 fb = D(Ka, 1);
22229 M(oa, 0, 0, za);
22230 if (fb) {
22231 var gb = D(Ka, 1) + 1,
22232 hb = D(Ka, 1),
22233 Ja = D(Ka, 0 == hb ? 1 : 8);
22234 oa[Ja] = 1;
22235 2 == gb && ((Ja = D(Ka, 8)), (oa[Ja] = 1));
22236 var ya = 1;
22237 } else {
22238 var Ua = V(19),
22239 Va = D(Ka, 4) + 4;
22240 if (19 < Va) {
22241 ta.a = 3;
22242 var Aa = 0;
22243 break d;
22244 }
22245 for (sa = 0; sa < Va; ++sa) Ua[ne[sa]] = D(Ka, 3);
22246 var Ba = void 0,
22247 sb = void 0,
22248 Wa = ta,
22249 ib = Ua,
22250 Ca = za,
22251 Xa = oa,
22252 Oa = 0,
22253 La = Wa.m,
22254 Ya = 8,
22255 Za = wa(128, O);
22256 e: for (;;) {
22257 if (!Z(Za, 0, 7, ib, 19)) break e;
22258 if (D(La, 1)) {
22259 var kb = 2 + 2 * D(La, 3),
22260 Ba = 2 + D(La, kb);
22261 if (Ba > Ca) break e;
22262 } else Ba = Ca;
22263 for (sb = 0; sb < Ca && Ba--; ) {
22264 Sa(La);
22265 var $a = Za[0 + (pb(La) & 127)];
22266 qb(La, La.u + $a.g);
22267 var jb = $a.value;
22268 if (16 > jb) (Xa[sb++] = jb), 0 != jb && (Ya = jb);
22269 else {
22270 var lb = 16 == jb,
22271 ab = jb - 16,
22272 mb = oe[ab],
22273 bb = D(La, pe[ab]) + mb;
22274 if (sb + bb > Ca) break e;
22275 else
22276 for (var nb = lb ? Ya : 0; 0 < bb--; )
22277 Xa[sb++] = nb;
22278 }
22279 }
22280 Oa = 1;
22281 break e;
22282 }
22283 Oa || (Wa.a = 3);
22284 ya = Oa;
22285 }
22286 (ya = ya && !Ka.h) && (Ia = Z(db, eb, 8, oa, za));
22287 ya && 0 != Ia ? (Aa = Ia) : ((ta.a = 3), (Aa = 0));
22288 }
22289 if (0 == Aa) break c;
22290 ra && 1 == qe[ba] && (ra = 0 == pa[U].g);
22291 Fa += pa[U].g;
22292 U += Aa;
22293 if (3 >= ba) {
22294 var Pa = ha[0],
22295 tb;
22296 for (tb = 1; tb < Y; ++tb) ha[tb] > Pa && (Pa = ha[tb]);
22297 Ha += Pa;
22298 }
22299 }
22300 ja.nd = ra;
22301 ja.Qb = 0;
22302 ra &&
22303 ((ja.qb =
22304 ((da[3][ea[3] + 0].value << 24) |
22305 (da[1][ea[1] + 0].value << 16) |
22306 da[2][ea[2] + 0].value) >>>
22307 0),
22308 0 == Fa &&
22309 256 > da[0][ea[0] + 0].value &&
22310 ((ja.Qb = 1), (ja.qb += da[0][ea[0] + 0].value << 8)));
22311 ja.jc = !ja.Qb && 6 > Ha;
22312 if (ja.jc) {
22313 var Ga,
22314 Ea = ja;
22315 for (Ga = 0; Ga < xb; ++Ga) {
22316 var Ma = Ga,
22317 Na = Ea.pd[Ma],
22318 vb = Ea.G[0][Ea.H[0] + Ma];
22319 256 <= vb.value
22320 ? ((Na.g = vb.g + 256), (Na.value = vb.value))
22321 : ((Na.g = 0),
22322 (Na.value = 0),
22323 (Ma >>= ub(vb, 8, Na)),
22324 (Ma >>= ub(Ea.G[1][Ea.H[1] + Ma], 16, Na)),
22325 (Ma >>= ub(Ea.G[2][Ea.H[2] + Ma], 0, Na)),
22326 ub(Ea.G[3][Ea.H[3] + Ma], 24, Na));
22327 }
22328 }
22329 }
22330 R.vc = P;
22331 R.Wb = W;
22332 R.Ya = la;
22333 R.yc = ma;
22334 H = 1;
22335 break b;
22336 }
22337 H = 0;
22338 }
22339 f = H;
22340 if (!f) {
22341 d.a = 3;
22342 break a;
22343 }
22344 if (0 < n) {
22345 if (((l.ua = 1 << n), !Zb(l.Wa, n))) {
22346 d.a = 1;
22347 f = 0;
22348 break a;
22349 }
22350 } else l.ua = 0;
22351 var Qa = d,
22352 cb = g,
22353 ob = h,
22354 Ra = Qa.s,
22355 Ta = Ra.xc;
22356 Qa.c = cb;
22357 Qa.i = ob;
22358 Ra.md = xa(cb, Ta);
22359 Ra.wc = 0 == Ta ? -1 : (1 << Ta) - 1;
22360 if (c) {
22361 d.xb = re;
22362 break a;
22363 }
22364 m = V(g * h);
22365 if (null == m) {
22366 d.a = 1;
22367 f = 0;
22368 break a;
22369 }
22370 f = (f = Jb(d, m, 0, g, h, h, null)) && !k.h;
22371 break a;
22372 }
22373 f
22374 ? (null != e ? (e[0] = m) : (x(null == m), x(c)), (d.$ = 0), c || Ac(l))
22375 : Ac(l);
22376 return f;
22377 }
22378 function Ec(a, b) {
22379 var c = a.c * a.i,
22380 d = c + b + 16 * b;
22381 x(a.c <= b);
22382 a.V = V(d);
22383 if (null == a.V) return (a.Ta = null), (a.Ua = 0), (a.a = 1), 0;
22384 a.Ta = a.V;
22385 a.Ua = a.Ba + c + b;
22386 return 1;
22387 }
22388 function se(a, b) {
22389 var c = a.C,
22390 d = b - c,
22391 e = a.V,
22392 f = a.Ba + a.c * c;
22393 for (x(b <= a.l.o); 0 < d; ) {
22394 var g = 16 < d ? 16 : d,
22395 h = a.l.ma,
22396 k = a.l.width,
22397 l = k * g,
22398 m = h.ca,
22399 n = h.tb + k * c,
22400 r = a.Ta,
22401 q = a.Ua;
22402 oc(a, g, e, f);
22403 Fc(r, q, m, n, l);
22404 zc(h, c, c + g, m, n, k);
22405 d -= g;
22406 e += g * a.c;
22407 c += g;
22408 }
22409 x(c == b);
22410 a.C = a.Ma = b;
22411 }
22412 function te(a, b) {
22413 var c = [0],
22414 d = [0],
22415 e = [0];
22416 a: for (;;) {
22417 if (null == a) return 0;
22418 if (null == b) return (a.a = 2), 0;
22419 a.l = b;
22420 a.a = 0;
22421 cb(a.m, b.data, b.w, b.ha);
22422 if (!mc(a.m, c, d, e)) {
22423 a.a = 3;
22424 break a;
22425 }
22426 a.xb = Cc;
22427 b.width = c[0];
22428 b.height = d[0];
22429 if (!rb(c[0], d[0], 1, a, null)) break a;
22430 return 1;
22431 }
22432 x(0 != a.a);
22433 return 0;
22434 }
22435 function ue() {
22436 this.ub = this.yd = this.td = this.Rb = 0;
22437 }
22438 function ve() {
22439 this.Kd = this.Ld = this.Ud = this.Td = this.i = this.c = 0;
22440 }
22441 function we() {
22442 this.Fb = this.Bb = this.Cb = 0;
22443 this.Zb = V(4);
22444 this.Lb = V(4);
22445 }
22446 function Gc() {
22447 this.Yb = wb();
22448 }
22449 function xe() {
22450 this.jb = V(3);
22451 this.Wc = Ed([4, 8], Gc);
22452 this.Xc = Ed([4, 17], Gc);
22453 }
22454 function ye() {
22455 this.Pc = this.wb = this.Tb = this.zd = 0;
22456 this.vd = new V(4);
22457 this.od = new V(4);
22458 }
22459 function Xa() {
22460 this.ld = this.La = this.dd = this.tc = 0;
22461 }
22462 function Hc() {
22463 this.Na = this.la = 0;
22464 }
22465 function ze() {
22466 this.Sc = [0, 0];
22467 this.Eb = [0, 0];
22468 this.Qc = [0, 0];
22469 this.ia = this.lc = 0;
22470 }
22471 function Kb() {
22472 this.ad = V(384);
22473 this.Za = 0;
22474 this.Ob = V(16);
22475 this.$b = this.Ad = this.ia = this.Gc = this.Hc = this.Dd = 0;
22476 }
22477 function Ae() {
22478 this.uc = this.M = this.Nb = 0;
22479 this.wa = Array(new Xa());
22480 this.Y = 0;
22481 this.ya = Array(new Kb());
22482 this.aa = 0;
22483 this.l = new Oa();
22484 }
22485 function Ic() {
22486 this.y = V(16);
22487 this.f = V(8);
22488 this.ea = V(8);
22489 }
22490 function Be() {
22491 this.cb = this.a = 0;
22492 this.sc = "";
22493 this.m = new Wb();
22494 this.Od = new ue();
22495 this.Kc = new ve();
22496 this.ed = new ye();
22497 this.Qa = new we();
22498 this.Ic = this.$c = this.Aa = 0;
22499 this.D = new Ae();
22500 this.Xb = this.Va = this.Hb = this.zb = this.yb = this.Ub = this.za = 0;
22501 this.Jc = wa(8, Wb);
22502 this.ia = 0;
22503 this.pb = wa(4, ze);
22504 this.Pa = new xe();
22505 this.Bd = this.kc = 0;
22506 this.Ac = [];
22507 this.Bc = 0;
22508 this.zc = [0, 0, 0, 0];
22509 this.Gd = Array(new Ic());
22510 this.Hd = 0;
22511 this.rb = Array(new Hc());
22512 this.sb = 0;
22513 this.wa = Array(new Xa());
22514 this.Y = 0;
22515 this.oc = [];
22516 this.pc = 0;
22517 this.sa = [];
22518 this.ta = 0;
22519 this.qa = [];
22520 this.ra = 0;
22521 this.Ha = [];
22522 this.B = this.R = this.Ia = 0;
22523 this.Ec = [];
22524 this.M = this.ja = this.Vb = this.Fc = 0;
22525 this.ya = Array(new Kb());
22526 this.L = this.aa = 0;
22527 this.gd = Ed([4, 2], Xa);
22528 this.ga = null;
22529 this.Fa = [];
22530 this.Cc = this.qc = this.P = 0;
22531 this.Gb = [];
22532 this.Uc = 0;
22533 this.mb = [];
22534 this.nb = 0;
22535 this.rc = [];
22536 this.Ga = this.Vc = 0;
22537 }
22538 function ga(a, b) {
22539 return 0 > a ? 0 : a > b ? b : a;
22540 }
22541 function Oa() {
22542 this.T = this.U = this.ka = this.height = this.width = 0;
22543 this.y = [];
22544 this.f = [];
22545 this.ea = [];
22546 this.Rc = this.fa = this.W = this.N = this.O = 0;
22547 this.ma = "void";
22548 this.put = "VP8IoPutHook";
22549 this.ac = "VP8IoSetupHook";
22550 this.bc = "VP8IoTeardownHook";
22551 this.ha = this.Kb = 0;
22552 this.data = [];
22553 this.hb = this.ib = this.da = this.o = this.j = this.va = this.v = this.Da = this.ob = this.w = 0;
22554 this.F = [];
22555 this.J = 0;
22556 }
22557 function Ce() {
22558 var a = new Be();
22559 null != a &&
22560 ((a.a = 0), (a.sc = "OK"), (a.cb = 0), (a.Xb = 0), oa || (oa = De));
22561 return a;
22562 }
22563 function T(a, b, c) {
22564 0 == a.a && ((a.a = b), (a.sc = c), (a.cb = 0));
22565 return 0;
22566 }
22567 function Jc(a, b, c) {
22568 return 3 <= c && 157 == a[b + 0] && 1 == a[b + 1] && 42 == a[b + 2];
22569 }
22570 function Kc(a, b) {
22571 if (null == a) return 0;
22572 a.a = 0;
22573 a.sc = "OK";
22574 if (null == b) return T(a, 2, "null VP8Io passed to VP8GetHeaders()");
22575 var c = b.data;
22576 var d = b.w;
22577 var e = b.ha;
22578 if (4 > e) return T(a, 7, "Truncated header.");
22579 var f = c[d + 0] | (c[d + 1] << 8) | (c[d + 2] << 16);
22580 var g = a.Od;
22581 g.Rb = !(f & 1);
22582 g.td = (f >> 1) & 7;
22583 g.yd = (f >> 4) & 1;
22584 g.ub = f >> 5;
22585 if (3 < g.td) return T(a, 3, "Incorrect keyframe parameters.");
22586 if (!g.yd) return T(a, 4, "Frame not displayable.");
22587 d += 3;
22588 e -= 3;
22589 var h = a.Kc;
22590 if (g.Rb) {
22591 if (7 > e) return T(a, 7, "cannot parse picture header");
22592 if (!Jc(c, d, e)) return T(a, 3, "Bad code word");
22593 h.c = ((c[d + 4] << 8) | c[d + 3]) & 16383;
22594 h.Td = c[d + 4] >> 6;
22595 h.i = ((c[d + 6] << 8) | c[d + 5]) & 16383;
22596 h.Ud = c[d + 6] >> 6;
22597 d += 7;
22598 e -= 7;
22599 a.za = (h.c + 15) >> 4;
22600 a.Ub = (h.i + 15) >> 4;
22601 b.width = h.c;
22602 b.height = h.i;
22603 b.Da = 0;
22604 b.j = 0;
22605 b.v = 0;
22606 b.va = b.width;
22607 b.o = b.height;
22608 b.da = 0;
22609 b.ib = b.width;
22610 b.hb = b.height;
22611 b.U = b.width;
22612 b.T = b.height;
22613 f = a.Pa;
22614 M(f.jb, 0, 255, f.jb.length);
22615 f = a.Qa;
22616 x(null != f);
22617 f.Cb = 0;
22618 f.Bb = 0;
22619 f.Fb = 1;
22620 M(f.Zb, 0, 0, f.Zb.length);
22621 M(f.Lb, 0, 0, f.Lb);
22622 }
22623 if (g.ub > e) return T(a, 7, "bad partition length");
22624 f = a.m;
22625 ma(f, c, d, g.ub);
22626 d += g.ub;
22627 e -= g.ub;
22628 g.Rb && ((h.Ld = G(f)), (h.Kd = G(f)));
22629 h = a.Qa;
22630 var k = a.Pa,
22631 l;
22632 x(null != f);
22633 x(null != h);
22634 h.Cb = G(f);
22635 if (h.Cb) {
22636 h.Bb = G(f);
22637 if (G(f)) {
22638 h.Fb = G(f);
22639 for (l = 0; 4 > l; ++l) h.Zb[l] = G(f) ? ca(f, 7) : 0;
22640 for (l = 0; 4 > l; ++l) h.Lb[l] = G(f) ? ca(f, 6) : 0;
22641 }
22642 if (h.Bb) for (l = 0; 3 > l; ++l) k.jb[l] = G(f) ? na(f, 8) : 255;
22643 } else h.Bb = 0;
22644 if (f.Ka) return T(a, 3, "cannot parse segment header");
22645 h = a.ed;
22646 h.zd = G(f);
22647 h.Tb = na(f, 6);
22648 h.wb = na(f, 3);
22649 h.Pc = G(f);
22650 if (h.Pc && G(f)) {
22651 for (k = 0; 4 > k; ++k) G(f) && (h.vd[k] = ca(f, 6));
22652 for (k = 0; 4 > k; ++k) G(f) && (h.od[k] = ca(f, 6));
22653 }
22654 a.L = 0 == h.Tb ? 0 : h.zd ? 1 : 2;
22655 if (f.Ka) return T(a, 3, "cannot parse filter header");
22656 l = d;
22657 var m = e;
22658 e = l;
22659 d = l + m;
22660 h = m;
22661 a.Xb = (1 << na(a.m, 2)) - 1;
22662 k = a.Xb;
22663 if (m < 3 * k) c = 7;
22664 else {
22665 l += 3 * k;
22666 h -= 3 * k;
22667 for (m = 0; m < k; ++m) {
22668 var n = c[e + 0] | (c[e + 1] << 8) | (c[e + 2] << 16);
22669 n > h && (n = h);
22670 ma(a.Jc[+m], c, l, n);
22671 l += n;
22672 h -= n;
22673 e += 3;
22674 }
22675 ma(a.Jc[+k], c, l, h);
22676 c = l < d ? 0 : 5;
22677 }
22678 if (0 != c) return T(a, c, "cannot parse partitions");
22679 l = a.m;
22680 c = na(l, 7);
22681 e = G(l) ? ca(l, 4) : 0;
22682 d = G(l) ? ca(l, 4) : 0;
22683 h = G(l) ? ca(l, 4) : 0;
22684 k = G(l) ? ca(l, 4) : 0;
22685 l = G(l) ? ca(l, 4) : 0;
22686 m = a.Qa;
22687 for (n = 0; 4 > n; ++n) {
22688 if (m.Cb) {
22689 var r = m.Zb[n];
22690 m.Fb || (r += c);
22691 } else if (0 < n) {
22692 a.pb[n] = a.pb[0];
22693 continue;
22694 } else r = c;
22695 var q = a.pb[n];
22696 q.Sc[0] = Lb[ga(r + e, 127)];
22697 q.Sc[1] = Mb[ga(r + 0, 127)];
22698 q.Eb[0] = 2 * Lb[ga(r + d, 127)];
22699 q.Eb[1] = (101581 * Mb[ga(r + h, 127)]) >> 16;
22700 8 > q.Eb[1] && (q.Eb[1] = 8);
22701 q.Qc[0] = Lb[ga(r + k, 117)];
22702 q.Qc[1] = Mb[ga(r + l, 127)];
22703 q.lc = r + l;
22704 }
22705 if (!g.Rb) return T(a, 4, "Not a key frame.");
22706 G(f);
22707 g = a.Pa;
22708 for (c = 0; 4 > c; ++c) {
22709 for (e = 0; 8 > e; ++e)
22710 for (d = 0; 3 > d; ++d)
22711 for (h = 0; 11 > h; ++h)
22712 (k = K(f, Ee[c][e][d][h]) ? na(f, 8) : Fe[c][e][d][h]),
22713 (g.Wc[c][e].Yb[d][h] = k);
22714 for (e = 0; 17 > e; ++e) g.Xc[c][e] = g.Wc[c][Ge[e]];
22715 }
22716 a.kc = G(f);
22717 a.kc && (a.Bd = na(f, 8));
22718 return (a.cb = 1);
22719 }
22720 function De(a, b, c, d, e, f, g) {
22721 var h = b[e].Yb[c];
22722 for (c = 0; 16 > e; ++e) {
22723 if (!K(a, h[c + 0])) return e;
22724 for (; !K(a, h[c + 1]); )
22725 if (((h = b[++e].Yb[0]), (c = 0), 16 == e)) return 16;
22726 var k = b[e + 1].Yb;
22727 if (K(a, h[c + 2])) {
22728 var l = a,
22729 m = h,
22730 n = c;
22731 var r = 0;
22732 if (K(l, m[n + 3]))
22733 if (K(l, m[n + 6])) {
22734 h = 0;
22735 r = K(l, m[n + 8]);
22736 m = K(l, m[n + 9 + r]);
22737 n = 2 * r + m;
22738 r = 0;
22739 for (m = He[n]; m[h]; ++h) r += r + K(l, m[h]);
22740 r += 3 + (8 << n);
22741 } else
22742 K(l, m[n + 7])
22743 ? ((r = 7 + 2 * K(l, 165)), (r += K(l, 145)))
22744 : (r = 5 + K(l, 159));
22745 else K(l, m[n + 4]) ? (r = 3 + K(l, m[n + 5])) : (r = 2);
22746 h = k[2];
22747 } else (r = 1), (h = k[1]);
22748 k = g + Ie[e];
22749 l = a;
22750 0 > l.b && Qa(l);
22751 var m = l.b,
22752 n = l.Ca >> 1,
22753 q = (n - (l.I >> m)) >> 31;
22754 --l.b;
22755 l.Ca += q;
22756 l.Ca |= 1;
22757 l.I -= ((n + 1) & q) << m;
22758 f[k] = ((r ^ q) - q) * d[(0 < e) + 0];
22759 }
22760 return 16;
22761 }
22762 function Lc(a) {
22763 var b = a.rb[a.sb - 1];
22764 b.la = 0;
22765 b.Na = 0;
22766 M(a.zc, 0, 0, a.zc.length);
22767 a.ja = 0;
22768 }
22769 function Je(a, b) {
22770 for (a.M = 0; a.M < a.Va; ++a.M) {
22771 var c = a.Jc[a.M & a.Xb],
22772 d = a.m,
22773 e = a,
22774 f;
22775 for (f = 0; f < e.za; ++f) {
22776 var g = d;
22777 var h = e;
22778 var k = h.Ac,
22779 l = h.Bc + 4 * f,
22780 m = h.zc,
22781 n = h.ya[h.aa + f];
22782 h.Qa.Bb
22783 ? (n.$b = K(g, h.Pa.jb[0])
22784 ? 2 + K(g, h.Pa.jb[2])
22785 : K(g, h.Pa.jb[1]))
22786 : (n.$b = 0);
22787 h.kc && (n.Ad = K(g, h.Bd));
22788 n.Za = !K(g, 145) + 0;
22789 if (n.Za) {
22790 var r = n.Ob,
22791 q = 0;
22792 for (h = 0; 4 > h; ++h) {
22793 var t = m[0 + h];
22794 var v;
22795 for (v = 0; 4 > v; ++v) {
22796 t = Ke[k[l + v]][t];
22797 for (var p = Mc[K(g, t[0])]; 0 < p; )
22798 p = Mc[2 * p + K(g, t[p])];
22799 t = -p;
22800 k[l + v] = t;
22801 }
22802 I(r, q, k, l, 4);
22803 q += 4;
22804 m[0 + h] = t;
22805 }
22806 } else
22807 (t = K(g, 156) ? (K(g, 128) ? 1 : 3) : K(g, 163) ? 2 : 0),
22808 (n.Ob[0] = t),
22809 M(k, l, t, 4),
22810 M(m, 0, t, 4);
22811 n.Dd = K(g, 142) ? (K(g, 114) ? (K(g, 183) ? 1 : 3) : 2) : 0;
22812 }
22813 if (e.m.Ka) return T(a, 7, "Premature end-of-partition0 encountered.");
22814 for (; a.ja < a.za; ++a.ja) {
22815 d = a;
22816 e = c;
22817 g = d.rb[d.sb - 1];
22818 k = d.rb[d.sb + d.ja];
22819 f = d.ya[d.aa + d.ja];
22820 if ((l = d.kc ? f.Ad : 0))
22821 (g.la = k.la = 0),
22822 f.Za || (g.Na = k.Na = 0),
22823 (f.Hc = 0),
22824 (f.Gc = 0),
22825 (f.ia = 0);
22826 else {
22827 var u,
22828 w,
22829 g = k,
22830 k = e,
22831 l = d.Pa.Xc,
22832 m = d.ya[d.aa + d.ja],
22833 n = d.pb[m.$b];
22834 h = m.ad;
22835 r = 0;
22836 q = d.rb[d.sb - 1];
22837 t = v = 0;
22838 M(h, r, 0, 384);
22839 if (m.Za) {
22840 var y = 0;
22841 var A = l[3];
22842 } else {
22843 p = V(16);
22844 var E = g.Na + q.Na;
22845 E = oa(k, l[1], E, n.Eb, 0, p, 0);
22846 g.Na = q.Na = (0 < E) + 0;
22847 if (1 < E) Nc(p, 0, h, r);
22848 else {
22849 var B = (p[0] + 3) >> 3;
22850 for (p = 0; 256 > p; p += 16) h[r + p] = B;
22851 }
22852 y = 1;
22853 A = l[0];
22854 }
22855 var C = g.la & 15;
22856 var N = q.la & 15;
22857 for (p = 0; 4 > p; ++p) {
22858 var z = N & 1;
22859 for (B = w = 0; 4 > B; ++B)
22860 (E = z + (C & 1)),
22861 (E = oa(k, A, E, n.Sc, y, h, r)),
22862 (z = E > y),
22863 (C = (C >> 1) | (z << 7)),
22864 (w = (w << 2) | (3 < E ? 3 : 1 < E ? 2 : 0 != h[r + 0])),
22865 (r += 16);
22866 C >>= 4;
22867 N = (N >> 1) | (z << 7);
22868 v = ((v << 8) | w) >>> 0;
22869 }
22870 A = C;
22871 y = N >> 4;
22872 for (u = 0; 4 > u; u += 2) {
22873 w = 0;
22874 C = g.la >> (4 + u);
22875 N = q.la >> (4 + u);
22876 for (p = 0; 2 > p; ++p) {
22877 z = N & 1;
22878 for (B = 0; 2 > B; ++B)
22879 (E = z + (C & 1)),
22880 (E = oa(k, l[2], E, n.Qc, 0, h, r)),
22881 (z = 0 < E),
22882 (C = (C >> 1) | (z << 3)),
22883 (w = (w << 2) | (3 < E ? 3 : 1 < E ? 2 : 0 != h[r + 0])),
22884 (r += 16);
22885 C >>= 2;
22886 N = (N >> 1) | (z << 5);
22887 }
22888 t |= w << (4 * u);
22889 A |= (C << 4) << u;
22890 y |= (N & 240) << u;
22891 }
22892 g.la = A;
22893 q.la = y;
22894 m.Hc = v;
22895 m.Gc = t;
22896 m.ia = t & 43690 ? 0 : n.ia;
22897 l = !(v | t);
22898 }
22899 0 < d.L &&
22900 ((d.wa[d.Y + d.ja] = d.gd[f.$b][f.Za]),
22901 (d.wa[d.Y + d.ja].La |= !l));
22902 if (e.Ka) return T(a, 7, "Premature end-of-file encountered.");
22903 }
22904 Lc(a);
22905 c = a;
22906 d = b;
22907 e = 1;
22908 f = c.D;
22909 g = 0 < c.L && c.M >= c.zb && c.M <= c.Va;
22910 if (0 == c.Aa)
22911 a: {
22912 (f.M = c.M), (f.uc = g), Oc(c, f), (e = 1);
22913 w = c.D;
22914 f = w.Nb;
22915 t = Ya[c.L];
22916 g = t * c.R;
22917 k = (t / 2) * c.B;
22918 p = 16 * f * c.R;
22919 B = 8 * f * c.B;
22920 l = c.sa;
22921 m = c.ta - g + p;
22922 n = c.qa;
22923 h = c.ra - k + B;
22924 r = c.Ha;
22925 q = c.Ia - k + B;
22926 C = w.M;
22927 N = 0 == C;
22928 v = C >= c.Va - 1;
22929 2 == c.Aa && Oc(c, w);
22930 if (w.uc)
22931 for (E = c, z = E.D.M, x(E.D.uc), w = E.yb; w < E.Hb; ++w) {
22932 var Q = E;
22933 y = w;
22934 A = z;
22935 var S = Q.D,
22936 D = S.Nb;
22937 u = Q.R;
22938 var S = S.wa[S.Y + y],
22939 F = Q.sa,
22940 H = Q.ta + 16 * D * u + 16 * y,
22941 J = S.dd,
22942 G = S.tc;
22943 if (0 != G)
22944 if ((x(3 <= G), 1 == Q.L))
22945 0 < y && Pc(F, H, u, G + 4),
22946 S.La && Qc(F, H, u, G),
22947 0 < A && Rc(F, H, u, G + 4),
22948 S.La && Sc(F, H, u, G);
22949 else {
22950 var L = Q.B,
22951 O = Q.qa,
22952 P = Q.ra + 8 * D * L + 8 * y,
22953 R = Q.Ha,
22954 Q = Q.Ia + 8 * D * L + 8 * y,
22955 D = S.ld;
22956 0 < y &&
22957 (Tc(F, H, u, G + 4, J, D),
22958 Uc(O, P, R, Q, L, G + 4, J, D));
22959 S.La && (Vc(F, H, u, G, J, D), Wc(O, P, R, Q, L, G, J, D));
22960 0 < A &&
22961 (Xc(F, H, u, G + 4, J, D),
22962 Yc(O, P, R, Q, L, G + 4, J, D));
22963 S.La && (Zc(F, H, u, G, J, D), $c(O, P, R, Q, L, G, J, D));
22964 }
22965 }
22966 c.ia && alert("todo:DitherRow");
22967 if (null != d.put) {
22968 w = 16 * C;
22969 C = 16 * (C + 1);
22970 N
22971 ? ((d.y = c.sa),
22972 (d.O = c.ta + p),
22973 (d.f = c.qa),
22974 (d.N = c.ra + B),
22975 (d.ea = c.Ha),
22976 (d.W = c.Ia + B))
22977 : ((w -= t),
22978 (d.y = l),
22979 (d.O = m),
22980 (d.f = n),
22981 (d.N = h),
22982 (d.ea = r),
22983 (d.W = q));
22984 v || (C -= t);
22985 C > d.o && (C = d.o);
22986 d.F = null;
22987 d.J = null;
22988 if (
22989 null != c.Fa &&
22990 0 < c.Fa.length &&
22991 w < C &&
22992 ((d.J = Le(c, d, w, C - w)),
22993 (d.F = c.mb),
22994 null == d.F && 0 == d.F.length)
22995 ) {
22996 e = T(c, 3, "Could not decode alpha data.");
22997 break a;
22998 }
22999 w < d.j &&
23000 ((t = d.j - w),
23001 (w = d.j),
23002 x(!(t & 1)),
23003 (d.O += c.R * t),
23004 (d.N += c.B * (t >> 1)),
23005 (d.W += c.B * (t >> 1)),
23006 null != d.F && (d.J += d.width * t));
23007 w < C &&
23008 ((d.O += d.v),
23009 (d.N += d.v >> 1),
23010 (d.W += d.v >> 1),
23011 null != d.F && (d.J += d.v),
23012 (d.ka = w - d.j),
23013 (d.U = d.va - d.v),
23014 (d.T = C - w),
23015 (e = d.put(d)));
23016 }
23017 f + 1 != c.Ic ||
23018 v ||
23019 (I(c.sa, c.ta - g, l, m + 16 * c.R, g),
23020 I(c.qa, c.ra - k, n, h + 8 * c.B, k),
23021 I(c.Ha, c.Ia - k, r, q + 8 * c.B, k));
23022 }
23023 if (!e) return T(a, 6, "Output aborted.");
23024 }
23025 return 1;
23026 }
23027 function Me(a, b) {
23028 if (null == a) return 0;
23029 if (null == b) return T(a, 2, "NULL VP8Io parameter in VP8Decode().");
23030 if (!a.cb && !Kc(a, b)) return 0;
23031 x(a.cb);
23032 if (null == b.ac || b.ac(b)) {
23033 b.ob && (a.L = 0);
23034 var c = Ya[a.L];
23035 2 == a.L
23036 ? ((a.yb = 0), (a.zb = 0))
23037 : ((a.yb = (b.v - c) >> 4),
23038 (a.zb = (b.j - c) >> 4),
23039 0 > a.yb && (a.yb = 0),
23040 0 > a.zb && (a.zb = 0));
23041 a.Va = (b.o + 15 + c) >> 4;
23042 a.Hb = (b.va + 15 + c) >> 4;
23043 a.Hb > a.za && (a.Hb = a.za);
23044 a.Va > a.Ub && (a.Va = a.Ub);
23045 if (0 < a.L) {
23046 var d = a.ed;
23047 for (c = 0; 4 > c; ++c) {
23048 var e;
23049 if (a.Qa.Cb) {
23050 var f = a.Qa.Lb[c];
23051 a.Qa.Fb || (f += d.Tb);
23052 } else f = d.Tb;
23053 for (e = 0; 1 >= e; ++e) {
23054 var g = a.gd[c][e],
23055 h = f;
23056 d.Pc && ((h += d.vd[0]), e && (h += d.od[0]));
23057 h = 0 > h ? 0 : 63 < h ? 63 : h;
23058 if (0 < h) {
23059 var k = h;
23060 0 < d.wb &&
23061 ((k = 4 < d.wb ? k >> 2 : k >> 1),
23062 k > 9 - d.wb && (k = 9 - d.wb));
23063 1 > k && (k = 1);
23064 g.dd = k;
23065 g.tc = 2 * h + k;
23066 g.ld = 40 <= h ? 2 : 15 <= h ? 1 : 0;
23067 } else g.tc = 0;
23068 g.La = e;
23069 }
23070 }
23071 }
23072 c = 0;
23073 } else T(a, 6, "Frame setup failed"), (c = a.a);
23074 if ((c = 0 == c)) {
23075 if (c) {
23076 a.$c = 0;
23077 0 < a.Aa || (a.Ic = Ne);
23078 b: {
23079 c = a.Ic;
23080 var k = a.za,
23081 d = 4 * k,
23082 l = 32 * k,
23083 m = k + 1,
23084 n = 0 < a.L ? k * (0 < a.Aa ? 2 : 1) : 0,
23085 r = (2 == a.Aa ? 2 : 1) * k;
23086 e = ((3 * (16 * c + Ya[a.L])) / 2) * l;
23087 f = null != a.Fa && 0 < a.Fa.length ? a.Kc.c * a.Kc.i : 0;
23088 g = d + 832 + e + f;
23089 if (g != g) c = 0;
23090 else {
23091 if (g > a.Vb) {
23092 a.Vb = 0;
23093 a.Ec = V(g);
23094 a.Fc = 0;
23095 if (null == a.Ec) {
23096 c = T(a, 1, "no memory during frame initialization.");
23097 break b;
23098 }
23099 a.Vb = g;
23100 }
23101 g = a.Ec;
23102 h = a.Fc;
23103 a.Ac = g;
23104 a.Bc = h;
23105 h += d;
23106 a.Gd = wa(l, Ic);
23107 a.Hd = 0;
23108 a.rb = wa(m + 1, Hc);
23109 a.sb = 1;
23110 a.wa = n ? wa(n, Xa) : null;
23111 a.Y = 0;
23112 a.D.Nb = 0;
23113 a.D.wa = a.wa;
23114 a.D.Y = a.Y;
23115 0 < a.Aa && (a.D.Y += k);
23116 x(!0);
23117 a.oc = g;
23118 a.pc = h;
23119 h += 832;
23120 a.ya = wa(r, Kb);
23121 a.aa = 0;
23122 a.D.ya = a.ya;
23123 a.D.aa = a.aa;
23124 2 == a.Aa && (a.D.aa += k);
23125 a.R = 16 * k;
23126 a.B = 8 * k;
23127 l = Ya[a.L];
23128 k = l * a.R;
23129 l = (l / 2) * a.B;
23130 a.sa = g;
23131 a.ta = h + k;
23132 a.qa = a.sa;
23133 a.ra = a.ta + 16 * c * a.R + l;
23134 a.Ha = a.qa;
23135 a.Ia = a.ra + 8 * c * a.B + l;
23136 a.$c = 0;
23137 h += e;
23138 a.mb = f ? g : null;
23139 a.nb = f ? h : null;
23140 x(h + f <= a.Fc + a.Vb);
23141 Lc(a);
23142 M(a.Ac, a.Bc, 0, d);
23143 c = 1;
23144 }
23145 }
23146 if (c) {
23147 b.ka = 0;
23148 b.y = a.sa;
23149 b.O = a.ta;
23150 b.f = a.qa;
23151 b.N = a.ra;
23152 b.ea = a.Ha;
23153 b.Vd = a.Ia;
23154 b.fa = a.R;
23155 b.Rc = a.B;
23156 b.F = null;
23157 b.J = 0;
23158 if (!ad) {
23159 for (c = -255; 255 >= c; ++c) bd[255 + c] = 0 > c ? -c : c;
23160 for (c = -1020; 1020 >= c; ++c)
23161 cd[1020 + c] = -128 > c ? -128 : 127 < c ? 127 : c;
23162 for (c = -112; 112 >= c; ++c)
23163 dd[112 + c] = -16 > c ? -16 : 15 < c ? 15 : c;
23164 for (c = -255; 510 >= c; ++c)
23165 ed[255 + c] = 0 > c ? 0 : 255 < c ? 255 : c;
23166 ad = 1;
23167 }
23168 Nc = Oe;
23169 Za = Pe;
23170 Nb = Qe;
23171 pa = Re;
23172 Ob = Se;
23173 fd = Te;
23174 Xc = Ue;
23175 Tc = Ve;
23176 Yc = We;
23177 Uc = Xe;
23178 Zc = Ye;
23179 Vc = Ze;
23180 $c = $e;
23181 Wc = af;
23182 Rc = gd;
23183 Pc = hd;
23184 Sc = bf;
23185 Qc = cf;
23186 W[0] = df;
23187 W[1] = ef;
23188 W[2] = ff;
23189 W[3] = gf;
23190 W[4] = hf;
23191 W[5] = jf;
23192 W[6] = kf;
23193 W[7] = lf;
23194 W[8] = mf;
23195 W[9] = nf;
23196 Y[0] = of;
23197 Y[1] = pf;
23198 Y[2] = qf;
23199 Y[3] = rf;
23200 Y[4] = sf;
23201 Y[5] = tf;
23202 Y[6] = uf;
23203 ka[0] = vf;
23204 ka[1] = wf;
23205 ka[2] = xf;
23206 ka[3] = yf;
23207 ka[4] = zf;
23208 ka[5] = Af;
23209 ka[6] = Bf;
23210 c = 1;
23211 } else c = 0;
23212 }
23213 c && (c = Je(a, b));
23214 null != b.bc && b.bc(b);
23215 c &= 1;
23216 }
23217 if (!c) return 0;
23218 a.cb = 0;
23219 return c;
23220 }
23221 function qa(a, b, c, d, e) {
23222 e = a[b + c + 32 * d] + (e >> 3);
23223 a[b + c + 32 * d] = e & -256 ? (0 > e ? 0 : 255) : e;
23224 }
23225 function kb(a, b, c, d, e, f) {
23226 qa(a, b, 0, c, d + e);
23227 qa(a, b, 1, c, d + f);
23228 qa(a, b, 2, c, d - f);
23229 qa(a, b, 3, c, d - e);
23230 }
23231 function da(a) {
23232 return ((20091 * a) >> 16) + a;
23233 }
23234 function id(a, b, c, d) {
23235 var e = 0,
23236 f;
23237 var g = V(16);
23238 for (f = 0; 4 > f; ++f) {
23239 var h = a[b + 0] + a[b + 8];
23240 var k = a[b + 0] - a[b + 8];
23241 var l = ((35468 * a[b + 4]) >> 16) - da(a[b + 12]);
23242 var m = da(a[b + 4]) + ((35468 * a[b + 12]) >> 16);
23243 g[e + 0] = h + m;
23244 g[e + 1] = k + l;
23245 g[e + 2] = k - l;
23246 g[e + 3] = h - m;
23247 e += 4;
23248 b++;
23249 }
23250 for (f = e = 0; 4 > f; ++f)
23251 (a = g[e + 0] + 4),
23252 (h = a + g[e + 8]),
23253 (k = a - g[e + 8]),
23254 (l = ((35468 * g[e + 4]) >> 16) - da(g[e + 12])),
23255 (m = da(g[e + 4]) + ((35468 * g[e + 12]) >> 16)),
23256 qa(c, d, 0, 0, h + m),
23257 qa(c, d, 1, 0, k + l),
23258 qa(c, d, 2, 0, k - l),
23259 qa(c, d, 3, 0, h - m),
23260 e++,
23261 (d += 32);
23262 }
23263 function Te(a, b, c, d) {
23264 var e = a[b + 0] + 4,
23265 f = (35468 * a[b + 4]) >> 16,
23266 g = da(a[b + 4]),
23267 h = (35468 * a[b + 1]) >> 16;
23268 a = da(a[b + 1]);
23269 kb(c, d, 0, e + g, a, h);
23270 kb(c, d, 1, e + f, a, h);
23271 kb(c, d, 2, e - f, a, h);
23272 kb(c, d, 3, e - g, a, h);
23273 }
23274 function Pe(a, b, c, d, e) {
23275 id(a, b, c, d);
23276 e && id(a, b + 16, c, d + 4);
23277 }
23278 function Qe(a, b, c, d) {
23279 Za(a, b + 0, c, d, 1);
23280 Za(a, b + 32, c, d + 128, 1);
23281 }
23282 function Re(a, b, c, d) {
23283 a = a[b + 0] + 4;
23284 var e;
23285 for (e = 0; 4 > e; ++e) for (b = 0; 4 > b; ++b) qa(c, d, b, e, a);
23286 }
23287 function Se(a, b, c, d) {
23288 a[b + 0] && pa(a, b + 0, c, d);
23289 a[b + 16] && pa(a, b + 16, c, d + 4);
23290 a[b + 32] && pa(a, b + 32, c, d + 128);
23291 a[b + 48] && pa(a, b + 48, c, d + 128 + 4);
23292 }
23293 function Oe(a, b, c, d) {
23294 var e = V(16),
23295 f;
23296 for (f = 0; 4 > f; ++f) {
23297 var g = a[b + 0 + f] + a[b + 12 + f];
23298 var h = a[b + 4 + f] + a[b + 8 + f];
23299 var k = a[b + 4 + f] - a[b + 8 + f];
23300 var l = a[b + 0 + f] - a[b + 12 + f];
23301 e[0 + f] = g + h;
23302 e[8 + f] = g - h;
23303 e[4 + f] = l + k;
23304 e[12 + f] = l - k;
23305 }
23306 for (f = 0; 4 > f; ++f)
23307 (a = e[0 + 4 * f] + 3),
23308 (g = a + e[3 + 4 * f]),
23309 (h = e[1 + 4 * f] + e[2 + 4 * f]),
23310 (k = e[1 + 4 * f] - e[2 + 4 * f]),
23311 (l = a - e[3 + 4 * f]),
23312 (c[d + 0] = (g + h) >> 3),
23313 (c[d + 16] = (l + k) >> 3),
23314 (c[d + 32] = (g - h) >> 3),
23315 (c[d + 48] = (l - k) >> 3),
23316 (d += 64);
23317 }
23318 function Pb(a, b, c) {
23319 var d = b - 32,
23320 e = R,
23321 f = 255 - a[d - 1],
23322 g;
23323 for (g = 0; g < c; ++g) {
23324 var h = e,
23325 k = f + a[b - 1],
23326 l;
23327 for (l = 0; l < c; ++l) a[b + l] = h[k + a[d + l]];
23328 b += 32;
23329 }
23330 }
23331 function ef(a, b) {
23332 Pb(a, b, 4);
23333 }
23334 function wf(a, b) {
23335 Pb(a, b, 8);
23336 }
23337 function pf(a, b) {
23338 Pb(a, b, 16);
23339 }
23340 function qf(a, b) {
23341 var c;
23342 for (c = 0; 16 > c; ++c) I(a, b + 32 * c, a, b - 32, 16);
23343 }
23344 function rf(a, b) {
23345 var c;
23346 for (c = 16; 0 < c; --c) M(a, b, a[b - 1], 16), (b += 32);
23347 }
23348 function $a(a, b, c) {
23349 var d;
23350 for (d = 0; 16 > d; ++d) M(b, c + 32 * d, a, 16);
23351 }
23352 function of(a, b) {
23353 var c = 16,
23354 d;
23355 for (d = 0; 16 > d; ++d) c += a[b - 1 + 32 * d] + a[b + d - 32];
23356 $a(c >> 5, a, b);
23357 }
23358 function sf(a, b) {
23359 var c = 8,
23360 d;
23361 for (d = 0; 16 > d; ++d) c += a[b - 1 + 32 * d];
23362 $a(c >> 4, a, b);
23363 }
23364 function tf(a, b) {
23365 var c = 8,
23366 d;
23367 for (d = 0; 16 > d; ++d) c += a[b + d - 32];
23368 $a(c >> 4, a, b);
23369 }
23370 function uf(a, b) {
23371 $a(128, a, b);
23372 }
23373 function z(a, b, c) {
23374 return (a + 2 * b + c + 2) >> 2;
23375 }
23376 function ff(a, b) {
23377 var c = b - 32,
23378 c = new Uint8Array([
23379 z(a[c - 1], a[c + 0], a[c + 1]),
23380 z(a[c + 0], a[c + 1], a[c + 2]),
23381 z(a[c + 1], a[c + 2], a[c + 3]),
23382 z(a[c + 2], a[c + 3], a[c + 4])
23383 ]),
23384 d;
23385 for (d = 0; 4 > d; ++d) I(a, b + 32 * d, c, 0, c.length);
23386 }
23387 function gf(a, b) {
23388 var c = a[b - 1],
23389 d = a[b - 1 + 32],
23390 e = a[b - 1 + 64],
23391 f = a[b - 1 + 96];
23392 ra(a, b + 0, 16843009 * z(a[b - 1 - 32], c, d));
23393 ra(a, b + 32, 16843009 * z(c, d, e));
23394 ra(a, b + 64, 16843009 * z(d, e, f));
23395 ra(a, b + 96, 16843009 * z(e, f, f));
23396 }
23397 function df(a, b) {
23398 var c = 4,
23399 d;
23400 for (d = 0; 4 > d; ++d) c += a[b + d - 32] + a[b - 1 + 32 * d];
23401 c >>= 3;
23402 for (d = 0; 4 > d; ++d) M(a, b + 32 * d, c, 4);
23403 }
23404 function hf(a, b) {
23405 var c = a[b - 1 + 0],
23406 d = a[b - 1 + 32],
23407 e = a[b - 1 + 64],
23408 f = a[b - 1 - 32],
23409 g = a[b + 0 - 32],
23410 h = a[b + 1 - 32],
23411 k = a[b + 2 - 32],
23412 l = a[b + 3 - 32];
23413 a[b + 0 + 96] = z(d, e, a[b - 1 + 96]);
23414 a[b + 1 + 96] = a[b + 0 + 64] = z(c, d, e);
23415 a[b + 2 + 96] = a[b + 1 + 64] = a[b + 0 + 32] = z(f, c, d);
23416 a[b + 3 + 96] = a[b + 2 + 64] = a[b + 1 + 32] = a[b + 0 + 0] = z(g, f, c);
23417 a[b + 3 + 64] = a[b + 2 + 32] = a[b + 1 + 0] = z(h, g, f);
23418 a[b + 3 + 32] = a[b + 2 + 0] = z(k, h, g);
23419 a[b + 3 + 0] = z(l, k, h);
23420 }
23421 function kf(a, b) {
23422 var c = a[b + 1 - 32],
23423 d = a[b + 2 - 32],
23424 e = a[b + 3 - 32],
23425 f = a[b + 4 - 32],
23426 g = a[b + 5 - 32],
23427 h = a[b + 6 - 32],
23428 k = a[b + 7 - 32];
23429 a[b + 0 + 0] = z(a[b + 0 - 32], c, d);
23430 a[b + 1 + 0] = a[b + 0 + 32] = z(c, d, e);
23431 a[b + 2 + 0] = a[b + 1 + 32] = a[b + 0 + 64] = z(d, e, f);
23432 a[b + 3 + 0] = a[b + 2 + 32] = a[b + 1 + 64] = a[b + 0 + 96] = z(e, f, g);
23433 a[b + 3 + 32] = a[b + 2 + 64] = a[b + 1 + 96] = z(f, g, h);
23434 a[b + 3 + 64] = a[b + 2 + 96] = z(g, h, k);
23435 a[b + 3 + 96] = z(h, k, k);
23436 }
23437 function jf(a, b) {
23438 var c = a[b - 1 + 0],
23439 d = a[b - 1 + 32],
23440 e = a[b - 1 + 64],
23441 f = a[b - 1 - 32],
23442 g = a[b + 0 - 32],
23443 h = a[b + 1 - 32],
23444 k = a[b + 2 - 32],
23445 l = a[b + 3 - 32];
23446 a[b + 0 + 0] = a[b + 1 + 64] = (f + g + 1) >> 1;
23447 a[b + 1 + 0] = a[b + 2 + 64] = (g + h + 1) >> 1;
23448 a[b + 2 + 0] = a[b + 3 + 64] = (h + k + 1) >> 1;
23449 a[b + 3 + 0] = (k + l + 1) >> 1;
23450 a[b + 0 + 96] = z(e, d, c);
23451 a[b + 0 + 64] = z(d, c, f);
23452 a[b + 0 + 32] = a[b + 1 + 96] = z(c, f, g);
23453 a[b + 1 + 32] = a[b + 2 + 96] = z(f, g, h);
23454 a[b + 2 + 32] = a[b + 3 + 96] = z(g, h, k);
23455 a[b + 3 + 32] = z(h, k, l);
23456 }
23457 function lf(a, b) {
23458 var c = a[b + 0 - 32],
23459 d = a[b + 1 - 32],
23460 e = a[b + 2 - 32],
23461 f = a[b + 3 - 32],
23462 g = a[b + 4 - 32],
23463 h = a[b + 5 - 32],
23464 k = a[b + 6 - 32],
23465 l = a[b + 7 - 32];
23466 a[b + 0 + 0] = (c + d + 1) >> 1;
23467 a[b + 1 + 0] = a[b + 0 + 64] = (d + e + 1) >> 1;
23468 a[b + 2 + 0] = a[b + 1 + 64] = (e + f + 1) >> 1;
23469 a[b + 3 + 0] = a[b + 2 + 64] = (f + g + 1) >> 1;
23470 a[b + 0 + 32] = z(c, d, e);
23471 a[b + 1 + 32] = a[b + 0 + 96] = z(d, e, f);
23472 a[b + 2 + 32] = a[b + 1 + 96] = z(e, f, g);
23473 a[b + 3 + 32] = a[b + 2 + 96] = z(f, g, h);
23474 a[b + 3 + 64] = z(g, h, k);
23475 a[b + 3 + 96] = z(h, k, l);
23476 }
23477 function nf(a, b) {
23478 var c = a[b - 1 + 0],
23479 d = a[b - 1 + 32],
23480 e = a[b - 1 + 64],
23481 f = a[b - 1 + 96];
23482 a[b + 0 + 0] = (c + d + 1) >> 1;
23483 a[b + 2 + 0] = a[b + 0 + 32] = (d + e + 1) >> 1;
23484 a[b + 2 + 32] = a[b + 0 + 64] = (e + f + 1) >> 1;
23485 a[b + 1 + 0] = z(c, d, e);
23486 a[b + 3 + 0] = a[b + 1 + 32] = z(d, e, f);
23487 a[b + 3 + 32] = a[b + 1 + 64] = z(e, f, f);
23488 a[b + 3 + 64] = a[b + 2 + 64] = a[b + 0 + 96] = a[b + 1 + 96] = a[
23489 b + 2 + 96
23490 ] = a[b + 3 + 96] = f;
23491 }
23492 function mf(a, b) {
23493 var c = a[b - 1 + 0],
23494 d = a[b - 1 + 32],
23495 e = a[b - 1 + 64],
23496 f = a[b - 1 + 96],
23497 g = a[b - 1 - 32],
23498 h = a[b + 0 - 32],
23499 k = a[b + 1 - 32],
23500 l = a[b + 2 - 32];
23501 a[b + 0 + 0] = a[b + 2 + 32] = (c + g + 1) >> 1;
23502 a[b + 0 + 32] = a[b + 2 + 64] = (d + c + 1) >> 1;
23503 a[b + 0 + 64] = a[b + 2 + 96] = (e + d + 1) >> 1;
23504 a[b + 0 + 96] = (f + e + 1) >> 1;
23505 a[b + 3 + 0] = z(h, k, l);
23506 a[b + 2 + 0] = z(g, h, k);
23507 a[b + 1 + 0] = a[b + 3 + 32] = z(c, g, h);
23508 a[b + 1 + 32] = a[b + 3 + 64] = z(d, c, g);
23509 a[b + 1 + 64] = a[b + 3 + 96] = z(e, d, c);
23510 a[b + 1 + 96] = z(f, e, d);
23511 }
23512 function xf(a, b) {
23513 var c;
23514 for (c = 0; 8 > c; ++c) I(a, b + 32 * c, a, b - 32, 8);
23515 }
23516 function yf(a, b) {
23517 var c;
23518 for (c = 0; 8 > c; ++c) M(a, b, a[b - 1], 8), (b += 32);
23519 }
23520 function lb(a, b, c) {
23521 var d;
23522 for (d = 0; 8 > d; ++d) M(b, c + 32 * d, a, 8);
23523 }
23524 function vf(a, b) {
23525 var c = 8,
23526 d;
23527 for (d = 0; 8 > d; ++d) c += a[b + d - 32] + a[b - 1 + 32 * d];
23528 lb(c >> 4, a, b);
23529 }
23530 function Af(a, b) {
23531 var c = 4,
23532 d;
23533 for (d = 0; 8 > d; ++d) c += a[b + d - 32];
23534 lb(c >> 3, a, b);
23535 }
23536 function zf(a, b) {
23537 var c = 4,
23538 d;
23539 for (d = 0; 8 > d; ++d) c += a[b - 1 + 32 * d];
23540 lb(c >> 3, a, b);
23541 }
23542 function Bf(a, b) {
23543 lb(128, a, b);
23544 }
23545 function ab(a, b, c) {
23546 var d = a[b - c],
23547 e = a[b + 0],
23548 f = 3 * (e - d) + Qb[1020 + a[b - 2 * c] - a[b + c]],
23549 g = mb[112 + ((f + 4) >> 3)];
23550 a[b - c] = R[255 + d + mb[112 + ((f + 3) >> 3)]];
23551 a[b + 0] = R[255 + e - g];
23552 }
23553 function jd(a, b, c, d) {
23554 var e = a[b + 0],
23555 f = a[b + c];
23556 return U[255 + a[b - 2 * c] - a[b - c]] > d || U[255 + f - e] > d;
23557 }
23558 function kd(a, b, c, d) {
23559 return (
23560 4 * U[255 + a[b - c] - a[b + 0]] + U[255 + a[b - 2 * c] - a[b + c]] <= d
23561 );
23562 }
23563 function ld(a, b, c, d, e) {
23564 var f = a[b - 3 * c],
23565 g = a[b - 2 * c],
23566 h = a[b - c],
23567 k = a[b + 0],
23568 l = a[b + c],
23569 m = a[b + 2 * c],
23570 n = a[b + 3 * c];
23571 return 4 * U[255 + h - k] + U[255 + g - l] > d
23572 ? 0
23573 : U[255 + a[b - 4 * c] - f] <= e &&
23574 U[255 + f - g] <= e &&
23575 U[255 + g - h] <= e &&
23576 U[255 + n - m] <= e &&
23577 U[255 + m - l] <= e &&
23578 U[255 + l - k] <= e;
23579 }
23580 function gd(a, b, c, d) {
23581 var e = 2 * d + 1;
23582 for (d = 0; 16 > d; ++d) kd(a, b + d, c, e) && ab(a, b + d, c);
23583 }
23584 function hd(a, b, c, d) {
23585 var e = 2 * d + 1;
23586 for (d = 0; 16 > d; ++d) kd(a, b + d * c, 1, e) && ab(a, b + d * c, 1);
23587 }
23588 function bf(a, b, c, d) {
23589 var e;
23590 for (e = 3; 0 < e; --e) (b += 4 * c), gd(a, b, c, d);
23591 }
23592 function cf(a, b, c, d) {
23593 var e;
23594 for (e = 3; 0 < e; --e) (b += 4), hd(a, b, c, d);
23595 }
23596 function ea(a, b, c, d, e, f, g, h) {
23597 for (f = 2 * f + 1; 0 < e--; ) {
23598 if (ld(a, b, c, f, g))
23599 if (jd(a, b, c, h)) ab(a, b, c);
23600 else {
23601 var k = a,
23602 l = b,
23603 m = c,
23604 n = k[l - 2 * m],
23605 r = k[l - m],
23606 q = k[l + 0],
23607 t = k[l + m],
23608 v = k[l + 2 * m],
23609 p = Qb[1020 + 3 * (q - r) + Qb[1020 + n - t]],
23610 u = (27 * p + 63) >> 7,
23611 w = (18 * p + 63) >> 7,
23612 p = (9 * p + 63) >> 7;
23613 k[l - 3 * m] = R[255 + k[l - 3 * m] + p];
23614 k[l - 2 * m] = R[255 + n + w];
23615 k[l - m] = R[255 + r + u];
23616 k[l + 0] = R[255 + q - u];
23617 k[l + m] = R[255 + t - w];
23618 k[l + 2 * m] = R[255 + v - p];
23619 }
23620 b += d;
23621 }
23622 }
23623 function Fa(a, b, c, d, e, f, g, h) {
23624 for (f = 2 * f + 1; 0 < e--; ) {
23625 if (ld(a, b, c, f, g))
23626 if (jd(a, b, c, h)) ab(a, b, c);
23627 else {
23628 var k = a,
23629 l = b,
23630 m = c,
23631 n = k[l - m],
23632 r = k[l + 0],
23633 q = k[l + m],
23634 t = 3 * (r - n),
23635 v = mb[112 + ((t + 4) >> 3)],
23636 t = mb[112 + ((t + 3) >> 3)],
23637 p = (v + 1) >> 1;
23638 k[l - 2 * m] = R[255 + k[l - 2 * m] + p];
23639 k[l - m] = R[255 + n + t];
23640 k[l + 0] = R[255 + r - v];
23641 k[l + m] = R[255 + q - p];
23642 }
23643 b += d;
23644 }
23645 }
23646 function Ue(a, b, c, d, e, f) {
23647 ea(a, b, c, 1, 16, d, e, f);
23648 }
23649 function Ve(a, b, c, d, e, f) {
23650 ea(a, b, 1, c, 16, d, e, f);
23651 }
23652 function Ye(a, b, c, d, e, f) {
23653 var g;
23654 for (g = 3; 0 < g; --g) (b += 4 * c), Fa(a, b, c, 1, 16, d, e, f);
23655 }
23656 function Ze(a, b, c, d, e, f) {
23657 var g;
23658 for (g = 3; 0 < g; --g) (b += 4), Fa(a, b, 1, c, 16, d, e, f);
23659 }
23660 function We(a, b, c, d, e, f, g, h) {
23661 ea(a, b, e, 1, 8, f, g, h);
23662 ea(c, d, e, 1, 8, f, g, h);
23663 }
23664 function Xe(a, b, c, d, e, f, g, h) {
23665 ea(a, b, 1, e, 8, f, g, h);
23666 ea(c, d, 1, e, 8, f, g, h);
23667 }
23668 function $e(a, b, c, d, e, f, g, h) {
23669 Fa(a, b + 4 * e, e, 1, 8, f, g, h);
23670 Fa(c, d + 4 * e, e, 1, 8, f, g, h);
23671 }
23672 function af(a, b, c, d, e, f, g, h) {
23673 Fa(a, b + 4, 1, e, 8, f, g, h);
23674 Fa(c, d + 4, 1, e, 8, f, g, h);
23675 }
23676 function Cf() {
23677 this.ba = new Cb();
23678 this.ec = [];
23679 this.cc = [];
23680 this.Mc = [];
23681 this.Dc = this.Nc = this.dc = this.fc = 0;
23682 this.Oa = new Ud();
23683 this.memory = 0;
23684 this.Ib = "OutputFunc";
23685 this.Jb = "OutputAlphaFunc";
23686 this.Nd = "OutputRowFunc";
23687 }
23688 function md() {
23689 this.data = [];
23690 this.offset = this.kd = this.ha = this.w = 0;
23691 this.na = [];
23692 this.xa = this.gb = this.Ja = this.Sa = this.P = 0;
23693 }
23694 function Df() {
23695 this.nc = this.Ea = this.b = this.hc = 0;
23696 this.K = [];
23697 this.w = 0;
23698 }
23699 function Ef() {
23700 this.ua = 0;
23701 this.Wa = new ac();
23702 this.vb = new ac();
23703 this.md = this.xc = this.wc = 0;
23704 this.vc = [];
23705 this.Wb = 0;
23706 this.Ya = new Ub();
23707 this.yc = new O();
23708 }
23709 function je() {
23710 this.xb = this.a = 0;
23711 this.l = new Oa();
23712 this.ca = new Cb();
23713 this.V = [];
23714 this.Ba = 0;
23715 this.Ta = [];
23716 this.Ua = 0;
23717 this.m = new Ra();
23718 this.Pb = 0;
23719 this.wd = new Ra();
23720 this.Ma = this.$ = this.C = this.i = this.c = this.xd = 0;
23721 this.s = new Ef();
23722 this.ab = 0;
23723 this.gc = wa(4, Df);
23724 this.Oc = 0;
23725 }
23726 function Ff() {
23727 this.Lc = this.Z = this.$a = this.i = this.c = 0;
23728 this.l = new Oa();
23729 this.ic = 0;
23730 this.ca = [];
23731 this.tb = 0;
23732 this.qd = null;
23733 this.rd = 0;
23734 }
23735 function Rb(a, b, c, d, e, f, g) {
23736 a = null == a ? 0 : a[b + 0];
23737 for (b = 0; b < g; ++b) (e[f + b] = (a + c[d + b]) & 255), (a = e[f + b]);
23738 }
23739 function Gf(a, b, c, d, e, f, g) {
23740 if (null == a) Rb(null, null, c, d, e, f, g);
23741 else {
23742 var h;
23743 for (h = 0; h < g; ++h) e[f + h] = (a[b + h] + c[d + h]) & 255;
23744 }
23745 }
23746 function Hf(a, b, c, d, e, f, g) {
23747 if (null == a) Rb(null, null, c, d, e, f, g);
23748 else {
23749 var h = a[b + 0],
23750 k = h,
23751 l = h,
23752 m;
23753 for (m = 0; m < g; ++m)
23754 (h = a[b + m]),
23755 (k = l + h - k),
23756 (l = (c[d + m] + (k & -256 ? (0 > k ? 0 : 255) : k)) & 255),
23757 (k = h),
23758 (e[f + m] = l);
23759 }
23760 }
23761 function Le(a, b, c, d) {
23762 var e = b.width,
23763 f = b.o;
23764 x(null != a && null != b);
23765 if (0 > c || 0 >= d || c + d > f) return null;
23766 if (!a.Cc) {
23767 if (null == a.ga) {
23768 a.ga = new Ff();
23769 var g;
23770 (g = null == a.ga) ||
23771 ((g = b.width * b.o),
23772 x(0 == a.Gb.length),
23773 (a.Gb = V(g)),
23774 (a.Uc = 0),
23775 null == a.Gb
23776 ? (g = 0)
23777 : ((a.mb = a.Gb), (a.nb = a.Uc), (a.rc = null), (g = 1)),
23778 (g = !g));
23779 if (!g) {
23780 g = a.ga;
23781 var h = a.Fa,
23782 k = a.P,
23783 l = a.qc,
23784 m = a.mb,
23785 n = a.nb,
23786 r = k + 1,
23787 q = l - 1,
23788 t = g.l;
23789 x(null != h && null != m && null != b);
23790 ia[0] = null;
23791 ia[1] = Rb;
23792 ia[2] = Gf;
23793 ia[3] = Hf;
23794 g.ca = m;
23795 g.tb = n;
23796 g.c = b.width;
23797 g.i = b.height;
23798 x(0 < g.c && 0 < g.i);
23799 if (1 >= l) b = 0;
23800 else if (
23801 ((g.$a = (h[k + 0] >> 0) & 3),
23802 (g.Z = (h[k + 0] >> 2) & 3),
23803 (g.Lc = (h[k + 0] >> 4) & 3),
23804 (k = (h[k + 0] >> 6) & 3),
23805 0 > g.$a || 1 < g.$a || 4 <= g.Z || 1 < g.Lc || k)
23806 )
23807 b = 0;
23808 else if (
23809 ((t.put = kc),
23810 (t.ac = gc),
23811 (t.bc = lc),
23812 (t.ma = g),
23813 (t.width = b.width),
23814 (t.height = b.height),
23815 (t.Da = b.Da),
23816 (t.v = b.v),
23817 (t.va = b.va),
23818 (t.j = b.j),
23819 (t.o = b.o),
23820 g.$a)
23821 )
23822 b: {
23823 x(1 == g.$a), (b = Bc());
23824 c: for (;;) {
23825 if (null == b) {
23826 b = 0;
23827 break b;
23828 }
23829 x(null != g);
23830 g.mc = b;
23831 b.c = g.c;
23832 b.i = g.i;
23833 b.l = g.l;
23834 b.l.ma = g;
23835 b.l.width = g.c;
23836 b.l.height = g.i;
23837 b.a = 0;
23838 cb(b.m, h, r, q);
23839 if (!rb(g.c, g.i, 1, b, null)) break c;
23840 1 == b.ab && 3 == b.gc[0].hc && yc(b.s)
23841 ? ((g.ic = 1),
23842 (h = b.c * b.i),
23843 (b.Ta = null),
23844 (b.Ua = 0),
23845 (b.V = V(h)),
23846 (b.Ba = 0),
23847 null == b.V ? ((b.a = 1), (b = 0)) : (b = 1))
23848 : ((g.ic = 0), (b = Ec(b, g.c)));
23849 if (!b) break c;
23850 b = 1;
23851 break b;
23852 }
23853 g.mc = null;
23854 b = 0;
23855 }
23856 else b = q >= g.c * g.i;
23857 g = !b;
23858 }
23859 if (g) return null;
23860 1 != a.ga.Lc ? (a.Ga = 0) : (d = f - c);
23861 }
23862 x(null != a.ga);
23863 x(c + d <= f);
23864 a: {
23865 h = a.ga;
23866 b = h.c;
23867 f = h.l.o;
23868 if (0 == h.$a) {
23869 r = a.rc;
23870 q = a.Vc;
23871 t = a.Fa;
23872 k = a.P + 1 + c * b;
23873 l = a.mb;
23874 m = a.nb + c * b;
23875 x(k <= a.P + a.qc);
23876 if (0 != h.Z)
23877 for (x(null != ia[h.Z]), g = 0; g < d; ++g)
23878 ia[h.Z](r, q, t, k, l, m, b),
23879 (r = l),
23880 (q = m),
23881 (m += b),
23882 (k += b);
23883 else
23884 for (g = 0; g < d; ++g)
23885 I(l, m, t, k, b), (r = l), (q = m), (m += b), (k += b);
23886 a.rc = r;
23887 a.Vc = q;
23888 } else {
23889 x(null != h.mc);
23890 b = c + d;
23891 g = h.mc;
23892 x(null != g);
23893 x(b <= g.i);
23894 if (g.C >= b) b = 1;
23895 else if ((h.ic || Aa(), h.ic)) {
23896 var h = g.V,
23897 r = g.Ba,
23898 q = g.c,
23899 v = g.i,
23900 t = 1,
23901 k = g.$ / q,
23902 l = g.$ % q,
23903 m = g.m,
23904 n = g.s,
23905 p = g.$,
23906 u = q * v,
23907 w = q * b,
23908 y = n.wc,
23909 A = p < w ? ha(n, l, k) : null;
23910 x(p <= u);
23911 x(b <= v);
23912 x(yc(n));
23913 c: for (;;) {
23914 for (; !m.h && p < w; ) {
23915 l & y || (A = ha(n, l, k));
23916 x(null != A);
23917 Sa(m);
23918 v = ua(A.G[0], A.H[0], m);
23919 if (256 > v)
23920 (h[r + p] = v),
23921 ++p,
23922 ++l,
23923 l >= q && ((l = 0), ++k, k <= b && !(k % 16) && Ib(g, k));
23924 else if (280 > v) {
23925 var v = ib(v - 256, m);
23926 var E = ua(A.G[4], A.H[4], m);
23927 Sa(m);
23928 E = ib(E, m);
23929 E = nc(q, E);
23930 if (p >= E && u - p >= v) {
23931 var B;
23932 for (B = 0; B < v; ++B) h[r + p + B] = h[r + p + B - E];
23933 } else {
23934 t = 0;
23935 break c;
23936 }
23937 p += v;
23938 for (l += v; l >= q; )
23939 (l -= q), ++k, k <= b && !(k % 16) && Ib(g, k);
23940 p < w && l & y && (A = ha(n, l, k));
23941 } else {
23942 t = 0;
23943 break c;
23944 }
23945 x(m.h == db(m));
23946 }
23947 Ib(g, k > b ? b : k);
23948 break c;
23949 }
23950 !t || (m.h && p < u) ? ((t = 0), (g.a = m.h ? 5 : 3)) : (g.$ = p);
23951 b = t;
23952 } else b = Jb(g, g.V, g.Ba, g.c, g.i, b, se);
23953 if (!b) {
23954 d = 0;
23955 break a;
23956 }
23957 }
23958 c + d >= f && (a.Cc = 1);
23959 d = 1;
23960 }
23961 if (!d) return null;
23962 if (
23963 a.Cc &&
23964 ((d = a.ga), null != d && (d.mc = null), (a.ga = null), 0 < a.Ga)
23965 )
23966 return alert("todo:WebPDequantizeLevels"), null;
23967 }
23968 return a.nb + c * e;
23969 }
23970 function If(a, b, c, d, e, f) {
23971 for (; 0 < e--; ) {
23972 var g = a,
23973 h = b + (c ? 1 : 0),
23974 k = a,
23975 l = b + (c ? 0 : 3),
23976 m;
23977 for (m = 0; m < d; ++m) {
23978 var n = k[l + 4 * m];
23979 255 != n &&
23980 ((n *= 32897),
23981 (g[h + 4 * m + 0] = (g[h + 4 * m + 0] * n) >> 23),
23982 (g[h + 4 * m + 1] = (g[h + 4 * m + 1] * n) >> 23),
23983 (g[h + 4 * m + 2] = (g[h + 4 * m + 2] * n) >> 23));
23984 }
23985 b += f;
23986 }
23987 }
23988 function Jf(a, b, c, d, e) {
23989 for (; 0 < d--; ) {
23990 var f;
23991 for (f = 0; f < c; ++f) {
23992 var g = a[b + 2 * f + 0],
23993 h = a[b + 2 * f + 1],
23994 k = h & 15,
23995 l = 4369 * k,
23996 h = (((h & 240) | (h >> 4)) * l) >> 16;
23997 a[b + 2 * f + 0] =
23998 (((((g & 240) | (g >> 4)) * l) >> 16) & 240) |
23999 ((((((g & 15) | (g << 4)) * l) >> 16) >> 4) & 15);
24000 a[b + 2 * f + 1] = (h & 240) | k;
24001 }
24002 b += e;
24003 }
24004 }
24005 function Kf(a, b, c, d, e, f, g, h) {
24006 var k = 255,
24007 l,
24008 m;
24009 for (m = 0; m < e; ++m) {
24010 for (l = 0; l < d; ++l) {
24011 var n = a[b + l];
24012 f[g + 4 * l] = n;
24013 k &= n;
24014 }
24015 b += c;
24016 g += h;
24017 }
24018 return 255 != k;
24019 }
24020 function Lf(a, b, c, d, e) {
24021 var f;
24022 for (f = 0; f < e; ++f) c[d + f] = a[b + f] >> 8;
24023 }
24024 function Aa() {
24025 za = If;
24026 vc = Jf;
24027 fc = Kf;
24028 Fc = Lf;
24029 }
24030 function va(a, b, c) {
24031 self[a] = function(a, e, f, g, h, k, l, m, n, r, q, t, v, p, u, w, y) {
24032 var d,
24033 E = (y - 1) >> 1;
24034 var B = h[k + 0] | (l[m + 0] << 16);
24035 var C = n[r + 0] | (q[t + 0] << 16);
24036 x(null != a);
24037 var z = (3 * B + C + 131074) >> 2;
24038 b(a[e + 0], z & 255, z >> 16, v, p);
24039 null != f &&
24040 ((z = (3 * C + B + 131074) >> 2),
24041 b(f[g + 0], z & 255, z >> 16, u, w));
24042 for (d = 1; d <= E; ++d) {
24043 var D = h[k + d] | (l[m + d] << 16);
24044 var G = n[r + d] | (q[t + d] << 16);
24045 var F = B + D + C + G + 524296;
24046 var H = (F + 2 * (D + C)) >> 3;
24047 F = (F + 2 * (B + G)) >> 3;
24048 z = (H + B) >> 1;
24049 B = (F + D) >> 1;
24050 b(a[e + 2 * d - 1], z & 255, z >> 16, v, p + (2 * d - 1) * c);
24051 b(a[e + 2 * d - 0], B & 255, B >> 16, v, p + (2 * d - 0) * c);
24052 null != f &&
24053 ((z = (F + C) >> 1),
24054 (B = (H + G) >> 1),
24055 b(f[g + 2 * d - 1], z & 255, z >> 16, u, w + (2 * d - 1) * c),
24056 b(f[g + 2 * d + 0], B & 255, B >> 16, u, w + (2 * d + 0) * c));
24057 B = D;
24058 C = G;
24059 }
24060 y & 1 ||
24061 ((z = (3 * B + C + 131074) >> 2),
24062 b(a[e + y - 1], z & 255, z >> 16, v, p + (y - 1) * c),
24063 null != f &&
24064 ((z = (3 * C + B + 131074) >> 2),
24065 b(f[g + y - 1], z & 255, z >> 16, u, w + (y - 1) * c)));
24066 };
24067 }
24068 function ic() {
24069 P[Ca] = Mf;
24070 P[Ua] = nd;
24071 P[tc] = Nf;
24072 P[Va] = od;
24073 P[ya] = pd;
24074 P[Db] = qd;
24075 P[wc] = Of;
24076 P[zb] = nd;
24077 P[Ab] = od;
24078 P[Ja] = pd;
24079 P[Bb] = qd;
24080 }
24081 function Sb(a) {
24082 return a & ~Pf ? (0 > a ? 0 : 255) : a >> rd;
24083 }
24084 function bb(a, b) {
24085 return Sb(((19077 * a) >> 8) + ((26149 * b) >> 8) - 14234);
24086 }
24087 function nb(a, b, c) {
24088 return Sb(
24089 ((19077 * a) >> 8) - ((6419 * b) >> 8) - ((13320 * c) >> 8) + 8708
24090 );
24091 }
24092 function Pa(a, b) {
24093 return Sb(((19077 * a) >> 8) + ((33050 * b) >> 8) - 17685);
24094 }
24095 function Ga(a, b, c, d, e) {
24096 d[e + 0] = bb(a, c);
24097 d[e + 1] = nb(a, b, c);
24098 d[e + 2] = Pa(a, b);
24099 }
24100 function Tb(a, b, c, d, e) {
24101 d[e + 0] = Pa(a, b);
24102 d[e + 1] = nb(a, b, c);
24103 d[e + 2] = bb(a, c);
24104 }
24105 function sd(a, b, c, d, e) {
24106 var f = nb(a, b, c);
24107 b = ((f << 3) & 224) | (Pa(a, b) >> 3);
24108 d[e + 0] = (bb(a, c) & 248) | (f >> 5);
24109 d[e + 1] = b;
24110 }
24111 function td(a, b, c, d, e) {
24112 var f = (Pa(a, b) & 240) | 15;
24113 d[e + 0] = (bb(a, c) & 240) | (nb(a, b, c) >> 4);
24114 d[e + 1] = f;
24115 }
24116 function ud(a, b, c, d, e) {
24117 d[e + 0] = 255;
24118 Ga(a, b, c, d, e + 1);
24119 }
24120 function vd(a, b, c, d, e) {
24121 Tb(a, b, c, d, e);
24122 d[e + 3] = 255;
24123 }
24124 function wd(a, b, c, d, e) {
24125 Ga(a, b, c, d, e);
24126 d[e + 3] = 255;
24127 }
24128 function ga(a, b) {
24129 return 0 > a ? 0 : a > b ? b : a;
24130 }
24131 function la(a, b, c) {
24132 self[a] = function(a, e, f, g, h, k, l, m, n) {
24133 for (var d = m + (n & -2) * c; m != d; )
24134 b(a[e + 0], f[g + 0], h[k + 0], l, m),
24135 b(a[e + 1], f[g + 0], h[k + 0], l, m + c),
24136 (e += 2),
24137 ++g,
24138 ++k,
24139 (m += 2 * c);
24140 n & 1 && b(a[e + 0], f[g + 0], h[k + 0], l, m);
24141 };
24142 }
24143 function xd(a, b, c) {
24144 return 0 == c ? (0 == a ? (0 == b ? 6 : 5) : 0 == b ? 4 : 0) : c;
24145 }
24146 function yd(a, b, c, d, e) {
24147 switch (a >>> 30) {
24148 case 3:
24149 Za(b, c, d, e, 0);
24150 break;
24151 case 2:
24152 fd(b, c, d, e);
24153 break;
24154 case 1:
24155 pa(b, c, d, e);
24156 }
24157 }
24158 function Oc(a, b) {
24159 var c,
24160 d,
24161 e = b.M,
24162 f = b.Nb,
24163 g = a.oc,
24164 h = a.pc + 40,
24165 k = a.oc,
24166 l = a.pc + 584,
24167 m = a.oc,
24168 n = a.pc + 600;
24169 for (c = 0; 16 > c; ++c) g[h + 32 * c - 1] = 129;
24170 for (c = 0; 8 > c; ++c)
24171 (k[l + 32 * c - 1] = 129), (m[n + 32 * c - 1] = 129);
24172 0 < e
24173 ? (g[h - 1 - 32] = k[l - 1 - 32] = m[n - 1 - 32] = 129)
24174 : (M(g, h - 32 - 1, 127, 21),
24175 M(k, l - 32 - 1, 127, 9),
24176 M(m, n - 32 - 1, 127, 9));
24177 for (d = 0; d < a.za; ++d) {
24178 var r = b.ya[b.aa + d];
24179 if (0 < d) {
24180 for (c = -1; 16 > c; ++c) I(g, h + 32 * c - 4, g, h + 32 * c + 12, 4);
24181 for (c = -1; 8 > c; ++c)
24182 I(k, l + 32 * c - 4, k, l + 32 * c + 4, 4),
24183 I(m, n + 32 * c - 4, m, n + 32 * c + 4, 4);
24184 }
24185 var q = a.Gd,
24186 t = a.Hd + d,
24187 v = r.ad,
24188 p = r.Hc;
24189 0 < e &&
24190 (I(g, h - 32, q[t].y, 0, 16),
24191 I(k, l - 32, q[t].f, 0, 8),
24192 I(m, n - 32, q[t].ea, 0, 8));
24193 if (r.Za) {
24194 var u = g;
24195 var w = h - 32 + 16;
24196 0 < e &&
24197 (d >= a.za - 1
24198 ? M(u, w, q[t].y[15], 4)
24199 : I(u, w, q[t + 1].y, 0, 4));
24200 for (c = 0; 4 > c; c++)
24201 u[w + 128 + c] = u[w + 256 + c] = u[w + 384 + c] = u[w + 0 + c];
24202 for (c = 0; 16 > c; ++c, p <<= 2)
24203 (u = g), (w = h + zd[c]), W[r.Ob[c]](u, w), yd(p, v, 16 * +c, u, w);
24204 } else if (((u = xd(d, e, r.Ob[0])), Y[u](g, h), 0 != p))
24205 for (c = 0; 16 > c; ++c, p <<= 2) yd(p, v, 16 * +c, g, h + zd[c]);
24206 c = r.Gc;
24207 u = xd(d, e, r.Dd);
24208 ka[u](k, l);
24209 ka[u](m, n);
24210 r = c >> 0;
24211 p = v;
24212 u = k;
24213 w = l;
24214 r & 255 && (r & 170 ? Nb(p, 256, u, w) : Ob(p, 256, u, w));
24215 c >>= 8;
24216 r = m;
24217 p = n;
24218 c & 255 && (c & 170 ? Nb(v, 320, r, p) : Ob(v, 320, r, p));
24219 e < a.Ub - 1 &&
24220 (I(q[t].y, 0, g, h + 480, 16),
24221 I(q[t].f, 0, k, l + 224, 8),
24222 I(q[t].ea, 0, m, n + 224, 8));
24223 c = 8 * f * a.B;
24224 q = a.sa;
24225 t = a.ta + 16 * d + 16 * f * a.R;
24226 v = a.qa;
24227 r = a.ra + 8 * d + c;
24228 p = a.Ha;
24229 u = a.Ia + 8 * d + c;
24230 for (c = 0; 16 > c; ++c) I(q, t + c * a.R, g, h + 32 * c, 16);
24231 for (c = 0; 8 > c; ++c)
24232 I(v, r + c * a.B, k, l + 32 * c, 8),
24233 I(p, u + c * a.B, m, n + 32 * c, 8);
24234 }
24235 }
24236 function Ad(a, b, c, d, e, f, g, h, k) {
24237 var l = [0],
24238 m = [0],
24239 n = 0,
24240 r = null != k ? k.kd : 0,
24241 q = null != k ? k : new md();
24242 if (null == a || 12 > c) return 7;
24243 q.data = a;
24244 q.w = b;
24245 q.ha = c;
24246 b = [b];
24247 c = [c];
24248 q.gb = [q.gb];
24249 a: {
24250 var t = b;
24251 var v = c;
24252 var p = q.gb;
24253 x(null != a);
24254 x(null != v);
24255 x(null != p);
24256 p[0] = 0;
24257 if (12 <= v[0] && !fa(a, t[0], "RIFF")) {
24258 if (fa(a, t[0] + 8, "WEBP")) {
24259 p = 3;
24260 break a;
24261 }
24262 var u = Ha(a, t[0] + 4);
24263 if (12 > u || 4294967286 < u) {
24264 p = 3;
24265 break a;
24266 }
24267 if (r && u > v[0] - 8) {
24268 p = 7;
24269 break a;
24270 }
24271 p[0] = u;
24272 t[0] += 12;
24273 v[0] -= 12;
24274 }
24275 p = 0;
24276 }
24277 if (0 != p) return p;
24278 u = 0 < q.gb[0];
24279 for (c = c[0]; ; ) {
24280 t = [0];
24281 n = [n];
24282 a: {
24283 var w = a;
24284 v = b;
24285 p = c;
24286 var y = n,
24287 A = l,
24288 z = m,
24289 B = t;
24290 y[0] = 0;
24291 if (8 > p[0]) p = 7;
24292 else {
24293 if (!fa(w, v[0], "VP8X")) {
24294 if (10 != Ha(w, v[0] + 4)) {
24295 p = 3;
24296 break a;
24297 }
24298 if (18 > p[0]) {
24299 p = 7;
24300 break a;
24301 }
24302 var C = Ha(w, v[0] + 8);
24303 var D = 1 + Yb(w, v[0] + 12);
24304 w = 1 + Yb(w, v[0] + 15);
24305 if (2147483648 <= D * w) {
24306 p = 3;
24307 break a;
24308 }
24309 null != B && (B[0] = C);
24310 null != A && (A[0] = D);
24311 null != z && (z[0] = w);
24312 v[0] += 18;
24313 p[0] -= 18;
24314 y[0] = 1;
24315 }
24316 p = 0;
24317 }
24318 }
24319 n = n[0];
24320 t = t[0];
24321 if (0 != p) return p;
24322 v = !!(t & 2);
24323 if (!u && n) return 3;
24324 null != f && (f[0] = !!(t & 16));
24325 null != g && (g[0] = v);
24326 null != h && (h[0] = 0);
24327 g = l[0];
24328 t = m[0];
24329 if (n && v && null == k) {
24330 p = 0;
24331 break;
24332 }
24333 if (4 > c) {
24334 p = 7;
24335 break;
24336 }
24337 if ((u && n) || (!u && !n && !fa(a, b[0], "ALPH"))) {
24338 c = [c];
24339 q.na = [q.na];
24340 q.P = [q.P];
24341 q.Sa = [q.Sa];
24342 a: {
24343 C = a;
24344 p = b;
24345 u = c;
24346 var y = q.gb,
24347 A = q.na,
24348 z = q.P,
24349 B = q.Sa;
24350 D = 22;
24351 x(null != C);
24352 x(null != u);
24353 w = p[0];
24354 var F = u[0];
24355 x(null != A);
24356 x(null != B);
24357 A[0] = null;
24358 z[0] = null;
24359 for (B[0] = 0; ; ) {
24360 p[0] = w;
24361 u[0] = F;
24362 if (8 > F) {
24363 p = 7;
24364 break a;
24365 }
24366 var G = Ha(C, w + 4);
24367 if (4294967286 < G) {
24368 p = 3;
24369 break a;
24370 }
24371 var H = (8 + G + 1) & -2;
24372 D += H;
24373 if (0 < y && D > y) {
24374 p = 3;
24375 break a;
24376 }
24377 if (!fa(C, w, "VP8 ") || !fa(C, w, "VP8L")) {
24378 p = 0;
24379 break a;
24380 }
24381 if (F[0] < H) {
24382 p = 7;
24383 break a;
24384 }
24385 fa(C, w, "ALPH") || ((A[0] = C), (z[0] = w + 8), (B[0] = G));
24386 w += H;
24387 F -= H;
24388 }
24389 }
24390 c = c[0];
24391 q.na = q.na[0];
24392 q.P = q.P[0];
24393 q.Sa = q.Sa[0];
24394 if (0 != p) break;
24395 }
24396 c = [c];
24397 q.Ja = [q.Ja];
24398 q.xa = [q.xa];
24399 a: if (
24400 ((y = a),
24401 (p = b),
24402 (u = c),
24403 (A = q.gb[0]),
24404 (z = q.Ja),
24405 (B = q.xa),
24406 (C = p[0]),
24407 (w = !fa(y, C, "VP8 ")),
24408 (D = !fa(y, C, "VP8L")),
24409 x(null != y),
24410 x(null != u),
24411 x(null != z),
24412 x(null != B),
24413 8 > u[0])
24414 )
24415 p = 7;
24416 else {
24417 if (w || D) {
24418 y = Ha(y, C + 4);
24419 if (12 <= A && y > A - 12) {
24420 p = 3;
24421 break a;
24422 }
24423 if (r && y > u[0] - 8) {
24424 p = 7;
24425 break a;
24426 }
24427 z[0] = y;
24428 p[0] += 8;
24429 u[0] -= 8;
24430 B[0] = D;
24431 } else
24432 (B[0] = 5 <= u[0] && 47 == y[C + 0] && !(y[C + 4] >> 5)),
24433 (z[0] = u[0]);
24434 p = 0;
24435 }
24436 c = c[0];
24437 q.Ja = q.Ja[0];
24438 q.xa = q.xa[0];
24439 b = b[0];
24440 if (0 != p) break;
24441 if (4294967286 < q.Ja) return 3;
24442 null == h || v || (h[0] = q.xa ? 2 : 1);
24443 g = [g];
24444 t = [t];
24445 if (q.xa) {
24446 if (5 > c) {
24447 p = 7;
24448 break;
24449 }
24450 h = g;
24451 r = t;
24452 v = f;
24453 null == a || 5 > c
24454 ? (a = 0)
24455 : 5 <= c && 47 == a[b + 0] && !(a[b + 4] >> 5)
24456 ? ((u = [0]),
24457 (y = [0]),
24458 (A = [0]),
24459 (z = new Ra()),
24460 cb(z, a, b, c),
24461 mc(z, u, y, A)
24462 ? (null != h && (h[0] = u[0]),
24463 null != r && (r[0] = y[0]),
24464 null != v && (v[0] = A[0]),
24465 (a = 1))
24466 : (a = 0))
24467 : (a = 0);
24468 } else {
24469 if (10 > c) {
24470 p = 7;
24471 break;
24472 }
24473 h = t;
24474 null == a || 10 > c || !Jc(a, b + 3, c - 3)
24475 ? (a = 0)
24476 : ((r = a[b + 0] | (a[b + 1] << 8) | (a[b + 2] << 16)),
24477 (v = ((a[b + 7] << 8) | a[b + 6]) & 16383),
24478 (a = ((a[b + 9] << 8) | a[b + 8]) & 16383),
24479 r & 1 ||
24480 3 < ((r >> 1) & 7) ||
24481 !((r >> 4) & 1) ||
24482 r >> 5 >= q.Ja ||
24483 !v ||
24484 !a
24485 ? (a = 0)
24486 : (g && (g[0] = v), h && (h[0] = a), (a = 1)));
24487 }
24488 if (!a) return 3;
24489 g = g[0];
24490 t = t[0];
24491 if (n && (l[0] != g || m[0] != t)) return 3;
24492 null != k &&
24493 ((k[0] = q),
24494 (k.offset = b - k.w),
24495 x(4294967286 > b - k.w),
24496 x(k.offset == k.ha - c));
24497 break;
24498 }
24499 return 0 == p || (7 == p && n && null == k)
24500 ? (null != f && (f[0] |= null != q.na && 0 < q.na.length),
24501 null != d && (d[0] = g),
24502 null != e && (e[0] = t),
24503 0)
24504 : p;
24505 }
24506 function hc(a, b, c) {
24507 var d = b.width,
24508 e = b.height,
24509 f = 0,
24510 g = 0,
24511 h = d,
24512 k = e;
24513 b.Da = null != a && 0 < a.Da;
24514 if (
24515 b.Da &&
24516 ((h = a.cd),
24517 (k = a.bd),
24518 (f = a.v),
24519 (g = a.j),
24520 11 > c || ((f &= -2), (g &= -2)),
24521 0 > f || 0 > g || 0 >= h || 0 >= k || f + h > d || g + k > e)
24522 )
24523 return 0;
24524 b.v = f;
24525 b.j = g;
24526 b.va = f + h;
24527 b.o = g + k;
24528 b.U = h;
24529 b.T = k;
24530 b.da = null != a && 0 < a.da;
24531 if (b.da) {
24532 c = [a.ib];
24533 f = [a.hb];
24534 if (!bc(h, k, c, f)) return 0;
24535 b.ib = c[0];
24536 b.hb = f[0];
24537 }
24538 b.ob = null != a && a.ob;
24539 b.Kb = null == a || !a.Sd;
24540 b.da && ((b.ob = b.ib < (3 * d) / 4 && b.hb < (3 * e) / 4), (b.Kb = 0));
24541 return 1;
24542 }
24543 function Bd(a) {
24544 if (null == a) return 2;
24545 if (11 > a.S) {
24546 var b = a.f.RGBA;
24547 b.fb += (a.height - 1) * b.A;
24548 b.A = -b.A;
24549 } else
24550 (b = a.f.kb),
24551 (a = a.height),
24552 (b.O += (a - 1) * b.fa),
24553 (b.fa = -b.fa),
24554 (b.N += ((a - 1) >> 1) * b.Ab),
24555 (b.Ab = -b.Ab),
24556 (b.W += ((a - 1) >> 1) * b.Db),
24557 (b.Db = -b.Db),
24558 null != b.F && ((b.J += (a - 1) * b.lb), (b.lb = -b.lb));
24559 return 0;
24560 }
24561 function Cd(a, b, c, d) {
24562 if (null == d || 0 >= a || 0 >= b) return 2;
24563 if (null != c) {
24564 if (c.Da) {
24565 var e = c.cd,
24566 f = c.bd,
24567 g = c.v & -2,
24568 h = c.j & -2;
24569 if (0 > g || 0 > h || 0 >= e || 0 >= f || g + e > a || h + f > b)
24570 return 2;
24571 a = e;
24572 b = f;
24573 }
24574 if (c.da) {
24575 e = [c.ib];
24576 f = [c.hb];
24577 if (!bc(a, b, e, f)) return 2;
24578 a = e[0];
24579 b = f[0];
24580 }
24581 }
24582 d.width = a;
24583 d.height = b;
24584 a: {
24585 var k = d.width;
24586 var l = d.height;
24587 a = d.S;
24588 if (0 >= k || 0 >= l || !(a >= Ca && 13 > a)) a = 2;
24589 else {
24590 if (0 >= d.Rd && null == d.sd) {
24591 var g = (f = e = b = 0),
24592 h = k * Dd[a],
24593 m = h * l;
24594 11 > a ||
24595 ((b = (k + 1) / 2),
24596 (f = ((l + 1) / 2) * b),
24597 12 == a && ((e = k), (g = e * l)));
24598 l = V(m + 2 * f + g);
24599 if (null == l) {
24600 a = 1;
24601 break a;
24602 }
24603 d.sd = l;
24604 11 > a
24605 ? ((k = d.f.RGBA),
24606 (k.eb = l),
24607 (k.fb = 0),
24608 (k.A = h),
24609 (k.size = m))
24610 : ((k = d.f.kb),
24611 (k.y = l),
24612 (k.O = 0),
24613 (k.fa = h),
24614 (k.Fd = m),
24615 (k.f = l),
24616 (k.N = 0 + m),
24617 (k.Ab = b),
24618 (k.Cd = f),
24619 (k.ea = l),
24620 (k.W = 0 + m + f),
24621 (k.Db = b),
24622 (k.Ed = f),
24623 12 == a && ((k.F = l), (k.J = 0 + m + 2 * f)),
24624 (k.Tc = g),
24625 (k.lb = e));
24626 }
24627 b = 1;
24628 e = d.S;
24629 f = d.width;
24630 g = d.height;
24631 if (e >= Ca && 13 > e)
24632 if (11 > e)
24633 (a = d.f.RGBA),
24634 (h = Math.abs(a.A)),
24635 (b &= h * (g - 1) + f <= a.size),
24636 (b &= h >= f * Dd[e]),
24637 (b &= null != a.eb);
24638 else {
24639 a = d.f.kb;
24640 h = (f + 1) / 2;
24641 m = (g + 1) / 2;
24642 k = Math.abs(a.fa);
24643 var l = Math.abs(a.Ab),
24644 n = Math.abs(a.Db),
24645 r = Math.abs(a.lb),
24646 q = r * (g - 1) + f;
24647 b &= k * (g - 1) + f <= a.Fd;
24648 b &= l * (m - 1) + h <= a.Cd;
24649 b &= n * (m - 1) + h <= a.Ed;
24650 b = b & (k >= f) & (l >= h) & (n >= h);
24651 b &= null != a.y;
24652 b &= null != a.f;
24653 b &= null != a.ea;
24654 12 == e && ((b &= r >= f), (b &= q <= a.Tc), (b &= null != a.F));
24655 }
24656 else b = 0;
24657 a = b ? 0 : 2;
24658 }
24659 }
24660 if (0 != a) return a;
24661 null != c && c.fd && (a = Bd(d));
24662 return a;
24663 }
24664 var xb = 64,
24665 Hd = [
24666 0,
24667 1,
24668 3,
24669 7,
24670 15,
24671 31,
24672 63,
24673 127,
24674 255,
24675 511,
24676 1023,
24677 2047,
24678 4095,
24679 8191,
24680 16383,
24681 32767,
24682 65535,
24683 131071,
24684 262143,
24685 524287,
24686 1048575,
24687 2097151,
24688 4194303,
24689 8388607,
24690 16777215
24691 ],
24692 Gd = 24,
24693 ob = 32,
24694 Xb = 8,
24695 Id = [
24696 0,
24697 0,
24698 1,
24699 1,
24700 2,
24701 2,
24702 2,
24703 2,
24704 3,
24705 3,
24706 3,
24707 3,
24708 3,
24709 3,
24710 3,
24711 3,
24712 4,
24713 4,
24714 4,
24715 4,
24716 4,
24717 4,
24718 4,
24719 4,
24720 4,
24721 4,
24722 4,
24723 4,
24724 4,
24725 4,
24726 4,
24727 4,
24728 5,
24729 5,
24730 5,
24731 5,
24732 5,
24733 5,
24734 5,
24735 5,
24736 5,
24737 5,
24738 5,
24739 5,
24740 5,
24741 5,
24742 5,
24743 5,
24744 5,
24745 5,
24746 5,
24747 5,
24748 5,
24749 5,
24750 5,
24751 5,
24752 5,
24753 5,
24754 5,
24755 5,
24756 5,
24757 5,
24758 5,
24759 5,
24760 6,
24761 6,
24762 6,
24763 6,
24764 6,
24765 6,
24766 6,
24767 6,
24768 6,
24769 6,
24770 6,
24771 6,
24772 6,
24773 6,
24774 6,
24775 6,
24776 6,
24777 6,
24778 6,
24779 6,
24780 6,
24781 6,
24782 6,
24783 6,
24784 6,
24785 6,
24786 6,
24787 6,
24788 6,
24789 6,
24790 6,
24791 6,
24792 6,
24793 6,
24794 6,
24795 6,
24796 6,
24797 6,
24798 6,
24799 6,
24800 6,
24801 6,
24802 6,
24803 6,
24804 6,
24805 6,
24806 6,
24807 6,
24808 6,
24809 6,
24810 6,
24811 6,
24812 6,
24813 6,
24814 6,
24815 6,
24816 6,
24817 6,
24818 6,
24819 6,
24820 6,
24821 6,
24822 6,
24823 6,
24824 7,
24825 7,
24826 7,
24827 7,
24828 7,
24829 7,
24830 7,
24831 7,
24832 7,
24833 7,
24834 7,
24835 7,
24836 7,
24837 7,
24838 7,
24839 7,
24840 7,
24841 7,
24842 7,
24843 7,
24844 7,
24845 7,
24846 7,
24847 7,
24848 7,
24849 7,
24850 7,
24851 7,
24852 7,
24853 7,
24854 7,
24855 7,
24856 7,
24857 7,
24858 7,
24859 7,
24860 7,
24861 7,
24862 7,
24863 7,
24864 7,
24865 7,
24866 7,
24867 7,
24868 7,
24869 7,
24870 7,
24871 7,
24872 7,
24873 7,
24874 7,
24875 7,
24876 7,
24877 7,
24878 7,
24879 7,
24880 7,
24881 7,
24882 7,
24883 7,
24884 7,
24885 7,
24886 7,
24887 7,
24888 7,
24889 7,
24890 7,
24891 7,
24892 7,
24893 7,
24894 7,
24895 7,
24896 7,
24897 7,
24898 7,
24899 7,
24900 7,
24901 7,
24902 7,
24903 7,
24904 7,
24905 7,
24906 7,
24907 7,
24908 7,
24909 7,
24910 7,
24911 7,
24912 7,
24913 7,
24914 7,
24915 7,
24916 7,
24917 7,
24918 7,
24919 7,
24920 7,
24921 7,
24922 7,
24923 7,
24924 7,
24925 7,
24926 7,
24927 7,
24928 7,
24929 7,
24930 7,
24931 7,
24932 7,
24933 7,
24934 7,
24935 7,
24936 7,
24937 7,
24938 7,
24939 7,
24940 7,
24941 7,
24942 7,
24943 7,
24944 7,
24945 7,
24946 7,
24947 7,
24948 7,
24949 7,
24950 7,
24951 7
24952 ];
24953 X("Predictor0", "PredictorAdd0");
24954 self.Predictor0 = function() {
24955 return 4278190080;
24956 };
24957 self.Predictor1 = function(a) {
24958 return a;
24959 };
24960 self.Predictor2 = function(a, b, c) {
24961 return b[c + 0];
24962 };
24963 self.Predictor3 = function(a, b, c) {
24964 return b[c + 1];
24965 };
24966 self.Predictor4 = function(a, b, c) {
24967 return b[c - 1];
24968 };
24969 self.Predictor5 = function(a, b, c) {
24970 return aa(aa(a, b[c + 1]), b[c + 0]);
24971 };
24972 self.Predictor6 = function(a, b, c) {
24973 return aa(a, b[c - 1]);
24974 };
24975 self.Predictor7 = function(a, b, c) {
24976 return aa(a, b[c + 0]);
24977 };
24978 self.Predictor8 = function(a, b, c) {
24979 return aa(b[c - 1], b[c + 0]);
24980 };
24981 self.Predictor9 = function(a, b, c) {
24982 return aa(b[c + 0], b[c + 1]);
24983 };
24984 self.Predictor10 = function(a, b, c) {
24985 return aa(aa(a, b[c - 1]), aa(b[c + 0], b[c + 1]));
24986 };
24987 self.Predictor11 = function(a, b, c) {
24988 var d = b[c + 0];
24989 b = b[c - 1];
24990 return 0 >=
24991 Ia((d >> 24) & 255, (a >> 24) & 255, (b >> 24) & 255) +
24992 Ia((d >> 16) & 255, (a >> 16) & 255, (b >> 16) & 255) +
24993 Ia((d >> 8) & 255, (a >> 8) & 255, (b >> 8) & 255) +
24994 Ia(d & 255, a & 255, b & 255)
24995 ? d
24996 : a;
24997 };
24998 self.Predictor12 = function(a, b, c) {
24999 var d = b[c + 0];
25000 b = b[c - 1];
25001 return (
25002 ((sa(((a >> 24) & 255) + ((d >> 24) & 255) - ((b >> 24) & 255)) << 24) |
25003 (sa(((a >> 16) & 255) + ((d >> 16) & 255) - ((b >> 16) & 255)) <<
25004 16) |
25005 (sa(((a >> 8) & 255) + ((d >> 8) & 255) - ((b >> 8) & 255)) << 8) |
25006 sa((a & 255) + (d & 255) - (b & 255))) >>>
25007 0
25008 );
25009 };
25010 self.Predictor13 = function(a, b, c) {
25011 var d = b[c - 1];
25012 a = aa(a, b[c + 0]);
25013 return (
25014 ((eb((a >> 24) & 255, (d >> 24) & 255) << 24) |
25015 (eb((a >> 16) & 255, (d >> 16) & 255) << 16) |
25016 (eb((a >> 8) & 255, (d >> 8) & 255) << 8) |
25017 eb((a >> 0) & 255, (d >> 0) & 255)) >>>
25018 0
25019 );
25020 };
25021 var ee = self.PredictorAdd0;
25022 self.PredictorAdd1 = cc;
25023 X("Predictor2", "PredictorAdd2");
25024 X("Predictor3", "PredictorAdd3");
25025 X("Predictor4", "PredictorAdd4");
25026 X("Predictor5", "PredictorAdd5");
25027 X("Predictor6", "PredictorAdd6");
25028 X("Predictor7", "PredictorAdd7");
25029 X("Predictor8", "PredictorAdd8");
25030 X("Predictor9", "PredictorAdd9");
25031 X("Predictor10", "PredictorAdd10");
25032 X("Predictor11", "PredictorAdd11");
25033 X("Predictor12", "PredictorAdd12");
25034 X("Predictor13", "PredictorAdd13");
25035 var fe = self.PredictorAdd2;
25036 ec(
25037 "ColorIndexInverseTransform",
25038 "MapARGB",
25039 "32b",
25040 function(a) {
25041 return (a >> 8) & 255;
25042 },
25043 function(a) {
25044 return a;
25045 }
25046 );
25047 ec(
25048 "VP8LColorIndexInverseTransformAlpha",
25049 "MapAlpha",
25050 "8b",
25051 function(a) {
25052 return a;
25053 },
25054 function(a) {
25055 return (a >> 8) & 255;
25056 }
25057 );
25058 var rc = self.ColorIndexInverseTransform,
25059 ke = self.MapARGB,
25060 he = self.VP8LColorIndexInverseTransformAlpha,
25061 le = self.MapAlpha,
25062 pc,
25063 qc = (self.VP8LPredictorsAdd = []);
25064 qc.length = 16;
25065 (self.VP8LPredictors = []).length = 16;
25066 (self.VP8LPredictorsAdd_C = []).length = 16;
25067 (self.VP8LPredictors_C = []).length = 16;
25068 var Fb,
25069 sc,
25070 Gb,
25071 Hb,
25072 xc,
25073 uc,
25074 bd = V(511),
25075 cd = V(2041),
25076 dd = V(225),
25077 ed = V(767),
25078 ad = 0,
25079 Qb = cd,
25080 mb = dd,
25081 R = ed,
25082 U = bd,
25083 Ca = 0,
25084 Ua = 1,
25085 tc = 2,
25086 Va = 3,
25087 ya = 4,
25088 Db = 5,
25089 wc = 6,
25090 zb = 7,
25091 Ab = 8,
25092 Ja = 9,
25093 Bb = 10,
25094 pe = [2, 3, 7],
25095 oe = [3, 3, 11],
25096 Dc = [280, 256, 256, 256, 40],
25097 qe = [0, 1, 1, 1, 0],
25098 ne = [17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
25099 de = [
25100 24,
25101 7,
25102 23,
25103 25,
25104 40,
25105 6,
25106 39,
25107 41,
25108 22,
25109 26,
25110 38,
25111 42,
25112 56,
25113 5,
25114 55,
25115 57,
25116 21,
25117 27,
25118 54,
25119 58,
25120 37,
25121 43,
25122 72,
25123 4,
25124 71,
25125 73,
25126 20,
25127 28,
25128 53,
25129 59,
25130 70,
25131 74,
25132 36,
25133 44,
25134 88,
25135 69,
25136 75,
25137 52,
25138 60,
25139 3,
25140 87,
25141 89,
25142 19,
25143 29,
25144 86,
25145 90,
25146 35,
25147 45,
25148 68,
25149 76,
25150 85,
25151 91,
25152 51,
25153 61,
25154 104,
25155 2,
25156 103,
25157 105,
25158 18,
25159 30,
25160 102,
25161 106,
25162 34,
25163 46,
25164 84,
25165 92,
25166 67,
25167 77,
25168 101,
25169 107,
25170 50,
25171 62,
25172 120,
25173 1,
25174 119,
25175 121,
25176 83,
25177 93,
25178 17,
25179 31,
25180 100,
25181 108,
25182 66,
25183 78,
25184 118,
25185 122,
25186 33,
25187 47,
25188 117,
25189 123,
25190 49,
25191 63,
25192 99,
25193 109,
25194 82,
25195 94,
25196 0,
25197 116,
25198 124,
25199 65,
25200 79,
25201 16,
25202 32,
25203 98,
25204 110,
25205 48,
25206 115,
25207 125,
25208 81,
25209 95,
25210 64,
25211 114,
25212 126,
25213 97,
25214 111,
25215 80,
25216 113,
25217 127,
25218 96,
25219 112
25220 ],
25221 me = [
25222 2954,
25223 2956,
25224 2958,
25225 2962,
25226 2970,
25227 2986,
25228 3018,
25229 3082,
25230 3212,
25231 3468,
25232 3980,
25233 5004
25234 ],
25235 ie = 8,
25236 Lb = [
25237 4,
25238 5,
25239 6,
25240 7,
25241 8,
25242 9,
25243 10,
25244 10,
25245 11,
25246 12,
25247 13,
25248 14,
25249 15,
25250 16,
25251 17,
25252 17,
25253 18,
25254 19,
25255 20,
25256 20,
25257 21,
25258 21,
25259 22,
25260 22,
25261 23,
25262 23,
25263 24,
25264 25,
25265 25,
25266 26,
25267 27,
25268 28,
25269 29,
25270 30,
25271 31,
25272 32,
25273 33,
25274 34,
25275 35,
25276 36,
25277 37,
25278 37,
25279 38,
25280 39,
25281 40,
25282 41,
25283 42,
25284 43,
25285 44,
25286 45,
25287 46,
25288 46,
25289 47,
25290 48,
25291 49,
25292 50,
25293 51,
25294 52,
25295 53,
25296 54,
25297 55,
25298 56,
25299 57,
25300 58,
25301 59,
25302 60,
25303 61,
25304 62,
25305 63,
25306 64,
25307 65,
25308 66,
25309 67,
25310 68,
25311 69,
25312 70,
25313 71,
25314 72,
25315 73,
25316 74,
25317 75,
25318 76,
25319 76,
25320 77,
25321 78,
25322 79,
25323 80,
25324 81,
25325 82,
25326 83,
25327 84,
25328 85,
25329 86,
25330 87,
25331 88,
25332 89,
25333 91,
25334 93,
25335 95,
25336 96,
25337 98,
25338 100,
25339 101,
25340 102,
25341 104,
25342 106,
25343 108,
25344 110,
25345 112,
25346 114,
25347 116,
25348 118,
25349 122,
25350 124,
25351 126,
25352 128,
25353 130,
25354 132,
25355 134,
25356 136,
25357 138,
25358 140,
25359 143,
25360 145,
25361 148,
25362 151,
25363 154,
25364 157
25365 ],
25366 Mb = [
25367 4,
25368 5,
25369 6,
25370 7,
25371 8,
25372 9,
25373 10,
25374 11,
25375 12,
25376 13,
25377 14,
25378 15,
25379 16,
25380 17,
25381 18,
25382 19,
25383 20,
25384 21,
25385 22,
25386 23,
25387 24,
25388 25,
25389 26,
25390 27,
25391 28,
25392 29,
25393 30,
25394 31,
25395 32,
25396 33,
25397 34,
25398 35,
25399 36,
25400 37,
25401 38,
25402 39,
25403 40,
25404 41,
25405 42,
25406 43,
25407 44,
25408 45,
25409 46,
25410 47,
25411 48,
25412 49,
25413 50,
25414 51,
25415 52,
25416 53,
25417 54,
25418 55,
25419 56,
25420 57,
25421 58,
25422 60,
25423 62,
25424 64,
25425 66,
25426 68,
25427 70,
25428 72,
25429 74,
25430 76,
25431 78,
25432 80,
25433 82,
25434 84,
25435 86,
25436 88,
25437 90,
25438 92,
25439 94,
25440 96,
25441 98,
25442 100,
25443 102,
25444 104,
25445 106,
25446 108,
25447 110,
25448 112,
25449 114,
25450 116,
25451 119,
25452 122,
25453 125,
25454 128,
25455 131,
25456 134,
25457 137,
25458 140,
25459 143,
25460 146,
25461 149,
25462 152,
25463 155,
25464 158,
25465 161,
25466 164,
25467 167,
25468 170,
25469 173,
25470 177,
25471 181,
25472 185,
25473 189,
25474 193,
25475 197,
25476 201,
25477 205,
25478 209,
25479 213,
25480 217,
25481 221,
25482 225,
25483 229,
25484 234,
25485 239,
25486 245,
25487 249,
25488 254,
25489 259,
25490 264,
25491 269,
25492 274,
25493 279,
25494 284
25495 ],
25496 oa = null,
25497 He = [
25498 [173, 148, 140, 0],
25499 [176, 155, 140, 135, 0],
25500 [180, 157, 141, 134, 130, 0],
25501 [254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0]
25502 ],
25503 Ie = [0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15],
25504 Mc = [-0, 1, -1, 2, -2, 3, 4, 6, -3, 5, -4, -5, -6, 7, -7, 8, -8, -9],
25505 Fe = [
25506 [
25507 [
25508 [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128],
25509 [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128],
25510 [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128]
25511 ],
25512 [
25513 [253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128],
25514 [189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128],
25515 [106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128]
25516 ],
25517 [
25518 [1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128],
25519 [181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128],
25520 [78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128]
25521 ],
25522 [
25523 [1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128],
25524 [184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128],
25525 [77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128]
25526 ],
25527 [
25528 [1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128],
25529 [170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128],
25530 [37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128]
25531 ],
25532 [
25533 [1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128],
25534 [207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128],
25535 [102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128]
25536 ],
25537 [
25538 [1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128],
25539 [177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128],
25540 [80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128]
25541 ],
25542 [
25543 [1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128],
25544 [246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128],
25545 [255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128]
25546 ]
25547 ],
25548 [
25549 [
25550 [198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62],
25551 [131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1],
25552 [68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128]
25553 ],
25554 [
25555 [1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128],
25556 [184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128],
25557 [81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128]
25558 ],
25559 [
25560 [1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128],
25561 [99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128],
25562 [23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128]
25563 ],
25564 [
25565 [1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128],
25566 [109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128],
25567 [44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128]
25568 ],
25569 [
25570 [1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128],
25571 [94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128],
25572 [22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128]
25573 ],
25574 [
25575 [1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128],
25576 [124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128],
25577 [35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128]
25578 ],
25579 [
25580 [1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128],
25581 [121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128],
25582 [45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128]
25583 ],
25584 [
25585 [1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128],
25586 [203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128],
25587 [137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128]
25588 ]
25589 ],
25590 [
25591 [
25592 [253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128],
25593 [175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128],
25594 [73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128]
25595 ],
25596 [
25597 [1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128],
25598 [239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128],
25599 [155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128]
25600 ],
25601 [
25602 [1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128],
25603 [201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128],
25604 [69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128]
25605 ],
25606 [
25607 [1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128],
25608 [223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128],
25609 [141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128]
25610 ],
25611 [
25612 [1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128],
25613 [190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128],
25614 [149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128]
25615 ],
25616 [
25617 [1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128],
25618 [247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128],
25619 [240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128]
25620 ],
25621 [
25622 [1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128],
25623 [213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128],
25624 [55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128]
25625 ],
25626 [
25627 [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128],
25628 [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128],
25629 [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128]
25630 ]
25631 ],
25632 [
25633 [
25634 [202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255],
25635 [126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128],
25636 [61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128]
25637 ],
25638 [
25639 [1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128],
25640 [166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128],
25641 [39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128]
25642 ],
25643 [
25644 [1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128],
25645 [124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128],
25646 [24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128]
25647 ],
25648 [
25649 [1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128],
25650 [149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128],
25651 [28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128]
25652 ],
25653 [
25654 [1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128],
25655 [123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128],
25656 [20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128]
25657 ],
25658 [
25659 [1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128],
25660 [168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128],
25661 [47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128]
25662 ],
25663 [
25664 [1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128],
25665 [141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128],
25666 [42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128]
25667 ],
25668 [
25669 [1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128],
25670 [244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128],
25671 [238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128]
25672 ]
25673 ]
25674 ],
25675 Ke = [
25676 [
25677 [231, 120, 48, 89, 115, 113, 120, 152, 112],
25678 [152, 179, 64, 126, 170, 118, 46, 70, 95],
25679 [175, 69, 143, 80, 85, 82, 72, 155, 103],
25680 [56, 58, 10, 171, 218, 189, 17, 13, 152],
25681 [114, 26, 17, 163, 44, 195, 21, 10, 173],
25682 [121, 24, 80, 195, 26, 62, 44, 64, 85],
25683 [144, 71, 10, 38, 171, 213, 144, 34, 26],
25684 [170, 46, 55, 19, 136, 160, 33, 206, 71],
25685 [63, 20, 8, 114, 114, 208, 12, 9, 226],
25686 [81, 40, 11, 96, 182, 84, 29, 16, 36]
25687 ],
25688 [
25689 [134, 183, 89, 137, 98, 101, 106, 165, 148],
25690 [72, 187, 100, 130, 157, 111, 32, 75, 80],
25691 [66, 102, 167, 99, 74, 62, 40, 234, 128],
25692 [41, 53, 9, 178, 241, 141, 26, 8, 107],
25693 [74, 43, 26, 146, 73, 166, 49, 23, 157],
25694 [65, 38, 105, 160, 51, 52, 31, 115, 128],
25695 [104, 79, 12, 27, 217, 255, 87, 17, 7],
25696 [87, 68, 71, 44, 114, 51, 15, 186, 23],
25697 [47, 41, 14, 110, 182, 183, 21, 17, 194],
25698 [66, 45, 25, 102, 197, 189, 23, 18, 22]
25699 ],
25700 [
25701 [88, 88, 147, 150, 42, 46, 45, 196, 205],
25702 [43, 97, 183, 117, 85, 38, 35, 179, 61],
25703 [39, 53, 200, 87, 26, 21, 43, 232, 171],
25704 [56, 34, 51, 104, 114, 102, 29, 93, 77],
25705 [39, 28, 85, 171, 58, 165, 90, 98, 64],
25706 [34, 22, 116, 206, 23, 34, 43, 166, 73],
25707 [107, 54, 32, 26, 51, 1, 81, 43, 31],
25708 [68, 25, 106, 22, 64, 171, 36, 225, 114],
25709 [34, 19, 21, 102, 132, 188, 16, 76, 124],
25710 [62, 18, 78, 95, 85, 57, 50, 48, 51]
25711 ],
25712 [
25713 [193, 101, 35, 159, 215, 111, 89, 46, 111],
25714 [60, 148, 31, 172, 219, 228, 21, 18, 111],
25715 [112, 113, 77, 85, 179, 255, 38, 120, 114],
25716 [40, 42, 1, 196, 245, 209, 10, 25, 109],
25717 [88, 43, 29, 140, 166, 213, 37, 43, 154],
25718 [61, 63, 30, 155, 67, 45, 68, 1, 209],
25719 [100, 80, 8, 43, 154, 1, 51, 26, 71],
25720 [142, 78, 78, 16, 255, 128, 34, 197, 171],
25721 [41, 40, 5, 102, 211, 183, 4, 1, 221],
25722 [51, 50, 17, 168, 209, 192, 23, 25, 82]
25723 ],
25724 [
25725 [138, 31, 36, 171, 27, 166, 38, 44, 229],
25726 [67, 87, 58, 169, 82, 115, 26, 59, 179],
25727 [63, 59, 90, 180, 59, 166, 93, 73, 154],
25728 [40, 40, 21, 116, 143, 209, 34, 39, 175],
25729 [47, 15, 16, 183, 34, 223, 49, 45, 183],
25730 [46, 17, 33, 183, 6, 98, 15, 32, 183],
25731 [57, 46, 22, 24, 128, 1, 54, 17, 37],
25732 [65, 32, 73, 115, 28, 128, 23, 128, 205],
25733 [40, 3, 9, 115, 51, 192, 18, 6, 223],
25734 [87, 37, 9, 115, 59, 77, 64, 21, 47]
25735 ],
25736 [
25737 [104, 55, 44, 218, 9, 54, 53, 130, 226],
25738 [64, 90, 70, 205, 40, 41, 23, 26, 57],
25739 [54, 57, 112, 184, 5, 41, 38, 166, 213],
25740 [30, 34, 26, 133, 152, 116, 10, 32, 134],
25741 [39, 19, 53, 221, 26, 114, 32, 73, 255],
25742 [31, 9, 65, 234, 2, 15, 1, 118, 73],
25743 [75, 32, 12, 51, 192, 255, 160, 43, 51],
25744 [88, 31, 35, 67, 102, 85, 55, 186, 85],
25745 [56, 21, 23, 111, 59, 205, 45, 37, 192],
25746 [55, 38, 70, 124, 73, 102, 1, 34, 98]
25747 ],
25748 [
25749 [125, 98, 42, 88, 104, 85, 117, 175, 82],
25750 [95, 84, 53, 89, 128, 100, 113, 101, 45],
25751 [75, 79, 123, 47, 51, 128, 81, 171, 1],
25752 [57, 17, 5, 71, 102, 57, 53, 41, 49],
25753 [38, 33, 13, 121, 57, 73, 26, 1, 85],
25754 [41, 10, 67, 138, 77, 110, 90, 47, 114],
25755 [115, 21, 2, 10, 102, 255, 166, 23, 6],
25756 [101, 29, 16, 10, 85, 128, 101, 196, 26],
25757 [57, 18, 10, 102, 102, 213, 34, 20, 43],
25758 [117, 20, 15, 36, 163, 128, 68, 1, 26]
25759 ],
25760 [
25761 [102, 61, 71, 37, 34, 53, 31, 243, 192],
25762 [69, 60, 71, 38, 73, 119, 28, 222, 37],
25763 [68, 45, 128, 34, 1, 47, 11, 245, 171],
25764 [62, 17, 19, 70, 146, 85, 55, 62, 70],
25765 [37, 43, 37, 154, 100, 163, 85, 160, 1],
25766 [63, 9, 92, 136, 28, 64, 32, 201, 85],
25767 [75, 15, 9, 9, 64, 255, 184, 119, 16],
25768 [86, 6, 28, 5, 64, 255, 25, 248, 1],
25769 [56, 8, 17, 132, 137, 255, 55, 116, 128],
25770 [58, 15, 20, 82, 135, 57, 26, 121, 40]
25771 ],
25772 [
25773 [164, 50, 31, 137, 154, 133, 25, 35, 218],
25774 [51, 103, 44, 131, 131, 123, 31, 6, 158],
25775 [86, 40, 64, 135, 148, 224, 45, 183, 128],
25776 [22, 26, 17, 131, 240, 154, 14, 1, 209],
25777 [45, 16, 21, 91, 64, 222, 7, 1, 197],
25778 [56, 21, 39, 155, 60, 138, 23, 102, 213],
25779 [83, 12, 13, 54, 192, 255, 68, 47, 28],
25780 [85, 26, 85, 85, 128, 128, 32, 146, 171],
25781 [18, 11, 7, 63, 144, 171, 4, 4, 246],
25782 [35, 27, 10, 146, 174, 171, 12, 26, 128]
25783 ],
25784 [
25785 [190, 80, 35, 99, 180, 80, 126, 54, 45],
25786 [85, 126, 47, 87, 176, 51, 41, 20, 32],
25787 [101, 75, 128, 139, 118, 146, 116, 128, 85],
25788 [56, 41, 15, 176, 236, 85, 37, 9, 62],
25789 [71, 30, 17, 119, 118, 255, 17, 18, 138],
25790 [101, 38, 60, 138, 55, 70, 43, 26, 142],
25791 [146, 36, 19, 30, 171, 255, 97, 27, 20],
25792 [138, 45, 61, 62, 219, 1, 81, 188, 64],
25793 [32, 41, 20, 117, 151, 142, 20, 21, 163],
25794 [112, 19, 12, 61, 195, 128, 48, 4, 24]
25795 ]
25796 ],
25797 Ee = [
25798 [
25799 [
25800 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25801 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25802 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25803 ],
25804 [
25805 [176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25806 [223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255],
25807 [249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255]
25808 ],
25809 [
25810 [255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255],
25811 [234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25812 [253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25813 ],
25814 [
25815 [255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25816 [239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25817 [254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255]
25818 ],
25819 [
25820 [255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25821 [251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25822 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25823 ],
25824 [
25825 [255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25826 [251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25827 [254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255]
25828 ],
25829 [
25830 [255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255],
25831 [250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255],
25832 [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25833 ],
25834 [
25835 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25836 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25837 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25838 ]
25839 ],
25840 [
25841 [
25842 [217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25843 [225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255],
25844 [234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255]
25845 ],
25846 [
25847 [255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25848 [223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25849 [238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255]
25850 ],
25851 [
25852 [255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25853 [249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25854 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25855 ],
25856 [
25857 [255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25858 [247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25859 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25860 ],
25861 [
25862 [255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25863 [252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25864 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25865 ],
25866 [
25867 [255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25868 [253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25869 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25870 ],
25871 [
25872 [255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255],
25873 [250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25874 [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25875 ],
25876 [
25877 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25878 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25879 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25880 ]
25881 ],
25882 [
25883 [
25884 [186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255],
25885 [234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255],
25886 [251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255]
25887 ],
25888 [
25889 [255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25890 [236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25891 [251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255]
25892 ],
25893 [
25894 [255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25895 [254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25896 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25897 ],
25898 [
25899 [255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25900 [254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25901 [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25902 ],
25903 [
25904 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25905 [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25906 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25907 ],
25908 [
25909 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25910 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25911 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25912 ],
25913 [
25914 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25915 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25916 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25917 ],
25918 [
25919 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25920 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25921 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25922 ]
25923 ],
25924 [
25925 [
25926 [248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25927 [250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255],
25928 [248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255]
25929 ],
25930 [
25931 [255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255],
25932 [246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255],
25933 [252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255]
25934 ],
25935 [
25936 [255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255],
25937 [248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255],
25938 [253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255]
25939 ],
25940 [
25941 [255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25942 [245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25943 [253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255]
25944 ],
25945 [
25946 [255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255],
25947 [252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25948 [255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25949 ],
25950 [
25951 [255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25952 [249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255],
25953 [255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255]
25954 ],
25955 [
25956 [255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255],
25957 [250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25958 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25959 ],
25960 [
25961 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25962 [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
25963 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
25964 ]
25965 ]
25966 ],
25967 Ge = [0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0],
25968 Nc,
25969 Y = [],
25970 W = [],
25971 ka = [],
25972 Za,
25973 fd,
25974 Nb,
25975 pa,
25976 Ob,
25977 Xc,
25978 Tc,
25979 Yc,
25980 Uc,
25981 Zc,
25982 Vc,
25983 $c,
25984 Wc,
25985 Rc,
25986 Pc,
25987 Sc,
25988 Qc,
25989 re = 1,
25990 Cc = 2,
25991 ia = [],
25992 za,
25993 vc,
25994 fc,
25995 Fc,
25996 P = [];
25997 va("UpsampleRgbLinePair", Ga, 3);
25998 va("UpsampleBgrLinePair", Tb, 3);
25999 va("UpsampleRgbaLinePair", wd, 4);
26000 va("UpsampleBgraLinePair", vd, 4);
26001 va("UpsampleArgbLinePair", ud, 4);
26002 va("UpsampleRgba4444LinePair", td, 2);
26003 va("UpsampleRgb565LinePair", sd, 2);
26004 var Mf = self.UpsampleRgbLinePair,
26005 Nf = self.UpsampleBgrLinePair,
26006 nd = self.UpsampleRgbaLinePair,
26007 od = self.UpsampleBgraLinePair,
26008 pd = self.UpsampleArgbLinePair,
26009 qd = self.UpsampleRgba4444LinePair,
26010 Of = self.UpsampleRgb565LinePair,
26011 Wa = 16,
26012 Ba = 1 << (Wa - 1),
26013 ta = -227,
26014 Eb = 482,
26015 rd = 6,
26016 Pf = (256 << rd) - 1,
26017 jc = 0,
26018 Yd = V(256),
26019 ae = V(256),
26020 $d = V(256),
26021 Zd = V(256),
26022 be = V(Eb - ta),
26023 ce = V(Eb - ta);
26024 la("YuvToRgbRow", Ga, 3);
26025 la("YuvToBgrRow", Tb, 3);
26026 la("YuvToRgbaRow", wd, 4);
26027 la("YuvToBgraRow", vd, 4);
26028 la("YuvToArgbRow", ud, 4);
26029 la("YuvToRgba4444Row", td, 2);
26030 la("YuvToRgb565Row", sd, 2);
26031 var zd = [
26032 0,
26033 4,
26034 8,
26035 12,
26036 128,
26037 132,
26038 136,
26039 140,
26040 256,
26041 260,
26042 264,
26043 268,
26044 384,
26045 388,
26046 392,
26047 396
26048 ],
26049 Ya = [0, 2, 8],
26050 Qf = [8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1],
26051 Ne = 1;
26052 this.WebPDecodeRGBA = function(a, b, c, d, e) {
26053 var f = Ua;
26054 var g = new Cf(),
26055 h = new Cb();
26056 g.ba = h;
26057 h.S = f;
26058 h.width = [h.width];
26059 h.height = [h.height];
26060 var k = h.width;
26061 var l = h.height,
26062 m = new Td();
26063 if (null == m || null == a) var n = 2;
26064 else
26065 x(null != m),
26066 (n = Ad(a, b, c, m.width, m.height, m.Pd, m.Qd, m.format, null));
26067 0 != n
26068 ? (k = 0)
26069 : (null != k && (k[0] = m.width[0]),
26070 null != l && (l[0] = m.height[0]),
26071 (k = 1));
26072 if (k) {
26073 h.width = h.width[0];
26074 h.height = h.height[0];
26075 null != d && (d[0] = h.width);
26076 null != e && (e[0] = h.height);
26077 b: {
26078 d = new Oa();
26079 e = new md();
26080 e.data = a;
26081 e.w = b;
26082 e.ha = c;
26083 e.kd = 1;
26084 b = [0];
26085 x(null != e);
26086 a = Ad(e.data, e.w, e.ha, null, null, null, b, null, e);
26087 (0 == a || 7 == a) && b[0] && (a = 4);
26088 b = a;
26089 if (0 == b) {
26090 x(null != g);
26091 d.data = e.data;
26092 d.w = e.w + e.offset;
26093 d.ha = e.ha - e.offset;
26094 d.put = kc;
26095 d.ac = gc;
26096 d.bc = lc;
26097 d.ma = g;
26098 if (e.xa) {
26099 a = Bc();
26100 if (null == a) {
26101 g = 1;
26102 break b;
26103 }
26104 if (te(a, d)) {
26105 b = Cd(d.width, d.height, g.Oa, g.ba);
26106 if ((d = 0 == b)) {
26107 c: {
26108 d = a;
26109 d: for (;;) {
26110 if (null == d) {
26111 d = 0;
26112 break c;
26113 }
26114 x(null != d.s.yc);
26115 x(null != d.s.Ya);
26116 x(0 < d.s.Wb);
26117 c = d.l;
26118 x(null != c);
26119 e = c.ma;
26120 x(null != e);
26121 if (0 != d.xb) {
26122 d.ca = e.ba;
26123 d.tb = e.tb;
26124 x(null != d.ca);
26125 if (!hc(e.Oa, c, Va)) {
26126 d.a = 2;
26127 break d;
26128 }
26129 if (!Ec(d, c.width)) break d;
26130 if (c.da) break d;
26131 (c.da || hb(d.ca.S)) && Aa();
26132 11 > d.ca.S ||
26133 (alert("todo:WebPInitConvertARGBToYUV"),
26134 null != d.ca.f.kb.F && Aa());
26135 if (
26136 d.Pb &&
26137 0 < d.s.ua &&
26138 null == d.s.vb.X &&
26139 !Zb(d.s.vb, d.s.Wa.Xa)
26140 ) {
26141 d.a = 1;
26142 break d;
26143 }
26144 d.xb = 0;
26145 }
26146 if (!Jb(d, d.V, d.Ba, d.c, d.i, c.o, ge)) break d;
26147 e.Dc = d.Ma;
26148 d = 1;
26149 break c;
26150 }
26151 x(0 != d.a);
26152 d = 0;
26153 }
26154 d = !d;
26155 }
26156 d && (b = a.a);
26157 } else b = a.a;
26158 } else {
26159 a = new Ce();
26160 if (null == a) {
26161 g = 1;
26162 break b;
26163 }
26164 a.Fa = e.na;
26165 a.P = e.P;
26166 a.qc = e.Sa;
26167 if (Kc(a, d)) {
26168 if (((b = Cd(d.width, d.height, g.Oa, g.ba)), 0 == b)) {
26169 a.Aa = 0;
26170 c = g.Oa;
26171 e = a;
26172 x(null != e);
26173 if (null != c) {
26174 k = c.Md;
26175 k = 0 > k ? 0 : 100 < k ? 255 : (255 * k) / 100;
26176 if (0 < k) {
26177 for (l = m = 0; 4 > l; ++l)
26178 (n = e.pb[l]),
26179 12 > n.lc &&
26180 (n.ia = (k * Qf[0 > n.lc ? 0 : n.lc]) >> 3),
26181 (m |= n.ia);
26182 m && (alert("todo:VP8InitRandom"), (e.ia = 1));
26183 }
26184 e.Ga = c.Id;
26185 100 < e.Ga ? (e.Ga = 100) : 0 > e.Ga && (e.Ga = 0);
26186 }
26187 Me(a, d) || (b = a.a);
26188 }
26189 } else b = a.a;
26190 }
26191 0 == b && null != g.Oa && g.Oa.fd && (b = Bd(g.ba));
26192 }
26193 g = b;
26194 }
26195 f = 0 != g ? null : 11 > f ? h.f.RGBA.eb : h.f.kb.y;
26196 } else f = null;
26197 return f;
26198 };
26199 var Dd = [3, 4, 3, 4, 4, 2, 2, 4, 4, 4, 2, 1, 1];
26200 };
26201 new WebPDecoder();
26202
26203 /** @license
26204 * Copyright (c) 2017 Dominik Homberger
26205
26206 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
26207
26208 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
26209
26210 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26211
26212 https://webpjs.appspot.com
26213 WebPRiffParser dominikhlbg@gmail.com
26214 */
26215
26216 function memcmp(data, data_off, str, size) {
26217 for (var i = 0; i < size; i++)
26218 if (data[data_off + i] != str.charCodeAt(i)) return true;
26219 return false;
26220 }
26221
26222 function GetTag(data, data_off) {
26223 var str = "";
26224 for (var i = 0; i < 4; i++) str += String.fromCharCode(data[data_off++]);
26225 return str;
26226 }
26227
26228 function GetLE16(data, data_off) {
26229 return (data[data_off + 0] << 0) | (data[data_off + 1] << 8);
26230 }
26231
26232 function GetLE24(data, data_off) {
26233 return (
26234 ((data[data_off + 0] << 0) |
26235 (data[data_off + 1] << 8) |
26236 (data[data_off + 2] << 16)) >>>
26237 0
26238 );
26239 }
26240
26241 function GetLE32(data, data_off) {
26242 return (
26243 ((data[data_off + 0] << 0) |
26244 (data[data_off + 1] << 8) |
26245 (data[data_off + 2] << 16) |
26246 (data[data_off + 3] << 24)) >>>
26247 0
26248 );
26249 }
26250
26251 function WebPRiffParser(src, src_off) {
26252 var imagearray = {};
26253 var i = 0;
26254 var alpha_chunk = false;
26255 var alpha_size = 0;
26256 var alpha_offset = 0;
26257 imagearray["frames"] = [];
26258 if (memcmp(src, src_off, "RIFF", 4)) return;
26259 src_off += 4;
26260 var riff_size = GetLE32(src, src_off) + 8;
26261 src_off += 8;
26262
26263 while (src_off < src.length) {
26264 var fourcc = GetTag(src, src_off);
26265 src_off += 4;
26266
26267 var payload_size = GetLE32(src, src_off);
26268 src_off += 4;
26269 var payload_size_padded = payload_size + (payload_size & 1);
26270
26271 switch (fourcc) {
26272 case "VP8 ":
26273 case "VP8L":
26274 if (typeof imagearray["frames"][i] === "undefined")
26275 imagearray["frames"][i] = {};
26276 var obj = imagearray["frames"][i];
26277 var height = [0];
26278 var width = [0];
26279 obj["src_off"] = alpha_chunk ? alpha_offset : src_off - 8;
26280 obj["src_size"] = alpha_size + payload_size + 8;
26281 //var rgba = webpdecoder.WebPDecodeRGBA(src,(alpha_chunk?alpha_offset:src_off-8),alpha_size+payload_size+8,width,height);
26282 //imagearray[i]={'rgba':rgba,'width':width[0],'height':height[0]};
26283 i++;
26284 if (alpha_chunk) {
26285 alpha_chunk = false;
26286 alpha_size = 0;
26287 alpha_offset = 0;
26288 }
26289 break;
26290 case "VP8X":
26291 var obj = (imagearray["header"] = {});
26292 var feature_flags = (obj["feature_flags"] = src[src_off]);
26293 var src_off_ = src_off + 4;
26294 var canvas_width = (obj["canvas_width"] = 1 + GetLE24(src, src_off_));
26295 src_off_ += 3;
26296 var canvas_height = (obj["canvas_height"] =
26297 1 + GetLE24(src, src_off_));
26298 src_off_ += 3;
26299 break;
26300 case "ALPH":
26301 alpha_chunk = true;
26302 alpha_size = payload_size_padded + 8;
26303 alpha_offset = src_off - 8;
26304 break;
26305
26306 case "ANIM":
26307 var obj = imagearray["header"];
26308 var bgcolor = (obj["bgcolor"] = GetLE32(src, src_off));
26309 src_off_ = src_off + 4;
26310
26311 var loop_count = (obj["loop_count"] = GetLE16(src, src_off_));
26312 src_off_ += 2;
26313 break;
26314 case "ANMF":
26315 var offset_x = 0,
26316 offset_y = 0,
26317 width = 0,
26318 height = 0,
26319 duration = 0,
26320 blend = 0,
26321 dispose = 0,
26322 temp = 0;
26323 var obj = (imagearray["frames"][i] = {});
26324 obj["offset_x"] = offset_x = 2 * GetLE24(src, src_off);
26325 src_off += 3;
26326 obj["offset_y"] = offset_y = 2 * GetLE24(src, src_off);
26327 src_off += 3;
26328 obj["width"] = width = 1 + GetLE24(src, src_off);
26329 src_off += 3;
26330 obj["height"] = height = 1 + GetLE24(src, src_off);
26331 src_off += 3;
26332 obj["duration"] = duration = GetLE24(src, src_off);
26333 src_off += 3;
26334 temp = src[src_off++];
26335 obj["dispose"] = dispose = temp & 1;
26336 obj["blend"] = blend = (temp >> 1) & 1;
26337 break;
26338 }
26339 if (fourcc != "ANMF") src_off += payload_size_padded;
26340 }
26341 return imagearray;
26342 }
26343
26344 var height = [0];
26345 var width = [0];
26346 var pixels = [];
26347 var webpdecoder = new WebPDecoder();
26348
26349 var response = imageData;
26350 var imagearray = WebPRiffParser(response, 0);
26351 imagearray["response"] = response;
26352 imagearray["rgbaoutput"] = true;
26353 imagearray["dataurl"] = false;
26354
26355 var header = imagearray["header"] ? imagearray["header"] : null;
26356 var frames = imagearray["frames"] ? imagearray["frames"] : null;
26357
26358 if (header) {
26359 header["loop_counter"] = header["loop_count"];
26360 height = [header["canvas_height"]];
26361 width = [header["canvas_width"]];
26362 for (var f = 0; f < frames.length; f++)
26363 if (frames[f]["blend"] == 0) {
26364 break;
26365 }
26366 }
26367
26368 var frame = frames[0];
26369 var rgba = webpdecoder.WebPDecodeRGBA(
26370 response,
26371 frame["src_off"],
26372 frame["src_size"],
26373 width,
26374 height
26375 );
26376 frame["rgba"] = rgba;
26377 frame["imgwidth"] = width[0];
26378 frame["imgheight"] = height[0];
26379
26380 for (var i = 0; i < width[0] * height[0] * 4; i++) {
26381 pixels[i] = rgba[i];
26382 }
26383
26384 this.width = width;
26385 this.height = height;
26386 this.data = pixels;
26387 return this;
26388 }
26389
26390 WebPDecoder.prototype.getData = function() {
26391 return this.data;
26392 };
26393
26394 /**
26395 * @license
26396 * Copyright (c) 2019 Aras Abbasi
26397 *
26398 * Licensed under the MIT License.
26399 * http://opensource.org/licenses/mit-license
26400 */
26401
26402 /**
26403 * jsPDF webp Support PlugIn
26404 *
26405 * @name webp_support
26406 * @module
26407 */
26408 (function(jsPDFAPI) {
26409
26410 jsPDFAPI.processWEBP = function(imageData, index, alias, compression) {
26411 var reader = new WebPDecoder(imageData, false);
26412 var width = reader.width,
26413 height = reader.height;
26414 var qu = 100;
26415 var pixels = reader.getData();
26416
26417 var rawImageData = {
26418 data: pixels,
26419 width: width,
26420 height: height
26421 };
26422
26423 var encoder = new JPEGEncoder(qu);
26424 var data = encoder.encode(rawImageData, qu);
26425 return jsPDFAPI.processJPEG.call(this, data, index, alias, compression);
26426 };
26427 })(jsPDF.API);
26428
26429 /**
26430 * @license
26431 * Licensed under the MIT License.
26432 * http://opensource.org/licenses/mit-license
26433 */
26434
26435 /**
26436 * jsPDF setLanguage Plugin
26437 *
26438 * @name setLanguage
26439 * @module
26440 */
26441 (function(jsPDFAPI) {
26442
26443 /**
26444 * Add Language Tag to the generated PDF
26445 *
26446 * @name setLanguage
26447 * @function
26448 * @param {string} langCode The Language code as ISO-639-1 (e.g. 'en') or as country language code (e.g. 'en-GB').
26449 * @returns {jsPDF}
26450 * @example
26451 * var doc = new jsPDF()
26452 * doc.text(10, 10, 'This is a test')
26453 * doc.setLanguage("en-US")
26454 * doc.save('english.pdf')
26455 */
26456 jsPDFAPI.setLanguage = function(langCode) {
26457
26458 var langCodes = {
26459 af: "Afrikaans",
26460 sq: "Albanian",
26461 ar: "Arabic (Standard)",
26462 "ar-DZ": "Arabic (Algeria)",
26463 "ar-BH": "Arabic (Bahrain)",
26464 "ar-EG": "Arabic (Egypt)",
26465 "ar-IQ": "Arabic (Iraq)",
26466 "ar-JO": "Arabic (Jordan)",
26467 "ar-KW": "Arabic (Kuwait)",
26468 "ar-LB": "Arabic (Lebanon)",
26469 "ar-LY": "Arabic (Libya)",
26470 "ar-MA": "Arabic (Morocco)",
26471 "ar-OM": "Arabic (Oman)",
26472 "ar-QA": "Arabic (Qatar)",
26473 "ar-SA": "Arabic (Saudi Arabia)",
26474 "ar-SY": "Arabic (Syria)",
26475 "ar-TN": "Arabic (Tunisia)",
26476 "ar-AE": "Arabic (U.A.E.)",
26477 "ar-YE": "Arabic (Yemen)",
26478 an: "Aragonese",
26479 hy: "Armenian",
26480 as: "Assamese",
26481 ast: "Asturian",
26482 az: "Azerbaijani",
26483 eu: "Basque",
26484 be: "Belarusian",
26485 bn: "Bengali",
26486 bs: "Bosnian",
26487 br: "Breton",
26488 bg: "Bulgarian",
26489 my: "Burmese",
26490 ca: "Catalan",
26491 ch: "Chamorro",
26492 ce: "Chechen",
26493 zh: "Chinese",
26494 "zh-HK": "Chinese (Hong Kong)",
26495 "zh-CN": "Chinese (PRC)",
26496 "zh-SG": "Chinese (Singapore)",
26497 "zh-TW": "Chinese (Taiwan)",
26498 cv: "Chuvash",
26499 co: "Corsican",
26500 cr: "Cree",
26501 hr: "Croatian",
26502 cs: "Czech",
26503 da: "Danish",
26504 nl: "Dutch (Standard)",
26505 "nl-BE": "Dutch (Belgian)",
26506 en: "English",
26507 "en-AU": "English (Australia)",
26508 "en-BZ": "English (Belize)",
26509 "en-CA": "English (Canada)",
26510 "en-IE": "English (Ireland)",
26511 "en-JM": "English (Jamaica)",
26512 "en-NZ": "English (New Zealand)",
26513 "en-PH": "English (Philippines)",
26514 "en-ZA": "English (South Africa)",
26515 "en-TT": "English (Trinidad & Tobago)",
26516 "en-GB": "English (United Kingdom)",
26517 "en-US": "English (United States)",
26518 "en-ZW": "English (Zimbabwe)",
26519 eo: "Esperanto",
26520 et: "Estonian",
26521 fo: "Faeroese",
26522 fj: "Fijian",
26523 fi: "Finnish",
26524 fr: "French (Standard)",
26525 "fr-BE": "French (Belgium)",
26526 "fr-CA": "French (Canada)",
26527 "fr-FR": "French (France)",
26528 "fr-LU": "French (Luxembourg)",
26529 "fr-MC": "French (Monaco)",
26530 "fr-CH": "French (Switzerland)",
26531 fy: "Frisian",
26532 fur: "Friulian",
26533 gd: "Gaelic (Scots)",
26534 "gd-IE": "Gaelic (Irish)",
26535 gl: "Galacian",
26536 ka: "Georgian",
26537 de: "German (Standard)",
26538 "de-AT": "German (Austria)",
26539 "de-DE": "German (Germany)",
26540 "de-LI": "German (Liechtenstein)",
26541 "de-LU": "German (Luxembourg)",
26542 "de-CH": "German (Switzerland)",
26543 el: "Greek",
26544 gu: "Gujurati",
26545 ht: "Haitian",
26546 he: "Hebrew",
26547 hi: "Hindi",
26548 hu: "Hungarian",
26549 is: "Icelandic",
26550 id: "Indonesian",
26551 iu: "Inuktitut",
26552 ga: "Irish",
26553 it: "Italian (Standard)",
26554 "it-CH": "Italian (Switzerland)",
26555 ja: "Japanese",
26556 kn: "Kannada",
26557 ks: "Kashmiri",
26558 kk: "Kazakh",
26559 km: "Khmer",
26560 ky: "Kirghiz",
26561 tlh: "Klingon",
26562 ko: "Korean",
26563 "ko-KP": "Korean (North Korea)",
26564 "ko-KR": "Korean (South Korea)",
26565 la: "Latin",
26566 lv: "Latvian",
26567 lt: "Lithuanian",
26568 lb: "Luxembourgish",
26569 mk: "FYRO Macedonian",
26570 ms: "Malay",
26571 ml: "Malayalam",
26572 mt: "Maltese",
26573 mi: "Maori",
26574 mr: "Marathi",
26575 mo: "Moldavian",
26576 nv: "Navajo",
26577 ng: "Ndonga",
26578 ne: "Nepali",
26579 no: "Norwegian",
26580 nb: "Norwegian (Bokmal)",
26581 nn: "Norwegian (Nynorsk)",
26582 oc: "Occitan",
26583 or: "Oriya",
26584 om: "Oromo",
26585 fa: "Persian",
26586 "fa-IR": "Persian/Iran",
26587 pl: "Polish",
26588 pt: "Portuguese",
26589 "pt-BR": "Portuguese (Brazil)",
26590 pa: "Punjabi",
26591 "pa-IN": "Punjabi (India)",
26592 "pa-PK": "Punjabi (Pakistan)",
26593 qu: "Quechua",
26594 rm: "Rhaeto-Romanic",
26595 ro: "Romanian",
26596 "ro-MO": "Romanian (Moldavia)",
26597 ru: "Russian",
26598 "ru-MO": "Russian (Moldavia)",
26599 sz: "Sami (Lappish)",
26600 sg: "Sango",
26601 sa: "Sanskrit",
26602 sc: "Sardinian",
26603 sd: "Sindhi",
26604 si: "Singhalese",
26605 sr: "Serbian",
26606 sk: "Slovak",
26607 sl: "Slovenian",
26608 so: "Somani",
26609 sb: "Sorbian",
26610 es: "Spanish",
26611 "es-AR": "Spanish (Argentina)",
26612 "es-BO": "Spanish (Bolivia)",
26613 "es-CL": "Spanish (Chile)",
26614 "es-CO": "Spanish (Colombia)",
26615 "es-CR": "Spanish (Costa Rica)",
26616 "es-DO": "Spanish (Dominican Republic)",
26617 "es-EC": "Spanish (Ecuador)",
26618 "es-SV": "Spanish (El Salvador)",
26619 "es-GT": "Spanish (Guatemala)",
26620 "es-HN": "Spanish (Honduras)",
26621 "es-MX": "Spanish (Mexico)",
26622 "es-NI": "Spanish (Nicaragua)",
26623 "es-PA": "Spanish (Panama)",
26624 "es-PY": "Spanish (Paraguay)",
26625 "es-PE": "Spanish (Peru)",
26626 "es-PR": "Spanish (Puerto Rico)",
26627 "es-ES": "Spanish (Spain)",
26628 "es-UY": "Spanish (Uruguay)",
26629 "es-VE": "Spanish (Venezuela)",
26630 sx: "Sutu",
26631 sw: "Swahili",
26632 sv: "Swedish",
26633 "sv-FI": "Swedish (Finland)",
26634 "sv-SV": "Swedish (Sweden)",
26635 ta: "Tamil",
26636 tt: "Tatar",
26637 te: "Teluga",
26638 th: "Thai",
26639 tig: "Tigre",
26640 ts: "Tsonga",
26641 tn: "Tswana",
26642 tr: "Turkish",
26643 tk: "Turkmen",
26644 uk: "Ukrainian",
26645 hsb: "Upper Sorbian",
26646 ur: "Urdu",
26647 ve: "Venda",
26648 vi: "Vietnamese",
26649 vo: "Volapuk",
26650 wa: "Walloon",
26651 cy: "Welsh",
26652 xh: "Xhosa",
26653 ji: "Yiddish",
26654 zu: "Zulu"
26655 };
26656
26657 if (this.internal.languageSettings === undefined) {
26658 this.internal.languageSettings = {};
26659 this.internal.languageSettings.isSubscribed = false;
26660 }
26661
26662 if (langCodes[langCode] !== undefined) {
26663 this.internal.languageSettings.languageCode = langCode;
26664 if (this.internal.languageSettings.isSubscribed === false) {
26665 this.internal.events.subscribe("putCatalog", function() {
26666 this.internal.write(
26667 "/Lang (" + this.internal.languageSettings.languageCode + ")"
26668 );
26669 });
26670 this.internal.languageSettings.isSubscribed = true;
26671 }
26672 }
26673 return this;
26674 };
26675 })(jsPDF.API);
26676
26677 /** @license
26678 * MIT license.
26679 * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
26680 * 2014 Diego Casorran, https://github.com/diegocr
26681 *
26682 * Permission is hereby granted, free of charge, to any person obtaining
26683 * a copy of this software and associated documentation files (the
26684 * "Software"), to deal in the Software without restriction, including
26685 * without limitation the rights to use, copy, modify, merge, publish,
26686 * distribute, sublicense, and/or sell copies of the Software, and to
26687 * permit persons to whom the Software is furnished to do so, subject to
26688 * the following conditions:
26689 *
26690 * The above copyright notice and this permission notice shall be
26691 * included in all copies or substantial portions of the Software.
26692 *
26693 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26694 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26695 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26696 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26697 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26698 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26699 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26700 * ====================================================================
26701 */
26702
26703 /**
26704 * jsPDF split_text_to_size plugin
26705 *
26706 * @name split_text_to_size
26707 * @module
26708 */
26709 (function(API) {
26710 /**
26711 * Returns an array of length matching length of the 'word' string, with each
26712 * cell occupied by the width of the char in that position.
26713 *
26714 * @name getCharWidthsArray
26715 * @function
26716 * @param {string} text
26717 * @param {Object} options
26718 * @returns {Array}
26719 */
26720 var getCharWidthsArray = (API.getCharWidthsArray = function(text, options) {
26721 options = options || {};
26722
26723 var activeFont = options.font || this.internal.getFont();
26724 var fontSize = options.fontSize || this.internal.getFontSize();
26725 var charSpace = options.charSpace || this.internal.getCharSpace();
26726
26727 var widths = options.widths
26728 ? options.widths
26729 : activeFont.metadata.Unicode.widths;
26730 var widthsFractionOf = widths.fof ? widths.fof : 1;
26731 var kerning = options.kerning
26732 ? options.kerning
26733 : activeFont.metadata.Unicode.kerning;
26734 var kerningFractionOf = kerning.fof ? kerning.fof : 1;
26735 var doKerning = options.doKerning === false ? false : true;
26736 var kerningValue = 0;
26737
26738 var i;
26739 var length = text.length;
26740 var char_code;
26741 var prior_char_code = 0; //for kerning
26742 var default_char_width = widths[0] || widthsFractionOf;
26743 var output = [];
26744
26745 for (i = 0; i < length; i++) {
26746 char_code = text.charCodeAt(i);
26747
26748 if (typeof activeFont.metadata.widthOfString === "function") {
26749 output.push(
26750 (activeFont.metadata.widthOfGlyph(
26751 activeFont.metadata.characterToGlyph(char_code)
26752 ) +
26753 charSpace * (1000 / fontSize) || 0) / 1000
26754 );
26755 } else {
26756 if (
26757 doKerning &&
26758 typeof kerning[char_code] === "object" &&
26759 !isNaN(parseInt(kerning[char_code][prior_char_code], 10))
26760 ) {
26761 kerningValue =
26762 kerning[char_code][prior_char_code] / kerningFractionOf;
26763 } else {
26764 kerningValue = 0;
26765 }
26766 output.push(
26767 (widths[char_code] || default_char_width) / widthsFractionOf +
26768 kerningValue
26769 );
26770 }
26771 prior_char_code = char_code;
26772 }
26773
26774 return output;
26775 });
26776
26777 /**
26778 * Returns a widths of string in a given font, if the font size is set as 1 point.
26779 *
26780 * In other words, this is "proportional" value. For 1 unit of font size, the length
26781 * of the string will be that much.
26782 *
26783 * Multiply by font size to get actual width in *points*
26784 * Then divide by 72 to get inches or divide by (72/25.6) to get 'mm' etc.
26785 *
26786 * @name getStringUnitWidth
26787 * @public
26788 * @function
26789 * @param {string} text
26790 * @param {string} options
26791 * @returns {number} result
26792 */
26793 var getStringUnitWidth = (API.getStringUnitWidth = function(text, options) {
26794 options = options || {};
26795
26796 var fontSize = options.fontSize || this.internal.getFontSize();
26797 var font = options.font || this.internal.getFont();
26798 var charSpace = options.charSpace || this.internal.getCharSpace();
26799 var result = 0;
26800
26801 if (API.processArabic) {
26802 text = API.processArabic(text);
26803 }
26804
26805 if (typeof font.metadata.widthOfString === "function") {
26806 result =
26807 font.metadata.widthOfString(text, fontSize, charSpace) / fontSize;
26808 } else {
26809 result = getCharWidthsArray
26810 .apply(this, arguments)
26811 .reduce(function(pv, cv) {
26812 return pv + cv;
26813 }, 0);
26814 }
26815 return result;
26816 });
26817
26818 /**
26819 returns array of lines
26820 */
26821 var splitLongWord = function(word, widths_array, firstLineMaxLen, maxLen) {
26822 var answer = [];
26823
26824 // 1st, chop off the piece that can fit on the hanging line.
26825 var i = 0,
26826 l = word.length,
26827 workingLen = 0;
26828 while (i !== l && workingLen + widths_array[i] < firstLineMaxLen) {
26829 workingLen += widths_array[i];
26830 i++;
26831 }
26832 // this is first line.
26833 answer.push(word.slice(0, i));
26834
26835 // 2nd. Split the rest into maxLen pieces.
26836 var startOfLine = i;
26837 workingLen = 0;
26838 while (i !== l) {
26839 if (workingLen + widths_array[i] > maxLen) {
26840 answer.push(word.slice(startOfLine, i));
26841 workingLen = 0;
26842 startOfLine = i;
26843 }
26844 workingLen += widths_array[i];
26845 i++;
26846 }
26847 if (startOfLine !== i) {
26848 answer.push(word.slice(startOfLine, i));
26849 }
26850
26851 return answer;
26852 };
26853
26854 // Note, all sizing inputs for this function must be in "font measurement units"
26855 // By default, for PDF, it's "point".
26856 var splitParagraphIntoLines = function(text, maxlen, options) {
26857 // at this time works only on Western scripts, ones with space char
26858 // separating the words. Feel free to expand.
26859
26860 if (!options) {
26861 options = {};
26862 }
26863
26864 var line = [],
26865 lines = [line],
26866 line_length = options.textIndent || 0,
26867 separator_length = 0,
26868 current_word_length = 0,
26869 word,
26870 widths_array,
26871 words = text.split(" "),
26872 spaceCharWidth = getCharWidthsArray.apply(this, [" ", options])[0],
26873 i,
26874 l,
26875 tmp,
26876 lineIndent;
26877
26878 if (options.lineIndent === -1) {
26879 lineIndent = words[0].length + 2;
26880 } else {
26881 lineIndent = options.lineIndent || 0;
26882 }
26883 if (lineIndent) {
26884 var pad = Array(lineIndent).join(" "),
26885 wrds = [];
26886 words.map(function(wrd) {
26887 wrd = wrd.split(/\s*\n/);
26888 if (wrd.length > 1) {
26889 wrds = wrds.concat(
26890 wrd.map(function(wrd, idx) {
26891 return (idx && wrd.length ? "\n" : "") + wrd;
26892 })
26893 );
26894 } else {
26895 wrds.push(wrd[0]);
26896 }
26897 });
26898 words = wrds;
26899 lineIndent = getStringUnitWidth.apply(this, [pad, options]);
26900 }
26901
26902 for (i = 0, l = words.length; i < l; i++) {
26903 var force = 0;
26904
26905 word = words[i];
26906 if (lineIndent && word[0] == "\n") {
26907 word = word.substr(1);
26908 force = 1;
26909 }
26910 widths_array = getCharWidthsArray.apply(this, [word, options]);
26911 current_word_length = widths_array.reduce(function(pv, cv) {
26912 return pv + cv;
26913 }, 0);
26914
26915 if (
26916 line_length + separator_length + current_word_length > maxlen ||
26917 force
26918 ) {
26919 if (current_word_length > maxlen) {
26920 // this happens when you have space-less long URLs for example.
26921 // we just chop these to size. We do NOT insert hiphens
26922 tmp = splitLongWord.apply(this, [
26923 word,
26924 widths_array,
26925 maxlen - (line_length + separator_length),
26926 maxlen
26927 ]);
26928 // first line we add to existing line object
26929 line.push(tmp.shift()); // it's ok to have extra space indicator there
26930 // last line we make into new line object
26931 line = [tmp.pop()];
26932 // lines in the middle we apped to lines object as whole lines
26933 while (tmp.length) {
26934 lines.push([tmp.shift()]); // single fragment occupies whole line
26935 }
26936 current_word_length = widths_array
26937 .slice(word.length - (line[0] ? line[0].length : 0))
26938 .reduce(function(pv, cv) {
26939 return pv + cv;
26940 }, 0);
26941 } else {
26942 // just put it on a new line
26943 line = [word];
26944 }
26945
26946 // now we attach new line to lines
26947 lines.push(line);
26948 line_length = current_word_length + lineIndent;
26949 separator_length = spaceCharWidth;
26950 } else {
26951 line.push(word);
26952
26953 line_length += separator_length + current_word_length;
26954 separator_length = spaceCharWidth;
26955 }
26956 }
26957
26958 var postProcess;
26959 if (lineIndent) {
26960 postProcess = function(ln, idx) {
26961 return (idx ? pad : "") + ln.join(" ");
26962 };
26963 } else {
26964 postProcess = function(ln) {
26965 return ln.join(" ");
26966 };
26967 }
26968
26969 return lines.map(postProcess);
26970 };
26971
26972 /**
26973 * Splits a given string into an array of strings. Uses 'size' value
26974 * (in measurement units declared as default for the jsPDF instance)
26975 * and the font's "widths" and "Kerning" tables, where available, to
26976 * determine display length of a given string for a given font.
26977 *
26978 * We use character's 100% of unit size (height) as width when Width
26979 * table or other default width is not available.
26980 *
26981 * @name splitTextToSize
26982 * @public
26983 * @function
26984 * @param {string} text Unencoded, regular JavaScript (Unicode, UTF-16 / UCS-2) string.
26985 * @param {number} size Nominal number, measured in units default to this instance of jsPDF.
26986 * @param {Object} options Optional flags needed for chopper to do the right thing.
26987 * @returns {Array} array Array with strings chopped to size.
26988 */
26989 API.splitTextToSize = function(text, maxlen, options) {
26990
26991 options = options || {};
26992
26993 var fsize = options.fontSize || this.internal.getFontSize(),
26994 newOptions = function(options) {
26995 var widths = {
26996 0: 1
26997 },
26998 kerning = {};
26999
27000 if (!options.widths || !options.kerning) {
27001 var f = this.internal.getFont(options.fontName, options.fontStyle),
27002 encoding = "Unicode";
27003 // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE
27004 // Actual JavaScript-native String's 16bit char codes used.
27005 // no multi-byte logic here
27006
27007 if (f.metadata[encoding]) {
27008 return {
27009 widths: f.metadata[encoding].widths || widths,
27010 kerning: f.metadata[encoding].kerning || kerning
27011 };
27012 } else {
27013 return {
27014 font: f.metadata,
27015 fontSize: this.internal.getFontSize(),
27016 charSpace: this.internal.getCharSpace()
27017 };
27018 }
27019 } else {
27020 return {
27021 widths: options.widths,
27022 kerning: options.kerning
27023 };
27024 }
27025 }.call(this, options);
27026
27027 // first we split on end-of-line chars
27028 var paragraphs;
27029 if (Array.isArray(text)) {
27030 paragraphs = text;
27031 } else {
27032 paragraphs = String(text).split(/\r?\n/);
27033 }
27034
27035 // now we convert size (max length of line) into "font size units"
27036 // at present time, the "font size unit" is always 'point'
27037 // 'proportional' means, "in proportion to font size"
27038 var fontUnit_maxLen = (1.0 * this.internal.scaleFactor * maxlen) / fsize;
27039 // at this time, fsize is always in "points" regardless of the default measurement unit of the doc.
27040 // this may change in the future?
27041 // until then, proportional_maxlen is likely to be in 'points'
27042
27043 // If first line is to be indented (shorter or longer) than maxLen
27044 // we indicate that by using CSS-style "text-indent" option.
27045 // here it's in font units too (which is likely 'points')
27046 // it can be negative (which makes the first line longer than maxLen)
27047 newOptions.textIndent = options.textIndent
27048 ? (options.textIndent * 1.0 * this.internal.scaleFactor) / fsize
27049 : 0;
27050 newOptions.lineIndent = options.lineIndent;
27051
27052 var i,
27053 l,
27054 output = [];
27055 for (i = 0, l = paragraphs.length; i < l; i++) {
27056 output = output.concat(
27057 splitParagraphIntoLines.apply(this, [
27058 paragraphs[i],
27059 fontUnit_maxLen,
27060 newOptions
27061 ])
27062 );
27063 }
27064
27065 return output;
27066 };
27067 })(jsPDF.API);
27068
27069 /** @license
27070 jsPDF standard_fonts_metrics plugin
27071 * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
27072 * MIT license.
27073 * Permission is hereby granted, free of charge, to any person obtaining
27074 * a copy of this software and associated documentation files (the
27075 * "Software"), to deal in the Software without restriction, including
27076 * without limitation the rights to use, copy, modify, merge, publish,
27077 * distribute, sublicense, and/or sell copies of the Software, and to
27078 * permit persons to whom the Software is furnished to do so, subject to
27079 * the following conditions:
27080 *
27081 * The above copyright notice and this permission notice shall be
27082 * included in all copies or substantial portions of the Software.
27083 *
27084 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27085 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27086 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27087 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27088 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27089 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27090 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27091 * ====================================================================
27092 */
27093
27094 /**
27095 * This file adds the standard font metrics to jsPDF.
27096 *
27097 * Font metrics data is reprocessed derivative of contents of
27098 * "Font Metrics for PDF Core 14 Fonts" package, which exhibits the following copyright and license:
27099 *
27100 * Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
27101 *
27102 * This file and the 14 PostScript(R) AFM files it accompanies may be used,
27103 * copied, and distributed for any purpose and without charge, with or without
27104 * modification, provided that all copyright notices are retained; that the AFM
27105 * files are not distributed without this file; that all modifications to this
27106 * file or any of the AFM files are prominently noted in the modified file(s);
27107 * and that this paragraph is not modified. Adobe Systems has no responsibility
27108 * or obligation to support the use of the AFM files.
27109 *
27110 * @name standard_fonts_metrics
27111 * @module
27112 */
27113
27114 (function(API) {
27115 API.__fontmetrics__ = API.__fontmetrics__ || {};
27116
27117 var decoded = "0123456789abcdef",
27118 encoded = "klmnopqrstuvwxyz",
27119 mappingUncompress = {},
27120 mappingCompress = {};
27121
27122 for (var i = 0; i < encoded.length; i++) {
27123 mappingUncompress[encoded[i]] = decoded[i];
27124 mappingCompress[decoded[i]] = encoded[i];
27125 }
27126
27127 var hex = function(value) {
27128 return "0x" + parseInt(value, 10).toString(16);
27129 };
27130
27131 var compress = (API.__fontmetrics__.compress = function(data) {
27132 var vals = ["{"];
27133 var value, keystring, valuestring, numberprefix;
27134
27135 for (var key in data) {
27136 value = data[key];
27137
27138 if (!isNaN(parseInt(key, 10))) {
27139 key = parseInt(key, 10);
27140 keystring = hex(key).slice(2);
27141 keystring =
27142 keystring.slice(0, -1) + mappingCompress[keystring.slice(-1)];
27143 } else {
27144 keystring = "'" + key + "'";
27145 }
27146
27147 if (typeof value == "number") {
27148 if (value < 0) {
27149 valuestring = hex(value).slice(3);
27150 numberprefix = "-";
27151 } else {
27152 valuestring = hex(value).slice(2);
27153 numberprefix = "";
27154 }
27155 valuestring =
27156 numberprefix +
27157 valuestring.slice(0, -1) +
27158 mappingCompress[valuestring.slice(-1)];
27159 } else {
27160 if (typeof value === "object") {
27161 valuestring = compress(value);
27162 } else {
27163 throw new Error(
27164 "Don't know what to do with value type " + typeof value + "."
27165 );
27166 }
27167 }
27168 vals.push(keystring + valuestring);
27169 }
27170 vals.push("}");
27171 return vals.join("");
27172 });
27173
27174 /**
27175 * Uncompresses data compressed into custom, base16-like format.
27176 *
27177 * @public
27178 * @function
27179 * @param
27180 * @returns {Type}
27181 */
27182 var uncompress = (API.__fontmetrics__.uncompress = function(data) {
27183 if (typeof data !== "string") {
27184 throw new Error("Invalid argument passed to uncompress.");
27185 }
27186
27187 var output = {},
27188 sign = 1,
27189 stringparts, // undef. will be [] in string mode
27190 activeobject = output,
27191 parentchain = [],
27192 parent_key_pair,
27193 keyparts = "",
27194 valueparts = "",
27195 key, // undef. will be Truthy when Key is resolved.
27196 datalen = data.length - 1, // stripping ending }
27197 ch;
27198
27199 for (var i = 1; i < datalen; i += 1) {
27200 // - { } ' are special.
27201
27202 ch = data[i];
27203
27204 if (ch == "'") {
27205 if (stringparts) {
27206 // end of string mode
27207 key = stringparts.join("");
27208 stringparts = undefined;
27209 } else {
27210 // start of string mode
27211 stringparts = [];
27212 }
27213 } else if (stringparts) {
27214 stringparts.push(ch);
27215 } else if (ch == "{") {
27216 // start of object
27217 parentchain.push([activeobject, key]);
27218 activeobject = {};
27219 key = undefined;
27220 } else if (ch == "}") {
27221 // end of object
27222 parent_key_pair = parentchain.pop();
27223 parent_key_pair[0][parent_key_pair[1]] = activeobject;
27224 key = undefined;
27225 activeobject = parent_key_pair[0];
27226 } else if (ch == "-") {
27227 sign = -1;
27228 } else {
27229 // must be number
27230 if (key === undefined) {
27231 if (mappingUncompress.hasOwnProperty(ch)) {
27232 keyparts += mappingUncompress[ch];
27233 key = parseInt(keyparts, 16) * sign;
27234 sign = +1;
27235 keyparts = "";
27236 } else {
27237 keyparts += ch;
27238 }
27239 } else {
27240 if (mappingUncompress.hasOwnProperty(ch)) {
27241 valueparts += mappingUncompress[ch];
27242 activeobject[key] = parseInt(valueparts, 16) * sign;
27243 sign = +1;
27244 key = undefined;
27245 valueparts = "";
27246 } else {
27247 valueparts += ch;
27248 }
27249 }
27250 }
27251 }
27252 return output;
27253 });
27254
27255 // encoding = 'Unicode'
27256 // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE. NO clever BOM behavior
27257 // Actual 16bit char codes used.
27258 // no multi-byte logic here
27259
27260 // Unicode characters to WinAnsiEncoding:
27261 // {402: 131, 8211: 150, 8212: 151, 8216: 145, 8217: 146, 8218: 130, 8220: 147, 8221: 148, 8222: 132, 8224: 134, 8225: 135, 8226: 149, 8230: 133, 8364: 128, 8240:137, 8249: 139, 8250: 155, 710: 136, 8482: 153, 338: 140, 339: 156, 732: 152, 352: 138, 353: 154, 376: 159, 381: 142, 382: 158}
27262 // as you can see, all Unicode chars are outside of 0-255 range. No char code conflicts.
27263 // this means that you can give Win cp1252 encoded strings to jsPDF for rendering directly
27264 // as well as give strings with some (supported by these fonts) Unicode characters and
27265 // these will be mapped to win cp1252
27266 // for example, you can send char code (cp1252) 0x80 or (unicode) 0x20AC, getting "Euro" glyph displayed in both cases.
27267
27268 var encodingBlock = {
27269 codePages: ["WinAnsiEncoding"],
27270 WinAnsiEncoding: uncompress(
27271 "{19m8n201n9q201o9r201s9l201t9m201u8m201w9n201x9o201y8o202k8q202l8r202m9p202q8p20aw8k203k8t203t8v203u9v2cq8s212m9t15m8w15n9w2dw9s16k8u16l9u17s9z17x8y17y9y}"
27272 )
27273 };
27274 var encodings = {
27275 Unicode: {
27276 Courier: encodingBlock,
27277 "Courier-Bold": encodingBlock,
27278 "Courier-BoldOblique": encodingBlock,
27279 "Courier-Oblique": encodingBlock,
27280 Helvetica: encodingBlock,
27281 "Helvetica-Bold": encodingBlock,
27282 "Helvetica-BoldOblique": encodingBlock,
27283 "Helvetica-Oblique": encodingBlock,
27284 "Times-Roman": encodingBlock,
27285 "Times-Bold": encodingBlock,
27286 "Times-BoldItalic": encodingBlock,
27287 "Times-Italic": encodingBlock
27288 // , 'Symbol'
27289 // , 'ZapfDingbats'
27290 }
27291 };
27292
27293 var fontMetrics = {
27294 Unicode: {
27295 // all sizing numbers are n/fontMetricsFractionOf = one font size unit
27296 // this means that if fontMetricsFractionOf = 1000, and letter A's width is 476, it's
27297 // width is 476/1000 or 47.6% of its height (regardless of font size)
27298 // At this time this value applies to "widths" and "kerning" numbers.
27299
27300 // char code 0 represents "default" (average) width - use it for chars missing in this table.
27301 // key 'fof' represents the "fontMetricsFractionOf" value
27302
27303 "Courier-Oblique": uncompress(
27304 "{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"
27305 ),
27306 "Times-BoldItalic": uncompress(
27307 "{'widths'{k3o2q4ycx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2r202m2n2n3m2o3m2p5n202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5n4l4m4m4m4n4m4o4s4p4m4q4m4r4s4s4y4t2r4u3m4v4m4w3x4x5t4y4s4z4s5k3x5l4s5m4m5n3r5o3x5p4s5q4m5r5t5s4m5t3x5u3x5v2l5w1w5x2l5y3t5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q2l6r3m6s3r6t1w6u1w6v3m6w1w6x4y6y3r6z3m7k3m7l3m7m2r7n2r7o1w7p3r7q2w7r4m7s3m7t2w7u2r7v2n7w1q7x2n7y3t202l3mcl4mal2ram3man3mao3map3mar3mas2lat4uau1uav3maw3way4uaz2lbk2sbl3t'fof'6obo2lbp3tbq3mbr1tbs2lbu1ybv3mbz3mck4m202k3mcm4mcn4mco4mcp4mcq5ycr4mcs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz2w203k6o212m6o2dw2l2cq2l3t3m3u2l17s3x19m3m}'kerning'{cl{4qu5kt5qt5rs17ss5ts}201s{201ss}201t{cks4lscmscnscoscpscls2wu2yu201ts}201x{2wu2yu}2k{201ts}2w{4qx5kx5ou5qx5rs17su5tu}2x{17su5tu5ou}2y{4qx5kx5ou5qx5rs17ss5ts}'fof'-6ofn{17sw5tw5ou5qw5rs}7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qs}3v{17su5tu5os5qs}7p{17su5tu}ck{4qu5kt5qt5rs17ss5ts}4l{4qu5kt5qt5rs17ss5ts}cm{4qu5kt5qt5rs17ss5ts}cn{4qu5kt5qt5rs17ss5ts}co{4qu5kt5qt5rs17ss5ts}cp{4qu5kt5qt5rs17ss5ts}6l{4qu5ou5qw5rt17su5tu}5q{ckuclucmucnucoucpu4lu}5r{ckuclucmucnucoucpu4lu}7q{cksclscmscnscoscps4ls}6p{4qu5ou5qw5rt17sw5tw}ek{4qu5ou5qw5rt17su5tu}el{4qu5ou5qw5rt17su5tu}em{4qu5ou5qw5rt17su5tu}en{4qu5ou5qw5rt17su5tu}eo{4qu5ou5qw5rt17su5tu}ep{4qu5ou5qw5rt17su5tu}es{17ss5ts5qs4qu}et{4qu5ou5qw5rt17sw5tw}eu{4qu5ou5qw5rt17ss5ts}ev{17ss5ts5qs4qu}6z{17sw5tw5ou5qw5rs}fm{17sw5tw5ou5qw5rs}7n{201ts}fo{17sw5tw5ou5qw5rs}fp{17sw5tw5ou5qw5rs}fq{17sw5tw5ou5qw5rs}7r{cksclscmscnscoscps4ls}fs{17sw5tw5ou5qw5rs}ft{17su5tu}fu{17su5tu}fv{17su5tu}fw{17su5tu}fz{cksclscmscnscoscps4ls}}}"
27308 ),
27309 "Helvetica-Bold": uncompress(
27310 "{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}"
27311 ),
27312 Courier: uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
27313 "Courier-BoldOblique": uncompress(
27314 "{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"
27315 ),
27316 "Times-Bold": uncompress(
27317 "{'widths'{k3q2q5ncx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2l202m2n2n3m2o3m2p6o202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5x4l4s4m4m4n4s4o4s4p4m4q3x4r4y4s4y4t2r4u3m4v4y4w4m4x5y4y4s4z4y5k3x5l4y5m4s5n3r5o4m5p4s5q4s5r6o5s4s5t4s5u4m5v2l5w1w5x2l5y3u5z3m6k2l6l3m6m3r6n2w6o3r6p2w6q2l6r3m6s3r6t1w6u2l6v3r6w1w6x5n6y3r6z3m7k3r7l3r7m2w7n2r7o2l7p3r7q3m7r4s7s3m7t3m7u2w7v2r7w1q7x2r7y3o202l3mcl4sal2lam3man3mao3map3mar3mas2lat4uau1yav3maw3tay4uaz2lbk2sbl3t'fof'6obo2lbp3rbr1tbs2lbu2lbv3mbz3mck4s202k3mcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3rek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3m3u2l17s4s19m3m}'kerning'{cl{4qt5ks5ot5qy5rw17sv5tv}201t{cks4lscmscnscoscpscls4wv}2k{201ts}2w{4qu5ku7mu5os5qx5ru17su5tu}2x{17su5tu5ou5qs}2y{4qv5kv7mu5ot5qz5ru17su5tu}'fof'-6o7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qu}3v{17su5tu5os5qu}fu{17su5tu5ou5qu}7p{17su5tu5ou5qu}ck{4qt5ks5ot5qy5rw17sv5tv}4l{4qt5ks5ot5qy5rw17sv5tv}cm{4qt5ks5ot5qy5rw17sv5tv}cn{4qt5ks5ot5qy5rw17sv5tv}co{4qt5ks5ot5qy5rw17sv5tv}cp{4qt5ks5ot5qy5rw17sv5tv}6l{17st5tt5ou5qu}17s{ckuclucmucnucoucpu4lu4wu}5o{ckuclucmucnucoucpu4lu4wu}5q{ckzclzcmzcnzcozcpz4lz4wu}5r{ckxclxcmxcnxcoxcpx4lx4wu}5t{ckuclucmucnucoucpu4lu4wu}7q{ckuclucmucnucoucpu4lu}6p{17sw5tw5ou5qu}ek{17st5tt5qu}el{17st5tt5ou5qu}em{17st5tt5qu}en{17st5tt5qu}eo{17st5tt5qu}ep{17st5tt5ou5qu}es{17ss5ts5qu}et{17sw5tw5ou5qu}eu{17sw5tw5ou5qu}ev{17ss5ts5qu}6z{17sw5tw5ou5qu5rs}fm{17sw5tw5ou5qu5rs}fn{17sw5tw5ou5qu5rs}fo{17sw5tw5ou5qu5rs}fp{17sw5tw5ou5qu5rs}fq{17sw5tw5ou5qu5rs}7r{cktcltcmtcntcotcpt4lt5os}fs{17sw5tw5ou5qu5rs}ft{17su5tu5ou5qu}7m{5os}fv{17su5tu5ou5qu}fw{17su5tu5ou5qu}fz{cksclscmscnscoscps4ls}}}"
27318 ),
27319 Symbol: uncompress(
27320 "{'widths'{k3uaw4r19m3m2k1t2l2l202m2y2n3m2p5n202q6o3k3m2s2l2t2l2v3r2w1t3m3m2y1t2z1wbk2sbl3r'fof'6o3n3m3o3m3p3m3q3m3r3m3s3m3t3m3u1w3v1w3w3r3x3r3y3r3z2wbp3t3l3m5v2l5x2l5z3m2q4yfr3r7v3k7w1o7x3k}'kerning'{'fof'-6o}}"
27321 ),
27322 Helvetica: uncompress(
27323 "{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}"
27324 ),
27325 "Helvetica-BoldOblique": uncompress(
27326 "{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}"
27327 ),
27328 ZapfDingbats: uncompress("{'widths'{k4u2k1w'fof'6o}'kerning'{'fof'-6o}}"),
27329 "Courier-Bold": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
27330 "Times-Italic": uncompress(
27331 "{'widths'{k3n2q4ycx2l201n3m201o5t201s2l201t2l201u2l201w3r201x3r201y3r2k1t2l2l202m2n2n3m2o3m2p5n202q5t2r1p2s2l2t2l2u3m2v4n2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w4n3x4n3y4n3z3m4k5w4l3x4m3x4n4m4o4s4p3x4q3x4r4s4s4s4t2l4u2w4v4m4w3r4x5n4y4m4z4s5k3x5l4s5m3x5n3m5o3r5p4s5q3x5r5n5s3x5t3r5u3r5v2r5w1w5x2r5y2u5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q1w6r3m6s3m6t1w6u1w6v2w6w1w6x4s6y3m6z3m7k3m7l3m7m2r7n2r7o1w7p3m7q2w7r4m7s2w7t2w7u2r7v2s7w1v7x2s7y3q202l3mcl3xal2ram3man3mao3map3mar3mas2lat4wau1vav3maw4nay4waz2lbk2sbl4n'fof'6obo2lbp3mbq3obr1tbs2lbu1zbv3mbz3mck3x202k3mcm3xcn3xco3xcp3xcq5tcr4mcs3xct3xcu3xcv3xcw2l2m2ucy2lcz2ldl4mdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr4nfs3mft3mfu3mfv3mfw3mfz2w203k6o212m6m2dw2l2cq2l3t3m3u2l17s3r19m3m}'kerning'{cl{5kt4qw}201s{201sw}201t{201tw2wy2yy6q-t}201x{2wy2yy}2k{201tw}2w{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}2x{17ss5ts5os}2y{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}'fof'-6o6t{17ss5ts5qs}7t{5os}3v{5qs}7p{17su5tu5qs}ck{5kt4qw}4l{5kt4qw}cm{5kt4qw}cn{5kt4qw}co{5kt4qw}cp{5kt4qw}6l{4qs5ks5ou5qw5ru17su5tu}17s{2ks}5q{ckvclvcmvcnvcovcpv4lv}5r{ckuclucmucnucoucpu4lu}5t{2ks}6p{4qs5ks5ou5qw5ru17su5tu}ek{4qs5ks5ou5qw5ru17su5tu}el{4qs5ks5ou5qw5ru17su5tu}em{4qs5ks5ou5qw5ru17su5tu}en{4qs5ks5ou5qw5ru17su5tu}eo{4qs5ks5ou5qw5ru17su5tu}ep{4qs5ks5ou5qw5ru17su5tu}es{5ks5qs4qs}et{4qs5ks5ou5qw5ru17su5tu}eu{4qs5ks5qw5ru17su5tu}ev{5ks5qs4qs}ex{17ss5ts5qs}6z{4qv5ks5ou5qw5ru17su5tu}fm{4qv5ks5ou5qw5ru17su5tu}fn{4qv5ks5ou5qw5ru17su5tu}fo{4qv5ks5ou5qw5ru17su5tu}fp{4qv5ks5ou5qw5ru17su5tu}fq{4qv5ks5ou5qw5ru17su5tu}7r{5os}fs{4qv5ks5ou5qw5ru17su5tu}ft{17su5tu5qs}fu{17su5tu5qs}fv{17su5tu5qs}fw{17su5tu5qs}}}"
27332 ),
27333 "Times-Roman": uncompress(
27334 "{'widths'{k3n2q4ycx2l201n3m201o6o201s2l201t2l201u2l201w2w201x2w201y2w2k1t2l2l202m2n2n3m2o3m2p5n202q6o2r1m2s2l2t2l2u3m2v3s2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v1w3w3s3x3s3y3s3z2w4k5w4l4s4m4m4n4m4o4s4p3x4q3r4r4s4s4s4t2l4u2r4v4s4w3x4x5t4y4s4z4s5k3r5l4s5m4m5n3r5o3x5p4s5q4s5r5y5s4s5t4s5u3x5v2l5w1w5x2l5y2z5z3m6k2l6l2w6m3m6n2w6o3m6p2w6q2l6r3m6s3m6t1w6u1w6v3m6w1w6x4y6y3m6z3m7k3m7l3m7m2l7n2r7o1w7p3m7q3m7r4s7s3m7t3m7u2w7v3k7w1o7x3k7y3q202l3mcl4sal2lam3man3mao3map3mar3mas2lat4wau1vav3maw3say4waz2lbk2sbl3s'fof'6obo2lbp3mbq2xbr1tbs2lbu1zbv3mbz2wck4s202k3mcm4scn4sco4scp4scq5tcr4mcs3xct3xcu3xcv3xcw2l2m2tcy2lcz2ldl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek2wel2wem2wen2weo2wep2weq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr3sfs3mft3mfu3mfv3mfw3mfz3m203k6o212m6m2dw2l2cq2l3t3m3u1w17s4s19m3m}'kerning'{cl{4qs5ku17sw5ou5qy5rw201ss5tw201ws}201s{201ss}201t{ckw4lwcmwcnwcowcpwclw4wu201ts}2k{201ts}2w{4qs5kw5os5qx5ru17sx5tx}2x{17sw5tw5ou5qu}2y{4qs5kw5os5qx5ru17sx5tx}'fof'-6o7t{ckuclucmucnucoucpu4lu5os5rs}3u{17su5tu5qs}3v{17su5tu5qs}7p{17sw5tw5qs}ck{4qs5ku17sw5ou5qy5rw201ss5tw201ws}4l{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cm{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cn{4qs5ku17sw5ou5qy5rw201ss5tw201ws}co{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cp{4qs5ku17sw5ou5qy5rw201ss5tw201ws}6l{17su5tu5os5qw5rs}17s{2ktclvcmvcnvcovcpv4lv4wuckv}5o{ckwclwcmwcnwcowcpw4lw4wu}5q{ckyclycmycnycoycpy4ly4wu5ms}5r{cktcltcmtcntcotcpt4lt4ws}5t{2ktclvcmvcnvcovcpv4lv4wuckv}7q{cksclscmscnscoscps4ls}6p{17su5tu5qw5rs}ek{5qs5rs}el{17su5tu5os5qw5rs}em{17su5tu5os5qs5rs}en{17su5qs5rs}eo{5qs5rs}ep{17su5tu5os5qw5rs}es{5qs}et{17su5tu5qw5rs}eu{17su5tu5qs5rs}ev{5qs}6z{17sv5tv5os5qx5rs}fm{5os5qt5rs}fn{17sv5tv5os5qx5rs}fo{17sv5tv5os5qx5rs}fp{5os5qt5rs}fq{5os5qt5rs}7r{ckuclucmucnucoucpu4lu5os}fs{17sv5tv5os5qx5rs}ft{17ss5ts5qs}fu{17sw5tw5qs}fv{17sw5tw5qs}fw{17ss5ts5qs}fz{ckuclucmucnucoucpu4lu5os5rs}}}"
27335 ),
27336 "Helvetica-Oblique": uncompress(
27337 "{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}"
27338 )
27339 }
27340 };
27341
27342 /*
27343 This event handler is fired when a new jsPDF object is initialized
27344 This event handler appends metrics data to standard fonts within
27345 that jsPDF instance. The metrics are mapped over Unicode character
27346 codes, NOT CIDs or other codes matching the StandardEncoding table of the
27347 standard PDF fonts.
27348 Future:
27349 Also included is the encoding maping table, converting Unicode (UCS-2, UTF-16)
27350 char codes to StandardEncoding character codes. The encoding table is to be used
27351 somewhere around "pdfEscape" call.
27352 */
27353 API.events.push([
27354 "addFont",
27355 function(data) {
27356 var font = data.font;
27357
27358 var metrics = fontMetrics["Unicode"][font.postScriptName];
27359 if (metrics) {
27360 font.metadata["Unicode"] = {};
27361 font.metadata["Unicode"].widths = metrics.widths;
27362 font.metadata["Unicode"].kerning = metrics.kerning;
27363 }
27364
27365 var encodingBlock = encodings["Unicode"][font.postScriptName];
27366 if (encodingBlock) {
27367 font.metadata["Unicode"].encoding = encodingBlock;
27368 font.encoding = encodingBlock.codePages[0];
27369 }
27370 }
27371 ]); // end of adding event handler
27372 })(jsPDF.API);
27373
27374 /**
27375 * @license
27376 * Licensed under the MIT License.
27377 * http://opensource.org/licenses/mit-license
27378 */
27379
27380 /**
27381 * @name ttfsupport
27382 * @module
27383 */
27384 (function(jsPDF) {
27385
27386 var binaryStringToUint8Array = function(binary_string) {
27387 var len = binary_string.length;
27388 var bytes = new Uint8Array(len);
27389 for (var i = 0; i < len; i++) {
27390 bytes[i] = binary_string.charCodeAt(i);
27391 }
27392 return bytes;
27393 };
27394
27395 var addFont = function(font, file) {
27396 // eslint-disable-next-line no-control-regex
27397 if (/^\x00\x01\x00\x00/.test(file)) {
27398 file = binaryStringToUint8Array(file);
27399 } else {
27400 file = binaryStringToUint8Array(atob(file));
27401 }
27402 font.metadata = jsPDF.API.TTFFont.open(file);
27403 font.metadata.Unicode = font.metadata.Unicode || {
27404 encoding: {},
27405 kerning: {},
27406 widths: []
27407 };
27408 font.metadata.glyIdsUsed = [0];
27409 };
27410
27411 jsPDF.API.events.push([
27412 "addFont",
27413 function(data) {
27414 var file = undefined;
27415 var font = data.font;
27416 var instance = data.instance;
27417 if (font.isStandardFont) {
27418 return;
27419 }
27420 if (typeof instance !== "undefined") {
27421 if (instance.existsFileInVFS(font.postScriptName) === false) {
27422 file = instance.loadFile(font.postScriptName);
27423 } else {
27424 file = instance.getFileFromVFS(font.postScriptName);
27425 }
27426 if (typeof file !== "string") {
27427 throw new Error(
27428 "Font is not stored as string-data in vFS, import fonts or remove declaration doc.addFont('" +
27429 font.postScriptName +
27430 "')."
27431 );
27432 }
27433 addFont(font, file);
27434 } else {
27435 throw new Error(
27436 "Font does not exist in vFS, import fonts or remove declaration doc.addFont('" +
27437 font.postScriptName +
27438 "')."
27439 );
27440 }
27441 }
27442 ]); // end of adding event handler
27443 })(jsPDF);
27444
27445 /** @license
27446 * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
27447 *
27448 * Permission is hereby granted, free of charge, to any person obtaining
27449 * a copy of this software and associated documentation files (the
27450 * "Software"), to deal in the Software without restriction, including
27451 * without limitation the rights to use, copy, modify, merge, publish,
27452 * distribute, sublicense, and/or sell copies of the Software, and to
27453 * permit persons to whom the Software is furnished to do so, subject to
27454 * the following conditions:
27455 *
27456 * The above copyright notice and this permission notice shall be
27457 * included in all copies or substantial portions of the Software.
27458 *
27459 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27460 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27461 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27462 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27463 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27464 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27465 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27466 * ====================================================================
27467 */
27468
27469 /**
27470 * jsPDF SVG plugin
27471 *
27472 * @name svg
27473 * @module
27474 */
27475 (function(jsPDFAPI) {
27476
27477 function loadCanvg() {
27478 return (function() {
27479 if (globalObject["canvg"]) {
27480 return Promise.resolve(globalObject["canvg"]);
27481 }
27482
27483
27484 if (typeof exports === "object" && typeof module !== "undefined") {
27485 return new Promise(function(resolve, reject) {
27486 try {
27487 resolve(require("canvg"));
27488 } catch (e) {
27489 reject(e);
27490 }
27491 });
27492 }
27493 if (typeof define === "function" && define.amd) {
27494 return new Promise(function(resolve, reject) {
27495 try {
27496 require(["canvg"], resolve);
27497 } catch (e) {
27498 reject(e);
27499 }
27500 });
27501 }
27502 return Promise.reject(new Error("Could not load canvg"));
27503 })()
27504 .catch(function(e) {
27505 return Promise.reject(new Error("Could not load canvg: " + e));
27506 })
27507 .then(function(canvg) {
27508 return canvg.default ? canvg.default : canvg;
27509 });
27510 }
27511
27512 /**
27513 * Parses SVG XML and saves it as image into the PDF.
27514 *
27515 * Depends on canvas-element and canvg
27516 *
27517 * @name addSvgAsImage
27518 * @public
27519 * @function
27520 * @param {string} SVG-Data as Text
27521 * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
27522 * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
27523 * @param {number} width of SVG-Image (in units declared at inception of PDF document)
27524 * @param {number} height of SVG-Image (in units declared at inception of PDF document)
27525 * @param {string} alias of SVG-Image (if used multiple times)
27526 * @param {string} compression of the generated JPEG, can have the values 'NONE', 'FAST', 'MEDIUM' and 'SLOW'
27527 * @param {number} rotation of the image in degrees (0-359)
27528 *
27529 * @returns jsPDF jsPDF-instance
27530 */
27531 jsPDFAPI.addSvgAsImage = function(
27532 svg,
27533 x,
27534 y,
27535 w,
27536 h,
27537 alias,
27538 compression,
27539 rotation
27540 ) {
27541 if (isNaN(x) || isNaN(y)) {
27542 console.error("jsPDF.addSvgAsImage: Invalid coordinates", arguments);
27543 throw new Error("Invalid coordinates passed to jsPDF.addSvgAsImage");
27544 }
27545
27546 if (isNaN(w) || isNaN(h)) {
27547 console.error("jsPDF.addSvgAsImage: Invalid measurements", arguments);
27548 throw new Error(
27549 "Invalid measurements (width and/or height) passed to jsPDF.addSvgAsImage"
27550 );
27551 }
27552
27553 var canvas = document.createElement("canvas");
27554 canvas.width = w;
27555 canvas.height = h;
27556 var ctx = canvas.getContext("2d");
27557 ctx.fillStyle = "#fff"; /// set white fill style
27558 ctx.fillRect(0, 0, canvas.width, canvas.height);
27559
27560 var options = {
27561 ignoreMouse: true,
27562 ignoreAnimation: true,
27563 ignoreDimensions: true
27564 };
27565 var doc = this;
27566 return loadCanvg()
27567 .then(
27568 function(canvg) {
27569 return canvg.fromString(ctx, svg, options);
27570 },
27571 function() {
27572 return Promise.reject(new Error("Could not load canvg."));
27573 }
27574 )
27575 .then(function(instance) {
27576 return instance.render(options);
27577 })
27578 .then(function() {
27579 doc.addImage(
27580 canvas.toDataURL("image/jpeg", 1.0),
27581 x,
27582 y,
27583 w,
27584 h,
27585 compression,
27586 rotation
27587 );
27588 });
27589 };
27590 })(jsPDF.API);
27591
27592 /**
27593 * @license
27594 * ====================================================================
27595 * Copyright (c) 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br
27596 *
27597 * Permission is hereby granted, free of charge, to any person obtaining
27598 * a copy of this software and associated documentation files (the
27599 * "Software"), to deal in the Software without restriction, including
27600 * without limitation the rights to use, copy, modify, merge, publish,
27601 * distribute, sublicense, and/or sell copies of the Software, and to
27602 * permit persons to whom the Software is furnished to do so, subject to
27603 * the following conditions:
27604 *
27605 * The above copyright notice and this permission notice shall be
27606 * included in all copies or substantial portions of the Software.
27607 *
27608 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27609 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27610 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27611 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27612 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27613 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27614 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27615 * ====================================================================
27616 */
27617
27618 /**
27619 * jsPDF total_pages plugin
27620 * @name total_pages
27621 * @module
27622 */
27623 (function(jsPDFAPI) {
27624 /**
27625 * @name putTotalPages
27626 * @function
27627 * @param {string} pageExpression Regular Expression
27628 * @returns {jsPDF} jsPDF-instance
27629 */
27630
27631 jsPDFAPI.putTotalPages = function(pageExpression) {
27632
27633 var replaceExpression;
27634 var totalNumberOfPages = 0;
27635 if (parseInt(this.internal.getFont().id.substr(1), 10) < 15) {
27636 replaceExpression = new RegExp(pageExpression, "g");
27637 totalNumberOfPages = this.internal.getNumberOfPages();
27638 } else {
27639 replaceExpression = new RegExp(
27640 this.pdfEscape16(pageExpression, this.internal.getFont()),
27641 "g"
27642 );
27643 totalNumberOfPages = this.pdfEscape16(
27644 this.internal.getNumberOfPages() + "",
27645 this.internal.getFont()
27646 );
27647 }
27648
27649 for (var n = 1; n <= this.internal.getNumberOfPages(); n++) {
27650 for (var i = 0; i < this.internal.pages[n].length; i++) {
27651 this.internal.pages[n][i] = this.internal.pages[n][i].replace(
27652 replaceExpression,
27653 totalNumberOfPages
27654 );
27655 }
27656 }
27657
27658 return this;
27659 };
27660 })(jsPDF.API);
27661
27662 /**
27663 * @license
27664 * jsPDF viewerPreferences Plugin
27665 * @author Aras Abbasi (github.com/arasabbasi)
27666 * Licensed under the MIT License.
27667 * http://opensource.org/licenses/mit-license
27668 */
27669
27670 /**
27671 * Adds the ability to set ViewerPreferences and by thus
27672 * controlling the way the document is to be presented on the
27673 * screen or in print.
27674 * @name viewerpreferences
27675 * @module
27676 */
27677 (function(jsPDFAPI) {
27678 /**
27679 * Set the ViewerPreferences of the generated PDF
27680 *
27681 * @name viewerPreferences
27682 * @function
27683 * @public
27684 * @param {Object} options Array with the ViewerPreferences<br />
27685 * Example: doc.viewerPreferences({"FitWindow":true});<br />
27686 * <br />
27687 * You can set following preferences:<br />
27688 * <br/>
27689 * <b>HideToolbar</b> <i>(boolean)</i><br />
27690 * Default value: false<br />
27691 * <br />
27692 * <b>HideMenubar</b> <i>(boolean)</i><br />
27693 * Default value: false.<br />
27694 * <br />
27695 * <b>HideWindowUI</b> <i>(boolean)</i><br />
27696 * Default value: false.<br />
27697 * <br />
27698 * <b>FitWindow</b> <i>(boolean)</i><br />
27699 * Default value: false.<br />
27700 * <br />
27701 * <b>CenterWindow</b> <i>(boolean)</i><br />
27702 * Default value: false<br />
27703 * <br />
27704 * <b>DisplayDocTitle</b> <i>(boolean)</i><br />
27705 * Default value: false.<br />
27706 * <br />
27707 * <b>NonFullScreenPageMode</b> <i>(string)</i><br />
27708 * Possible values: UseNone, UseOutlines, UseThumbs, UseOC<br />
27709 * Default value: UseNone<br/>
27710 * <br />
27711 * <b>Direction</b> <i>(string)</i><br />
27712 * Possible values: L2R, R2L<br />
27713 * Default value: L2R.<br />
27714 * <br />
27715 * <b>ViewArea</b> <i>(string)</i><br />
27716 * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
27717 * Default value: CropBox.<br />
27718 * <br />
27719 * <b>ViewClip</b> <i>(string)</i><br />
27720 * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
27721 * Default value: CropBox<br />
27722 * <br />
27723 * <b>PrintArea</b> <i>(string)</i><br />
27724 * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
27725 * Default value: CropBox<br />
27726 * <br />
27727 * <b>PrintClip</b> <i>(string)</i><br />
27728 * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
27729 * Default value: CropBox.<br />
27730 * <br />
27731 * <b>PrintScaling</b> <i>(string)</i><br />
27732 * Possible values: AppDefault, None<br />
27733 * Default value: AppDefault.<br />
27734 * <br />
27735 * <b>Duplex</b> <i>(string)</i><br />
27736 * Possible values: Simplex, DuplexFlipLongEdge, DuplexFlipShortEdge
27737 * Default value: none<br />
27738 * <br />
27739 * <b>PickTrayByPDFSize</b> <i>(boolean)</i><br />
27740 * Default value: false<br />
27741 * <br />
27742 * <b>PrintPageRange</b> <i>(Array)</i><br />
27743 * Example: [[1,5], [7,9]]<br />
27744 * Default value: as defined by PDF viewer application<br />
27745 * <br />
27746 * <b>NumCopies</b> <i>(Number)</i><br />
27747 * Possible values: 1, 2, 3, 4, 5<br />
27748 * Default value: 1<br />
27749 * <br />
27750 * For more information see the PDF Reference, sixth edition on Page 577
27751 * @param {boolean} doReset True to reset the settings
27752 * @function
27753 * @returns jsPDF jsPDF-instance
27754 * @example
27755 * var doc = new jsPDF()
27756 * doc.text('This is a test', 10, 10)
27757 * doc.viewerPreferences({'FitWindow': true}, true)
27758 * doc.save("viewerPreferences.pdf")
27759 *
27760 * // Example printing 10 copies, using cropbox, and hiding UI.
27761 * doc.viewerPreferences({
27762 * 'HideWindowUI': true,
27763 * 'PrintArea': 'CropBox',
27764 * 'NumCopies': 10
27765 * })
27766 */
27767 jsPDFAPI.viewerPreferences = function(options, doReset) {
27768 options = options || {};
27769 doReset = doReset || false;
27770
27771 var configuration;
27772 var configurationTemplate = {
27773 HideToolbar: {
27774 defaultValue: false,
27775 value: false,
27776 type: "boolean",
27777 explicitSet: false,
27778 valueSet: [true, false],
27779 pdfVersion: 1.3
27780 },
27781 HideMenubar: {
27782 defaultValue: false,
27783 value: false,
27784 type: "boolean",
27785 explicitSet: false,
27786 valueSet: [true, false],
27787 pdfVersion: 1.3
27788 },
27789 HideWindowUI: {
27790 defaultValue: false,
27791 value: false,
27792 type: "boolean",
27793 explicitSet: false,
27794 valueSet: [true, false],
27795 pdfVersion: 1.3
27796 },
27797 FitWindow: {
27798 defaultValue: false,
27799 value: false,
27800 type: "boolean",
27801 explicitSet: false,
27802 valueSet: [true, false],
27803 pdfVersion: 1.3
27804 },
27805 CenterWindow: {
27806 defaultValue: false,
27807 value: false,
27808 type: "boolean",
27809 explicitSet: false,
27810 valueSet: [true, false],
27811 pdfVersion: 1.3
27812 },
27813 DisplayDocTitle: {
27814 defaultValue: false,
27815 value: false,
27816 type: "boolean",
27817 explicitSet: false,
27818 valueSet: [true, false],
27819 pdfVersion: 1.4
27820 },
27821 NonFullScreenPageMode: {
27822 defaultValue: "UseNone",
27823 value: "UseNone",
27824 type: "name",
27825 explicitSet: false,
27826 valueSet: ["UseNone", "UseOutlines", "UseThumbs", "UseOC"],
27827 pdfVersion: 1.3
27828 },
27829 Direction: {
27830 defaultValue: "L2R",
27831 value: "L2R",
27832 type: "name",
27833 explicitSet: false,
27834 valueSet: ["L2R", "R2L"],
27835 pdfVersion: 1.3
27836 },
27837 ViewArea: {
27838 defaultValue: "CropBox",
27839 value: "CropBox",
27840 type: "name",
27841 explicitSet: false,
27842 valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
27843 pdfVersion: 1.4
27844 },
27845 ViewClip: {
27846 defaultValue: "CropBox",
27847 value: "CropBox",
27848 type: "name",
27849 explicitSet: false,
27850 valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
27851 pdfVersion: 1.4
27852 },
27853 PrintArea: {
27854 defaultValue: "CropBox",
27855 value: "CropBox",
27856 type: "name",
27857 explicitSet: false,
27858 valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
27859 pdfVersion: 1.4
27860 },
27861 PrintClip: {
27862 defaultValue: "CropBox",
27863 value: "CropBox",
27864 type: "name",
27865 explicitSet: false,
27866 valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
27867 pdfVersion: 1.4
27868 },
27869 PrintScaling: {
27870 defaultValue: "AppDefault",
27871 value: "AppDefault",
27872 type: "name",
27873 explicitSet: false,
27874 valueSet: ["AppDefault", "None"],
27875 pdfVersion: 1.6
27876 },
27877 Duplex: {
27878 defaultValue: "",
27879 value: "none",
27880 type: "name",
27881 explicitSet: false,
27882 valueSet: [
27883 "Simplex",
27884 "DuplexFlipShortEdge",
27885 "DuplexFlipLongEdge",
27886 "none"
27887 ],
27888 pdfVersion: 1.7
27889 },
27890 PickTrayByPDFSize: {
27891 defaultValue: false,
27892 value: false,
27893 type: "boolean",
27894 explicitSet: false,
27895 valueSet: [true, false],
27896 pdfVersion: 1.7
27897 },
27898 PrintPageRange: {
27899 defaultValue: "",
27900 value: "",
27901 type: "array",
27902 explicitSet: false,
27903 valueSet: null,
27904 pdfVersion: 1.7
27905 },
27906 NumCopies: {
27907 defaultValue: 1,
27908 value: 1,
27909 type: "integer",
27910 explicitSet: false,
27911 valueSet: null,
27912 pdfVersion: 1.7
27913 }
27914 };
27915
27916 var configurationKeys = Object.keys(configurationTemplate);
27917
27918 var rangeArray = [];
27919 var i = 0;
27920 var j = 0;
27921 var k = 0;
27922 var isValid;
27923
27924 var method;
27925 var value;
27926
27927 function arrayContainsElement(array, element) {
27928 var iterator;
27929 var result = false;
27930
27931 for (iterator = 0; iterator < array.length; iterator += 1) {
27932 if (array[iterator] === element) {
27933 result = true;
27934 }
27935 }
27936 return result;
27937 }
27938
27939 if (this.internal.viewerpreferences === undefined) {
27940 this.internal.viewerpreferences = {};
27941 this.internal.viewerpreferences.configuration = JSON.parse(
27942 JSON.stringify(configurationTemplate)
27943 );
27944 this.internal.viewerpreferences.isSubscribed = false;
27945 }
27946 configuration = this.internal.viewerpreferences.configuration;
27947
27948 if (options === "reset" || doReset === true) {
27949 var len = configurationKeys.length;
27950
27951 for (k = 0; k < len; k += 1) {
27952 configuration[configurationKeys[k]].value =
27953 configuration[configurationKeys[k]].defaultValue;
27954 configuration[configurationKeys[k]].explicitSet = false;
27955 }
27956 }
27957
27958 if (typeof options === "object") {
27959 for (method in options) {
27960 value = options[method];
27961 if (
27962 arrayContainsElement(configurationKeys, method) &&
27963 value !== undefined
27964 ) {
27965 if (
27966 configuration[method].type === "boolean" &&
27967 typeof value === "boolean"
27968 ) {
27969 configuration[method].value = value;
27970 } else if (
27971 configuration[method].type === "name" &&
27972 arrayContainsElement(configuration[method].valueSet, value)
27973 ) {
27974 configuration[method].value = value;
27975 } else if (
27976 configuration[method].type === "integer" &&
27977 Number.isInteger(value)
27978 ) {
27979 configuration[method].value = value;
27980 } else if (configuration[method].type === "array") {
27981 for (i = 0; i < value.length; i += 1) {
27982 isValid = true;
27983 if (value[i].length === 1 && typeof value[i][0] === "number") {
27984 rangeArray.push(String(value[i] - 1));
27985 } else if (value[i].length > 1) {
27986 for (j = 0; j < value[i].length; j += 1) {
27987 if (typeof value[i][j] !== "number") {
27988 isValid = false;
27989 }
27990 }
27991 if (isValid === true) {
27992 rangeArray.push([value[i][0] - 1, value[i][1] - 1].join(" "));
27993 }
27994 }
27995 }
27996 configuration[method].value = "[" + rangeArray.join(" ") + "]";
27997 } else {
27998 configuration[method].value = configuration[method].defaultValue;
27999 }
28000
28001 configuration[method].explicitSet = true;
28002 }
28003 }
28004 }
28005
28006 if (this.internal.viewerpreferences.isSubscribed === false) {
28007 this.internal.events.subscribe("putCatalog", function() {
28008 var pdfDict = [];
28009 var vPref;
28010 for (vPref in configuration) {
28011 if (configuration[vPref].explicitSet === true) {
28012 if (configuration[vPref].type === "name") {
28013 pdfDict.push("/" + vPref + " /" + configuration[vPref].value);
28014 } else {
28015 pdfDict.push("/" + vPref + " " + configuration[vPref].value);
28016 }
28017 }
28018 }
28019 if (pdfDict.length !== 0) {
28020 this.internal.write(
28021 "/ViewerPreferences\n<<\n" + pdfDict.join("\n") + "\n>>"
28022 );
28023 }
28024 });
28025 this.internal.viewerpreferences.isSubscribed = true;
28026 }
28027
28028 this.internal.viewerpreferences.configuration = configuration;
28029 return this;
28030 };
28031 })(jsPDF.API);
28032
28033 /** ====================================================================
28034 * @license
28035 * jsPDF XMP metadata plugin
28036 * Copyright (c) 2016 Jussi Utunen, u-jussi@suomi24.fi
28037 *
28038 * Permission is hereby granted, free of charge, to any person obtaining
28039 * a copy of this software and associated documentation files (the
28040 * "Software"), to deal in the Software without restriction, including
28041 * without limitation the rights to use, copy, modify, merge, publish,
28042 * distribute, sublicense, and/or sell copies of the Software, and to
28043 * permit persons to whom the Software is furnished to do so, subject to
28044 * the following conditions:
28045 *
28046 * The above copyright notice and this permission notice shall be
28047 * included in all copies or substantial portions of the Software.
28048 *
28049 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28050 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28051 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28052 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28053 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28054 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28055 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28056 * ====================================================================
28057 */
28058
28059 /**
28060 * @name xmp_metadata
28061 * @module
28062 */
28063 (function(jsPDFAPI) {
28064
28065 var postPutResources = function() {
28066 var xmpmeta_beginning = '<x:xmpmeta xmlns:x="adobe:ns:meta/">';
28067 var rdf_beginning =
28068 '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="" xmlns:jspdf="' +
28069 this.internal.__metadata__.namespaceuri +
28070 '"><jspdf:metadata>';
28071 var rdf_ending = "</jspdf:metadata></rdf:Description></rdf:RDF>";
28072 var xmpmeta_ending = "</x:xmpmeta>";
28073 var utf8_xmpmeta_beginning = unescape(
28074 encodeURIComponent(xmpmeta_beginning)
28075 );
28076 var utf8_rdf_beginning = unescape(encodeURIComponent(rdf_beginning));
28077 var utf8_metadata = unescape(
28078 encodeURIComponent(this.internal.__metadata__.metadata)
28079 );
28080 var utf8_rdf_ending = unescape(encodeURIComponent(rdf_ending));
28081 var utf8_xmpmeta_ending = unescape(encodeURIComponent(xmpmeta_ending));
28082
28083 var total_len =
28084 utf8_rdf_beginning.length +
28085 utf8_metadata.length +
28086 utf8_rdf_ending.length +
28087 utf8_xmpmeta_beginning.length +
28088 utf8_xmpmeta_ending.length;
28089
28090 this.internal.__metadata__.metadata_object_number = this.internal.newObject();
28091 this.internal.write(
28092 "<< /Type /Metadata /Subtype /XML /Length " + total_len + " >>"
28093 );
28094 this.internal.write("stream");
28095 this.internal.write(
28096 utf8_xmpmeta_beginning +
28097 utf8_rdf_beginning +
28098 utf8_metadata +
28099 utf8_rdf_ending +
28100 utf8_xmpmeta_ending
28101 );
28102 this.internal.write("endstream");
28103 this.internal.write("endobj");
28104 };
28105
28106 var putCatalog = function() {
28107 if (this.internal.__metadata__.metadata_object_number) {
28108 this.internal.write(
28109 "/Metadata " +
28110 this.internal.__metadata__.metadata_object_number +
28111 " 0 R"
28112 );
28113 }
28114 };
28115
28116 /**
28117 * Adds XMP formatted metadata to PDF
28118 *
28119 * @name addMetadata
28120 * @function
28121 * @param {String} metadata The actual metadata to be added. The metadata shall be stored as XMP simple value. Note that if the metadata string contains XML markup characters "<", ">" or "&", those characters should be written using XML entities.
28122 * @param {String} namespaceuri Sets the namespace URI for the metadata. Last character should be slash or hash.
28123 * @returns {jsPDF} jsPDF-instance
28124 */
28125 jsPDFAPI.addMetadata = function(metadata, namespaceuri) {
28126 if (typeof this.internal.__metadata__ === "undefined") {
28127 this.internal.__metadata__ = {
28128 metadata: metadata,
28129 namespaceuri: namespaceuri || "http://jspdf.default.namespaceuri/"
28130 };
28131 this.internal.events.subscribe("putCatalog", putCatalog);
28132
28133 this.internal.events.subscribe("postPutResources", postPutResources);
28134 }
28135 return this;
28136 };
28137 })(jsPDF.API);
28138
28139 /**
28140 * @name utf8
28141 * @module
28142 */
28143 (function(jsPDF) {
28144 var jsPDFAPI = jsPDF.API;
28145
28146 /***************************************************************************************************/
28147 /* function : pdfEscape16 */
28148 /* comment : The character id of a 2-byte string is converted to a hexadecimal number by obtaining */
28149 /* the corresponding glyph id and width, and then adding padding to the string. */
28150 /***************************************************************************************************/
28151 var pdfEscape16 = (jsPDFAPI.pdfEscape16 = function(text, font) {
28152 var widths = font.metadata.Unicode.widths;
28153 var padz = ["", "0", "00", "000", "0000"];
28154 var ar = [""];
28155 for (var i = 0, l = text.length, t; i < l; ++i) {
28156 t = font.metadata.characterToGlyph(text.charCodeAt(i));
28157 font.metadata.glyIdsUsed.push(t);
28158 font.metadata.toUnicode[t] = text.charCodeAt(i);
28159 if (widths.indexOf(t) == -1) {
28160 widths.push(t);
28161 widths.push([parseInt(font.metadata.widthOfGlyph(t), 10)]);
28162 }
28163 if (t == "0") {
28164 //Spaces are not allowed in cmap.
28165 return ar.join("");
28166 } else {
28167 t = t.toString(16);
28168 ar.push(padz[4 - t.length], t);
28169 }
28170 }
28171 return ar.join("");
28172 });
28173
28174 var toUnicodeCmap = function(map) {
28175 var code, codes, range, unicode, unicodeMap, _i, _len;
28176 unicodeMap =
28177 "/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";
28178 codes = Object.keys(map).sort(function(a, b) {
28179 return a - b;
28180 });
28181
28182 range = [];
28183 for (_i = 0, _len = codes.length; _i < _len; _i++) {
28184 code = codes[_i];
28185 if (range.length >= 100) {
28186 unicodeMap +=
28187 "\n" +
28188 range.length +
28189 " beginbfchar\n" +
28190 range.join("\n") +
28191 "\nendbfchar";
28192 range = [];
28193 }
28194
28195 if (
28196 map[code] !== undefined &&
28197 map[code] !== null &&
28198 typeof map[code].toString === "function"
28199 ) {
28200 unicode = ("0000" + map[code].toString(16)).slice(-4);
28201 code = ("0000" + (+code).toString(16)).slice(-4);
28202 range.push("<" + code + "><" + unicode + ">");
28203 }
28204 }
28205
28206 if (range.length) {
28207 unicodeMap +=
28208 "\n" +
28209 range.length +
28210 " beginbfchar\n" +
28211 range.join("\n") +
28212 "\nendbfchar\n";
28213 }
28214 unicodeMap +=
28215 "endcmap\nCMapName currentdict /CMap defineresource pop\nend\nend";
28216 return unicodeMap;
28217 };
28218
28219 var identityHFunction = function(options) {
28220 var font = options.font;
28221 var out = options.out;
28222 var newObject = options.newObject;
28223 var putStream = options.putStream;
28224 var pdfEscapeWithNeededParanthesis = options.pdfEscapeWithNeededParanthesis;
28225
28226 if (
28227 font.metadata instanceof jsPDF.API.TTFFont &&
28228 font.encoding === "Identity-H"
28229 ) {
28230 //Tag with Identity-H
28231 var widths = font.metadata.Unicode.widths;
28232 var data = font.metadata.subset.encode(font.metadata.glyIdsUsed, 1);
28233 var pdfOutput = data;
28234 var pdfOutput2 = "";
28235 for (var i = 0; i < pdfOutput.length; i++) {
28236 pdfOutput2 += String.fromCharCode(pdfOutput[i]);
28237 }
28238 var fontTable = newObject();
28239 putStream({ data: pdfOutput2, addLength1: true, objectId: fontTable });
28240 out("endobj");
28241
28242 var cmap = newObject();
28243 var cmapData = toUnicodeCmap(font.metadata.toUnicode);
28244 putStream({ data: cmapData, addLength1: true, objectId: cmap });
28245 out("endobj");
28246
28247 var fontDescriptor = newObject();
28248 out("<<");
28249 out("/Type /FontDescriptor");
28250 out("/FontName /" + pdfEscapeWithNeededParanthesis(font.fontName));
28251 out("/FontFile2 " + fontTable + " 0 R");
28252 out("/FontBBox " + jsPDF.API.PDFObject.convert(font.metadata.bbox));
28253 out("/Flags " + font.metadata.flags);
28254 out("/StemV " + font.metadata.stemV);
28255 out("/ItalicAngle " + font.metadata.italicAngle);
28256 out("/Ascent " + font.metadata.ascender);
28257 out("/Descent " + font.metadata.decender);
28258 out("/CapHeight " + font.metadata.capHeight);
28259 out(">>");
28260 out("endobj");
28261
28262 var DescendantFont = newObject();
28263 out("<<");
28264 out("/Type /Font");
28265 out("/BaseFont /" + pdfEscapeWithNeededParanthesis(font.fontName));
28266 out("/FontDescriptor " + fontDescriptor + " 0 R");
28267 out("/W " + jsPDF.API.PDFObject.convert(widths));
28268 out("/CIDToGIDMap /Identity");
28269 out("/DW 1000");
28270 out("/Subtype /CIDFontType2");
28271 out("/CIDSystemInfo");
28272 out("<<");
28273 out("/Supplement 0");
28274 out("/Registry (Adobe)");
28275 out("/Ordering (" + font.encoding + ")");
28276 out(">>");
28277 out(">>");
28278 out("endobj");
28279
28280 font.objectNumber = newObject();
28281 out("<<");
28282 out("/Type /Font");
28283 out("/Subtype /Type0");
28284 out("/ToUnicode " + cmap + " 0 R");
28285 out("/BaseFont /" + pdfEscapeWithNeededParanthesis(font.fontName));
28286 out("/Encoding /" + font.encoding);
28287 out("/DescendantFonts [" + DescendantFont + " 0 R]");
28288 out(">>");
28289 out("endobj");
28290
28291 font.isAlreadyPutted = true;
28292 }
28293 };
28294
28295 jsPDFAPI.events.push([
28296 "putFont",
28297 function(args) {
28298 identityHFunction(args);
28299 }
28300 ]);
28301
28302 var winAnsiEncodingFunction = function(options) {
28303 var font = options.font;
28304 var out = options.out;
28305 var newObject = options.newObject;
28306 var putStream = options.putStream;
28307 var pdfEscapeWithNeededParanthesis = options.pdfEscapeWithNeededParanthesis;
28308
28309 if (
28310 font.metadata instanceof jsPDF.API.TTFFont &&
28311 font.encoding === "WinAnsiEncoding"
28312 ) {
28313 //Tag with WinAnsi encoding
28314 var data = font.metadata.rawData;
28315 var pdfOutput = data;
28316 var pdfOutput2 = "";
28317 for (var i = 0; i < pdfOutput.length; i++) {
28318 pdfOutput2 += String.fromCharCode(pdfOutput[i]);
28319 }
28320 var fontTable = newObject();
28321 putStream({ data: pdfOutput2, addLength1: true, objectId: fontTable });
28322 out("endobj");
28323
28324 var cmap = newObject();
28325 var cmapData = toUnicodeCmap(font.metadata.toUnicode);
28326 putStream({ data: cmapData, addLength1: true, objectId: cmap });
28327 out("endobj");
28328
28329 var fontDescriptor = newObject();
28330 out("<<");
28331 out("/Descent " + font.metadata.decender);
28332 out("/CapHeight " + font.metadata.capHeight);
28333 out("/StemV " + font.metadata.stemV);
28334 out("/Type /FontDescriptor");
28335 out("/FontFile2 " + fontTable + " 0 R");
28336 out("/Flags 96");
28337 out("/FontBBox " + jsPDF.API.PDFObject.convert(font.metadata.bbox));
28338 out("/FontName /" + pdfEscapeWithNeededParanthesis(font.fontName));
28339 out("/ItalicAngle " + font.metadata.italicAngle);
28340 out("/Ascent " + font.metadata.ascender);
28341 out(">>");
28342 out("endobj");
28343 font.objectNumber = newObject();
28344 for (var j = 0; j < font.metadata.hmtx.widths.length; j++) {
28345 font.metadata.hmtx.widths[j] = parseInt(
28346 font.metadata.hmtx.widths[j] * (1000 / font.metadata.head.unitsPerEm)
28347 ); //Change the width of Em units to Point units.
28348 }
28349 out(
28350 "<</Subtype/TrueType/Type/Font/ToUnicode " +
28351 cmap +
28352 " 0 R/BaseFont/" +
28353 pdfEscapeWithNeededParanthesis(font.fontName) +
28354 "/FontDescriptor " +
28355 fontDescriptor +
28356 " 0 R" +
28357 "/Encoding/" +
28358 font.encoding +
28359 " /FirstChar 29 /LastChar 255 /Widths " +
28360 jsPDF.API.PDFObject.convert(font.metadata.hmtx.widths) +
28361 ">>"
28362 );
28363 out("endobj");
28364 font.isAlreadyPutted = true;
28365 }
28366 };
28367
28368 jsPDFAPI.events.push([
28369 "putFont",
28370 function(args) {
28371 winAnsiEncodingFunction(args);
28372 }
28373 ]);
28374
28375 var utf8TextFunction = function(args) {
28376 var text = args.text || "";
28377 var x = args.x;
28378 var y = args.y;
28379 var options = args.options || {};
28380 var mutex = args.mutex || {};
28381
28382 var pdfEscape = mutex.pdfEscape;
28383 var activeFontKey = mutex.activeFontKey;
28384 var fonts = mutex.fonts;
28385 var key = activeFontKey;
28386
28387 var str = "",
28388 s = 0,
28389 cmapConfirm;
28390 var strText = "";
28391 var encoding = fonts[key].encoding;
28392
28393 if (fonts[key].encoding !== "Identity-H") {
28394 return {
28395 text: text,
28396 x: x,
28397 y: y,
28398 options: options,
28399 mutex: mutex
28400 };
28401 }
28402 strText = text;
28403
28404 key = activeFontKey;
28405 if (Array.isArray(text)) {
28406 strText = text[0];
28407 }
28408 for (s = 0; s < strText.length; s += 1) {
28409 if (fonts[key].metadata.hasOwnProperty("cmap")) {
28410 cmapConfirm =
28411 fonts[key].metadata.cmap.unicode.codeMap[strText[s].charCodeAt(0)];
28412 /*
28413 if (Object.prototype.toString.call(text) === '[object Array]') {
28414 var i = 0;
28415 // for (i = 0; i < text.length; i += 1) {
28416 if (Object.prototype.toString.call(text[s]) === '[object Array]') {
28417 cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s][0].charCodeAt(0)]; //Make sure the cmap has the corresponding glyph id
28418 } else {
28419
28420 }
28421 //}
28422
28423 } else {
28424 cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s].charCodeAt(0)]; //Make sure the cmap has the corresponding glyph id
28425 }*/
28426 }
28427 if (!cmapConfirm) {
28428 if (
28429 strText[s].charCodeAt(0) < 256 &&
28430 fonts[key].metadata.hasOwnProperty("Unicode")
28431 ) {
28432 str += strText[s];
28433 } else {
28434 str += "";
28435 }
28436 } else {
28437 str += strText[s];
28438 }
28439 }
28440 var result = "";
28441 if (parseInt(key.slice(1)) < 14 || encoding === "WinAnsiEncoding") {
28442 //For the default 13 font
28443 result = pdfEscape(str, key)
28444 .split("")
28445 .map(function(cv) {
28446 return cv.charCodeAt(0).toString(16);
28447 })
28448 .join("");
28449 } else if (encoding === "Identity-H") {
28450 result = pdfEscape16(str, fonts[key]);
28451 }
28452 mutex.isHex = true;
28453
28454 return {
28455 text: result,
28456 x: x,
28457 y: y,
28458 options: options,
28459 mutex: mutex
28460 };
28461 };
28462
28463 var utf8EscapeFunction = function(parms) {
28464 var text = parms.text || "",
28465 x = parms.x,
28466 y = parms.y,
28467 options = parms.options,
28468 mutex = parms.mutex;
28469 var tmpText = [];
28470 var args = {
28471 text: text,
28472 x: x,
28473 y: y,
28474 options: options,
28475 mutex: mutex
28476 };
28477
28478 if (Array.isArray(text)) {
28479 var i = 0;
28480 for (i = 0; i < text.length; i += 1) {
28481 if (Array.isArray(text[i])) {
28482 if (text[i].length === 3) {
28483 tmpText.push([
28484 utf8TextFunction(Object.assign({}, args, { text: text[i][0] }))
28485 .text,
28486 text[i][1],
28487 text[i][2]
28488 ]);
28489 } else {
28490 tmpText.push(
28491 utf8TextFunction(Object.assign({}, args, { text: text[i] })).text
28492 );
28493 }
28494 } else {
28495 tmpText.push(
28496 utf8TextFunction(Object.assign({}, args, { text: text[i] })).text
28497 );
28498 }
28499 }
28500 parms.text = tmpText;
28501 } else {
28502 parms.text = utf8TextFunction(
28503 Object.assign({}, args, { text: text })
28504 ).text;
28505 }
28506 };
28507
28508 jsPDFAPI.events.push(["postProcessText", utf8EscapeFunction]);
28509 })(jsPDF);
28510
28511 /**
28512 * @license
28513 * jsPDF virtual FileSystem functionality
28514 *
28515 * Licensed under the MIT License.
28516 * http://opensource.org/licenses/mit-license
28517 */
28518
28519 /**
28520 * Use the vFS to handle files
28521 *
28522 * @name vFS
28523 * @module
28524 */
28525 (function(jsPDFAPI) {
28526
28527 var _initializeVFS = function() {
28528 if (typeof this.internal.vFS === "undefined") {
28529 this.internal.vFS = {};
28530 }
28531 return true;
28532 };
28533
28534 /**
28535 * Check if the file exists in the vFS
28536 *
28537 * @name existsFileInVFS
28538 * @function
28539 * @param {string} Possible filename in the vFS.
28540 * @returns {boolean}
28541 * @example
28542 * doc.existsFileInVFS("someFile.txt");
28543 */
28544 jsPDFAPI.existsFileInVFS = function(filename) {
28545 _initializeVFS.call(this);
28546 return typeof this.internal.vFS[filename] !== "undefined";
28547 };
28548
28549 /**
28550 * Add a file to the vFS
28551 *
28552 * @name addFileToVFS
28553 * @function
28554 * @param {string} filename The name of the file which should be added.
28555 * @param {string} filecontent The content of the file.
28556 * @returns {jsPDF}
28557 * @example
28558 * doc.addFileToVFS("someFile.txt", "BADFACE1");
28559 */
28560 jsPDFAPI.addFileToVFS = function(filename, filecontent) {
28561 _initializeVFS.call(this);
28562 this.internal.vFS[filename] = filecontent;
28563 return this;
28564 };
28565
28566 /**
28567 * Get the file from the vFS
28568 *
28569 * @name getFileFromVFS
28570 * @function
28571 * @param {string} The name of the file which gets requested.
28572 * @returns {string}
28573 * @example
28574 * doc.getFileFromVFS("someFile.txt");
28575 */
28576 jsPDFAPI.getFileFromVFS = function(filename) {
28577 _initializeVFS.call(this);
28578
28579 if (typeof this.internal.vFS[filename] !== "undefined") {
28580 return this.internal.vFS[filename];
28581 }
28582 return null;
28583 };
28584 })(jsPDF.API);
28585
28586 /**
28587 * @license
28588 * Unicode Bidi Engine based on the work of Alex Shensis (@asthensis)
28589 * MIT License
28590 */
28591
28592 (function(jsPDF) {
28593 /**
28594 * Table of Unicode types.
28595 *
28596 * Generated by:
28597 *
28598 * var bidi = require("./bidi/index");
28599 * var bidi_accumulate = bidi.slice(0, 256).concat(bidi.slice(0x0500, 0x0500 + 256 * 3)).
28600 * concat(bidi.slice(0x2000, 0x2000 + 256)).concat(bidi.slice(0xFB00, 0xFB00 + 256)).
28601 * concat(bidi.slice(0xFE00, 0xFE00 + 2 * 256));
28602 *
28603 * for( var i = 0; i < bidi_accumulate.length; i++) {
28604 * if(bidi_accumulate[i] === undefined || bidi_accumulate[i] === 'ON')
28605 * bidi_accumulate[i] = 'N'; //mark as neutral to conserve space and substitute undefined
28606 * }
28607 * var bidiAccumulateStr = 'return [ "' + bidi_accumulate.toString().replace(/,/g, '", "') + '" ];';
28608 * require("fs").writeFile('unicode-types.js', bidiAccumulateStr);
28609 *
28610 * Based on:
28611 * https://github.com/mathiasbynens/unicode-8.0.0
28612 */
28613 var bidiUnicodeTypes = [
28614 "BN",
28615 "BN",
28616 "BN",
28617 "BN",
28618 "BN",
28619 "BN",
28620 "BN",
28621 "BN",
28622 "BN",
28623 "S",
28624 "B",
28625 "S",
28626 "WS",
28627 "B",
28628 "BN",
28629 "BN",
28630 "BN",
28631 "BN",
28632 "BN",
28633 "BN",
28634 "BN",
28635 "BN",
28636 "BN",
28637 "BN",
28638 "BN",
28639 "BN",
28640 "BN",
28641 "BN",
28642 "B",
28643 "B",
28644 "B",
28645 "S",
28646 "WS",
28647 "N",
28648 "N",
28649 "ET",
28650 "ET",
28651 "ET",
28652 "N",
28653 "N",
28654 "N",
28655 "N",
28656 "N",
28657 "ES",
28658 "CS",
28659 "ES",
28660 "CS",
28661 "CS",
28662 "EN",
28663 "EN",
28664 "EN",
28665 "EN",
28666 "EN",
28667 "EN",
28668 "EN",
28669 "EN",
28670 "EN",
28671 "EN",
28672 "CS",
28673 "N",
28674 "N",
28675 "N",
28676 "N",
28677 "N",
28678 "N",
28679 "L",
28680 "L",
28681 "L",
28682 "L",
28683 "L",
28684 "L",
28685 "L",
28686 "L",
28687 "L",
28688 "L",
28689 "L",
28690 "L",
28691 "L",
28692 "L",
28693 "L",
28694 "L",
28695 "L",
28696 "L",
28697 "L",
28698 "L",
28699 "L",
28700 "L",
28701 "L",
28702 "L",
28703 "L",
28704 "L",
28705 "N",
28706 "N",
28707 "N",
28708 "N",
28709 "N",
28710 "N",
28711 "L",
28712 "L",
28713 "L",
28714 "L",
28715 "L",
28716 "L",
28717 "L",
28718 "L",
28719 "L",
28720 "L",
28721 "L",
28722 "L",
28723 "L",
28724 "L",
28725 "L",
28726 "L",
28727 "L",
28728 "L",
28729 "L",
28730 "L",
28731 "L",
28732 "L",
28733 "L",
28734 "L",
28735 "L",
28736 "L",
28737 "N",
28738 "N",
28739 "N",
28740 "N",
28741 "BN",
28742 "BN",
28743 "BN",
28744 "BN",
28745 "BN",
28746 "BN",
28747 "B",
28748 "BN",
28749 "BN",
28750 "BN",
28751 "BN",
28752 "BN",
28753 "BN",
28754 "BN",
28755 "BN",
28756 "BN",
28757 "BN",
28758 "BN",
28759 "BN",
28760 "BN",
28761 "BN",
28762 "BN",
28763 "BN",
28764 "BN",
28765 "BN",
28766 "BN",
28767 "BN",
28768 "BN",
28769 "BN",
28770 "BN",
28771 "BN",
28772 "BN",
28773 "BN",
28774 "CS",
28775 "N",
28776 "ET",
28777 "ET",
28778 "ET",
28779 "ET",
28780 "N",
28781 "N",
28782 "N",
28783 "N",
28784 "L",
28785 "N",
28786 "N",
28787 "BN",
28788 "N",
28789 "N",
28790 "ET",
28791 "ET",
28792 "EN",
28793 "EN",
28794 "N",
28795 "L",
28796 "N",
28797 "N",
28798 "N",
28799 "EN",
28800 "L",
28801 "N",
28802 "N",
28803 "N",
28804 "N",
28805 "N",
28806 "L",
28807 "L",
28808 "L",
28809 "L",
28810 "L",
28811 "L",
28812 "L",
28813 "L",
28814 "L",
28815 "L",
28816 "L",
28817 "L",
28818 "L",
28819 "L",
28820 "L",
28821 "L",
28822 "L",
28823 "L",
28824 "L",
28825 "L",
28826 "L",
28827 "L",
28828 "L",
28829 "N",
28830 "L",
28831 "L",
28832 "L",
28833 "L",
28834 "L",
28835 "L",
28836 "L",
28837 "L",
28838 "L",
28839 "L",
28840 "L",
28841 "L",
28842 "L",
28843 "L",
28844 "L",
28845 "L",
28846 "L",
28847 "L",
28848 "L",
28849 "L",
28850 "L",
28851 "L",
28852 "L",
28853 "L",
28854 "L",
28855 "L",
28856 "L",
28857 "L",
28858 "L",
28859 "L",
28860 "L",
28861 "N",
28862 "L",
28863 "L",
28864 "L",
28865 "L",
28866 "L",
28867 "L",
28868 "L",
28869 "L",
28870 "L",
28871 "L",
28872 "L",
28873 "L",
28874 "L",
28875 "L",
28876 "L",
28877 "L",
28878 "L",
28879 "L",
28880 "L",
28881 "L",
28882 "L",
28883 "L",
28884 "L",
28885 "L",
28886 "L",
28887 "L",
28888 "L",
28889 "L",
28890 "L",
28891 "L",
28892 "L",
28893 "L",
28894 "L",
28895 "L",
28896 "L",
28897 "L",
28898 "L",
28899 "L",
28900 "L",
28901 "L",
28902 "L",
28903 "L",
28904 "L",
28905 "L",
28906 "L",
28907 "L",
28908 "L",
28909 "L",
28910 "L",
28911 "L",
28912 "L",
28913 "L",
28914 "L",
28915 "L",
28916 "L",
28917 "L",
28918 "N",
28919 "L",
28920 "L",
28921 "L",
28922 "L",
28923 "L",
28924 "L",
28925 "L",
28926 "L",
28927 "L",
28928 "L",
28929 "L",
28930 "L",
28931 "L",
28932 "L",
28933 "L",
28934 "L",
28935 "L",
28936 "L",
28937 "L",
28938 "L",
28939 "L",
28940 "L",
28941 "L",
28942 "L",
28943 "L",
28944 "L",
28945 "L",
28946 "L",
28947 "L",
28948 "L",
28949 "L",
28950 "L",
28951 "L",
28952 "L",
28953 "L",
28954 "L",
28955 "L",
28956 "L",
28957 "N",
28958 "N",
28959 "L",
28960 "L",
28961 "L",
28962 "L",
28963 "L",
28964 "L",
28965 "L",
28966 "N",
28967 "L",
28968 "L",
28969 "L",
28970 "L",
28971 "L",
28972 "L",
28973 "L",
28974 "L",
28975 "L",
28976 "L",
28977 "L",
28978 "L",
28979 "L",
28980 "L",
28981 "L",
28982 "L",
28983 "L",
28984 "L",
28985 "L",
28986 "L",
28987 "L",
28988 "L",
28989 "L",
28990 "L",
28991 "L",
28992 "L",
28993 "L",
28994 "L",
28995 "L",
28996 "L",
28997 "L",
28998 "L",
28999 "L",
29000 "L",
29001 "L",
29002 "L",
29003 "L",
29004 "L",
29005 "L",
29006 "N",
29007 "L",
29008 "N",
29009 "N",
29010 "N",
29011 "N",
29012 "N",
29013 "ET",
29014 "N",
29015 "NSM",
29016 "NSM",
29017 "NSM",
29018 "NSM",
29019 "NSM",
29020 "NSM",
29021 "NSM",
29022 "NSM",
29023 "NSM",
29024 "NSM",
29025 "NSM",
29026 "NSM",
29027 "NSM",
29028 "NSM",
29029 "NSM",
29030 "NSM",
29031 "NSM",
29032 "NSM",
29033 "NSM",
29034 "NSM",
29035 "NSM",
29036 "NSM",
29037 "NSM",
29038 "NSM",
29039 "NSM",
29040 "NSM",
29041 "NSM",
29042 "NSM",
29043 "NSM",
29044 "NSM",
29045 "NSM",
29046 "NSM",
29047 "NSM",
29048 "NSM",
29049 "NSM",
29050 "NSM",
29051 "NSM",
29052 "NSM",
29053 "NSM",
29054 "NSM",
29055 "NSM",
29056 "NSM",
29057 "NSM",
29058 "NSM",
29059 "NSM",
29060 "R",
29061 "NSM",
29062 "R",
29063 "NSM",
29064 "NSM",
29065 "R",
29066 "NSM",
29067 "NSM",
29068 "R",
29069 "NSM",
29070 "N",
29071 "N",
29072 "N",
29073 "N",
29074 "N",
29075 "N",
29076 "N",
29077 "N",
29078 "R",
29079 "R",
29080 "R",
29081 "R",
29082 "R",
29083 "R",
29084 "R",
29085 "R",
29086 "R",
29087 "R",
29088 "R",
29089 "R",
29090 "R",
29091 "R",
29092 "R",
29093 "R",
29094 "R",
29095 "R",
29096 "R",
29097 "R",
29098 "R",
29099 "R",
29100 "R",
29101 "R",
29102 "R",
29103 "R",
29104 "R",
29105 "N",
29106 "N",
29107 "N",
29108 "N",
29109 "N",
29110 "R",
29111 "R",
29112 "R",
29113 "R",
29114 "R",
29115 "N",
29116 "N",
29117 "N",
29118 "N",
29119 "N",
29120 "N",
29121 "N",
29122 "N",
29123 "N",
29124 "N",
29125 "N",
29126 "AN",
29127 "AN",
29128 "AN",
29129 "AN",
29130 "AN",
29131 "AN",
29132 "N",
29133 "N",
29134 "AL",
29135 "ET",
29136 "ET",
29137 "AL",
29138 "CS",
29139 "AL",
29140 "N",
29141 "N",
29142 "NSM",
29143 "NSM",
29144 "NSM",
29145 "NSM",
29146 "NSM",
29147 "NSM",
29148 "NSM",
29149 "NSM",
29150 "NSM",
29151 "NSM",
29152 "NSM",
29153 "AL",
29154 "AL",
29155 "N",
29156 "AL",
29157 "AL",
29158 "AL",
29159 "AL",
29160 "AL",
29161 "AL",
29162 "AL",
29163 "AL",
29164 "AL",
29165 "AL",
29166 "AL",
29167 "AL",
29168 "AL",
29169 "AL",
29170 "AL",
29171 "AL",
29172 "AL",
29173 "AL",
29174 "AL",
29175 "AL",
29176 "AL",
29177 "AL",
29178 "AL",
29179 "AL",
29180 "AL",
29181 "AL",
29182 "AL",
29183 "AL",
29184 "AL",
29185 "AL",
29186 "AL",
29187 "AL",
29188 "AL",
29189 "AL",
29190 "AL",
29191 "AL",
29192 "AL",
29193 "AL",
29194 "AL",
29195 "AL",
29196 "AL",
29197 "AL",
29198 "AL",
29199 "AL",
29200 "AL",
29201 "NSM",
29202 "NSM",
29203 "NSM",
29204 "NSM",
29205 "NSM",
29206 "NSM",
29207 "NSM",
29208 "NSM",
29209 "NSM",
29210 "NSM",
29211 "NSM",
29212 "NSM",
29213 "NSM",
29214 "NSM",
29215 "NSM",
29216 "NSM",
29217 "NSM",
29218 "NSM",
29219 "NSM",
29220 "NSM",
29221 "NSM",
29222 "AN",
29223 "AN",
29224 "AN",
29225 "AN",
29226 "AN",
29227 "AN",
29228 "AN",
29229 "AN",
29230 "AN",
29231 "AN",
29232 "ET",
29233 "AN",
29234 "AN",
29235 "AL",
29236 "AL",
29237 "AL",
29238 "NSM",
29239 "AL",
29240 "AL",
29241 "AL",
29242 "AL",
29243 "AL",
29244 "AL",
29245 "AL",
29246 "AL",
29247 "AL",
29248 "AL",
29249 "AL",
29250 "AL",
29251 "AL",
29252 "AL",
29253 "AL",
29254 "AL",
29255 "AL",
29256 "AL",
29257 "AL",
29258 "AL",
29259 "AL",
29260 "AL",
29261 "AL",
29262 "AL",
29263 "AL",
29264 "AL",
29265 "AL",
29266 "AL",
29267 "AL",
29268 "AL",
29269 "AL",
29270 "AL",
29271 "AL",
29272 "AL",
29273 "AL",
29274 "AL",
29275 "AL",
29276 "AL",
29277 "AL",
29278 "AL",
29279 "AL",
29280 "AL",
29281 "AL",
29282 "AL",
29283 "AL",
29284 "AL",
29285 "AL",
29286 "AL",
29287 "AL",
29288 "AL",
29289 "AL",
29290 "AL",
29291 "AL",
29292 "AL",
29293 "AL",
29294 "AL",
29295 "AL",
29296 "AL",
29297 "AL",
29298 "AL",
29299 "AL",
29300 "AL",
29301 "AL",
29302 "AL",
29303 "AL",
29304 "AL",
29305 "AL",
29306 "AL",
29307 "AL",
29308 "AL",
29309 "AL",
29310 "AL",
29311 "AL",
29312 "AL",
29313 "AL",
29314 "AL",
29315 "AL",
29316 "AL",
29317 "AL",
29318 "AL",
29319 "AL",
29320 "AL",
29321 "AL",
29322 "AL",
29323 "AL",
29324 "AL",
29325 "AL",
29326 "AL",
29327 "AL",
29328 "AL",
29329 "AL",
29330 "AL",
29331 "AL",
29332 "AL",
29333 "AL",
29334 "AL",
29335 "AL",
29336 "AL",
29337 "AL",
29338 "AL",
29339 "AL",
29340 "NSM",
29341 "NSM",
29342 "NSM",
29343 "NSM",
29344 "NSM",
29345 "NSM",
29346 "NSM",
29347 "AN",
29348 "N",
29349 "NSM",
29350 "NSM",
29351 "NSM",
29352 "NSM",
29353 "NSM",
29354 "NSM",
29355 "AL",
29356 "AL",
29357 "NSM",
29358 "NSM",
29359 "N",
29360 "NSM",
29361 "NSM",
29362 "NSM",
29363 "NSM",
29364 "AL",
29365 "AL",
29366 "EN",
29367 "EN",
29368 "EN",
29369 "EN",
29370 "EN",
29371 "EN",
29372 "EN",
29373 "EN",
29374 "EN",
29375 "EN",
29376 "AL",
29377 "AL",
29378 "AL",
29379 "AL",
29380 "AL",
29381 "AL",
29382 "AL",
29383 "AL",
29384 "AL",
29385 "AL",
29386 "AL",
29387 "AL",
29388 "AL",
29389 "AL",
29390 "AL",
29391 "AL",
29392 "AL",
29393 "AL",
29394 "AL",
29395 "AL",
29396 "N",
29397 "AL",
29398 "AL",
29399 "NSM",
29400 "AL",
29401 "AL",
29402 "AL",
29403 "AL",
29404 "AL",
29405 "AL",
29406 "AL",
29407 "AL",
29408 "AL",
29409 "AL",
29410 "AL",
29411 "AL",
29412 "AL",
29413 "AL",
29414 "AL",
29415 "AL",
29416 "AL",
29417 "AL",
29418 "AL",
29419 "AL",
29420 "AL",
29421 "AL",
29422 "AL",
29423 "AL",
29424 "AL",
29425 "AL",
29426 "AL",
29427 "AL",
29428 "AL",
29429 "AL",
29430 "NSM",
29431 "NSM",
29432 "NSM",
29433 "NSM",
29434 "NSM",
29435 "NSM",
29436 "NSM",
29437 "NSM",
29438 "NSM",
29439 "NSM",
29440 "NSM",
29441 "NSM",
29442 "NSM",
29443 "NSM",
29444 "NSM",
29445 "NSM",
29446 "NSM",
29447 "NSM",
29448 "NSM",
29449 "NSM",
29450 "NSM",
29451 "NSM",
29452 "NSM",
29453 "NSM",
29454 "NSM",
29455 "NSM",
29456 "NSM",
29457 "N",
29458 "N",
29459 "AL",
29460 "AL",
29461 "AL",
29462 "AL",
29463 "AL",
29464 "AL",
29465 "AL",
29466 "AL",
29467 "AL",
29468 "AL",
29469 "AL",
29470 "AL",
29471 "AL",
29472 "AL",
29473 "AL",
29474 "AL",
29475 "AL",
29476 "AL",
29477 "AL",
29478 "AL",
29479 "AL",
29480 "AL",
29481 "AL",
29482 "AL",
29483 "AL",
29484 "AL",
29485 "AL",
29486 "AL",
29487 "AL",
29488 "AL",
29489 "AL",
29490 "AL",
29491 "AL",
29492 "AL",
29493 "AL",
29494 "AL",
29495 "AL",
29496 "AL",
29497 "AL",
29498 "AL",
29499 "AL",
29500 "AL",
29501 "AL",
29502 "AL",
29503 "AL",
29504 "AL",
29505 "AL",
29506 "AL",
29507 "AL",
29508 "AL",
29509 "AL",
29510 "AL",
29511 "AL",
29512 "AL",
29513 "AL",
29514 "AL",
29515 "AL",
29516 "AL",
29517 "AL",
29518 "AL",
29519 "AL",
29520 "AL",
29521 "AL",
29522 "AL",
29523 "AL",
29524 "AL",
29525 "AL",
29526 "AL",
29527 "AL",
29528 "AL",
29529 "AL",
29530 "AL",
29531 "AL",
29532 "AL",
29533 "AL",
29534 "AL",
29535 "AL",
29536 "AL",
29537 "AL",
29538 "AL",
29539 "AL",
29540 "AL",
29541 "AL",
29542 "AL",
29543 "AL",
29544 "AL",
29545 "AL",
29546 "AL",
29547 "AL",
29548 "NSM",
29549 "NSM",
29550 "NSM",
29551 "NSM",
29552 "NSM",
29553 "NSM",
29554 "NSM",
29555 "NSM",
29556 "NSM",
29557 "NSM",
29558 "NSM",
29559 "AL",
29560 "N",
29561 "N",
29562 "N",
29563 "N",
29564 "N",
29565 "N",
29566 "N",
29567 "N",
29568 "N",
29569 "N",
29570 "N",
29571 "N",
29572 "N",
29573 "N",
29574 "R",
29575 "R",
29576 "R",
29577 "R",
29578 "R",
29579 "R",
29580 "R",
29581 "R",
29582 "R",
29583 "R",
29584 "R",
29585 "R",
29586 "R",
29587 "R",
29588 "R",
29589 "R",
29590 "R",
29591 "R",
29592 "R",
29593 "R",
29594 "R",
29595 "R",
29596 "R",
29597 "R",
29598 "R",
29599 "R",
29600 "R",
29601 "R",
29602 "R",
29603 "R",
29604 "R",
29605 "R",
29606 "R",
29607 "R",
29608 "R",
29609 "R",
29610 "R",
29611 "R",
29612 "R",
29613 "R",
29614 "R",
29615 "R",
29616 "R",
29617 "NSM",
29618 "NSM",
29619 "NSM",
29620 "NSM",
29621 "NSM",
29622 "NSM",
29623 "NSM",
29624 "NSM",
29625 "NSM",
29626 "R",
29627 "R",
29628 "N",
29629 "N",
29630 "N",
29631 "N",
29632 "R",
29633 "N",
29634 "N",
29635 "N",
29636 "N",
29637 "N",
29638 "WS",
29639 "WS",
29640 "WS",
29641 "WS",
29642 "WS",
29643 "WS",
29644 "WS",
29645 "WS",
29646 "WS",
29647 "WS",
29648 "WS",
29649 "BN",
29650 "BN",
29651 "BN",
29652 "L",
29653 "R",
29654 "N",
29655 "N",
29656 "N",
29657 "N",
29658 "N",
29659 "N",
29660 "N",
29661 "N",
29662 "N",
29663 "N",
29664 "N",
29665 "N",
29666 "N",
29667 "N",
29668 "N",
29669 "N",
29670 "N",
29671 "N",
29672 "N",
29673 "N",
29674 "N",
29675 "N",
29676 "N",
29677 "N",
29678 "WS",
29679 "B",
29680 "LRE",
29681 "RLE",
29682 "PDF",
29683 "LRO",
29684 "RLO",
29685 "CS",
29686 "ET",
29687 "ET",
29688 "ET",
29689 "ET",
29690 "ET",
29691 "N",
29692 "N",
29693 "N",
29694 "N",
29695 "N",
29696 "N",
29697 "N",
29698 "N",
29699 "N",
29700 "N",
29701 "N",
29702 "N",
29703 "N",
29704 "N",
29705 "N",
29706 "CS",
29707 "N",
29708 "N",
29709 "N",
29710 "N",
29711 "N",
29712 "N",
29713 "N",
29714 "N",
29715 "N",
29716 "N",
29717 "N",
29718 "N",
29719 "N",
29720 "N",
29721 "N",
29722 "N",
29723 "N",
29724 "N",
29725 "N",
29726 "N",
29727 "N",
29728 "N",
29729 "N",
29730 "N",
29731 "N",
29732 "N",
29733 "WS",
29734 "BN",
29735 "BN",
29736 "BN",
29737 "BN",
29738 "BN",
29739 "N",
29740 "LRI",
29741 "RLI",
29742 "FSI",
29743 "PDI",
29744 "BN",
29745 "BN",
29746 "BN",
29747 "BN",
29748 "BN",
29749 "BN",
29750 "EN",
29751 "L",
29752 "N",
29753 "N",
29754 "EN",
29755 "EN",
29756 "EN",
29757 "EN",
29758 "EN",
29759 "EN",
29760 "ES",
29761 "ES",
29762 "N",
29763 "N",
29764 "N",
29765 "L",
29766 "EN",
29767 "EN",
29768 "EN",
29769 "EN",
29770 "EN",
29771 "EN",
29772 "EN",
29773 "EN",
29774 "EN",
29775 "EN",
29776 "ES",
29777 "ES",
29778 "N",
29779 "N",
29780 "N",
29781 "N",
29782 "L",
29783 "L",
29784 "L",
29785 "L",
29786 "L",
29787 "L",
29788 "L",
29789 "L",
29790 "L",
29791 "L",
29792 "L",
29793 "L",
29794 "L",
29795 "N",
29796 "N",
29797 "N",
29798 "ET",
29799 "ET",
29800 "ET",
29801 "ET",
29802 "ET",
29803 "ET",
29804 "ET",
29805 "ET",
29806 "ET",
29807 "ET",
29808 "ET",
29809 "ET",
29810 "ET",
29811 "ET",
29812 "ET",
29813 "ET",
29814 "ET",
29815 "ET",
29816 "ET",
29817 "ET",
29818 "ET",
29819 "ET",
29820 "ET",
29821 "ET",
29822 "ET",
29823 "ET",
29824 "ET",
29825 "ET",
29826 "ET",
29827 "ET",
29828 "ET",
29829 "N",
29830 "N",
29831 "N",
29832 "N",
29833 "N",
29834 "N",
29835 "N",
29836 "N",
29837 "N",
29838 "N",
29839 "N",
29840 "N",
29841 "N",
29842 "N",
29843 "N",
29844 "N",
29845 "N",
29846 "NSM",
29847 "NSM",
29848 "NSM",
29849 "NSM",
29850 "NSM",
29851 "NSM",
29852 "NSM",
29853 "NSM",
29854 "NSM",
29855 "NSM",
29856 "NSM",
29857 "NSM",
29858 "NSM",
29859 "NSM",
29860 "NSM",
29861 "NSM",
29862 "NSM",
29863 "NSM",
29864 "NSM",
29865 "NSM",
29866 "NSM",
29867 "NSM",
29868 "NSM",
29869 "NSM",
29870 "NSM",
29871 "NSM",
29872 "NSM",
29873 "NSM",
29874 "NSM",
29875 "NSM",
29876 "NSM",
29877 "NSM",
29878 "NSM",
29879 "N",
29880 "N",
29881 "N",
29882 "N",
29883 "N",
29884 "N",
29885 "N",
29886 "N",
29887 "N",
29888 "N",
29889 "N",
29890 "N",
29891 "N",
29892 "N",
29893 "N",
29894 "L",
29895 "L",
29896 "L",
29897 "L",
29898 "L",
29899 "L",
29900 "L",
29901 "N",
29902 "N",
29903 "N",
29904 "N",
29905 "N",
29906 "N",
29907 "N",
29908 "N",
29909 "N",
29910 "N",
29911 "N",
29912 "N",
29913 "L",
29914 "L",
29915 "L",
29916 "L",
29917 "L",
29918 "N",
29919 "N",
29920 "N",
29921 "N",
29922 "N",
29923 "R",
29924 "NSM",
29925 "R",
29926 "R",
29927 "R",
29928 "R",
29929 "R",
29930 "R",
29931 "R",
29932 "R",
29933 "R",
29934 "R",
29935 "ES",
29936 "R",
29937 "R",
29938 "R",
29939 "R",
29940 "R",
29941 "R",
29942 "R",
29943 "R",
29944 "R",
29945 "R",
29946 "R",
29947 "R",
29948 "R",
29949 "N",
29950 "R",
29951 "R",
29952 "R",
29953 "R",
29954 "R",
29955 "N",
29956 "R",
29957 "N",
29958 "R",
29959 "R",
29960 "N",
29961 "R",
29962 "R",
29963 "N",
29964 "R",
29965 "R",
29966 "R",
29967 "R",
29968 "R",
29969 "R",
29970 "R",
29971 "R",
29972 "R",
29973 "R",
29974 "AL",
29975 "AL",
29976 "AL",
29977 "AL",
29978 "AL",
29979 "AL",
29980 "AL",
29981 "AL",
29982 "AL",
29983 "AL",
29984 "AL",
29985 "AL",
29986 "AL",
29987 "AL",
29988 "AL",
29989 "AL",
29990 "AL",
29991 "AL",
29992 "AL",
29993 "AL",
29994 "AL",
29995 "AL",
29996 "AL",
29997 "AL",
29998 "AL",
29999 "AL",
30000 "AL",
30001 "AL",
30002 "AL",
30003 "AL",
30004 "AL",
30005 "AL",
30006 "AL",
30007 "AL",
30008 "AL",
30009 "AL",
30010 "AL",
30011 "AL",
30012 "AL",
30013 "AL",
30014 "AL",
30015 "AL",
30016 "AL",
30017 "AL",
30018 "AL",
30019 "AL",
30020 "AL",
30021 "AL",
30022 "AL",
30023 "AL",
30024 "AL",
30025 "AL",
30026 "AL",
30027 "AL",
30028 "AL",
30029 "AL",
30030 "AL",
30031 "AL",
30032 "AL",
30033 "AL",
30034 "AL",
30035 "AL",
30036 "AL",
30037 "AL",
30038 "AL",
30039 "AL",
30040 "AL",
30041 "AL",
30042 "AL",
30043 "AL",
30044 "AL",
30045 "AL",
30046 "AL",
30047 "AL",
30048 "AL",
30049 "AL",
30050 "AL",
30051 "AL",
30052 "AL",
30053 "AL",
30054 "AL",
30055 "AL",
30056 "AL",
30057 "AL",
30058 "AL",
30059 "AL",
30060 "AL",
30061 "AL",
30062 "AL",
30063 "AL",
30064 "AL",
30065 "AL",
30066 "AL",
30067 "AL",
30068 "AL",
30069 "AL",
30070 "AL",
30071 "AL",
30072 "AL",
30073 "AL",
30074 "AL",
30075 "AL",
30076 "AL",
30077 "AL",
30078 "AL",
30079 "AL",
30080 "AL",
30081 "AL",
30082 "AL",
30083 "AL",
30084 "AL",
30085 "AL",
30086 "AL",
30087 "AL",
30088 "N",
30089 "N",
30090 "N",
30091 "N",
30092 "N",
30093 "N",
30094 "N",
30095 "N",
30096 "N",
30097 "N",
30098 "N",
30099 "N",
30100 "N",
30101 "N",
30102 "N",
30103 "N",
30104 "N",
30105 "AL",
30106 "AL",
30107 "AL",
30108 "AL",
30109 "AL",
30110 "AL",
30111 "AL",
30112 "AL",
30113 "AL",
30114 "AL",
30115 "AL",
30116 "AL",
30117 "AL",
30118 "AL",
30119 "AL",
30120 "AL",
30121 "AL",
30122 "AL",
30123 "AL",
30124 "AL",
30125 "AL",
30126 "AL",
30127 "AL",
30128 "AL",
30129 "AL",
30130 "AL",
30131 "AL",
30132 "AL",
30133 "AL",
30134 "AL",
30135 "AL",
30136 "AL",
30137 "AL",
30138 "AL",
30139 "AL",
30140 "AL",
30141 "AL",
30142 "AL",
30143 "AL",
30144 "AL",
30145 "AL",
30146 "AL",
30147 "AL",
30148 "AL",
30149 "AL",
30150 "NSM",
30151 "NSM",
30152 "NSM",
30153 "NSM",
30154 "NSM",
30155 "NSM",
30156 "NSM",
30157 "NSM",
30158 "NSM",
30159 "NSM",
30160 "NSM",
30161 "NSM",
30162 "NSM",
30163 "NSM",
30164 "NSM",
30165 "NSM",
30166 "N",
30167 "N",
30168 "N",
30169 "N",
30170 "N",
30171 "N",
30172 "N",
30173 "N",
30174 "N",
30175 "N",
30176 "N",
30177 "N",
30178 "N",
30179 "N",
30180 "N",
30181 "N",
30182 "NSM",
30183 "NSM",
30184 "NSM",
30185 "NSM",
30186 "NSM",
30187 "NSM",
30188 "NSM",
30189 "NSM",
30190 "NSM",
30191 "NSM",
30192 "NSM",
30193 "NSM",
30194 "NSM",
30195 "NSM",
30196 "NSM",
30197 "NSM",
30198 "N",
30199 "N",
30200 "N",
30201 "N",
30202 "N",
30203 "N",
30204 "N",
30205 "N",
30206 "N",
30207 "N",
30208 "N",
30209 "N",
30210 "N",
30211 "N",
30212 "N",
30213 "N",
30214 "N",
30215 "N",
30216 "N",
30217 "N",
30218 "N",
30219 "N",
30220 "N",
30221 "N",
30222 "N",
30223 "N",
30224 "N",
30225 "N",
30226 "N",
30227 "N",
30228 "N",
30229 "N",
30230 "CS",
30231 "N",
30232 "CS",
30233 "N",
30234 "N",
30235 "CS",
30236 "N",
30237 "N",
30238 "N",
30239 "N",
30240 "N",
30241 "N",
30242 "N",
30243 "N",
30244 "N",
30245 "ET",
30246 "N",
30247 "N",
30248 "ES",
30249 "ES",
30250 "N",
30251 "N",
30252 "N",
30253 "N",
30254 "N",
30255 "ET",
30256 "ET",
30257 "N",
30258 "N",
30259 "N",
30260 "N",
30261 "N",
30262 "AL",
30263 "AL",
30264 "AL",
30265 "AL",
30266 "AL",
30267 "N",
30268 "AL",
30269 "AL",
30270 "AL",
30271 "AL",
30272 "AL",
30273 "AL",
30274 "AL",
30275 "AL",
30276 "AL",
30277 "AL",
30278 "AL",
30279 "AL",
30280 "AL",
30281 "AL",
30282 "AL",
30283 "AL",
30284 "AL",
30285 "AL",
30286 "AL",
30287 "AL",
30288 "AL",
30289 "AL",
30290 "AL",
30291 "AL",
30292 "AL",
30293 "AL",
30294 "AL",
30295 "AL",
30296 "AL",
30297 "AL",
30298 "AL",
30299 "AL",
30300 "AL",
30301 "AL",
30302 "AL",
30303 "AL",
30304 "AL",
30305 "AL",
30306 "AL",
30307 "AL",
30308 "AL",
30309 "AL",
30310 "AL",
30311 "AL",
30312 "AL",
30313 "AL",
30314 "AL",
30315 "AL",
30316 "AL",
30317 "AL",
30318 "AL",
30319 "AL",
30320 "AL",
30321 "AL",
30322 "AL",
30323 "AL",
30324 "AL",
30325 "AL",
30326 "AL",
30327 "AL",
30328 "AL",
30329 "AL",
30330 "AL",
30331 "AL",
30332 "AL",
30333 "AL",
30334 "AL",
30335 "AL",
30336 "AL",
30337 "AL",
30338 "AL",
30339 "AL",
30340 "AL",
30341 "AL",
30342 "AL",
30343 "AL",
30344 "AL",
30345 "AL",
30346 "AL",
30347 "AL",
30348 "AL",
30349 "AL",
30350 "AL",
30351 "AL",
30352 "AL",
30353 "AL",
30354 "AL",
30355 "AL",
30356 "AL",
30357 "AL",
30358 "AL",
30359 "AL",
30360 "AL",
30361 "AL",
30362 "AL",
30363 "AL",
30364 "AL",
30365 "AL",
30366 "AL",
30367 "AL",
30368 "AL",
30369 "AL",
30370 "AL",
30371 "AL",
30372 "AL",
30373 "AL",
30374 "AL",
30375 "AL",
30376 "AL",
30377 "AL",
30378 "AL",
30379 "AL",
30380 "AL",
30381 "AL",
30382 "AL",
30383 "AL",
30384 "AL",
30385 "AL",
30386 "AL",
30387 "AL",
30388 "AL",
30389 "AL",
30390 "AL",
30391 "AL",
30392 "AL",
30393 "AL",
30394 "AL",
30395 "AL",
30396 "AL",
30397 "AL",
30398 "AL",
30399 "AL",
30400 "AL",
30401 "AL",
30402 "AL",
30403 "N",
30404 "N",
30405 "BN",
30406 "N",
30407 "N",
30408 "N",
30409 "ET",
30410 "ET",
30411 "ET",
30412 "N",
30413 "N",
30414 "N",
30415 "N",
30416 "N",
30417 "ES",
30418 "CS",
30419 "ES",
30420 "CS",
30421 "CS",
30422 "EN",
30423 "EN",
30424 "EN",
30425 "EN",
30426 "EN",
30427 "EN",
30428 "EN",
30429 "EN",
30430 "EN",
30431 "EN",
30432 "CS",
30433 "N",
30434 "N",
30435 "N",
30436 "N",
30437 "N",
30438 "N",
30439 "L",
30440 "L",
30441 "L",
30442 "L",
30443 "L",
30444 "L",
30445 "L",
30446 "L",
30447 "L",
30448 "L",
30449 "L",
30450 "L",
30451 "L",
30452 "L",
30453 "L",
30454 "L",
30455 "L",
30456 "L",
30457 "L",
30458 "L",
30459 "L",
30460 "L",
30461 "L",
30462 "L",
30463 "L",
30464 "L",
30465 "N",
30466 "N",
30467 "N",
30468 "N",
30469 "N",
30470 "N",
30471 "L",
30472 "L",
30473 "L",
30474 "L",
30475 "L",
30476 "L",
30477 "L",
30478 "L",
30479 "L",
30480 "L",
30481 "L",
30482 "L",
30483 "L",
30484 "L",
30485 "L",
30486 "L",
30487 "L",
30488 "L",
30489 "L",
30490 "L",
30491 "L",
30492 "L",
30493 "L",
30494 "L",
30495 "L",
30496 "L",
30497 "N",
30498 "N",
30499 "N",
30500 "N",
30501 "N",
30502 "N",
30503 "N",
30504 "N",
30505 "N",
30506 "N",
30507 "N",
30508 "L",
30509 "L",
30510 "L",
30511 "L",
30512 "L",
30513 "L",
30514 "L",
30515 "L",
30516 "L",
30517 "L",
30518 "L",
30519 "L",
30520 "L",
30521 "L",
30522 "L",
30523 "L",
30524 "L",
30525 "L",
30526 "L",
30527 "L",
30528 "L",
30529 "L",
30530 "L",
30531 "L",
30532 "L",
30533 "L",
30534 "L",
30535 "L",
30536 "L",
30537 "L",
30538 "L",
30539 "L",
30540 "L",
30541 "L",
30542 "L",
30543 "L",
30544 "L",
30545 "L",
30546 "L",
30547 "L",
30548 "L",
30549 "L",
30550 "L",
30551 "L",
30552 "L",
30553 "L",
30554 "L",
30555 "L",
30556 "L",
30557 "L",
30558 "L",
30559 "L",
30560 "L",
30561 "L",
30562 "L",
30563 "L",
30564 "L",
30565 "L",
30566 "L",
30567 "L",
30568 "L",
30569 "L",
30570 "L",
30571 "L",
30572 "L",
30573 "L",
30574 "L",
30575 "L",
30576 "L",
30577 "L",
30578 "L",
30579 "L",
30580 "L",
30581 "L",
30582 "L",
30583 "L",
30584 "L",
30585 "L",
30586 "L",
30587 "L",
30588 "L",
30589 "L",
30590 "L",
30591 "L",
30592 "L",
30593 "L",
30594 "L",
30595 "L",
30596 "L",
30597 "N",
30598 "N",
30599 "N",
30600 "L",
30601 "L",
30602 "L",
30603 "L",
30604 "L",
30605 "L",
30606 "N",
30607 "N",
30608 "L",
30609 "L",
30610 "L",
30611 "L",
30612 "L",
30613 "L",
30614 "N",
30615 "N",
30616 "L",
30617 "L",
30618 "L",
30619 "L",
30620 "L",
30621 "L",
30622 "N",
30623 "N",
30624 "L",
30625 "L",
30626 "L",
30627 "N",
30628 "N",
30629 "N",
30630 "ET",
30631 "ET",
30632 "N",
30633 "N",
30634 "N",
30635 "ET",
30636 "ET",
30637 "N",
30638 "N",
30639 "N",
30640 "N",
30641 "N",
30642 "N",
30643 "N",
30644 "N",
30645 "N",
30646 "N",
30647 "N",
30648 "N",
30649 "N",
30650 "N",
30651 "N",
30652 "N",
30653 "N",
30654 "N",
30655 "N",
30656 "N",
30657 "N",
30658 "N",
30659 "N",
30660 "N",
30661 "N"
30662 ];
30663
30664 /**
30665 * Unicode Bidi algorithm compliant Bidi engine.
30666 * For reference see http://unicode.org/reports/tr9/
30667 */
30668
30669 /**
30670 * constructor ( options )
30671 *
30672 * Initializes Bidi engine
30673 *
30674 * @param {Object} See 'setOptions' below for detailed description.
30675 * options are cashed between invocation of 'doBidiReorder' method
30676 *
30677 * sample usage pattern of BidiEngine:
30678 * var opt = {
30679 * isInputVisual: true,
30680 * isInputRtl: false,
30681 * isOutputVisual: false,
30682 * isOutputRtl: false,
30683 * isSymmetricSwapping: true
30684 * }
30685 * var sourceToTarget = [], levels = [];
30686 * var bidiEng = Globalize.bidiEngine(opt);
30687 * var src = "text string to be reordered";
30688 * var ret = bidiEng.doBidiReorder(src, sourceToTarget, levels);
30689 */
30690
30691 jsPDF.__bidiEngine__ = jsPDF.prototype.__bidiEngine__ = function(options) {
30692 var _UNICODE_TYPES = _bidiUnicodeTypes;
30693
30694 var _STATE_TABLE_LTR = [
30695 [0, 3, 0, 1, 0, 0, 0],
30696 [0, 3, 0, 1, 2, 2, 0],
30697 [0, 3, 0, 0x11, 2, 0, 1],
30698 [0, 3, 5, 5, 4, 1, 0],
30699 [0, 3, 0x15, 0x15, 4, 0, 1],
30700 [0, 3, 5, 5, 4, 2, 0]
30701 ];
30702
30703 var _STATE_TABLE_RTL = [
30704 [2, 0, 1, 1, 0, 1, 0],
30705 [2, 0, 1, 1, 0, 2, 0],
30706 [2, 0, 2, 1, 3, 2, 0],
30707 [2, 0, 2, 0x21, 3, 1, 1]
30708 ];
30709
30710 var _TYPE_NAMES_MAP = { L: 0, R: 1, EN: 2, AN: 3, N: 4, B: 5, S: 6 };
30711
30712 var _UNICODE_RANGES_MAP = {
30713 0: 0,
30714 5: 1,
30715 6: 2,
30716 7: 3,
30717 0x20: 4,
30718 0xfb: 5,
30719 0xfe: 6,
30720 0xff: 7
30721 };
30722
30723 var _SWAP_TABLE = [
30724 "\u0028",
30725 "\u0029",
30726 "\u0028",
30727 "\u003C",
30728 "\u003E",
30729 "\u003C",
30730 "\u005B",
30731 "\u005D",
30732 "\u005B",
30733 "\u007B",
30734 "\u007D",
30735 "\u007B",
30736 "\u00AB",
30737 "\u00BB",
30738 "\u00AB",
30739 "\u2039",
30740 "\u203A",
30741 "\u2039",
30742 "\u2045",
30743 "\u2046",
30744 "\u2045",
30745 "\u207D",
30746 "\u207E",
30747 "\u207D",
30748 "\u208D",
30749 "\u208E",
30750 "\u208D",
30751 "\u2264",
30752 "\u2265",
30753 "\u2264",
30754 "\u2329",
30755 "\u232A",
30756 "\u2329",
30757 "\uFE59",
30758 "\uFE5A",
30759 "\uFE59",
30760 "\uFE5B",
30761 "\uFE5C",
30762 "\uFE5B",
30763 "\uFE5D",
30764 "\uFE5E",
30765 "\uFE5D",
30766 "\uFE64",
30767 "\uFE65",
30768 "\uFE64"
30769 ];
30770
30771 var _LTR_RANGES_REG_EXPR = new RegExp(
30772 /^([1-4|9]|1[0-9]|2[0-9]|3[0168]|4[04589]|5[012]|7[78]|159|16[0-9]|17[0-2]|21[569]|22[03489]|250)$/
30773 );
30774
30775 var _lastArabic = false,
30776 _hasUbatB,
30777 _hasUbatS,
30778 DIR_LTR = 0,
30779 DIR_RTL = 1,
30780 _isInVisual,
30781 _isInRtl,
30782 _isOutVisual,
30783 _isOutRtl,
30784 _isSymmetricSwapping,
30785 _dir = DIR_LTR;
30786
30787 this.__bidiEngine__ = {};
30788
30789 var _init = function(text, sourceToTargetMap) {
30790 if (sourceToTargetMap) {
30791 for (var i = 0; i < text.length; i++) {
30792 sourceToTargetMap[i] = i;
30793 }
30794 }
30795 if (_isInRtl === undefined) {
30796 _isInRtl = _isContextualDirRtl(text);
30797 }
30798 if (_isOutRtl === undefined) {
30799 _isOutRtl = _isContextualDirRtl(text);
30800 }
30801 };
30802
30803 // for reference see 3.2 in http://unicode.org/reports/tr9/
30804 //
30805 var _getCharType = function(ch) {
30806 var charCode = ch.charCodeAt(),
30807 range = charCode >> 8,
30808 rangeIdx = _UNICODE_RANGES_MAP[range];
30809
30810 if (rangeIdx !== undefined) {
30811 return _UNICODE_TYPES[rangeIdx * 256 + (charCode & 0xff)];
30812 } else if (range === 0xfc || range === 0xfd) {
30813 return "AL";
30814 } else if (_LTR_RANGES_REG_EXPR.test(range)) {
30815 //unlikely case
30816 return "L";
30817 } else if (range === 8) {
30818 // even less likely
30819 return "R";
30820 }
30821 return "N"; //undefined type, mark as neutral
30822 };
30823
30824 var _isContextualDirRtl = function(text) {
30825 for (var i = 0, charType; i < text.length; i++) {
30826 charType = _getCharType(text.charAt(i));
30827 if (charType === "L") {
30828 return false;
30829 } else if (charType === "R") {
30830 return true;
30831 }
30832 }
30833 return false;
30834 };
30835
30836 // for reference see 3.3.4 & 3.3.5 in http://unicode.org/reports/tr9/
30837 //
30838 var _resolveCharType = function(chars, types, resolvedTypes, index) {
30839 var cType = types[index],
30840 wType,
30841 nType,
30842 i,
30843 len;
30844 switch (cType) {
30845 case "L":
30846 case "R":
30847 _lastArabic = false;
30848 break;
30849 case "N":
30850 case "AN":
30851 break;
30852
30853 case "EN":
30854 if (_lastArabic) {
30855 cType = "AN";
30856 }
30857 break;
30858
30859 case "AL":
30860 _lastArabic = true;
30861 cType = "R";
30862 break;
30863
30864 case "WS":
30865 cType = "N";
30866 break;
30867
30868 case "CS":
30869 if (
30870 index < 1 ||
30871 index + 1 >= types.length ||
30872 ((wType = resolvedTypes[index - 1]) !== "EN" && wType !== "AN") ||
30873 ((nType = types[index + 1]) !== "EN" && nType !== "AN")
30874 ) {
30875 cType = "N";
30876 } else if (_lastArabic) {
30877 nType = "AN";
30878 }
30879 cType = nType === wType ? nType : "N";
30880 break;
30881
30882 case "ES":
30883 wType = index > 0 ? resolvedTypes[index - 1] : "B";
30884 cType =
30885 wType === "EN" &&
30886 index + 1 < types.length &&
30887 types[index + 1] === "EN"
30888 ? "EN"
30889 : "N";
30890 break;
30891
30892 case "ET":
30893 if (index > 0 && resolvedTypes[index - 1] === "EN") {
30894 cType = "EN";
30895 break;
30896 } else if (_lastArabic) {
30897 cType = "N";
30898 break;
30899 }
30900 i = index + 1;
30901 len = types.length;
30902 while (i < len && types[i] === "ET") {
30903 i++;
30904 }
30905 if (i < len && types[i] === "EN") {
30906 cType = "EN";
30907 } else {
30908 cType = "N";
30909 }
30910 break;
30911
30912 case "NSM":
30913 if (_isInVisual && !_isInRtl) {
30914 //V->L
30915 len = types.length;
30916 i = index + 1;
30917 while (i < len && types[i] === "NSM") {
30918 i++;
30919 }
30920 if (i < len) {
30921 var c = chars[index];
30922 var rtlCandidate = (c >= 0x0591 && c <= 0x08ff) || c === 0xfb1e;
30923 wType = types[i];
30924 if (rtlCandidate && (wType === "R" || wType === "AL")) {
30925 cType = "R";
30926 break;
30927 }
30928 }
30929 }
30930 if (index < 1 || (wType = types[index - 1]) === "B") {
30931 cType = "N";
30932 } else {
30933 cType = resolvedTypes[index - 1];
30934 }
30935 break;
30936
30937 case "B":
30938 _lastArabic = false;
30939 _hasUbatB = true;
30940 cType = _dir;
30941 break;
30942
30943 case "S":
30944 _hasUbatS = true;
30945 cType = "N";
30946 break;
30947
30948 case "LRE":
30949 case "RLE":
30950 case "LRO":
30951 case "RLO":
30952 case "PDF":
30953 _lastArabic = false;
30954 break;
30955 case "BN":
30956 cType = "N";
30957 break;
30958 }
30959 return cType;
30960 };
30961
30962 var _handleUbatS = function(types, levels, length) {
30963 for (var i = 0; i < length; i++) {
30964 if (types[i] === "S") {
30965 levels[i] = _dir;
30966 for (var j = i - 1; j >= 0; j--) {
30967 if (types[j] === "WS") {
30968 levels[j] = _dir;
30969 } else {
30970 break;
30971 }
30972 }
30973 }
30974 }
30975 };
30976
30977 var _invertString = function(text, sourceToTargetMap, levels) {
30978 var charArray = text.split("");
30979 if (levels) {
30980 _computeLevels(charArray, levels, { hiLevel: _dir });
30981 }
30982 charArray.reverse();
30983 sourceToTargetMap && sourceToTargetMap.reverse();
30984 return charArray.join("");
30985 };
30986
30987 // For reference see 3.3 in http://unicode.org/reports/tr9/
30988 //
30989 var _computeLevels = function(chars, levels, params) {
30990 var action,
30991 condition,
30992 i,
30993 index,
30994 newLevel,
30995 prevState,
30996 condPos = -1,
30997 len = chars.length,
30998 newState = 0,
30999 resolvedTypes = [],
31000 stateTable = _dir ? _STATE_TABLE_RTL : _STATE_TABLE_LTR,
31001 types = [];
31002
31003 _lastArabic = false;
31004 _hasUbatB = false;
31005 _hasUbatS = false;
31006 for (i = 0; i < len; i++) {
31007 types[i] = _getCharType(chars[i]);
31008 }
31009 for (index = 0; index < len; index++) {
31010 prevState = newState;
31011 resolvedTypes[index] = _resolveCharType(
31012 chars,
31013 types,
31014 resolvedTypes,
31015 index
31016 );
31017 newState = stateTable[prevState][_TYPE_NAMES_MAP[resolvedTypes[index]]];
31018 action = newState & 0xf0;
31019 newState &= 0x0f;
31020 levels[index] = newLevel = stateTable[newState][5];
31021 if (action > 0) {
31022 if (action === 0x10) {
31023 for (i = condPos; i < index; i++) {
31024 levels[i] = 1;
31025 }
31026 condPos = -1;
31027 } else {
31028 condPos = -1;
31029 }
31030 }
31031 condition = stateTable[newState][6];
31032 if (condition) {
31033 if (condPos === -1) {
31034 condPos = index;
31035 }
31036 } else {
31037 if (condPos > -1) {
31038 for (i = condPos; i < index; i++) {
31039 levels[i] = newLevel;
31040 }
31041 condPos = -1;
31042 }
31043 }
31044 if (types[index] === "B") {
31045 levels[index] = 0;
31046 }
31047 params.hiLevel |= newLevel;
31048 }
31049 if (_hasUbatS) {
31050 _handleUbatS(types, levels, len);
31051 }
31052 };
31053
31054 // for reference see 3.4 in http://unicode.org/reports/tr9/
31055 //
31056 var _invertByLevel = function(
31057 level,
31058 charArray,
31059 sourceToTargetMap,
31060 levels,
31061 params
31062 ) {
31063 if (params.hiLevel < level) {
31064 return;
31065 }
31066 if (level === 1 && _dir === DIR_RTL && !_hasUbatB) {
31067 charArray.reverse();
31068 sourceToTargetMap && sourceToTargetMap.reverse();
31069 return;
31070 }
31071 var ch,
31072 high,
31073 end,
31074 low,
31075 len = charArray.length,
31076 start = 0;
31077
31078 while (start < len) {
31079 if (levels[start] >= level) {
31080 end = start + 1;
31081 while (end < len && levels[end] >= level) {
31082 end++;
31083 }
31084 for (low = start, high = end - 1; low < high; low++, high--) {
31085 ch = charArray[low];
31086 charArray[low] = charArray[high];
31087 charArray[high] = ch;
31088 if (sourceToTargetMap) {
31089 ch = sourceToTargetMap[low];
31090 sourceToTargetMap[low] = sourceToTargetMap[high];
31091 sourceToTargetMap[high] = ch;
31092 }
31093 }
31094 start = end;
31095 }
31096 start++;
31097 }
31098 };
31099
31100 // for reference see 7 & BD16 in http://unicode.org/reports/tr9/
31101 //
31102 var _symmetricSwap = function(charArray, levels, params) {
31103 if (params.hiLevel !== 0 && _isSymmetricSwapping) {
31104 for (var i = 0, index; i < charArray.length; i++) {
31105 if (levels[i] === 1) {
31106 index = _SWAP_TABLE.indexOf(charArray[i]);
31107 if (index >= 0) {
31108 charArray[i] = _SWAP_TABLE[index + 1];
31109 }
31110 }
31111 }
31112 }
31113 };
31114
31115 var _reorder = function(text, sourceToTargetMap, levels) {
31116 var charArray = text.split(""),
31117 params = { hiLevel: _dir };
31118
31119 if (!levels) {
31120 levels = [];
31121 }
31122 _computeLevels(charArray, levels, params);
31123 _symmetricSwap(charArray, levels, params);
31124 _invertByLevel(DIR_RTL + 1, charArray, sourceToTargetMap, levels, params);
31125 _invertByLevel(DIR_RTL, charArray, sourceToTargetMap, levels, params);
31126 return charArray.join("");
31127 };
31128
31129 // doBidiReorder( text, sourceToTargetMap, levels )
31130 // Performs Bidi reordering by implementing Unicode Bidi algorithm.
31131 // Returns reordered string
31132 // @text [String]:
31133 // - input string to be reordered, this is input parameter
31134 // $sourceToTargetMap [Array] (optional)
31135 // - resultant mapping between input and output strings, this is output parameter
31136 // $levels [Array] (optional)
31137 // - array of calculated Bidi levels, , this is output parameter
31138 this.__bidiEngine__.doBidiReorder = function(
31139 text,
31140 sourceToTargetMap,
31141 levels
31142 ) {
31143 _init(text, sourceToTargetMap);
31144 if (!_isInVisual && _isOutVisual && !_isOutRtl) {
31145 // LLTR->VLTR, LRTL->VLTR
31146 _dir = _isInRtl ? DIR_RTL : DIR_LTR;
31147 text = _reorder(text, sourceToTargetMap, levels);
31148 } else if (_isInVisual && _isOutVisual && _isInRtl ^ _isOutRtl) {
31149 // VRTL->VLTR, VLTR->VRTL
31150 _dir = _isInRtl ? DIR_RTL : DIR_LTR;
31151 text = _invertString(text, sourceToTargetMap, levels);
31152 } else if (!_isInVisual && _isOutVisual && _isOutRtl) {
31153 // LLTR->VRTL, LRTL->VRTL
31154 _dir = _isInRtl ? DIR_RTL : DIR_LTR;
31155 text = _reorder(text, sourceToTargetMap, levels);
31156 text = _invertString(text, sourceToTargetMap);
31157 } else if (_isInVisual && !_isInRtl && !_isOutVisual && !_isOutRtl) {
31158 // VLTR->LLTR
31159 _dir = DIR_LTR;
31160 text = _reorder(text, sourceToTargetMap, levels);
31161 } else if (_isInVisual && !_isOutVisual && _isInRtl ^ _isOutRtl) {
31162 // VLTR->LRTL, VRTL->LLTR
31163 text = _invertString(text, sourceToTargetMap);
31164 if (_isInRtl) {
31165 //LLTR -> VLTR
31166 _dir = DIR_LTR;
31167 text = _reorder(text, sourceToTargetMap, levels);
31168 } else {
31169 //LRTL -> VRTL
31170 _dir = DIR_RTL;
31171 text = _reorder(text, sourceToTargetMap, levels);
31172 text = _invertString(text, sourceToTargetMap);
31173 }
31174 } else if (_isInVisual && _isInRtl && !_isOutVisual && _isOutRtl) {
31175 // VRTL->LRTL
31176 _dir = DIR_RTL;
31177 text = _reorder(text, sourceToTargetMap, levels);
31178 text = _invertString(text, sourceToTargetMap);
31179 } else if (!_isInVisual && !_isOutVisual && _isInRtl ^ _isOutRtl) {
31180 // LRTL->LLTR, LLTR->LRTL
31181 var isSymmetricSwappingOrig = _isSymmetricSwapping;
31182 if (_isInRtl) {
31183 //LRTL->LLTR
31184 _dir = DIR_RTL;
31185 text = _reorder(text, sourceToTargetMap, levels);
31186 _dir = DIR_LTR;
31187 _isSymmetricSwapping = false;
31188 text = _reorder(text, sourceToTargetMap, levels);
31189 _isSymmetricSwapping = isSymmetricSwappingOrig;
31190 } else {
31191 //LLTR->LRTL
31192 _dir = DIR_LTR;
31193 text = _reorder(text, sourceToTargetMap, levels);
31194 text = _invertString(text, sourceToTargetMap);
31195 _dir = DIR_RTL;
31196 _isSymmetricSwapping = false;
31197 text = _reorder(text, sourceToTargetMap, levels);
31198 _isSymmetricSwapping = isSymmetricSwappingOrig;
31199 text = _invertString(text, sourceToTargetMap);
31200 }
31201 }
31202 return text;
31203 };
31204
31205 /**
31206 * @name setOptions( options )
31207 * @function
31208 * Sets options for Bidi conversion
31209 * @param {Object}:
31210 * - isInputVisual {boolean} (defaults to false): allowed values: true(Visual mode), false(Logical mode)
31211 * - isInputRtl {boolean}: allowed values true(Right-to-left direction), false (Left-to-right directiion), undefined(Contectual direction, i.e.direction defined by first strong character of input string)
31212 * - isOutputVisual {boolean} (defaults to false): allowed values: true(Visual mode), false(Logical mode)
31213 * - isOutputRtl {boolean}: allowed values true(Right-to-left direction), false (Left-to-right directiion), undefined(Contectual direction, i.e.direction defined by first strong characterof input string)
31214 * - isSymmetricSwapping {boolean} (defaults to false): allowed values true(needs symmetric swapping), false (no need in symmetric swapping),
31215 */
31216 this.__bidiEngine__.setOptions = function(options) {
31217 if (options) {
31218 _isInVisual = options.isInputVisual;
31219 _isOutVisual = options.isOutputVisual;
31220 _isInRtl = options.isInputRtl;
31221 _isOutRtl = options.isOutputRtl;
31222 _isSymmetricSwapping = options.isSymmetricSwapping;
31223 }
31224 };
31225
31226 this.__bidiEngine__.setOptions(options);
31227 return this.__bidiEngine__;
31228 };
31229
31230 var _bidiUnicodeTypes = bidiUnicodeTypes;
31231
31232 var bidiEngine = new jsPDF.__bidiEngine__({ isInputVisual: true });
31233
31234 var bidiEngineFunction = function(args) {
31235 var text = args.text;
31236 var x = args.x;
31237 var y = args.y;
31238 var options = args.options || {};
31239 var mutex = args.mutex || {};
31240 var lang = options.lang;
31241 var tmpText = [];
31242
31243 options.isInputVisual =
31244 typeof options.isInputVisual === "boolean" ? options.isInputVisual : true;
31245 bidiEngine.setOptions(options);
31246
31247 if (Object.prototype.toString.call(text) === "[object Array]") {
31248 var i = 0;
31249 tmpText = [];
31250 for (i = 0; i < text.length; i += 1) {
31251 if (Object.prototype.toString.call(text[i]) === "[object Array]") {
31252 tmpText.push([
31253 bidiEngine.doBidiReorder(text[i][0]),
31254 text[i][1],
31255 text[i][2]
31256 ]);
31257 } else {
31258 tmpText.push([bidiEngine.doBidiReorder(text[i])]);
31259 }
31260 }
31261 args.text = tmpText;
31262 } else {
31263 args.text = bidiEngine.doBidiReorder(text);
31264 }
31265 bidiEngine.setOptions({ isInputVisual: true });
31266 };
31267
31268 jsPDF.API.events.push(["postProcessText", bidiEngineFunction]);
31269 })(jsPDF);
31270
31271 /* eslint-disable no-control-regex */
31272
31273 jsPDF.API.TTFFont = (function() {
31274 /************************************************************************/
31275 /* function : open */
31276 /* comment : Decode the encoded ttf content and create a TTFFont object. */
31277 /************************************************************************/
31278 TTFFont.open = function(file) {
31279 return new TTFFont(file);
31280 };
31281 /***************************************************************/
31282 /* function : TTFFont gernerator */
31283 /* comment : Decode TTF contents are parsed, Data, */
31284 /* Subset object is created, and registerTTF function is called.*/
31285 /***************************************************************/
31286 function TTFFont(rawData) {
31287 var data;
31288 this.rawData = rawData;
31289 data = this.contents = new Data(rawData);
31290 this.contents.pos = 4;
31291 if (data.readString(4) === "ttcf") {
31292 throw new Error("TTCF not supported.");
31293 } else {
31294 data.pos = 0;
31295 this.parse();
31296 this.subset = new Subset(this);
31297 this.registerTTF();
31298 }
31299 }
31300 /********************************************************/
31301 /* function : parse */
31302 /* comment : TTF Parses the file contents by each table.*/
31303 /********************************************************/
31304 TTFFont.prototype.parse = function() {
31305 this.directory = new Directory(this.contents);
31306 this.head = new HeadTable(this);
31307 this.name = new NameTable(this);
31308 this.cmap = new CmapTable(this);
31309 this.toUnicode = {};
31310 this.hhea = new HheaTable(this);
31311 this.maxp = new MaxpTable(this);
31312 this.hmtx = new HmtxTable(this);
31313 this.post = new PostTable(this);
31314 this.os2 = new OS2Table(this);
31315 this.loca = new LocaTable(this);
31316 this.glyf = new GlyfTable(this);
31317 this.ascender =
31318 (this.os2.exists && this.os2.ascender) || this.hhea.ascender;
31319 this.decender =
31320 (this.os2.exists && this.os2.decender) || this.hhea.decender;
31321 this.lineGap = (this.os2.exists && this.os2.lineGap) || this.hhea.lineGap;
31322 return (this.bbox = [
31323 this.head.xMin,
31324 this.head.yMin,
31325 this.head.xMax,
31326 this.head.yMax
31327 ]);
31328 };
31329 /***************************************************************/
31330 /* function : registerTTF */
31331 /* comment : Get the value to assign pdf font descriptors. */
31332 /***************************************************************/
31333 TTFFont.prototype.registerTTF = function() {
31334 var e, hi, low, raw, _ref;
31335 this.scaleFactor = 1000.0 / this.head.unitsPerEm;
31336 this.bbox = function() {
31337 var _i, _len, _ref, _results;
31338 _ref = this.bbox;
31339 _results = [];
31340 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
31341 e = _ref[_i];
31342 _results.push(Math.round(e * this.scaleFactor));
31343 }
31344 return _results;
31345 }.call(this);
31346 this.stemV = 0;
31347 if (this.post.exists) {
31348 raw = this.post.italic_angle;
31349 hi = raw >> 16;
31350 low = raw & 0xff;
31351 if ((hi & 0x8000) !== 0) {
31352 hi = -((hi ^ 0xffff) + 1);
31353 }
31354 this.italicAngle = +("" + hi + "." + low);
31355 } else {
31356 this.italicAngle = 0;
31357 }
31358 this.ascender = Math.round(this.ascender * this.scaleFactor);
31359 this.decender = Math.round(this.decender * this.scaleFactor);
31360 this.lineGap = Math.round(this.lineGap * this.scaleFactor);
31361 this.capHeight = (this.os2.exists && this.os2.capHeight) || this.ascender;
31362 this.xHeight = (this.os2.exists && this.os2.xHeight) || 0;
31363 this.familyClass = ((this.os2.exists && this.os2.familyClass) || 0) >> 8;
31364 this.isSerif =
31365 (_ref = this.familyClass) === 1 ||
31366 _ref === 2 ||
31367 _ref === 3 ||
31368 _ref === 4 ||
31369 _ref === 5 ||
31370 _ref === 7;
31371 this.isScript = this.familyClass === 10;
31372 this.flags = 0;
31373 if (this.post.isFixedPitch) {
31374 this.flags |= 1 << 0;
31375 }
31376 if (this.isSerif) {
31377 this.flags |= 1 << 1;
31378 }
31379 if (this.isScript) {
31380 this.flags |= 1 << 3;
31381 }
31382 if (this.italicAngle !== 0) {
31383 this.flags |= 1 << 6;
31384 }
31385 this.flags |= 1 << 5;
31386 if (!this.cmap.unicode) {
31387 throw new Error("No unicode cmap for font");
31388 }
31389 };
31390 TTFFont.prototype.characterToGlyph = function(character) {
31391 var _ref;
31392 return (
31393 ((_ref = this.cmap.unicode) != null ? _ref.codeMap[character] : void 0) ||
31394 0
31395 );
31396 };
31397 TTFFont.prototype.widthOfGlyph = function(glyph) {
31398 var scale;
31399 scale = 1000.0 / this.head.unitsPerEm;
31400 return this.hmtx.forGlyph(glyph).advance * scale;
31401 };
31402 TTFFont.prototype.widthOfString = function(string, size, charSpace) {
31403 var charCode, i, scale, width, _ref;
31404 string = "" + string;
31405 width = 0;
31406 for (
31407 i = 0, _ref = string.length;
31408 0 <= _ref ? i < _ref : i > _ref;
31409 i = 0 <= _ref ? ++i : --i
31410 ) {
31411 charCode = string.charCodeAt(i);
31412 width +=
31413 this.widthOfGlyph(this.characterToGlyph(charCode)) +
31414 charSpace * (1000 / size) || 0;
31415 }
31416 scale = size / 1000;
31417 return width * scale;
31418 };
31419 TTFFont.prototype.lineHeight = function(size, includeGap) {
31420 var gap;
31421 if (includeGap == null) {
31422 includeGap = false;
31423 }
31424 gap = includeGap ? this.lineGap : 0;
31425 return ((this.ascender + gap - this.decender) / 1000) * size;
31426 };
31427 return TTFFont;
31428 })();
31429
31430 /************************************************************************************************/
31431 /* function : Data */
31432 /* comment : The ttf data decoded and stored in an array is read and written to the Data object.*/
31433 /************************************************************************************************/
31434 var Data = (function() {
31435 function Data(data) {
31436 this.data = data != null ? data : [];
31437 this.pos = 0;
31438 this.length = this.data.length;
31439 }
31440 Data.prototype.readByte = function() {
31441 return this.data[this.pos++];
31442 };
31443 Data.prototype.writeByte = function(byte) {
31444 return (this.data[this.pos++] = byte);
31445 };
31446 Data.prototype.readUInt32 = function() {
31447 var b1, b2, b3, b4;
31448 b1 = this.readByte() * 0x1000000;
31449 b2 = this.readByte() << 16;
31450 b3 = this.readByte() << 8;
31451 b4 = this.readByte();
31452 return b1 + b2 + b3 + b4;
31453 };
31454 Data.prototype.writeUInt32 = function(val) {
31455 this.writeByte((val >>> 24) & 0xff);
31456 this.writeByte((val >> 16) & 0xff);
31457 this.writeByte((val >> 8) & 0xff);
31458 return this.writeByte(val & 0xff);
31459 };
31460 Data.prototype.readInt32 = function() {
31461 var int;
31462 int = this.readUInt32();
31463 if (int >= 0x80000000) {
31464 return int - 0x100000000;
31465 } else {
31466 return int;
31467 }
31468 };
31469 Data.prototype.writeInt32 = function(val) {
31470 if (val < 0) {
31471 val += 0x100000000;
31472 }
31473 return this.writeUInt32(val);
31474 };
31475 Data.prototype.readUInt16 = function() {
31476 var b1, b2;
31477 b1 = this.readByte() << 8;
31478 b2 = this.readByte();
31479 return b1 | b2;
31480 };
31481 Data.prototype.writeUInt16 = function(val) {
31482 this.writeByte((val >> 8) & 0xff);
31483 return this.writeByte(val & 0xff);
31484 };
31485 Data.prototype.readInt16 = function() {
31486 var int;
31487 int = this.readUInt16();
31488 if (int >= 0x8000) {
31489 return int - 0x10000;
31490 } else {
31491 return int;
31492 }
31493 };
31494 Data.prototype.writeInt16 = function(val) {
31495 if (val < 0) {
31496 val += 0x10000;
31497 }
31498 return this.writeUInt16(val);
31499 };
31500 Data.prototype.readString = function(length) {
31501 var i, ret;
31502 ret = [];
31503 for (
31504 i = 0;
31505 0 <= length ? i < length : i > length;
31506 i = 0 <= length ? ++i : --i
31507 ) {
31508 ret[i] = String.fromCharCode(this.readByte());
31509 }
31510 return ret.join("");
31511 };
31512 Data.prototype.writeString = function(val) {
31513 var i, _ref, _results;
31514 _results = [];
31515 for (
31516 i = 0, _ref = val.length;
31517 0 <= _ref ? i < _ref : i > _ref;
31518 i = 0 <= _ref ? ++i : --i
31519 ) {
31520 _results.push(this.writeByte(val.charCodeAt(i)));
31521 }
31522 return _results;
31523 };
31524 /*Data.prototype.stringAt = function (pos, length) {
31525 this.pos = pos;
31526 return this.readString(length);
31527 };*/
31528 Data.prototype.readShort = function() {
31529 return this.readInt16();
31530 };
31531 Data.prototype.writeShort = function(val) {
31532 return this.writeInt16(val);
31533 };
31534 Data.prototype.readLongLong = function() {
31535 var b1, b2, b3, b4, b5, b6, b7, b8;
31536 b1 = this.readByte();
31537 b2 = this.readByte();
31538 b3 = this.readByte();
31539 b4 = this.readByte();
31540 b5 = this.readByte();
31541 b6 = this.readByte();
31542 b7 = this.readByte();
31543 b8 = this.readByte();
31544 if (b1 & 0x80) {
31545 return (
31546 ((b1 ^ 0xff) * 0x100000000000000 +
31547 (b2 ^ 0xff) * 0x1000000000000 +
31548 (b3 ^ 0xff) * 0x10000000000 +
31549 (b4 ^ 0xff) * 0x100000000 +
31550 (b5 ^ 0xff) * 0x1000000 +
31551 (b6 ^ 0xff) * 0x10000 +
31552 (b7 ^ 0xff) * 0x100 +
31553 (b8 ^ 0xff) +
31554 1) *
31555 -1
31556 );
31557 }
31558 return (
31559 b1 * 0x100000000000000 +
31560 b2 * 0x1000000000000 +
31561 b3 * 0x10000000000 +
31562 b4 * 0x100000000 +
31563 b5 * 0x1000000 +
31564 b6 * 0x10000 +
31565 b7 * 0x100 +
31566 b8
31567 );
31568 };
31569 Data.prototype.writeLongLong = function(val) {
31570 var high, low;
31571 high = Math.floor(val / 0x100000000);
31572 low = val & 0xffffffff;
31573 this.writeByte((high >> 24) & 0xff);
31574 this.writeByte((high >> 16) & 0xff);
31575 this.writeByte((high >> 8) & 0xff);
31576 this.writeByte(high & 0xff);
31577 this.writeByte((low >> 24) & 0xff);
31578 this.writeByte((low >> 16) & 0xff);
31579 this.writeByte((low >> 8) & 0xff);
31580 return this.writeByte(low & 0xff);
31581 };
31582 Data.prototype.readInt = function() {
31583 return this.readInt32();
31584 };
31585 Data.prototype.writeInt = function(val) {
31586 return this.writeInt32(val);
31587 };
31588 /*Data.prototype.slice = function (start, end) {
31589 return this.data.slice(start, end);
31590 };*/
31591 Data.prototype.read = function(bytes) {
31592 var buf, i;
31593 buf = [];
31594 for (
31595 i = 0;
31596 0 <= bytes ? i < bytes : i > bytes;
31597 i = 0 <= bytes ? ++i : --i
31598 ) {
31599 buf.push(this.readByte());
31600 }
31601 return buf;
31602 };
31603 Data.prototype.write = function(bytes) {
31604 var byte, i, _len, _results;
31605 _results = [];
31606 for (i = 0, _len = bytes.length; i < _len; i++) {
31607 byte = bytes[i];
31608 _results.push(this.writeByte(byte));
31609 }
31610 return _results;
31611 };
31612 return Data;
31613 })();
31614
31615 var Directory = (function() {
31616 var checksum;
31617
31618 /*****************************************************************************************************/
31619 /* function : Directory generator */
31620 /* comment : Initialize the offset, tag, length, and checksum for each table for the font to be used.*/
31621 /*****************************************************************************************************/
31622 function Directory(data) {
31623 var entry, i, _ref;
31624 this.scalarType = data.readInt();
31625 this.tableCount = data.readShort();
31626 this.searchRange = data.readShort();
31627 this.entrySelector = data.readShort();
31628 this.rangeShift = data.readShort();
31629 this.tables = {};
31630 for (
31631 i = 0, _ref = this.tableCount;
31632 0 <= _ref ? i < _ref : i > _ref;
31633 i = 0 <= _ref ? ++i : --i
31634 ) {
31635 entry = {
31636 tag: data.readString(4),
31637 checksum: data.readInt(),
31638 offset: data.readInt(),
31639 length: data.readInt()
31640 };
31641 this.tables[entry.tag] = entry;
31642 }
31643 }
31644 /********************************************************************************************************/
31645 /* function : encode */
31646 /* comment : It encodes and stores the font table object and information used for the directory object. */
31647 /********************************************************************************************************/
31648 Directory.prototype.encode = function(tables) {
31649 var adjustment,
31650 directory,
31651 directoryLength,
31652 entrySelector,
31653 headOffset,
31654 log2,
31655 offset,
31656 rangeShift,
31657 searchRange,
31658 sum,
31659 table,
31660 tableCount,
31661 tableData,
31662 tag;
31663 tableCount = Object.keys(tables).length;
31664 log2 = Math.log(2);
31665 searchRange = Math.floor(Math.log(tableCount) / log2) * 16;
31666 entrySelector = Math.floor(searchRange / log2);
31667 rangeShift = tableCount * 16 - searchRange;
31668 directory = new Data();
31669 directory.writeInt(this.scalarType);
31670 directory.writeShort(tableCount);
31671 directory.writeShort(searchRange);
31672 directory.writeShort(entrySelector);
31673 directory.writeShort(rangeShift);
31674 directoryLength = tableCount * 16;
31675 offset = directory.pos + directoryLength;
31676 headOffset = null;
31677 tableData = [];
31678 for (tag in tables) {
31679 table = tables[tag];
31680 directory.writeString(tag);
31681 directory.writeInt(checksum(table));
31682 directory.writeInt(offset);
31683 directory.writeInt(table.length);
31684 tableData = tableData.concat(table);
31685 if (tag === "head") {
31686 headOffset = offset;
31687 }
31688 offset += table.length;
31689 while (offset % 4) {
31690 tableData.push(0);
31691 offset++;
31692 }
31693 }
31694 directory.write(tableData);
31695 sum = checksum(directory.data);
31696 adjustment = 0xb1b0afba - sum;
31697 directory.pos = headOffset + 8;
31698 directory.writeUInt32(adjustment);
31699 return directory.data;
31700 };
31701 /***************************************************************/
31702 /* function : checksum */
31703 /* comment : Duplicate the table for the tag. */
31704 /***************************************************************/
31705 checksum = function(data) {
31706 var i, sum, tmp, _ref;
31707 data = __slice.call(data);
31708 while (data.length % 4) {
31709 data.push(0);
31710 }
31711 tmp = new Data(data);
31712 sum = 0;
31713 for (i = 0, _ref = data.length; i < _ref; i = i += 4) {
31714 sum += tmp.readUInt32();
31715 }
31716 return sum & 0xffffffff;
31717 };
31718 return Directory;
31719 })();
31720
31721 var Table,
31722 __hasProp = {}.hasOwnProperty,
31723 __extends = function(child, parent) {
31724 for (var key in parent) {
31725 if (__hasProp.call(parent, key)) child[key] = parent[key];
31726 }
31727
31728 function ctor() {
31729 this.constructor = child;
31730 }
31731 ctor.prototype = parent.prototype;
31732 child.prototype = new ctor();
31733 child.__super__ = parent.prototype;
31734 return child;
31735 };
31736
31737 /***************************************************************/
31738 /* function : Table */
31739 /* comment : Save info for each table, and parse the table. */
31740 /***************************************************************/
31741 Table = (function() {
31742 function Table(file) {
31743 var info;
31744 this.file = file;
31745 info = this.file.directory.tables[this.tag];
31746 this.exists = !!info;
31747 if (info) {
31748 (this.offset = info.offset), (this.length = info.length);
31749 this.parse(this.file.contents);
31750 }
31751 }
31752 Table.prototype.parse = function() {};
31753 Table.prototype.encode = function() {};
31754 Table.prototype.raw = function() {
31755 if (!this.exists) {
31756 return null;
31757 }
31758 this.file.contents.pos = this.offset;
31759 return this.file.contents.read(this.length);
31760 };
31761 return Table;
31762 })();
31763
31764 var HeadTable = (function(_super) {
31765 __extends(HeadTable, _super);
31766
31767 function HeadTable() {
31768 return HeadTable.__super__.constructor.apply(this, arguments);
31769 }
31770 HeadTable.prototype.tag = "head";
31771 HeadTable.prototype.parse = function(data) {
31772 data.pos = this.offset;
31773 this.version = data.readInt();
31774 this.revision = data.readInt();
31775 this.checkSumAdjustment = data.readInt();
31776 this.magicNumber = data.readInt();
31777 this.flags = data.readShort();
31778 this.unitsPerEm = data.readShort();
31779 this.created = data.readLongLong();
31780 this.modified = data.readLongLong();
31781 this.xMin = data.readShort();
31782 this.yMin = data.readShort();
31783 this.xMax = data.readShort();
31784 this.yMax = data.readShort();
31785 this.macStyle = data.readShort();
31786 this.lowestRecPPEM = data.readShort();
31787 this.fontDirectionHint = data.readShort();
31788 this.indexToLocFormat = data.readShort();
31789 return (this.glyphDataFormat = data.readShort());
31790 };
31791 HeadTable.prototype.encode = function(indexToLocFormat) {
31792 var table;
31793 table = new Data();
31794 table.writeInt(this.version);
31795 table.writeInt(this.revision);
31796 table.writeInt(this.checkSumAdjustment);
31797 table.writeInt(this.magicNumber);
31798 table.writeShort(this.flags);
31799 table.writeShort(this.unitsPerEm);
31800 table.writeLongLong(this.created);
31801 table.writeLongLong(this.modified);
31802 table.writeShort(this.xMin);
31803 table.writeShort(this.yMin);
31804 table.writeShort(this.xMax);
31805 table.writeShort(this.yMax);
31806 table.writeShort(this.macStyle);
31807 table.writeShort(this.lowestRecPPEM);
31808 table.writeShort(this.fontDirectionHint);
31809 table.writeShort(indexToLocFormat);
31810 table.writeShort(this.glyphDataFormat);
31811 return table.data;
31812 };
31813 return HeadTable;
31814 })(Table);
31815
31816 /************************************************************************************/
31817 /* function : CmapEntry */
31818 /* comment : Cmap Initializes and encodes object information (required by pdf spec).*/
31819 /************************************************************************************/
31820 var CmapEntry = (function() {
31821 function CmapEntry(data, offset) {
31822 var code,
31823 count,
31824 endCode,
31825 glyphId,
31826 glyphIds,
31827 i,
31828 idDelta,
31829 idRangeOffset,
31830 index,
31831 saveOffset,
31832 segCount,
31833 segCountX2,
31834 start,
31835 startCode,
31836 tail,
31837 _j,
31838 _k,
31839 _len;
31840 this.platformID = data.readUInt16();
31841 this.encodingID = data.readShort();
31842 this.offset = offset + data.readInt();
31843 saveOffset = data.pos;
31844 data.pos = this.offset;
31845 this.format = data.readUInt16();
31846 this.length = data.readUInt16();
31847 this.language = data.readUInt16();
31848 this.isUnicode =
31849 (this.platformID === 3 && this.encodingID === 1 && this.format === 4) ||
31850 (this.platformID === 0 && this.format === 4);
31851 this.codeMap = {};
31852 switch (this.format) {
31853 case 0:
31854 for (i = 0; i < 256; ++i) {
31855 this.codeMap[i] = data.readByte();
31856 }
31857 break;
31858 case 4:
31859 segCountX2 = data.readUInt16();
31860 segCount = segCountX2 / 2;
31861 data.pos += 6;
31862 endCode = (function() {
31863 var _j, _results;
31864 _results = [];
31865 for (
31866 i = _j = 0;
31867 0 <= segCount ? _j < segCount : _j > segCount;
31868 i = 0 <= segCount ? ++_j : --_j
31869 ) {
31870 _results.push(data.readUInt16());
31871 }
31872 return _results;
31873 })();
31874 data.pos += 2;
31875 startCode = (function() {
31876 var _j, _results;
31877 _results = [];
31878 for (
31879 i = _j = 0;
31880 0 <= segCount ? _j < segCount : _j > segCount;
31881 i = 0 <= segCount ? ++_j : --_j
31882 ) {
31883 _results.push(data.readUInt16());
31884 }
31885 return _results;
31886 })();
31887 idDelta = (function() {
31888 var _j, _results;
31889 _results = [];
31890 for (
31891 i = _j = 0;
31892 0 <= segCount ? _j < segCount : _j > segCount;
31893 i = 0 <= segCount ? ++_j : --_j
31894 ) {
31895 _results.push(data.readUInt16());
31896 }
31897 return _results;
31898 })();
31899 idRangeOffset = (function() {
31900 var _j, _results;
31901 _results = [];
31902 for (
31903 i = _j = 0;
31904 0 <= segCount ? _j < segCount : _j > segCount;
31905 i = 0 <= segCount ? ++_j : --_j
31906 ) {
31907 _results.push(data.readUInt16());
31908 }
31909 return _results;
31910 })();
31911 count = (this.length - data.pos + this.offset) / 2;
31912 glyphIds = (function() {
31913 var _j, _results;
31914 _results = [];
31915 for (
31916 i = _j = 0;
31917 0 <= count ? _j < count : _j > count;
31918 i = 0 <= count ? ++_j : --_j
31919 ) {
31920 _results.push(data.readUInt16());
31921 }
31922 return _results;
31923 })();
31924 for (i = _j = 0, _len = endCode.length; _j < _len; i = ++_j) {
31925 tail = endCode[i];
31926 start = startCode[i];
31927 for (
31928 code = _k = start;
31929 start <= tail ? _k <= tail : _k >= tail;
31930 code = start <= tail ? ++_k : --_k
31931 ) {
31932 if (idRangeOffset[i] === 0) {
31933 glyphId = code + idDelta[i];
31934 } else {
31935 index = idRangeOffset[i] / 2 + (code - start) - (segCount - i);
31936 glyphId = glyphIds[index] || 0;
31937 if (glyphId !== 0) {
31938 glyphId += idDelta[i];
31939 }
31940 }
31941 this.codeMap[code] = glyphId & 0xffff;
31942 }
31943 }
31944 }
31945 data.pos = saveOffset;
31946 }
31947 CmapEntry.encode = function(charmap, encoding) {
31948 var charMap,
31949 code,
31950 codeMap,
31951 codes,
31952 delta,
31953 deltas,
31954 diff,
31955 endCode,
31956 endCodes,
31957 entrySelector,
31958 glyphIDs,
31959 i,
31960 id,
31961 indexes,
31962 last,
31963 map,
31964 nextID,
31965 offset,
31966 old,
31967 rangeOffsets,
31968 rangeShift,
31969 searchRange,
31970 segCount,
31971 segCountX2,
31972 startCode,
31973 startCodes,
31974 startGlyph,
31975 subtable,
31976 _i,
31977 _j,
31978 _k,
31979 _l,
31980 _len,
31981 _len1,
31982 _len2,
31983 _len3,
31984 _len4,
31985 _len5,
31986 _len6,
31987 _len7,
31988 _m,
31989 _n,
31990 _name,
31991 _o,
31992 _p,
31993 _q;
31994 subtable = new Data();
31995 codes = Object.keys(charmap).sort(function(a, b) {
31996 return a - b;
31997 });
31998 switch (encoding) {
31999 case "macroman":
32000 id = 0;
32001 indexes = (function() {
32002 var _results = [];
32003 for (i = 0; i < 256; ++i) {
32004 _results.push(0);
32005 }
32006 return _results;
32007 })();
32008 map = {
32009 0: 0
32010 };
32011 codeMap = {};
32012 for (_i = 0, _len = codes.length; _i < _len; _i++) {
32013 code = codes[_i];
32014 if (map[(_name = charmap[code])] == null) {
32015 map[_name] = ++id;
32016 }
32017 codeMap[code] = {
32018 old: charmap[code],
32019 new: map[charmap[code]]
32020 };
32021 indexes[code] = map[charmap[code]];
32022 }
32023 subtable.writeUInt16(1);
32024 subtable.writeUInt16(0);
32025 subtable.writeUInt32(12);
32026 subtable.writeUInt16(0);
32027 subtable.writeUInt16(262);
32028 subtable.writeUInt16(0);
32029 subtable.write(indexes);
32030 return {
32031 charMap: codeMap,
32032 subtable: subtable.data,
32033 maxGlyphID: id + 1
32034 };
32035 case "unicode":
32036 startCodes = [];
32037 endCodes = [];
32038 nextID = 0;
32039 map = {};
32040 charMap = {};
32041 last = diff = null;
32042 for (_j = 0, _len1 = codes.length; _j < _len1; _j++) {
32043 code = codes[_j];
32044 old = charmap[code];
32045 if (map[old] == null) {
32046 map[old] = ++nextID;
32047 }
32048 charMap[code] = {
32049 old: old,
32050 new: map[old]
32051 };
32052 delta = map[old] - code;
32053 if (last == null || delta !== diff) {
32054 if (last) {
32055 endCodes.push(last);
32056 }
32057 startCodes.push(code);
32058 diff = delta;
32059 }
32060 last = code;
32061 }
32062 if (last) {
32063 endCodes.push(last);
32064 }
32065 endCodes.push(0xffff);
32066 startCodes.push(0xffff);
32067 segCount = startCodes.length;
32068 segCountX2 = segCount * 2;
32069 searchRange = 2 * Math.pow(Math.log(segCount) / Math.LN2, 2);
32070 entrySelector = Math.log(searchRange / 2) / Math.LN2;
32071 rangeShift = 2 * segCount - searchRange;
32072 deltas = [];
32073 rangeOffsets = [];
32074 glyphIDs = [];
32075 for (i = _k = 0, _len2 = startCodes.length; _k < _len2; i = ++_k) {
32076 startCode = startCodes[i];
32077 endCode = endCodes[i];
32078 if (startCode === 0xffff) {
32079 deltas.push(0);
32080 rangeOffsets.push(0);
32081 break;
32082 }
32083 startGlyph = charMap[startCode]["new"];
32084 if (startCode - startGlyph >= 0x8000) {
32085 deltas.push(0);
32086 rangeOffsets.push(2 * (glyphIDs.length + segCount - i));
32087 for (
32088 code = _l = startCode;
32089 startCode <= endCode ? _l <= endCode : _l >= endCode;
32090 code = startCode <= endCode ? ++_l : --_l
32091 ) {
32092 glyphIDs.push(charMap[code]["new"]);
32093 }
32094 } else {
32095 deltas.push(startGlyph - startCode);
32096 rangeOffsets.push(0);
32097 }
32098 }
32099 subtable.writeUInt16(3);
32100 subtable.writeUInt16(1);
32101 subtable.writeUInt32(12);
32102 subtable.writeUInt16(4);
32103 subtable.writeUInt16(16 + segCount * 8 + glyphIDs.length * 2);
32104 subtable.writeUInt16(0);
32105 subtable.writeUInt16(segCountX2);
32106 subtable.writeUInt16(searchRange);
32107 subtable.writeUInt16(entrySelector);
32108 subtable.writeUInt16(rangeShift);
32109 for (_m = 0, _len3 = endCodes.length; _m < _len3; _m++) {
32110 code = endCodes[_m];
32111 subtable.writeUInt16(code);
32112 }
32113 subtable.writeUInt16(0);
32114 for (_n = 0, _len4 = startCodes.length; _n < _len4; _n++) {
32115 code = startCodes[_n];
32116 subtable.writeUInt16(code);
32117 }
32118 for (_o = 0, _len5 = deltas.length; _o < _len5; _o++) {
32119 delta = deltas[_o];
32120 subtable.writeUInt16(delta);
32121 }
32122 for (_p = 0, _len6 = rangeOffsets.length; _p < _len6; _p++) {
32123 offset = rangeOffsets[_p];
32124 subtable.writeUInt16(offset);
32125 }
32126 for (_q = 0, _len7 = glyphIDs.length; _q < _len7; _q++) {
32127 id = glyphIDs[_q];
32128 subtable.writeUInt16(id);
32129 }
32130 return {
32131 charMap: charMap,
32132 subtable: subtable.data,
32133 maxGlyphID: nextID + 1
32134 };
32135 }
32136 };
32137 return CmapEntry;
32138 })();
32139
32140 var CmapTable = (function(_super) {
32141 __extends(CmapTable, _super);
32142
32143 function CmapTable() {
32144 return CmapTable.__super__.constructor.apply(this, arguments);
32145 }
32146 CmapTable.prototype.tag = "cmap";
32147 CmapTable.prototype.parse = function(data) {
32148 var entry, i, tableCount;
32149 data.pos = this.offset;
32150 this.version = data.readUInt16();
32151 tableCount = data.readUInt16();
32152 this.tables = [];
32153 this.unicode = null;
32154 for (
32155 i = 0;
32156 0 <= tableCount ? i < tableCount : i > tableCount;
32157 i = 0 <= tableCount ? ++i : --i
32158 ) {
32159 entry = new CmapEntry(data, this.offset);
32160 this.tables.push(entry);
32161 if (entry.isUnicode) {
32162 if (this.unicode == null) {
32163 this.unicode = entry;
32164 }
32165 }
32166 }
32167 return true;
32168 };
32169 /*************************************************************************/
32170 /* function : encode */
32171 /* comment : Encode the cmap table corresponding to the input character. */
32172 /*************************************************************************/
32173 CmapTable.encode = function(charmap, encoding) {
32174 var result, table;
32175 if (encoding == null) {
32176 encoding = "macroman";
32177 }
32178 result = CmapEntry.encode(charmap, encoding);
32179 table = new Data();
32180 table.writeUInt16(0);
32181 table.writeUInt16(1);
32182 result.table = table.data.concat(result.subtable);
32183 return result;
32184 };
32185 return CmapTable;
32186 })(Table);
32187
32188 var HheaTable = (function(_super) {
32189 __extends(HheaTable, _super);
32190
32191 function HheaTable() {
32192 return HheaTable.__super__.constructor.apply(this, arguments);
32193 }
32194 HheaTable.prototype.tag = "hhea";
32195 HheaTable.prototype.parse = function(data) {
32196 data.pos = this.offset;
32197 this.version = data.readInt();
32198 this.ascender = data.readShort();
32199 this.decender = data.readShort();
32200 this.lineGap = data.readShort();
32201 this.advanceWidthMax = data.readShort();
32202 this.minLeftSideBearing = data.readShort();
32203 this.minRightSideBearing = data.readShort();
32204 this.xMaxExtent = data.readShort();
32205 this.caretSlopeRise = data.readShort();
32206 this.caretSlopeRun = data.readShort();
32207 this.caretOffset = data.readShort();
32208 data.pos += 4 * 2;
32209 this.metricDataFormat = data.readShort();
32210 return (this.numberOfMetrics = data.readUInt16());
32211 };
32212 /*HheaTable.prototype.encode = function (ids) {
32213 var i, table, _i, _ref;
32214 table = new Data;
32215 table.writeInt(this.version);
32216 table.writeShort(this.ascender);
32217 table.writeShort(this.decender);
32218 table.writeShort(this.lineGap);
32219 table.writeShort(this.advanceWidthMax);
32220 table.writeShort(this.minLeftSideBearing);
32221 table.writeShort(this.minRightSideBearing);
32222 table.writeShort(this.xMaxExtent);
32223 table.writeShort(this.caretSlopeRise);
32224 table.writeShort(this.caretSlopeRun);
32225 table.writeShort(this.caretOffset);
32226 for (i = _i = 0, _ref = 4 * 2; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
32227 table.writeByte(0);
32228 }
32229 table.writeShort(this.metricDataFormat);
32230 table.writeUInt16(ids.length);
32231 return table.data;
32232 };*/
32233 return HheaTable;
32234 })(Table);
32235
32236 var OS2Table = (function(_super) {
32237 __extends(OS2Table, _super);
32238
32239 function OS2Table() {
32240 return OS2Table.__super__.constructor.apply(this, arguments);
32241 }
32242 OS2Table.prototype.tag = "OS/2";
32243 OS2Table.prototype.parse = function(data) {
32244 data.pos = this.offset;
32245 this.version = data.readUInt16();
32246 this.averageCharWidth = data.readShort();
32247 this.weightClass = data.readUInt16();
32248 this.widthClass = data.readUInt16();
32249 this.type = data.readShort();
32250 this.ySubscriptXSize = data.readShort();
32251 this.ySubscriptYSize = data.readShort();
32252 this.ySubscriptXOffset = data.readShort();
32253 this.ySubscriptYOffset = data.readShort();
32254 this.ySuperscriptXSize = data.readShort();
32255 this.ySuperscriptYSize = data.readShort();
32256 this.ySuperscriptXOffset = data.readShort();
32257 this.ySuperscriptYOffset = data.readShort();
32258 this.yStrikeoutSize = data.readShort();
32259 this.yStrikeoutPosition = data.readShort();
32260 this.familyClass = data.readShort();
32261 this.panose = (function() {
32262 var i, _results;
32263 _results = [];
32264 for (i = 0; i < 10; ++i) {
32265 _results.push(data.readByte());
32266 }
32267 return _results;
32268 })();
32269 this.charRange = (function() {
32270 var i, _results;
32271 _results = [];
32272 for (i = 0; i < 4; ++i) {
32273 _results.push(data.readInt());
32274 }
32275 return _results;
32276 })();
32277 this.vendorID = data.readString(4);
32278 this.selection = data.readShort();
32279 this.firstCharIndex = data.readShort();
32280 this.lastCharIndex = data.readShort();
32281 if (this.version > 0) {
32282 this.ascent = data.readShort();
32283 this.descent = data.readShort();
32284 this.lineGap = data.readShort();
32285 this.winAscent = data.readShort();
32286 this.winDescent = data.readShort();
32287 this.codePageRange = (function() {
32288 var i, _results;
32289 _results = [];
32290 for (i = 0; i < 2; i = ++i) {
32291 _results.push(data.readInt());
32292 }
32293 return _results;
32294 })();
32295 if (this.version > 1) {
32296 this.xHeight = data.readShort();
32297 this.capHeight = data.readShort();
32298 this.defaultChar = data.readShort();
32299 this.breakChar = data.readShort();
32300 return (this.maxContext = data.readShort());
32301 }
32302 }
32303 };
32304 /*OS2Table.prototype.encode = function () {
32305 return this.raw();
32306 };*/
32307 return OS2Table;
32308 })(Table);
32309
32310 var PostTable = (function(_super) {
32311 __extends(PostTable, _super);
32312
32313 function PostTable() {
32314 return PostTable.__super__.constructor.apply(this, arguments);
32315 }
32316 PostTable.prototype.tag = "post";
32317 PostTable.prototype.parse = function(data) {
32318 var length, numberOfGlyphs, _results;
32319 data.pos = this.offset;
32320 this.format = data.readInt();
32321 this.italicAngle = data.readInt();
32322 this.underlinePosition = data.readShort();
32323 this.underlineThickness = data.readShort();
32324 this.isFixedPitch = data.readInt();
32325 this.minMemType42 = data.readInt();
32326 this.maxMemType42 = data.readInt();
32327 this.minMemType1 = data.readInt();
32328 this.maxMemType1 = data.readInt();
32329 switch (this.format) {
32330 case 0x00010000:
32331 break;
32332 case 0x00020000:
32333 numberOfGlyphs = data.readUInt16();
32334 this.glyphNameIndex = [];
32335 var i;
32336 for (
32337 i = 0;
32338 0 <= numberOfGlyphs ? i < numberOfGlyphs : i > numberOfGlyphs;
32339 i = 0 <= numberOfGlyphs ? ++i : --i
32340 ) {
32341 this.glyphNameIndex.push(data.readUInt16());
32342 }
32343 this.names = [];
32344 _results = [];
32345 while (data.pos < this.offset + this.length) {
32346 length = data.readByte();
32347 _results.push(this.names.push(data.readString(length)));
32348 }
32349 return _results;
32350 case 0x00025000:
32351 numberOfGlyphs = data.readUInt16();
32352 return (this.offsets = data.read(numberOfGlyphs));
32353 case 0x00030000:
32354 break;
32355 case 0x00040000:
32356 return (this.map = function() {
32357 var _j, _ref, _results1;
32358 _results1 = [];
32359 for (
32360 i = _j = 0, _ref = this.file.maxp.numGlyphs;
32361 0 <= _ref ? _j < _ref : _j > _ref;
32362 i = 0 <= _ref ? ++_j : --_j
32363 ) {
32364 _results1.push(data.readUInt32());
32365 }
32366 return _results1;
32367 }.call(this));
32368 }
32369 };
32370 return PostTable;
32371 })(Table);
32372
32373 /*********************************************************************************************************/
32374 /* function : NameEntry */
32375 /* comment : Store copyright information, platformID, encodingID, and languageID in the NameEntry object.*/
32376 /*********************************************************************************************************/
32377 var NameEntry = (function() {
32378 function NameEntry(raw, entry) {
32379 this.raw = raw;
32380 this.length = raw.length;
32381 this.platformID = entry.platformID;
32382 this.encodingID = entry.encodingID;
32383 this.languageID = entry.languageID;
32384 }
32385 return NameEntry;
32386 })();
32387
32388 var NameTable = (function(_super) {
32389 __extends(NameTable, _super);
32390
32391 function NameTable() {
32392 return NameTable.__super__.constructor.apply(this, arguments);
32393 }
32394 NameTable.prototype.tag = "name";
32395 NameTable.prototype.parse = function(data) {
32396 var count,
32397 entries,
32398 entry,
32399 i,
32400 name,
32401 stringOffset,
32402 strings,
32403 text,
32404 _j,
32405 _len,
32406 _name;
32407 data.pos = this.offset;
32408 data.readShort(); //format
32409 count = data.readShort();
32410 stringOffset = data.readShort();
32411 entries = [];
32412 for (
32413 i = 0;
32414 0 <= count ? i < count : i > count;
32415 i = 0 <= count ? ++i : --i
32416 ) {
32417 entries.push({
32418 platformID: data.readShort(),
32419 encodingID: data.readShort(),
32420 languageID: data.readShort(),
32421 nameID: data.readShort(),
32422 length: data.readShort(),
32423 offset: this.offset + stringOffset + data.readShort()
32424 });
32425 }
32426 strings = {};
32427 for (i = _j = 0, _len = entries.length; _j < _len; i = ++_j) {
32428 entry = entries[i];
32429 data.pos = entry.offset;
32430 text = data.readString(entry.length);
32431 name = new NameEntry(text, entry);
32432 if (strings[(_name = entry.nameID)] == null) {
32433 strings[_name] = [];
32434 }
32435 strings[entry.nameID].push(name);
32436 }
32437 this.strings = strings;
32438 this.copyright = strings[0];
32439 this.fontFamily = strings[1];
32440 this.fontSubfamily = strings[2];
32441 this.uniqueSubfamily = strings[3];
32442 this.fontName = strings[4];
32443 this.version = strings[5];
32444 try {
32445 this.postscriptName = strings[6][0].raw.replace(
32446 /[\x00-\x19\x80-\xff]/g,
32447 ""
32448 );
32449 } catch (e) {
32450 this.postscriptName = strings[4][0].raw.replace(
32451 /[\x00-\x19\x80-\xff]/g,
32452 ""
32453 );
32454 }
32455 this.trademark = strings[7];
32456 this.manufacturer = strings[8];
32457 this.designer = strings[9];
32458 this.description = strings[10];
32459 this.vendorUrl = strings[11];
32460 this.designerUrl = strings[12];
32461 this.license = strings[13];
32462 this.licenseUrl = strings[14];
32463 this.preferredFamily = strings[15];
32464 this.preferredSubfamily = strings[17];
32465 this.compatibleFull = strings[18];
32466 return (this.sampleText = strings[19]);
32467 };
32468 /*NameTable.prototype.encode = function () {
32469 var id, list, nameID, nameTable, postscriptName, strCount, strTable, string, strings, table, val, _i, _len, _ref;
32470 strings = {};
32471 _ref = this.strings;
32472 for (id in _ref) {
32473 val = _ref[id];
32474 strings[id] = val;
32475 }
32476 postscriptName = new NameEntry("" + subsetTag + "+" + this.postscriptName, {
32477 platformID: 1
32478 , encodingID: 0
32479 , languageID: 0
32480 });
32481 strings[6] = [postscriptName];
32482 subsetTag = successorOf(subsetTag);
32483 strCount = 0;
32484 for (id in strings) {
32485 list = strings[id];
32486 if (list != null) {
32487 strCount += list.length;
32488 }
32489 }
32490 table = new Data;
32491 strTable = new Data;
32492 table.writeShort(0);
32493 table.writeShort(strCount);
32494 table.writeShort(6 + 12 * strCount);
32495 for (nameID in strings) {
32496 list = strings[nameID];
32497 if (list != null) {
32498 for (_i = 0, _len = list.length; _i < _len; _i++) {
32499 string = list[_i];
32500 table.writeShort(string.platformID);
32501 table.writeShort(string.encodingID);
32502 table.writeShort(string.languageID);
32503 table.writeShort(nameID);
32504 table.writeShort(string.length);
32505 table.writeShort(strTable.pos);
32506 strTable.writeString(string.raw);
32507 }
32508 }
32509 }
32510 return nameTable = {
32511 postscriptName: postscriptName.raw
32512 , table: table.data.concat(strTable.data)
32513 };
32514 };*/
32515 return NameTable;
32516 })(Table);
32517
32518 var MaxpTable = (function(_super) {
32519 __extends(MaxpTable, _super);
32520
32521 function MaxpTable() {
32522 return MaxpTable.__super__.constructor.apply(this, arguments);
32523 }
32524 MaxpTable.prototype.tag = "maxp";
32525 MaxpTable.prototype.parse = function(data) {
32526 data.pos = this.offset;
32527 this.version = data.readInt();
32528 this.numGlyphs = data.readUInt16();
32529 this.maxPoints = data.readUInt16();
32530 this.maxContours = data.readUInt16();
32531 this.maxCompositePoints = data.readUInt16();
32532 this.maxComponentContours = data.readUInt16();
32533 this.maxZones = data.readUInt16();
32534 this.maxTwilightPoints = data.readUInt16();
32535 this.maxStorage = data.readUInt16();
32536 this.maxFunctionDefs = data.readUInt16();
32537 this.maxInstructionDefs = data.readUInt16();
32538 this.maxStackElements = data.readUInt16();
32539 this.maxSizeOfInstructions = data.readUInt16();
32540 this.maxComponentElements = data.readUInt16();
32541 return (this.maxComponentDepth = data.readUInt16());
32542 };
32543 /*MaxpTable.prototype.encode = function (ids) {
32544 var table;
32545 table = new Data;
32546 table.writeInt(this.version);
32547 table.writeUInt16(ids.length);
32548 table.writeUInt16(this.maxPoints);
32549 table.writeUInt16(this.maxContours);
32550 table.writeUInt16(this.maxCompositePoints);
32551 table.writeUInt16(this.maxComponentContours);
32552 table.writeUInt16(this.maxZones);
32553 table.writeUInt16(this.maxTwilightPoints);
32554 table.writeUInt16(this.maxStorage);
32555 table.writeUInt16(this.maxFunctionDefs);
32556 table.writeUInt16(this.maxInstructionDefs);
32557 table.writeUInt16(this.maxStackElements);
32558 table.writeUInt16(this.maxSizeOfInstructions);
32559 table.writeUInt16(this.maxComponentElements);
32560 table.writeUInt16(this.maxComponentDepth);
32561 return table.data;
32562 };*/
32563 return MaxpTable;
32564 })(Table);
32565
32566 var HmtxTable = (function(_super) {
32567 __extends(HmtxTable, _super);
32568
32569 function HmtxTable() {
32570 return HmtxTable.__super__.constructor.apply(this, arguments);
32571 }
32572 HmtxTable.prototype.tag = "hmtx";
32573 HmtxTable.prototype.parse = function(data) {
32574 var i, last, lsbCount, m, _j, _ref, _results;
32575 data.pos = this.offset;
32576 this.metrics = [];
32577 for (
32578 i = 0, _ref = this.file.hhea.numberOfMetrics;
32579 0 <= _ref ? i < _ref : i > _ref;
32580 i = 0 <= _ref ? ++i : --i
32581 ) {
32582 this.metrics.push({
32583 advance: data.readUInt16(),
32584 lsb: data.readInt16()
32585 });
32586 }
32587 lsbCount = this.file.maxp.numGlyphs - this.file.hhea.numberOfMetrics;
32588 this.leftSideBearings = (function() {
32589 var _j, _results;
32590 _results = [];
32591 for (
32592 i = _j = 0;
32593 0 <= lsbCount ? _j < lsbCount : _j > lsbCount;
32594 i = 0 <= lsbCount ? ++_j : --_j
32595 ) {
32596 _results.push(data.readInt16());
32597 }
32598 return _results;
32599 })();
32600 this.widths = function() {
32601 var _j, _len, _ref1, _results;
32602 _ref1 = this.metrics;
32603 _results = [];
32604 for (_j = 0, _len = _ref1.length; _j < _len; _j++) {
32605 m = _ref1[_j];
32606 _results.push(m.advance);
32607 }
32608 return _results;
32609 }.call(this);
32610 last = this.widths[this.widths.length - 1];
32611 _results = [];
32612 for (
32613 i = _j = 0;
32614 0 <= lsbCount ? _j < lsbCount : _j > lsbCount;
32615 i = 0 <= lsbCount ? ++_j : --_j
32616 ) {
32617 _results.push(this.widths.push(last));
32618 }
32619 return _results;
32620 };
32621 /***************************************************************/
32622 /* function : forGlyph */
32623 /* comment : Returns the advance width and lsb for this glyph. */
32624 /***************************************************************/
32625 HmtxTable.prototype.forGlyph = function(id) {
32626 if (id in this.metrics) {
32627 return this.metrics[id];
32628 }
32629 return {
32630 advance: this.metrics[this.metrics.length - 1].advance,
32631 lsb: this.leftSideBearings[id - this.metrics.length]
32632 };
32633 };
32634 /*HmtxTable.prototype.encode = function (mapping) {
32635 var id, metric, table, _i, _len;
32636 table = new Data;
32637 for (_i = 0, _len = mapping.length; _i < _len; _i++) {
32638 id = mapping[_i];
32639 metric = this.forGlyph(id);
32640 table.writeUInt16(metric.advance);
32641 table.writeUInt16(metric.lsb);
32642 }
32643 return table.data;
32644 };*/
32645 return HmtxTable;
32646 })(Table);
32647
32648 var __slice = [].slice;
32649
32650 var GlyfTable = (function(_super) {
32651 __extends(GlyfTable, _super);
32652
32653 function GlyfTable() {
32654 return GlyfTable.__super__.constructor.apply(this, arguments);
32655 }
32656 GlyfTable.prototype.tag = "glyf";
32657 GlyfTable.prototype.parse = function() {
32658 return (this.cache = {});
32659 };
32660 GlyfTable.prototype.glyphFor = function(id) {
32661 var data,
32662 index,
32663 length,
32664 loca,
32665 numberOfContours,
32666 raw,
32667 xMax,
32668 xMin,
32669 yMax,
32670 yMin;
32671 if (id in this.cache) {
32672 return this.cache[id];
32673 }
32674 loca = this.file.loca;
32675 data = this.file.contents;
32676 index = loca.indexOf(id);
32677 length = loca.lengthOf(id);
32678 if (length === 0) {
32679 return (this.cache[id] = null);
32680 }
32681 data.pos = this.offset + index;
32682 raw = new Data(data.read(length));
32683 numberOfContours = raw.readShort();
32684 xMin = raw.readShort();
32685 yMin = raw.readShort();
32686 xMax = raw.readShort();
32687 yMax = raw.readShort();
32688 if (numberOfContours === -1) {
32689 this.cache[id] = new CompoundGlyph(raw, xMin, yMin, xMax, yMax);
32690 } else {
32691 this.cache[id] = new SimpleGlyph(
32692 raw,
32693 numberOfContours,
32694 xMin,
32695 yMin,
32696 xMax,
32697 yMax
32698 );
32699 }
32700 return this.cache[id];
32701 };
32702 GlyfTable.prototype.encode = function(glyphs, mapping, old2new) {
32703 var glyph, id, offsets, table, _i, _len;
32704 table = [];
32705 offsets = [];
32706 for (_i = 0, _len = mapping.length; _i < _len; _i++) {
32707 id = mapping[_i];
32708 glyph = glyphs[id];
32709 offsets.push(table.length);
32710 if (glyph) {
32711 table = table.concat(glyph.encode(old2new));
32712 }
32713 }
32714 offsets.push(table.length);
32715 return {
32716 table: table,
32717 offsets: offsets
32718 };
32719 };
32720 return GlyfTable;
32721 })(Table);
32722
32723 var SimpleGlyph = (function() {
32724 /**************************************************************************/
32725 /* function : SimpleGlyph */
32726 /* comment : Stores raw, xMin, yMin, xMax, and yMax values for this glyph.*/
32727 /**************************************************************************/
32728 function SimpleGlyph(raw, numberOfContours, xMin, yMin, xMax, yMax) {
32729 this.raw = raw;
32730 this.numberOfContours = numberOfContours;
32731 this.xMin = xMin;
32732 this.yMin = yMin;
32733 this.xMax = xMax;
32734 this.yMax = yMax;
32735 this.compound = false;
32736 }
32737 SimpleGlyph.prototype.encode = function() {
32738 return this.raw.data;
32739 };
32740 return SimpleGlyph;
32741 })();
32742
32743 var CompoundGlyph = (function() {
32744 var ARG_1_AND_2_ARE_WORDS,
32745 MORE_COMPONENTS,
32746 WE_HAVE_AN_X_AND_Y_SCALE,
32747 WE_HAVE_A_SCALE,
32748 WE_HAVE_A_TWO_BY_TWO;
32749 ARG_1_AND_2_ARE_WORDS = 0x0001;
32750 WE_HAVE_A_SCALE = 0x0008;
32751 MORE_COMPONENTS = 0x0020;
32752 WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
32753 WE_HAVE_A_TWO_BY_TWO = 0x0080;
32754
32755 /********************************************************************************************************************/
32756 /* function : CompoundGlypg generator */
32757 /* comment : It stores raw, xMin, yMin, xMax, yMax, glyph id, and glyph offset for the corresponding compound glyph.*/
32758 /********************************************************************************************************************/
32759 function CompoundGlyph(raw, xMin, yMin, xMax, yMax) {
32760 var data, flags;
32761 this.raw = raw;
32762 this.xMin = xMin;
32763 this.yMin = yMin;
32764 this.xMax = xMax;
32765 this.yMax = yMax;
32766 this.compound = true;
32767 this.glyphIDs = [];
32768 this.glyphOffsets = [];
32769 data = this.raw;
32770 while (true) {
32771 flags = data.readShort();
32772 this.glyphOffsets.push(data.pos);
32773 this.glyphIDs.push(data.readUInt16());
32774 if (!(flags & MORE_COMPONENTS)) {
32775 break;
32776 }
32777 if (flags & ARG_1_AND_2_ARE_WORDS) {
32778 data.pos += 4;
32779 } else {
32780 data.pos += 2;
32781 }
32782 if (flags & WE_HAVE_A_TWO_BY_TWO) {
32783 data.pos += 8;
32784 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
32785 data.pos += 4;
32786 } else if (flags & WE_HAVE_A_SCALE) {
32787 data.pos += 2;
32788 }
32789 }
32790 }
32791 /****************************************************************************************************************/
32792 /* function : CompoundGlypg encode */
32793 /* comment : After creating a table for the characters you typed, you call directory.encode to encode the table.*/
32794 /****************************************************************************************************************/
32795 CompoundGlyph.prototype.encode = function() {
32796 var i, result, _len, _ref;
32797 result = new Data(__slice.call(this.raw.data));
32798 _ref = this.glyphIDs;
32799 for (i = 0, _len = _ref.length; i < _len; ++i) {
32800 result.pos = this.glyphOffsets[i];
32801 }
32802 return result.data;
32803 };
32804 return CompoundGlyph;
32805 })();
32806
32807 var LocaTable = (function(_super) {
32808 __extends(LocaTable, _super);
32809
32810 function LocaTable() {
32811 return LocaTable.__super__.constructor.apply(this, arguments);
32812 }
32813 LocaTable.prototype.tag = "loca";
32814 LocaTable.prototype.parse = function(data) {
32815 var format, i;
32816 data.pos = this.offset;
32817 format = this.file.head.indexToLocFormat;
32818 if (format === 0) {
32819 return (this.offsets = function() {
32820 var _ref, _results;
32821 _results = [];
32822 for (i = 0, _ref = this.length; i < _ref; i += 2) {
32823 _results.push(data.readUInt16() * 2);
32824 }
32825 return _results;
32826 }.call(this));
32827 } else {
32828 return (this.offsets = function() {
32829 var _ref, _results;
32830 _results = [];
32831 for (i = 0, _ref = this.length; i < _ref; i += 4) {
32832 _results.push(data.readUInt32());
32833 }
32834 return _results;
32835 }.call(this));
32836 }
32837 };
32838 LocaTable.prototype.indexOf = function(id) {
32839 return this.offsets[id];
32840 };
32841 LocaTable.prototype.lengthOf = function(id) {
32842 return this.offsets[id + 1] - this.offsets[id];
32843 };
32844 LocaTable.prototype.encode = function(offsets, activeGlyphs) {
32845 var LocaTable = new Uint32Array(this.offsets.length);
32846 var glyfPtr = 0;
32847 var listGlyf = 0;
32848 for (var k = 0; k < LocaTable.length; ++k) {
32849 LocaTable[k] = glyfPtr;
32850 if (listGlyf < activeGlyphs.length && activeGlyphs[listGlyf] == k) {
32851 ++listGlyf;
32852 LocaTable[k] = glyfPtr;
32853 var start = this.offsets[k];
32854 var len = this.offsets[k + 1] - start;
32855 if (len > 0) {
32856 glyfPtr += len;
32857 }
32858 }
32859 }
32860 var newLocaTable = new Array(LocaTable.length * 4);
32861 for (var j = 0; j < LocaTable.length; ++j) {
32862 newLocaTable[4 * j + 3] = LocaTable[j] & 0x000000ff;
32863 newLocaTable[4 * j + 2] = (LocaTable[j] & 0x0000ff00) >> 8;
32864 newLocaTable[4 * j + 1] = (LocaTable[j] & 0x00ff0000) >> 16;
32865 newLocaTable[4 * j] = (LocaTable[j] & 0xff000000) >> 24;
32866 }
32867 return newLocaTable;
32868 };
32869 return LocaTable;
32870 })(Table);
32871
32872 /************************************************************************************/
32873 /* function : invert */
32874 /* comment : Change the object's (key: value) to create an object with (value: key).*/
32875 /************************************************************************************/
32876 var invert = function(object) {
32877 var key, ret, val;
32878 ret = {};
32879 for (key in object) {
32880 val = object[key];
32881 ret[val] = key;
32882 }
32883 return ret;
32884 };
32885
32886 /*var successorOf = function (input) {
32887 var added, alphabet, carry, i, index, isUpperCase, last, length, next, result;
32888 alphabet = 'abcdefghijklmnopqrstuvwxyz';
32889 length = alphabet.length;
32890 result = input;
32891 i = input.length;
32892 while (i >= 0) {
32893 last = input.charAt(--i);
32894 if (isNaN(last)) {
32895 index = alphabet.indexOf(last.toLowerCase());
32896 if (index === -1) {
32897 next = last;
32898 carry = true;
32899 }
32900 else {
32901 next = alphabet.charAt((index + 1) % length);
32902 isUpperCase = last === last.toUpperCase();
32903 if (isUpperCase) {
32904 next = next.toUpperCase();
32905 }
32906 carry = index + 1 >= length;
32907 if (carry && i === 0) {
32908 added = isUpperCase ? 'A' : 'a';
32909 result = added + next + result.slice(1);
32910 break;
32911 }
32912 }
32913 }
32914 else {
32915 next = +last + 1;
32916 carry = next > 9;
32917 if (carry) {
32918 next = 0;
32919 }
32920 if (carry && i === 0) {
32921 result = '1' + next + result.slice(1);
32922 break;
32923 }
32924 }
32925 result = result.slice(0, i) + next + result.slice(i + 1);
32926 if (!carry) {
32927 break;
32928 }
32929 }
32930 return result;
32931 };*/
32932
32933 var Subset = (function() {
32934 function Subset(font) {
32935 this.font = font;
32936 this.subset = {};
32937 this.unicodes = {};
32938 this.next = 33;
32939 }
32940 /*Subset.prototype.use = function (character) {
32941 var i, _i, _ref;
32942 if (typeof character === 'string') {
32943 for (i = _i = 0, _ref = character.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
32944 this.use(character.charCodeAt(i));
32945 }
32946 return;
32947 }
32948 if (!this.unicodes[character]) {
32949 this.subset[this.next] = character;
32950 return this.unicodes[character] = this.next++;
32951 }
32952 };*/
32953 /*Subset.prototype.encodeText = function (text) {
32954 var char, i, string, _i, _ref;
32955 string = '';
32956 for (i = _i = 0, _ref = text.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
32957 char = this.unicodes[text.charCodeAt(i)];
32958 string += String.fromCharCode(char);
32959 }
32960 return string;
32961 };*/
32962 /***************************************************************/
32963 /* function : generateCmap */
32964 /* comment : Returns the unicode cmap for this font. */
32965 /***************************************************************/
32966 Subset.prototype.generateCmap = function() {
32967 var mapping, roman, unicode, unicodeCmap, _ref;
32968 unicodeCmap = this.font.cmap.tables[0].codeMap;
32969 mapping = {};
32970 _ref = this.subset;
32971 for (roman in _ref) {
32972 unicode = _ref[roman];
32973 mapping[roman] = unicodeCmap[unicode];
32974 }
32975 return mapping;
32976 };
32977 /*Subset.prototype.glyphIDs = function () {
32978 var ret, roman, unicode, unicodeCmap, val, _ref;
32979 unicodeCmap = this.font.cmap.tables[0].codeMap;
32980 ret = [0];
32981 _ref = this.subset;
32982 for (roman in _ref) {
32983 unicode = _ref[roman];
32984 val = unicodeCmap[unicode];
32985 if ((val != null) && __indexOf.call(ret, val) < 0) {
32986 ret.push(val);
32987 }
32988 }
32989 return ret.sort();
32990 };*/
32991 /******************************************************************/
32992 /* function : glyphsFor */
32993 /* comment : Returns simple glyph objects for the input character.*/
32994 /******************************************************************/
32995 Subset.prototype.glyphsFor = function(glyphIDs) {
32996 var additionalIDs, glyph, glyphs, id, _i, _len, _ref;
32997 glyphs = {};
32998 for (_i = 0, _len = glyphIDs.length; _i < _len; _i++) {
32999 id = glyphIDs[_i];
33000 glyphs[id] = this.font.glyf.glyphFor(id);
33001 }
33002 additionalIDs = [];
33003 for (id in glyphs) {
33004 glyph = glyphs[id];
33005 if (glyph != null ? glyph.compound : void 0) {
33006 additionalIDs.push.apply(additionalIDs, glyph.glyphIDs);
33007 }
33008 }
33009 if (additionalIDs.length > 0) {
33010 _ref = this.glyphsFor(additionalIDs);
33011 for (id in _ref) {
33012 glyph = _ref[id];
33013 glyphs[id] = glyph;
33014 }
33015 }
33016 return glyphs;
33017 };
33018 /***************************************************************/
33019 /* function : encode */
33020 /* comment : Encode various tables for the characters you use. */
33021 /***************************************************************/
33022 Subset.prototype.encode = function(glyID, indexToLocFormat) {
33023 var cmap,
33024 code,
33025 glyf,
33026 glyphs,
33027 id,
33028 ids,
33029 loca,
33030 new2old,
33031 newIDs,
33032 nextGlyphID,
33033 old2new,
33034 oldID,
33035 oldIDs,
33036 tables,
33037 _ref;
33038 cmap = CmapTable.encode(this.generateCmap(), "unicode");
33039 glyphs = this.glyphsFor(glyID);
33040 old2new = {
33041 0: 0
33042 };
33043 _ref = cmap.charMap;
33044 for (code in _ref) {
33045 ids = _ref[code];
33046 old2new[ids.old] = ids["new"];
33047 }
33048 nextGlyphID = cmap.maxGlyphID;
33049 for (oldID in glyphs) {
33050 if (!(oldID in old2new)) {
33051 old2new[oldID] = nextGlyphID++;
33052 }
33053 }
33054 new2old = invert(old2new);
33055 newIDs = Object.keys(new2old).sort(function(a, b) {
33056 return a - b;
33057 });
33058 oldIDs = (function() {
33059 var _i, _len, _results;
33060 _results = [];
33061 for (_i = 0, _len = newIDs.length; _i < _len; _i++) {
33062 id = newIDs[_i];
33063 _results.push(new2old[id]);
33064 }
33065 return _results;
33066 })();
33067 glyf = this.font.glyf.encode(glyphs, oldIDs, old2new);
33068 loca = this.font.loca.encode(glyf.offsets, oldIDs);
33069 tables = {
33070 cmap: this.font.cmap.raw(),
33071 glyf: glyf.table,
33072 loca: loca,
33073 hmtx: this.font.hmtx.raw(),
33074 hhea: this.font.hhea.raw(),
33075 maxp: this.font.maxp.raw(),
33076 post: this.font.post.raw(),
33077 name: this.font.name.raw(),
33078 head: this.font.head.encode(indexToLocFormat)
33079 };
33080 if (this.font.os2.exists) {
33081 tables["OS/2"] = this.font.os2.raw();
33082 }
33083 return this.font.directory.encode(tables);
33084 };
33085 return Subset;
33086 })();
33087
33088 jsPDF.API.PDFObject = (function() {
33089 var pad;
33090
33091 function PDFObject() {}
33092 pad = function(str, length) {
33093 return (Array(length + 1).join("0") + str).slice(-length);
33094 };
33095 /*****************************************************************************/
33096 /* function : convert */
33097 /* comment :Converts pdf tag's / FontBBox and array values in / W to strings */
33098 /*****************************************************************************/
33099 PDFObject.convert = function(object) {
33100 var e, items, key, out, val;
33101 if (Array.isArray(object)) {
33102 items = (function() {
33103 var _i, _len, _results;
33104 _results = [];
33105 for (_i = 0, _len = object.length; _i < _len; _i++) {
33106 e = object[_i];
33107 _results.push(PDFObject.convert(e));
33108 }
33109 return _results;
33110 })().join(" ");
33111 return "[" + items + "]";
33112 } else if (typeof object === "string") {
33113 return "/" + object;
33114 } else if (object != null ? object.isString : void 0) {
33115 return "(" + object + ")";
33116 } else if (object instanceof Date) {
33117 return (
33118 "(D:" +
33119 pad(object.getUTCFullYear(), 4) +
33120 pad(object.getUTCMonth(), 2) +
33121 pad(object.getUTCDate(), 2) +
33122 pad(object.getUTCHours(), 2) +
33123 pad(object.getUTCMinutes(), 2) +
33124 pad(object.getUTCSeconds(), 2) +
33125 "Z)"
33126 );
33127 } else if ({}.toString.call(object) === "[object Object]") {
33128 out = ["<<"];
33129 for (key in object) {
33130 val = object[key];
33131 out.push("/" + key + " " + PDFObject.convert(val));
33132 }
33133 out.push(">>");
33134 return out.join("\n");
33135 } else {
33136 return "" + object;
33137 }
33138 };
33139 return PDFObject;
33140 })();
33141
33142 exports.AcroForm = AcroForm;
33143 exports.AcroFormAppearance = AcroFormAppearance;
33144 exports.AcroFormButton = AcroFormButton;
33145 exports.AcroFormCheckBox = AcroFormCheckBox;
33146 exports.AcroFormChoiceField = AcroFormChoiceField;
33147 exports.AcroFormComboBox = AcroFormComboBox;
33148 exports.AcroFormEditBox = AcroFormEditBox;
33149 exports.AcroFormListBox = AcroFormListBox;
33150 exports.AcroFormPasswordField = AcroFormPasswordField;
33151 exports.AcroFormPushButton = AcroFormPushButton;
33152 exports.AcroFormRadioButton = AcroFormRadioButton;
33153 exports.AcroFormTextField = AcroFormTextField;
33154 exports.GState = GState;
33155 exports.ShadingPattern = ShadingPattern;
33156 exports.TilingPattern = TilingPattern;
33157 exports.default = jsPDF;
33158 exports.jsPDF = jsPDF;
33159
33160 Object.defineProperty(exports, '__esModule', { value: true });
33161
33162})));
33163//# sourceMappingURL=jspdf.umd.js.map