PageSourceSearch

https://ficemea.org/wp-content/plugins/pdf-print/js/jspdf.js?ver=5.4.23

js ficemea.org collected 2026-10-02 11:14:53 UTC 880,373 bytes, 25,664 lines download raw bytes

1(function (factory) {
2  typeof define === 'function' && define.amd ? define(factory) :
3  factory();
4}(function () { 'use strict';
5
6  /** @license
7   * jsPDF - PDF Document creation from JavaScript
8   * Version 1.5.3 Built on 2018-12-27T14:11:42.696Z
9   *                      CommitID d93d28db14
10   *
11   * Copyright (c) 2010-2016 James Hall <[email protected]>, https://github.com/MrRio/jsPDF
12   *               2010 Aaron Spike, https://github.com/acspike
13   *               2012 Willow Systems Corporation, willow-systems.com
14   *               2012 Pablo Hess, https://github.com/pablohess
15   *               2012 Florian Jenett, https://github.com/fjenett
16   *               2013 Warren Weckesser, https://github.com/warrenweckesser
17   *               2013 Youssef Beddad, https://github.com/lifof
18   *               2013 Lee Driscoll, https://github.com/lsdriscoll
19   *               2013 Stefan Slonevskiy, https://github.com/stefslon
20   *               2013 Jeremy Morel, https://github.com/jmorel
21   *               2013 Christoph Hartmann, https://github.com/chris-rock
22   *               2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
23   *               2014 James Makes, https://github.com/dollaruw
24   *               2014 Diego Casorran, https://github.com/diegocr
25   *               2014 Steven Spungin, https://github.com/Flamenco
26   *               2014 Kenneth Glassey, https://github.com/Gavvers
27   *
28   * Licensed under the MIT License
29   *
30   * Contributor(s):
31   *    siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango,
32   *    kim3er, mfo, alnorth, Flamenco
33   */
34
35  function _typeof(obj) {
36    if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
37      _typeof = function (obj) {
38        return typeof obj;
39      };
40    } else {
41      _typeof = function (obj) {
42        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
43      };
44    }
45
46    return _typeof(obj);
47  }
48
49  /**
50   * JavaScript Polyfill functions for jsPDF
51   * Collected from public resources by
52   * https://github.com/diegocr
53   */
54  (function (global) {
55    if (_typeof(global.console) !== "object") {
56      // Console-polyfill. MIT license.
57      // https://github.com/paulmillr/console-polyfill
58      // Make it safe to do console.log() always.
59      global.console = {};
60      var con = global.console;
61      var prop, method;
62
63      var dummy = function dummy() {};
64
65      var properties = ['memory'];
66      var methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' + 'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' + 'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(',');
67
68      while (prop = properties.pop()) {
69        if (!con[prop]) con[prop] = {};
70      }
71
72      while (method = methods.pop()) {
73        if (!con[method]) con[method] = dummy;
74      }
75    }
76
77    var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
78
79    if (typeof global.btoa === 'undefined') {
80      global.btoa = function (data) {
81        //  discuss at: http://phpjs.org/functions/base64_encode/
82        // original by: Tyler Akins (http://rumkin.com)
83        // improved by: Bayron Guevara
84        // improved by: Thunder.m
85        // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
86        // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
87        // improved by: Rafal Kukawski (http://kukawski.pl)
88        // bugfixed by: Pellentesque Malesuada
89        //   example 1: base64_encode('Kevin van Zonneveld');
90        //   returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
91        var o1,
92            o2,
93            o3,
94            h1,
95            h2,
96            h3,
97            h4,
98            bits,
99            i = 0,
100            ac = 0,
101            enc = '',
102            tmp_arr = [];
103
104        if (!data) {
105          return data;
106        }
107
108        do {
109          // pack three octets into four hexets
110          o1 = data.charCodeAt(i++);
111          o2 = data.charCodeAt(i++);
112          o3 = data.charCodeAt(i++);
113          bits = o1 << 16 | o2 << 8 | o3;
114          h1 = bits >> 18 & 0x3f;
115          h2 = bits >> 12 & 0x3f;
116          h3 = bits >> 6 & 0x3f;
117          h4 = bits & 0x3f; // use hexets to index into b64, and append result to encoded string
118
119          tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
120        } while (i < data.length);
121
122        enc = tmp_arr.join('');
123        var r = data.length % 3;
124        return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
125      };
126    }
127
128    if (typeof global.atob === 'undefined') {
129      global.atob = function (data) {
130        //  discuss at: http://phpjs.org/functions/base64_decode/
131        // original by: Tyler Akins (http://rumkin.com)
132        // improved by: Thunder.m
133        // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
134        // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
135        //    input by: Aman Gupta
136        //    input by: Brett Zamir (http://brett-zamir.me)
137        // bugfixed by: Onno Marsman
138        // bugfixed by: Pellentesque Malesuada
139        // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
140        //   example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
141        //   returns 1: 'Kevin van Zonneveld'
142        var o1,
143            o2,
144            o3,
145            h1,
146            h2,
147            h3,
148            h4,
149            bits,
150            i = 0,
151            ac = 0,
152            dec = '',
153            tmp_arr = [];
154
155        if (!data) {
156          return data;
157        }
158
159        data += '';
160
161        do {
162          // unpack four hexets into three octets using index points in b64
163          h1 = b64.indexOf(data.charAt(i++));
164          h2 = b64.indexOf(data.charAt(i++));
165          h3 = b64.indexOf(data.charAt(i++));
166          h4 = b64.indexOf(data.charAt(i++));
167          bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
168          o1 = bits >> 16 & 0xff;
169          o2 = bits >> 8 & 0xff;
170          o3 = bits & 0xff;
171
172          if (h3 == 64) {
173            tmp_arr[ac++] = String.fromCharCode(o1);
174          } else if (h4 == 64) {
175            tmp_arr[ac++] = String.fromCharCode(o1, o2);
176          } else {
177            tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
178          }
179        } while (i < data.length);
180
181        dec = tmp_arr.join('');
182        return dec;
183      };
184    }
185
186    if (!Array.prototype.map) {
187      Array.prototype.map = function (fun
188      /*, thisArg */
189      ) {
190        if (this === void 0 || this === null || typeof fun !== "function") throw new TypeError();
191        var t = Object(this),
192            len = t.length >>> 0,
193            res = new Array(len);
194        var thisArg = arguments.length > 1 ? arguments[1] : void 0;
195
196        for (var i = 0; i < len; i++) {
197          // NOTE: Absolute correctness would demand Object.defineProperty
198          //       be used.  But this method is fairly new, and failure is
199          //       possible only if Object.prototype or Array.prototype
200          //       has a property |i| (very unlikely), so use a less-correct
201          //       but more portable alternative.
202          if (i in t) res[i] = fun.call(thisArg, t[i], i, t);
203        }
204
205        return res;
206      };
207    }
208
209    if (!Array.isArray) {
210      Array.isArray = function (arg) {
211        return Object.prototype.toString.call(arg) === '[object Array]';
212      };
213    }
214
215    if (!Array.prototype.forEach) {
216      Array.prototype.forEach = function (fun, thisArg) {
217
218        if (this === void 0 || this === null || typeof fun !== "function") throw new TypeError();
219        var t = Object(this),
220            len = t.length >>> 0;
221
222        for (var i = 0; i < len; i++) {
223          if (i in t) fun.call(thisArg, t[i], i, t);
224        }
225      };
226    } // https://tc39.github.io/ecma262/#sec-array.prototype.find
227
228
229    if (!Array.prototype.find) {
230      Object.defineProperty(Array.prototype, 'find', {
231        value: function value(predicate) {
232          // 1. Let O be ? ToObject(this value).
233          if (this == null) {
234            throw new TypeError('"this" is null or not defined');
235          }
236
237          var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")).
238
239          var len = o.length >>> 0; // 3. If IsCallable(predicate) is false, throw a TypeError exception.
240
241          if (typeof predicate !== 'function') {
242            throw new TypeError('predicate must be a function');
243          } // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
244
245
246          var thisArg = arguments[1]; // 5. Let k be 0.
247
248          var k = 0; // 6. Repeat, while k < len
249
250          while (k < len) {
251            // a. Let Pk be ! ToString(k).
252            // b. Let kValue be ? Get(O, Pk).
253            // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
254            // d. If testResult is true, return kValue.
255            var kValue = o[k];
256
257            if (predicate.call(thisArg, kValue, k, o)) {
258              return kValue;
259            } // e. Increase k by 1.
260
261
262            k++;
263          } // 7. Return undefined.
264
265
266          return undefined;
267        },
268        configurable: true,
269        writable: true
270      });
271    }
272
273    if (!Object.keys) {
274      Object.keys = function () {
275
276        var hasOwnProperty = Object.prototype.hasOwnProperty,
277            hasDontEnumBug = !{
278          toString: null
279        }.propertyIsEnumerable('toString'),
280            dontEnums = ['toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'],
281            dontEnumsLength = dontEnums.length;
282        return function (obj) {
283          if (_typeof(obj) !== 'object' && (typeof obj !== 'function' || obj === null)) {
284            throw new TypeError();
285          }
286
287          var result = [],
288              prop,
289              i;
290
291          for (prop in obj) {
292            if (hasOwnProperty.call(obj, prop)) {
293              result.push(prop);
294            }
295          }
296
297          if (hasDontEnumBug) {
298            for (i = 0; i < dontEnumsLength; i++) {
299              if (hasOwnProperty.call(obj, dontEnums[i])) {
300                result.push(dontEnums[i]);
301              }
302            }
303          }
304
305          return result;
306        };
307      }();
308    }
309
310    if (typeof Object.assign != 'function') {
311      Object.assign = function (target) {
312
313        if (target == null) {
314          throw new TypeError('Cannot convert undefined or null to object');
315        }
316
317        target = Object(target);
318
319        for (var index = 1; index < arguments.length; index++) {
320          var source = arguments[index];
321
322          if (source != null) {
323            for (var key in source) {
324              if (Object.prototype.hasOwnProperty.call(source, key)) {
325                target[key] = source[key];
326              }
327            }
328          }
329        }
330
331        return target;
332      };
333    }
334
335    if (!String.prototype.trim) {
336      String.prototype.trim = function () {
337        return this.replace(/^\s+|\s+$/g, '');
338      };
339    }
340
341    if (!String.prototype.trimLeft) {
342      String.prototype.trimLeft = function () {
343        return this.replace(/^\s+/g, "");
344      };
345    }
346
347    if (!String.prototype.trimRight) {
348      String.prototype.trimRight = function () {
349        return this.replace(/\s+$/g, "");
350      };
351    }
352
353    Number.isInteger = Number.isInteger || function (value) {
354      return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
355    };
356  })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function('return this')()); // `self` is undefined in Firefox for Android content script context
357  // while `this` is nsIContentFrameMessageManager
358  // with an attribute `content` that corresponds to the window
359
360  /**
361   * Creates new jsPDF document object instance.
362   * @name jsPDF
363   * @class
364   * @param orientation {string/Object} Orientation of the first page. Possible values are "portrait" or "landscape" (or shortcuts "p" (Default), "l").<br />
365   * Can also be an options object.
366   * @param unit {string}  Measurement unit to be used when coordinates are specified.<br />
367   * Possible values are "pt" (points), "mm" (Default), "cm", "in" or "px".
368   * @param format {string/Array} 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 />
369   * 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]
370   * @returns {jsPDF} jsPDF-instance
371   * @description
372   * If the first parameter (orientation) is an object, it will be interpreted as an object of named parameters
373   * ```
374   * {
375   *  orientation: 'p',
376   *  unit: 'mm',
377   *  format: 'a4',
378   *  hotfixes: [] // an array of hotfix strings to enable
379   * }
380   * ```
381   */
382  var jsPDF = function (global) {
383    /**
384     * jsPDF's Internal PubSub Implementation.
385     * Backward compatible rewritten on 2014 by
386     * Diego Casorran, https://github.com/diegocr
387     *
388     * @class
389     * @name PubSub
390     * @ignore
391     */
392
393    function PubSub(context) {
394      if (_typeof(context) !== 'object') {
395        throw new Error('Invalid Context passed to initialize PubSub (jsPDF-module)');
396      }
397
398      var topics = {};
399
400      this.subscribe = function (topic, callback, once) {
401        once = once || false;
402
403        if (typeof topic !== 'string' || typeof callback !== 'function' || typeof once !== 'boolean') {
404          throw new Error('Invalid arguments passed to PubSub.subscribe (jsPDF-module)');
405        }
406
407        if (!topics.hasOwnProperty(topic)) {
408          topics[topic] = {};
409        }
410
411        var token = Math.random().toString(35);
412        topics[topic][token] = [callback, !!once];
413        return token;
414      };
415
416      this.unsubscribe = function (token) {
417        for (var topic in topics) {
418          if (topics[topic][token]) {
419            delete topics[topic][token];
420
421            if (Object.keys(topics[topic]).length === 0) {
422              delete topics[topic];
423            }
424
425            return true;
426          }
427        }
428
429        return false;
430      };
431
432      this.publish = function (topic) {
433        if (topics.hasOwnProperty(topic)) {
434          var args = Array.prototype.slice.call(arguments, 1),
435              tokens = [];
436
437          for (var token in topics[topic]) {
438            var sub = topics[topic][token];
439
440            try {
441              sub[0].apply(context, args);
442            } catch (ex) {
443              if (global.console) {
444                console.error('jsPDF PubSub Error', ex.message, ex);
445              }
446            }
447
448            if (sub[1]) tokens.push(token);
449          }
450
451          if (tokens.length) tokens.forEach(this.unsubscribe);
452        }
453      };
454
455      this.getTopics = function () {
456        return topics;
457      };
458    }
459    /**
460     * @constructor
461     * @private
462     */
463
464
465    function jsPDF(orientation, unit, format, compressPdf) {
466      var options = {};
467      var filters = [];
468      var userUnit = 1.0;
469
470      if (_typeof(orientation) === 'object') {
471        options = orientation;
472        orientation = options.orientation;
473        unit = options.unit || unit;
474        format = options.format || format;
475        compressPdf = options.compress || options.compressPdf || compressPdf;
476        filters = options.filters || (compressPdf === true ? ['FlateEncode'] : filters);
477        userUnit = typeof options.userUnit === "number" ? Math.abs(options.userUnit) : 1.0;
478      }
479
480      unit = unit || 'mm';
481      orientation = ('' + (orientation || 'P')).toLowerCase();
482      var putOnlyUsedFonts = options.putOnlyUsedFonts || true;
483      var usedFonts = {};
484      var API = {
485        internal: {},
486        __private__: {}
487      };
488      API.__private__.PubSub = PubSub;
489      var pdfVersion = '1.3';
490
491      var getPdfVersion = API.__private__.getPdfVersion = function () {
492        return pdfVersion;
493      };
494
495      var setPdfVersion = API.__private__.setPdfVersion = function (value) {
496        pdfVersion = value;
497      }; // Size in pt of various paper formats
498
499
500      var pageFormats = {
501        'a0': [2383.94, 3370.39],
502        'a1': [1683.78, 2383.94],
503        'a2': [1190.55, 1683.78],
504        'a3': [841.89, 1190.55],
505        'a4': [595.28, 841.89],
506        'a5': [419.53, 595.28],
507        'a6': [297.64, 419.53],
508        'a7': [209.76, 297.64],
509        'a8': [147.40, 209.76],
510        'a9': [104.88, 147.40],
511        'a10': [73.70, 104.88],
512        'b0': [2834.65, 4008.19],
513        'b1': [2004.09, 2834.65],
514        'b2': [1417.32, 2004.09],
515        'b3': [1000.63, 1417.32],
516        'b4': [708.66, 1000.63],
517        'b5': [498.90, 708.66],
518        'b6': [354.33, 498.90],
519        'b7': [249.45, 354.33],
520        'b8': [175.75, 249.45],
521        'b9': [124.72, 175.75],
522        'b10': [87.87, 124.72],
523        'c0': [2599.37, 3676.54],
524        'c1': [1836.85, 2599.37],
525        'c2': [1298.27, 1836.85],
526        'c3': [918.43, 1298.27],
527        'c4': [649.13, 918.43],
528        'c5': [459.21, 649.13],
529        'c6': [323.15, 459.21],
530        'c7': [229.61, 323.15],
531        'c8': [161.57, 229.61],
532        'c9': [113.39, 161.57],
533        'c10': [79.37, 113.39],
534        'dl': [311.81, 623.62],
535        'letter': [612, 792],
536        'government-letter': [576, 756],
537        'legal': [612, 1008],
538        'junior-legal': [576, 360],
539        'ledger': [1224, 792],
540        'tabloid': [792, 1224],
541        'credit-card': [153, 243]
542      };
543
544      var getPageFormats = API.__private__.getPageFormats = function () {
545        return pageFormats;
546      };
547
548      var getPageFormat = API.__private__.getPageFormat = function (value) {
549        return pageFormats[value];
550      };
551
552      if (typeof format === "string") {
553        format = getPageFormat(format);
554      }
555
556      format = format || getPageFormat('a4');
557
558      var f2 = API.f2 = API.__private__.f2 = function (number) {
559        if (isNaN(number)) {
560          throw new Error('Invalid argument passed to jsPDF.f2');
561        }
562
563        return number.toFixed(2); // Ie, %.2f
564      };
565
566      var f3 = API.__private__.f3 = function (number) {
567        if (isNaN(number)) {
568          throw new Error('Invalid argument passed to jsPDF.f3');
569        }
570
571        return number.toFixed(3); // Ie, %.3f
572      };
573
574      var fileId = '00000000000000000000000000000000';
575
576      var getFileId = API.__private__.getFileId = function () {
577        return fileId;
578      };
579
580      var setFileId = API.__private__.setFileId = function (value) {
581        value = value || "12345678901234567890123456789012".split('').map(function () {
582          return "ABCDEF0123456789".charAt(Math.floor(Math.random() * 16));
583        }).join('');
584        fileId = value;
585        return fileId;
586      };
587      /**
588       * @name setFileId
589       * @memberOf jsPDF
590       * @function
591       * @instance
592       * @param {string} value GUID.
593       * @returns {jsPDF}
594       */
595
596
597      API.setFileId = function (value) {
598        setFileId(value);
599        return this;
600      };
601      /**
602       * @name getFileId
603       * @memberOf jsPDF
604       * @function
605       * @instance
606       *
607       * @returns {string} GUID.
608       */
609
610
611      API.getFileId = function () {
612        return getFileId();
613      };
614
615      var creationDate;
616
617      var convertDateToPDFDate = API.__private__.convertDateToPDFDate = function (parmDate) {
618        var result = '';
619        var tzoffset = parmDate.getTimezoneOffset(),
620            tzsign = tzoffset < 0 ? '+' : '-',
621            tzhour = Math.floor(Math.abs(tzoffset / 60)),
622            tzmin = Math.abs(tzoffset % 60),
623            timeZoneString = [tzsign, padd2(tzhour), "'", padd2(tzmin), "'"].join('');
624        result = ['D:', parmDate.getFullYear(), padd2(parmDate.getMonth() + 1), padd2(parmDate.getDate()), padd2(parmDate.getHours()), padd2(parmDate.getMinutes()), padd2(parmDate.getSeconds()), timeZoneString].join('');
625        return result;
626      };
627
628      var convertPDFDateToDate = API.__private__.convertPDFDateToDate = function (parmPDFDate) {
629        var year = parseInt(parmPDFDate.substr(2, 4), 10);
630        var month = parseInt(parmPDFDate.substr(6, 2), 10) - 1;
631        var date = parseInt(parmPDFDate.substr(8, 2), 10);
632        var hour = parseInt(parmPDFDate.substr(10, 2), 10);
633        var minutes = parseInt(parmPDFDate.substr(12, 2), 10);
634        var seconds = parseInt(parmPDFDate.substr(14, 2), 10);
635        var timeZoneHour = parseInt(parmPDFDate.substr(16, 2), 10);
636        var timeZoneMinutes = parseInt(parmPDFDate.substr(20, 2), 10);
637        var resultingDate = new Date(year, month, date, hour, minutes, seconds, 0);
638        return resultingDate;
639      };
640
641      var setCreationDate = API.__private__.setCreationDate = function (date) {
642        var tmpCreationDateString;
643        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])\'?$/;
644
645        if (typeof date === "undefined") {
646          date = new Date();
647        }
648
649        if (_typeof(date) === "object" && Object.prototype.toString.call(date) === "[object Date]") {
650          tmpCreationDateString = convertDateToPDFDate(date);
651        } else if (regexPDFCreationDate.test(date)) {
652          tmpCreationDateString = date;
653        } else {
654          throw new Error('Invalid argument passed to jsPDF.setCreationDate');
655        }
656
657        creationDate = tmpCreationDateString;
658        return creationDate;
659      };
660
661      var getCreationDate = API.__private__.getCreationDate = function (type) {
662        var result = creationDate;
663
664        if (type === "jsDate") {
665          result = convertPDFDateToDate(creationDate);
666        }
667
668        return result;
669      };
670      /**
671       * @name setCreationDate
672       * @memberOf jsPDF
673       * @function
674       * @instance
675       * @param {Object} date
676       * @returns {jsPDF}
677       */
678
679
680      API.setCreationDate = function (date) {
681        setCreationDate(date);
682        return this;
683      };
684      /**
685       * @name getCreationDate
686       * @memberOf jsPDF
687       * @function
688       * @instance
689       * @param {Object} type
690       * @returns {Object}
691       */
692
693
694      API.getCreationDate = function (type) {
695        return getCreationDate(type);
696      };
697
698      var padd2 = API.__private__.padd2 = function (number) {
699        return ('0' + parseInt(number)).slice(-2);
700      };
701
702      var outToPages = !1; // switches where out() prints. outToPages true = push to pages obj. outToPages false = doc builder content
703
704      var pages = [];
705      var content = [];
706      var currentPage;
707      var content_length = 0;
708      var customOutputDestination;
709
710      var setOutputDestination = API.__private__.setCustomOutputDestination = function (destination) {
711        customOutputDestination = destination;
712      };
713
714      var resetOutputDestination = API.__private__.resetCustomOutputDestination = function (destination) {
715        customOutputDestination = undefined;
716      };
717
718      var out = API.__private__.out = function (string) {
719        var writeArray;
720        string = typeof string === "string" ? string : string.toString();
721
722        if (typeof customOutputDestination === "undefined") {
723          writeArray = outToPages ? pages[currentPage] : content;
724        } else {
725          writeArray = customOutputDestination;
726        }
727
728        writeArray.push(string);
729
730        if (!outToPages) {
731          content_length += string.length + 1;
732        }
733
734        return writeArray;
735      };
736
737      var write = API.__private__.write = function (value) {
738        return out(arguments.length === 1 ? value.toString() : Array.prototype.join.call(arguments, ' '));
739      };
740
741      var getArrayBuffer = API.__private__.getArrayBuffer = function (data) {
742        var len = data.length,
743            ab = new ArrayBuffer(len),
744            u8 = new Uint8Array(ab);
745
746        while (len--) {
747          u8[len] = data.charCodeAt(len);
748        }
749
750        return ab;
751      };
752
753      var standardFonts = [['Helvetica', "helvetica", "normal", 'WinAnsiEncoding'], ['Helvetica-Bold', "helvetica", "bold", 'WinAnsiEncoding'], ['Helvetica-Oblique', "helvetica", "italic", 'WinAnsiEncoding'], ['Helvetica-BoldOblique', "helvetica", "bolditalic", 'WinAnsiEncoding'], ['Courier', "courier", "normal", 'WinAnsiEncoding'], ['Courier-Bold', "courier", "bold", 'WinAnsiEncoding'], ['Courier-Oblique', "courier", "italic", 'WinAnsiEncoding'], ['Courier-BoldOblique', "courier", "bolditalic", 'WinAnsiEncoding'], ['Times-Roman', "times", "normal", 'WinAnsiEncoding'], ['Times-Bold', "times", "bold", 'WinAnsiEncoding'], ['Times-Italic', "times", "italic", 'WinAnsiEncoding'], ['Times-BoldItalic', "times", "bolditalic", 'WinAnsiEncoding'], ['ZapfDingbats', "zapfdingbats", "normal", null], ['Symbol', "symbol", "normal", null]];
754
755      var getStandardFonts = API.__private__.getStandardFonts = function (data) {
756        return standardFonts;
757      };
758
759      var activeFontSize = options.fontSize || 16;
760      /**
761       * Sets font size for upcoming text elements.
762       *
763       * @param {number} size Font size in points.
764       * @function
765       * @instance
766       * @returns {jsPDF}
767       * @memberOf jsPDF
768       * @name setFontSize
769       */
770
771      var setFontSize = API.__private__.setFontSize = API.setFontSize = function (size) {
772        activeFontSize = size;
773        return this;
774      };
775      /**
776       * Gets the fontsize for upcoming text elements.
777       *
778       * @function
779       * @instance
780       * @returns {number}
781       * @memberOf jsPDF
782       * @name getFontSize
783       */
784
785
786      var getFontSize = API.__private__.getFontSize = API.getFontSize = function () {
787        return activeFontSize;
788      };
789
790      var R2L = options.R2L || false;
791      /**
792       * Set value of R2L functionality.
793       *
794       * @param {boolean} value
795       * @function
796       * @instance
797       * @returns {jsPDF} jsPDF-instance
798       * @memberOf jsPDF
799       * @name setR2L
800       */
801
802      var setR2L = API.__private__.setR2L = API.setR2L = function (value) {
803        R2L = value;
804        return this;
805      };
806      /**
807       * Get value of R2L functionality.
808       *
809       * @function
810       * @instance
811       * @returns {boolean} jsPDF-instance
812       * @memberOf jsPDF
813       * @name getR2L
814       */
815
816
817      var getR2L = API.__private__.getR2L = API.getR2L = function (value) {
818        return R2L;
819      };
820
821      var zoomMode; // default: 1;
822
823      var setZoomMode = API.__private__.setZoomMode = function (zoom) {
vendor: 15,483 bytes, lines 824-1250
824        var validZoomModes = [undefined, null, 'fullwidth', 'fullheight', 'fullpage', 'original'];
825
826        if (/^\d*\.?\d*\%$/.test(zoom)) {
827          zoomMode = zoom;
828        } else if (!isNaN(zoom)) {
829          zoomMode = parseInt(zoom, 10);
830        } else if (validZoomModes.indexOf(zoom) !== -1) {
831          zoomMode = zoom;
832        } else {
833          throw new Error('zoom must be Integer (e.g. 2), a percentage Value (e.g. 300%) or fullwidth, fullheight, fullpage, original. "' + zoom + '" is not recognized.');
834        }
835      };
836
837      var getZoomMode = API.__private__.getZoomMode = function () {
838        return zoomMode;
839      };
840
841      var pageMode; // default: 'UseOutlines';
842
843      var setPageMode = API.__private__.setPageMode = function (pmode) {
844        var validPageModes = [undefined, null, 'UseNone', 'UseOutlines', 'UseThumbs', 'FullScreen'];
845
846        if (validPageModes.indexOf(pmode) == -1) {
847          throw new Error('Page mode must be one of UseNone, UseOutlines, UseThumbs, or FullScreen. "' + pmode + '" is not recognized.');
848        }
849
850        pageMode = pmode;
851      };
852
853      var getPageMode = API.__private__.getPageMode = function () {
854        return pageMode;
855      };
856
857      var layoutMode; // default: 'continuous';
858
859      var setLayoutMode = API.__private__.setLayoutMode = function (layout) {
860        var validLayoutModes = [undefined, null, 'continuous', 'single', 'twoleft', 'tworight', 'two'];
861
862        if (validLayoutModes.indexOf(layout) == -1) {
863          throw new Error('Layout mode must be one of continuous, single, twoleft, tworight. "' + layout + '" is not recognized.');
864        }
865
866        layoutMode = layout;
867      };
868
869      var getLayoutMode = API.__private__.getLayoutMode = function () {
870        return layoutMode;
871      };
872      /**
873       * Set the display mode options of the page like zoom and layout.
874       *
875       * @name setDisplayMode
876       * @memberOf jsPDF
877       * @function 
878       * @instance
879       * @param {integer|String} zoom   You can pass an integer or percentage as
880       * a string. 2 will scale the document up 2x, '200%' will scale up by the
881       * same amount. You can also set it to 'fullwidth', 'fullheight',
882       * 'fullpage', or 'original'.
883       *
884       * Only certain PDF readers support this, such as Adobe Acrobat.
885       *
886       * @param {string} layout Layout mode can be: 'continuous' - this is the
887       * default continuous scroll. 'single' - the single page mode only shows one
888       * page at a time. 'twoleft' - two column left mode, first page starts on
889       * the left, and 'tworight' - pages are laid out in two columns, with the
890       * first page on the right. This would be used for books.
891       * @param {string} pmode 'UseOutlines' - it shows the
892       * outline of the document on the left. 'UseThumbs' - shows thumbnails along
893       * the left. 'FullScreen' - prompts the user to enter fullscreen mode.
894       *
895       * @returns {jsPDF}
896       */
897
898
899      var setDisplayMode = API.__private__.setDisplayMode = API.setDisplayMode = function (zoom, layout, pmode) {
900        setZoomMode(zoom);
901        setLayoutMode(layout);
902        setPageMode(pmode);
903        return this;
904      };
905
906      var documentProperties = {
907        'title': '',
908        'subject': '',
909        'author': '',
910        'keywords': '',
911        'creator': ''
912      };
913
914      var getDocumentProperty = API.__private__.getDocumentProperty = function (key) {
915        if (Object.keys(documentProperties).indexOf(key) === -1) {
916          throw new Error('Invalid argument passed to jsPDF.getDocumentProperty');
917        }
918
919        return documentProperties[key];
920      };
921
922      var getDocumentProperties = API.__private__.getDocumentProperties = function (properties) {
923        return documentProperties;
924      };
925      /**
926       * Adds a properties to the PDF document.
927       *
928       * @param {Object} A property_name-to-property_value object structure.
929       * @function
930       * @instance
931       * @returns {jsPDF}
932       * @memberOf jsPDF
933       * @name setDocumentProperties
934       */
935
936
937      var setDocumentProperties = API.__private__.setDocumentProperties = API.setProperties = API.setDocumentProperties = function (properties) {
938        // copying only those properties we can render.
939        for (var property in documentProperties) {
940          if (documentProperties.hasOwnProperty(property) && properties[property]) {
941            documentProperties[property] = properties[property];
942          }
943        }
944
945        return this;
946      };
947
948      var setDocumentProperty = API.__private__.setDocumentProperty = function (key, value) {
949        if (Object.keys(documentProperties).indexOf(key) === -1) {
950          throw new Error('Invalid arguments passed to jsPDF.setDocumentProperty');
951        }
952
953        return documentProperties[key] = value;
954      };
955
956      var objectNumber = 0; // 'n' Current object number
957
958      var offsets = []; // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes.
959
960      var fonts = {}; // collection of font objects, where key is fontKey - a dynamically created label for a given font.
961
962      var fontmap = {}; // mapping structure fontName > fontStyle > font key - performance layer. See addFont()
963
964      var activeFontKey; // will be string representing the KEY of the font as combination of fontName + fontStyle
965
966      var k; // Scale factor
967
968      var page = 0;
969      var pagesContext = [];
970      var additionalObjects = [];
971      var events = new PubSub(API);
972      var hotfixes = options.hotfixes || [];
973
974      var newObject = API.__private__.newObject = function () {
975        var oid = newObjectDeferred();
976        newObjectDeferredBegin(oid, true);
977        return oid;
978      }; // Does not output the object.  The caller must call newObjectDeferredBegin(oid) before outputing any data
979
980
981      var newObjectDeferred = API.__private__.newObjectDeferred = function () {
982        objectNumber++;
983
984        offsets[objectNumber] = function () {
985          return content_length;
986        };
987
988        return objectNumber;
989      };
990
991      var newObjectDeferredBegin = function newObjectDeferredBegin(oid, doOutput) {
992        doOutput = typeof doOutput === 'boolean' ? doOutput : false;
993        offsets[oid] = content_length;
994
995        if (doOutput) {
996          out(oid + ' 0 obj');
997        }
998
999        return oid;
1000      }; // Does not output the object until after the pages have been output.
1001      // Returns an object containing the objectId and content.
1002      // All pages have been added so the object ID can be estimated to start right after.
1003      // This does not modify the current objectNumber;  It must be updated after the newObjects are output.
1004
1005
1006      var newAdditionalObject = API.__private__.newAdditionalObject = function () {
1007        var objId = newObjectDeferred();
1008        var obj = {
1009          objId: objId,
1010          content: ''
1011        };
1012        additionalObjects.push(obj);
1013        return obj;
1014      };
1015
1016      var rootDictionaryObjId = newObjectDeferred();
1017      var resourceDictionaryObjId = newObjectDeferred(); /////////////////////
1018      // Private functions
1019      /////////////////////
1020
1021      var decodeColorString = API.__private__.decodeColorString = function (color) {
1022        var colorEncoded = color.split(' ');
1023
1024        if (colorEncoded.length === 2 && (colorEncoded[1] === 'g' || colorEncoded[1] === 'G')) {
1025          // convert grayscale value to rgb so that it can be converted to hex for consistency
1026          var floatVal = parseFloat(colorEncoded[0]);
1027          colorEncoded = [floatVal, floatVal, floatVal, 'r'];
1028        }
1029
1030        var colorAsRGB = '#';
1031
1032        for (var i = 0; i < 3; i++) {
1033          colorAsRGB += ('0' + Math.floor(parseFloat(colorEncoded[i]) * 255).toString(16)).slice(-2);
1034        }
1035
1036        return colorAsRGB;
1037      };
1038
1039      var encodeColorString = API.__private__.encodeColorString = function (options) {
1040        var color;
1041
1042        if (typeof options === "string") {
1043          options = {
1044            ch1: options
1045          };
1046        }
1047
1048        var ch1 = options.ch1;
1049        var ch2 = options.ch2;
1050        var ch3 = options.ch3;
1051        var ch4 = options.ch4;
1052        var precision = options.precision;
1053        var letterArray = options.pdfColorType === "draw" ? ['G', 'RG', 'K'] : ['g', 'rg', 'k'];
1054
1055        if (typeof ch1 === "string" && ch1.charAt(0) !== '#') {
1056          var rgbColor = new RGBColor(ch1);
1057
1058          if (rgbColor.ok) {
1059            ch1 = rgbColor.toHex();
1060          } else if (!/^\d*\.?\d*$/.test(ch1)) {
1061            throw new Error('Invalid color "' + ch1 + '" passed to jsPDF.encodeColorString.');
1062          }
1063        } //convert short rgb to long form
1064
1065
1066        if (typeof ch1 === "string" && /^#[0-9A-Fa-f]{3}$/.test(ch1)) {
1067          ch1 = '#' + ch1[1] + ch1[1] + ch1[2] + ch1[2] + ch1[3] + ch1[3];
1068        }
1069
1070        if (typeof ch1 === "string" && /^#[0-9A-Fa-f]{6}$/.test(ch1)) {
1071          var hex = parseInt(ch1.substr(1), 16);
1072          ch1 = hex >> 16 & 255;
1073          ch2 = hex >> 8 & 255;
1074          ch3 = hex & 255;
1075        }
1076
1077        if (typeof ch2 === "undefined" || typeof ch4 === "undefined" && ch1 === ch2 && ch2 === ch3) {
1078          // Gray color space.
1079          if (typeof ch1 === "string") {
1080            color = ch1 + " " + letterArray[0];
1081          } else {
1082            switch (options.precision) {
1083              case 2:
1084                color = f2(ch1 / 255) + " " + letterArray[0];
1085                break;
1086
1087              case 3:
1088              default:
1089                color = f3(ch1 / 255) + " " + letterArray[0];
1090            }
1091          }
1092        } else if (typeof ch4 === "undefined" || _typeof(ch4) === "object") {
1093          // assume RGBA
1094          if (ch4 && !isNaN(ch4.a)) {
1095            //TODO Implement transparency.
1096            //WORKAROUND use white for now, if transparent, otherwise handle as rgb
1097            if (ch4.a === 0) {
1098              color = ['1.000', '1.000', '1.000', letterArray[1]].join(" ");
1099              return color;
1100            }
1101          } // assume RGB
1102
1103
1104          if (typeof ch1 === "string") {
1105            color = [ch1, ch2, ch3, letterArray[1]].join(" ");
1106          } else {
1107            switch (options.precision) {
1108              case 2:
1109                color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), letterArray[1]].join(" ");
1110                break;
1111
1112              default:
1113              case 3:
1114                color = [f3(ch1 / 255), f3(ch2 / 255), f3(ch3 / 255), letterArray[1]].join(" ");
1115            }
1116          }
1117        } else {
1118          // assume CMYK
1119          if (typeof ch1 === 'string') {
1120            color = [ch1, ch2, ch3, ch4, letterArray[2]].join(" ");
1121          } else {
1122            switch (options.precision) {
1123              case 2:
1124                color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), f2(ch4 / 255), letterArray[2]].join(" ");
1125                break;
1126
1127              case 3:
1128              default:
1129                color = [f3(ch1 / 255), f3(ch2 / 255), f3(ch3 / 255), f3(ch4 / 255), letterArray[2]].join(" ");
1130            }
1131          }
1132        }
1133
1134        return color;
1135      };
1136
1137      var getFilters = API.__private__.getFilters = function () {
1138        return filters;
1139      };
1140
1141      var putStream = API.__private__.putStream = function (options) {
1142        options = options || {};
1143        var data = options.data || '';
1144        var filters = options.filters || getFilters();
1145        var alreadyAppliedFilters = options.alreadyAppliedFilters || [];
1146        var addLength1 = options.addLength1 || false;
1147        var valueOfLength1 = data.length;
1148        var processedData = {};
1149
1150        if (filters === true) {
1151          filters = ['FlateEncode'];
1152        }
1153
1154        var keyValues = options.additionalKeyValues || [];
1155
1156        if (typeof jsPDF.API.processDataByFilters !== 'undefined') {
1157          processedData = jsPDF.API.processDataByFilters(data, filters);
1158        } else {
1159          processedData = {
1160            data: data,
1161            reverseChain: []
1162          };
1163        }
1164
1165        var filterAsString = processedData.reverseChain + (Array.isArray(alreadyAppliedFilters) ? alreadyAppliedFilters.join(' ') : alreadyAppliedFilters.toString());
1166
1167        if (processedData.data.length !== 0) {
1168          keyValues.push({
1169            key: 'Length',
1170            value: processedData.data.length
1171          });
1172
1173          if (addLength1 === true) {
1174            keyValues.push({
1175              key: 'Length1',
1176              value: valueOfLength1
1177            });
1178          }
1179        }
1180
1181        if (filterAsString.length != 0) {
1182          //if (filters.length === 0 && alreadyAppliedFilters.length === 1 && typeof alreadyAppliedFilters !== "undefined") {
1183          if (filterAsString.split('/').length - 1 === 1) {
1184            keyValues.push({
1185              key: 'Filter',
1186              value: filterAsString
1187            });
1188          } else {
1189            keyValues.push({
1190              key: 'Filter',
1191              value: '[' + filterAsString + ']'
1192            });
1193          }
1194        }
1195
1196        out('<<');
1197
1198        for (var i = 0; i < keyValues.length; i++) {
1199          out('/' + keyValues[i].key + ' ' + keyValues[i].value);
1200        }
1201
1202        out('>>');
1203
1204        if (processedData.data.length !== 0) {
1205          out('stream');
1206          out(processedData.data);
1207          out('endstream');
1208        }
1209      };
1210
1211      var putPage = API.__private__.putPage = function (page) {
1212        var mediaBox = page.mediaBox;
1213        var pageNumber = page.number;
1214        var data = page.data;
1215        var pageObjectNumber = page.objId;
1216        var pageContentsObjId = page.contentsObjId;
1217        newObjectDeferredBegin(pageObjectNumber, true);
1218        var wPt = pagesContext[currentPage].mediaBox.topRightX - pagesContext[currentPage].mediaBox.bottomLeftX;
1219        var hPt = pagesContext[currentPage].mediaBox.topRightY - pagesContext[currentPage].mediaBox.bottomLeftY;
1220        out('<</Type /Page');
1221        out('/Parent ' + page.rootDictionaryObjId + ' 0 R');
1222        out('/Resources ' + page.resourceDictionaryObjId + ' 0 R');
1223        out('/MediaBox [' + parseFloat(f2(page.mediaBox.bottomLeftX)) + ' ' + parseFloat(f2(page.mediaBox.bottomLeftY)) + ' ' + f2(page.mediaBox.topRightX) + ' ' + f2(page.mediaBox.topRightY) + ']');
1224
1225        if (page.cropBox !== null) {
1226          out('/CropBox [' + f2(page.cropBox.bottomLeftX) + ' ' + f2(page.cropBox.bottomLeftY) + ' ' + f2(page.cropBox.topRightX) + ' ' + f2(page.cropBox.topRightY) + ']');
1227        }
1228
1229        if (page.bleedBox !== null) {
1230          out('/BleedBox [' + f2(page.bleedBox.bottomLeftX) + ' ' + f2(page.bleedBox.bottomLeftY) + ' ' + f2(page.bleedBox.topRightX) + ' ' + f2(page.bleedBox.topRightY) + ']');
1231        }
1232
1233        if (page.trimBox !== null) {
1234          out('/TrimBox [' + f2(page.trimBox.bottomLeftX) + ' ' + f2(page.trimBox.bottomLeftY) + ' ' + f2(page.trimBox.topRightX) + ' ' + f2(page.trimBox.topRightY) + ']');
1235        }
1236
1237        if (page.artBox !== null) {
1238          out('/ArtBox [' + f2(page.artBox.bottomLeftX) + ' ' + f2(page.artBox.bottomLeftY) + ' ' + f2(page.artBox.topRightX) + ' ' + f2(page.artBox.topRightY) + ']');
1239        }
1240
1241        if (typeof page.userUnit === "number" && page.userUnit !== 1.0) {
1242          out('/UserUnit ' + page.userUnit);
1243        }
1244
1245        events.publish('putPage', {
1246          objId: pageObjectNumber,
1247          pageContext: pagesContext[pageNumber],
1248          pageNumber: pageNumber,
1249          page: data
1250        });
1251        out('/Contents ' + pageContentsObjId + ' 0 R');
1252        out('>>');
1253        out('endobj'); // Page content
1254
1255        var pageContent = data.join('\n');
1256        newObjectDeferredBegin(pageContentsObjId, true);
1257        putStream({
1258          data: pageContent,
1259          filters: getFilters()
1260        });
1261        out('endobj');
1262        return pageObjectNumber;
1263      };
1264
1265      var putPages = API.__private__.putPages = function () {
1266        var n,
1267            i,
1268            pageObjectNumbers = [];
1269
1270        for (n = 1; n <= page; n++) {
1271          pagesContext[n].objId = newObjectDeferred();
1272          pagesContext[n].contentsObjId = newObjectDeferred();
1273        }
1274
1275        for (n = 1; n <= page; n++) {
1276          pageObjectNumbers.push(putPage({
1277            number: n,
1278            data: pages[n],
1279            objId: pagesContext[n].objId,
1280            contentsObjId: pagesContext[n].contentsObjId,
1281            mediaBox: pagesContext[n].mediaBox,
1282            cropBox: pagesContext[n].cropBox,
1283            bleedBox: pagesContext[n].bleedBox,
1284            trimBox: pagesContext[n].trimBox,
1285            artBox: pagesContext[n].artBox,
1286            userUnit: pagesContext[n].userUnit,
1287            rootDictionaryObjId: rootDictionaryObjId,
1288            resourceDictionaryObjId: resourceDictionaryObjId
1289          }));
1290        }
1291
1292        newObjectDeferredBegin(rootDictionaryObjId, true);
1293        out('<</Type /Pages');
1294        var kids = '/Kids [';
1295
1296        for (i = 0; i < page; i++) {
1297          kids += pageObjectNumbers[i] + ' 0 R ';
1298        }
1299
1300        out(kids + ']');
1301        out('/Count ' + page);
1302        out('>>');
1303        out('endobj');
1304        events.publish('postPutPages');
1305      };
1306
1307      var putFont = function putFont(font) {
1308        events.publish('putFont', {
1309          font: font,
1310          out: out,
1311          newObject: newObject,
1312          putStream: putStream
1313        });
1314
1315        if (font.isAlreadyPutted !== true) {
1316          font.objectNumber = newObject();
1317          out('<<');
1318          out('/Type /Font');
1319          out('/BaseFont /' + font.postScriptName);
1320          out('/Subtype /Type1');
1321
1322          if (typeof font.encoding === 'string') {
1323            out('/Encoding /' + font.encoding);
1324          }
1325
1326          out('/FirstChar 32');
1327          out('/LastChar 255');
1328          out('>>');
1329          out('endobj');
1330        }
1331      };
1332
1333      var putFonts = function putFonts() {
1334        for (var fontKey in fonts) {
1335          if (fonts.hasOwnProperty(fontKey)) {
1336            if (putOnlyUsedFonts === false || putOnlyUsedFonts === true && usedFonts.hasOwnProperty(fontKey)) {
1337              putFont(fonts[fontKey]);
1338            }
1339          }
1340        }
1341      };
1342
1343      var putResourceDictionary = function putResourceDictionary() {
1344        out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
1345        out('/Font <<'); // Do this for each font, the '1' bit is the index of the font
1346
1347        for (var fontKey in fonts) {
1348          if (fonts.hasOwnProperty(fontKey)) {
1349            if (putOnlyUsedFonts === false || putOnlyUsedFonts === true && usedFonts.hasOwnProperty(fontKey)) {
1350              out('/' + fontKey + ' ' + fonts[fontKey].objectNumber + ' 0 R');
1351            }
1352          }
1353        }
1354
1355        out('>>');
1356        out('/XObject <<');
1357        events.publish('putXobjectDict');
1358        out('>>');
1359      };
1360
1361      var putResources = function putResources() {
1362        putFonts();
1363        events.publish('putResources');
1364        newObjectDeferredBegin(resourceDictionaryObjId, true);
1365        out('<<');
1366        putResourceDictionary();
1367        out('>>');
1368        out('endobj');
1369        events.publish('postPutResources');
1370      };
1371
1372      var putAdditionalObjects = function putAdditionalObjects() {
1373        events.publish('putAdditionalObjects');
1374
1375        for (var i = 0; i < additionalObjects.length; i++) {
1376          var obj = additionalObjects[i];
1377          newObjectDeferredBegin(obj.objId, true);
1378          out(obj.content);
1379          out('endobj');
1380        }
1381
1382        events.publish('postPutAdditionalObjects');
1383      };
1384
1385      var addToFontDictionary = function addToFontDictionary(fontKey, fontName, fontStyle) {
1386        // this is mapping structure for quick font key lookup.
1387        // returns the KEY of the font (ex: "F1") for a given
1388        // pair of font name and type (ex: "Arial". "Italic")
1389        if (!fontmap.hasOwnProperty(fontName)) {
1390          fontmap[fontName] = {};
1391        }
1392
1393        fontmap[fontName][fontStyle] = fontKey;
1394      };
1395
1396      var addFont = function addFont(postScriptName, fontName, fontStyle, encoding, isStandardFont) {
1397        isStandardFont = isStandardFont || false;
1398        var fontKey = 'F' + (Object.keys(fonts).length + 1).toString(10),
1399            // This is FontObject
1400        font = {
1401          'id': fontKey,
1402          'postScriptName': postScriptName,
1403          'fontName': fontName,
1404          'fontStyle': fontStyle,
1405          'encoding': encoding,
1406          'isStandardFont': isStandardFont,
1407          'metadata': {}
1408        };
1409        var instance = this;
1410        events.publish('addFont', {
1411          font: font,
1412          instance: instance
1413        });
1414
1415        if (fontKey !== undefined) {
1416          fonts[fontKey] = font;
1417          addToFontDictionary(fontKey, fontName, fontStyle);
1418        }
1419
1420        return fontKey;
1421      };
1422
1423      var addFonts = function addFonts(arrayOfFonts) {
1424        for (var i = 0, l = standardFonts.length; i < l; i++) {
1425          var fontKey = addFont(arrayOfFonts[i][0], arrayOfFonts[i][1], arrayOfFonts[i][2], standardFonts[i][3], true);
1426          usedFonts[fontKey] = true; // adding aliases for standard fonts, this time matching the capitalization
1427
1428          var parts = arrayOfFonts[i][0].split('-');
1429          addToFontDictionary(fontKey, parts[0], parts[1] || '');
1430        }
1431
1432        events.publish('addFonts', {
1433          fonts: fonts,
1434          dictionary: fontmap
1435        });
1436      };
1437
1438      var SAFE = function __safeCall(fn) {
1439        fn.foo = function __safeCallWrapper() {
1440          try {
1441            return fn.apply(this, arguments);
1442          } catch (e) {
1443            var stack = e.stack || '';
1444            if (~stack.indexOf(' at ')) stack = stack.split(" at ")[1];
1445            var m = "Error in function " + stack.split("\n")[0].split('<')[0] + ": " + e.message;
1446
1447            if (global.console) {
1448              global.console.error(m, e);
1449              if (global.alert) alert(m);
1450            } else {
1451              throw new Error(m);
1452            }
1453          }
1454        };
1455
1456        fn.foo.bar = fn;
1457        return fn.foo;
1458      };
1459
1460      var to8bitStream = function to8bitStream(text, flags) {
1461        /**
1462         * PDF 1.3 spec:
1463         * "For text strings encoded in Unicode, the first two bytes must be 254 followed by
1464         * 255, representing the Unicode byte order marker, U+FEFF. (This sequence conflicts
1465         * with the PDFDocEncoding character sequence thorn ydieresis, which is unlikely
1466         * to be a meaningful beginning of a word or phrase.) The remainder of the
1467         * string consists of Unicode character codes, according to the UTF-16 encoding
1468         * specified in the Unicode standard, version 2.0. Commonly used Unicode values
1469         * are represented as 2 bytes per character, with the high-order byte appearing first
1470         * in the string."
1471         *
1472         * In other words, if there are chars in a string with char code above 255, we
1473         * recode the string to UCS2 BE - string doubles in length and BOM is prepended.
1474         *
1475         * HOWEVER!
1476         * Actual *content* (body) text (as opposed to strings used in document properties etc)
1477         * does NOT expect BOM. There, it is treated as a literal GID (Glyph ID)
1478         *
1479         * Because of Adobe's focus on "you subset your fonts!" you are not supposed to have
1480         * a font that maps directly Unicode (UCS2 / UTF16BE) code to font GID, but you could
1481         * fudge it with "Identity-H" encoding and custom CIDtoGID map that mimics Unicode
1482         * code page. There, however, all characters in the stream are treated as GIDs,
1483         * including BOM, which is the reason we need to skip BOM in content text (i.e. that
1484         * that is tied to a font).
1485         *
1486         * To signal this "special" PDFEscape / to8bitStream handling mode,
1487         * API.text() function sets (unless you overwrite it with manual values
1488         * given to API.text(.., flags) )
1489         * flags.autoencode = true
1490         * flags.noBOM = true
1491         *
1492         * ===================================================================================
1493         * `flags` properties relied upon:
1494         *   .sourceEncoding = string with encoding label.
1495         *                     "Unicode" by default. = encoding of the incoming text.
1496         *                     pass some non-existing encoding name
1497         *                     (ex: 'Do not touch my strings! I know what I am doing.')
1498         *                     to make encoding code skip the encoding step.
1499         *   .outputEncoding = Either valid PDF encoding name
1500         *                     (must be supported by jsPDF font metrics, otherwise no encoding)
1501         *                     or a JS object, where key = sourceCharCode, value = outputCharCode
1502         *                     missing keys will be treated as: sourceCharCode === outputCharCode
1503         *   .noBOM
1504         *       See comment higher above for explanation for why this is important
1505         *   .autoencode
1506         *       See comment higher above for explanation for why this is important
1507         */
1508        var i, l, sourceEncoding, encodingBlock, outputEncoding, newtext, isUnicode, ch, bch;
1509        flags = flags || {};
1510        sourceEncoding = flags.sourceEncoding || 'Unicode';
1511        outputEncoding = flags.outputEncoding; // This 'encoding' section relies on font metrics format
1512        // attached to font objects by, among others,
1513        // "Willow Systems' standard_font_metrics plugin"
1514        // see jspdf.plugin.standard_font_metrics.js for format
1515        // of the font.metadata.encoding Object.
1516        // It should be something like
1517        //   .encoding = {'codePages':['WinANSI....'], 'WinANSI...':{code:code, ...}}
1518        //   .widths = {0:width, code:width, ..., 'fof':divisor}
1519        //   .kerning = {code:{previous_char_code:shift, ..., 'fof':-divisor},...}
1520
1521        if ((flags.autoencode || outputEncoding) && fonts[activeFontKey].metadata && fonts[activeFontKey].metadata[sourceEncoding] && fonts[activeFontKey].metadata[sourceEncoding].encoding) {
1522          encodingBlock = fonts[activeFontKey].metadata[sourceEncoding].encoding; // each font has default encoding. Some have it clearly defined.
1523
1524          if (!outputEncoding && fonts[activeFontKey].encoding) {
1525            outputEncoding = fonts[activeFontKey].encoding;
1526          } // Hmmm, the above did not work? Let's try again, in different place.
1527
1528
1529          if (!outputEncoding && encodingBlock.codePages) {
1530            outputEncoding = encodingBlock.codePages[0]; // let's say, first one is the default
1531          }
1532
1533          if (typeof outputEncoding === 'string') {
1534            outputEncoding = encodingBlock[outputEncoding];
1535          } // we want output encoding to be a JS Object, where
1536          // key = sourceEncoding's character code and
1537          // value = outputEncoding's character code.
1538
1539
1540          if (outputEncoding) {
1541            isUnicode = false;
vendor: 12,224 bytes, lines 1542-1935
1542            newtext = [];
1543
1544            for (i = 0, l = text.length; i < l; i++) {
1545              ch = outputEncoding[text.charCodeAt(i)];
1546
1547              if (ch) {
1548                newtext.push(String.fromCharCode(ch));
1549              } else {
1550                newtext.push(text[i]);
1551              } // since we are looping over chars anyway, might as well
1552              // check for residual unicodeness
1553
1554
1555              if (newtext[i].charCodeAt(0) >> 8) {
1556                /* more than 255 */
1557                isUnicode = true;
1558              }
1559            }
1560
1561            text = newtext.join('');
1562          }
1563        }
1564
1565        i = text.length; // isUnicode may be set to false above. Hence the triple-equal to undefined
1566
1567        while (isUnicode === undefined && i !== 0) {
1568          if (text.charCodeAt(i - 1) >> 8) {
1569            /* more than 255 */
1570            isUnicode = true;
1571          }
1572
1573          i--;
1574        }
1575
1576        if (!isUnicode) {
1577          return text;
1578        }
1579
1580        newtext = flags.noBOM ? [] : [254, 255];
1581
1582        for (i = 0, l = text.length; i < l; i++) {
1583          ch = text.charCodeAt(i);
1584          bch = ch >> 8; // divide by 256
1585
1586          if (bch >> 8) {
1587            /* something left after dividing by 256 second time */
1588            throw new Error("Character at position " + i + " of string '" + text + "' exceeds 16bits. Cannot be encoded into UCS-2 BE");
1589          }
1590
1591          newtext.push(bch);
1592          newtext.push(ch - (bch << 8));
1593        }
1594
1595        return String.fromCharCode.apply(undefined, newtext);
1596      };
1597
1598      var pdfEscape = API.__private__.pdfEscape = API.pdfEscape = function (text, flags) {
1599        /**
1600         * Replace '/', '(', and ')' with pdf-safe versions
1601         *
1602         * Doing to8bitStream does NOT make this PDF display unicode text. For that
1603         * we also need to reference a unicode font and embed it - royal pain in the rear.
1604         *
1605         * There is still a benefit to to8bitStream - PDF simply cannot handle 16bit chars,
1606         * which JavaScript Strings are happy to provide. So, while we still cannot display
1607         * 2-byte characters property, at least CONDITIONALLY converting (entire string containing)
1608         * 16bit chars to (USC-2-BE) 2-bytes per char + BOM streams we ensure that entire PDF
1609         * is still parseable.
1610         * This will allow immediate support for unicode in document properties strings.
1611         */
1612        return to8bitStream(text, flags).replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
1613      };
1614
1615      var beginPage = API.__private__.beginPage = function (width, height) {
1616        var tmp; // Dimensions are stored as user units and converted to points on output
1617
1618        var orientation = typeof height === 'string' && height.toLowerCase();
1619
1620        if (typeof width === 'string') {
1621          if (tmp = getPageFormat(width.toLowerCase())) {
1622            width = tmp[0];
1623            height = tmp[1];
1624          }
1625        }
1626
1627        if (Array.isArray(width)) {
1628          height = width[1];
1629          width = width[0];
1630        }
1631
1632        if (isNaN(width) || isNaN(height)) {
1633          width = format[0];
1634          height = format[1];
1635        }
1636
1637        if (orientation) {
1638          switch (orientation.substr(0, 1)) {
1639            case 'l':
1640              if (height > width) orientation = 's';
1641              break;
1642
1643            case 'p':
1644              if (width > height) orientation = 's';
1645              break;
1646          }
1647
1648          if (orientation === 's') {
1649            tmp = width;
1650            width = height;
1651            height = tmp;
1652          }
1653        }
1654
1655        if (width > 14400 || height > 14400) {
1656          console.warn('A page in a PDF can not be wider or taller than 14400 userUnit. jsPDF limits the width/height to 14400');
1657          width = Math.min(14400, width);
1658          height = Math.min(14400, height);
1659        }
1660
1661        format = [width, height];
1662        outToPages = true;
1663        pages[++page] = [];
1664        pagesContext[page] = {
1665          objId: 0,
1666          contentsObjId: 0,
1667          userUnit: Number(userUnit),
1668          artBox: null,
1669          bleedBox: null,
1670          cropBox: null,
1671          trimBox: null,
1672          mediaBox: {
1673            bottomLeftX: 0,
1674            bottomLeftY: 0,
1675            topRightX: Number(width),
1676            topRightY: Number(height)
1677          }
1678        };
1679
1680        _setPage(page);
1681      };
1682
1683      var _addPage = function _addPage() {
1684        beginPage.apply(this, arguments); // Set line width
1685
1686        setLineWidth(lineWidth); // Set draw color
1687
1688        out(strokeColor); // resurrecting non-default line caps, joins
1689
1690        if (lineCapID !== 0) {
1691          out(lineCapID + ' J');
1692        }
1693
1694        if (lineJoinID !== 0) {
1695          out(lineJoinID + ' j');
1696        }
1697
1698        events.publish('addPage', {
1699          pageNumber: page
1700        });
1701      };
1702
1703      var _deletePage = function _deletePage(n) {
1704        if (n > 0 && n <= page) {
1705          pages.splice(n, 1);
1706          page--;
1707
1708          if (currentPage > page) {
1709            currentPage = page;
1710          }
1711
1712          this.setPage(currentPage);
1713        }
1714      };
1715
1716      var _setPage = function _setPage(n) {
1717        if (n > 0 && n <= page) {
1718          currentPage = n;
1719        }
1720      };
1721
1722      var getNumberOfPages = API.__private__.getNumberOfPages = API.getNumberOfPages = function () {
1723        return pages.length - 1;
1724      };
1725      /**
1726       * Returns a document-specific font key - a label assigned to a
1727       * font name + font type combination at the time the font was added
1728       * to the font inventory.
1729       *
1730       * Font key is used as label for the desired font for a block of text
1731       * to be added to the PDF document stream.
1732       * @private
1733       * @function
1734       * @param fontName {string} can be undefined on "falthy" to indicate "use current"
1735       * @param fontStyle {string} can be undefined on "falthy" to indicate "use current"
1736       * @returns {string} Font key.
1737       * @ignore
1738       */
1739
1740
1741      var _getFont = function getFont(fontName, fontStyle, options) {
1742        var key = undefined,
1743            fontNameLowerCase;
1744        options = options || {};
1745        fontName = fontName !== undefined ? fontName : fonts[activeFontKey].fontName;
1746        fontStyle = fontStyle !== undefined ? fontStyle : fonts[activeFontKey].fontStyle;
1747        fontNameLowerCase = fontName.toLowerCase();
1748
1749        if (fontmap[fontNameLowerCase] !== undefined && fontmap[fontNameLowerCase][fontStyle] !== undefined) {
1750          key = fontmap[fontNameLowerCase][fontStyle];
1751        } else if (fontmap[fontName] !== undefined && fontmap[fontName][fontStyle] !== undefined) {
1752          key = fontmap[fontName][fontStyle];
1753        } else {
1754          if (options.disableWarning === false) {
1755            console.warn("Unable to look up font label for font '" + fontName + "', '" + fontStyle + "'. Refer to getFontList() for available fonts.");
1756          }
1757        }
1758
1759        if (!key && !options.noFallback) {
1760          key = fontmap['times'][fontStyle];
1761
1762          if (key == null) {
1763            key = fontmap['times']['normal'];
1764          }
1765        }
1766
1767        return key;
1768      };
1769
1770      var putInfo = API.__private__.putInfo = function () {
1771        newObject();
1772        out('<<');
1773        out('/Producer (jsPDF ' + jsPDF.version + ')');
1774
1775        for (var key in documentProperties) {
1776          if (documentProperties.hasOwnProperty(key) && documentProperties[key]) {
1777            out('/' + key.substr(0, 1).toUpperCase() + key.substr(1) + ' (' + pdfEscape(documentProperties[key]) + ')');
1778          }
1779        }
1780
1781        out('/CreationDate (' + creationDate + ')');
1782        out('>>');
1783        out('endobj');
1784      };
1785
1786      var putCatalog = API.__private__.putCatalog = function (options) {
1787        options = options || {};
1788        var tmpRootDictionaryObjId = options.rootDictionaryObjId || rootDictionaryObjId;
1789        newObject();
1790        out('<<');
1791        out('/Type /Catalog');
1792        out('/Pages ' + tmpRootDictionaryObjId + ' 0 R'); // PDF13ref Section 7.2.1
1793
1794        if (!zoomMode) zoomMode = 'fullwidth';
1795
1796        switch (zoomMode) {
1797          case 'fullwidth':
1798            out('/OpenAction [3 0 R /FitH null]');
1799            break;
1800
1801          case 'fullheight':
1802            out('/OpenAction [3 0 R /FitV null]');
1803            break;
1804
1805          case 'fullpage':
1806            out('/OpenAction [3 0 R /Fit]');
1807            break;
1808
1809          case 'original':
1810            out('/OpenAction [3 0 R /XYZ null null 1]');
1811            break;
1812
1813          default:
1814            var pcn = '' + zoomMode;
1815            if (pcn.substr(pcn.length - 1) === '%') zoomMode = parseInt(zoomMode) / 100;
1816
1817            if (typeof zoomMode === 'number') {
1818              out('/OpenAction [3 0 R /XYZ null null ' + f2(zoomMode) + ']');
1819            }
1820
1821        }
1822
1823        if (!layoutMode) layoutMode = 'continuous';
1824
1825        switch (layoutMode) {
1826          case 'continuous':
1827            out('/PageLayout /OneColumn');
1828            break;
1829
1830          case 'single':
1831            out('/PageLayout /SinglePage');
1832            break;
1833
1834          case 'two':
1835          case 'twoleft':
1836            out('/PageLayout /TwoColumnLeft');
1837            break;
1838
1839          case 'tworight':
1840            out('/PageLayout /TwoColumnRight');
1841            break;
1842        }
1843
1844        if (pageMode) {
1845          /**
1846           * A name object specifying how the document should be displayed when opened:
1847           * UseNone      : Neither document outline nor thumbnail images visible -- DEFAULT
1848           * UseOutlines  : Document outline visible
1849           * UseThumbs    : Thumbnail images visible
1850           * FullScreen   : Full-screen mode, with no menu bar, window controls, or any other window visible
1851           */
1852          out('/PageMode /' + pageMode);
1853        }
1854
1855        events.publish('putCatalog');
1856        out('>>');
1857        out('endobj');
1858      };
1859
1860      var putTrailer = API.__private__.putTrailer = function () {
1861        out('trailer');
1862        out('<<');
1863        out('/Size ' + (objectNumber + 1));
1864        out('/Root ' + objectNumber + ' 0 R');
1865        out('/Info ' + (objectNumber - 1) + ' 0 R');
1866        out("/ID [ <" + fileId + "> <" + fileId + "> ]");
1867        out('>>');
1868      };
1869
1870      var putHeader = API.__private__.putHeader = function () {
1871        out('%PDF-' + pdfVersion);
1872        out("%\xBA\xDF\xAC\xE0");
1873      };
1874
1875      var putXRef = API.__private__.putXRef = function () {
1876        var i = 1;
1877        var p = "0000000000";
1878        out('xref');
1879        out('0 ' + (objectNumber + 1));
1880        out('0000000000 65535 f ');
1881
1882        for (i = 1; i <= objectNumber; i++) {
1883          var offset = offsets[i];
1884
1885          if (typeof offset === 'function') {
1886            out((p + offsets[i]()).slice(-10) + ' 00000 n ');
1887          } else {
1888            if (typeof offsets[i] !== "undefined") {
1889              out((p + offsets[i]).slice(-10) + ' 00000 n ');
1890            } else {
1891              out('0000000000 00000 n ');
1892            }
1893          }
1894        }
1895      };
1896
1897      var buildDocument = API.__private__.buildDocument = function () {
1898        outToPages = false; // switches out() to content
1899        //reset fields relevant for objectNumber generation and xref.
1900
1901        objectNumber = 0;
1902        content_length = 0;
1903        content = [];
1904        offsets = [];
1905        additionalObjects = [];
1906        rootDictionaryObjId = newObjectDeferred();
1907        resourceDictionaryObjId = newObjectDeferred();
1908        events.publish('buildDocument');
1909        putHeader();
1910        putPages();
1911        putAdditionalObjects();
1912        putResources();
1913        putInfo();
1914        putCatalog();
1915        var offsetOfXRef = content_length;
1916        putXRef();
1917        putTrailer();
1918        out('startxref');
1919        out('' + offsetOfXRef);
1920        out('%%EOF');
1921        outToPages = true;
1922        return content.join('\n');
1923      };
1924
1925      var getBlob = API.__private__.getBlob = function (data) {
1926        return new Blob([getArrayBuffer(data)], {
1927          type: "application/pdf"
1928        });
1929      };
1930      /**
1931       * Generates the PDF document.
1932       *
1933       * If `type` argument is undefined, output is raw body of resulting PDF returned as a string.
1934       *
1935       * @param {string}
1935 type A string identifying one of the possible output types. Possible values are 'arraybuffer', 'blob', 'bloburi'/'bloburl', 'datauristring'/'dataurlstring', 'datauri'/'dataurl', 'dataurlnewwindow'.
1936       * @param {Object} options An object providing some additional signalling to PDF generator. Possible options are 'filename'.
1937       *
1938       * @function
1939       * @instance
1940       * @returns {jsPDF}
1941       * @memberOf jsPDF
1942       * @name output
1943       */
1944
1945
1946      var output = API.output = API.__private__.output = SAFE(function output(type, options) {
1947        options = options || {};
1948        var pdfDocument = buildDocument();
1949
1950        if (typeof options === "string") {
1951          options = {
1952            filename: options
1953          };
1954        } else {
1955          options.filename = options.filename || 'generated.pdf';
1956        }
1957
1958        switch (type) {
1959          case undefined:
1960            return pdfDocument;
1961
1962          case 'save':
1963            API.save(options.filename);
1964            break;
1965
1966          case 'arraybuffer':
1967            return getArrayBuffer(pdfDocument);
1968
1969          case 'blob':
1970            return getBlob(pdfDocument);
1971
1972          case 'bloburi':
1973          case 'bloburl':
1974            // Developer is responsible of calling revokeObjectURL
1975            if (typeof global.URL !== "undefined" && typeof global.URL.createObjectURL === "function") {
1976              return global.URL && global.URL.createObjectURL(getBlob(pdfDocument)) || void 0;
1977            } else {
1978              console.warn('bloburl is not supported by your system, because URL.createObjectURL is not supported by your browser.');
1979            }
1980
1981            break;
1982
1983          case 'datauristring':
1984          case 'dataurlstring':
1985            return 'data:application/pdf;filename=' + options.filename + ';base64,' + btoa(pdfDocument);
1986
1987          case 'dataurlnewwindow':
1988            var htmlForNewWindow = '<html>' + '<style>html, body { padding: 0; margin: 0; } iframe { width: 100%; height: 100%; border: 0;}  </style>' + '<body>' + '<iframe src="' + this.output('datauristring') + '"></iframe>' + '</body></html>';
1989            var nW = global.open();
1990
1991            if (nW !== null) {
1992              nW.document.write(htmlForNewWindow);
1993            }
1994
1995            if (nW || typeof safari === "undefined") return nW;
1996
1997          /* pass through */
1998
1999          case 'datauri':
2000          case 'dataurl':
2001            return global.document.location.href = 'data:application/pdf;filename=' + options.filename + ';base64,' + btoa(pdfDocument);
2002
2003          default:
2004            return null;
2005        }
2006      });
2007      /**
2008       * Used to see if a supplied hotfix was requested when the pdf instance was created.
2009       * @param {string} hotfixName - The name of the hotfix to check.
2010       * @returns {boolean}
2011       */
2012
2013      var hasHotfix = function hasHotfix(hotfixName) {
2014        return Array.isArray(hotfixes) === true && hotfixes.indexOf(hotfixName) > -1;
2015      };
2016
2017      switch (unit) {
2018        case 'pt':
2019          k = 1;
2020          break;
2021
2022        case 'mm':
2023          k = 72 / 25.4;
2024          break;
2025
2026        case 'cm':
2027          k = 72 / 2.54;
2028          break;
2029
2030        case 'in':
2031          k = 72;
2032          break;
2033
2034        case 'px':
2035          if (hasHotfix('px_scaling') == true) {
2036            k = 72 / 96;
2037          } else {
2038            k = 96 / 72;
2039          }
2040
2041          break;
2042
2043        case 'pc':
2044          k = 12;
2045          break;
2046
2047        case 'em':
2048          k = 12;
2049          break;
2050
2051        case 'ex':
2052          k = 6;
2053          break;
2054
2055        default:
2056          throw new Error('Invalid unit: ' + unit);
2057      }
2058
2059      setCreationDate();
2060      setFileId(); //---------------------------------------
2061      // Public API
2062
2063      var getPageInfo = API.__private__.getPageInfo = function (pageNumberOneBased) {
2064        if (isNaN(pageNumberOneBased) || pageNumberOneBased % 1 !== 0) {
2065          throw new Error('Invalid argument passed to jsPDF.getPageInfo');
2066        }
2067
2068        var objId = pagesContext[pageNumberOneBased].objId;
2069        return {
2070          objId: objId,
2071          pageNumber: pageNumberOneBased,
2072          pageContext: pagesContext[pageNumberOneBased]
2073        };
2074      };
2075
2076      var getPageInfoByObjId = API.__private__.getPageInfoByObjId = function (objId) {
2077
2078        for (var pageNumber in pagesContext) {
2079          if (pagesContext[pageNumber].objId === objId) {
2080            break;
2081          }
2082        }
2083
2084        if (isNaN(objId) || objId % 1 !== 0) {
vendor: 5,506 bytes, lines 2085-2230
2085          throw new Error('Invalid argument passed to jsPDF.getPageInfoByObjId');
2086        }
2087
2088        return getPageInfo(pageNumber);
2089      };
2090
2091      var getCurrentPageInfo = API.__private__.getCurrentPageInfo = function () {
2092        return {
2093          objId: pagesContext[currentPage].objId,
2094          pageNumber: currentPage,
2095          pageContext: pagesContext[currentPage]
2096        };
2097      };
2098      /**
2099       * Adds (and transfers the focus to) new page to the PDF document.
2100       * @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 />
2101       * 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]
2102       * @param orientation {string} Orientation of the new page. Possible values are "portrait" or "landscape" (or shortcuts "p" (Default), "l").
2103       * @function
2104       * @instance
2105       * @returns {jsPDF}
2106       *
2107       * @memberOf jsPDF
2108       * @name addPage
2109       */
2110
2111
2112      API.addPage = function () {
2113        _addPage.apply(this, arguments);
2114
2115        return this;
2116      };
2117      /**
2118       * Adds (and transfers the focus to) new page to the PDF document.
2119       * @function
2120       * @instance
2121       * @returns {jsPDF}
2122       *
2123       * @memberOf jsPDF
2124       * @name setPage
2125       * @param {number} page Switch the active page to the page number specified.
2126       * @example
2127       * doc = jsPDF()
2128       * doc.addPage()
2129       * doc.addPage()
2130       * doc.text('I am on page 3', 10, 10)
2131       * doc.setPage(1)
2132       * doc.text('I am on page 1', 10, 10)
2133       */
2134
2135
2136      API.setPage = function () {
2137        _setPage.apply(this, arguments);
2138
2139        return this;
2140      };
2141      /**
2142       * @name insertPage
2143       * @memberOf jsPDF
2144       * 
2145       * @function 
2146       * @instance
2147       * @param {Object} beforePage
2148       * @returns {jsPDF}
2149       */
2150
2151
2152      API.insertPage = function (beforePage) {
2153        this.addPage();
2154        this.movePage(currentPage, beforePage);
2155        return this;
2156      };
2157      /**
2158       * @name movePage
2159       * @memberOf jsPDF
2160       * @function
2161       * @instance
2162       * @param {Object} targetPage
2163       * @param {Object} beforePage
2164       * @returns {jsPDF}
2165       */
2166
2167
2168      API.movePage = function (targetPage, beforePage) {
2169        if (targetPage > beforePage) {
2170          var tmpPages = pages[targetPage];
2171          var tmpPagesContext = pagesContext[targetPage];
2172
2173          for (var i = targetPage; i > beforePage; i--) {
2174            pages[i] = pages[i - 1];
2175            pagesContext[i] = pagesContext[i - 1];
2176          }
2177
2178          pages[beforePage] = tmpPages;
2179          pagesContext[beforePage] = tmpPagesContext;
2180          this.setPage(beforePage);
2181        } else if (targetPage < beforePage) {
2182          var tmpPages = pages[targetPage];
2183          var tmpPagesContext = pagesContext[targetPage];
2184
2185          for (var i = targetPage; i < beforePage; i++) {
2186            pages[i] = pages[i + 1];
2187            pagesContext[i] = pagesContext[i + 1];
2188          }
2189
2190          pages[beforePage] = tmpPages;
2191          pagesContext[beforePage] = tmpPagesContext;
2192          this.setPage(beforePage);
2193        }
2194
2195        return this;
2196      };
2197      /**
2198       * Deletes a page from the PDF.
2199       * @name deletePage
2200       * @memberOf jsPDF
2201       * @function
2202       * @instance
2203       * @returns {jsPDF}
2204       */
2205
2206
2207      API.deletePage = function () {
2208        _deletePage.apply(this, arguments);
2209
2210        return this;
2211      };
2212      /**
2213       * Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings.
2214       *
2215       * @function
2216       * @instance
2217       * @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.
2218       * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page.
2219       * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page.
2220       * @param {Object} [options] - Collection of settings signaling how the text must be encoded.
2221       * @param {string} [options.align=left] - The alignment of the text, possible values: left, center, right, justify.
2222       * @param {string} [options.baseline=alphabetic] - Sets text baseline used when drawing the text, possible values: alphabetic, ideographic, bottom, top, middle.
2223       * @param {string} [options.angle=0] - Rotate the text counterclockwise. Expects the angle in degree.
2224       * @param {string} [options.charSpace=0] - The space between each letter.
2225       * @param {string} [options.lineHeightFactor=1.15] - The lineheight of each line.
2226       * @param {string} [options.flags] - Flags for to8bitStream.
2227       * @param {string} [options.flags.noBOM=true] - Don't add BOM to Unicode-text.
2228       * @param {string} [options.flags.autoencode=true] - Autoencode the Text.
2229       * @param {string} [options.maxWidth=0] - Split the text by given width, 0 = no split.
2230       * @param {string} [options.renderingMode=fill] - Set how the text should be rendered, possible values: fill, stroke, fillThenStroke, invisible, fillAndAddForClipping, strokeAndAddPathForClipping, fillThenStrokeAndAddToPathF
2230orClipping, addToPathForClipping.
2231       * @returns {jsPDF}
2232       * @memberOf jsPDF
2233       * @name text
2234       */
2235
2236
2237      var text = API.__private__.text = API.text = function (text, x, y, options) {
2238        /**
2239         * Inserts something like this into PDF
2240         *   BT
2241         *    /F1 16 Tf  % Font name + size
2242         *    16 TL % How many units down for next line in multiline text
2243         *    0 g % color
2244         *    28.35 813.54 Td % position
2245         *    (line one) Tj
2246         *    T* (line two) Tj
2247         *    T* (line three) Tj
2248         *   ET
2249         */
2250        //backwardsCompatibility
2251        var tmp; // Pre-August-2012 the order of arguments was function(x, y, text, flags)
2252        // in effort to make all calls have similar signature like
2253        //   function(data, coordinates... , miscellaneous)
2254        // this method had its args flipped.
2255        // code below allows backward compatibility with old arg order.
2256
2257        if (typeof text === 'number' && typeof x === 'number' && (typeof y === 'string' || Array.isArray(y))) {
2258          tmp = y;
2259          y = x;
2260          x = text;
2261          text = tmp;
2262        }
2263
2264        var flags = arguments[3];
2265        var angle = arguments[4];
2266        var align = arguments[5];
2267
2268        if (_typeof(flags) !== "object" || flags === null) {
2269          if (typeof angle === 'string') {
2270            align = angle;
2271            angle = null;
2272          }
2273
2274          if (typeof flags === 'string') {
2275            align = flags;
2276            flags = null;
2277          }
2278
2279          if (typeof flags === 'number') {
2280            angle = flags;
2281            flags = null;
2282          }
2283
2284          options = {
2285            flags: flags,
2286            angle: angle,
2287            align: align
2288          };
2289        }
2290
2291        flags = flags || {};
2292        flags.noBOM = flags.noBOM || true;
2293        flags.autoencode = flags.autoencode || true;
2294
2295        if (isNaN(x) || isNaN(y) || typeof text === "undefined" || text === null) {
2296          throw new Error('Invalid arguments passed to jsPDF.text');
2297        }
2298
2299        if (text.length === 0) {
2300          return scope;
2301        }
2302
2303        var xtra = '';
2304        var isHex = false;
2305        var lineHeight = typeof options.lineHeightFactor === 'number' ? options.lineHeightFactor : lineHeightFactor;
2306        var scope = options.scope || this;
2307
2308        function ESC(s) {
2309          s = s.split("\t").join(Array(options.TabLen || 9).join(" "));
2310          return pdfEscape(s, flags);
2311        }
2312
2313        function transformTextToSpecialArray(text) {
2314          //we don't want to destroy original text array, so cloning it
2315          var sa = text.concat();
2316          var da = [];
2317          var len = sa.length;
2318          var curDa; //we do array.join('text that must not be PDFescaped")
2319          //thus, pdfEscape each component separately
2320
2321          while (len--) {
2322            curDa = sa.shift();
2323
2324            if (typeof curDa === "string") {
2325              da.push(curDa);
2326            } else {
2327              if (Array.isArray(text) && curDa.length === 1) {
2328                da.push(curDa[0]);
2329              } else {
2330                da.push([curDa[0], curDa[1], curDa[2]]);
2331              }
2332            }
2333          }
2334
2335          return da;
2336        }
2337
2338        function processTextByFunction(text, processingFunction) {
2339          var result;
2340
2341          if (typeof text === 'string') {
2342            result = processingFunction(text)[0];
2343          } else if (Array.isArray(text)) {
2344            //we don't want to destroy original text array, so cloning it
2345            var sa = text.concat();
2346            var da = [];
2347            var len = sa.length;
2348            var curDa;
2349            var tmpResult; //we do array.join('text that must not be PDFescaped")
2350            //thus, pdfEscape each component separately
2351
2352            while (len--) {
2353              curDa = sa.shift();
2354
2355              if (typeof curDa === "string") {
2356                da.push(processingFunction(curDa)[0]);
2357              } else if (Array.isArray(curDa) && curDa[0] === "string") {
2358                tmpResult = processingFunction(curDa[0], curDa[1], curDa[2]);
2359                da.push([tmpResult[0], tmpResult[1], tmpResult[2]]);
2360              }
2361            }
2362
2363            result = da;
2364          }
2365
2366          return result;
2367        }
2367 //Check if text is of type String
2368
2369
2370        var textIsOfTypeString = false;
2371        var tmpTextIsOfTypeString = true;
2372
2373        if (typeof text === 'string') {
2374          textIsOfTypeString = true;
2375        } else if (Array.isArray(text)) {
2376          //we don't want to destroy original text array, so cloning it
2377          var sa = text.concat();
2378          var da = [];
2379          var len = sa.length;
2380          var curDa; //we do array.join('text that must not be PDFescaped")
2381          //thus, pdfEscape each component separately
2382
2383          while (len--) {
2384            curDa = sa.shift();
2385
2386            if (typeof curDa !== "string" || Array.isArray(curDa) && typeof curDa[0] !== "string") {
2387              tmpTextIsOfTypeString = false;
2388            }
2389          }
2390
2391          textIsOfTypeString = tmpTextIsOfTypeString;
2392        }
2393
2394        if (textIsOfTypeString === false) {
2395          throw new Error('Type of text must be string or Array. "' + text + '" is not recognized.');
2396        } //Escaping 
2397
2398
2399        var activeFontEncoding = fonts[activeFontKey].encoding;
2400
2401        if (activeFontEncoding === "WinAnsiEncoding" || activeFontEncoding === "StandardEncoding") {
2402          text = processTextByFunction(text, function (text, posX, posY) {
2403            return [ESC(text), posX, posY];
2404          });
2405        } //If there are any newlines in text, we assume
2406        //the user wanted to print multiple lines, so break the
2407        //text up into an array. If the text is already an array,
2408        //we assume the user knows what they are doing.
2409        //Convert text into an array anyway to simplify
2410        //later code.
2411
2412
2413        if (typeof text === 'string') {
2414          if (text.match(/[\r?\n]/)) {
2415            text = text.split(/\r\n|\r|\n/g);
2416          } else {
2417            text = [text];
2418          }
2419        } //baseline
2420
2421
2422        var height = activeFontSize / scope.internal.scaleFactor;
2423        var descent = height * (lineHeightFactor - 1);
2424
2425        switch (options.baseline) {
2426          case 'bottom':
2427            y -= descent;
2428            break;
2429
2430          case 'top':
2431            y += height - descent;
2432            break;
2433
2434          case 'hanging':
2435            y += height - 2 * descent;
2436            break;
2437
2438          case 'middle':
2439            y += height / 2 - descent;
2440            break;
2441
2442          case 'ideographic':
2443          case 'alphabetic':
2444          default:
2445            // do nothing, everything is fine
2446            break;
2447        } //multiline
2448
2449
2450        var maxWidth = options.maxWidth || 0;
2451
2452        if (maxWidth > 0) {
2453          if (typeof text === 'string') {
2454            text = scope.splitTextToSize(text, maxWidth);
2455          } else if (Object.prototype.toString.call(text) === '[object Array]') {
2456            text = scope.splitTextToSize(text.join(" "), maxWidth);
2457          }
2458        } //creating Payload-Object to make text byRef
2459
2460
2461        var payload = {
2462          text: text,
2463          x: x,
2464          y: y,
2465          options: options,
2466          mutex: {
2467            pdfEscape: pdfEscape,
2468            activeFontKey: activeFontKey,
2469            fonts: fonts,
2470            activeFontSize: activeFontSize
2471          }
2472        };
2473        events.publish('preProcessText', payload);
2474        text = payload.text;
2475        options = payload.options; //angle
2476
2477        var angle = options.angle;
2478        var k = scope.internal.scaleFactor;
2479        var transformationMatrix = [];
2480
2481        if (angle) {
2482          angle *= Math.PI / 180;
2483          var c = Math.cos(angle),
2484              s = Math.sin(angle);
2485          transformationMatrix = [f2(c), f2(s), f2(s * -1), f2(c)];
2486        } //charSpace
2487
2488
2489        var charSpace = options.charSpace;
2490
2491        if (typeof charSpace !== 'undefined') {
2492          xtra += f3(charSpace * k) + " Tc\n";
2493        } //lang
2494
2495
2496        var lang = options.lang;
2497        var tmpRenderingMode = -1;
2498        var parmRenderingMode = typeof options.renderingMode !== "undefined" ? options.renderingMode : options.stroke;
2499        var pageContext = scope.internal.getCurrentPageInfo().pageContext;
2500
2501        switch (parmRenderingMode) {
2502          case 0:
2503          case false:
2504          case 'fill':
2505            tmpRenderingMode = 0;
2506            break;
2507
2508          case 1:
2509          case true:
2510          case 'stroke':
2511            tmpRenderingMode = 1;
2512            break;
2513
2514          case 2:
2515          case 'fillThenStroke':
2516            tmpRenderingMode = 2;
2517            break;
2518
2519          case 3:
2520          case 'invisible':
2521            tmpRenderingMode = 3;
2522            break;
2523
2524          case 4:
2525          case 'fillAndAddForClipping':
2526            tmpRenderingMode = 4;
2527            break;
2528
2529          case 5:
2530          case 'strokeAndAddPathForClipping':
2531            tmpRenderingMode = 5;
2532            break;
2533
2534          case 6:
2535          case 'fillThenStrokeAndAddToPathForClipping':
2536            tmpRenderingMode = 6;
2537            break;
2538
2539          case 7:
2540          case 'addToPathForClipping':
2541            tmpRenderingMode = 7;
2542            break;
2543        }
2544
2545        var usedRenderingMode = typeof pageContext.usedRenderingMode !== 'undefined' ? pageContext.usedRenderingMode : -1; //if the coder wrote it explicitly to use a specific 
2546        //renderingMode, then use it
2547
2548        if (tmpRenderingMode !== -1) {
2549          xtra += tmpRenderingMode + " Tr\n"; //otherwise check if we used the rendering Mode already
2550          //if so then set the rendering Mode...
2551        } else if (usedRenderingMode !== -1) {
2552          xtra += "0 Tr\n";
2553        }
2554
2555        if (tmpRenderingMode !== -1) {
2556          pageContext.usedRenderingMode = tmpRenderingMode;
2557        } //align
2558
2559
2560        var align = options.align || 'left';
2561        var leading = activeFontSize * lineHeight;
2562        var pageWidth = scope.internal.pageSize.getWidth();
2563        var k = scope.internal.scaleFactor;
2564        var activeFont = fonts[activeFontKey];
2565        var charSpace = options.charSpace || activeCharSpace;
2566        var maxWidth = options.maxWidth || 0;
2567        var lineWidths;
2568        var flags = {};
2569        var wordSpacingPerLine = [];
2570
2571        if (Object.prototype.toString.call(text) === '[object Array]') {
2572          var da = transformTextToSpecialArray(text);
2573          var newY;
2574          var maxLineLength;
2575          var lineWidths;
2576
2577          if (align !== "left") {
2578            lineWidths = da.map(function (v) {
2579              return scope.getStringUnitWidth(v, {
2580                font: activeFont,
2581                charSpace: charSpace,
2582                fontSize: activeFontSize
2583              }) * activeFontSize / k;
2584            });
2585          }
2586
2587          var maxLineLength = Math.max.apply(Math, lineWidths); //The first line uses the "main" Td setting,
2588          //and the subsequent lines are offset by the
2589          //previous line's x coordinate.
2590
2591          var prevWidth = 0;
2592          var delta;
2593          var newX;
2594
2595          if (align === "right") {
2596            x -= lineWidths[0];
2597            text = [];
2598
2599            for (var i = 0, len = da.length; i < len; i++) {
2600              delta = maxLineLength - lineWidths[i];
2601
2602              if (i === 0) {
2603                newX = getHorizontalCoordinate(x);
2604                newY = getVerticalCoordinate(y);
2605              } else {
2606                newX = (prevWidth - lineWidths[i]) * k;
2607                newY = -leading;
2608              }
2609
2610              text.push([da[i], newX, newY]);
2611              prevWidth = lineWidths[i];
2612            }
2613          } else if (align === "center") {
2614            x -= lineWidths[0] / 2;
2615            text = [];
2616
2617            for (var i = 0, len = da.length; i < len; i++) {
2618              delta = (maxLineLength - lineWidths[i]) / 2;
2619
2620              if (i === 0) {
2621                newX = getHorizontalCoordinate(x);
2622                newY = getVerticalCoordinate(y);
2623              } else {
2624                newX = (prevWidth - lineWidths[i]) / 2 * k;
2625                newY = -leading;
2626              }
2627
2628              text.push([da[i], newX, newY]);
2629              prevWidth = lineWidths[i];
2630            }
2631          } else if (align === "left") {
2632            text = [];
2633
2634            for (var i = 0, len = da.length; i < len; i++) {
2635              newY = i === 0 ? getVerticalCoordinate(y) : -leading;
2636              newX = i === 0 ? getHorizontalCoordinate(x) : 0; //text.push([da[i], newX, newY]);
2637
2638              text.push(da[i]);
2639            }
2640          } else if (align === "justify") {
2641            text = [];
2642            var maxWidth = maxWidth !== 0 ? maxWidth : pageWidth;
2643
2644            for (var i = 0, len = da.length; i < len; i++) {
2645              newY = i === 0 ? getVerticalCoordinate(y) : -leading;
2646              newX = i === 0 ? getHorizontalCoordinate(x) : 0;
2647
2648              if (i < len - 1) {
2649                wordSpacingPerLine.push(((maxWidth - lineWidths[i]) / (da[i].split(" ").length - 1) * k).toFixed(2));
2650              }
2651
2652              text.push([da[i], newX, newY]);
2653            }
2654          } else {
2655            throw new Error('Unrecognized alignment option, use "left", "center", "right" or "justify".');
2656          }
2657        } //R2L
2658
2659
2660        var doReversing = typeof options.R2L === "boolean" ? options.R2L : R2L;
2661
2662        if (doReversing === true) {
2663          text = processTextByFunction(text, function (text, posX, posY) {
2664            return [text.split("").reverse().join(""), posX, posY];
2665          });
2666        } //creating Payload-Object to make text byRef
2667
2668
2669        var payload = {
2670          text: text,
2671          x: x,
2672          y: y,
2673          options: options,
2674          mutex: {
2675            pdfEscape: pdfEscape,
2676            activeFontKey: activeFontKey,
2677            fonts: fonts,
2678            activeFontSize: activeFontSize
2679          }
2680        };
2681        events.publish('postProcessText', payload);
2682        text = payload.text;
2683        isHex = payload.mutex.isHex;
2684        var da = transformTextToSpecialArray(text);
2685        text = [];
2686        var variant = 0;
2687        var len = da.length;
2688        var posX;
2689        var posY;
2690        var content;
2691        var wordSpacing = '';
2692
2693        for (var i = 0; i < len; i++) {
2694          wordSpacing = '';
2695
2696          if (!Array.isArray(da[i])) {
2697            posX = getHorizontalCoordinate(x);
2698            posY = getVerticalCoordinate(y);
2699            content = (isHex ? "<" : "(") + da[i] + (isHex ? ">" : ")");
2700          } else {
2701            posX = parseFloat(da[i][1]);
2702            posY = parseFloat(da[i][2]);
2703            content = (isHex ? "<" : "(") + da[i][0] + (isHex ? ">" : ")");
2704            variant = 1;
2705          }
2706
2707          if (wordSpacingPerLine !== undefined && wordSpacingPerLine[i] !== undefined) {
2708            wordSpacing = wordSpacingPerLine[i] + " Tw\n";
2709          }
2710
2711          if (transformationMatrix.length !== 0 && i === 0) {
2712            text.push(wordSpacing + transformationMatrix.join(" ") + " " + posX.toFixed(2) + " " + posY.toFixed(2) + " Tm\n" + content);
2713          } else if (variant === 1 || variant === 0 && i === 0) {
2714            text.push(wordSpacing + posX.toFixed(2) + " " + posY.toFixed(2) + " Td\n" + content);
2715          } else {
2716            text.push(wordSpacing + content);
2717          }
2718        }
2719
2720        if (variant === 0) {
2721          text = text.join(" Tj\nT* ");
2722        } else {
2723          text = text.join(" Tj\n");
2724        }
2725
2726        text += " Tj\n";
2727        var result = 'BT\n/' + activeFontKey + ' ' + activeFontSize + ' Tf\n' + // font face, style, size
2728        (activeFontSize * lineHeight).toFixed(2) + ' TL\n' + // line spacing
2729        textColor + '\n';
2730        result += xtra;
2731        result += text;
2732        result += "ET";
2733        out(result);
2734        usedFonts[activeFontKey] = true;
2735        return scope;
2736      };
2737      /**
2738       * Letter spacing method to print text with gaps
2739       *
2740       * @function
2741       * @instance
2742       * @param {String|Array} text String to be added to the page.
2743       * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
2744       * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
2745       * @param {number} spacing Spacing (in units declared at inception)
2746       * @returns {jsPDF}
2747       * @memberOf jsPDF
2748       * @name lstext
2749       * @deprecated We'll be removing this function. It doesn't take character width into account.
2750       */
2751
2752
2753      var lstext = API.__private__.lstext = API.lstext = function (text, x, y, charSpace) {
2754        console.warn('jsPDF.lstext is deprecated');
2755        return this.text(text, x, y, {
2756          charSpace: charSpace
2757        });
2758      };
2759      /**
2760       * 
2761       * @name clip
2762       * @function
2763       * @instance
2764       * @param {string} rule 
2765       * @returns {jsPDF}
2766       * @memberOf jsPDF
2767       * @description All .clip() after calling drawing ops with a style argument of null.
2768       */
2769
2770
2771      var clip = API.__private__.clip = API.clip = function (rule) {
2772        // Call .clip() after calling drawing ops with a style argument of null
2773        // W is the PDF clipping op
2774        if ('evenodd' === rule) {
2775          out('W*');
2776        } else {
2777          out('W');
2778        } // End the path object without filling or stroking it.
2779        // This operator is a path-painting no-op, used primarily for the side effect of changing the current clipping path
2780        // (see Section 4.4.3, “Clipping Path Operators”)
2781
2782
2783        out('n');
2784      };
2785      /**
2786       * This fixes the previous function clip(). Perhaps the 'stroke path' hack was due to the missing 'n' instruction?
2787       * We introduce the fixed version so as to not break API.
2788       * @param fillRule
2789       * @ignore
2790       */
2791
2792
2793      var clip_fixed = API.__private__.clip_fixed = API.clip_fixed = function (rule) {
2794        console.log("clip_fixed is deprecated");
2795        API.clip(rule);
2796      };
2797
2798      var isValidStyle = API.__private__.isValidStyle = function (style) {
2799        var validStyleVariants = [undefined, null, 'S', 'F', 'DF', 'FD', 'f', 'f*', 'B', 'B*'];
2800        var result = false;
2801
2802        if (validStyleVariants.indexOf(style) !== -1) {
2803          result = true;
2804        }
2805
2806        return result;
2807      };
2808
2809      var getStyle = API.__private__.getStyle = function (style) {
2810        // see path-painting operators in PDF spec
2811        var op = 'S'; // stroke
2812
2813        if (style === 'F') {
2814          op = 'f'; // fill
2815        } else if (style === 'FD' || style === 'DF') {
2816          op = 'B'; // both
2817        } else if (style === 'f' || style === 'f*' || style === 'B' || style === 'B*') {
2818          /*
2819           Allow direct use of these PDF path-painting operators:
2820           - f    fill using nonzero winding number rule
2821           - f*    fill using even-odd rule
2822           - B    fill then stroke with fill using non-zero winding number rule
2823           - B*    fill then stroke with fill using even-odd rule
2824           */
2825          op = style;
2826        }
2827
2828        return op;
2829      };
2830      /**
2831       * Draw a line on the current page.
2832       *
2833       * @name line
2834       * @function 
2835       * @instance
2836       * @param {number} x1
2837       * @param {number} y1
2838       * @param {number} x2
2839       * @param {number} y2
2840       * @returns {jsPDF}
2841       * @memberOf jsPDF
2842       */
2843
2844
2845      var line = API.__private__.line = API.line = function (x1, y1, x2, y2) {
2846        if (isNaN(x1) || isNaN(y1) || isNaN(x2) || isNaN(y2)) {
2847          throw new Error('Invalid arguments passed to jsPDF.line');
2848        }
2849
2850        return this.lines([[x2 - x1, y2 - y1]], x1, y1);
2851      };
2852      /**
2853       * Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates.
2854       * All data points in `lines` are relative to last line origin.
2855       * `x`, `y` become x1,y1 for first line / curve in the set.
2856       * For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point.
2857       * 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.
2858       *
2859       * @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
2860       * @param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves).
2861       * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page.
2862       * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page.
2863       * @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.
2864       * @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.
2865       * @param {boolean} closed If true, the path is closed with a straight line from the end of the last curve to the starting point.
2866       * @function
2867       * @instance
2868       * @returns {jsPDF}
2869       * @memberOf jsPDF
2870       * @name lines
2871       */
2872
2873
2874      var lines = API.__private__.lines = API.lines = function (lines, x, y, scale, style, closed) {
2875        var scalex, scaley, i, l, leg, x2, y2, x3, y3, x4, y4, tmp; // Pre-August-2012 the order of arguments was function(x, y, lines, scale, style)
2876        // in effort to make all calls have similar signature like
2877        //   function(content, coordinateX, coordinateY , miscellaneous)
2878        // this method had its args flipped.
2879        // code below allows backward compatibility with old arg order.
2880
2881        if (typeof lines === 'number') {
2882          tmp = y;
2883          y = x;
2884          x = lines;
2885          lines = tmp;
2886        }
2887
2888        scale = scale || [1, 1];
2889        closed = closed || false;
2890
2891        if (isNaN(x) || isNaN(y) || !Array.isArray(lines) || !Array.isArray(scale) || !isValidStyle(style) || typeof closed !== 'boolean') {
2892          throw new Error('Invalid arguments passed to jsPDF.lines');
2893        } // starting point
2894
2895
2896        out(f3(getHorizontalCoordinate(x)) + ' ' + f3(getVerticalCoordinate(y)) + ' m ');
2897        scalex = scale[0];
2898        scaley = scale[1];
2899        l = lines.length; //, x2, y2 // bezier only. In page default measurement "units", *after* scaling
2900        //, x3, y3 // bezier only. In page default measurement "units", *after* scaling
2901        // ending point for all, lines and bezier. . In page default measurement "units", *after* scaling
2902
2903        x4 = x; // last / ending point = starting point for first item.
2904
2905        y4 = y; // last / ending point = starting point for first item.
2906
2907        for (i = 0; i < l; i++) {
2908          leg = lines[i];
2909
2910          if (leg.length === 2) {
2911            // simple line
2912            x4 = leg[0] * scalex + x4; // here last x4 was prior ending point
2913
2914            y4 = leg[1] * scaley + y4; // here last y4 was prior ending point
2915
2916            out(f3(getHorizontalCoordinate(x4)) + ' ' + f3(getVerticalCoordinate(y4)) + ' l');
2917          } else {
2918            // bezier curve
2919            x2 = leg[0] * scalex + x4; // here last x4 is prior ending point
2920
2921            y2 = leg[1] * scaley + y4; // here last y4 is prior ending point
2922
2923            x3 = leg[2] * scalex + x4; // here last x4 is prior ending point
2924
2925            y3 = leg[3] * scaley + y4; // here last y4 is prior ending point
2926
2927            x4 = leg[4] * scalex + x4; // here last x4 was prior ending point
2928
2929            y4 = leg[5] * scaley + y4; // here last y4 was prior ending point
2930
2931            out(f3(getHorizontalCoordinate(x2)) + ' ' + f3(getVerticalCoordinate(y2)) + ' ' + f3(getHorizontalCoordinate(x3)) + ' ' + f3(getVerticalCoordinate(y3)) + ' ' + f3(getHorizontalCoordinate(x4)) + ' ' + f3(getVerticalCoordinate(y4)) + ' c');
2932          }
2933        }
2934
2935        if (closed) {
2936          out(' h');
2937        } // stroking / filling / both the path
2938
2939
2940        if (style !== null) {
2941          out(getStyle(style));
2942        }
2943
2944        return this;
2945      };
2946      /**
2947       * Adds a rectangle to PDF.
2948       *
2949       * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page.
2950       * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page.
2951       * @param {number} w Width (in units declared at inception of PDF document).
2952       * @param {number} h Height (in units declared at inception of PDF document).
2953       * @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.
2954       * @function
2955       * @instance
2956       * @returns {jsPDF}
2957       * @memberOf jsPDF
2958       * @name rect
2959       */
2960
2961
2962      var rect = API.__private__.rect = API.rect = function (x, y, w, h, style) {
2963        if (isNaN(x) || isNaN(y) || isNaN(w) || isNaN(h) || !isValidStyle(style)) {
2964          throw new Error('Invalid arguments passed to jsPDF.rect');
2965        }
2966
2967        out([f2(getHorizontalCoordinate(x)), f2(getVerticalCoordinate(y)), f2(w * k), f2(-h * k), 're'].join(' '));
2968
2969        if (style !== null) {
2970          out(getStyle(style));
2971        }
2972
2973        return this;
2974      };
2975      /**
2976       * Adds a triangle to PDF.
2977       *
2978       * @param {number} x1 Coordinate (in units declared at inception of PDF document) against left edge of the page.
2979       * @param {number} y1 Coordinate (in units declared at inception of PDF document) against upper edge of the page.
2980       * @param {number} x2 Coordinate (in units declared at inception of PDF document) against left edge of the page.
2981       * @param {number} y2 Coordinate (in units declared at inception of PDF document) against upper edge of the page.
2982       * @param {number} x3 Coordinate (in units declared at inception of PDF document) against left edge of the page.
2983       * @param {number} y3 Coordinate (in units declared at inception of PDF document) against upper edge of the page.
2984       * @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.
2985       * @function
2986       * @instance
2987       * @returns {jsPDF}
2988       * @memberOf jsPDF
2989       * @name triangle
2990       */
2991
2992
2993      var triangle = API.__private__.triangle = API.triangle = function (x1, y1, x2, y2, x3, y3, style) {
2994        if (isNaN(x1) || isNaN(y1) || isNaN(x2) || isNaN(y2) || isNaN(x3) || isNaN(y3) || !isValidStyle(style)) {
2995          throw new Error('Invalid arguments passed to jsPDF.triangle');
2996        }
2997
2998        this.lines([[x2 - x1, y2 - y1], // vector to point 2
2999        [x3 - x2, y3 - y2], // vector to point 3
3000        [x1 - x3, y1 - y3] // closing vector back to point 1
3001        ], x1, y1, // start of path
3002        [1, 1], style, true);
3003        return this;
3004      };
3005      /**
3006       * Adds a rectangle with rounded corners to PDF.
3007       *
3008       * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page.
3009       * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page.
3010       * @param {number} w Width (in units declared at inception of PDF document).
3011       * @param {number} h Height (in units declared at inception of PDF document).
3012       * @param {number} rx Radius along x axis (in units declared at inception of PDF document).
3013       * @param {number} ry Radius along y axis (in units declared at inception of PDF document).
3014       * @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.
3015       * @function
3016       * @instance
3017       * @returns {jsPDF}
3018       * @memberOf jsPDF
3019       * @name roundedRect
3020       */
3021
3022
3023      var roundedRect = API.__private__.roundedRect = API.roundedRect = function (x, y, w, h, rx, ry, style) {
3024        if (isNaN(x) || isNaN(y) || isNaN(w) || isNaN(h) || isNaN(rx) || isNaN(ry) || !isValidStyle(style)) {
3025          throw new Error('Invalid arguments passed to jsPDF.roundedRect');
3026        }
3027
3028        var MyArc = 4 / 3 * (Math.SQRT2 - 1);
3029        this.lines([[w - 2 * rx, 0], [rx * MyArc, 0, rx, ry - ry * MyArc, rx, ry], [0, h - 2 * ry], [0, ry * MyArc, -(rx * MyArc), ry, -rx, ry], [-w + 2 * rx, 0], [-(rx * MyArc), 0, -rx, -(ry * MyArc), -rx, -ry], [0, -h + 2 * ry], [0, -(ry * MyArc), rx * MyArc, -ry, rx, -ry]], x + rx, y, // start of path
3030        [1, 1], style);
3031        return this;
3032      };
3033      /**
3034       * Adds an ellipse to PDF.
3035       *
3036       * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page.
3037       * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page.
3038       * @param {number} rx Radius along x axis (in units declared at inception of PDF document).
3039       * @param {number} ry Radius along y axis (in units declared at inception of PDF document).
3040       * @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.
3041       * @function
3042       * @instance
3043       * @returns {jsPDF}
3044       * @memberOf jsPDF
3045       * @name ellipse
3046       */
3047
3048
3049      var ellise = API.__private__.ellipse = API.ellipse = function (x, y, rx, ry, style) {
3050        if (isNaN(x) || isNaN(y) || isNaN(rx) || isNaN(ry) || !isValidStyle(style)) {
3051          throw new Error('Invalid arguments passed to jsPDF.ellipse');
3052        }
3053
3054        var lx = 4 / 3 * (Math.SQRT2 - 1) * rx,
3055            ly = 4 / 3 * (Math.SQRT2 - 1) * ry;
3056        out([f2(getHorizontalCoordinate(x + rx)), f2(getVerticalCoordinate(y)), 'm', f2(getHorizontalCoordinate(x + rx)), f2(getVerticalCoordinate(y - ly)), f2(getHorizontalCoordinate(x + lx)), f2(getVerticalCoordinate(y - ry)), f2(getHorizontalCoordinate(x)), f2(getVerticalCoordinate(y - ry)), 'c'].join(' '));
3057        out([f2(getHorizontalCoordinate(x - lx)), f2(getVerticalCoordinate(y - ry)), f2(getHorizontalCoordinate(x - rx)), f2(getVerticalCoordinate(y - ly)), f2(getHorizontalCoordinate(x - rx)), f2(getVerticalCoordinate(y)), 'c'].join(' '));
3058        out([f2(getHorizontalCoordinate(x - rx)), f2(getVerticalCoordinate(y + ly)), f2(getHorizontalCoordinate(x - lx)), f2(getVerticalCoordinate(y + ry)), f2(getHorizontalCoordinate(x)), f2(getVerticalCoordinate(y + ry)), 'c'].join(' '));
3059        out([f2(getHorizontalCoordinate(x + lx)), f2(getVerticalCoordinate(y + ry)), f2(getHorizontalCoordinate(x + rx)), f2(getVerticalCoordinate(y + ly)), f2(getHorizontalCoordinate(x + rx)), f2(getVerticalCoordinate(y)), 'c'].join(' '));
3060
3061        if (style !== null) {
3062          out(getStyle(style));
3063        }
3064
3065        return this;
3066      };
3067      /**
3068       * Adds an circle to PDF.
3069       *
3070       * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page.
3071       * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page.
3072       * @param {number} r Radius (in units declared at inception of PDF document).
3073       * @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.
3074       * @function
3075       * @instance
3076       * @returns {jsPDF}
3077       * @memberOf jsPDF
3078       * @name circle
3079       */
3080
3081
3082      var circle = API.__private__.circle = API.circle = function (x, y, r, style) {
3083        if (isNaN(x) || isNaN(y) || isNaN(r) || !isValidStyle(style)) {
3084          throw new Error('Invalid arguments passed to jsPDF.circle');
3085        }
3086
3087        return this.ellipse(x, y, r, r, style);
3088      };
3089      /**
3090       * Sets text font face, variant for upcoming text elements.
3091       * See output of jsPDF.getFontList() for possible font names, styles.
3092       *
3093       * @param {string} fontName Font name or family. Example: "times".
3094       * @param {string} fontStyle Font style or variant. Example: "italic".
3095       * @function
3096       * @instance
3097       * @returns {jsPDF}
3098       * @memberOf jsPDF
3099       * @name setFont
3100       */
3101
3102
3103      API.setFont = function (fontName, fontStyle) {
3104        activeFontKey = _getFont(fontName, fontStyle, {
3105          disableWarning: false
3106        });
3107        return this;
3108      };
3109      /**
3110       * Switches font style or variant for upcoming text elements,
3111       * while keeping the font face or family same.
3112       * See output of jsPDF.getFontList() for possible font names, styles.
3113       *
3114       * @param {string} style Font style or variant. Example: "italic".
3115       * @function
3116       * @instance
3117       * @returns {jsPDF}
3118       * @memberOf jsPDF
3119       * @name setFontStyle
3120       */
3121
3122
3123      API.setFontStyle = API.setFontType = function (style) {
3124        activeFontKey = _getFont(undefined, style); // if font is not found, the above line blows up and we never go further
3125
3126        return this;
3127      };
3128      /**
3129       * Returns an object - a tree of fontName to fontStyle relationships available to
3130       * active PDF document.
3131       *
3132       * @public
3133       * @function
3134       * @instance
3135       * @returns {Object} Like {'times':['normal', 'italic', ... ], 'arial':['normal', 'bold', ... ], ... }
3136       * @memberOf jsPDF
3137       * @name getFontList
3138       */
3139
3140
3141      var getFontList = API.__private__.getFontList = API.getFontList = function () {
3142        // TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added.
3143        var list = {},
3144            fontName,
3145            fontStyle,
3146            tmp;
3147
3148        for (fontName in fontmap) {
3149          if (fontmap.hasOwnProperty(fontName)) {
3150            list[fontName] = tmp = [];
3151
3152            for (fontStyle in fontmap[fontName]) {
3153              if (fontmap[fontName].hasOwnProperty(fontStyle)) {
3154                tmp.push(fontStyle);
3155              }
3156            }
3157          }
3158        }
3159
3160        return list;
3161      };
3162      /**
3163       * Add a custom font to the current instance.
3164       *
3165       * @property {string} postScriptName PDF specification full name for the font.
3166       * @property {string} id PDF-document-instance-specific label assinged to the font.
3167       * @property {string} fontStyle Style of the Font.
3168       * @property {Object} encoding Encoding_name-to-Font_metrics_object mapping.
3169       * @function
3170       * @instance
3171       * @memberOf jsPDF
3172       * @name addFont
3173       */
3174
3175
3176      API.addFont = function (postScriptName, fontName, fontStyle, encoding) {
3177        encoding = encoding || 'Identity-H';
3178        addFont.call(this, postScriptName, fontName, fontStyle, encoding);
3179      };
3180
3181      var lineWidth = options.lineWidth || 0.200025; // 2mm
3182
3183      /**
3184       * Sets line width for upcoming lines.
3185       *
3186       * @param {number} width Line width (in units declared at inception of PDF document).
3187       * @function
3188       * @instance
3189       * @returns {jsPDF}
3190       * @memberOf jsPDF
3191       * @name setLineWidth
3192       */
3193
3194      var setLineWidth = API.__private__.setLineWidth = API.setLineWidth = function (width) {
3195        out((width * k).toFixed(2) + ' w');
3196        return this;
3197      };
3198      /**
3199       * Sets the dash pattern for upcoming lines.
3200       * 
3201       * To reset the settings simply call the method without any parameters.
3202       * @param {array} dashArray The pattern of the line, expects numbers. 
3203       * @param {number} dashPhase The phase at which the dash pattern starts.
3204       * @function
3205       * @instance
3206       * @returns {jsPDF}
3207       * @memberOf jsPDF
3208       * @name setLineDash
3209       */
3210
3211
3212      var setLineDash = API.__private__.setLineDash = jsPDF.API.setLineDash = function (dashArray, dashPhase) {
3213        dashArray = dashArray || [];
3214        dashPhase = dashPhase || 0;
3215
3216        if (isNaN(dashPhase) || !Array.isArray(dashArray)) {
3217          throw new Error('Invalid arguments passed to jsPDF.setLineDash');
3218        }
3219
3220        dashArray = dashArray.map(function (x) {
3221          return (x * k).toFixed(3);
3222        }).join(' ');
3223        dashPhase = parseFloat((dashPhase * k).toFixed(3));
3224        out('[' + dashArray + '] ' + dashPhase + ' d');
3225        return this;
3226      };
3227
3228      var lineHeightFactor;
3229
3230      var getLineHeight = API.__private__.getLineHeight = API.getLineHeight = function () {
3231        return activeFontSize * lineHeightFactor;
3232      };
3233
3234      var lineHeightFactor;
3235
3236      var getLineHeight = API.__private__.getLineHeight = API.getLineHeight = function () {
3237        return activeFontSize * lineHeightFactor;
3238      };
3239      /**
3240       * Sets the LineHeightFactor of proportion.
3241       *
3242       * @param {number} value LineHeightFactor value. Default: 1.15.
3243       * @function
3244       * @instance
3245       * @returns {jsPDF}
3246       * @memberOf jsPDF
3247       * @name setLineHeightFactor
3248       */
3249
3250
3251      var setLineHeightFactor = API.__private__.setLineHeightFactor = API.setLineHeightFactor = function (value) {
3252        value = value || 1.15;
3253
3254        if (typeof value === "number") {
3255          lineHeightFactor = value;
3256        }
3257
3258        return this;
3259      };
3260      /**
3261       * Gets the LineHeightFactor, default: 1.15.
3262       *
3263       * @function
3264       * @instance
3265       * @returns {number} lineHeightFactor
3266       * @memberOf jsPDF
3267       * @name getLineHeightFactor
3268       */
3269
3270
3271      var getLineHeightFactor = API.__private__.getLineHeightFactor = API.getLineHeightFactor = function () {
3272        return lineHeightFactor;
3273      };
3274
3275      setLineHeightFactor(options.lineHeight);
3276
3277      var getHorizontalCoordinate = API.__private__.getHorizontalCoordinate = function (value) {
3278        return value * k;
3279      };
3280
3281      var getVerticalCoordinate = API.__private__.getVerticalCoordinate = function (value) {
3282        return pagesContext[currentPage].mediaBox.topRightY - pagesContext[currentPage].mediaBox.bottomLeftY - value * k;
3283      };
3284
3285      var getHorizontalCoordinateString = API.__private__.getHorizontalCoordinateString = function (value) {
3286        return f2(value * k);
3287      };
3288
3289      var getVerticalCoordinateString = API.__private__.getVerticalCoordinateString = function (value) {
3290        return f2(pagesContext[currentPage].mediaBox.topRightY - pagesContext[currentPage].mediaBox.bottomLeftY - value * k);
3291      };
3292
3293      var strokeColor = options.strokeColor || '0 G';
3294      /**
3295       *  Gets the stroke color for upcoming elements.
3296       *
3297       * @function
3298       * @instance
3299       * @returns {string} colorAsHex
3300       * @memberOf jsPDF
3301       * @name getDrawColor
3302       */
3303
3304      var getStrokeColor = API.__private__.getStrokeColor = API.getDrawColor = function () {
3305        return decodeColorString(strokeColor);
3306      };
3307      /**
3308       * Sets the stroke color for upcoming elements.
3309       *
3310       * Depending on the number of arguments given, Gray, RGB, or CMYK
3311       * color space is implied.
3312       *
3313       * When only ch1 is given, "Gray" color space is implied and it
3314       * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
3315       * if values are communicated as String types, or in range from 0 (black)
3316       * to 255 (white) if communicated as Number type.
3317       * The RGB-like 0-255 range is provided for backward compatibility.
3318       *
3319       * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
3320       * value must be in the range from 0.00 (minimum intensity) to to 1.00
3321       * (max intensity) if values are communicated as String types, or
3322       * from 0 (min intensity) to to 255 (max intensity) if values are communicated
3323       * as Number types.
3324       * The RGB-like 0-255 range is provided for backward compatibility.
3325       *
3326       * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
3327       * value must be a in the range from 0.00 (0% concentration) to to
3328       * 1.00 (100% concentration)
3329       *
3330       * Because JavaScript treats fixed point numbers badly (rounds to
3331       * floating point nearest to binary representation) it is highly advised to
3332       * communicate the fractional numbers as String types, not JavaScript Number type.
3333       *
3334       * @param {Number|String} ch1 Color channel value or {string}
3334 ch1 color value in hexadecimal, example: '#FFFFFF'.
3335       * @param {Number|String} ch2 Color channel value.
3336       * @param {Number|String} ch3 Color channel value.
3337       * @param {Number|String} ch4 Color channel value.
3338       *
3339       * @function
3340       * @instance
3341       * @returns {jsPDF}
3342       * @memberOf jsPDF
3343       * @name setDrawColor
3344       */
3345
3346
3347      var setStrokeColor = API.__private__.setStrokeColor = API.setDrawColor = function (ch1, ch2, ch3, ch4) {
3348        var options = {
3349          "ch1": ch1,
3350          "ch2": ch2,
3351          "ch3": ch3,
3352          "ch4": ch4,
3353          "pdfColorType": "draw",
3354          "precision": 2
3355        };
3356        strokeColor = encodeColorString(options);
3357        out(strokeColor);
3358        return this;
3359      };
3360
3361      var fillColor = options.fillColor || '0 g';
3362      /**
3363       * Gets the fill color for upcoming elements.
3364       *
3365       * @function
3366       * @instance
3367       * @returns {string} colorAsHex
3368       * @memberOf jsPDF
3369       * @name getFillColor
3370       */
3371
3372      var getFillColor = API.__private__.getFillColor = API.getFillColor = function () {
3373        return decodeColorString(fillColor);
3374      };
3375      /**
3376       * Sets the fill color for upcoming elements.
3377       *
3378       * Depending on the number of arguments given, Gray, RGB, or CMYK
3379       * color space is implied.
3380       *
3381       * When only ch1 is given, "Gray" color space is implied and it
3382       * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
3383       * if values are communicated as String types, or in range from 0 (black)
3384       * to 255 (white) if communicated as Number type.
3385       * The RGB-like 0-255 range is provided for backward compatibility.
3386       *
3387       * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
3388       * value must be in the range from 0.00 (minimum intensity) to to 1.00
3389       * (max intensity) if values are communicated as String types, or
3390       * from 0 (min intensity) to to 255 (max intensity) if values are communicated
3391       * as Number types.
3392       * The RGB-like 0-255 range is provided for backward compatibility.
3393       *
3394       * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
3395       * value must be a in the range from 0.00 (0% concentration) to to
3396       * 1.00 (100% concentration)
3397       *
3398       * Because JavaScript treats fixed point numbers badly (rounds to
3399       * floating point nearest to binary representation) it is highly advised to
3400       * communicate the fractional numbers as String types, not JavaScript Number type.
3401       *
3402       * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF'.
3403       * @param {Number|String} ch2 Color channel value.
3404       * @param {Number|String} ch3 Color channel value.
3405       * @param {Number|String} ch4 Color channel value.
3406       *
3407       * @function
3408       * @instance
3409       * @returns {jsPDF}
3410       * @memberOf jsPDF
3411       * @name setFillColor
3412       */
3413
3414
3415      var setFillColor = API.__private__.setFillColor = API.setFillColor = function (ch1, ch2, ch3, ch4) {
3416        var options = {
3417          "ch1": ch1,
3418          "ch2": ch2,
3419          "ch3": ch3,
3420          "ch4": ch4,
3421          "pdfColorType": "fill",
3422          "precision": 2
3423        };
3424        fillColor = encodeColorString(options);
3425        out(fillColor);
3426        return this;
3427      };
3428
3429      var textColor = options.textColor || '0 g';
3430      /**
3431       * Gets the text color for upcoming elements.
3432       *
3433       * @function
3434       * @instance
3435       * @returns {string} colorAsHex
3436       * @memberOf jsPDF
3437       * @name getTextColor
3438       */
3439
3440      var getTextColor = API.__private__.getTextColor = API.getTextColor = function () {
3441        return decodeColorString(textColor);
3442      };
3443      /**
3444       * Sets the text color for upcoming elements.
3445       *
3446       * Depending on the number of arguments given, Gray, RGB, or CMYK
3447       * color space is implied.
3448       *
3449       * When only ch1 is given, "Gray" color space is implied and it
3450       * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
3451       * if values are communicated as String types, or in range from 0 (black)
3452       * to 255 (white) if communicated as Number type.
3453       * The RGB-like 0-255 range is provided for backward compatibility.
3454       *
3455       * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
3456       * value must be in the range from 0.00 (minimum intensity) to to 1.00
3457       * (max intensity) if values are communicated as String types, or
3458       * from 0 (min intensity) to to 255 (max intensity) if values are communicated
3459       * as Number types.
3460       * The RGB-like 0-255 range is provided for backward compatibility.
3461       *
3462       * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
3463       * value must be a in the range from 0.00 (0% concentration) to to
3464       * 1.00 (100% concentration)
3465       *
3466       * Because JavaScript treats fixed point numbers badly (rounds to
3467       * floating point nearest to binary representation) it is highly advised to
3468       * communicate the fractional numbers as String types, not JavaScript Number type.
3469       *
3470       * @param {Number|String} ch1 Color channel value or {string}
3470 ch1 color value in hexadecimal, example: '#FFFFFF'.
3471       * @param {Number|String} ch2 Color channel value.
3472       * @param {Number|String} ch3 Color channel value.
3473       * @param {Number|String} ch4 Color channel value.
3474       *
3475       * @function
3476       * @instance
3477       * @returns {jsPDF}
3478       * @memberOf jsPDF
3479       * @name setTextColor
3480       */
3481
3482
3483      var setTextColor = API.__private__.setTextColor = API.setTextColor = function (ch1, ch2, ch3, ch4) {
3484        var options = {
3485          "ch1": ch1,
3486          "ch2": ch2,
3487          "ch3": ch3,
3488          "ch4": ch4,
3489          "pdfColorType": "text",
3490          "precision": 3
3491        };
3492        textColor = encodeColorString(options);
3493        return this;
3494      };
3495
3496      var activeCharSpace = options.charSpace || 0;
3497      /**
3498       * Get global value of CharSpace.
3499       *
3500       * @function
3501       * @instance
3502       * @returns {number} charSpace
3503       * @memberOf jsPDF
3504       * @name getCharSpace
3505       */
3506
3507      var getCharSpace = API.__private__.getCharSpace = API.getCharSpace = function () {
3508        return activeCharSpace;
3509      };
3510      /**
3511       * Set global value of CharSpace.
3512       *
3513       * @param {number} charSpace
3514       * @function
3515       * @instance
3516       * @returns {jsPDF} jsPDF-instance
3517       * @memberOf jsPDF
3518       * @name setCharSpace
3519       */
3520
3521
3522      var setCharSpace = API.__private__.setCharSpace = API.setCharSpace = function (charSpace) {
3523        if (isNaN(charSpace)) {
3524          throw new Error('Invalid argument passed to jsPDF.setCharSpace');
3525        }
3526
3527        activeCharSpace = charSpace;
3528        return this;
3529      };
3530
3531      var lineCapID = 0;
3532      /**
3533       * Is an Object providing a mapping from human-readable to
3534       * integer flag values designating the varieties of line cap
3535       * and join styles.
3536       *
3537       * @memberOf jsPDF
3538       * @name CapJoinStyles
3539       */
3540
3541      API.CapJoinStyles = {
3542        0: 0,
3543        'butt': 0,
3544        'but': 0,
3545        'miter': 0,
3546        1: 1,
3547        'round': 1,
3548        'rounded': 1,
3549        'circle': 1,
3550        2: 2,
3551        'projecting': 2,
3552        'project': 2,
3553        'square': 2,
3554        'bevel': 2
3555      };
3556      /**
3557       * Sets the line cap styles.
3558       * See {jsPDF.CapJoinStyles} for variants.
3559       *
3560       * @param {String|Number} style A string or number identifying the type of line cap.
3561       * @function
3562       * @instance
3563       * @returns {jsPDF}
3564       * @memberOf jsPDF
3565       * @name setLineCap
3566       */
3567
3568      var setLineCap = API.__private__.setLineCap = API.setLineCap = function (style) {
3569        var id = API.CapJoinStyles[style];
3570
3571        if (id === undefined) {
3572          throw new Error("Line cap style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
3573        }
3574
3575        lineCapID = id;
3576        out(id + ' J');
3577        return this;
3578      };
3579
3580      var lineJoinID = 0;
3581      /**
3582       * Sets the line join styles.
3583       * See {jsPDF.CapJoinStyles} for variants.
3584       *
3585       * @param {String|Number} style A string or number identifying the type of line join.
3586       * @function
3587       * @instance
3588       * @returns {jsPDF}
3589       * @memberOf jsPDF
3590       * @name setLineJoin
3591       */
3592
3593      var setLineJoin = API.__private__.setLineJoin = API.setLineJoin = function (style) {
3594        var id = API.CapJoinStyles[style];
3595
3596        if (id === undefined) {
3597          throw new Error("Line join style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
3598        }
3599
3600        lineJoinID = id;
3601        out(id + ' j');
3602        return this;
3603      };
3604
3605      var miterLimit;
3606      /**
3607       * Sets the miterLimit property, which effects the maximum miter length.
3608       *
3609       * @param {number} length The length of the miter
3610       * @function
3611       * @instance
3612       * @returns {jsPDF}
3613       * @memberOf jsPDF
3614       * @name setMiterLimit
3615       */
3616
3617      var setMiterLimit = API.__private__.setMiterLimit = API.setMiterLimit = function (length) {
3618        length = length || 0;
3619
3620        if (isNaN(length)) {
3621          throw new Error('Invalid argument passed to jsPDF.setMiterLimit');
3622        }
3623
3624        miterLimit = parseFloat(f2(length * k));
3625        out(miterLimit + ' M');
3626        return this;
3627      };
3628      /**
3629       * Saves as PDF document. An alias of jsPDF.output('save', 'filename.pdf').
3630       * Uses FileSaver.js-method saveAs.
3631       *
3632       * @memberOf jsPDF
3633       * @name save
3634       * @function
3635       * @instance
3636       * @param  {string} filename The filename including extension.
3637       * @param  {Object} options An Object with additional options, possible options: 'returnPromise'.
3638       * @returns {jsPDF} jsPDF-instance
3639       */
3640
3641
3642      API.save = function (filename, options) {
3643        filename = filename || 'generated.pdf';
3644        options = options || {};
3645        options.returnPromise = options.returnPromise || false;
3646
3647        if (options.returnPromise === false) {
3648          saveAs(getBlob(buildDocument()), filename);
3649
3650          if (typeof saveAs.unload === 'function') {
3651            if (global.setTimeout) {
3652              setTimeout(saveAs.unload, 911);
3653            }
3654          }
3655        } else {
3656          return new Promise(function (resolve, reject) {
3657            try {
3658              var result = saveAs(getBlob(buildDocument()), filename);
3659
3660              if (typeof saveAs.unload === 'function') {
3661                if (global.setTimeout) {
3662                  setTimeout(saveAs.unload, 911);
3663                }
3664              }
3665
3666              resolve(result);
3667            } catch (e) {
3668              reject(e.message);
3669            }
3670          });
3671        }
3672      }; // applying plugins (more methods) ON TOP of built-in API.
3673      // this is intentional as we allow plugins to override
3674      // built-ins
3675
3676
3677      for (var plugin in jsPDF.API) {
3678        if (jsPDF.API.hasOwnProperty(plugin)) {
3679          if (plugin === 'events' && jsPDF.API.events.length) {
3680            (function (events, newEvents) {
3681              // jsPDF.API.events is a JS Array of Arrays
3682              // where each Array is a pair of event name, handler
3683              // Events were added by plugins to the jsPDF instantiator.
3684              // These are always added to the new instance and some ran
3685              // during instantiation.
3686              var eventname, handler_and_args, i;
3687
3688              for (i = newEvents.length - 1; i !== -1; i--) {
3689                // subscribe takes 3 args: 'topic', function, runonce_flag
3690                // if undefined, runonce is false.
3691                // users can attach callback directly,
3692                // or they can attach an array with [callback, runonce_flag]
3693                // that's what the "apply" magic is for below.
3694                eventname = newEvents[i][0];
3695                handler_and_args = newEvents[i][1];
3696                events.subscribe.apply(events, [eventname].concat(typeof handler_and_args === 'function' ? [handler_and_args] : handler_and_args));
3697              }
3698            })(events, jsPDF.API.events);
3699          } else {
3700            API[plugin] = jsPDF.API[plugin];
3701          }
3702        }
3703      }
3704      /**
3705       * Object exposing internal API to plugins
3706       * @public
3707       * @ignore
3708       */
3709
3710
3711      API.internal = {
3712        'pdfEscape': pdfEscape,
3713        'getStyle': getStyle,
3714        'getFont': function getFont() {
3715          return fonts[_getFont.apply(API, arguments)];
3716        },
3717        'getFontSize': getFontSize,
3718        'getCharSpace': getCharSpace,
3719        'getTextColor': getTextColor,
3720        'getLineHeight': getLineHeight,
3721        'getLineHeightFactor': getLineHeightFactor,
3722        'write': write,
3723        'getHorizontalCoordinate': getHorizontalCoordinate,
3724        'getVerticalCoordinate': getVerticalCoordinate,
3725        'getCoordinateString': getHorizontalCoordinateString,
3726        'getVerticalCoordinateString': getVerticalCoordinateString,
3727        'collections': {},
3728        'newObject': newObject,
3729        'newAdditionalObject': newAdditionalObject,
3730        'newObjectDeferred': newObjectDeferred,
3731        'newObjectDeferredBegin': newObjectDeferredBegin,
3732        'getFilters': getFilters,
3733        'putStream': putStream,
3734        'events': events,
3735        // ratio that you use in multiplication of a given "size" number to arrive to 'point'
3736        // units of measurement.
3737        // scaleFactor is set at initialization of the document and calculated against the stated
3738        // default measurement units for the document.
3739        // If default is "mm", k is the number that will turn number in 'mm' into 'points' number.
3740        // through multiplication.
3741        'scaleFactor': k,
3742        'pageSize': {
3743          getWidth: function getWidth() {
3744            return (pagesContext[currentPage].mediaBox.topRightX - pagesContext[currentPage].mediaBox.bottomLeftX) / k;
3745          },
3746          setWidth: function setWidth(value) {
3747            pagesContext[currentPage].mediaBox.topRightX = value * k + pagesContext[currentPage].mediaBox.bottomLeftX;
3748          },
3749          getHeight: function getHeight() {
3750            return (pagesContext[currentPage].mediaBox.topRightY - pagesContext[currentPage].mediaBox.bottomLeftY) / k;
3751          },
3752          setHeight: function setHeight(value) {
3753            pagesContext[currentPage].mediaBox.topRightY = value * k + pagesContext[currentPage].mediaBox.bottomLeftY;
3754          }
3755        },
3756        'output': output,
3757        'getNumberOfPages': getNumberOfPages,
3758        'pages': pages,
3759        'out': out,
3760        'f2': f2,
3761        'f3': f3,
3762        'getPageInfo': getPageInfo,
3763        'getPageInfoByObjId': getPageInfoByObjId,
3764        'getCurrentPageInfo': getCurrentPageInfo,
3765        'getPDFVersion': getPdfVersion,
3766        'hasHotfix': hasHotfix //Expose the hasHotfix check so plugins can also check them.
3767
3768      };
3769      Object.defineProperty(API.internal.pageSize, 'width', {
3770        get: function get() {
3771          return (pagesContext[currentPage].mediaBox.topRightX - pagesContext[currentPage].mediaBox.bottomLeftX) / k;
3772        },
3773        set: function set(value) {
3774          pagesContext[currentPage].mediaBox.topRightX = value * k + pagesContext[currentPage].mediaBox.bottomLeftX;
3775        },
3776        enumerable: true,
3777        configurable: true
3778      });
3779      Object.defineProperty(API.internal.pageSize, 'height', {
3780        get: function get() {
3781          return (pagesContext[currentPage].mediaBox.topRightY - pagesContext[currentPage].mediaBox.bottomLeftY) / k;
3782        },
3783        set: function set(value) {
3784          pagesContext[currentPage].mediaBox.topRightY = value * k + pagesContext[currentPage].mediaBox.bottomLeftY;
3785        },
3786        enumerable: true,
3787        configurable: true
3788      }); //////////////////////////////////////////////////////
3789      // continuing initialization of jsPDF Document object
3790      //////////////////////////////////////////////////////
3791      // Add the first page automatically
3792
3793      addFonts(standardFonts);
3794      activeFontKey = 'F1';
3795
3796      _addPage(format, orientation);
3797
3798      events.publish('initialized');
3799      return API;
3800    }
3801    /**
3802     * jsPDF.API is a STATIC property of jsPDF class.
3803     * jsPDF.API is an object you can add methods and properties to.
3804     * The methods / properties you add will show up in new jsPDF objects.
3805     *
3806     * One property is prepopulated. It is the 'events' Object. Plugin authors can add topics,
3807     * callbacks to this object. These will be reassigned to all new instances of jsPDF.
3808     *
3809     * @static
3810     * @public
3811     * @memberOf jsPDF
3812     * @name API
3813     *
3814     * @example
3815     * jsPDF.API.mymethod = function(){
3816     *   // 'this' will be ref to internal API object. see jsPDF source
3817     *   // , so you can refer to built-in methods like so:
3818     *   //     this.line(....)
3819     *   //     this.text(....)
3820     * }
3821     * var pdfdoc = new jsPDF()
3822     * pdfdoc.mymethod() // <- !!!!!!
3823     */
3824
3825
3826    jsPDF.API = {
3827      events: []
3828    };
3829    /**
3830     * The version of jsPDF.
3831     * @name version
3832     * @type {string}
3833     * @memberOf jsPDF
3834     */
3835
3836    jsPDF.version = '1.5.3';
3837
3838    if (typeof define === 'function' && define.amd) {
3839      define('jsPDF', function () {
3840        return jsPDF;
3841      });
3842    } else if (typeof module !== 'undefined' && module.exports) {
3843      module.exports = jsPDF;
3844      module.exports.jsPDF = jsPDF;
3845    } else {
3846      global.jsPDF = jsPDF;
3847    }
3848
3849    return jsPDF;
3850  }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function('return this')()); // `self` is undefined in Firefox for Android content script context
3851  // while `this` is nsIContentFrameMessageManager
3852  // with an attribute `content` that corresponds to the window
3853
3854  /*rollup-keeper-start*/
3855
3856
3857  window.tmp = jsPDF;
3858  /*rollup-keeper-end*/
3859
3860  /**
3861   * @license
3862   * Copyright (c) 2016 Alexander Weidt,
3863   * https://github.com/BiggA94
3864   * 
3865   * Licensed under the MIT License. http://opensource.org/licenses/mit-license
3866   */
3867
3868  /** 
3869  * jsPDF AcroForm Plugin
3870  * @module AcroForm
3871  */
3872  (function (jsPDFAPI, globalObj) {
3873
3874    var scope;
3875    var scaleFactor = 1;
3876
3877    var pdfEscape = function pdfEscape(value) {
3878      return value.replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
3879    };
3880
3881    var pdfUnescape = function pdfUnescape(value) {
3882      return value.replace(/\\\\/g, '\\').replace(/\\\(/g, '(').replace(/\\\)/g, ')');
3883    };
3884
3885    var f2 = function f2(number) {
3886      if (isNaN(number)) {
3887        throw new Error('Invalid argument passed to jsPDF.f2');
3888      }
3889
3890      return number.toFixed(2); // Ie, %.2f
3891    };
3892
3893    var f5 = function f5(number) {
3894      if (isNaN(number)) {
3895        throw new Error('Invalid argument passed to jsPDF.f2');
3896      }
3897
3898      return number.toFixed(5); // Ie, %.2f
3899    };
3900
3901    jsPDFAPI.__acroform__ = {};
3902
3903    var inherit = function inherit(child, parent) {
3904
3905      child.prototype = Object.create(parent.prototype);
3906      child.prototype.constructor = child;
3907    };
3908
3909    var scale = function scale(x) {
3910      return x * scaleFactor;
3911    };
3912
3913    var antiScale = function antiScale(x) {
3914      return x / scaleFactor;
3915    };
3916
3917    var createFormXObject = function createFormXObject(formObject) {
3918      var xobj = new AcroFormXObject();
3919      var height = AcroFormAppearance.internal.getHeight(formObject) || 0;
3920      var width = AcroFormAppearance.internal.getWidth(formObject) || 0;
3921      xobj.BBox = [0, 0, Number(f2(width)), Number(f2(height))];
3922      return xobj;
3923    };
3924    /**
3925    * Bit-Operations
3926    */
3927
3928
3929    var setBit = jsPDFAPI.__acroform__.setBit = function (number, bitPosition) {
3930      number = number || 0;
3931      bitPosition = bitPosition || 0;
3932
3933      if (isNaN(number) || isNaN(bitPosition)) {
3934        throw new Error('Invalid arguments passed to jsPDF.API.__acroform__.setBit');
3935      }
3936
3937      var bitMask = 1 << bitPosition;
3938      number |= bitMask;
3939      return number;
3940    };
3941
3942    var clearBit = jsPDFAPI.__acroform__.clearBit = function (number, bitPosition) {
3943      number = number || 0;
3944      bitPosition = bitPosition || 0;
3945
3946      if (isNaN(number) || isNaN(bitPosition)) {
vendor: 4,078 bytes, lines 3947-4057
3947        throw new Error('Invalid arguments passed to jsPDF.API.__acroform__.clearBit');
3948      }
3949
3950      var bitMask = 1 << bitPosition;
3951      number &= ~bitMask;
3952      return number;
3953    };
3954
3955    var getBit = jsPDFAPI.__acroform__.getBit = function (number, bitPosition) {
3956      if (isNaN(number) || isNaN(bitPosition)) {
3957        throw new Error('Invalid arguments passed to jsPDF.API.__acroform__.getBit');
3958      }
3959
3960      return (number & 1 << bitPosition) === 0 ? 0 : 1;
3961    };
3962    /*
3963    * Ff starts counting the bit position at 1 and not like javascript at 0
3964    */
3965
3966
3967    var getBitForPdf = jsPDFAPI.__acroform__.getBitForPdf = function (number, bitPosition) {
3968      if (isNaN(number) || isNaN(bitPosition)) {
3969        throw new Error('Invalid arguments passed to jsPDF.API.__acroform__.getBitForPdf');
3970      }
3971
3972      return getBit(number, bitPosition - 1);
3973    };
3974
3975    var setBitForPdf = jsPDFAPI.__acroform__.setBitForPdf = function (number, bitPosition) {
3976      if (isNaN(number) || isNaN(bitPosition)) {
3977        throw new Error('Invalid arguments passed to jsPDF.API.__acroform__.setBitForPdf');
3978      }
3979
3980      return setBit(number, bitPosition - 1);
3981    };
3982
3983    var clearBitForPdf = jsPDFAPI.__acroform__.clearBitForPdf = function (number, bitPosition, value) {
3984      if (isNaN(number) || isNaN(bitPosition)) {
3985        throw new Error('Invalid arguments passed to jsPDF.API.__acroform__.clearBitForPdf');
3986      }
3987
3988      return clearBit(number, bitPosition - 1);
3989    };
3990
3991    var calculateCoordinates = jsPDFAPI.__acroform__.calculateCoordinates = function (args) {
3992      var getHorizontalCoordinate = this.internal.getHorizontalCoordinate;
3993      var getVerticalCoordinate = this.internal.getVerticalCoordinate;
3994      var x = args[0];
3995      var y = args[1];
3996      var w = args[2];
3997      var h = args[3];
3998      var coordinates = {};
3999      coordinates.lowerLeft_X = getHorizontalCoordinate(x) || 0;
4000      coordinates.lowerLeft_Y = getVerticalCoordinate(y + h) || 0;
4001      coordinates.upperRight_X = getHorizontalCoordinate(x + w) || 0;
4002      coordinates.upperRight_Y = getVerticalCoordinate(y) || 0;
4003      return [Number(f2(coordinates.lowerLeft_X)), Number(f2(coordinates.lowerLeft_Y)), Number(f2(coordinates.upperRight_X)), Number(f2(coordinates.upperRight_Y))];
4004    };
4005
4006    var calculateAppearanceStream = function calculateAppearanceStream(formObject) {
4007      if (formObject.appearanceStreamContent) {
4008        return formObject.appearanceStreamContent;
4009      }
4010
4011      if (!formObject.V && !formObject.DV) {
4012        return;
4013      } // else calculate it
4014
4015
4016      var stream = [];
4017      var text = formObject.V || formObject.DV;
4018      var calcRes = calculateX(formObject, text);
4019      var fontKey = scope.internal.getFont(formObject.fontName, formObject.fontStyle).id; //PDF 32000-1:2008, page 444
4020
4021      stream.push('/Tx BMC');
4022      stream.push('q');
4023      stream.push('BT'); // Begin Text
4024
4025      stream.push(scope.__private__.encodeColorString(formObject.color));
4026      stream.push('/' + fontKey + ' ' + f2(calcRes.fontSize) + ' Tf');
4027      stream.push('1 0 0 1 0 0 Tm'); // Transformation Matrix
4028
4029      stream.push(calcRes.text);
4030      stream.push('ET'); // End Text    
4031
4032      stream.push('Q');
4033      stream.push('EMC');
4034      var appearanceStreamContent = new createFormXObject(formObject);
4035      appearanceStreamContent.stream = stream.join("\n");
4036      return appearanceStreamContent;
4037    };
4038
4039    var calculateX = function calculateX(formObject, text) {
4040      var maxFontSize = formObject.maxFontSize || 12;
4041      var font = formObject.fontName;
4042      var returnValue = {
4043        text: "",
4044        fontSize: ""
4045      }; // Remove Brackets
4046
4047      text = text.substr(0, 1) == '(' ? text.substr(1) : text;
4048      text = text.substr(text.length - 1) == ')' ? text.substr(0, text.length - 1) : text; // split into array of words
4049
4050      var textSplit = text.split(' ');
4051
4052      var color = scope.__private__.encodeColorString(formObject.color);
4053
4054      var fontSize = maxFontSize; // The Starting fontSize (The Maximum)
4055
4056      var lineSpacing = 2;
4057      var borderPadding = 2;
4058      var height = AcroFormAppearance.internal.getHeight(formObject) || 0;
4059      height = height < 0 ? -height : height;
4060      var width = AcroFormAppearance.internal.getWidth(formObject) || 0;
4061      width = width < 0 ? -width : width;
4062
4063      var isSmallerThanWidth = function isSmallerThanWidth(i, lastLine, fontSize) {
4064        if (i + 1 < textSplit.length) {
4065          var tmp = lastLine + " " + textSplit[i + 1];
4066          var TextWidth = calculateFontSpace(tmp, formObject, fontSize).width;
4067          var FieldWidth = width - 2 * borderPadding;
4068          return TextWidth <= FieldWidth;
4069        } else {
4070          return false;
4071        }
4072      };
4073
4074      fontSize++;
4075
4076      FontSize: while (true) {
4077        var text = "";
4078        fontSize--;
4079        var textHeight = calculateFontSpace("3", formObject, fontSize).height;
4080        var startY = formObject.multiline ? height - fontSize : (height - textHeight) / 2;
4081        startY += lineSpacing;
4082        var startX = -borderPadding;
4083        var lastY = startY;
4084        var firstWordInLine = 0,
4085            lastWordInLine = 0;
4086        var lastLength = 0;
4087
4088        if (fontSize <= 0) {
4089          // In case, the Text doesn't fit at all
4090          fontSize = 12;
4091          text = "(...) Tj\n";
4092          text += "% Width of Text: " + calculateFontSpace(text, formObject, fontSize).width + ", FieldWidth:" + width + "\n";
4093          break;
4094        }
4095
4096        lastLength = calculateFontSpace(textSplit[0] + " ", formObject, fontSize).width;
4097        var lastLine = "";
4098        var lineCount = 0;
4099
4100        Line: for (var i in textSplit) {
4101          if (textSplit.hasOwnProperty(i)) {
4102            lastLine += textSplit[i] + " "; // Remove last blank
4103
4104            lastLine = lastLine.substr(lastLine.length - 1) == " " ? lastLine.substr(0, lastLine.length - 1) : lastLine;
4105            var key = parseInt(i);
4106            lastLength = calculateFontSpace(lastLine + " ", formObject, fontSize).width;
4107            var nextLineIsSmaller = isSmallerThanWidth(key, lastLine, fontSize);
4108            var isLastWord = i >= textSplit.length - 1;
4109
4110            if (nextLineIsSmaller && !isLastWord) {
4111              lastLine += " ";
4112              continue; // Line
4113            } else if (!nextLineIsSmaller && !isLastWord) {
4114              if (!formObject.multiline) {
4115                continue FontSize;
4116              } else {
4117                if ((textHeight + lineSpacing) * (lineCount + 2) + lineSpacing > height) {
4118                  // If the Text is higher than the
4119                  // FieldObject
4120                  continue FontSize;
4121                }
4122
4123                lastWordInLine = key; // go on
4124              }
4125            } else if (isLastWord) {
4126              lastWordInLine = key;
4127            } else {
4128              if (formObject.multiline && (textHeight + lineSpacing) * (lineCount + 2) + lineSpacing > height) {
4129                // If the Text is higher than the FieldObject
4130                continue FontSize;
4131              }
4132            }
4133
4134            var line = '';
4135
4136            for (var x = firstWordInLine; x <= lastWordInLine; x++) {
4137              line += textSplit[x] + ' ';
4138            } // Remove last blank
4139
4140
4141            line = line.substr(line.length - 1) == " " ? line.substr(0, line.length - 1) : line; // lastLength -= blankSpace.width;
4142
4143            lastLength = calculateFontSpace(line, formObject, fontSize).width; // Calculate startX
4144
4145            switch (formObject.textAlign) {
4146              case 'right':
4147                startX = width - lastLength - borderPadding;
4148                break;
4149
4150              case 'center':
4151                startX = (width - lastLength) / 2;
4152                break;
4153
4154              case 'left':
4155              default:
4156                startX = borderPadding;
4157                break;
4158            }
4159
4160            text += f2(startX) + ' ' + f2(lastY) + ' Td\n';
4161            text += '(' + pdfEscape(line) + ') Tj\n'; // reset X in PDF
4162
4163            text += -f2(startX) + ' 0 Td\n'; // After a Line, adjust y position
4164
4165            lastY = -(fontSize + lineSpacing);
4166
4167            lastLength = 0;
4168            firstWordInLine = lastWordInLine + 1;
4169            lineCount++;
4170            lastLine = "";
4171            continue Line;
4172          }
4173        }
4174
4175        break;
4176      }
4177
4178      returnValue.text = text;
4179      returnValue.fontSize = fontSize;
4180      return returnValue;
4181    };
4182    /**
4183    * Small workaround for calculating the TextMetric approximately.
4184    * 
4185    * @param text
4186    * @param fontsize
4187    * @returns {TextMetrics} (Has Height and Width)
4188    */
4189
4190
4191    var calculateFontSpace = function calculateFontSpace(text, formObject, fontSize) {
4192      var font = scope.internal.getFont(formObject.fontName, formObject.fontStyle);
4193      var width = scope.getStringUnitWidth(text, {
4194        font: font,
4195        fontSize: parseFloat(fontSize),
4196        charSpace: 0
4197      }) * parseFloat(fontSize);
4198      var height = scope.getStringUnitWidth("3", {
4199        font: font,
4200        fontSize: parseFloat(fontSize),
4201        charSpace: 0
4202      }) * parseFloat(fontSize) * 1.5;
4203      return {
4204        height: height,
4205        width: width
4206      };
4207    };
4208
4209    var acroformPluginTemplate = {
4210      fields: [],
4211      xForms: [],
4212
4213      /**
4214      * acroFormDictionaryRoot contains information about the AcroForm
4215      * Dictionary 0: The Event-Token, the AcroFormDictionaryCallback has
4216      * 1: The Object ID of the Root
4217      */
4218      acroFormDictionaryRoot: null,
4219
4220      /**
4221      * After the PDF gets evaluated, the reference to the root has to be
4222      * reset, this indicates, whether the root has already been printed
4223      * out
4224      */
4225      printedOut: false,
4226      internal: null,
4227      isInitialized: false
4228    };
4229
4230    var annotReferenceCallback = function annotReferenceCallback() {
4231      //set objId to undefined and force it to get a new objId on buildDocument
4232      scope.internal.acroformPlugin.acroFormDictionaryRoot.objId = undefined;
4233      var fields = scope.internal.acroformPlugin.acroFormDictionaryRoot.Fields;
4234
4235      for (var i in fields) {
4236        if (fields.hasOwnProperty(i)) {
4237          var formObject = fields[i]; //set objId to undefined and force it to get a new objId on buildDocument
4238
4239          formObject.objId = undefined; // add Annot Reference!
4240
4241          if (formObject.hasAnnotation) {
4242            // If theres an Annotation Widget in the Form Object, put the
4243            // Reference in the /Annot array
4244            createAnnotationReference.call(scope, formObject);
4245          }
4246        }
4247      }
4248    };
4249
4250    var putForm = function putForm(formObject) {
4251      if (scope.internal.acroformPlugin.printedOut) {
4252        scope.internal.acroformPlugin.printedOut = false;
4253        scope.internal.acroformPlugin.acroFormDictionaryRoot = null;
4254      }
4255
4256      if (!scope.internal.acroformPlugin.acroFormDictionaryRoot) {
4257        initializeAcroForm.call(scope);
4258      }
4259
4260      scope.internal.acroformPlugin.acroFormDictionaryRoot.Fields.push(formObject);
4261    };
4262    /**
4263    * Create the Reference to the widgetAnnotation, so that it gets referenced
4264    * in the Annot[] int the+ (Requires the Annotation Plugin)
4265    */
4266
4267
4268    var createAnnotationReference = function createAnnotationReference(object) {
4269      var options = {
4270        type: 'reference',
4271        object: object
4272      };
4273
4274      var findEntry = function findEntry(entry) {
4275        return entry.type === options.type && entry.object === options.object;
4276      };
4277
4278      if (scope.internal.getPageInfo(object.page).pageContext.annotations.find(findEntry) === undefined) {
4279        scope.internal.getPageInfo(object.page).pageContext.annotations.push(options);
4280      }
4281    }; // Callbacks
4282
4283
4284    var putCatalogCallback = function putCatalogCallback() {
4285      // Put reference to AcroForm to DocumentCatalog
4286      if (typeof scope.internal.acroformPlugin.acroFormDictionaryRoot != 'undefined') {
4287        // for safety, shouldn't normally be the case
4288        scope.internal.write('/AcroForm ' + scope.internal.acroformPlugin.acroFormDictionaryRoot.objId + ' ' + 0 + ' R');
4289      } else {
4290        throw new Error('putCatalogCallback: Root missing.');
4291      }
4292    };
4293    /**
4294    * Adds /Acroform X 0 R to Document Catalog, and creates the AcroForm
4295    * Dictionary
4296    */
4297
4298
4299    var AcroFormDictionaryCallback = function AcroFormDictionaryCallback() {
4300      // Remove event
4301      scope.internal.events.unsubscribe(scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID);
4302      delete scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID;
4303      scope.internal.acroformPlugin.printedOut = true;
4304    };
4305    /**
4306    * Creates the single Fields and writes them into the Document
4307    * 
4308    * If fieldArray is set, use the fields that are inside it instead of the
4309    * fields from the AcroRoot (for the FormXObjects...)
4310    */
4311
4312
4313    var createFieldCallback = function createFieldCallback(fieldArray) {
4314      var standardFields = !fieldArray;
4315
4316      if (!fieldArray) {
4317        // in case there is no fieldArray specified, we want to print out
4318        // the Fields of the AcroForm
4319        // Print out Root
4320        scope.internal.newObjectDeferredBegin(scope.internal.acroformPlugin.acroFormDictionaryRoot.objId, true);
4321        scope.internal.acroformPlugin.acroFormDictionaryRoot.putStream();
4322      }
4323
4324      var fieldArray = fieldArray || scope.internal.acroformPlugin.acroFormDictionaryRoot.Kids;
4325
4326      for (var i in fieldArray) {
4327        if (fieldArray.hasOwnProperty(i)) {
4328          var fieldObject = fieldArray[i];
4329          var keyValueList = [];
4330          var oldRect = fieldObject.Rect;
4331
4332          if (fieldObject.Rect) {
4333            fieldObject.Rect = calculateCoordinates.call(this, fieldObject.Rect);
4334          } // Start Writing the Object
4335
4336
4337          scope.internal.newObjectDeferredBegin(fieldObject.objId, true);
4338          fieldObject.DA = AcroFormAppearance.createDefaultAppearanceStream(fieldObject);
4339
4340          if (_typeof(fieldObject) === "object" && typeof fieldObject.getKeyValueListForStream === "function") {
4341            keyValueList = fieldObject.getKeyValueListForStream();
4342          }
4343
4344          fieldObject.Rect = oldRect;
4345
4346          if (fieldObject.hasAppearanceStream && !fieldObject.appearanceStreamContent) {
4347            // Calculate Appearance
4348            var appearance = calculateAppearanceStream.call(this, fieldObject);
4349            keyValueList.push({
4350              key: 'AP',
4351              value: "<</N " + appearance + ">>"
4352            });
4353            scope.internal.acroformPlugin.xForms.push(appearance);
4354          } // Assume AppearanceStreamContent is a Array with N,R,D (at least
4355          // one of them!)
4356
4357
4358          if (fieldObject.appearanceStreamContent) {
4359            var appearanceStreamString = ""; // Iterate over N,R and D
4360
4361            for (var k in fieldObject.appearanceStreamContent) {
4362              if (fieldObject.appearanceStreamContent.hasOwnProperty(k)) {
4363                var value = fieldObject.appearanceStreamContent[k];
4364                appearanceStreamString += "/" + k + " ";
4365                appearanceStreamString += "<<";
4366
4367                if (Object.keys(value).length >= 1 || Array.isArray(value)) {
4368                  // appearanceStream is an Array or Object!
4369                  for (var i in value) {
4370                    if (value.hasOwnProperty(i)) {
4371                      var obj = value[i];
4372
4373                      if (typeof obj === 'function') {
4374                        // if Function is referenced, call it in order
4375                        // to get the FormXObject
4376                        obj = obj.call(this, fieldObject);
4377                      }
4378
4379                      appearanceStreamString += "/" + i + " " + obj + " "; // In case the XForm is already used, e.g. OffState
4380                      // of CheckBoxes, don't add it
4381
4382                      if (!(scope.internal.acroformPlugin.xForms.indexOf(obj) >= 0)) scope.internal.acroformPlugin.xForms.push(obj);
4383                    }
4384                  }
4385                } else {
4386                  var obj = value;
4387
4388                  if (typeof obj === 'function') {
4389                    // if Function is referenced, call it in order to
4390                    // get the FormXObject
4391                    obj = obj.call(this, fieldObject);
4392                  }
4393
4394                  appearanceStreamString += "/" + i + " " + obj;
4395                  if (!(scope.internal.acroformPlugin.xForms.indexOf(obj) >= 0)) scope.internal.acroformPlugin.xForms.push(obj);
4396                }
4397
4398                appearanceStreamString += ">>";
4399              }
4400            } // appearance stream is a normal Object..
4401
4402
4403            keyValueList.push({
4404              key: 'AP',
4405              value: "<<\n" + appearanceStreamString + ">>"
4406            });
4407          }
4408
4409          scope.internal.putStream({
4410            additionalKeyValues: keyValueList
4411          });
4412          scope.internal.out("endobj");
4413        }
4414      }
4415
4416      if (standardFields) {
4417        createXFormObjectCallback.call(this, scope.internal.acroformPlugin.xForms);
4418      }
4419    };
4420
4421    var createXFormObjectCallback = function createXFormObjectCallback(fieldArray) {
4422      for (var i in fieldArray) {
4423        if (fieldArray.hasOwnProperty(i)) {
4424          var key = i;
4425          var fieldObject = fieldArray[i]; // Start Writing the Object
4426
4427          scope.internal.newObjectDeferredBegin(fieldObject && fieldObject.objId, true);
4428
4429          if (_typeof(fieldObject) === "object" && typeof fieldObject.putStream === "function") {
4430            fieldObject.putStream();
4431          }
4432
4433          delete fieldArray[key];
4434        }
4435      }
4436    };
4437
4438    var initializeAcroForm = function initializeAcroForm() {
4439      if (this.internal !== undefined && (this.internal.acroformPlugin === undefined || this.internal.acroformPlugin.isInitialized === false)) {
4440        scope = this;
4441        AcroFormField.FieldNum = 0;
4442        this.internal.acroformPlugin = JSON.parse(JSON.stringify(acroformPluginTemplate));
4443
4444        if (this.internal.acroformPlugin.acroFormDictionaryRoot) {
4445          throw new Error("Exception while creating AcroformDictionary");
4446        }
4447
4448        scaleFactor = scope.internal.scaleFactor; // The Object Number of the AcroForm Dictionary
4449
4450        scope.internal.acroformPlugin.acroFormDictionaryRoot = new AcroFormDictionary(); // add Callback for creating the AcroForm Dictionary
4451
4452        scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID = scope.internal.events.subscribe('postPutResources', AcroFormDictionaryCallback);
4453        scope.internal.events.subscribe('buildDocument', annotReferenceCallback); // buildDocument
4454        // Register event, that is triggered when the DocumentCatalog is
4455        // written, in order to add /AcroForm
4456
4457        scope.internal.events.subscribe('putCatalog', putCatalogCallback); // Register event, that creates all Fields
4458
4459        scope.internal.events.subscribe('postPutPages', createFieldCallback);
4460        scope.internal.acroformPlugin.isInitialized = true;
4461      }
4462    }; //PDF 32000-1:2008, page 26, 7.3.6
4463
4464
4465    var arrayToPdfArray = jsPDFAPI.__acroform__.arrayToPdfArray = function (array) {
4466      if (Array.isArray(array)) {
4467        var content = '[';
4468
4469        for (var i = 0; i < array.length; i++) {
4470          if (i !== 0) {
4471            content += ' ';
4472          }
4473
4474          switch (_typeof(array[i])) {
4475            case 'boolean':
4476            case 'number':
4477            case 'object':
4478              content += array[i].toString();
4479              break;
4480
4481            case 'string':
4482              if (array[i].substr(0, 1) !== '/') {
4483                content += '(' + pdfEscape(array[i].toString()) + ')';
4484              } else {
4485                content += array[i].toString();
4486              }
4487
4488              break;
4489          }
4490        }
4491
4492        content += ']';
4493        return content;
4494      }
4495
vendor: 7,227 bytes, lines 4496-4765
4496      throw new Error('Invalid argument passed to jsPDF.__acroform__.arrayToPdfArray');
4497    };
4498
4499    function getMatches(string, regex, index) {
4500      index || (index = 1); // default to the first capturing group
4501
4502      var matches = [];
4503      var match;
4504
4505      while (match = regex.exec(string)) {
4506        matches.push(match[index]);
4507      }
4508
4509      return matches;
4510    }
4511
4512    var pdfArrayToStringArray = function pdfArrayToStringArray(array) {
4513      var result = [];
4514
4515      if (typeof array === "string") {
4516        result = getMatches(array, /\((.*?)\)/g);
4517      }
4518
4519      return result;
4520    };
4521
4522    var toPdfString = function toPdfString(string) {
4523      string = string || "";
4524      string.toString();
4525      string = '(' + pdfEscape(string) + ')';
4526      return string;
4527    }; // ##########################
4528    // Classes
4529    // ##########################
4530
4531    /**
4532    * @class AcroFormPDFObject
4533    * @classdesc A AcroFormPDFObject
4534    */
4535
4536
4537    var AcroFormPDFObject = function AcroFormPDFObject() {
4538      var _objId;
4539      /**    *
4540      * @name AcroFormPDFObject#objId
4541      * @type {any}
4542      */
4543
4544
4545      Object.defineProperty(this, 'objId', {
4546        configurable: true,
4547        get: function get() {
4548          if (!_objId) {
4549            _objId = scope.internal.newObjectDeferred();
4550          }
4551
4552          if (!_objId) {
4553            throw new Error("AcroFormPDFObject: Couldn't create Object ID");
4554          }
4555
4556          return _objId;
4557        },
4558        set: function set(value) {
4559          _objId = value;
4560        }
4561      });
4562    };
4563    /**
4564    * @function AcroFormPDFObject.toString
4565    */
4566
4567
4568    AcroFormPDFObject.prototype.toString = function () {
4569      return this.objId + " 0 R";
4570    };
4571
4572    AcroFormPDFObject.prototype.putStream = function () {
4573      var keyValueList = this.getKeyValueListForStream();
4574      scope.internal.putStream({
4575        data: this.stream,
4576        additionalKeyValues: keyValueList
4577      });
4578      scope.internal.out("endobj");
4579    };
4580    /**
4581    * Returns an key-value-List of all non-configurable Variables from the Object
4582    * 
4583    * @name getKeyValueListForStream
4584    * @returns {string}
4585    */
4586
4587
4588    AcroFormPDFObject.prototype.getKeyValueListForStream = function () {
4589      var createKeyValueListFromFieldObject = function createKeyValueListFromFieldObject(fieldObject) {
4590        var keyValueList = [];
4591        var keys = Object.getOwnPropertyNames(fieldObject).filter(function (key) {
4592          return key != 'content' && key != 'appearanceStreamContent' && key.substring(0, 1) != "_";
4593        });
4594
4595        for (var i in keys) {
4596          if (Object.getOwnPropertyDescriptor(fieldObject, keys[i]).configurable === false) {
4597            var key = keys[i];
4598            var value = fieldObject[key];
4599
4600            if (value) {
4601              if (Array.isArray(value)) {
4602                keyValueList.push({
4603                  key: key,
4604                  value: arrayToPdfArray(value)
4605                });
4606              } else if (value instanceof AcroFormPDFObject) {
4607                // In case it is a reference to another PDFObject,
4608                // take the reference number
4609                keyValueList.push({
4610                  key: key,
4611                  value: value.objId + " 0 R"
4612                });
4613              } else if (typeof value !== "function") {
4614                keyValueList.push({
4615                  key: key,
4616                  value: value
4617                });
4618              }
4619            }
4620          }
4621        }
4622
4623        return keyValueList;
4624      };
4625
4626      return createKeyValueListFromFieldObject(this);
4627    };
4628
4629    var AcroFormXObject = function AcroFormXObject() {
4630      AcroFormPDFObject.call(this);
4631      Object.defineProperty(this, 'Type', {
4632        value: "/XObject",
4633        configurable: false,
4634        writeable: true
4635      });
4636      Object.defineProperty(this, 'Subtype', {
4637        value: "/Form",
4638        configurable: false,
4639        writeable: true
4640      });
4641      Object.defineProperty(this, 'FormType', {
4642        value: 1,
4643        configurable: false,
4644        writeable: true
4645      });
4646      var _BBox = [];
4647      Object.defineProperty(this, 'BBox', {
4648        configurable: false,
4649        writeable: true,
4650        get: function get() {
4651          return _BBox;
4652        },
4653        set: function set(value) {
4654          _BBox = value;
4655        }
4656      });
4657      Object.defineProperty(this, 'Resources', {
4658        value: "2 0 R",
4659        configurable: false,
4660        writeable: true
4661      });
4662
4663      var _stream;
4664
4665      Object.defineProperty(this, 'stream', {
4666        enumerable: false,
4667        configurable: true,
4668        set: function set(value) {
4669          _stream = value.trim();
4670        },
4671        get: function get() {
4672          if (_stream) {
4673            return _stream;
4674          } else {
4675            return null;
4676          }
4677        }
4678      });
4679    };
4680
4681    inherit(AcroFormXObject, AcroFormPDFObject);
4682
4683    var AcroFormDictionary = function AcroFormDictionary() {
4684      AcroFormPDFObject.call(this);
4685      var _Kids = [];
4686      Object.defineProperty(this, 'Kids', {
4687        enumerable: false,
4688        configurable: true,
4689        get: function get() {
4690          if (_Kids.length > 0) {
4691            return _Kids;
4692          } else {
4693            return;
4694          }
4695        }
4696      });
4697      Object.defineProperty(this, 'Fields', {
4698        enumerable: false,
4699        configurable: false,
4700        get: function get() {
4701          return _Kids;
4702        }
4703      }); // Default Appearance
4704
4705      var _DA;
4706
4707      Object.defineProperty(this, 'DA', {
4708        enumerable: false,
4709        configurable: false,
4710        get: function get() {
4711          if (!_DA) {
4712            return;
4713          }
4714
4715          return '(' + _DA + ')';
4716        },
4717        set: function set(value) {
4718          _DA = value;
4719        }
4720      });
4721    };
4722
4723    inherit(AcroFormDictionary, AcroFormPDFObject);
4724    /**
4725    * The Field Object contains the Variables, that every Field needs
4726    * 
4727    * @class AcroFormField
4728    * @classdesc An AcroForm FieldObject
4729    */
4730
4731    var AcroFormField = function AcroFormField() {
4732      AcroFormPDFObject.call(this); //Annotation-Flag See Table 165
4733
4734      var _F = 4;
4735      Object.defineProperty(this, 'F', {
4736        enumerable: false,
4737        configurable: false,
4738        get: function get() {
4739          return _F;
4740        },
4741        set: function set(value) {
4742          if (!isNaN(value)) {
4743            _F = value;
4744          } else {
4745            throw new Error('Invalid value "' + value + '" for attribute F supplied.');
4746          }
4747        }
4748      });
4749      /**
4750      * (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. 
4751      * NOTE 2 This can be useful for annotations representing interactive pushbuttons, which would serve no meaningful purpose on the printed page.
4752      *
4753      * @name AcroFormField#showWhenPrinted
4754      * @default true
4755      * @type {boolean}
4756      */
4757
4758      Object.defineProperty(this, 'showWhenPrinted', {
4759        enumerable: true,
4760        configurable: true,
4761        get: function get() {
4762          return Boolean(getBitForPdf(_F, 3));
4763        },
4764        set: function set(value) {
4765          if (Boolean(value) === true) {
4766            this.F = setBitForPdf(_F, 3);
4767          } else {
4768            this.F = clearBitForPdf(_F, 3);
4769          }
4770        }
4771      });
4772      var _Ff = 0;
4773      Object.defineProperty(this, 'Ff', {
4774        enumerable: false,
4775        configurable: false,
4776        get: function get() {
4777          return _Ff;
4778        },
4779        set: function set(value) {
4780          if (!isNaN(value)) {
4781            _Ff = value;
4782          } else {
4783            throw new Error('Invalid value "' + value + '" for attribute Ff supplied.');
4784          }
4785        }
4786      });
4787      var _Rect = [];
4788      Object.defineProperty(this, 'Rect', {
4789        enumerable: false,
4790        configurable: false,
4791        get: function get() {
4792          if (_Rect.length === 0) {
4793            return;
4794          }
4795
4796          return _Rect;
4797        },
4798        set: function set(value) {
4799          if (typeof value !== "undefined") {
4800            _Rect = value;
4801          } else {
4802            _Rect = [];
4803          }
4804        }
4805      });
4806      /**
4807      * The x-position of the field.
4808      *
4809      * @name AcroFormField#x
4810      * @default null
4811      * @type {number}
4812      */
4813
4814      Object.defineProperty(this, 'x', {
4815        enumerable: true,
4816        configurable: true,
4817        get: function get() {
4818          if (!_Rect || isNaN(_Rect[0])) {
4819            return 0;
4820          }
4821
4822          return antiScale(_Rect[0]);
4823        },
4824        set: function set(value) {
4825          _Rect[0] = scale(value);
4826        }
4827      });
4828      /**
4829      * The y-position of the field.
4830      *
4831      * @name AcroFormField#y
4832      * @default null
4833      * @type {number}
4834      */
4835
4836      Object.defineProperty(this, 'y', {
4837        enumerable: true,
4838        configurable: true,
4839        get: function get() {
4840          if (!_Rect || isNaN(_Rect[1])) {
4841            return 0;
4842          }
4843
4844          return antiScale(_Rect[1]);
4845        },
4846        set: function set(value) {
4847          _Rect[1] = scale(value);
4848        }
4849      });
4850      /**
4851      * The width of the field.
4852      *
4853      * @name AcroFormField#width
4854      * @default null
4855      * @type {number}
4856      */
4857
4858      Object.defineProperty(this, 'width', {
4859        enumerable: true,
4860        configurable: true,
4861        get: function get() {
4862          if (!_Rect || isNaN(_Rect[2])) {
4863            return 0;
4864          }
4865
4866          return antiScale(_Rect[2]);
4867        },
4868        set: function set(value) {
4869          _Rect[2] = scale(value);
4870        }
4871      });
4872      /**
4873      * The height of the field.
4874      *
4875      * @name AcroFormField#height
4876      * @default null
4877      * @type {number}
4878      */
4879
4880      Object.defineProperty(this, 'height', {
4881        enumerable: true,
4882        configurable: true,
4883        get: function get() {
4884          if (!_Rect || isNaN(_Rect[3])) {
4885            return 0;
4886          }
4887
4888          return antiScale(_Rect[3]);
4889        },
4890        set: function set(value) {
4891          _Rect[3] = scale(value);
4892        }
4893      });
4894      var _FT = "";
4895      Object.defineProperty(this, 'FT', {
4896        enumerable: true,
4897        configurable: false,
4898        get: function get() {
4899          return _FT;
4900        },
4901        set: function set(value) {
4902          switch (value) {
4903            case '/Btn':
4904            case '/Tx':
4905            case '/Ch':
4906            case '/Sig':
4907              _FT = value;
4908              break;
4909
4910            default:
4911              throw new Error('Invalid value "' + value + '" for attribute FT supplied.');
4912          }
4913        }
4914      });
4915      var _T = null;
4916      Object.defineProperty(this, 'T', {
4917        enumerable: true,
4918        configurable: false,
4919        get: function get() {
4920          if (!_T || _T.length < 1) {
4921            // In case of a Child from a Radio´Group, you don't need a FieldName
4922            if (this instanceof AcroFormChildClass) {
4923              return;
4924            }
4925
4926            _T = "FieldObject" + AcroFormField.FieldNum++;
4927          }
4928
4929          return '(' + pdfEscape(_T) + ')';
4930        },
4931        set: function set(value) {
4932          _T = value.toString();
4933        }
4934      });
4935      /**
4936      * (Optional) The partial field name (see 12.7.3.2, “Field N
vendor: 24,612 bytes, lines 4936-5818
4936ames”).
4937      *
4938      * @name AcroFormField#fieldName
4939      * @default null
4940      * @type {string}
4941      */
4942
4943      Object.defineProperty(this, 'fieldName', {
4944        configurable: true,
4945        enumerable: true,
4946        get: function get() {
4947          return _T;
4948        },
4949        set: function set(value) {
4950          _T = value;
4951        }
4952      });
4953      var _fontName = 'helvetica';
4954      /**
4955      * The fontName of the font to be used.
4956      *
4957      * @name AcroFormField#fontName
4958      * @default 'helvetica'
4959      * @type {string}
4960      */
4961
4962      Object.defineProperty(this, 'fontName', {
4963        enumerable: true,
4964        configurable: true,
4965        get: function get() {
4966          return _fontName;
4967        },
4968        set: function set(value) {
4969          _fontName = value;
4970        }
4971      });
4972      var _fontStyle = 'normal';
4973      /**
4974      * The fontStyle of the font to be used.
4975      *
4976      * @name AcroFormField#fontStyle
4977      * @default 'normal'
4978      * @type {string}
4979      */
4980
4981      Object.defineProperty(this, 'fontStyle', {
4982        enumerable: true,
4983        configurable: true,
4984        get: function get() {
4985          return _fontStyle;
4986        },
4987        set: function set(value) {
4988          _fontStyle = value;
4989        }
4990      });
4991      var _fontSize = 0;
4992      /**
4993      * The fontSize of the font to be used.
4994      *
4995      * @name AcroFormField#fontSize
4996      * @default 0 (for auto)
4997      * @type {number}
4998      */
4999
5000      Object.defineProperty(this, 'fontSize', {
5001        enumerable: true,
5002        configurable: true,
5003        get: function get() {
5004          return antiScale(_fontSize);
5005        },
5006        set: function set(value) {
5007          _fontSize = scale(value);
5008        }
5009      });
5010      var _maxFontSize = 50;
5011      /**
5012      * The maximum fontSize of the font to be used.
5013      *
5014      * @name AcroFormField#maxFontSize
5015      * @default 0 (for auto)
5016      * @type {number}
5017      */
5018
5019      Object.defineProperty(this, 'maxFontSize', {
5020        enumerable: true,
5021        configurable: true,
5022        get: function get() {
5023          return antiScale(_maxFontSize);
5024        },
5025        set: function set(value) {
5026          _maxFontSize = scale(value);
5027        }
5028      });
5029      var _color = 'black';
5030      /**
5031      * The color of the text
5032      *
5033      * @name AcroFormField#color
5034      * @default 'black'
5035      * @type {string|rgba}
5036      */
5037
5038      Object.defineProperty(this, 'color', {
5039        enumerable: true,
5040        configurable: true,
5041        get: function get() {
5042          return _color;
5043        },
5044        set: function set(value) {
5045          _color = value;
5046        }
5047      });
5048      var _DA = '/F1 0 Tf 0 g'; // Defines the default appearance (Needed for variable Text)
5049
5050      Object.defineProperty(this, 'DA', {
5051        enumerable: true,
5052        configurable: false,
5053        get: function get() {
5054          if (!_DA || this instanceof AcroFormChildClass || this instanceof AcroFormTextField) {
5055            return;
5056          }
5057
5058          return toPdfString(_DA);
5059        },
5060        set: function set(value) {
5061          value = value.toString();
5062          _DA = value;
5063        }
5064      });
5065      var _DV = null;
5066      Object.defineProperty(this, 'DV', {
5067        enumerable: false,
5068        configurable: false,
5069        get: function get() {
5070          if (!_DV) {
5071            return;
5072          }
5073
5074          if (this instanceof AcroFormButton === false) {
5075            return toPdfString(_DV);
5076          }
5077
5078          return _DV;
5079        },
5080        set: function set(value) {
5081          value = value.toString();
5082
5083          if (this instanceof AcroFormButton === false) {
5084            if (value.substr(0, 1) === '(') {
5085              _DV = pdfUnescape(value.substr(1, value.length - 2));
5086            } else {
5087              _DV = pdfUnescape(value);
5088            }
5089          } else {
5090            _DV = value;
5091          }
5092        }
5093      });
5094      /**
5095      * (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. 
5096      *
5097      * @name AcroFormField#defaultValue
5098      * @default null
5099      * @type {any}
5100      */
5101
5102      Object.defineProperty(this, 'defaultValue', {
5103        enumerable: true,
5104        configurable: true,
5105        get: function get() {
5106          if (this instanceof AcroFormButton === true) {
5107            return pdfUnescape(_DV.substr(1, _DV.length - 1));
5108          } else {
5109            return _DV;
5110          }
5111        },
5112        set: function set(value) {
5113          value = value.toString();
5114
5115          if (this instanceof AcroFormButton === true) {
5116            _DV = '/' + value;
5117          } else {
5118            _DV = value;
5119          }
5120        }
5121      });
5122      var _V = null;
5123      Object.defineProperty(this, 'V', {
5124        enumerable: false,
5125        configurable: false,
5126        get: function get() {
5127          if (!_V) {
5128            return;
5129          }
5130
5131          if (this instanceof AcroFormButton === false) {
5132            return toPdfString(_V);
5133          }
5134
5135          return _V;
5136        },
5137        set: function set(value) {
5138          value = value.toString();
5139
5140          if (this instanceof AcroFormButton === false) {
5141            if (value.substr(0, 1) === '(') {
5142              _V = pdfUnescape(value.substr(1, value.length - 2));
5143            } else {
5144              _V = pdfUnescape(value);
5145            }
5146          } else {
5147            _V = value;
5148          }
5149        }
5150      });
5151      /**
5152      * (Optional; inheritable) The field’s value, whose format varies depending on the field type. See the descriptions of individual field types for further information. 
5153      *
5154      * @name AcroFormField#value
5155      * @default null
5156      * @type {any}
5157      */
5158
5159      Object.defineProperty(this, 'value', {
5160        enumerable: true,
5161        configurable: true,
5162        get: function get() {
5163          if (this instanceof AcroFormButton === true) {
5164            return pdfUnescape(_V.substr(1, _V.length - 1));
5165          } else {
5166            return _V;
5167          }
5168        },
5169        set: function set(value) {
5170          value = value.toString();
5171
5172          if (this instanceof AcroFormButton === true) {
5173            _V = '/' + value;
5174          } else {
5175            _V = value;
5176          }
5177        }
5178      });
5179      /**
5180      * Check if field has annotations
5181      *
5182      * @name AcroFormField#hasAnnotation
5183      * @readonly
5184      * @type {boolean}
5185      */
5186
5187      Object.defineProperty(this, 'hasAnnotation', {
5188        enumerable: true,
5189        configurable: true,
5190        get: function get() {
5191          return this.Rect;
5192        }
5193      });
5194      Object.defineProperty(this, 'Type', {
5195        enumerable: true,
5196        configurable: false,
5197        get: function get() {
5198          return this.hasAnnotation ? "/Annot" : null;
5199        }
5200      });
5201      Object.defineProperty(this, 'Subtype', {
5202        enumerable: true,
5203        configurable: false,
5204        get: function get() {
5205          return this.hasAnnotation ? "/Widget" : null;
5206        }
5207      });
5208      var _hasAppearanceStream = false;
5209      /**
5210      * true if field has an appearanceStream
5211      *
5212      * @name AcroFormField#hasAppearanceStream
5213      * @readonly
5214      * @type {boolean}
5215      */
5216
5217      Object.defineProperty(this, 'hasAppearanceStream', {
5218        enumerable: true,
5219        configurable: true,
5220        writeable: true,
5221        get: function get() {
5222          return _hasAppearanceStream;
5223        },
5224        set: function set(value) {
5225          value = Boolean(value);
5226          _hasAppearanceStream = value;
5227        }
5228      });
5229      /**
5230      * The page on which the AcroFormField is placed
5231      *
5232      * @name AcroFormField#page
5233      * @type {number}
5234      */
5235
5236      var _page;
5237
5238      Object.defineProperty(this, 'page', {
5239        enumerable: true,
5240        configurable: true,
5241        writeable: true,
5242        get: function get() {
5243          if (!_page) {
5244            return;
5245          }
5246
5247          return _page;
5248        },
5249        set: function set(value) {
5250          _page = value;
5251        }
5252      });
5253      /**
5254      * 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. 
5255      *
5256      * @name AcroFormField#readOnly
5257      * @default false
5258      * @type {boolean}
5259      */
5260
5261      Object.defineProperty(this, 'readOnly', {
5262        enumerable: true,
5263        configurable: true,
5264        get: function get() {
5265          return Boolean(getBitForPdf(this.Ff, 1));
5266        },
5267        set: function set(value) {
5268          if (Boolean(value) === true) {
5269            this.Ff = setBitForPdf(this.Ff, 1);
5270          } else {
5271            this.Ff = clearBitForPdf(this.Ff, 1);
5272          }
5273        }
5274      });
5275      /**
5276      * 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”). 
5277      *
5278      * @name AcroFormField#required
5279      * @default false
5280      * @type {boolean}
5281      */
5282
5283      Object.defineProperty(this, 'required', {
5284        enumerable: true,
5285        configurable: true,
5286        get: function get() {
5287          return Boolean(getBitForPdf(this.Ff, 2));
5288        },
5289        set: function set(value) {
5290          if (Boolean(value) === true) {
5291            this.Ff = setBitForPdf(this.Ff, 2);
5292          } else {
5293            this.Ff = clearBitForPdf(this.Ff, 2);
5294          }
5295        }
5296      });
5297      /**
5298      * If set, the field shall not be exported by a submit-form action (see 12.7.5.2, “Submit-Form Action”)
5299      *
5300      * @name AcroFormField#noExport
5301      * @default false
5302      * @type {boolean}
5303      */
5304
5305      Object.defineProperty(this, 'noExport', {
5306        enumerable: true,
5307        configurable: true,
5308        get: function get() {
5309          return Boolean(getBitForPdf(this.Ff, 3));
5310        },
5311        set: function set(value) {
5312          if (Boolean(value) === true) {
5313            this.Ff = setBitForPdf(this.Ff, 3);
5314          } else {
5315            this.Ff = clearBitForPdf(this.Ff, 3);
5316          }
5317        }
5318      });
5319      var _Q = null;
5320      Object.defineProperty(this, 'Q', {
5321        enumerable: true,
5322        configurable: false,
5323        get: function get() {
5324          if (_Q === null) {
5325            return;
5326          }
5327
5328          return _Q;
5329        },
5330        set: function set(value) {
5331          if ([0, 1, 2].indexOf(value) !== -1) {
5332            _Q = value;
5333          } else {
5334            throw new Error('Invalid value "' + value + '" for attribute Q supplied.');
5335          }
5336        }
5337      });
5338      /**
5339      * (Optional; inheritable) A code specifying the form of quadding (justification) that shall be used in displaying the text:
5340      * 'left', 'center', 'right'
5341      *
5342      * @name AcroFormField#textAlign
5343      * @default 'left'
5344      * @type {string}
5345      */
5346
5347      Object.defineProperty(this, 'textAlign', {
5348        get: function get() {
5349          var result = 'left';
5350
5351          switch (_Q) {
5352            case 0:
5353            default:
5354              result = 'left';
5355              break;
5356
5357            case 1:
5358              result = 'center';
5359              break;
5360
5361            case 2:
5362              result = 'right';
5363              break;
5364          }
5365
5366          return result;
5367        },
5368        configurable: true,
5369        enumerable: true,
5370        set: function set(value) {
5371          switch (value) {
5372            case 'right':
5373            case 2:
5374              _Q = 2;
5375              break;
5376
5377            case 'center':
5378            case 1:
5379              _Q = 1;
5380              break;
5381
5382            case 'left':
5383            case 0:
5384            default:
5385              _Q = 0;
5386          }
5387        }
5388      });
5389    };
5390
5391    inherit(AcroFormField, AcroFormPDFObject);
5392    /**
5393    * @class AcroFormChoiceField
5394    * @extends AcroFormField
5395    */
5396
5397    var AcroFormChoiceField = function AcroFormChoiceField() {
5398      AcroFormField.call(this); // Field Type = Choice Field
5399
5400      this.FT = "/Ch"; // options
5401
5402      this.V = '()';
5403      this.fontName = 'zapfdingbats'; // Top Index
5404
5405      var _TI = 0;
5406      Object.defineProperty(this, 'TI', {
5407        enumerable: true,
5408        configurable: false,
5409        get: function get() {
5410          return _TI;
5411        },
5412        set: function set(value) {
5413          _TI = value;
5414        }
5415      });
5416      /**
5417      * (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.
5418      * 
5419      * @name AcroFormChoiceField#topIndex
5420      * @default 0
5421      * @type {number}
5422      */
5423
5424      Object.defineProperty(this, 'topIndex', {
5425        enumerable: true,
5426        configurable: true,
5427        get: function get() {
5428          return _TI;
5429        },
5430        set: function set(value) {
5431          _TI = value;
5432        }
5433      });
5434      var _Opt = [];
5435      Object.defineProperty(this, 'Opt', {
5436        enumerable: true,
5437        configurable: false,
5438        get: function get() {
5439          return arrayToPdfArray(_Opt);
5440        },
5441        set: function set(value) {
5442          _Opt = pdfArrayToStringArray(value);
5443        }
5444      });
5445      /**
5446      * @memberof AcroFormChoiceField
5447      * @name getOptions
5448      * @function
5449      * @instance
5450      * @returns {array} array of Options
5451      */
5452
5453      this.getOptions = function () {
5454        return _Opt;
5455      };
5456      /**
5457      * @memberof AcroFormChoiceField
5458      * @name setOptions
5459      * @function
5460      * @instance
5461      * @param {array} value
5462      */
5463
5464
5465      this.setOptions = function (value) {
5466        _Opt = value;
5467
5468        if (this.sort) {
5469          _Opt.sort();
5470        }
5471      };
5472      /**
5473      * @memberof AcroFormChoiceField
5474      * @name addOption
5475      * @function
5476      * @instance
5477      * @param {string} value
5478      */
5479
5480
5481      this.addOption = function (value) {
5482        value = value || "";
5483        value = value.toString();
5484
5485        _Opt.push(value);
5486
5487        if (this.sort) {
5488          _Opt.sort();
5489        }
5490      };
5491      /**
5492      * @memberof AcroFormChoiceField
5493      * @name removeOption
5494      * @function
5495      * @instance
5496      * @param {string} value
5497      * @param {boolean} allEntries (default: false)
5498      */
5499
5500
5501      this.removeOption = function (value, allEntries) {
5502        allEntries = allEntries || false;
5503        value = value || "";
5504        value = value.toString();
5505
5506        while (_Opt.indexOf(value) !== -1) {
5507          _Opt.splice(_Opt.indexOf(value), 1);
5508
5509          if (allEntries === false) {
5510            break;
5511          }
5512        }
5513      };
5514      /**
5515      * If set, the field is a combo box; if clear, the field is a list box. 
5516      *
5517      * @name AcroFormChoiceField#combo
5518      * @default false
5519      * @type {boolean}
5520      */
5521
5522
5523      Object.defineProperty(this, 'combo', {
5524        enumerable: true,
5525        configurable: true,
5526        get: function get() {
5527          return Boolean(getBitForPdf(this.Ff, 18));
5528        },
5529        set: function set(value) {
5530          if (Boolean(value) === true) {
5531            this.Ff = setBitForPdf(this.Ff, 18);
5532          } else {
5533            this.Ff = clearBitForPdf(this.Ff, 18);
5534          }
5535        }
5536      });
5537      /**
5538      * 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. 
5539      *
5540      * @name AcroFormChoiceField#edit
5541      * @default false
5542      * @type {boolean}
5543      */
5544
5545      Object.defineProperty(this, 'edit', {
5546        enumerable: true,
5547        configurable: true,
5548        get: function get() {
5549          return Boolean(getBitForPdf(this.Ff, 19));
5550        },
5551        set: function set(value) {
5552          //PDF 32000-1:2008, page 444
5553          if (this.combo === true) {
5554            if (Boolean(value) === true) {
5555              this.Ff = setBitForPdf(this.Ff, 19);
5556            } else {
5557              this.Ff = clearBitForPdf(this.Ff, 19);
5558            }
5559          }
5560        }
5561      });
5562      /**
5563      * 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). 
5564      *
5565      * @name AcroFormChoiceField#sort
5566      * @default false
5567      * @type {boolean}
5568      */
5569
5570      Object.defineProperty(this, 'sort', {
5571        enumerable: true,
5572        configurable: true,
5573        get: function get() {
5574          return Boolean(getBitForPdf(this.Ff, 20));
5575        },
5576        set: function set(value) {
5577          if (Boolean(value) === true) {
5578            this.Ff = setBitForPdf(this.Ff, 20);
5579
5580            _Opt.sort();
5581          } else {
5582            this.Ff = clearBitForPdf(this.Ff, 20);
5583          }
5584        }
5585      });
5586      /**
5587      * (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 
5588      *
5589      * @name AcroFormChoiceField#multiSelect
5590      * @default false
5591      * @type {boolean}
5592      */
5593
5594      Object.defineProperty(this, 'multiSelect', {
5595        enumerable: true,
5596        configurable: true,
5597        get: function get() {
5598          return Boolean(getBitForPdf(this.Ff, 22));
5599        },
5600        set: function set(value) {
5601          if (Boolean(value) === true) {
5602            this.Ff = setBitForPdf(this.Ff, 22);
5603          } else {
5604            this.Ff = clearBitForPdf(this.Ff, 22);
5605          }
5606        }
5607      });
5608      /**
5609      * (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. 
5610      *
5611      * @name AcroFormChoiceField#doNotSpellCheck
5612      * @default false
5613      * @type {boolean}
5614      */
5615
5616      Object.defineProperty(this, 'doNotSpellCheck', {
5617        enumerable: true,
5618        configurable: true,
5619        get: function get() {
5620          return Boolean(getBitForPdf(this.Ff, 23));
5621        },
5622        set: function set(value) {
5623          if (Boolean(value) === true) {
5624            this.Ff = setBitForPdf(this.Ff, 23);
5625          } else {
5626            this.Ff = clearBitForPdf(this.Ff, 23);
5627          }
5628        }
5629      });
5630      /**
5631      * (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.
5632      * 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.
5633      *
5634      * @name AcroFormChoiceField#commitOnSelChange
5635      * @default false
5636      * @type {boolean}
5637      */
5638
5639      Object.defineProperty(this, 'commitOnSelChange', {
5640        enumerable: true,
5641        configurable: true,
5642        get: function get() {
5643          return Boolean(getBitForPdf(this.Ff, 27));
5644        },
5645        set: function set(value) {
5646          if (Boolean(value) === true) {
5647            this.Ff = setBitForPdf(this.Ff, 27);
5648          } else {
5649            this.Ff = clearBitForPdf(this.Ff, 27);
5650          }
5651        }
5652      });
5653      this.hasAppearanceStream = false;
5654    };
5655
5656    inherit(AcroFormChoiceField, AcroFormField);
5657    /**
5658    * @class AcroFormListBox
5659    * @extends AcroFormChoiceField
5660    * @extends AcroFormField
5661    */
5662
5663    var AcroFormListBox = function AcroFormListBox() {
5664      AcroFormChoiceField.call(this);
5665      this.fontName = 'helvetica'; //PDF 32000-1:2008, page 444
5666
5667      this.combo = false;
5668    };
5669
5670    inherit(AcroFormListBox, AcroFormChoiceField);
5671    /**
5672    * @class AcroFormComboBox 
5673    * @extends AcroFormListBox
5674    * @extends AcroFormChoiceField
5675    * @extends AcroFormField
5676    */
5677
5678    var AcroFormComboBox = function AcroFormComboBox() {
5679      AcroFormListBox.call(this);
5680      this.combo = true;
5681    };
5682
5683    inherit(AcroFormComboBox, AcroFormListBox);
5684    /**
5685    * @class AcroFormEditBox 
5686    * @extends AcroFormComboBox
5687    * @extends AcroFormListBox
5688    * @extends AcroFormChoiceField
5689    * @extends AcroFormField
5690    */
5691
5692    var AcroFormEditBox = function AcroFormEditBox() {
5693      AcroFormComboBox.call(this);
5694      this.edit = true;
5695    };
5696
5697    inherit(AcroFormEditBox, AcroFormComboBox);
5698    /**
5699    * @class AcroFormButton
5700    * @extends AcroFormField
5701    */
5702
5703    var AcroFormButton = function AcroFormButton() {
5704      AcroFormField.call(this);
5705      this.FT = "/Btn";
5706      /**
5707      * (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.
5708      * 
5709      * @name AcroFormButton#noToggleToOff
5710      * @type {boolean}
5711      */
5712
5713      Object.defineProperty(this, 'noToggleToOff', {
5714        enumerable: true,
5715        configurable: true,
5716        get: function get() {
5717          return Boolean(getBitForPdf(this.Ff, 15));
5718        },
5719        set: function set(value) {
5720          if (Boolean(value) === true) {
5721            this.Ff = setBitForPdf(this.Ff, 15);
5722          } else {
5723            this.Ff = clearBitForPdf(this.Ff, 15);
5724          }
5725        }
5726      });
5727      /**
5728      * 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. 
5729      * 
5730      * @name AcroFormButton#radio
5731      * @type {boolean}
5732      */
5733
5734      Object.defineProperty(this, 'radio', {
5735        enumerable: true,
5736        configurable: true,
5737        get: function get() {
5738          return Boolean(getBitForPdf(this.Ff, 16));
5739        },
5740        set: function set(value) {
5741          if (Boolean(value) === true) {
5742            this.Ff = setBitForPdf(this.Ff, 16);
5743          } else {
5744            this.Ff = clearBitForPdf(this.Ff, 16);
5745          }
5746        }
5747      });
5748      /**
5749      * If set, the field is a pushbutton that does not retain a permanent value. 
5750      *
5751      * @name AcroFormButton#pushButton
5752      * @type {boolean}
5753      */
5754
5755      Object.defineProperty(this, 'pushButton', {
5756        enumerable: true,
5757        configurable: true,
5758        get: function get() {
5759          return Boolean(getBitForPdf(this.Ff, 17));
5760        },
5761        set: function set(value) {
5762          if (Boolean(value) === true) {
5763            this.Ff = setBitForPdf(this.Ff, 17);
5764          } else {
5765            this.Ff = clearBitForPdf(this.Ff, 17);
5766          }
5767        }
5768      });
5769      /**
5770      * (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).
5771      *
5772      * @name AcroFormButton#radioIsUnison
5773      * @type {boolean}
5774      */
5775
5776      Object.defineProperty(this, 'radioIsUnison', {
5777        enumerable: true,
5778        configurable: true,
5779        get: function get() {
5780          return Boolean(getBitForPdf(this.Ff, 26));
5781        },
5782        set: function set(value) {
5783          if (Boolean(value) === true) {
5784            this.Ff = setBitForPdf(this.Ff, 26);
5785          } else {
5786            this.Ff = clearBitForPdf(this.Ff, 26);
5787          }
5788        }
5789      });
5790      var _MK = {};
5791      Object.defineProperty(this, 'MK', {
5792        enumerable: false,
5793        configurable: false,
5794        get: function get() {
5795          if (Object.keys(_MK).length !== 0) {
5796            var result = [];
5797            result.push('<<');
5798            var key;
5799
5800            for (key in _MK) {
5801              result.push('/' + key + ' (' + _MK[key] + ')');
5802            }
5803
5804            result.push('>>');
5805            return result.join('\n');
5806          }
5807
5808          return;
5809        },
5810        set: function set(value) {
5811          if (_typeof(value) === "object") {
5812            _MK = value;
5813          }
5814        }
5815      });
5816      /**
5817      * From the PDF reference:
5818      * (Optional, button fields only) The widget annotation's normal caption which shall be displayed when it is not interacting with the user. 
5819      * 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").
5820      *
5821      * - '8' = Cross, 
5822      * - 'l' =  Circle,
5823      * - '' = nothing
5824      * @name AcroFormButton#caption
5825      * @type {string}
5826      */
5827
5828      Object.defineProperty(this, 'caption', {
5829        enumerable: true,
5830        configurable: true,
5831        get: function get() {
5832          return _MK.CA || '';
5833        },
5834        set: function set(value) {
5835          if (typeof value === "string") {
5836            _MK.CA = value;
5837          }
5838        }
5839      });
5840
5841      var _AS;
5842
5843      Object.defineProperty(this, 'AS', {
5844        enumerable: false,
5845        configurable: false,
5846        get: function get() {
5847          return _AS;
5848        },
5849        set: function set(value) {
5850          _AS = value;
5851        }
5852      });
5853      /**
5854      * (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")
5855      *
5856      * @name AcroFormButton#appearanceState
5857      * @type {any}
5858      */
5859
5860      Object.defineProperty(this, 'appearanceState', {
5861        enumerable: true,
5862        configurable: true,
5863        get: function get() {
5864          return _AS.substr(1, _AS.length - 1);
5865        },
5866        set: function set(value) {
5867          _AS = '/' + value;
5868        }
5869      });
5870    };
5871
5872    inherit(AcroFormButton, AcroFormField);
5873    /**
5874    * @class AcroFormPushButton
5875    * @extends AcroFormButton
5876    * @extends AcroFormField
5877    */
5878
5879    var AcroFormPushButton = function AcroFormPushButton() {
5880      AcroFormButton.call(this);
5881      this.pushButton = true;
5882    };
5883
5884    inherit(AcroFormPushButton, AcroFormButton);
5885    /**
5886    * @class AcroFormRadioButton
5887    * @extends AcroFormButton
5888    * @extends AcroFormField
5889    */
5890
5891    var AcroFormRadioButton = function AcroFormRadioButton() {
5892      AcroFormButton.call(this);
5893      this.radio = true;
5894      this.pushButton = false;
5895      var _Kids = [];
5896      Object.defineProperty(this, 'Kids', {
5897        enumerable: true,
5898        configurable: false,
5899        get: function get() {
5900          return _Kids;
5901        },
5902        set: function set(value) {
5903          if (typeof value !== "undefined") {
5904            _Kids = value;
5905          } else {
5906            _Kids = [];
5907          }
5908        }
5909      });
5910    };
5911
5912    inherit(AcroFormRadioButton, AcroFormButton);
5913    /**
5914    * The Child class of a RadioButton (the radioGroup) -> The single Buttons
5915    * 
5916    * @class AcroFormChildClass
5917    * @extends AcroFormField
5918    * @ignore
5919    */
5920
5921    var AcroFormChildClass = function AcroFormChildClass() {
5922      AcroFormField.call(this);
5923
5924      var _parent;
5925
5926      Object.defineProperty(this, 'Parent', {
5927        enumerable: false,
5928        configurable: false,
5929        get: function get() {
5930          return _parent;
5931        },
5932        set: function set(value) {
5933          _parent = value;
5934        }
5935      });
5936
5937      var _optionName;
5938
5939      Object.defineProperty(this, 'optionName', {
5940        enumerable: false,
5941        configurable: true,
5942        get: function get() {
5943          return _optionName;
5944        },
5945        set: function set(value) {
5946          _optionName = value;
5947        }
5948      });
5949      var _MK = {};
5950      Object.defineProperty(this, 'MK', {
5951        enumerable: false,
5952        configurable: false,
5953        get: function get() {
5954          var result = [];
5955          result.push('<<');
5956          var key;
5957
5958          for (key in _MK) {
5959            result.push('/' + key + ' (' + _MK[key] + ')');
5960          }
5961
5962          result.push('>>');
5963          return result.join('\n');
5964        },
5965        set: function set(value) {
5966          if (_typeof(value) === "object") {
5967            _MK = value;
5968          }
5969        }
5970      });
5971      /**
5972      * From the PDF reference:
5973      * (Optional, button fields only) The widget annotation's normal caption which shall be displayed when it is not interacting with the user. 
5974      * 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").
5975      *
5976      * - '8' = Cross, 
5977      * - 'l' =  Circle,
5978      * - '' = nothing
5979      * @name AcroFormButton#caption
5980      * @type {string}
5981      */
5982
5983      Object.defineProperty(this, 'caption', {
5984        enumerable: true,
5985        configurable: true,
5986        get: function get() {
5987          return _MK.CA || '';
5988        },
5989        set: function set(value) {
5990          if (typeof value === "string") {
5991            _MK.CA = value;
5992          }
5993        }
5994      });
5995
5996      var _AS;
5997
5998      Object.defineProperty(this, 'AS', {
5999        enumerable: false,
6000        configurable: false,
6001        get: function get() {
6002          return _AS;
6003        },
6004        set: function set(value) {
6005          _AS = value;
6006        }
6007      });
6008      /**
6009      * (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")
6010      *
6011      * @name AcroFormButton#appearanceState
6012      * @type {any}
6013      */
6014
6015      Object.defineProperty(this, 'appearanceState', {
6016        enumerable: true,
6017        configurable: true,
6018        get: function get() {
6019          return _AS.substr(1, _AS.length - 1);
6020        },
6021        set: function set(value) {
6022          _AS = '/' + value;
6023        }
6024      });
6025      this.optionName = name;
6026      this.caption = 'l';
6027      this.appearanceState = 'Off'; // todo: set AppearanceType as variable that can be set from the
6028      // outside...
6029
6030      this._AppearanceType = AcroFormAppearance.RadioButton.Circle; // The Default appearanceType is the Circle
6031
6032      this.appearanceStreamContent = this._AppearanceType.createAppearanceStream(name);
6033    };
6034
6035    inherit(AcroFormChildClass, AcroFormField);
6036
6037    AcroFormRadioButton.prototype.setAppearance = function (appearance) {
6038      if (!('createAppearanceStream' in appearance && 'getCA' in appearance)) {
6039        throw new Error("Couldn't assign Appearance to RadioButton. Appearance was Invalid!");
6040        return;
6041      }
6042
6043      for (var objId in this.Kids) {
6044        if (this.Kids.hasOwnProperty(objId)) {
6045          var child = this.Kids[objId];
6046          child.appearanceStreamContent = appearance.createAppearanceStream(child.optionName);
6047          child.caption = appearance.getCA();
6048        }
6049      }
6050    };
6051
6052    AcroFormRadioButton.prototype.createOption = function (name) {
6053      var kidCount = this.Kids.length; // Create new Child for RadioGroup
6054
6055      var child = new AcroFormChildClass();
6056      child.Parent = this;
6057      child.optionName = name; // Add to Parent
6058
6059      this.Kids.push(child);
6060      addField.call(this, child);
6061      return child;
6062    };
6063    /**
6064    * @class AcroFormCheckBox
6065    * @extends AcroFormButton
6066    * @extends AcroFormField
6067    */
6068
6069
6070    var AcroFormCheckBox = function AcroFormCheckBox() {
6071      AcroFormButton.call(this);
6072      this.fontName = 'zapfdingbats';
6073      this.caption = '3';
6074      this.appearanceState = 'On';
6075      this.value = "On";
6076      this.textAlign = 'center';
6077      this.appearanceStreamContent = AcroFormAppearance.CheckBox.createAppearanceStream();
6078    };
6079
6080    inherit(AcroFormCheckBox, AcroFormButton);
6081    /**
6082    * @class AcroFormTextField
6083    * @extends AcroFormField
6084    */
6085
6086    var AcroFormTextField = function AcroFormTextField() {
6087      AcroFormField.call(this);
6088      this.FT = '/Tx';
6089      /**
6090      * If set, the field may contain multiple lines of text; if clear, the field’s text shall be restricted to a single line. 
6091      *
6092      * @name AcroFormTextField#multiline
6093      * @type {boolean}
6094      */
6095
6096      Object.defineProperty(this, 'multiline', {
6097        enumerable: true,
6098        configurable: true,
6099        get: function get() {
6100          return Boolean(getBitForPdf(this.Ff, 13));
6101        },
6102        set: function set(value) {
6103          if (Boolean(value) === true) {
6104            this.Ff = setBitForPdf(this.Ff, 13);
6105          } else {
6106            this.Ff = clearBitForPdf(this.Ff, 13);
6107          }
6108        }
6109      });
6110      /**
6111      * (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. 
6112      * 
6113      * @name AcroFormTextField#fileSelect
6114      * @type {boolean}
6115      */
6116
6117      Object.defineProperty(this, 'fileSelect', {
6118        enumerable: true,
6119        configurable: true,
6120        get: function get() {
6121          return Boolean(getBitForPdf(this.Ff, 21));
6122        },
6123        set: function set(value) {
6124          if (Boolean(value) === true) {
6125            this.Ff = setBitForPdf(this.Ff, 21);
6126          } else {
6127            this.Ff = clearBitForPdf(this.Ff, 21);
6128          }
6129        }
6130      });
6131      /**
6132      * (PDF 1.4) If set, text entered in the field shall not be spell-checked. 
6133      *
6134      * @name AcroFormTextField#doNotSpellCheck
6135      * @type {boolean}
6136      */
6137
6138      Object.defineProperty(this, 'doNotSpellCheck', {
6139        enumerable: true,
6140        configurable: true,
6141        get: function get() {
6142          return Boolean(getBitForPdf(this.Ff, 23));
6143        },
6144        set: function set(value) {
6145          if (Boolean(value) === true) {
6146            this.Ff = setBitForPdf(this.Ff, 23);
6147          } else {
6148            this.Ff = clearBitForPdf(this.Ff, 23);
6149          }
6150        }
6151      });
6152      /**
6153      * (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. 
6154      * 
6155      * @name AcroFormTextField#doNotScroll
6156      * @type {boolean}
6157      */
6158
6159      Object.defineProperty(this, 'doNotScroll', {
6160        enumerable: true,
6161        configurable: true,
6162        get: function get() {
6163          return Boolean(getBitForPdf(this.Ff, 24));
6164        },
6165        set: function set(value) {
6166          if (Boolean(value) === true) {
6167            this.Ff = setBitForPdf(this.Ff, 24);
6168          } else {
6169            this.Ff = clearBitForPdf(this.Ff, 24);
6170          }
6171        }
6172      });
6173      /**
6174      * (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 divi
vendor: 18,085 bytes, lines 6174-6602
6174ded into as many equally spaced positions, or combs, as the value of MaxLen, and the text is laid out into those combs.
6175      * 
6176      * @name AcroFormTextField#comb
6177      * @type {boolean}
6178      */
6179
6180      Object.defineProperty(this, 'comb', {
6181        enumerable: true,
6182        configurable: true,
6183        get: function get() {
6184          return Boolean(getBitForPdf(this.Ff, 25));
6185        },
6186        set: function set(value) {
6187          if (Boolean(value) === true) {
6188            this.Ff = setBitForPdf(this.Ff, 25);
6189          } else {
6190            this.Ff = clearBitForPdf(this.Ff, 25);
6191          }
6192        }
6193      });
6194      /**
6195      * (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.
6196      * 
6197      * @name AcroFormTextField#richText
6198      * @type {boolean}
6199      */
6200
6201      Object.defineProperty(this, 'richText', {
6202        enumerable: true,
6203        configurable: true,
6204        get: function get() {
6205          return Boolean(getBitForPdf(this.Ff, 26));
6206        },
6207        set: function set(value) {
6208          if (Boolean(value) === true) {
6209            this.Ff = setBitForPdf(this.Ff, 26);
6210          } else {
6211            this.Ff = clearBitForPdf(this.Ff, 26);
6212          }
6213        }
6214      });
6215      var _MaxLen = null;
6216      Object.defineProperty(this, 'MaxLen', {
6217        enumerable: true,
6218        configurable: false,
6219        get: function get() {
6220          return _MaxLen;
6221        },
6222        set: function set(value) {
6223          _MaxLen = value;
6224        }
6225      });
6226      /**
6227      * (Optional; inheritable) The maximum length of the field’s text, in characters. 
6228      *
6229      * @name AcroFormTextField#maxLength
6230      * @type {number}
6231      */
6232
6233      Object.defineProperty(this, 'maxLength', {
6234        enumerable: true,
6235        configurable: true,
6236        get: function get() {
6237          return _MaxLen;
6238        },
6239        set: function set(value) {
6240          if (Number.isInteger(value)) {
6241            _MaxLen = value;
6242          }
6243        }
6244      });
6245      Object.defineProperty(this, 'hasAppearanceStream', {
6246        enumerable: true,
6247        configurable: true,
6248        get: function get() {
6249          return this.V || this.DV;
6250        }
6251      });
6252    };
6253
6254    inherit(AcroFormTextField, AcroFormField);
6255    /**
6256    * @class AcroFormPasswordField
6257    * @extends AcroFormTextField
6258    * @extends AcroFormField
6259    */
6260
6261    var AcroFormPasswordField = function AcroFormPasswordField() {
6262      AcroFormTextField.call(this);
6263      /**
6264      * 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.
6265      * NOTE To protect password confidentiality, readers should never store the value of the text field in the PDF file if this flag is set. 
6266      *
6267      * @name AcroFormTextField#password
6268      * @type {boolean}
6269      */
6270
6271      Object.defineProperty(this, 'password', {
6272        enumerable: true,
6273        configurable: true,
6274        get: function get() {
6275          return Boolean(getBitForPdf(this.Ff, 14));
6276        },
6277        set: function set(value) {
6278          if (Boolean(value) === true) {
6279            this.Ff = setBitForPdf(this.Ff, 14);
6280          } else {
6281            this.Ff = clearBitForPdf(this.Ff, 14);
6282          }
6283        }
6284      });
6285      this.password = true;
6286    };
6287
6288    inherit(AcroFormPasswordField, AcroFormTextField); // Contains Methods for creating standard appearances
6289
6290    var AcroFormAppearance = {
6291      CheckBox: {
6292        createAppearanceStream: function createAppearanceStream() {
6293          var appearance = {
6294            N: {
6295              On: AcroFormAppearance.CheckBox.YesNormal
6296            },
6297            D: {
6298              On: AcroFormAppearance.CheckBox.YesPushDown,
6299              Off: AcroFormAppearance.CheckBox.OffPushDown
6300            }
6301          };
6302          return appearance;
6303        },
6304
6305        /**
6306          * Returns the standard On Appearance for a CheckBox
6307          * 
6308          * @returns {AcroFormXObject}
6309          */
6310        YesPushDown: function YesPushDown(formObject) {
6311          var xobj = createFormXObject(formObject);
6312          var stream = [];
6313          var fontKey = scope.internal.getFont(formObject.fontName, formObject.fontStyle).id;
6314
6315          var encodedColor = scope.__private__.encodeColorString(formObject.color);
6316
6317          var calcRes = calculateX(formObject, formObject.caption);
6318          stream.push("0.749023 g");
6319          stream.push("0 0 " + f2(AcroFormAppearance.internal.getWidth(formObject)) + " " + f2(AcroFormAppearance.internal.getHeight(formObject)) + " re");
6320          stream.push("f");
6321          stream.push("BMC");
6322          stream.push("q");
6323          stream.push("0 0 1 rg");
6324          stream.push("/" + fontKey + " " + f2(calcRes.fontSize) + " Tf " + encodedColor);
6325          stream.push("BT");
6326          stream.push(calcRes.text);
6327          stream.push("ET");
6328          stream.push("Q");
6329          stream.push("EMC");
6330          xobj.stream = stream.join("\n");
6331          return xobj;
6332        },
6333        YesNormal: function YesNormal(formObject) {
6334          var xobj = createFormXObject(formObject);
6335          var fontKey = scope.internal.getFont(formObject.fontName, formObject.fontStyle).id;
6336
6337          var encodedColor = scope.__private__.encodeColorString(formObject.color);
6338
6339          var stream = [];
6340          var height = AcroFormAppearance.internal.getHeight(formObject);
6341          var width = AcroFormAppearance.internal.getWidth(formObject);
6342          var calcRes = calculateX(formObject, formObject.caption);
6343          stream.push("1 g");
6344          stream.push("0 0 " + f2(width) + " " + f2(height) + " re");
6345          stream.push("f");
6346          stream.push("q");
6347          stream.push("0 0 1 rg");
6348          stream.push("0 0 " + f2(width - 1) + " " + f2(height - 1) + " re");
6349          stream.push("W");
6350          stream.push("n");
6351          stream.push("0 g");
6352          stream.push("BT");
6353          stream.push("/" + fontKey + " " + f2(calcRes.fontSize) + " Tf " + encodedColor);
6354          stream.push(calcRes.text);
6355          stream.push("ET");
6356          stream.push("Q");
6357          xobj.stream = stream.join("\n");
6358          return xobj;
6359        },
6360
6361        /**
6362          * Returns the standard Off Appearance for a CheckBox
6363          * 
6364          * @returns {AcroFormXObject}
6365          */
6366        OffPushDown: function OffPushDown(formObject) {
6367          var xobj = createFormXObject(formObject);
6368          var stream = [];
6369          stream.push("0.749023 g");
6370          stream.push("0 0 " + f2(AcroFormAppearance.internal.getWidth(formObject)) + " " + f2(AcroFormAppearance.internal.getHeight(formObject)) + " re");
6371          stream.push("f");
6372          xobj.stream = stream.join("\n");
6373          return xobj;
6374        }
6375      },
6376      RadioButton: {
6377        Circle: {
6378          createAppearanceStream: function createAppearanceStream(name) {
6379            var appearanceStreamContent = {
6380              D: {
6381                'Off': AcroFormAppearance.RadioButton.Circle.OffPushDown
6382              },
6383              N: {}
6384            };
6385            appearanceStreamContent.N[name] = AcroFormAppearance.RadioButton.Circle.YesNormal;
6386            appearanceStreamContent.D[name] = AcroFormAppearance.RadioButton.Circle.YesPushDown;
6387            return appearanceStreamContent;
6388          },
6389          getCA: function getCA() {
6390            return 'l';
6391          },
6392          YesNormal: function YesNormal(formObject) {
6393            var xobj = createFormXObject(formObject);
6394            var stream = []; // Make the Radius of the Circle relative to min(height, width) of formObject
6395
6396            var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding...
6397
6398            DotRadius = Number((DotRadius * 0.9).toFixed(5));
6399            var c = AcroFormAppearance.internal.Bezier_C;
6400            var DotRadiusBezier = Number((DotRadius * c).toFixed(5));
6401            /*
6402              * The Following is a Circle created with Bezier-Curves.
6403              */
6404
6405            stream.push("q");
6406            stream.push("1 0 0 1 " + f5(AcroFormAppearance.internal.getWidth(formObject) / 2) + " " + f5(AcroFormAppearance.internal.getHeight(formObject) / 2) + " cm");
6407            stream.push(DotRadius + " 0 m");
6408            stream.push(DotRadius + " " + DotRadiusBezier + " " + DotRadiusBezier + " " + DotRadius + " 0 " + DotRadius + " c");
6409            stream.push("-" + DotRadiusBezier + " " + DotRadius + " -" + DotRadius + " " + DotRadiusBezier + " -" + DotRadius + " 0 c");
6410            stream.push("-" + DotRadius + " -" + DotRadiusBezier + " -" + DotRadiusBezier + " -" + DotRadius + " 0 -" + DotRadius + " c");
6411            stream.push(DotRadiusBezier + " -" + DotRadius + " " + DotRadius + " -" + DotRadiusBezier + " " + DotRadius + " 0 c");
6412            stream.push("f");
6413            stream.push("Q");
6414            xobj.stream = stream.join("\n");
6415            return xobj;
6416          },
6417          YesPushDown: function YesPushDown(formObject) {
6418            var xobj = createFormXObject(formObject);
6419            var stream = [];
6420            var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding...
6421
6422            var DotRadius = Number((DotRadius * 0.9).toFixed(5)); // Save results for later use; no need to waste
6423            // processor ticks on doing math
6424
6425            var k = Number((DotRadius * 2).toFixed(5));
6426            var kc = Number((k * AcroFormAppearance.internal.Bezier_C).toFixed(5));
6427            var dc = Number((DotRadius * AcroFormAppearance.internal.Bezier_C).toFixed(5));
6428            stream.push("0.749023 g");
6429            stream.push("q");
6430            stream.push("1 0 0 1 " + f5(AcroFormAppearance.internal.getWidth(formObject) / 2) + " " + f5(AcroFormAppearance.internal.getHeight(formObject) / 2) + " cm");
6431            stream.push(k + " 0 m");
6432            stream.push(k + " " + kc + " " + kc + " " + k + " 0 " + k + " c");
6433            stream.push("-" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c");
6434            stream.push("-" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c");
6435            stream.push(kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c");
6436            stream.push("f");
6437            stream.push("Q");
6438            stream.push("0 g");
6439            stream.push("q");
6440            stream.push("1 0 0 1 " + f5(AcroFormAppearance.internal.getWidth(formObject) / 2) + " " + f5(AcroFormAppearance.internal.getHeight(formObject) / 2) + " cm");
6441            stream.push(DotRadius + " 0 m");
6442            stream.push("" + DotRadius + " " + dc + " " + dc + " " + DotRadius + " 0 " + DotRadius + " c");
6443            stream.push("-" + dc + " " + DotRadius + " -" + DotRadius + " " + dc + " -" + DotRadius + " 0 c");
6444            stream.push("-" + DotRadius + " -" + dc + " -" + dc + " -" + DotRadius + " 0 -" + DotRadius + " c");
6445            stream.push(dc + " -" + DotRadius + " " + DotRadius + " -" + dc + " " + DotRadius + " 0 c");
6446            stream.push("f");
6447            stream.push("Q");
6448            xobj.stream = stream.join("\n");
6449            return xobj;
6450          },
6451          OffPushDown: function OffPushDown(formObject) {
6452            var xobj = createFormXObject(formObject);
6453            var stream = [];
6454            var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding...
6455
6456            var DotRadius = Number((DotRadius * 0.9).toFixed(5)); // Save results for later use; no need to waste
6457            // processor ticks on doing math
6458
6459            var k = Number((DotRadius * 2).toFixed(5));
6460            var kc = Number((k * AcroFormAppearance.internal.Bezier_C).toFixed(5));
6461            stream.push("0.749023 g");
6462            stream.push("q");
6463            stream.push("1 0 0 1 " + f5(AcroFormAppearance.internal.getWidth(formObject) / 2) + " " + f5(AcroFormAppearance.internal.getHeight(formObject) / 2) + " cm");
6464            stream.push(k + " 0 m");
6465            stream.push(k + " " + kc + " " + kc + " " + k + " 0 " + k + " c");
6466            stream.push("-" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c");
6467            stream.push("-" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c");
6468            stream.push(kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c");
6469            stream.push("f");
6470            stream.push("Q");
6471            xobj.stream = stream.join("\n");
6472            return xobj;
6473          }
6474        },
6475        Cross: {
6476          /**
6477            * Creates the Actual AppearanceDictionary-References
6478            * 
6479            * @param {string} name
6480            * @returns {Object}
6481            * @ignore
6482            */
6483          createAppearanceStream: function createAppearanceStream(name) {
6484            var appearanceStreamContent = {
6485              D: {
6486                'Off': AcroFormAppearance.RadioButton.Cross.OffPushDown
6487              },
6488              N: {}
6489            };
6490            appearanceStreamContent.N[name] = AcroFormAppearance.RadioButton.Cross.YesNormal;
6491            appearanceStreamContent.D[name] = AcroFormAppearance.RadioButton.Cross.YesPushDown;
6492            return appearanceStreamContent;
6493          },
6494          getCA: function getCA() {
6495            return '8';
6496          },
6497          YesNormal: function YesNormal(formObject) {
6498            var xobj = createFormXObject(formObject);
6499            var stream = [];
6500            var cross = AcroFormAppearance.internal.calculateCross(formObject);
6501            stream.push("q");
6502            stream.push("1 1 " + f2(AcroFormAppearance.internal.getWidth(formObject) - 2) + " " + f2(AcroFormAppearance.internal.getHeight(formObject) - 2) + " re");
6503            stream.push("W");
6504            stream.push("n");
6505            stream.push(f2(cross.x1.x) + " " + f2(cross.x1.y) + " m");
6506            stream.push(f2(cross.x2.x) + " " + f2(cross.x2.y) + " l");
6507            stream.push(f2(cross.x4.x) + " " + f2(cross.x4.y) + " m");
6508            stream.push(f2(cross.x3.x) + " " + f2(cross.x3.y) + " l");
6509            stream.push("s");
6510            stream.push("Q");
6511            xobj.stream = stream.join("\n");
6512            return xobj;
6513          },
6514          YesPushDown: function YesPushDown(formObject) {
6515            var xobj = createFormXObject(formObject);
6516            var cross = AcroFormAppearance.internal.calculateCross(formObject);
6517            var stream = [];
6518            stream.push("0.749023 g");
6519            stream.push("0 0 " + f2(AcroFormAppearance.internal.getWidth(formObject)) + " " + f2(AcroFormAppearance.internal.getHeight(formObject)) + " re");
6520            stream.push("f");
6521            stream.push("q");
6522            stream.push("1 1 " + f2(AcroFormAppearance.internal.getWidth(formObject) - 2) + " " + f2(AcroFormAppearance.internal.getHeight(formObject) - 2) + " re");
6523            stream.push("W");
6524            stream.push("n");
6525            stream.push(f2(cross.x1.x) + " " + f2(cross.x1.y) + " m");
6526            stream.push(f2(cross.x2.x) + " " + f2(cross.x2.y) + " l");
6527            stream.push(f2(cross.x4.x) + " " + f2(cross.x4.y) + " m");
6528            stream.push(f2(cross.x3.x) + " " + f2(cross.x3.y) + " l");
6529            stream.push("s");
6530            stream.push("Q");
6531            xobj.stream = stream.join("\n");
6532            return xobj;
6533          },
6534          OffPushDown: function OffPushDown(formObject) {
6535            var xobj = createFormXObject(formObject);
6536            var stream = [];
6537            stream.push("0.749023 g");
6538            stream.push("0 0 " + f2(AcroFormAppearance.internal.getWidth(formObject)) + " " + f2(AcroFormAppearance.internal.getHeight(formObject)) + " re");
6539            stream.push("f");
6540            xobj.stream = stream.join("\n");
6541            return xobj;
6542          }
6543        }
6544      },
6545
6546      /**
6547        * Returns the standard Appearance
6548        * 
6549        * @returns {AcroFormXObject}
6550        */
6551      createDefaultAppearanceStream: function createDefaultAppearanceStream(formObject) {
6552        // Set Helvetica to Standard Font (size: auto)
6553        // Color: Black
6554        var fontKey = scope.internal.getFont(formObject.fontName, formObject.fontStyle).id;
6555
6556        var encodedColor = scope.__private__.encodeColorString(formObject.color);
6557
6558        var fontSize = formObject.fontSize;
6559        var result = '/' + fontKey + ' ' + fontSize + ' Tf ' + encodedColor;
6560        return result;
6561      }
6562    };
6563    AcroFormAppearance.internal = {
6564      Bezier_C: 0.551915024494,
6565      calculateCross: function calculateCross(formObject) {
6566        var width = AcroFormAppearance.internal.getWidth(formObject);
6567        var height = AcroFormAppearance.internal.getHeight(formObject);
6568        var a = Math.min(width, height);
6569
6570        var cross = {
6571          x1: {
6572            // upperLeft
6573            x: (width - a) / 2,
6574            y: (height - a) / 2 + a // height - borderPadding
6575
6576          },
6577          x2: {
6578            // lowerRight
6579            x: (width - a) / 2 + a,
6580            y: (height - a) / 2 // borderPadding
6581
6582          },
6583          x3: {
6584            // lowerLeft
6585            x: (width - a) / 2,
6586            y: (height - a) / 2 // borderPadding
6587
6588          },
6589          x4: {
6590            // upperRight
6591            x: (width - a) / 2 + a,
6592            y: (height - a) / 2 + a // height - borderPadding
6593
6594          }
6595        };
6596        return cross;
6597      }
6598    };
6599
6600    AcroFormAppearance.internal.getWidth = function (formObject) {
6601      var result = 0;
6602
6603      if (_typeof(formObject) === "object") {
6604        result = scale(formObject.Rect[2]);
6605      }
6606
6607      return result;
6608    };
6609
6610    AcroFormAppearance.internal.getHeight = function (formObject) {
6611      var result = 0;
6612
6613      if (_typeof(formObject) === "object") {
6614        result = scale(formObject.Rect[3]);
6615      }
6616
6617      return result;
6618    }; // Public:
6619
6620    /**
6621    * Add an AcroForm-Field to the jsPDF-instance
6622    *
6623    * @name addField
6624    * @function 
6625    * @instance
6626    * @param {Object} fieldObject
6627    * @returns {jsPDF}
6628    */
6629
6630
6631    var addField = jsPDFAPI.addField = function (fieldObject) {
6632      initializeAcroForm.call(this);
6633
6634      if (fieldObject instanceof AcroFormField) {
6635        putForm.call(this, fieldObject);
6636      } else {
6637        throw new Error('Invalid argument passed to jsPDF.addField.');
6638      }
6639
6640      fieldObject.page = scope.internal.getCurrentPageInfo().pageNumber;
6641      return this;
6642    };
6643    /**
6644    * @name addButton
6645    * @function
6646    * @instance
6647    * @param {AcroFormButton} options
6648    * @returns {jsPDF}
6649    * @deprecated
6650    */
6651
6652
6653    var addButton = jsPDFAPI.addButton = function (button) {
6654      if (button instanceof AcroFormButton === false) {
6655        throw new Error('Invalid argument passed to jsPDF.addButton.');
6656      }
6657
6658      return addField.call(this, button);
6659    };
6660    /**
6661    * @name addTextField
6662    * @function
6663    * @instance
6664    * @param {AcroFormTextField} textField
6665    * @returns {jsPDF}
6666    * @deprecated
6667    */
6668
6669
6670    var addTextField = jsPDFAPI.addTextField = function (textField) {
6671      if (textField instanceof AcroFormTextField === false) {
6672        throw new Error('Invalid argument passed to jsPDF.addTextField.');
6673      }
6674
6675      return addField.call(this, textField);
6676    };
6677    /**
6678    * @name addChoiceField
6679    * @function
6680    * @instance
6681    * @param {AcroFormChoiceField} 
6682    * @returns {jsPDF}
6683    * @deprecated
6684    */
6685
6686
6687    var addChoiceField = jsPDFAPI.addChoiceField = function (choiceField) {
6688      if (choiceField instanceof AcroFormChoiceField === false) {
6689        throw new Error('Invalid argument passed to jsPDF.addChoiceField.');
6690      }
6691
6692      return addField.call(this, choiceField);
6693    };
6694
6695    if (_typeof(globalObj) == "object" && typeof globalObj["ChoiceField"] === "undefined" && typeof globalObj["ListBox"] === "undefined" && typeof globalObj["ComboBox"] === "undefined" && typeof globalObj["EditBox"] === "undefined" && typeof globalObj["Button"] === "undefined" && typeof globalObj["PushButton"] === "undefined" && typeof globalObj["RadioButton"] === "undefined" && typeof globalObj["CheckBox"] === "undefined" && typeof globalObj["TextField"] === "undefined" && typeof globalObj["PasswordField"] === "undefined") {
6696      globalObj["ChoiceField"] = AcroFormChoiceField;
6697      globalObj["ListBox"] = AcroFormListBox;
6698      globalObj["ComboBox"] = AcroFormComboBox;
6699      globalObj["EditBox"] = AcroFormEditBox;
6700      globalObj["Button"] = AcroFormButton;
6701      globalObj["PushButton"] = AcroFormPushButton;
6702      globalObj["RadioButton"] = AcroFormRadioButton;
6703      globalObj["CheckBox"] = AcroFormCheckBox;
6704      globalObj["TextField"] = AcroFormTextField;
6705      globalObj["PasswordField"] = AcroFormPasswordField; // backwardsCompatibility
6706
6707      globalObj["AcroForm"] = {
6708        Appearance: AcroFormAppearance
6709      };
6710    } else {
6711      console.warn("AcroForm-Classes are not populated into global-namespace, because the class-Names exist already.");
6712    }
6713
6714    jsPDFAPI.AcroFormChoiceField = AcroFormChoiceField;
6715    jsPDFAPI.AcroFormListBox = AcroFormListBox;
6716    jsPDFAPI.AcroFormComboBox = AcroFormComboBox;
6717    jsPDFAPI.AcroFormEditBox = AcroFormEditBox;
6718    jsPDFAPI.AcroFormButton = AcroFormButton;
6719    jsPDFAPI.AcroFormPushButton = AcroFormPushButton;
6720    jsPDFAPI.AcroFormRadioButton = AcroFormRadioButton;
6721    jsPDFAPI.AcroFormCheckBox = AcroFormCheckBox;
6722    jsPDFAPI.AcroFormTextField = AcroFormTextField;
6723    jsPDFAPI.AcroFormPasswordField = AcroFormPasswordField;
6724    jsPDFAPI.AcroFormAppearance = AcroFormAppearance;
6725    jsPDFAPI.AcroForm = {
6726      ChoiceField: AcroFormChoiceField,
6727      ListBox: AcroFormListBox,
6728      ComboBox: AcroFormComboBox,
6729      EditBox: AcroFormEditBox,
6730      Button: AcroFormButton,
6731      PushButton: AcroFormPushButton,
6732      RadioButton: AcroFormRadioButton,
6733      CheckBox: AcroFormCheckBox,
6734      TextField: AcroFormTextField,
6735      PasswordField: AcroFormPasswordField,
6736      Appearance: AcroFormAppearance
6737    };
6738  })(jsPDF.API, typeof window !== "undefined" && window || typeof global !== "undefined" && global);
6739
6740  /** @license
6741   * jsPDF addImage plugin
6742   * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/
6743   *               2013 Chris Dowling, https://github.com/gingerchris
6744   *               2013 Trinh Ho, https://github.com/ineedfat
6745   *               2013 Edwin Alejandro Perez, https://github.com/eaparango
6746   *               2013 Norah Smith, https://github.com/burnburnrocket
6747   *               2014 Diego Casorran, https://github.com/diegocr
6748   *               2014 James Robb, https://github.com/jamesbrobb
6749   *
6750   * 
6751   */
6752
6753  /**
6754  * @name addImage
6755  * @module
6756  */
6757  (function (jsPDFAPI) {
6758
6759    var namespace = 'addImage_';
6760    var imageFileTypeHeaders = {
6761      PNG: [[0x89, 0x50, 0x4e, 0x47]],
6762      TIFF: [[0x4D, 0x4D, 0x00, 0x2A], //Motorola
6763      [0x49, 0x49, 0x2A, 0x00] //Intel
6764      ],
6765      JPEG: [[0xFF, 0xD8, 0xFF, 0xE0, undefined, undefined, 0x4A, 0x46, 0x49, 0x46, 0x00], //JFIF
6766      [0xFF, 0xD8, 0xFF, 0xE1, undefined, undefined, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00] //Exif
6767      ],
6768      JPEG2000: [[0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20]],
6769      GIF87a: [[0x47, 0x49, 0x46, 0x38, 0x37, 0x61]],
6770      GIF89a: [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61]],
6771      BMP: [[0x42, 0x4D], //BM - Windows 3.1x, 95, NT, ... etc.
6772      [0x42, 0x41], //BA - OS/2 struct bitmap array
6773      [0x43, 0x49], //CI - OS/2 struct color icon
6774      [0x43, 0x50], //CP - OS/2 const color pointer
6775      [0x49, 0x43], //IC - OS/2 struct icon
6776      [0x50, 0x54] //PT - OS/2 pointer
6777      ]
6778    };
6779    /**
6780    * Recognize filetype of Image by magic-bytes
6781    * 
6782    * https://en.wikipedia.org/wiki/List_of_file_signatures
6783    *
6784    * @name getImageFileTypeByImageData
6785    * @public
6786    * @function
6787    * @param {string|arraybuffer} imageData imageData as binary String or arraybuffer
6788    * @param {string} format format of file if filetype-recognition fails, e.g. 'JPEG'
6789    * 
6790    * @returns {string} filetype of Image
6791    */
6792
6793    var getImageFileTypeByImageData = jsPDFAPI.getImageFileTypeByImageData = function (imageData, fallbackFormat) {
6794      fallbackFormat = fallbackFormat || 'UNKNOWN';
6795      var i;
6796      var j;
6797      var result = 'UNKNOWN';
6798      var headerSchemata;
6799      var compareResult;
6800      var fileType;
6801
6802      if (jsPDFAPI.isArrayBufferView(imageData)) {
6803        imageData = jsPDFAPI.arrayBufferToBinaryString(imageData);
6804      }
6805
6806      for (fileType in imageFileTypeHeaders) {
6807        headerSchemata = imageFileTypeHeaders[fileType];
6808
6809        for (i = 0; i < headerSchemata.length; i += 1) {
6810          compareResult = true;
6811
6812          for (j = 0; j < headerSchemata[i].length; j += 1) {
6813            if (headerSchemata[i][j] === undefined) {
6814              continue;
6815            }
6816
6817            if (headerSchemata[i][j] !== imageData.charCodeAt(j)) {
6818              compareResult = false;
6819              break;
6820            }
6821          }
6822
6823          if (compareResult === true) {
6824            result = fileType;
6825            break;
6826          }
6827        }
6828      }
6829
6830      if (result === 'UNKNOWN' && fallbackFormat !== 'UNKNOWN') {
6831        console.warn('FileType of Image not recognized. Processing image as "' + fallbackFormat + '".');
6832        result = fallbackFormat;
6833      }
6834
6835      return result;
6836    }; // Image functionality ported from pdf.js
6837
6838
6839    var putImage = function putImage(img) {
6840      var objectNumber = this.internal.newObject(),
6841          out = this.internal.write,
6842          putStream = this.internal.putStream,
6843          getFilters = this.internal.getFilters;
6844      var filters = getFilters();
6845
6846      while (filters.indexOf('FlateEncode') !== -1) {
6847        filters.splice(filters.indexOf('FlateEncode'), 1);
6848      }
6849
6850      img['n'] = objectNumber;
6851      var additionalKeyValues = [];
6852      additionalKeyValues.push({
6853        key: 'Type',
6854        value: '/XObject'
6855      });
6856      additionalKeyValues.push({
6857        key: 'Subtype',
6858        value: '/Image'
6859      });
6860      additionalKeyValues.push({
6861        key: 'Width',
6862        value: img['w']
6863      });
6864      additionalKeyValues.push({
6865        key: 'Height',
6866        value: img['h']
6867      });
6868
6869      if (img['cs'] === this.color_spaces.INDEXED) {
6870        additionalKeyValues.push({
6871          key: 'ColorSpace',
6872          value: '[/Indexed /DeviceRGB ' // if an indexed png defines more than one colour with transparency, we've created a smask
6873          + (img['pal'].length / 3 - 1) + ' ' + ('smask' in img ? objectNumber + 2 : objectNumber + 1) + ' 0 R]'
6874        });
6875      } else {
6876        additionalKeyValues.push({
6877          key: 'ColorSpace',
6878          value: '/' + img['cs']
6879        });
6880
6881        if (img['cs'] === this.color_spaces.DEVICE_CMYK) {
6882          additionalKeyValues.push({
6883            key: 'Decode',
6884            value: '[1 0 1 0 1 0 1 0]'
6885          });
6886        }
6887      }
6888
6889      additionalKeyValues.push({
6890        key: 'BitsPerComponent',
6891        value: img['bpc']
6892      });
6893
6894      if ('dp' in img) {
6895        additionalKeyValues.push({
6896          key: 'DecodeParms',
6897          value: '<<' + img['dp'] + '>>'
6898        });
6899      }
6900
6901      if ('trns' in img && img['trns'].constructor == Array) {
6902        var trns = '',
6903            i = 0,
6904            len = img['trns'].length;
6905
6906        for (; i < len; i++) {
6907          trns += img['trns'][i] + ' ' + img['trns'][i] + ' ';
6908        }
6909
6910        additionalKeyValues.push({
6911          key: 'Mask',
6912          value: '[' + trns + ']'
6913        });
6914      }
6915
6916      if ('smask' in img) {
6917        additionalKeyValues.push({
6918          key: 'SMask',
6919          value: objectNumber + 1 + ' 0 R'
6920        });
6921      }
6922
6923      var alreadyAppliedFilters = typeof img['f'] !== "undefined" ? ['/' + img['f']] : undefined;
6924      putStream({
6925        data: img['data'],
6926        additionalKeyValues: additionalKeyValues,
6927        alreadyAppliedFilters: alreadyAppliedFilters
6928      });
6929      out('endobj'); // Soft mask
6930
6931      if ('smask' in img) {
6932        var dp = '/Predictor ' + img['p'] + ' /Colors 1 /BitsPerComponent ' + img['bpc'] + ' /Columns ' + img['w'];
6933        var smask = {
6934          'w': img['w'],
6935          'h': img['h'],
6936          'cs': 'DeviceGray',
6937          'bpc': img['bpc'],
6938          'dp': dp,
6939          'data': img['smask']
6940        };
6941        if ('f' in img) smask.f = img['f'];
6942        putImage.call(this, smask);
6943      } //Palette
6944
6945
6946      if (img['cs'] === this.color_spaces.INDEXED) {
6947        this.internal.newObject(); //out('<< /Filter / ' + img['f'] +' /Length ' + img['pal'].length + '>>');
6948        //putStream(zlib.compress(img['pal']));
6949
6950        putStream({
6951          data: this.arrayBufferToBinaryString(new Uint8Array(img['pal']))
6952        });
6953        out('endobj');
6954      }
6955    },
6956        putResourcesCallback = function putResourcesCallback() {
6957      var images = this.internal.collections[namespace + 'images'];
6958
6959      for (var i in images) {
6960        putImage.call(this, images[i]);
6961      }
6962    },
6963        putXObjectsDictCallback = function putXObjectsDictCallback() {
6964      var images = this.internal.collections[namespace + 'images'],
6965          out = this.internal.write,
6966          image;
6967
6968      for (var i in images) {
6969        image = images[i];
6970        out('/I' + image['i'], image['n'], '0', 'R');
6971      }
6972    },
6973        checkCompressValue = function checkCompressValue(value) {
6974      if (value && typeof value === 'string') value = value.toUpperCase();
6975      return value in jsPDFAPI.image_compression ? value : jsPDFAPI.image_compression.NONE;
6976    },
6977        getImages = function getImages() {
6978      var images = this.internal.collections[namespace + 'images']; //first run, so initialise stuff
6979
6980      if (!images) {
6981        this.internal.collections[namespace + 'images'] = images = {};
6982        this.internal.events.subscribe('putResources', putResourcesCallback);
6983        this.internal.events.subscribe('putXobjectDict', putXObjectsDictCallback);
6984      }
6985
6986      return images;
6987    },
6988        getImageIndex = function getImageIndex(images) {
6989      var imageIndex = 0;
6990
6991      if (images) {
6992        // this is NOT the first time this method is ran on this instance of jsPDF object.
6993        imageIndex = Object.keys ? Object.keys(images).length : function (o) {
6994          var i = 0;
6995
6996          for (var e in o) {
6997            if (o.hasOwnProperty(e)) {
6998              i++;
6999            }
7000          }
7001
7002          return i;
7003        }(images);
7004      }
7005
7006      return imageIndex;
7007    },
7008        notDefined = function notDefined(value) {
7009      return typeof value === 'undefined' || value === null || value.length === 0;
7010    },
7011        generateAliasFromImageData = function generateAliasFromImageData(imageData) {
7012      if (typeof imageData === 'string') {
7013        return jsPDFAPI.sHashCode(imageData);
7014      }
7015
7016      if (jsPDFAPI.isArrayBufferView(imageData)) {
7017        return jsPDFAPI.sHashCode(jsPDFAPI.arrayBufferToBinaryString(imageData));
7018      }
7019
7020      return null;
7021    },
7022        isImageTypeSupported = function isImageTypeSupported(type) {
7023      return typeof jsPDFAPI["process" + type.toUpperCase()] === "function";
7024    },
7025        isDOMElement = function isDOMElement(object) {
7026      return _typeof(object) === 'object' && object.nodeType === 1;
7027    },
7028        createDataURIFromElement = function createDataURIFromElement(element, format) {
7029      //if element is an image which uses data url definition, just return the dataurl
7030      if (element.nodeName === 'IMG' && element.hasAttribute('src')) {
7031        var src = '' + element.getAttribute('src'); //is base64 encoded dataUrl, directly process it
7032
7033        if (src.indexOf('data:image/') === 0) {
7034          return unescape(src);
7035        } //it is probably an url, try to load it
7036
7037
7038        var tmpImageData = jsPDFAPI.loadFile(src);
7039
7040        if (tmpImageData !== undefined) {
7041          return btoa(tmpImageData);
7042        }
7043      }
7044
7045      if (element.nodeName === 'CANVAS') {
7046        var canvas = element;
7047        return element.toDataURL('image/jpeg', 1.0);
7048      } //absolute fallback method
7049
7050
7051      var canvas = document.createElement('canvas');
7052      canvas.width = element.clientWidth || element.width;
7053      canvas.height = element.clientHeight || element.height;
7054      var ctx = canvas.getContext('2d');
7055
7056      if (!ctx) {
7057        throw 'addImage requires canvas to be supported by browser.';
7058      }
7059
7060      ctx.drawImage(element, 0, 0, canvas.width, canvas.height);
7061      return canvas.toDataURL(('' + format).toLowerCase() == 'png' ? 'image/png' : 'image/jpeg');
7062    },
7063        checkImagesForAlias = function checkImagesForAlias(alias, images) {
7064      var cached_info;
7065
7066      if (images) {
7067        for (var e in images) {
7068          if (alias === images[e].alias) {
7069            cached_info = images[e];
7070            break;
7071          }
7072        }
7073      }
7074
7075      return cached_info;
7076    },
7077        determineWidthAndHeight = function determineWidthAndHeight(w, h, info) {
7078      if (!w && !h) {
7079        w = -96;
7080        h = -96;
7081      }
7082
7083      if (w < 0) {
7084        w = -1 * info['w'] * 72 / w / this.internal.scaleFactor;
7085      }
7086
7087      if (h < 0) {
7088        h = -1 * info['h'] * 72 / h / this.internal.scaleFactor;
7089      }
7090
7091      if (w === 0) {
7092        w = h * info['w'] / info['h'];
7093      }
7094
7095      if (h === 0) {
7096        h = w * info['h'] / info['w'];
7097      }
7098
7099      return [w, h];
7100    },
7101        writeImageToPDF = function writeImageToPDF(x, y, w, h, info, index, images, rotation) {
7102      var dims = determineWidthAndHeight.call(this, w, h, info),
7103          coord = this.internal.getCoordinateString,
7104          vcoord = this.internal.getVerticalCoordinateString;
7105      w = dims[0];
7106      h = dims[1];
7107      images[index] = info;
7108
7109      if (rotation) {
7110        rotation *= Math.PI / 180;
7111        var c = Math.cos(rotation);
7112        var s = Math.sin(rotation); //like in pdf Reference do it 4 digits instead of 2
7113
7114        var f4 = function f4(number) {
7115          return number.toFixed(4);
7116        };
7117
7118        var rotationTransformationMatrix = [f4(c), f4(s), f4(s * -1), f4(c), 0, 0, 'cm'];
7119      }
7120
7121      this.internal.write('q'); //Save graphics state
7122
7123      if (rotation) {
7124        this.internal.write([1, '0', '0', 1, coord(x), vcoord(y + h), 'cm'].join(' ')); //Translate
7125
7126        this.internal.write(rotationTransformationMatrix.join(' ')); //Rotate
7127
7128        this.internal.write([coord(w), '0', '0', coord(h), '0', '0', 'cm'].join(' ')); //Scale
7129      } else {
7130        this.internal.write([coord(w), '0', '0', coord(h), coord(x), vcoord(y + h), 'cm'].join(' ')); //Translate and Scale
7131      }
7132
7133      this.internal.write('/I' + info['i'] + ' Do'); //Paint Image
7134
7135      this.internal.write('Q'); //Restore graphics state
7136    };
7137    /**
7138     * COLOR SPACES
7139     */
7140
7141
7142    jsPDFAPI.color_spaces = {
7143      DEVICE_RGB: 'DeviceRGB',
7144      DEVICE_GRAY: 'DeviceGray',
7145      DEVICE_CMYK: 'DeviceCMYK',
7146      CAL_GREY: 'CalGray',
7147      CAL_RGB: 'CalRGB',
7148      LAB: 'Lab',
7149      ICC_BASED: 'ICCBased',
7150      INDEXED: 'Indexed',
7151      PATTERN: 'Pattern',
7152      SEPARATION: 'Separation',
7153      DEVICE_N: 'DeviceN'
7154    };
7155    /**
7156     * DECODE METHODS
7157     */
7158
7159    jsPDFAPI.decode = {
7160      DCT_DECODE: 'DCTDecode',
7161      FLATE_DECODE: 'FlateDecode',
7162      LZW_DECODE: 'LZWDecode',
7163      JPX_DECODE: 'JPXDecode',
7164      JBIG2_DECODE: 'JBIG2Decode',
7165      ASCII85_DECODE: 'ASCII85Decode',
7166      ASCII_HEX_DECODE: 'ASCIIHexDecode',
7167      RUN_LENGTH_DECODE: 'RunLengthDecode',
7168      CCITT_FAX_DECODE: 'CCITTFaxDecode'
7169    };
7170    /**
7171     * IMAGE COMPRESSION TYPES
7172     */
7173
7174    jsPDFAPI.image_compression = {
7175      NONE: 'NONE',
7176      FAST: 'FAST',
7177      MEDIUM: 'MEDIUM',
7178      SLOW: 'SLOW'
7179    };
7180    /**
7181    * @name sHashCode
7182    * @function 
7183    * @param {string} str
7184    * @returns {string} 
7185    */
7186
7187    jsPDFAPI.sHashCode = function (str) {
7188      str = str || "";
7189      var hash = 0,
7190          i,
7191          chr;
7192      if (str.length === 0) return hash;
7193
7194      for (i = 0; i < str.length; i++) {
7195        chr = str.charCodeAt(i);
7196        hash = (hash << 5) - hash + chr;
7197        hash |= 0; // Convert to 32bit integer
7198      }
7199
7200      return hash;
7201    };
7202    /**
7203    * @name isString
7204    * @function
7205    * @param {any} object
7206    * @returns {boolean} 
7207    */
7208
7209
7210    jsPDFAPI.isString = function (object) {
7211      return typeof object === 'string';
7212    };
7213    /**
7214    * Validates if given String is a valid Base64-String
7215    *
7216    * @name validateStringAsBase64
7217    * @public
7218    * @function
7219    * @param {String} possible Base64-String
7220    * 
7221    * @returns {boolean}
7222    */
7223
7224
7225    jsPDFAPI.validateStringAsBase64 = function (possibleBase64String) {
7226      possibleBase64String = possibleBase64String || '';
7227      possibleBase64String.toString().trim();
7228      var result = true;
7229
7230      if (possibleBase64String.length === 0) {
7231        result = false;
7232      }
7233
7234      if (possibleBase64String.length % 4 !== 0) {
7235        result = false;
7236      }
7237
7238      if (/^[A-Za-z0-9+\/]+$/.test(possibleBase64String.substr(0, possibleBase64String.length - 2)) === false) {
7239        result = false;
7240      }
7241
7242      if (/^[A-Za-z0-9\/][A-Za-z0-9+\/]|[A-Za-z0-9+\/]=|==$/.test(possibleBase64String.substr(-2)) === false) {
7243        result = false;
7244      }
7245
7246      return result;
7247    };
7248    /**
7249     * Strips out and returns info from a valid base64 data URI
7250     *
7251     * @name extractInfoFromBase64DataURI
7252     * @function 
7253     * @param {string} dataUrl a valid data URI of format 'data:[<MIME-type>][;base64],<data>'
7254     * @returns {Array}an Array containing the following
7255     * [0] the complete data URI
7256     * [1] <MIME-type>
7257     * [2] format - the second part of the mime-type i.e 'png' in 'image/png'
7258     * [4] <data>
7259     */
7260
7261
7262    jsPDFAPI.extractInfoFromBase64DataURI = function (dataURI) {
7263      return /^data:([\w]+?\/([\w]+?));\S*;*base64,(.+)$/g.exec(dataURI);
7264    };
7265    /**
7266     * Strips out and returns info from a valid base64 data URI
7267     *
7268     * @name extractImageFromDataUrl
7269     * @function 
7270     * @param {string} dataUrl a valid data URI of format 'data:[<MIME-type>][;base64],<data>'
7271     * @returns {Array}an Array containing the following
7272     * [0] the complete data URI
7273     * [1] <MIME-type>
7274     * [2] format - the second part of the mime-type i.e 'png' in 'image/png'
7275     * [4] <data>
7276     */
7277
7278
7279    jsPDFAPI.extractImageFromDataUrl = function (dataUrl) {
7280      dataUrl = dataUrl || '';
7281      var dataUrlParts = dataUrl.split('base64,');
7282      var result = null;
7283
7284      if (dataUrlParts.length === 2) {
7285        var extractedInfo = /^data:(\w*\/\w*);*(charset=[\w=-]*)*;*$/.exec(dataUrlParts[0]);
7286
7287        if (Array.isArray(extractedInfo)) {
7288          result = {
7289            mimeType: extractedInfo[1],
7290            charset: extractedInfo[2],
7291            data: dataUrlParts[1]
7292          };
7293        }
7294      }
7295
7296      return result;
7297    };
7298    /**
7299     * Check to see if ArrayBuffer is supported
7300     * 
7301     * @name supportsArrayBuffer
7302     * @function
7303     * @returns {boolean}
7304     */
7305
7306
7307    jsPDFAPI.supportsArrayBuffer = function () {
7308      return typeof ArrayBuffer !== 'undefined' && typeof Uint8Array !== 'undefined';
7309    };
7310    /**
7311     * Tests supplied object to determine if ArrayBuffer
7312     *
7313     * @name isArrayBuffer
7314     * @function 
7315     * @param {Object} object an Object
7316     * 
7317     * @returns {boolean}
7318     */
7319
7320
7321    jsPDFAPI.isArrayBuffer = function (object) {
7322      if (!this.supportsArrayBuffer()) return false;
7323      return object instanceof ArrayBuffer;
7324    };
7325    /**
7326     * Tests supplied object to determine if it implements the ArrayBufferView (TypedArray) interface
7327     *
7328     * @name isArrayBufferView
7329     * @function 
7330     * @param {Object} object an Object
7331     * @returns {boolean}
7332     */
7333
7334
7335    jsPDFAPI.isArrayBufferView = function (object) {
7336      if (!this.supportsArrayBuffer()) return false;
7337      if (typeof Uint32Array === 'undefined') return false;
7338      return object instanceof Int8Array || object instanceof Uint8Array || typeof Uint8ClampedArray !== 'undefined' && object instanceof Uint8ClampedArray || object instanceof Int16Array || object instanceof Uint16Array || object instanceof Int32Array || object instanceof Uint32Array || object instanceof Float32Array || object instanceof Float64Array;
7339    };
7340    /**
7341    * Convert the Buffer to a Binary String
7342    *
7343    * @name binaryStringToUint8Array
7344    * @public
7345    * @function
7346    * @param {ArrayBuffer} BinaryString with ImageData
7347    * 
7348    * @returns {Uint8Array}
7349    */
7350
7351
7352    jsPDFAPI.binaryStringToUint8Array = function (binary_string) {
7353      /*
7354       * not sure how efficient this will be will bigger files. Is there a native method?
7355       */
7356      var len = binary_string.length;
7357      var bytes = new Uint8Array(len);
7358
7359      for (var i = 0; i < len; i++) {
7360        bytes[i] = binary_string.charCodeAt(i);
7361      }
7362
7363      return bytes;
7364    };
7365    /**
7366    * Convert the Buffer to a Binary String
7367    *
7368    * @name arrayBufferToBinaryString
7369    * @public
7370    * @function
7371    * @param {ArrayBuffer} ArrayBuffer with ImageData
7372    * 
7373    * @returns {String}
7374    */
7375
7376
7377    jsPDFAPI.arrayBufferToBinaryString = function (buffer) {
7378      // if (typeof Uint8Array !== 'undefined' && typeof Uint8Array.prototype.reduce !== 'undefined') {
7379      // return new Uint8Array(buffer).reduce(function (data, byte) {
7380      // return data.push(String.fromCharCode(byte)), data;
7381      // }, []).join('');
7382      // }
7383      if (typeof atob === "function") {
7384        return atob(this.arrayBufferToBase64(buffer));
7385      }
7386    };
7387    /**
7388    * Converts an ArrayBuffer directly to base64
7389    *
7390    * Taken from  http://jsperf.com/encoding-xhr-image-data/31
7391    *
7392    * Need to test if this is a better solution for larger files
7393    *
7394    * @name arrayBufferToBase64
7395    * @param {arraybuffer} arrayBuffer
7396    * @public
7397    * @function
7398    * 
7399    * @returns {string}
7400    */
7401
7402
7403    jsPDFAPI.arrayBufferToBase64 = function (arrayBuffer) {
7404      var base64 = '';
7405      var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
7405+/';
7406      var bytes = new Uint8Array(arrayBuffer);
7407      var byteLength = bytes.byteLength;
7408      var byteRemainder = byteLength % 3;
7409      var mainLength = byteLength - byteRemainder;
7410      var a, b, c, d;
7411      var chunk; // Main loop deals with bytes in chunks of 3
7412
7413      for (var i = 0; i < mainLength; i = i + 3) {
7414        // Combine the three bytes into a single integer
7415        chunk = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2]; // Use bitmasks to extract 6-bit segments from the triplet
7416
7417        a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
7418
7419        b = (chunk & 258048) >> 12; // 258048   = (2^6 - 1) << 12
7420
7421        c = (chunk & 4032) >> 6; // 4032     = (2^6 - 1) << 6
7422
7423        d = chunk & 63; // 63       = 2^6 - 1
7424        // Convert the raw binary segments to the appropriate ASCII encoding
7425
7426        base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
7427      } // Deal with the remaining bytes and padding
7428
7429
7430      if (byteRemainder == 1) {
7431        chunk = bytes[mainLength];
7432        a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2
7433        // Set the 4 least significant bits to zero
7434
7435        b = (chunk & 3) << 4; // 3   = 2^2 - 1
7436
7437        base64 += encodings[a] + encodings[b] + '==';
7438      } else if (byteRemainder == 2) {
7439        chunk = bytes[mainLength] << 8 | bytes[mainLength + 1];
7440        a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
7441
7442        b = (chunk & 1008) >> 4; // 1008  = (2^6 - 1) << 4
7443        // Set the 2 least significant bits to zero
7444
7445        c = (chunk & 15) << 2; // 15    = 2^4 - 1
7446
7447        base64 += encodings[a] + encodings[b] + encodings[c] + '=';
7448      }
7449
7450      return base64;
7451    };
7452    /**
7453    * 
7454    * @name createImageInfo
7455    * @param {Object} data 
7456    * @param {number} wd width
7457    * @param {number} ht height
7458    * @param {Object} cs colorSpace
7459    * @param {number} bpc bits per channel
7460    * @param {any} f 
7461    * @param {number} imageIndex
7462    * @param {string} alias
7463    * @param {any} dp
7464    * @param {any} trns
7465    * @param {any} pal
7466    * @param {any} smask
7467    * @param {any} p
7468    * @public
7469    * @function
7470    * 
7471    * @returns {Object}
7472    */
7473
7474
7475    jsPDFAPI.createImageInfo = function (data, wd, ht, cs, bpc, f, imageIndex, alias, dp, trns, pal, smask, p) {
7476      var info = {
7477        alias: alias,
7478        w: wd,
7479        h: ht,
7480        cs: cs,
7481        bpc: bpc,
7482        i: imageIndex,
7483        data: data // n: objectNumber will be added by putImage code
7484
7485      };
7486      if (f) info.f = f;
7487      if (dp) info.dp = dp;
7488      if (trns) info.trns = trns;
7489      if (pal) info.pal = pal;
7490      if (smask) info.smask = smask;
7491      if (p) info.p = p; // predictor parameter for PNG compression
7492
7493      return info;
7494    };
7495    /**
7496    * Adds an Image to the PDF.
7497    *
7498    * @name addImage
7499    * @public
7500    * @function
7501    * @param {string/Image-Element/Canvas-Element/Uint8Array} imageData imageData as base64 encoded DataUrl or Image-HTMLElement or Canvas-HTMLElement
7502    * @param {string} format format of file if filetype-recognition fails, e.g. 'JPEG'
7503    * @param {number} x x Coordinate (in units declared at inception of PDF document) against left edge of the page
7504    * @param {number} y y Coordinate (in units declared at inception of PDF document) against upper edge of the page
7505    * @param {number} width width of the image (in units declared at inception of PDF document)
7506    * @param {number} height height of the Image (in units declared at inception of PDF document)
7507    * @param {string} alias alias of the image (if used multiple times)
7508    * @param {string} compression compression of the generated JPEG, can have the values 'NONE', 'FAST', 'MEDIUM' and 'SLOW'
7509    * @param {number} rotation rotation of the image in degrees (0-359)
7510    * 
7511    * @returns jsPDF
7512    */
7513
7514
7515    jsPDFAPI.addImage = function (imageData, format, x, y, w, h, alias, compression, rotation) {
7516
7517      var tmpImageData = '';
7518
7519      if (typeof format !== 'string') {
7520        var tmp = h;
7521        h = w;
7522        w = y;
7523        y = x;
7524        x = format;
7525        format = tmp;
7526      }
7527
7528      if (_typeof(imageData) === 'object' && !isDOMElement(imageData) && "imageData" in imageData) {
7529        var options = imageData;
7530        imageData = options.imageData;
7531        format = options.format || format || 'UNKNOWN';
7532        x = options.x || x || 0;
7533        y = options.y || y || 0;
7534        w = options.w || w;
7535        h = options.h || h;
7536        alias = options.alias || alias;
7537        compression = options.compression || compression;
7538        rotation = options.rotation || options.angle || rotation;
7539      } //If compression is not explicitly set, determine if we should use compression
7540
7541
7542      var filters = this.internal.getFilters();
7543
7544      if (compression === undefined && filters.indexOf('FlateEncode') !== -1) {
7545        compression = 'SLOW';
7546      }
7547
7548      if (typeof imageData === "string") {
7549        imageData = unescape(imageData);
7550      }
7551
7552      if (isNaN(x) || isNaN(y)) {
7553        console.error('jsPDF.addImage: Invalid coordinates', arguments);
7554        throw new Error('Invalid coordinates passed to jsPDF.addImage');
7555      }
7556
7557      var images = getImages.call(this),
7558          info,
7559          dataAsBinaryString;
7560
7561      if (!(info = checkImagesForAlias(imageData, images))) {
7562        if (isDOMElement(imageData)) imageData = createDataURIFromElement(imageData, format);
7563        if (notDefined(alias)) alias = generateAliasFromImageData(imageData);
7564
7565        if (!(info = checkImagesForAlias(alias, images))) {
7566          if (this.isString(imageData)) {
7567            tmpImageData = this.convertStringToImageData(imageData);
7568
7569            if (tmpImageData !== '') {
7570              imageData = tmpImageData;
7571            } else {
7572              tmpImageData = jsPDFAPI.loadFile(imageData);
7573
7574              if (tmpImageData !== undefined) {
7575                imageData = tmpImageData;
7576              }
7577            }
7578          }
7579
7580          format = this.getImageFileTypeByImageData(imageData, format);
7581          if (!isImageTypeSupported(format)) throw new Error('addImage does not support files of type \'' + format + '\', please ensure that a plugin for \'' + format + '\' support is added.');
7582          /**
7583           * need to test if it's more efficient to convert all binary strings
7584           * to TypedArray - or should we just leave and process as string?
7585           */
7586
7587          if (this.supportsArrayBuffer()) {
7588            // no need to convert if imageData is already uint8array
7589            if (!(imageData instanceof Uint8Array)) {
7590              dataAsBinaryString = imageData;
7591              imageData = this.binaryStringToUint8Array(imageData);
7592            }
7593          }
7594
7595          info = this['process' + format.toUpperCase()](imageData, getImageIndex(images), alias, checkCompressValue(compression), dataAsBinaryString);
7596
7597          if (!info) {
7598            throw new Error('An unknown error occurred whilst processing the image');
7599          }
7600        }
7601      }
7602
7603      writeImageToPDF.call(this, x, y, w, h, info, info.i, images, rotation);
7604      return this;
7605    };
7606    /**
7607    * @name convertStringToImageData
7608    * @function
7609    * @param {string} stringData
7610    * @returns {string} binary data
7611    */
7612
7613
7614    jsPDFAPI.convertStringToImageData = function (stringData) {
7615      var base64Info;
7616      var imageData = '';
7617      var rawData;
7618
7619      if (this.isString(stringData)) {
7620        var base64Info = this.extractImageFromDataUrl(stringData);
7621        rawData = base64Info !== null ? base64Info.data : stringData;
7622
7623        try {
7624          imageData = atob(rawData);
7625        } catch (e) {
7626          if (!jsPDFAPI.validateStringAsBase64(rawData)) {
7627            throw new Error('Supplied Data is not a valid base64-String jsPDF.convertStringToImageData ');
7628          } else {
7629            throw new Error('atob-Error in jsPDF.convertStringToImageData ' + e.message);
7630          }
7631        }
7632      }
7633
7634      return imageData;
7635    };
7636    /**
7637     * JPEG SUPPORT
7638     **/
7639    //takes a string imgData containing the raw bytes of
7640    //a jpeg image and returns [width, height]
7641    //Algorithm from: http://www.64lines.com/jpeg-width-height
7642
7643
7644    var getJpegSize = function getJpegSize(imgData) {
7645
7646      var width, height, numcomponents; // Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00
7647
7648      if (getImageFileTypeByImageData(imgData) !== 'JPEG') {
7649        throw new Error('getJpegSize requires a binary string jpeg file');
7650      }
7651
7652      var blockLength = imgData.charCodeAt(4) * 256 + imgData.charCodeAt(5);
7653      var i = 4,
7654          len = imgData.length;
7655
7656      while (i < len) {
7657        i += blockLength;
7658
7659        if (imgData.charCodeAt(i) !== 0xff) {
7660          throw new Error('getJpegSize could not find the size of the image');
7661        }
7662
7663        if (imgData.charCodeAt(i + 1) === 0xc0 || //(SOF) Huffman  - Baseline DCT
7664        imgData.charCodeAt(i + 1) === 0xc1 || //(SOF) Huffman  - Extended sequential DCT
7665        imgData.charCodeAt(i + 1) === 0xc2 || // Progressive DCT (SOF2)
7666        imgData.charCodeAt(i + 1) === 0xc3 || // Spatial (sequential) lossless (SOF3)
7667        imgData.charCodeAt(i + 1) === 0xc4 || // Differential sequential DCT (SOF5)
7668        imgData.charCodeAt(i + 1) === 0xc5 || // Differential progressive DCT (SOF6)
7669        imgData.charCodeAt(i + 1) === 0xc6 || // Differential spatial (SOF7)
7670        imgData.charCodeAt(i + 1) === 0xc7) {
7671          height = imgData.charCodeAt(i + 5) * 256 + imgData.charCodeAt(i + 6);
7672          width = imgData.charCodeAt(i + 7) * 256 + imgData.charCodeAt(i + 8);
7673          numcomponents = imgData.charCodeAt(i + 9);
7674          return [width, height, numcomponents];
7675        } else {
7676          i += 2;
7677          blockLength = imgData.charCodeAt(i) * 256 + imgData.charCodeAt(i + 1);
7678        }
7679      }
7680    },
7681        getJpegSizeFromBytes = function getJpegSizeFromBytes(data) {
7682      var hdr = data[0] << 8 | data[1];
7683      if (hdr !== 0xFFD8) throw new Error('Supplied data is not a JPEG');
7684      var len = data.length,
7685          block = (data[4] << 8) + data[5],
7686          pos = 4,
7687          bytes,
7688          width,
7689          height,
7690          numcomponents;
7691
7692      while (pos < len) {
7693        pos += block;
7694        bytes = readBytes(data, pos);
7695        block = (bytes[2] << 8) + bytes[3];
7696
7697        if ((bytes[1] === 0xC0 || bytes[1] === 0xC2) && bytes[0] === 0xFF && block > 7) {
7698          bytes = readBytes(data, pos + 5);
7699          width = (bytes[2] << 8) + bytes[3];
7700          height = (bytes[0] << 8) + bytes[1];
7701          numcomponents = bytes[4];
7702          return {
7703            width: width,
7704            height: height,
7705            numcomponents: numcomponents
7706          };
7707        }
7708
7709        pos += 2;
7710      }
7711
7712      throw new Error('getJpegSizeFromBytes could not find the size of the image');
7713    },
7714        readBytes = function readBytes(data, offset) {
7715      return data.subarray(offset, offset + 5);
7716    };
7717    /**
7718    * @ignore
7719    */
7720
7721
7722    jsPDFAPI.processJPEG = function (data, index, alias, compression, dataAsBinaryString, colorSpace) {
7723
7724      var filter = this.decode.DCT_DECODE,
7725          bpc = 8,
7726          dims;
7727
7728      if (!this.isString(data) && !this.isArrayBuffer(data) && !this.isArrayBufferView(data)) {
7729        return null;
7730      }
7731
7732      if (this.isString(data)) {
7733        dims = getJpegSize(data);
7734      }
7735
7736      if (this.isArrayBuffer(data)) {
7737        data = new Uint8Array(data);
7738      }
7739
7740      if (this.isArrayBufferView(data)) {
7741        dims = getJpegSizeFromBytes(data); // if we already have a stored binary string rep use that
7742
7743        data = dataAsBinaryString || this.arrayBufferToBinaryString(data);
7744      }
7745
7746      if (colorSpace === undefined) {
7747        switch (dims.numcomponents) {
7748          case 1:
7749            colorSpace = this.color_spaces.DEVICE_GRAY;
7750            break;
7751
7752          case 4:
7753            colorSpace = this.color_spaces.DEVICE_CMYK;
7754            break;
7755
7756          default:
7757          case 3:
7758            colorSpace = this.color_spaces.DEVICE_RGB;
7759            break;
7760        }
7761      }
7762
7763      return this.createImageInfo(data, dims.width, dims.height, colorSpace, bpc, filter, index, alias);
7764    };
7765    /**
7766    * @ignore
7767    */
7768
7769
7770    jsPDFAPI.processJPG = function ()
7771    /*data, index, alias, compression, dataAsBinaryString*/
7772    {
7773      return this.processJPEG.apply(this, arguments);
7774    };
7775    /**
7776    * @name getImageProperties
7777    * @function
7778    * @param {Object} imageData
7779    * @returns {Object}
7780    */
7781
7782
7783    jsPDFAPI.getImageProperties = function (imageData) {
7784      var info;
7785      var tmpImageData = '';
7786      var format;
7787
7788      if (isDOMElement(imageData)) {
7789        imageData = createDataURIFromElement(imageData);
7790      }
7791
7792      if (this.isString(imageData)) {
7793        tmpImageData = this.convertStringToImageData(imageData);
7794
7795        if (tmpImageData !== '') {
7796          imageData = tmpImageData;
7797        } else {
7798          tmpImageData = jsPDFAPI.loadFile(imageData);
7799
7800          if (tmpImageData !== undefined) {
7801            imageData = tmpImageData;
7802          }
7803        }
7804      }
7805
7806      format = this.getImageFileTypeByImageData(imageData);
7807
7808      if (!isImageTypeSupported(format)) {
7809        throw new Error('addImage does not support files of type \'' + format + '\', please ensure that a plugin for \'' + format + '\' support is added.');
7810      }
7811      /**
7812       * need to test if it's more efficient to convert all binary strings
7813       * to TypedArray - or should we just leave and process as string?
7814       */
7815
7816
7817      if (this.supportsArrayBuffer()) {
7818        // no need to convert if imageData is already uint8array
7819        if (!(imageData instanceof Uint8Array)) {
7820          imageData = this.binaryStringToUint8Array(imageData);
7821        }
7822      }
7823
7824      info = this['process' + format.toUpperCase()](imageData);
7825
7826      if (!info) {
7827        throw new Error('An unknown error occurred whilst processing the image');
7828      }
7829
7830      return {
7831        fileType: format,
7832        width: info.w,
7833        height: info.h,
7834        colorSpace: info.cs,
7835        compressionMode: info.f,
7836        bitsPerComponent: info.bpc
7837      };
7838    };
7839  })(jsPDF.API);
7840
7841  /**
7842   * @license
7843   * Copyright (c) 2014 Steven Spungin (TwelveTone LLC)  [email protected]
7844   *
7845   * Licensed under the MIT License.
7846   * http://opensource.org/licenses/mit-license
7847   */
7848
7849  /**
7850   * jsPDF Annotations PlugIn
7851   *
7852   * There are many types of annotations in a PDF document. Annotations are placed
7853   * on a page at a particular location. They are not 'attached' to an object.
7854   * <br />
7855   * This plugin current supports <br />
7856   * <li> Goto Page (set pageNumber and top in options)
7857   * <li> Goto Name (set name and top in options)
7858   * <li> Goto URL (set url in options)
7859   * <p>
7860   * 	The destination magnification factor can also be specified when goto is a page number or a named destination. (see documentation below)
7861   *  (set magFactor in options).  XYZ is the default.
7862   * </p>
7863   * <p>
7864   *  Links, Text, Popup, and FreeText are supported.
7865   * </p>
7866   * <p>
7867   * Options In PDF spec Not Implemented Yet
7868   * <li> link border
7869   * <li> named target
7870   * <li> page coordinates
7871   * <li> destination page scaling and layout
7872   * <li> actions other than URL and GotoPage
7873   * <li> background / hover actions
7874   * </p>
7875   * @name annotations
7876   * @module
7877   */
7878
7879  /*
7880      Destination Magnification Factors
7881      See PDF 1.3 Page 386 for meanings and options
7882
7883      [supported]
7884  	XYZ (options; left top zoom)
7885  	Fit (no options)
7886  	FitH (options: top)
7887  	FitV (options: left)
7888
7889  	[not supported]
7890  	FitR
7891  	FitB
7892  	FitBH
7893  	FitBV
7894   */
7895  (function (jsPDFAPI) {
7896
7897    jsPDF.API.events.push(['addPage', function (addPageData) {
7898      var pageInfo = this.internal.getPageInfo(addPageData.pageNumber);
7899      pageInfo.pageContext.annotations = [];
7900    }]);
7901    jsPDFAPI.events.push(['putPage', function (putPageData) {
7902      var pageInfo = this.internal.getPageInfoByObjId(putPageData.objId);
7903      var pageAnnos = putPageData.pageContext.annotations;
7904
7905      var notEmpty = function notEmpty(obj) {
7906        if (typeof obj != 'undefined') {
7907          if (obj != '') {
7908            return true;
7909          }
7910        }
7911      };
7912
7913      var found = false;
7914
7915      for (var a = 0; a < pageAnnos.length && !found; a++) {
7916        var anno = pageAnnos[a];
7917
7918        switch (anno.type) {
7919          case 'link':
7920            if (notEmpty(anno.options.url) || notEmpty(anno.options.pageNumber)) {
7921              found = true;
7922              break;
7923            }
7924
7925          case 'reference':
7926          case 'text':
7927          case 'freetext':
7928            found = true;
7929            break;
7930        }
7931      }
7932
7933      if (found == false) {
7934        return;
7935      }
7936
7937      this.internal.write("/Annots [");
7938      var pageHeight = this.internal.pageSize.height;
7939      var getHorizontalCoordinateString = this.internal.getCoordinateString;
7940      var getVerticalCoordinateString = this.internal.getVerticalCoordinateString;
7941
7942      for (var a = 0; a < pageAnnos.length; a++) {
7943        var anno = pageAnnos[a];
7944
7945        switch (anno.type) {
7946          case 'reference':
7947            // References to Widget Annotations (for AcroForm Fields)
7948            this.internal.write(' ' + anno.object.objId + ' 0 R ');
7949            break;
7950
7951          case 'text':
7952            // Create a an object for both the text and the popup
7953            var objText = this.internal.newAdditionalObject();
7954            var objPopup = this.internal.newAdditionalObject();
7955            var title = anno.title || 'Note';
7956            var rect = "/Rect [" + getHorizontalCoordinateString(anno.bounds.x) + " " + getVerticalCoordinateString(anno.bounds.y + anno.bounds.h) + " " + getHorizontalCoordinateString(anno.bounds.x + anno.bounds.w) + " " + getVerticalCoordinateString(anno.bounds.y) + "] ";
7957            line = '<</Type /Annot /Subtype /' + 'Text' + ' ' + rect + '/Contents (' + anno.contents + ')';
7958            line += ' /Popup ' + objPopup.objId + " 0 R";
7959            line += ' /P ' + pageInfo.objId + " 0 R";
7960            line += ' /T (' + title + ') >>';
7961            objText.content = line;
7962            var parent = objText.objId + ' 0 R';
7963            var popoff = 30;
7964            var rect = "/Rect [" + getHorizontalCoordinateString(anno.bounds.x + popoff) + " " + getVerticalCoordinateString(anno.bounds.y + anno.bounds.h) + " " + getHorizontalCoordinateString(anno.bounds.x + anno.bounds.w + popoff) + " " + getVerticalCoordinateString(anno.bounds.y) + "] ";
7965            line = '<</Type /Annot /Subtype /' + 'Popup' + ' ' + rect + ' /Parent ' + parent;
7966
7967            if (anno.open) {
7968              line += ' /Open true';
7969            }
7970
7971            line += ' >>';
7972            objPopup.content = line;
7973            this.internal.write(objText.objId, '0 R', objPopup.objId, '0 R');
7974            break;
7975
7976          case 'freetext':
7977            var rect = "/Rect [" + getHorizontalCoordinateString(anno.bounds.x) + " " + getVerticalCoordinateString(anno.bounds.y) + " " + getHorizontalCoordinateString(anno.bounds.x + anno.bounds.w) + " " + getVerticalCoordinateString(anno.bounds.y + anno.bounds.h) + "] ";
7978            var color = anno.color || '#000000';
7979            line = '<</Type /Annot /Subtype /' + 'FreeText' + ' ' + rect + '/Contents (' + anno.contents + ')';
7980            line += ' /DS(font: Helvetica,sans-serif 12.0pt; text-align:left; color:#' + color + ')';
7981            line += ' /Border [0 0 0]';
7982            line += ' >>';
7983            this.internal.write(line);
7984            break;
7985
7986          case 'link':
7987            if (anno.options.name) {
7988              var loc = this.annotations._nameMap[anno.options.name];
7989              anno.options.pageNumber = loc.page;
7990              anno.options.top = loc.y;
7991            } else {
7992              if (!anno.options.top) {
7993                anno.options.top = 0;
7994              }
7995            }
7996
7997            var rect = "/Rect [" + getHorizontalCoordinateString(anno.x) + " " + getVerticalCoordinateString(anno.y) + " " + getHorizontalCoordinateString(anno.x + anno.w) + " " + getVerticalCoordinateString(anno.y + anno.h) + "] ";
7998            var line = '';
7999
8000            if (anno.options.url) {
8001              line = '<</Type /Annot /Subtype /Link ' + rect + '/Border [0 0 0] /A <</S /URI /URI (' + anno.options.url + ') >>';
8002            } else if (anno.options.pageNumber) {
8003              // first page is 0
8004              var info = this.internal.getPageInfo(anno.options.pageNumber);
8005              line = '<</Type /Annot /Subtype /Link ' + rect + '/Border [0 0 0] /Dest [' + info.objId + " 0 R";
8006              anno.options.magFactor = anno.options.magFactor || "XYZ";
8007
8008              switch (anno.options.magFactor) {
8009                case 'Fit':
8010                  line += ' /Fit]';
8011                  break;
8012
8013                case 'FitH':
8014                  line += ' /FitH ' + anno.options.top + ']';
8015                  break;
8016
8017                case 'FitV':
8018                  anno.options.left = anno.options.left || 0;
8019                  line += ' /FitV ' + anno.options.left + ']';
8020                  break;
8021
8022                case 'XYZ':
8023                default:
8024                  var top = getVerticalCoordinateString(anno.options.top);
8025                  anno.options.left = anno.options.left || 0; // 0 or null zoom will not change zoom factor
8026
8027                  if (typeof anno.options.zoom === 'undefined') {
8028                    anno.options.zoom = 0;
8029                  }
8030
8031                  line += ' /XYZ ' + anno.options.left + ' ' + top + ' ' + anno.options.zoom + ']';
8032                  break;
8033              }
8034            }
8035
8036            if (line != '') {
8037              line += " >>";
8038              this.internal.write(line);
8039            }
8040
8041            break;
8042        }
8043      }
8044
8045      this.internal.write("]");
8046    }]);
8047    /**
8048    * @name createAnnotation
8049    * @function
8050    * @param {Object} options 
8051    */
8052
vendor: 21,206 bytes, lines 8053-8708
8053    jsPDFAPI.createAnnotation = function (options) {
8054      var pageInfo = this.internal.getCurrentPageInfo();
8055
8056      switch (options.type) {
8057        case 'link':
8058          this.link(options.bounds.x, options.bounds.y, options.bounds.w, options.bounds.h, options);
8059          break;
8060
8061        case 'text':
8062        case 'freetext':
8063          pageInfo.pageContext.annotations.push(options);
8064          break;
8065      }
8066    };
8067    /**
8068     * Create a link
8069     *
8070     * valid options
8071     * <li> pageNumber or url [required]
8072     * <p>If pageNumber is specified, top and zoom may also be specified</p>
8073     * @name link
8074     * @function
8075     * @param {number} x
8076     * @param {number} y
8077     * @param {number} w
8078     * @param {number} h
8079     * @param {Object} options
8080     */
8081
8082
8083    jsPDFAPI.link = function (x, y, w, h, options) {
8084      var pageInfo = this.internal.getCurrentPageInfo();
8085      pageInfo.pageContext.annotations.push({
8086        x: x,
8087        y: y,
8088        w: w,
8089        h: h,
8090        options: options,
8091        type: 'link'
8092      });
8093    };
8094    /**
8095     * Currently only supports single line text.
8096     * Returns the width of the text/link
8097     *
8098     * @name textWithLink
8099     * @function
8100     * @param {string} text
8101     * @param {number} x
8102     * @param {number} y
8103     * @param {Object} options
8104     * @returns {number} width the width of the text/link
8105     */
8106
8107
8108    jsPDFAPI.textWithLink = function (text, x, y, options) {
8109      var width = this.getTextWidth(text);
8110      var height = this.internal.getLineHeight() / this.internal.scaleFactor;
8111      this.text(text, x, y); //TODO We really need the text baseline height to do this correctly.
8112      // Or ability to draw text on top, bottom, center, or baseline.
8113
8114      y += height * .2;
8115      this.link(x, y - height, width, height, options);
8116      return width;
8117    }; //TODO move into external library
8118
8119    /**
8120    * @name getTextWidth
8121    * @function
8122    * @param {string} text
8123    * @returns {number} txtWidth
8124    */
8125
8126
8127    jsPDFAPI.getTextWidth = function (text) {
8128      var fontSize = this.internal.getFontSize();
8129      var txtWidth = this.getStringUnitWidth(text) * fontSize / this.internal.scaleFactor;
8130      return txtWidth;
8131    };
8132
8133    return this;
8134  })(jsPDF.API);
8135
8136  /**
8137   * @license
8138   * Copyright (c) 2017 Aras Abbasi 
8139   *
8140   * Licensed under the MIT License.
8141   * http://opensource.org/licenses/mit-license
8142   */
8143
8144  /**
8145  * jsPDF arabic parser PlugIn
8146  *
8147  * @name arabic
8148  * @module
8149  */
8150  (function (jsPDFAPI) {
8151    /**
8152     * Arabic shape substitutions: char code => (isolated, final, initial, medial).
8153     * Arabic Substition A
8154     */
8155
8156    var arabicSubstitionA = {
8157      0x0621: [0xFE80],
8158      // ARABIC LETTER HAMZA 
8159      0x0622: [0xFE81, 0xFE82],
8160      // ARABIC LETTER ALEF WITH MADDA ABOVE
8161      0x0623: [0xFE83, 0xFE84],
8162      // ARABIC LETTER ALEF WITH HAMZA ABOVE
8163      0x0624: [0xFE85, 0xFE86],
8164      // ARABIC LETTER WAW WITH HAMZA ABOVE
8165      0x0625: [0xFE87, 0xFE88],
8166      // ARABIC LETTER ALEF WITH HAMZA BELOW
8167      0x0626: [0xFE89, 0xFE8A, 0xFE8B, 0xFE8C],
8168      // ARABIC LETTER YEH WITH HAMZA ABOVE 
8169      0x0627: [0xFE8D, 0xFE8E],
8170      // ARABIC LETTER ALEF
8171      0x0628: [0xFE8F, 0xFE90, 0xFE91, 0xFE92],
8172      // ARABIC LETTER BEH
8173      0x0629: [0xFE93, 0xFE94],
8174      // ARABIC LETTER TEH MARBUTA 
8175      0x062A: [0xFE95, 0xFE96, 0xFE97, 0xFE98],
8176      // ARABIC LETTER TEH
8177      0x062B: [0xFE99, 0xFE9A, 0xFE9B, 0xFE9C],
8178      // ARABIC LETTER THEH
8179      0x062C: [0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0],
8180      // ARABIC LETTER JEEM
8181      0x062D: [0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4],
8182      // ARABIC LETTER HAH
8183      0x062E: [0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8],
8184      // ARABIC LETTER KHAH
8185      0x062F: [0xFEA9, 0xFEAA],
8186      // ARABIC LETTER DAL
8187      0x0630: [0xFEAB, 0xFEAC],
8188      // ARABIC LETTER THAL
8189      0x0631: [0xFEAD, 0xFEAE],
8190      // ARABIC LETTER REH
8191      0x0632: [0xFEAF, 0xFEB0],
8192      // ARABIC LETTER ZAIN
8193      0x0633: [0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4],
8194      // ARABIC LETTER SEEN
8195      0x0634: [0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8],
8196      // ARABIC LETTER SHEEN 
8197      0x0635: [0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC],
8198      // ARABIC LETTER SAD
8199      0x0636: [0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0],
8200      // ARABIC LETTER DAD
8201      0x0637: [0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4],
8202      // ARABIC LETTER TAH
8203      0x0638: [0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8],
8204      // ARABIC LETTER ZAH
8205      0x0639: [0xFEC9, 0xFECA, 0xFECB, 0xFECC],
8206      // ARABIC LETTER AIN
8207      0x063A: [0xFECD, 0xFECE, 0xFECF, 0xFED0],
8208      // ARABIC LETTER GHAIN 
8209      0x0641: [0xFED1, 0xFED2, 0xFED3, 0xFED4],
8210      // ARABIC LETTER FEH
8211      0x0642: [0xFED5, 0xFED6, 0xFED7, 0xFED8],
8212      // ARABIC LETTER QAF
8213      0x0643: [0xFED9, 0xFEDA, 0xFEDB, 0xFEDC],
8214      // ARABIC LETTER KAF
8215      0x0644: [0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0],
8216      // ARABIC LETTER LAM
8217      0x0645: [0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4],
8218      // ARABIC LETTER MEEM
8219      0x0646: [0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8],
8220      // ARABIC LETTER NOON 
8221      0x0647: [0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC],
8222      // ARABIC LETTER HEH
8223      0x0648: [0xFEED, 0xFEEE],
8224      // ARABIC LETTER WAW
8225      0x0649: [0xFEEF, 0xFEF0, 64488, 64489],
8226      // ARABIC LETTER ALEF MAKSURA 
8227      0x064A: [0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4],
8228      // ARABIC LETTER YEH
8229      0x0671: [0xFB50, 0xFB51],
8230      // ARABIC LETTER ALEF WASLA
8231      0x0677: [0xFBDD],
8232      // ARABIC LETTER U WITH HAMZA ABOVE
8233      0x0679: [0xFB66, 0xFB67, 0xFB68, 0xFB69],
8234      // ARABIC LETTER TTEH
8235      0x067A: [0xFB5E, 0xFB5F, 0xFB60, 0xFB61],
8236      // ARABIC LETTER TTEHEH
8237      0x067B: [0xFB52, 0xFB53, 0xFB54, 0xFB55],
8238      // ARABIC LETTER BEEH
8239      0x067E: [0xFB56, 0xFB57, 0xFB58, 0xFB59],
8240      // ARABIC LETTER PEH 
8241      0x067F: [0xFB62, 0xFB63, 0xFB64, 0xFB65],
8242      // ARABIC LETTER TEHEH
8243      0x0680: [0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D],
8244      // ARABIC LETTER BEHEH
8245      0x0683: [0xFB76, 0xFB77, 0xFB78, 0xFB79],
8246      // ARABIC LETTER NYEH
8247      0x0684: [0xFB72, 0xFB73, 0xFB74, 0xFB75],
8248      // ARABIC LETTER DYEH
8249      0x0686: [0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D],
8250      // ARABIC LETTER TCHEH
8251      0x0687: [0xFB7E, 0xFB7F, 0xFB80, 0xFB81],
8252      // ARABIC LETTER TCHEHEH
8253      0x0688: [0xFB88, 0xFB89],
8254      // ARABIC LETTER DDAL
8255      0x068C: [0xFB84, 0xFB85],
8256      // ARABIC LETTER DAHAL
8257      0x068D: [0xFB82, 0xFB83],
8258      // ARABIC LETTER DDAHAL
8259      0x068E: [0xFB86, 0xFB87],
8260      // ARABIC LETTER DUL 
8261      0x0691: [0xFB8C, 0xFB8D],
8262      // ARABIC LETTER RREH
8263      0x0698: [0xFB8A, 0xFB8B],
8264      // ARABIC LETTER JEH
8265      0x06A4: [0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D],
8266      // ARABIC LETTER VEH
8267      0x06A6: [0xFB6E, 0xFB6F, 0xFB70, 0xFB71],
8268      // ARABIC LETTER PEHEH
8269      0x06A9: [0xFB8E, 0xFB8F, 0xFB90, 0xFB91],
8270      // ARABIC LETTER KEHEH
8271      0x06AD: [0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6],
8272      // ARABIC LETTER NG
8273      0x06AF: [0xFB92, 0xFB93, 0xFB94, 0xFB95],
8274      // ARABIC LETTER GAF
8275      0x06B1: [0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D],
8276      // ARABIC LETTER NGOEH
8277      0x06B3: [0xFB96, 0xFB97, 0xFB98, 0xFB99],
8278      // ARABIC LETTER GUEH
8279      0x06BA: [0xFB9E, 0xFB9F],
8280      // ARABIC LETTER NOON GHUNNA
8281      0x06BB: [0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3],
8282      // ARABIC LETTER RNOON
8283      0x06BE: [0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD],
8284      // ARABIC LETTER HEH DOACHASHMEE
8285      0x06C0: [0xFBA4, 0xFBA5],
8286      // ARABIC LETTER HEH WITH YEH ABOVE
8287      0x06C1: [0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9],
8288      // ARABIC LETTER HEH GOAL
8289      0x06C5: [0xFBE0, 0xFBE1],
8290      // ARABIC LETTER KIRGHIZ OE
8291      0x06C6: [0xFBD9, 0xFBDA],
8292      // ARABIC LETTER OE
8293      0x06C7: [0xFBD7, 0xFBD8],
8294      // ARABIC LETTER U
8295      0x06C8: [0xFBDB, 0xFBDC],
8296      // ARABIC LETTER YU
8297      0x06C9: [0xFBE2, 0xFBE3],
8298      // ARABIC LETTER KIRGHIZ YU
8299      0x06CB: [0xFBDE, 0xFBDF],
8300      // ARABIC LETTER VE
8301      0x06CC: [0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF],
8302      // ARABIC LETTER FARSI YEH
8303      0x06D0: [0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7],
8304      //ARABIC LETTER E
8305      0x06D2: [0xFBAE, 0xFBAF],
8306      // ARABIC LETTER YEH BARREE
8307      0x06D3: [0xFBB0, 0xFBB1] // ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
8308
8309    };
8310    var ligatures = {
8311      0xFEDF: {
8312        0xFE82: 0xFEF5,
8313        // ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
8314        0xFE84: 0xFEF7,
8315        // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
8316        0xFE88: 0xFEF9,
8317        // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM
8318        0xFE8E: 0xFEFB // ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
8319
8320      },
8321      0xFEE0: {
8322        0xFE82: 0xFEF6,
8323        // ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
8324        0xFE84: 0xFEF8,
8325        // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
8326        0xFE88: 0xFEFA,
8327        // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM
8328        0xFE8E: 0xFEFC // ARABIC LIGATURE LAM WITH ALEF FINAL FORM
8329
8330      },
8331      0xFE8D: {
8332        0xFEDF: {
8333          0xFEE0: {
8334            0xFEEA: 0xFDF2
8335          }
8336        }
8337      },
8338      // ALLAH
8339      0x0651: {
8340        0x064C: 0xFC5E,
8341        // Shadda + Dammatan
8342        0x064D: 0xFC5F,
8343        // Shadda + Kasratan
8344        0x064E: 0xFC60,
8345        // Shadda + Fatha
8346        0x064F: 0xFC61,
8347        // Shadda + Damma
8348        0x0650: 0xFC62 // Shadda + Kasra
8349
8350      }
8351    };
8352    var arabic_diacritics = {
8353      1612: 64606,
8354      // Shadda + Dammatan
8355      1613: 64607,
8356      // Shadda + Kasratan
8357      1614: 64608,
8358      // Shadda + Fatha
8359      1615: 64609,
8360      // Shadda + Damma
8361      1616: 64610 // Shadda + Kasra
8362
8363    };
8364    var alfletter = [1570, 1571, 1573, 1575];
8365    var noChangeInForm = -1;
8366    var isolatedForm = 0;
8367    var finalForm = 1;
8368    var initialForm = 2;
8369    var medialForm = 3;
8370    jsPDFAPI.__arabicParser__ = {}; //private
8371
8372    var isInArabicSubstitutionA = jsPDFAPI.__arabicParser__.isInArabicSubstitutionA = function (letter) {
8373      return typeof arabicSubstitionA[letter.charCodeAt(0)] !== "undefined";
8374    };
8375
8376    var isArabicLetter = jsPDFAPI.__arabicParser__.isArabicLetter = function (letter) {
8377      return typeof letter === "string" && /^[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]+$/.test(letter);
8378    };
8379
8380    var isArabicEndLetter = jsPDFAPI.__arabicParser__.isArabicEndLetter = function (letter) {
8381      return isArabicLetter(letter) && isInArabicSubstitutionA(letter) && arabicSubstitionA[letter.charCodeAt(0)].length <= 2;
8382    };
8383
8384    var isArabicAlfLetter = jsPDFAPI.__arabicParser__.isArabicAlfLetter = function (letter) {
8385      return isArabicLetter(letter) && alfletter.indexOf(letter.charCodeAt(0)) >= 0;
8386    };
8387
8388    var arabicLetterHasIsolatedForm = jsPDFAPI.__arabicParser__.arabicLetterHasIsolatedForm = function (letter) {
8389      return isArabicLetter(letter) && isInArabicSubstitutionA(letter) && arabicSubstitionA[letter.charCodeAt(0)].length >= 1;
8390    };
8391
8392    var arabicLetterHasFinalForm = jsPDFAPI.__arabicParser__.arabicLetterHasFinalForm = function (letter) {
8393      return isArabicLetter(letter) && isInArabicSubstitutionA(letter) && arabicSubstitionA[letter.charCodeAt(0)].length >= 2;
8394    };
8395
8396    var arabicLetterHasInitialForm = jsPDFAPI.__arabicParser__.arabicLetterHasInitialForm = function (letter) {
8397      return isArabicLetter(letter) && isInArabicSubstitutionA(letter) && arabicSubstitionA[letter.charCodeAt(0)].length >= 3;
8398    };
8399
8400    var arabicLetterHasMedialForm = jsPDFAPI.__arabicParser__.arabicLetterHasMedialForm = function (letter) {
8401      return isArabicLetter(letter) && isInArabicSubstitutionA(letter) && arabicSubstitionA[letter.charCodeAt(0)].length == 4;
8402    };
8403
8404    var resolveLigatures = jsPDFAPI.__arabicParser__.resolveLigatures = function (letters) {
8405      var i = 0;
8406      var tmpLigatures = ligatures;
8407      var position = isolatedForm;
8408      var result = '';
8409      var effectedLetters = 0;
8410
8411      for (i = 0; i < letters.length; i += 1) {
8412        if (typeof tmpLigatures[letters.charCodeAt(i)] !== "undefined") {
8413          effectedLetters++;
8414          tmpLigatures = tmpLigatures[letters.charCodeAt(i)];
8415
8416          if (typeof tmpLigatures === "number") {
8417            position = getCorrectForm(letters.charAt(i), letters.charAt(i - effectedLetters), letters.charAt(i + 1));
8418            position = position !== -1 ? position : 0;
8419            result += String.fromCharCode(tmpLigatures);
8420            tmpLigatures = ligatures;
8421            effectedLetters = 0;
8422          }
8423
8424          if (i === letters.length - 1) {
8425            tmpLigatures = ligatures;
8426            result += letters.charAt(i - (effectedLetters - 1));
8427            i = i - (effectedLetters - 1);
8428            effectedLetters = 0;
8429          }
8430        } else {
8431          tmpLigatures = ligatures;
8432          result += letters.charAt(i - effectedLetters);
8433          i = i - effectedLetters;
8434          effectedLetters = 0;
8435        }
8436      }
8437
8438      return result;
8439    };
8440
8441    var isArabicDiacritic = jsPDFAPI.__arabicParser__.isArabicDiacritic = function (letter) {
8442      return letter !== undefined && arabic_diacritics[letter.charCodeAt(0)] !== undefined;
8443    };
8444
8445    var getCorrectForm = jsPDFAPI.__arabicParser__.getCorrectForm = function (currentChar, beforeChar, nextChar) {
8446
8447      if (!isArabicLetter(currentChar)) {
8448        return -1;
8449      }
8450
8451      if (isInArabicSubstitutionA(currentChar) === false) {
8452        return noChangeInForm;
8453      }
8454
8455      if (!arabicLetterHasFinalForm(currentChar) || !isArabicLetter(beforeChar) && !isArabicLetter(nextChar) || !isArabicLetter(nextChar) && isArabicEndLetter(beforeChar) || isArabicEndLetter(currentChar) && !isArabicLetter(beforeChar) || isArabicEndLetter(currentChar) && isArabicAlfLetter(beforeChar) || isArabicEndLetter(currentChar) && isArabicEndLetter(beforeChar)) {
8456        return isolatedForm;
8457      }
8458
8459      if (arabicLetterHasMedialForm(currentChar) && isArabicLetter(beforeChar) && !isArabicEndLetter(beforeChar) && isArabicLetter(nextChar) && arabicLetterHasFinalForm(nextChar)) {
8460        return medialForm;
8461      }
8462
8463      if (isArabicEndLetter(currentChar) || !isArabicLetter(nextChar)) {
8464        return finalForm;
8465      }
8466
8467      return initialForm;
8468    };
8469    /**
8470    * @name processArabic
8471    * @function
8472    * @param {string} text
8473    * @param {boolean} reverse
8474    * @returns {string}
8475    */
8476
8477
8478    var processArabic = jsPDFAPI.__arabicParser__.processArabic = jsPDFAPI.processArabic = function (text) {
8479      text = text || "";
8480      var result = "";
8481      var i = 0;
8482      var j = 0;
8483      var position = 0;
8484      var currentLetter = "";
8485      var prevLetter = "";
8486      var nextLetter = "";
8487      var words = text.split("\\s+");
8488      var newWords = [];
8489
8490      for (i = 0; i < words.length; i += 1) {
8491        newWords.push('');
8492
8493        for (j = 0; j < words[i].length; j += 1) {
8494          currentLetter = words[i][j];
8495          prevLetter = words[i][j - 1];
8496          nextLetter = words[i][j + 1];
8497
8498          if (isArabicLetter(currentLetter)) {
8499            position = getCorrectForm(currentLetter, prevLetter, nextLetter);
8500
8501            if (position !== -1) {
8502              newWords[i] += String.fromCharCode(arabicSubstitionA[currentLetter.charCodeAt(0)][position]);
8503            } else {
8504              newWords[i] += currentLetter;
8505            }
8506          } else {
8507            newWords[i] += currentLetter;
8508          }
8509        }
8510
8511        newWords[i] = resolveLigatures(newWords[i]);
8512      }
8513
8514      result = newWords.join(' ');
8515      return result;
8516    };
8517
8518    var arabicParserFunction = function arabicParserFunction(args) {
8519      var text = args.text;
8520      var x = args.x;
8521      var y = args.y;
8522      var options = args.options || {};
8523      var mutex = args.mutex || {};
8524      var lang = options.lang;
8525      var tmpText = [];
8526
8527      if (Object.prototype.toString.call(text) === '[object Array]') {
8528        var i = 0;
8529        tmpText = [];
8530
8531        for (i = 0; i < text.length; i += 1) {
8532          if (Object.prototype.toString.call(text[i]) === '[object Array]') {
8533            tmpText.push([processArabic(text[i][0]), text[i][1], text[i][2]]);
8534          } else {
8535            tmpText.push([processArabic(text[i])]);
8536          }
8537        }
8538
8539        args.text = tmpText;
8540      } else {
8541        args.text = processArabic(text);
8542      }
8543    };
8544
8545    jsPDFAPI.events.push(['preProcessText', arabicParserFunction]);
8546  })(jsPDF.API);
8547
8548  /** @license
8549   * jsPDF Autoprint Plugin
8550   *
8551   * Licensed under the MIT License.
8552   * http://opensource.org/licenses/mit-license
8553   */
8554
8555  /**
8556  * @name autoprint
8557  * @module
8558  */
8559  (function (jsPDFAPI) {
8560    /**
8561    * Makes the PDF automatically print. This works in Chrome, Firefox, Acrobat
8562    * Reader.
8563    *
8564    * @name autoPrint
8565    * @function
8566    * @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 .
8567    * @returns {jsPDF}
8568    * @example
8569    * var doc = new jsPDF();
8570    * doc.text(10, 10, 'This is a test');
8571    * doc.autoPrint({variant: 'non-conform'});
8572    * doc.save('autoprint.pdf');
8573    */
8574
8575    jsPDFAPI.autoPrint = function (options) {
8576
8577      var refAutoPrintTag;
8578      options = options || {};
8579      options.variant = options.variant || 'non-conform';
8580
8581      switch (options.variant) {
8582        case 'javascript':
8583          //https://github.com/Rob--W/pdf.js/commit/c676ecb5a0f54677b9f3340c3ef2cf42225453bb
8584          this.addJS('print({});');
8585          break;
8586
8587        case 'non-conform':
8588        default:
8589          this.internal.events.subscribe('postPutResources', function () {
8590            refAutoPrintTag = this.internal.newObject();
8591            this.internal.out("<<");
8592            this.internal.out("/S /Named");
8593            this.internal.out("/Type /Action");
8594            this.internal.out("/N /Print");
8595            this.internal.out(">>");
8596            this.internal.out("endobj");
8597          });
8598          this.internal.events.subscribe("putCatalog", function () {
8599            this.internal.out("/OpenAction " + refAutoPrintTag + " 0 R");
8600          });
8601          break;
8602      }
8603
8604      return this;
8605    };
8606  })(jsPDF.API);
8607
8608  /**
8609   * @license
8610   * Copyright (c) 2014 Steven Spungin (TwelveTone LLC)  [email protected]
8611   *
8612   * Licensed under the MIT License.
8613   * http://opensource.org/licenses/mit-license
8614   */
8615
8616  /**
8617   * jsPDF Canvas PlugIn
8618   * This plugin mimics the HTML5 Canvas
8619   * 
8620   * The goal is to provide a way for current canvas users to print directly to a PDF.
8621   * @name canvas
8622   * @module
8623   */
8624  (function (jsPDFAPI) {
8625    /**
8626    * @class Canvas
8627    * @classdesc A Canvas Wrapper for jsPDF
8628    */
8629
8630    var Canvas = function Canvas() {
8631      var jsPdfInstance = undefined;
8632      Object.defineProperty(this, 'pdf', {
8633        get: function get() {
8634          return jsPdfInstance;
8635        },
8636        set: function set(value) {
8637          jsPdfInstance = value;
8638        }
8639      });
8640      var _width = 150;
8641      /**
8642      * 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.
8643      * This is one of the two properties, the other being width, that controls the size of the canvas.
8644      *
8645      * @name width
8646      */
8647
8648      Object.defineProperty(this, 'width', {
8649        get: function get() {
8650          return _width;
8651        },
8652        set: function set(value) {
8653          if (isNaN(value) || Number.isInteger(value) === false || value < 0) {
8654            _width = 150;
8655          } else {
8656            _width = value;
8657          }
8658
8659          if (this.getContext('2d').pageWrapXEnabled) {
8660            this.getContext('2d').pageWrapX = _width + 1;
8661          }
8662        }
8663      });
8664      var _height = 300;
8665      /**
8666      * 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.
8667      * This is one of the two properties, the other being height, that controls the size of the canvas.
8668      *
8669      * @name height
8670      */
8671
8672      Object.defineProperty(this, 'height', {
8673        get: function get() {
8674          return _height;
8675        },
8676        set: function set(value) {
8677          if (isNaN(value) || Number.isInteger(value) === false || value < 0) {
8678            _height = 300;
8679          } else {
8680            _height = value;
8681          }
8682
8683          if (this.getContext('2d').pageWrapYEnabled) {
8684            this.getContext('2d').pageWrapY = _height + 1;
8685          }
8686        }
8687      });
8688      var _childNodes = [];
8689      Object.defineProperty(this, 'childNodes', {
8690        get: function get() {
8691          return _childNodes;
8692        },
8693        set: function set(value) {
8694          _childNodes = value;
8695        }
8696      });
8697      var _style = {};
8698      Object.defineProperty(this, 'style', {
8699        get: function get() {
8700          return _style;
8701        },
8702        set: function set(value) {
8703          _style = value;
8704        }
8705      });
8706      Object.defineProperty(this, 'parentNode', {
8707        get: function get() {
8708          return false;
8709        }
8710      });
8711    };
8712    /**
8713    * The getContext() method returns a drawing context on the canvas, or null if the context identifier is not supported.
8714    * 
8715    * @name getContext
8716    * @function
8717    * @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.
8718    * @param {object} contextAttributes
8719    */
8720
8721
8722    Canvas.prototype.getContext = function (contextType, contextAttributes) {
8723      contextType = contextType || '2d';
8724      var key;
8725
8726      if (contextType !== '2d') {
8727        return null;
8728      }
8729
8730      for (key in contextAttributes) {
8731        if (this.pdf.context2d.hasOwnProperty(key)) {
8732          this.pdf.context2d[key] = contextAttributes[key];
8733        }
8734      }
8735
8736      this.pdf.context2d._canvas = this;
8737      return this.pdf.context2d;
8738    };
8739    /**
8740    * The toDataURL() method is just a stub to throw an error if accidently called.
8741    * 
8742    * @name toDataURL
8743    * @function
8744    */
8745
8746
8747    Canvas.prototype.toDataURL = function () {
8748      throw new Error('toDataURL is not implemented.');
8749    };
8750
8751    jsPDFAPI.events.push(['initialized', function () {
8752      this.canvas = new Canvas();
8753      this.canvas.pdf = this;
8754    }]);
8755    return this;
8756  })(jsPDF.API);
8757
8758  /** 
8759   * @license
8760   * ====================================================================
8761   * Copyright (c) 2013 Youssef Beddad, [email protected]
8762   *               2013 Eduardo Menezes de Morais, [email protected]
8763   *               2013 Lee Driscoll, https://github.com/lsdriscoll
8764   *               2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
8765   *               2014 James Hall, [email protected]
8766   *               2014 Diego Casorran, https://github.com/diegocr
8767   *
8768   * 
8769   * ====================================================================
8770   */
8771
8772  /**
8773  * @name cell
8774  * @module
8775  */
8776  (function (jsPDFAPI) {
8777    /*jslint browser:true */
8778
8779    /*global document: false, jsPDF */
8780
8781    var padding = 3,
8782        margin = 13,
8783        headerFunction,
8784        lastCellPos = {
8785      x: undefined,
8786      y: undefined,
8787      w: undefined,
8788      h: undefined,
8789      ln: undefined
8790    },
8791        pages = 1,
8792        setLastCellPosition = function setLastCellPosition(x, y, w, h, ln) {
8793      lastCellPos = {
8794        'x': x,
8795        'y': y,
8796        'w': w,
8797        'h': h,
8798        'ln': ln
8799      };
8800    },
8801        getLastCellPosition = function getLastCellPosition() {
8802      return lastCellPos;
8803    },
8804        NO_MARGINS = {
8805      left: 0,
8806      top: 0,
8807      bottom: 0
8808    };
8809    /**
8810    * @name setHeaderFunction
8811    * @function
8812    * @param {function} func
8813    */
8814
8815
8816    jsPDFAPI.setHeaderFunction = function (func) {
8817      headerFunction = func;
8818    };
8819    /**
8820    * @name getTextDimensions
8821    * @function
8822    * @param {string} txt
8823    * @returns {Object} dimensions
8824    */
8825
8826
8827    jsPDFAPI.getTextDimensions = function (text, options) {
8828      var fontSize = this.table_font_size || this.internal.getFontSize();
8829      var fontStyle = this.internal.getFont().fontStyle;
8830      options = options || {};
8831      var scaleFactor = options.scaleFactor || this.internal.scaleFactor;
8832      var width = 0;
8833      var amountOfLines = 0;
8834      var height = 0;
8835      var tempWidth = 0;
8836
8837      if (typeof text === 'string') {
8838        width = this.getStringUnitWidth(text) * fontSize;
8839
8840        if (width !== 0) {
8841          amountOfLines = 1;
8842        }
8843      } else if (Object.prototype.toString.call(text) === '[object Array]') {
8844        for (var i = 0; i < text.length; i++) {
8845          tempWidth = this.getStringUnitWidth(text[i]) * fontSize;
8846
8847          if (width < tempWidth) {
8848            width = tempWidth;
8849          }
8850        }
8851
8852        if (width !== 0) {
8853          amountOfLines = text.length;
8854        }
8855      } else {
8856        throw new Error('getTextDimensions expects text-parameter to be of type String or an Array of Strings.');
8857      }
8858
8859      width = width / scaleFactor;
8860      height = Math.max((amountOfLines * fontSize * this.getLineHeightFactor() - fontSize * (this.getLineHeightFactor() - 1)) / scaleFactor, 0);
8861      return {
8862        w: width,
8863        h: height
8864      };
8865    };
8866    /**
8867    * @name cellAddPage
8868    * @function
8869    */
8870
8871
8872    jsPDFAPI.cellAddPage = function () {
8873      var margins = this.margins || NO_MARGINS;
8874      this.addPage();
8875      setLastCellPosition(margins.left, margins.top, undefined, undefined); //setLastCellPosition(undefined, undefined, undefined, undefined, undefined);
8876
8877      pages += 1;
8878    };
8879    /**
8880    * @name cellInitialize
8881    * @function
8882    */
8883
8884
8885    jsPDFAPI.cellInitialize = function () {
8886      lastCellPos = {
8887        x: undefined,
8888        y: undefined,
8889        w: undefined,
8890        h: undefined,
8891        ln: undefined
8892      };
8893      pages = 1;
8894    };
8895    /**
8896    * @name cell
8897    * @function
8898    * @param {number} x
8899    * @param {number} y
8900    * @param {number} w
8901    * @param {number} h
8902    * @param {string} txt
8903    * @param {number} ln lineNumber
8904    * @param {string} align
8905    * @return {jsPDF} jsPDF-instance
8906    */
8907
8908
8909    jsPDFAPI.cell = function (x, y, w, h, txt, ln, align) {
8910      var curCell = getLastCellPosition();
8911      var pgAdded = false; // If this is not the first cell, we must change its position
8912
8913      if (curCell.ln !== undefined) {
8914        if (curCell.ln === ln) {
8915          //Same line
8916          x = curCell.x + curCell.w;
8917          y = curCell.y;
8918        } else {
8919          //New line
8920          var margins = this.margins || NO_MARGINS;
8921
8922          if (curCell.y + curCell.h + h + margin >= this.internal.pageSize.getHeight() - margins.bottom) {
8923            this.cellAddPage();
8924            pgAdded = true;
8925
8926            if (this.printHeaders && this.tableHeaderRow) {
8927              this.printHeaderRow(ln, true);
8928            }
8929          } //We ignore the passed y: the lines may have different heights
8930
8931
8932          y = getLastCellPosition().y + getLastCellPosition().h;
8933          if (pgAdded) y = margin + 10;
8934        }
8935      }
8936
8937      if (txt[0] !== undefined) {
8938        if (this.printingHeaderRow) {
8939          this.rect(x, y, w, h, 'FD');
8940        } else {
8941          this.rect(x, y, w, h);
8942        }
8943
8944        if (align === 'right') {
8945          if (!(txt instanceof Array)) {
8946            txt = [txt];
8947          }
8948
8949          for (var i = 0; i < txt.length; i++) {
8950            var currentLine = txt[i];
8951            var textSize = this.getStringUnitWidth(currentLine) * this.internal.getFontSize() / this.internal.scaleFactor;
8952            this.text(currentLine, x + w - textSize - padding, y + this.internal.getLineHeight() * (i + 1));
8953          }
8954        } else {
8955          this.text(txt, x + padding, y + this.internal.getLineHeight());
8956        }
8957      }
8958
8959      setLastCellPosition(x, y, w, h, ln);
8960      return this;
8961    };
8962    /**
8963     * Return the maximum value from an array
8964     * 
8965     * @name arrayMax
8966     * @function 
8967     * @param {Array} array
8968     * @param comparisonFn
8969     * @returns {number}
8970     */
8971
8972
8973    jsPDFAPI.arrayMax = function (array, comparisonFn) {
8974      var max = array[0],
8975          i,
8976          ln,
8977          item;
8978
8979      for (i = 0, ln = array.length; i < ln; i += 1) {
8980        item = array[i];
8981
8982        if (comparisonFn) {
8983          if (comparisonFn(max, item) === -1) {
8984            max = item;
8985          }
8986        } else {
8987          if (item > max) {
8988            max = item;
8989          }
8990        }
8991      }
8992
8993      return max;
8994    };
8995    /**
8996     * Create a table from a set of data.
8997     * @name table
8998     * @function
8999     * @param {Integer} [x] : left-position for top-left corner of table
9000     * @param {Integer} [y] top-position for top-left corner of table
9001     * @param {Object[]} [data] As array of objects containing key-value pairs corresponding to a row of data.
9002     * @param {String[]} [headers] Omit or null to auto-generate headers at a performance cost
9003      * @param {Object} [config.printHeaders] True to print column headers at the top of every page
9004     * @param {Object} [config.autoSize] True to dynamically set the column widths to match the widest cell value
9005     * @param {Object} [config.margins] margin values for left, top, bottom, and width
9006     * @param {Object} [config.fontSize] Integer fontSize to use (optional)
9007     * @returns {jsPDF} jsPDF-instance
9008     */
9009
9010
9011    jsPDFAPI.table = function (x, y, data, headers, config) {
9012      if (!data) {
9013        throw 'No data for PDF table';
9014      }
9015
9016      var headerNames = [],
9017          headerPrompts = [],
9018          header,
9019          i,
9020          ln,
9021          cln,
9022          columnMatrix = {},
9023          columnWidths = {},
9024          columnData,
9025          column,
9026          columnMinWidths = [],
9027          j,
9028          tableHeaderConfigs = [],
9029          model,
9030          jln,
9031          func,
9032          //set up defaults. If a value is provided in config, defaults will be overwritten:
9033      autoSize = false,
9034          printHeaders = true,
9035          fontSize = 12,
9036          margins = NO_MARGINS;
9037      margins.width = this.internal.pageSize.getWidth();
9038
9039      if (config) {
9040        //override config defaults if the user has specified non-default behavior:
9041        if (config.autoSize === true) {
9042          autoSize = true;
9043        }
9044
9045        if (config.printHeaders === false) {
9046          printHeaders = false;
9047        }
9048
9049        if (config.fontSize) {
9050          fontSize = config.fontSize;
9051        }
9052
9053        if (config.css && typeof config.css['font-size'] !== "undefined") {
9054          fontSize = config.css['font-size'] * 16;
9055        }
9056
9057        if (config.margins) {
9058          margins = config.margins;
9059        }
9060      }
9061      /**
9062       * @property {Number} lnMod
9063       * Keep track of the current line number modifier used when creating cells
9064       */
9065
9066
9067      this.lnMod = 0;
9068      lastCellPos = {
9069        x: undefined,
9070        y: undefined,
9071        w: undefined,
9072        h: undefined,
9073        ln: undefined
9074      }, pages = 1;
9075      this.printHeaders = printHeaders;
9076      this.margins = margins;
9077      this.setFontSize(fontSize);
9078      this.table_font_size = fontSize; // Set header values
9079
9080      if (headers === undefined || headers === null) {
9081        // No headers defined so we derive from data
9082        headerNames = Object.keys(data[0]);
9083      } else if (headers[0] && typeof headers[0] !== 'string') {
9084        var px2pt = 0.264583 * 72 / 25.4; // Split header configs into names and prompts
9085
9086        for (i = 0, ln = headers.length; i < ln; i += 1) {
9087          header = headers[i];
9088          headerNames.push(header.name);
9089          headerPrompts.push(header.prompt);
9090          columnWidths[header.name] = header.width * px2pt;
9091        }
9092      } else {
9093        headerNames = headers;
9094      }
9095
9096      if (autoSize) {
9097        // Create a matrix of columns e.g., {column_title: [row1_Record, row2_Record]}
9098        func = function func(rec) {
9099          return rec[header];
9100        };
9101
9102        for (i = 0, ln = headerNames.length; i < ln; i += 1) {
9103          header = headerNames[i];
9104          columnMatrix[header] = data.map(func); // get header width
9105
9106          columnMinWidths.push(this.getTextDimensions(headerPrompts[i] || header, {
9107            scaleFactor: 1
9108          }).w);
9109          column = columnMatrix[header]; // get cell widths
9110
9111          for (j = 0, cln = column.length; j < cln; j += 1) {
9112            columnData = column[j];
9113            columnMinWidths.push(this.getTextDimensions(columnData, {
9114              scaleFactor: 1
9115            }).w);
9116          } // get final column width
9117
9118
9119          columnWidths[header] = jsPDFAPI.arrayMax(columnMinWidths); //have to reset
9120
9121          columnMinWidths = [];
9122        }
9123      } // -- Construct the table
9124
9125
9126      if (printHeaders) {
9127        var lineHeight = this.calculateLineHeight(headerNames, columnWidths, headerPrompts.length ? headerPrompts : headerNames); // Construct the header row
9128
9129        for (i = 0, ln = headerNames.length; i < ln; i += 1) {
9130          header = headerNames[i];
9131          tableHeaderConfigs.push([x, y, columnWidths[header], lineHeight, String(headerPrompts.length ? headerPrompts[i] : header)]);
9132        } // Store the table header config
9133
9134
9135        this.setTableHeaderRow(tableHeaderConfigs); // Print the header for the start of the table
9136
9137        this.printHeaderRow(1, false);
9138      } // Construct the data rows
9139
9140
9141      for (i = 0, ln = data.length; i < ln; i += 1) {
9142        var lineHeight;
9143        model = data[i];
9144        lineHeight = this.calculateLineHeight(headerNames, columnWidths, model);
9145
9146        for (j = 0, jln = headerNames.length; j < jln; j += 1) {
9147          header = headerNames[j];
9148          this.cell(x, y, columnWidths[header], lineHeight, model[header], i + 2, header.align);
9149        }
9150      }
9151
9152      this.lastCellPos = lastCellPos;
9153      this.table_x = x;
9154      this.table_y = y;
9155      return this;
9156    };
9157    /**
9158     * Calculate the height for containing the highest column
9159     *
9160     * @name calculateLineHeight
9161     * @function
9162     * @param {String[]} headerNames is the header, used as keys to the data
9163     * @param {Integer[]} columnWidths is size of each column
9164     * @param {Object[]} model is the line of data we want to calculate the height of
9165     * @returns {number} lineHeight
9166     */
9167
9168
9169    jsPDFAPI.calculateLineHeight = function (headerNames, columnWidths, model) {
9170      var header,
9171          lineHeight = 0;
9172
9173      for (var j = 0; j < headerNames.length; j++) {
9174        header = headerNames[j];
9175        model[header] = this.splitTextToSize(String(model[header]), columnWidths[header] - padding);
9176        var h = this.internal.getLineHeight() * model[header].length + padding;
9177        if (h > lineHeight) lineHeight = h;
9178      }
9179
9180      return lineHeight;
9181    };
9182    /**
9183     * Store the config for outputting a table header
9184     *
9185     * @name setTableHeaderRow
9186     * @function
9187     * @param {Object[]} config
9188     * An array of cell configs that would define a header row: Each config matches the config used by jsPDFAPI.
9188cell
9189     * except the ln parameter is excluded
9190     */
9191
9192
9193    jsPDFAPI.setTableHeaderRow = function (config) {
9194      this.tableHeaderRow = config;
9195    };
9196    /**
9197     * Output the store header row
9198     * 
9199     * @name printHeaderRow
9200     * @function
9201     * @param {number} lineNumber The line number to output the header at
9202     * @param {boolean} new_page 
9203     */
9204
9205
9206    jsPDFAPI.printHeaderRow = function (lineNumber, new_page) {
9207      if (!this.tableHeaderRow) {
9208        throw 'Property tableHeaderRow does not exist.';
9209      }
9210
9211      var tableHeaderCell, tmpArray, i, ln;
9212      this.printingHeaderRow = true;
9213
9214      if (headerFunction !== undefined) {
9215        var position = headerFunction(this, pages);
9216        setLastCellPosition(position[0], position[1], position[2], position[3], -1);
9217      }
9218
9219      this.setFontStyle('bold');
9220      var tempHeaderConf = [];
9221
9222      for (i = 0, ln = this.tableHeaderRow.length; i < ln; i += 1) {
9223        this.setFillColor(200, 200, 200);
9224        tableHeaderCell = this.tableHeaderRow[i];
9225
9226        if (new_page) {
9227          this.margins.top = margin;
9228          tableHeaderCell[1] = this.margins && this.margins.top || 0;
9229          tempHeaderConf.push(tableHeaderCell);
9230        }
9231
9232        tmpArray = [].concat(tableHeaderCell);
9233        this.cell.apply(this, tmpArray.concat(lineNumber));
9234      }
9235
9236      if (tempHeaderConf.length > 0) {
9237        this.setTableHeaderRow(tempHeaderConf);
9238      }
9239
9240      this.setFontStyle('normal');
9241      this.printingHeaderRow = false;
9242    };
9243  })(jsPDF.API);
9244
9245  /**
9246   * jsPDF Context2D PlugIn Copyright (c) 2014 Steven Spungin (TwelveTone LLC) [email protected]
9247   *
9248   * Licensed under the MIT License. http://opensource.org/licenses/mit-license
9249   */
9250
9251  /**
9252  * This plugin mimics the HTML5 CanvasRenderingContext2D.
9253  *
9254  * The goal is to provide a way for current canvas implementations to print directly to a PDF.
9255  *
9256  * @name context2d
9257  * @module
9258  */
9259  (function (jsPDFAPI, globalObj) {
9260
9261    var ContextLayer = function ContextLayer(ctx) {
9262      ctx = ctx || {};
9263      this.isStrokeTransparent = ctx.isStrokeTransparent || false;
9264      this.strokeOpacity = ctx.strokeOpacity || 1;
9265      this.strokeStyle = ctx.strokeStyle || '#000000';
9266      this.fillStyle = ctx.fillStyle || '#000000';
9267      this.isFillTransparent = ctx.isFillTransparent || false;
9268      this.fillOpacity = ctx.fillOpacity || 1;
9269      this.font = ctx.font || '10px sans-serif';
9270      this.textBaseline = ctx.textBaseline || 'alphabetic';
9271      this.textAlign = ctx.textAlign || 'left';
9272      this.lineWidth = ctx.lineWidth || 1;
9273      this.lineJoin = ctx.lineJoin || 'miter';
9274      this.lineCap = ctx.lineCap || 'butt';
9275      this.path = ctx.path || [];
9276      this.transform = typeof ctx.transform !== 'undefined' ? ctx.transform.clone() : new Matrix();
9277      this.globalCompositeOperation = ctx.globalCompositeOperation || 'normal';
9278      this.globalAlpha = ctx.globalAlpha || 1.0;
9279      this.clip_path = ctx.clip_path || [];
9280      this.currentPoint = ctx.currentPoint || new Point();
9281      this.miterLimit = ctx.miterLimit || 10.0;
9282      this.lastPoint = ctx.lastPoint || new Point();
9283      this.ignoreClearRect = typeof ctx.ignoreClearRect === "boolean" ? ctx.ignoreClearRect : true;
9284      return this;
9285    }; //stub
9286
9287
9288    var f2, f3, getHorizontalCoordinateString, getVerticalCoordinateString, getHorizontalCoordinate, getVerticalCoordinate;
9289    jsPDFAPI.events.push(['initialized', function () {
9290      this.context2d = new Context2D(this);
9291      f2 = this.internal.f2;
9292      f3 = this.internal.f3;
9293      getHorizontalCoordinateString = this.internal.getCoordinateString;
9294      getVerticalCoordinateString = this.internal.getVerticalCoordinateString;
9295      getHorizontalCoordinate = this.internal.getHorizontalCoordinate;
9296      getVerticalCoordinate = this.internal.getVerticalCoordinate;
9297    }]);
9298
9299    var Context2D = function Context2D(pdf) {
9300      Object.defineProperty(this, 'canvas', {
9301        get: function get() {
9302          return {
9303            parentNode: false,
9304            style: false
9305          };
9306        }
9307      });
9308      Object.defineProperty(this, 'pdf', {
9309        get: function get() {
9310          return pdf;
9311        }
9312      });
9313      var _pageWrapXEnabled = false;
vendor: 5,761 bytes, lines 9314-9533
9314      /**
9315      * @name pageWrapXEnabled
9316      * @type {boolean}
9317      * @default false
9318      */
9319
9320      Object.defineProperty(this, 'pageWrapXEnabled', {
9321        get: function get() {
9322          return _pageWrapXEnabled;
9323        },
9324        set: function set(value) {
9325          _pageWrapXEnabled = Boolean(value);
9326        }
9327      });
9328      var _pageWrapYEnabled = false;
9329      /**
9330      * @name pageWrapYEnabled
9331      * @type {boolean}
9332      * @default true
9333      */
9334
9335      Object.defineProperty(this, 'pageWrapYEnabled', {
9336        get: function get() {
9337          return _pageWrapYEnabled;
9338        },
9339        set: function set(value) {
9340          _pageWrapYEnabled = Boolean(value);
9341        }
9342      });
9343      var _posX = 0;
9344      /**
9345      * @name posX
9346      * @type {number}
9347      * @default 0
9348      */
9349
9350      Object.defineProperty(this, 'posX', {
9351        get: function get() {
9352          return _posX;
9353        },
9354        set: function set(value) {
9355          if (!isNaN(value)) {
9356            _posX = value;
9357          }
9358        }
9359      });
9360      var _posY = 0;
9361      /**
9362      * @name posY
9363      * @type {number}
9364      * @default 0
9365      */
9366
9367      Object.defineProperty(this, 'posY', {
9368        get: function get() {
9369          return _posY;
9370        },
9371        set: function set(value) {
9372          if (!isNaN(value)) {
9373            _posY = value;
9374          }
9375        }
9376      });
9377      var _autoPaging = false;
9378      /**
9379      * @name autoPaging
9380      * @type {boolean}
9381      * @default true
9382      */
9383
9384      Object.defineProperty(this, 'autoPaging', {
9385        get: function get() {
9386          return _autoPaging;
9387        },
9388        set: function set(value) {
9389          _autoPaging = Boolean(value);
9390        }
9391      });
9392      var lastBreak = 0;
9393      /**
9394      * @name lastBreak
9395      * @type {number}
9396      * @default 0
9397      */
9398
9399      Object.defineProperty(this, 'lastBreak', {
9400        get: function get() {
9401          return lastBreak;
9402        },
9403        set: function set(value) {
9404          lastBreak = value;
9405        }
9406      });
9407      var pageBreaks = [];
9408      /**
9409      * Y Position of page breaks.
9410      * @name pageBreaks
9411      * @type {number}
9412      * @default 0
9413      */
9414
9415      Object.defineProperty(this, 'pageBreaks', {
9416        get: function get() {
9417          return pageBreaks;
9418        },
9419        set: function set(value) {
9420          pageBreaks = value;
9421        }
9422      });
9423
9424      var _ctx = new ContextLayer();
9425      /**
9426      * @name ctx
9427      * @type {object}
9428      * @default {}
9429      */
9430
9431
9432      Object.defineProperty(this, 'ctx', {
9433        get: function get() {
9434          return _ctx;
9435        },
9436        set: function set(value) {
9437          if (value instanceof ContextLayer) {
9438            _ctx = value;
9439          }
9440        }
9441      });
9442      /**
9443      * @name path
9444      * @type {array}
9445      * @default []
9446      */
9447
9448      Object.defineProperty(this, 'path', {
9449        get: function get() {
9450          return _ctx.path;
9451        },
9452        set: function set(value) {
9453          _ctx.path = value;
9454        }
9455      });
9456      /**
9457      * @name ctxStack
9458      * @type {array}
9459      * @default []
9460      */
9461
9462      var _ctxStack = [];
9463      Object.defineProperty(this, 'ctxStack', {
9464        get: function get() {
9465          return _ctxStack;
9466        },
9467        set: function set(value) {
9468          _ctxStack = value;
9469        }
9470      });
9471      /**
9472      * Sets or returns the color, gradient, or pattern used to fill the drawing
9473      *
9474      * @name fillStyle
9475      * @default #000000
9476      * @property {(color|gradient|pattern)} value The color of the drawing. Default value is #000000<br />
9477      * A gradient object (linear or radial) used to fill the drawing (not supported by context2d)<br />
9478      * A pattern object to use to fill the drawing (not supported by context2d)
9479      */
9480
9481      Object.defineProperty(this, 'fillStyle', {
9482        get: function get() {
9483          return this.ctx.fillStyle;
9484        },
9485        set: function set(value) {
9486          var rgba;
9487          rgba = getRGBA(value);
9488          this.ctx.fillStyle = rgba.style;
9489          this.ctx.isFillTransparent = rgba.a === 0;
9490          this.ctx.fillOpacity = rgba.a;
9491          this.pdf.setFillColor(rgba.r, rgba.g, rgba.b, {
9492            a: rgba.a
9493          });
9494          this.pdf.setTextColor(rgba.r, rgba.g, rgba.b, {
9495            a: rgba.a
9496          });
9497        }
9498      });
9499      /**
9500      * Sets or returns the color, gradient, or pattern used for strokes
9501      *
9502      * @name strokeStyle
9503      * @default #000000
9504      * @property {color} color A CSS color value that indicates the stroke color of the drawing. Default value is #000000 (not supported by context2d)
9505      * @property {gradient} gradient A gradient object (linear or radial) used to create a gradient stroke (not supported by context2d)
9506      * @property {pattern} pattern A pattern object used to create a pattern stroke (not supported by context2d)
9507      */
9508
9509      Object.defineProperty(this, 'strokeStyle', {
9510        get: function get() {
9511          return this.ctx.strokeStyle;
9512        },
9513        set: function set(value) {
9514          var rgba = getRGBA(value);
9515          this.ctx.strokeStyle = rgba.style;
9516          this.ctx.isStrokeTransparent = rgba.a === 0;
9517          this.ctx.strokeOpacity = rgba.a;
9518
9519          if (rgba.a === 0) {
9520            this.pdf.setDrawColor(255, 255, 255);
9521          } else if (rgba.a === 1) {
9522            this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b);
9523          } else {
9524            this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b);
9525          }
9526        }
9527      });
9528      /**
9529      * Sets or returns the style of the end caps for a line
9530      *
9531      * @name lineCap
9532      * @default butt
9533      * @property {(butt|round|square)} lineCap butt A flat edge is added to each end of the line <br/>
9534      * round A rounded end cap is added to each end of the line<br/>
9535      * square A square end cap is added to each end of the line<br/>
9536      */
9537
9538      Object.defineProperty(this, 'lineCap', {
9539        get: function get() {
9540          return this.ctx.lineCap;
9541        },
9542        set: function set(value) {
9543          if (['butt', 'round', 'square'].indexOf(value) !== -1) {
9544            this.ctx.lineCap = value;
9545            this.pdf.setLineCap(value);
9546          }
9547        }
9548      });
9549      /**
9550      * Sets or returns the current line width
9551      *
9552      * @name lineWidth
9553      * @default 1
9554      * @property {number} lineWidth The current line width, in pixels
9555      */
9556
9557      Object.defineProperty(this, 'lineWidth', {
9558        get: function get() {
9559          return this.ctx.lineWidth;
9560        },
9561        set: function set(value) {
9562          if (!isNaN(value)) {
9563            this.ctx.lineWidth = value;
9564            this.pdf.setLineWidth(value);
9565          }
9566        }
9567      });
9568      /**
9569      * Sets or returns the type of corner created, when two lines meet
9570      */
9571
9572      Object.defineProperty(this, 'lineJoin', {
9573        get: function get() {
9574          return this.ctx.lineJoin;
9575        },
9576        set: function set(value) {
9577          if (['bevel', 'round', 'miter'].indexOf(value) !== -1) {
9578            this.ctx.lineJoin = value;
9579            this.pdf.setLineJoin(value);
9580          }
9581        }
9582      });
9583      /**
9584      * 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.
9585      *
9586      * @name miterLimit
9587      * @default 10
9588      */
9589
9590      Object.defineProperty(this, 'miterLimit', {
9591        get: function get() {
9592          return this.ctx.miterLimit;
9593        },
9594        set: function set(value) {
9595          if (!isNaN(value)) {
9596            this.ctx.miterLimit = value;
9597            this.pdf.setMiterLimit(value);
9598          }
9599        }
9600      });
9601      Object.defineProperty(this, 'textBaseline', {
9602        get: function get() {
9603          return this.ctx.textBaseline;
9604        },
9605        set: function set(value) {
9606          this.ctx.textBaseline = value;
9607        }
9608      });
9609      Object.defineProperty(this, 'textAlign', {
9610        get: function get() {
9611          return this.ctx.textAlign;
9612        },
9613        set: function set(value) {
9614          if (['right', 'end', 'center', 'left', 'start'].indexOf(value) !== -1) {
9615            this.ctx.textAlign = value;
9616          }
9617        }
9618      });
9619      Object.defineProperty(this, 'font', {
9620        get: function get() {
9621          return this.ctx.font;
9622        },
9623        set: function set(value) {
9624          this.ctx.font = value;
9625          var rx, matches; //source: https://stackoverflow.com/a/10136041
9626
vendor: 4,147 bytes, lines 9627-9751
9627          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;
9628          matches = rx.exec(value);
9629
9630          if (matches !== null) {
9631            var fontStyle = matches[1];
9632            var fontVariant = matches[2];
9633            var fontWeight = matches[3];
9634            var fontSize = matches[4];
9635            var fontSizeUnit = matches[5];
9636            var fontFamily = matches[6];
9637          } else {
9638            return;
9639          }
9640
9641          if ('px' === fontSizeUnit) {
9642            fontSize = Math.floor(parseFloat(fontSize));
9643          } else if ('em' === fontSizeUnit) {
9644            fontSize = Math.floor(parseFloat(fontSize) * this.pdf.getFontSize());
9645          } else {
9646            fontSize = Math.floor(parseFloat(fontSize));
9647          }
9648
9649          this.pdf.setFontSize(fontSize);
9650          var style = '';
9651
9652          if (fontWeight === 'bold' || parseInt(fontWeight, 10) >= 700 || fontStyle === 'bold') {
9653            style = 'bold';
9654          }
9655
9656          if (fontStyle === 'italic') {
9657            style += 'italic';
9658          }
9659
9660          if (style.length === 0) {
9661            style = 'normal';
9662          }
9663
9664          var jsPdfFontName = '';
9665          var parts = fontFamily.toLowerCase().replace(/"|'/g, '').split(/\s*,\s*/);
9666          var fallbackFonts = {
9667            arial: 'Helvetica',
9668            verdana: 'Helvetica',
9669            helvetica: 'Helvetica',
9670            'sans-serif': 'Helvetica',
9671            fixed: 'Courier',
9672            monospace: 'Courier',
9673            terminal: 'Courier',
9674            courier: 'Courier',
9675            times: 'Times',
9676            cursive: 'Times',
9677            fantasy: 'Times',
9678            serif: 'Times'
9679          };
9680
9681          for (var i = 0; i < parts.length; i++) {
9682            if (this.pdf.internal.getFont(parts[i], style, {
9683              noFallback: true,
9684              disableWarning: true
9685            }) !== undefined) {
9686              jsPdfFontName = parts[i];
9687              break;
9688            } else if (style === 'bolditalic' && this.pdf.internal.getFont(parts[i], 'bold', {
9689              noFallback: true,
9690              disableWarning: true
9691            }) !== undefined) {
9692              jsPdfFontName = parts[i];
9693              style = 'bold';
9694            } else if (this.pdf.internal.getFont(parts[i], 'normal', {
9695              noFallback: true,
9696              disableWarning: true
9697            }) !== undefined) {
9698              jsPdfFontName = parts[i];
9699              style = 'normal';
9700              break;
9701            }
9702          }
9703
9704          if (jsPdfFontName === '') {
9705            for (var i = 0; i < parts.length; i++) {
9706              if (fallbackFonts[parts[i]]) {
9707                jsPdfFontName = fallbackFonts[parts[i]];
9708                break;
9709              }
9710            }
9711          }
9712
9713          jsPdfFontName = jsPdfFontName === '' ? 'Times' : jsPdfFontName;
9714          this.pdf.setFont(jsPdfFontName, style);
9715        }
9716      });
9717      Object.defineProperty(this, 'globalCompositeOperation', {
9718        get: function get() {
9719          return this.ctx.globalCompositeOperation;
9720        },
9721        set: function set(value) {
9722          this.ctx.globalCompositeOperation = value;
9723        }
9724      });
9725      Object.defineProperty(this, 'globalAlpha', {
9726        get: function get() {
9727          return this.ctx.globalAlpha;
9728        },
9729        set: function set(value) {
9730          this.ctx.globalAlpha = value;
9731        }
9732      }); // Not HTML API
9733
9734      Object.defineProperty(this, 'ignoreClearRect', {
9735        get: function get() {
9736          return this.ctx.ignoreClearRect;
9737        },
9738        set: function set(value) {
9739          this.ctx.ignoreClearRect = Boolean(value);
9740        }
9741      });
9742    };
9743
9744    Context2D.prototype.fill = function () {
9745      pathPreProcess.call(this, 'fill', false);
9746    };
9747    /**
9748    * Actually draws the path you have defined
9749    *
9750    * @name stroke
9751    * @function
9752    * @description The stroke() method actually draws the path you have defined with all those moveTo() and lineTo() methods. The default color is black.
9753    */
9754
9755
9756    Context2D.prototype.stroke = function () {
9757      pathPreProcess.call(this, 'stroke', false);
9758    };
9759    /**
9760    * Begins a path, or resets the current 
9761    *
9762    * @name beginPath
9763    * @function 
9764    * @description The beginPath() method begins a path, or resets the current path.
9765    */
9766
9767
9768    Context2D.prototype.beginPath = function () {
9769      this.path = [{
9770        type: 'begin'
9771      }];
9772    };
9773    /**
9774    * Moves the path to the specified point in the canvas, without creating a line
9775    * 
9776    * @name moveTo
9777    * @function
9778    * @param x {Number} The x-coordinate of where to move the path to
9779    * @param y {Number} The y-coordinate of where to move the path to
9780    */
9781
9782
9783    Context2D.prototype.moveTo = function (x, y) {
9784      if (isNaN(x) || isNaN(y)) {
9785        console.error('jsPDF.context2d.moveTo: Invalid arguments', arguments);
9786        throw new Error('Invalid arguments passed to jsPDF.context2d.moveTo');
9787      }
9788
9789      var pt = this.ctx.transform.applyToPoint(new Point(x, y));
9790      this.path.push({
9791        type: 'mt',
9792        x: pt.x,
9793        y: pt.y
9794      });
9795      this.ctx.lastPoint = new Point(x, y);
9796    };
9797    /**
9798    * Creates a path from the current point back to the starting point
9799    * 
9800    * @name closePath
9801    * @function
9802    * @description The closePath() method creates a path from the current point back to the starting point.
9803    */
9804
9805
9806    Context2D.prototype.closePath = function () {
9807      var pathBegin = new Point(0, 0);
9808      var i = 0;
9809
9810      for (i = this.path.length - 1; i !== -1; i--) {
9811        if (this.path[i].type === 'begin') {
9812          if (_typeof(this.path[i + 1]) === 'object' && typeof this.path[i + 1].x === 'number') {
9813            pathBegin = new Point(this.path[i + 1].x, this.path[i + 1].y);
9814            this.path.push({
9815              type: 'lt',
9816              x: pathBegin.x,
9817              y: pathBegin.y
9818            });
9819            break;
9820          }
9821        }
9822      }
9823
9824      if (_typeof(this.path[i + 2]) === 'object' && typeof this.path[i + 2].x === 'number') {
9825        this.path.push(JSON.parse(JSON.stringify(this.path[i + 2])));
9826      }
9827
9828      this.path.push({
9829        type: 'close'
9830      });
9831      this.ctx.lastPoint = new Point(pathBegin.x, pathBegin.y);
9832    };
9833    /**
9834    * Adds a new point and creates a line to that point from the last specified point in the canvas
9835    * 
9836    * @name lineTo
9837    * @function
9838    * @param x The x-coordinate of where to create the line to
9839    * @param y The y-coordinate of where to create the line to
9840    * @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).
9841    */
9842
9843
9844    Context2D.prototype.lineTo = function (x, y) {
9845      if (isNaN(x) || isNaN(y)) {
9846        console.error('jsPDF.context2d.lineTo: Invalid arguments', arguments);
9847        throw new Error('Invalid arguments passed to jsPDF.context2d.lineTo');
9848      }
9849
9850      var pt = this.ctx.transform.applyToPoint(new Point(x, y));
9851      this.path.push({
9852        type: 'lt',
9853        x: pt.x,
9854        y: pt.y
9855      });
9856      this.ctx.lastPoint = new Point(pt.x, pt.y);
9857    };
9858    /**
9859    * Clips a region of any shape and size from the original canvas
9860    * 
9861    * @name clip
9862    * @function
9863    * @description The clip() method clips a region of any shape and size from the original canvas.
9864    */
9865
9866
9867    Context2D.prototype.clip = function () {
9868      this.ctx.clip_path = JSON.parse(JSON.stringify(this.path));
9869      pathPreProcess.call(this, null, true);
9870    };
9871    /**
9872    * Creates a cubic Bézier curve
9873    *
9874    * @name quadraticCurveTo
9875    * @function
9876    * @param cpx {Number} The x-coordinate of the Bézier control point
9877    * @param cpy {Number} The y-coordinate of the Bézier control point
9878    * @param x {Number} The x-coordinate of the ending point
9879    * @param y {Number} The y-coordinate of the ending point
9880    * @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.
9881    */
9882
9883
9884    Context2D.prototype.quadraticCurveTo = function (cpx, cpy, x, y) {
9885      if (isNaN(x) || isNaN(y) || isNaN(cpx) || isNaN(cpy)) {
9886        console.error('jsPDF.context2d.quadraticCurveTo: Invalid arguments', arguments);
vendor: 4,669 bytes, lines 9887-9992
9887        throw new Error('Invalid arguments passed to jsPDF.context2d.quadraticCurveTo');
9888      }
9889
9890      var pt0 = this.ctx.transform.applyToPoint(new Point(x, y));
9891      var pt1 = this.ctx.transform.applyToPoint(new Point(cpx, cpy));
9892      this.path.push({
9893        type: 'qct',
9894        x1: pt1.x,
9895        y1: pt1.y,
9896        x: pt0.x,
9897        y: pt0.y
9898      });
9899      this.ctx.lastPoint = new Point(pt0.x, pt0.y);
9900    };
9901    /**
9902    * Creates a cubic Bézier curve
9903    *
9904    * @name bezierCurveTo
9905    * @function
9906    * @param cp1x {Number} The x-coordinate of the first Bézier control point
9907    * @param cp1y {Number} The y-coordinate of the first Bézier control point
9908    * @param cp2x {Number} The x-coordinate of the second Bézier control point
9909    * @param cp2y {Number} The y-coordinate of the second Bézier control point
9910    * @param x {Number} The x-coordinate of the ending point
9911    * @param y {Number} The y-coordinate of the ending point
9912    * @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.
9913    */
9914
9915
9916    Context2D.prototype.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
9917      if (isNaN(x) || isNaN(y) || isNaN(cp1x) || isNaN(cp1y) || isNaN(cp2x) || isNaN(cp2y)) {
9918        console.error('jsPDF.context2d.bezierCurveTo: Invalid arguments', arguments);
9919        throw new Error('Invalid arguments passed to jsPDF.context2d.bezierCurveTo');
9920      }
9921
9922      var pt0 = this.ctx.transform.applyToPoint(new Point(x, y));
9923      var pt1 = this.ctx.transform.applyToPoint(new Point(cp1x, cp1y));
9924      var pt2 = this.ctx.transform.applyToPoint(new Point(cp2x, cp2y));
9925      this.path.push({
9926        type: 'bct',
9927        x1: pt1.x,
9928        y1: pt1.y,
9929        x2: pt2.x,
9930        y2: pt2.y,
9931        x: pt0.x,
9932        y: pt0.y
9933      });
9934      this.ctx.lastPoint = new Point(pt0.x, pt0.y);
9935    };
9936    /**
9937    * Creates an arc/curve (used to create circles, or parts of circles)
9938    *
9939    * @name arc
9940    * @function
9941    * @param x {Number} The x-coordinate of the center of the circle
9942    * @param y {Number} The y-coordinate of the center of the circle
9943    * @param radius {Number} The radius of the circle
9944    * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle)
9945    * @param endAngle {Number} The ending angle, in radians
9946    * @param counterclockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise.
9947    * @description The arc() method creates an arc/curve (used to create circles, or parts of circles).
9948    */
9949
9950
9951    Context2D.prototype.arc = function (x, y, radius, startAngle, endAngle, counterclockwise) {
9952      if (isNaN(x) || isNaN(y) || isNaN(radius) || isNaN(startAngle) || isNaN(endAngle)) {
9953        console.error('jsPDF.context2d.arc: Invalid arguments', arguments);
9954        throw new Error('Invalid arguments passed to jsPDF.context2d.arc');
9955      }
9956
9957      counterclockwise = Boolean(counterclockwise);
9958
9959      if (!this.ctx.transform.isIdentity) {
9960        var xpt = this.ctx.transform.applyToPoint(new Point(x, y));
9961        x = xpt.x;
9962        y = xpt.y;
9963        var x_radPt = this.ctx.transform.applyToPoint(new Point(0, radius));
9964        var x_radPt0 = this.ctx.transform.applyToPoint(new Point(0, 0));
9965        radius = Math.sqrt(Math.pow(x_radPt.x - x_radPt0.x, 2) + Math.pow(x_radPt.y - x_radPt0.y, 2));
9966      }
9967
9968      if (Math.abs(endAngle - startAngle) >= 2 * Math.PI) {
9969        startAngle = 0;
9970        endAngle = 2 * Math.PI;
9971      }
9972
9973      this.path.push({
9974        type: 'arc',
9975        x: x,
9976        y: y,
9977        radius: radius,
9978        startAngle: startAngle,
9979        endAngle: endAngle,
9980        counterclockwise: counterclockwise
9981      }); // this.ctx.lastPoint(new Point(pt.x,pt.y));
9982    };
9983    /**
9984    * Creates an arc/curve between two tangents
9985    * 
9986    * @name arcTo
9987    * @function
9988    * @param x1 {Number} The x-coordinate of the first tangent
9989    * @param y1 {Number} The y-coordinate of the first tangent
9990    * @param x2 {Number} The x-coordinate of the second tangent
9991    * @param y2 {Number} The y-coordinate of the second tangent
9992    * @param radius The radius of the arc
9993    * @description The arcTo() method creates an arc/curve between two tangents on the canvas.
9994    */
9995
9996
9997    Context2D.prototype.arcTo = function (x1, y1, x2, y2, radius) {
9998      throw new Error('arcTo not implemented.');
9999    };
10000    /**
10001    * Creates a rectangle
10002    *
10003    * @name rect
10004    * @function
10005    * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
10006    * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
10007    * @param w {Number} The width of the rectangle, in pixels
10008    * @param h {Number} The height of the rectangle, in pixels
10009    * @description The rect() method creates a rectangle.
10010    */
10011
10012
10013    Context2D.prototype.rect = function (x, y, w, h) {
10014      if (isNaN(x) || isNaN(y) || isNaN(w) || isNaN(h)) {
10015        console.error('jsPDF.context2d.rect: Invalid arguments', arguments);
10016        throw new Error('Invalid arguments passed to jsPDF.context2d.rect');
10017      }
10018
10019      this.moveTo(x, y);
10020      this.lineTo(x + w, y);
10021      this.lineTo(x + w, y + h);
10022      this.lineTo(x, y + h);
10023      this.lineTo(x, y);
10024      this.lineTo(x + w, y);
10025      this.lineTo(x, y);
10026    };
10027    /**
10028    * Draws a "filled" rectangle
10029    *
10030    * @name fillRect
10031    * @function
10032    * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
10033    * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
10034    * @param w {Number} The width of the rectangle, in pixels
10035    * @param h {Number} The height of the rectangle, in pixels
10036    * @description The fillRect() method draws a "filled" rectangle. The default color of the fill is black.
10037    */
10038
10039
10040    Context2D.prototype.fillRect = function (x, y, w, h) {
10041      if (isNaN(x) || isNaN(y) || isNaN(w) || isNaN(h)) {
10042        console.error('jsPDF.context2d.fillRect: Invalid arguments', arguments);
10043        throw new Error('Invalid arguments passed to jsPDF.context2d.fillRect');
10044      }
10045
10046      if (isFillTransparent.call(this)) {
10047        return;
10048      }
10049
10050      var tmp = {};
10051
10052      if (this.lineCap !== 'butt') {
10053        tmp.lineCap = this.lineCap;
10054        this.lineCap = 'butt';
10055      }
10056
10057      if (this.lineJoin !== 'miter') {
10058        tmp.lineJoin = this.lineJoin;
10059        this.lineJoin = 'miter';
10060      }
10061
10062      this.beginPath();
10063      this.rect(x, y, w, h);
10064      this.fill();
10065
10066      if (tmp.hasOwnProperty('lineCap')) {
10067        this.lineCap = tmp.lineCap;
10068      }
10069
10070      if (tmp.hasOwnProperty('lineJoin')) {
10071        this.lineJoin = tmp.lineJoin;
10072      }
10073    };
10074    /**
10075    *     Draws a rectangle (no fill)
10076    *
10077    * @name strokeRect
10078    * @function
10079    * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
10080    * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
10081    * @param w {Number} The width of the rectangle, in pixels
10082    * @param h {Number} The height of the rectangle, in pixels
vendor: 34,633 bytes, lines 10083-11153
10083    * @description The strokeRect() method draws a rectangle (no fill). The default color of the stroke is black.
10084    */
10085
10086
10087    Context2D.prototype.strokeRect = function strokeRect(x, y, w, h) {
10088      if (isNaN(x) || isNaN(y) || isNaN(w) || isNaN(h)) {
10089        console.error('jsPDF.context2d.strokeRect: Invalid arguments', arguments);
10090        throw new Error('Invalid arguments passed to jsPDF.context2d.strokeRect');
10091      }
10092
10093      if (isStrokeTransparent.call(this)) {
10094        return;
10095      }
10096
10097      this.beginPath();
10098      this.rect(x, y, w, h);
10099      this.stroke();
10100    };
10101    /**
10102    * Clears the specified pixels within a given rectangle
10103    *
10104    * @name clearRect
10105    * @function
10106    * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
10107    * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
10108    * @param w {Number} The width of the rectangle to clear, in pixels
10109    * @param h {Number} The height of the rectangle to clear, in pixels
10110    * @description We cannot clear PDF commands that were already written to PDF, so we use white instead. <br />
10111    * As a special case, read a special flag (ignoreClearRect) and do nothing if it is set.
10112    * This results in all calls to clearRect() to do nothing, and keep the canvas transparent.
10113    * This flag is stored in the save/restore context and is managed the same way as other drawing states.
10114    *
10115    */
10116
10117
10118    Context2D.prototype.clearRect = function (x, y, w, h) {
10119      if (isNaN(x) || isNaN(y) || isNaN(w) || isNaN(h)) {
10120        console.error('jsPDF.context2d.clearRect: Invalid arguments', arguments);
10121        throw new Error('Invalid arguments passed to jsPDF.context2d.clearRect');
10122      }
10123
10124      if (this.ignoreClearRect) {
10125        return;
10126      }
10127
10128      this.fillStyle = '#ffffff';
10129      this.fillRect(x, y, w, h);
10130    };
10131    /**
10132    * Saves the state of the current context
10133    * 
10134    * @name save
10135    * @function
10136    */
10137
10138
10139    Context2D.prototype.save = function (doStackPush) {
10140      doStackPush = typeof doStackPush === 'boolean' ? doStackPush : true;
10141      var tmpPageNumber = this.pdf.internal.getCurrentPageInfo().pageNumber;
10142
10143      for (var i = 0; i < this.pdf.internal.getNumberOfPages(); i++) {
10144        this.pdf.setPage(i + 1);
10145        this.pdf.internal.out('q');
10146      }
10147
10148      this.pdf.setPage(tmpPageNumber);
10149
10150      if (doStackPush) {
10151        this.ctx.fontSize = this.pdf.internal.getFontSize();
10152        var ctx = new ContextLayer(this.ctx);
10153        this.ctxStack.push(this.ctx);
10154        this.ctx = ctx;
10155      }
10156    };
10157    /**
10158    * Returns previously saved path state and attributes
10159    * 
10160    * @name restore
10161    * @function
10162    */
10163
10164
10165    Context2D.prototype.restore = function (doStackPop) {
10166      doStackPop = typeof doStackPop === 'boolean' ? doStackPop : true;
10167      var tmpPageNumber = this.pdf.internal.getCurrentPageInfo().pageNumber;
10168
10169      for (var i = 0; i < this.pdf.internal.getNumberOfPages(); i++) {
10170        this.pdf.setPage(i + 1);
10171        this.pdf.internal.out('Q');
10172      }
10173
10174      this.pdf.setPage(tmpPageNumber);
10175
10176      if (doStackPop && this.ctxStack.length !== 0) {
10177        this.ctx = this.ctxStack.pop();
10178        this.fillStyle = this.ctx.fillStyle;
10179        this.strokeStyle = this.ctx.strokeStyle;
10180        this.font = this.ctx.font;
10181        this.lineCap = this.ctx.lineCap;
10182        this.lineWidth = this.ctx.lineWidth;
10183        this.lineJoin = this.ctx.lineJoin;
10184      }
10185    };
10186    /** 
10187    * @name toDataURL
10188    * @function
10189    */
10190
10191
10192    Context2D.prototype.toDataURL = function () {
10193      throw new Error('toDataUrl not implemented.');
10194    }; //helper functions
10195
10196    /**
10197    * Get the decimal values of r, g, b and a
10198    *
10199    * @name getRGBA
10200    * @function
10201    * @private
10202    * @ignore
10203    */
10204
10205
10206    var getRGBA = function getRGBA(style) {
10207      var rxRgb = /rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/;
10208      var rxRgba = /rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/;
10209      var rxTransparent = /transparent|rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*0+\s*\)/;
10210      var r, g, b, a;
10211
10212      if (style.isCanvasGradient === true) {
10213        style = style.getColor();
10214      }
10215
10216      if (!style) {
10217        return {
10218          r: 0,
10219          g: 0,
10220          b: 0,
10221          a: 0,
10222          style: style
10223        };
10224      }
10225
10226      if (rxTransparent.test(style)) {
10227        r = 0;
10228        g = 0;
10229        b = 0;
10230        a = 0;
10231      } else {
10232        var matches = rxRgb.exec(style);
10233
10234        if (matches !== null) {
10235          r = parseInt(matches[1]);
10236          g = parseInt(matches[2]);
10237          b = parseInt(matches[3]);
10238          a = 1;
10239        } else {
10240          matches = rxRgba.exec(style);
10241
10242          if (matches !== null) {
10243            r = parseInt(matches[1]);
10244            g = parseInt(matches[2]);
10245            b = parseInt(matches[3]);
10246            a = parseFloat(matches[4]);
10247          } else {
10248            a = 1;
10249
10250            if (typeof style === "string" && style.charAt(0) !== '#') {
10251              var rgbColor = new RGBColor(style);
10252
10253              if (rgbColor.ok) {
10254                style = rgbColor.toHex();
10255              } else {
10256                style = '#000000';
10257              }
10258            }
10259
10260            if (style.length === 4) {
10261              r = style.substring(1, 2);
10262              r += r;
10263              g = style.substring(2, 3);
10264              g += g;
10265              b = style.substring(3, 4);
10266              b += b;
10267            } else {
10268              r = style.substring(1, 3);
10269              g = style.substring(3, 5);
10270              b = style.substring(5, 7);
10271            }
10272
10273            r = parseInt(r, 16);
10274            g = parseInt(g, 16);
10275            b = parseInt(b, 16);
10276          }
10277        }
10278      }
10279
10280      return {
10281        r: r,
10282        g: g,
10283        b: b,
10284        a: a,
10285        style: style
10286      };
10287    };
10288    /**
10289    * @name isFillTransparent
10290    * @function 
10291    * @private
10292    * @ignore
10293    * @returns {Boolean}
10294    */
10295
10296
10297    var isFillTransparent = function isFillTransparent() {
10298      return this.ctx.isFillTransparent || this.globalAlpha == 0;
10299    };
10300    /**
10301    * @name isStrokeTransparent
10302    * @function 
10303    * @private
10304    * @ignore
10305    * @returns {Boolean}
10306    */
10307
10308
10309    var isStrokeTransparent = function isStrokeTransparent() {
10310      return Boolean(this.ctx.isStrokeTransparent || this.globalAlpha == 0);
10311    };
10312    /**
10313    * Draws "filled" text on the canvas
10314    * 
10315    * @name fillText
10316    * @function
10317    * @param text {String} Specifies the text that will be written on the canvas
10318    * @param x {Number} The x coordinate where to start painting the text (relative to the canvas)
10319    * @param y {Number} The y coordinate where to start painting the text (relative to the canvas)
10320    * @param maxWidth {Number} Optional. The maximum allowed width of the text, in pixels
10321    * @description The fillText() method draws filled text on the canvas. The default color of the text is black.
10322    */
10323
10324
10325    Context2D.prototype.fillText = function (text, x, y, maxWidth) {
10326      if (isNaN(x) || isNaN(y) || typeof text !== 'string') {
10327        console.error('jsPDF.context2d.fillText: Invalid arguments', arguments);
10328        throw new Error('Invalid arguments passed to jsPDF.context2d.fillText');
10329      }
10330
10331      maxWidth = isNaN(maxWidth) ? undefined : maxWidth;
10332
10333      if (isFillTransparent.call(this)) {
10334        return;
10335      }
10336
10337      y = getBaseline.call(this, y);
10338      var degs = rad2deg(this.ctx.transform.rotation); // We only use X axis as scale hint 
10339
10340      var scale = this.ctx.transform.scaleX;
10341      putText.call(this, {
10342        text: text,
10343        x: x,
10344        y: y,
10345        scale: scale,
10346        angle: degs,
10347        align: this.textAlign,
10348        maxWidth: maxWidth
10349      });
10350    };
10351    /**
10352    * Draws text on the canvas (no fill)
10353    * 
10354    * @name strokeText
10355    * @function
10356    * @param text {String} Specifies the text that will be written on the canvas
10357    * @param x {Number} The x coordinate where to start painting the text (relative to the canvas)
10358    * @param y {Number} The y coordinate where to start painting the text (relative to the canvas)
10359    * @param maxWidth {Number} Optional. The maximum allowed width of the text, in pixels
10360    * @description The strokeText() method draws text (with no fill) on the canvas. The default color of the text is black.
10361    */
10362
10363
10364    Context2D.prototype.strokeText = function (text, x, y, maxWidth) {
10365      if (isNaN(x) || isNaN(y) || typeof text !== 'string') {
10366        console.error('jsPDF.context2d.strokeText: Invalid arguments', arguments);
10367        throw new Error('Invalid arguments passed to jsPDF.context2d.strokeText');
10368      }
10369
10370      if (isStrokeTransparent.call(this)) {
10371        return;
10372      }
10373
10374      maxWidth = isNaN(maxWidth) ? undefined : maxWidth;
10375      y = getBaseline.call(this, y);
10376      var degs = rad2deg(this.ctx.transform.rotation);
10377      var scale = this.ctx.transform.scaleX;
10378      putText.call(this, {
10379        text: text,
10380        x: x,
10381        y: y,
10382        scale: scale,
10383        renderingMode: 'stroke',
10384        angle: degs,
10385        align: this.textAlign,
10386        maxWidth: maxWidth
10387      });
10388    };
10389    /**
10390    * Returns an object that contains the width of the specified text
10391    *
10392    * @name measureText
10393    * @function 
10394    * @param text {String} The text to be measured
10395    * @description The measureText() method returns an object that contains the width of the specified text, in pixels.
10396    * @returns {Number}
10397    */
10398
10399
10400    Context2D.prototype.measureText = function (text) {
10401      if (typeof text !== 'string') {
10402        console.error('jsPDF.context2d.measureText: Invalid arguments', arguments);
10403        throw new Error('Invalid arguments passed to jsPDF.context2d.measureText');
10404      }
10405
10406      var pdf = this.pdf;
10407      var k = this.pdf.internal.scaleFactor;
10408      var fontSize = pdf.internal.getFontSize();
10409      var txtWidth = pdf.getStringUnitWidth(text) * fontSize / pdf.internal.scaleFactor;
10410      txtWidth *= Math.round(k * 96 / 72 * 10000) / 10000;
10411
10412      var TextMetrics = function TextMetrics(options) {
10413        options = options || {};
10414
10415        var _width = options.width || 0;
10416
10417        Object.defineProperty(this, 'width', {
10418          get: function get() {
10419            return _width;
10420          }
10421        });
10422        return this;
10423      };
10424
10425      return new TextMetrics({
10426        width: txtWidth
10427      });
10428    }; //Transformations
10429
10430    /**
10431    * Scales the current drawing bigger or smaller
10432    * 
10433    * @name scale 
10434    * @function
10435    * @param scalewidth {Number} Scales the width of the current drawing (1=100%, 0.5=50%, 2=200%, etc.)
10436    * @param scaleheight {Number} Scales the height of the current drawing (1=100%, 0.5=50%, 2=200%, etc.)
10437    * @description The scale() method scales the current drawing, bigger or smaller.
10438    */
10439
10440
10441    Context2D.prototype.scale = function (scalewidth, scaleheight) {
10442      if (isNaN(scalewidth) || isNaN(scaleheight)) {
10443        console.error('jsPDF.context2d.scale: Invalid arguments', arguments);
10444        throw new Error('Invalid arguments passed to jsPDF.context2d.scale');
10445      }
10446
10447      var matrix = new Matrix(scalewidth, 0.0, 0.0, scaleheight, 0.0, 0.0);
10448      this.ctx.transform = this.ctx.transform.multiply(matrix);
10449    };
10450    /**
10451    * Rotates the current drawing
10452    * 
10453    * @name rotate
10454    * @function
10455    * @param angle {Number} The rotation angle, in radians.
10456    * @description To calculate from degrees to radians: degrees*Math.PI/180. <br />
10457    * Example: to rotate 5 degrees, specify the following: 5*Math.PI/180
10458    */
10459
10460
10461    Context2D.prototype.rotate = function (angle) {
10462      if (isNaN(angle)) {
10463        console.error('jsPDF.context2d.rotate: Invalid arguments', arguments);
10464        throw new Error('Invalid arguments passed to jsPDF.context2d.rotate');
10465      }
10466
10467      var matrix = new Matrix(Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0.0, 0.0);
10468      this.ctx.transform = this.ctx.transform.multiply(matrix);
10469    };
10470    /**
10471    * Remaps the (0,0) position on the canvas
10472    * 
10473    * @name translate
10474    * @function
10475    * @param x {Number} The value to add to horizontal (x) coordinates
10476    * @param y {Number} The value to add to vertical (y) coordinates
10477    * @description The translate() method remaps the (0,0) position on the canvas.
10478    */
10479
10480
10481    Context2D.prototype.translate = function (x, y) {
10482      if (isNaN(x) || isNaN(y)) {
10483        console.error('jsPDF.context2d.translate: Invalid arguments', arguments);
10484        throw new Error('Invalid arguments passed to jsPDF.context2d.translate');
10485      }
10486
10487      var matrix = new Matrix(1.0, 0.0, 0.0, 1.0, x, y);
10488      this.ctx.transform = this.ctx.transform.multiply(matrix);
10489    };
10490    /**
10491    * Replaces the current transformation matrix for the drawing
10492    * 
10493    * @name transform
10494    * @function
10495    * @param a {Number} Horizontal scaling
10496    * @param b {Number} Horizontal skewing
10497    * @param c {Number} Vertical skewing
10498    * @param d {Number} Vertical scaling
10499    * @param e {Number} Horizontal moving
10500    * @param f {Number} Vertical moving
10501    * @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.
10502    */
10503
10504
10505    Context2D.prototype.transform = function (a, b, c, d, e, f) {
10506      if (isNaN(a) || isNaN(b) || isNaN(c) || isNaN(d) || isNaN(e) || isNaN(f)) {
10507        console.error('jsPDF.context2d.transform: Invalid arguments', arguments);
10508        throw new Error('Invalid arguments passed to jsPDF.context2d.transform');
10509      }
10510
10511      var matrix = new Matrix(a, b, c, d, e, f);
10512      this.ctx.transform = this.ctx.transform.multiply(matrix);
10513    };
10514    /**
10515    * Resets the current transform to the identity matrix. Then runs transform()
10516    * 
10517    * @name setTransform
10518    * @function
10519    * @param a {Number} Horizontal scaling
10520    * @param b {Number} Horizontal skewing
10521    * @param c {Number} Vertical skewing
10522    * @param d {Number} Vertical scaling
10523    * @param e {Number} Horizontal moving
10524    * @param f {Number} Vertical moving
10525    * @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.
10526    */
10527
10528
10529    Context2D.prototype.setTransform = function (a, b, c, d, e, f) {
10530      a = isNaN(a) ? 1 : a;
10531      b = isNaN(b) ? 0 : b;
10532      c = isNaN(c) ? 0 : c;
10533      d = isNaN(d) ? 1 : d;
10534      e = isNaN(e) ? 0 : e;
10535      f = isNaN(f) ? 0 : f;
10536      this.ctx.transform = new Matrix(a, b, c, d, e, f);
10537    };
10538    /**
10539    * Draws an image, canvas, or video onto the canvas
10540    * 
10541    * @function 
10542    * @param img {} Specifies the image, canvas, or video element to use
10543    * @param sx {Number} Optional. The x coordinate where to start clipping
10544    * @param sy {Number} Optional. The y coordinate where to start clipping
10545    * @param swidth {Number} Optional. The width of the clipped image
10546    * @param sheight {Number} Optional. The height of the clipped image
10547    * @param x {Number} The x coordinate where to place the image on the canvas
10548    * @param y {Number} The y coordinate where to place the image on the canvas
10549    * @param width {Number} Optional. The width of the image to use (stretch or reduce the image)
10550    * @param height {Number} Optional. The height of the image to use (stretch or reduce the image)
10551    */
10552
10553
10554    Context2D.prototype.drawImage = function (img, sx, sy, swidth, sheight, x, y, width, height) {
10555      var imageProperties = this.pdf.getImageProperties(img);
10556      var factorX = 1;
10557      var factorY = 1;
10558      var clipFactorX = 1;
10559      var clipFactorY = 1;
10560      var scaleFactorX = 1;
10561
10562      if (typeof swidth !== 'undefined' && typeof width !== 'undefined') {
10563        clipFactorX = width / swidth;
10564        clipFactorY = height / sheight;
10565        factorX = imageProperties.width / swidth * width / swidth;
10566        factorY = imageProperties.height / sheight * height / sheight;
10567      } //is sx and sy are set and x and y not, set x and y with values of sx and sy
10568
10569
10570      if (typeof x === 'undefined') {
10571        x = sx;
10572        y = sy;
10573        sx = 0;
10574        sy = 0;
10575      }
10576
10577      if (typeof swidth !== 'undefined' && typeof width === 'undefined') {
10578        width = swidth;
10579        height = sheight;
10580      }
10581
10582      if (typeof swidth === 'undefined' && typeof width === 'undefined') {
10583        width = imageProperties.width;
10584        height = imageProperties.height;
10585      }
10586
10587      var decomposedTransformationMatrix = this.ctx.transform.decompose();
10588      var angle = rad2deg(decomposedTransformationMatrix.rotate.shx);
10589      scaleFactorX = decomposedTransformationMatrix.scale.sx;
10590      scaleFactorX = decomposedTransformationMatrix.scale.sy;
10591      var matrix = new Matrix();
10592      matrix = matrix.multiply(decomposedTransformationMatrix.translate);
10593      matrix = matrix.multiply(decomposedTransformationMatrix.skew);
10594      matrix = matrix.multiply(decomposedTransformationMatrix.scale);
10595      var mP = matrix.applyToPoint(new Point(width, height));
10596      var xRect = matrix.applyToRectangle(new Rectangle(x - sx * clipFactorX, y - sy * clipFactorY, swidth * factorX, sheight * factorY));
10597      var pageArray = getPagesByPath.call(this, xRect);
10598      var pages = [];
10599
10600      for (var ii = 0; ii < pageArray.length; ii += 1) {
10601        if (pages.indexOf(pageArray[ii]) === -1) {
10602          pages.push(pageArray[ii]);
10603        }
10604      }
10605
10606      pages.sort();
10607      var clipPath;
10608
10609      if (this.autoPaging) {
10610        var min = pages[0];
10611        var max = pages[pages.length - 1];
10612
10613        for (var i = min; i < max + 1; i++) {
10614          this.pdf.setPage(i);
10615
10616          if (this.ctx.clip_path.length !== 0) {
10617            var tmpPaths = this.path;
10618            clipPath = JSON.parse(JSON.stringify(this.ctx.clip_path));
10619            this.path = pathPositionRedo(clipPath, this.posX, -1 * this.pdf.internal.pageSize.height * (i - 1) + this.posY);
10620            drawPaths.call(this, 'fill', true);
10621            this.path = tmpPaths;
10622          }
10623
10624          var tmpRect = JSON.parse(JSON.stringify(xRect));
10625          tmpRect = pathPositionRedo([tmpRect], this.posX, -1 * this.pdf.internal.pageSize.height * (i - 1) + this.posY)[0];
10626          this.pdf.addImage(img, 'jpg', tmpRect.x, tmpRect.y, tmpRect.w, tmpRect.h, null, null, angle);
10627        }
10628      } else {
10629        this.pdf.addImage(img, 'jpg', xRect.x, xRect.y, xRect.w, xRect.h, null, null, angle);
10630      }
10631    };
10632
10633    var getPagesByPath = function getPagesByPath(path, pageWrapX, pageWrapY) {
10634      var result = [];
10635      pageWrapX = pageWrapX || this.pdf.internal.pageSize.width;
10636      pageWrapY = pageWrapY || this.pdf.internal.pageSize.height;
10637
10638      switch (path.type) {
10639        default:
10640        case 'mt':
10641        case 'lt':
10642          result.push(Math.floor((path.y + this.posY) / pageWrapY) + 1);
10643          break;
10644
10645        case 'arc':
10646          result.push(Math.floor((path.y + this.posY - path.radius) / pageWrapY) + 1);
10647          result.push(Math.floor((path.y + this.posY + path.radius) / pageWrapY) + 1);
10648          break;
10649
10650        case 'qct':
10651          var rectOfQuadraticCurve = getQuadraticCurveBoundary(this.ctx.lastPoint.x, this.ctx.lastPoint.y, path.x1, path.y1, path.x, path.y);
10652          result.push(Math.floor(rectOfQuadraticCurve.y / pageWrapY) + 1);
10653          result.push(Math.floor((rectOfQuadraticCurve.y + rectOfQuadraticCurve.h) / pageWrapY) + 1);
10654          break;
10655
10656        case 'bct':
10657          var rectOfBezierCurve = getBezierCurveBoundary(this.ctx.lastPoint.x, this.ctx.lastPoint.y, path.x1, path.y1, path.x2, path.y2, path.x, path.y);
10658          result.push(Math.floor(rectOfBezierCurve.y / pageWrapY) + 1);
10659          result.push(Math.floor((rectOfBezierCurve.y + rectOfBezierCurve.h) / pageWrapY) + 1);
10660          break;
10661
10662        case 'rect':
10663          result.push(Math.floor((path.y + this.posY) / pageWrapY) + 1);
10664          result.push(Math.floor((path.y + path.h + this.posY) / pageWrapY) + 1);
10665      }
10666
10667      for (var i = 0; i < result.length; i += 1) {
10668        while (this.pdf.internal.getNumberOfPages() < result[i]) {
10669          addPage.call(this);
10670        }
10671      }
10672
10673      return result;
10674    };
10675
10676    var addPage = function addPage() {
10677      var fillStyle = this.fillStyle;
10678      var strokeStyle = this.strokeStyle;
10679      var font = this.font;
10680      var lineCap = this.lineCap;
10681      var lineWidth = this.lineWidth;
10682      var lineJoin = this.lineJoin;
10683      this.pdf.addPage();
10684      this.fillStyle = fillStyle;
10685      this.strokeStyle = strokeStyle;
10686      this.font = font;
10687      this.lineCap = lineCap;
10688      this.lineWidth = lineWidth;
10689      this.lineJoin = lineJoin;
10690    };
10691
10692    var pathPositionRedo = function pathPositionRedo(paths, x, y) {
10693      for (var i = 0; i < paths.length; i++) {
10694        switch (paths[i].type) {
10695          case 'bct':
10696            paths[i].x2 += x;
10697            paths[i].y2 += y;
10698
10699          case 'qct':
10700            paths[i].x1 += x;
10701            paths[i].y1 += y;
10702
10703          case 'mt':
10704          case 'lt':
10705          case 'arc':
10706          default:
10707            paths[i].x += x;
10708            paths[i].y += y;
10709        }
10710      }
10711
10712      return paths;
10713    };
10714
10715    var pathPreProcess = function pathPreProcess(rule, isClip) {
10716      var fillStyle = this.fillStyle;
10717      var strokeStyle = this.strokeStyle;
10718      var font = this.font;
10719      var lineCap = this.lineCap;
10720      var lineWidth = this.lineWidth;
10721      var lineJoin = this.lineJoin;
10722      var origPath = JSON.parse(JSON.stringify(this.path));
10723      var xPath = JSON.parse(JSON.stringify(this.path));
10724      var clipPath;
10725      var tmpPath;
10726      var pages = [];
10727
10728      for (var i = 0; i < xPath.length; i++) {
10729        if (typeof xPath[i].x !== "undefined") {
10730          var page = getPagesByPath.call(this, xPath[i]);
10731
10732          for (var ii = 0; ii < page.length; ii += 1) {
10733            if (pages.indexOf(page[ii]) === -1) {
10734              pages.push(page[ii]);
10735            }
10736          }
10737        }
10738      }
10739
10740      for (var i = 0; i < pages.length; i++) {
10741        while (this.pdf.internal.getNumberOfPages() < pages[i]) {
10742          addPage.call(this);
10743        }
10744      }
10745
10746      pages.sort();
10747
10748      if (this.autoPaging) {
10749        var min = pages[0];
10750        var max = pages[pages.length - 1];
10751
10752        for (var i = min; i < max + 1; i++) {
10753          this.pdf.setPage(i);
10754          this.fillStyle = fillStyle;
10755          this.strokeStyle = strokeStyle;
10756          this.lineCap = lineCap;
10757          this.lineWidth = lineWidth;
10758          this.lineJoin = lineJoin;
10759
10760          if (this.ctx.clip_path.length !== 0) {
10761            var tmpPaths = this.path;
10762            clipPath = JSON.parse(JSON.stringify(this.ctx.clip_path));
10763            this.path = pathPositionRedo(clipPath, this.posX, -1 * this.pdf.internal.pageSize.height * (i - 1) + this.posY);
10764            drawPaths.call(this, rule, true);
10765            this.path = tmpPaths;
10766          }
10767
10768          tmpPath = JSON.parse(JSON.stringify(origPath));
10769          this.path = pathPositionRedo(tmpPath, this.posX, -1 * this.pdf.internal.pageSize.height * (i - 1) + this.posY);
10770
10771          if (isClip === false || i === 0) {
10772            drawPaths.call(this, rule, isClip);
10773          }
10774        }
10775      } else {
10776        drawPaths.call(this, rule, isClip);
10777      }
10778
10779      this.path = origPath;
10780    };
10781    /**
10782    * Processes the paths
10783    *
10784    * @function 
10785    * @param rule {String}
10786    * @param isClip {Boolean}
10787    * @private
10788    * @ignore
10789    */
10790
10791
10792    var drawPaths = function drawPaths(rule, isClip) {
10793      if (rule === 'stroke' && !isClip && isStrokeTransparent.call(this)) {
10794        return;
10795      }
10796
10797      if (rule !== 'stroke' && !isClip && isFillTransparent.call(this)) {
10798        return;
10799      }
10800
10801      var moves = [];
10802      var alpha = this.ctx.globalAlpha;
10803
10804      if (this.ctx.fillOpacity < 1) {
10805        alpha = this.ctx.fillOpacity;
10806      }
10807
10808      var xPath = this.path;
10809
10810      for (var i = 0; i < xPath.length; i++) {
10811        var pt = xPath[i];
10812
10813        switch (pt.type) {
10814          case 'begin':
10815            moves.push({
10816              begin: true
10817            });
10818            break;
10819
10820          case 'close':
10821            moves.push({
10822              close: true
10823            });
10824            break;
10825
10826          case 'mt':
10827            moves.push({
10828              start: pt,
10829              deltas: [],
10830              abs: []
10831            });
10832            break;
10833
10834          case 'lt':
10835            var iii = moves.length;
10836
10837            if (!isNaN(xPath[i - 1].x)) {
10838              var delta = [pt.x - xPath[i - 1].x, pt.y - xPath[i - 1].y];
10839
10840              if (iii > 0) {
10841                for (iii; iii >= 0; iii--) {
10842                  if (moves[iii - 1].close !== true && moves[iii - 1].begin !== true) {
10843                    moves[iii - 1].deltas.push(delta);
10844                    moves[iii - 1].abs.push(pt);
10845                    break;
10846                  }
10847                }
10848              }
10849            }
10850
10851            break;
10852
10853          case 'bct':
10854            var delta = [pt.x1 - xPath[i - 1].x, pt.y1 - xPath[i - 1].y, pt.x2 - xPath[i - 1].x, pt.y2 - xPath[i - 1].y, pt.x - xPath[i - 1].x, pt.y - xPath[i - 1].y];
10855            moves[moves.length - 1].deltas.push(delta);
10856            break;
10857
10858          case 'qct':
10859            var x1 = xPath[i - 1].x + 2.0 / 3.0 * (pt.x1 - xPath[i - 1].x);
10860            var y1 = xPath[i - 1].y + 2.0 / 3.0 * (pt.y1 - xPath[i - 1].y);
10861            var x2 = pt.x + 2.0 / 3.0 * (pt.x1 - pt.x);
10862            var y2 = pt.y + 2.0 / 3.0 * (pt.y1 - pt.y);
10863            var x3 = pt.x;
10864            var y3 = pt.y;
10865            var delta = [x1 - xPath[i - 1].x, y1 - xPath[i - 1].y, x2 - xPath[i - 1].x, y2 - xPath[i - 1].y, x3 - xPath[i - 1].x, y3 - xPath[i - 1].y];
10866            moves[moves.length - 1].deltas.push(delta);
10867            break;
10868
10869          case 'arc':
10870            moves.push({
10871              deltas: [],
10872              abs: [],
10873              arc: true
10874            });
10875
10876            if (Array.isArray(moves[moves.length - 1].abs)) {
10877              moves[moves.length - 1].abs.push(pt);
10878            }
10879
10880            break;
10881        }
10882      }
10883
10884      var style;
10885
10886      if (!isClip) {
10887        if (rule === 'stroke') {
10888          style = 'stroke';
10889        } else {
10890          style = 'fill';
10891        }
10892      } else {
10893        style = null;
10894      }
10895
10896      for (var i = 0; i < moves.length; i++) {
10897        if (moves[i].arc) {
10898          var arcs = moves[i].abs;
10899
10900          for (var ii = 0; ii < arcs.length; ii++) {
10901            var arc = arcs[ii];
10902
10903            if (typeof arc.startAngle !== 'undefined') {
10904              var start = rad2deg(arc.startAngle);
10905              var end = rad2deg(arc.endAngle);
10906              var x = arc.x;
10907              var y = arc.y;
10908              drawArc.call(this, x, y, arc.radius, start, end, arc.counterclockwise, style, isClip);
10909            } else {
10910              drawLine.call(this, arc.x, arc.y);
10911            }
10912          }
10913        }
10914
10915        if (!moves[i].arc) {
10916          if (moves[i].close !== true && moves[i].begin !== true) {
10917            var x = moves[i].start.x;
10918            var y = moves[i].start.y;
10919            drawLines.call(this, moves[i].deltas, x, y, null, null);
10920          }
10921        }
10922      }
10923
10924      if (style) {
10925        putStyle.call(this, style);
10926      }
10927
10928      if (isClip) {
10929        doClip.call(this);
10930      }
10931    };
10932
10933    var getBaseline = function getBaseline(y) {
10934      var height = this.pdf.internal.getFontSize() / this.pdf.internal.scaleFactor;
10935      var descent = height * (this.pdf.internal.getLineHeightFactor() - 1);
10936
10937      switch (this.ctx.textBaseline) {
10938        case 'bottom':
10939          return y - descent;
10940
10941        case 'top':
10942          return y + height - descent;
10943
10944        case 'hanging':
10945          return y + height - 2 * descent;
10946
10947        case 'middle':
10948          return y + height / 2 - descent;
10949
10950        case 'ideographic':
10951          // TODO not implemented
10952          return y;
10953
10954        case 'alphabetic':
10955        default:
10956          return y;
10957      }
10958    };
10959
10960    Context2D.prototype.createLinearGradient = function createLinearGradient() {
10961      var canvasGradient = function canvasGradient() {};
10962
10963      canvasGradient.colorStops = [];
10964
10965      canvasGradient.addColorStop = function (offset, color) {
10966        this.colorStops.push([offset, color]);
10967      };
10968
10969      canvasGradient.getColor = function () {
10970        if (this.colorStops.length === 0) {
10971          return '#000000';
10972        }
10973
10974        return this.colorStops[0][1];
10975      };
10976
10977      canvasGradient.isCanvasGradient = true;
10978      return canvasGradient;
10979    };
10980
10981    Context2D.prototype.createPattern = function createPattern() {
10982      return this.createLinearGradient();
10983    };
10984
10985    Context2D.prototype.createRadialGradient = function createRadialGradient() {
10986      return this.createLinearGradient();
10987    };
10988    /**
10989    *
10990    * @param x Edge point X
10991    * @param y Edge point Y
10992    * @param r Radius
10993    * @param a1 start angle
10994    * @param a2 end angle
10995    * @param counterclockwise
10996    * @param style
10997    * @param isClip
10998    */
10999
11000
11001    var drawArc = function drawArc(x, y, r, a1, a2, counterclockwise, style, isClip) {
11002      var k = this.pdf.internal.scaleFactor;
11003      var a1r = deg2rad(a1);
11004      var a2r = deg2rad(a2);
11005      var curves = createArc.call(this, r, a1r, a2r, counterclockwise);
11006
11007      for (var i = 0; i < curves.length; i++) {
11008        var curve = curves[i];
11009
11010        if (i === 0) {
11011          doMove.call(this, curve.x1 + x, curve.y1 + y);
11012        }
11013        drawCurve.call(this, x, y, curve.x2, curve.y2, curve.x3, curve.y3, curve.x4, curve.y4);
11014      }
11015
11016      if (!isClip) {
11017        putStyle.call(this, style);
11018      } else {
11019        doClip.call(this);
11020      }
11021    };
11022
11023    var putStyle = function putStyle(style) {
11024      switch (style) {
11025        case 'stroke':
11026          this.pdf.internal.out('S');
11027          break;
11028
11029        case 'fill':
11030          this.pdf.internal.out('f');
11031          break;
11032      }
11033    };
11034
11035    var doClip = function doClip() {
11036      this.pdf.clip();
11037    };
11038
11039    var doMove = function doMove(x, y) {
11040      this.pdf.internal.out(getHorizontalCoordinateString(x) + ' ' + getVerticalCoordinateString(y) + ' m');
11041    };
11042
11043    var putText = function putText(options) {
11044      var textAlign;
11045
11046      switch (options.align) {
11047        case 'right':
11048        case 'end':
11049          textAlign = 'right';
11050          break;
11051
11052        case 'center':
11053          textAlign = 'center';
11054          break;
11055
11056        case 'left':
11057        case 'start':
11058        default:
11059          textAlign = 'left';
11060          break;
11061      }
11062
11063      var pt = this.ctx.transform.applyToPoint(new Point(options.x, options.y));
11064      var decomposedTransformationMatrix = this.ctx.transform.decompose();
11065      var matrix = new Matrix();
11066      matrix = matrix.multiply(decomposedTransformationMatrix.translate);
11067      matrix = matrix.multiply(decomposedTransformationMatrix.skew);
11068      matrix = matrix.multiply(decomposedTransformationMatrix.scale);
11069      var textDimensions = this.pdf.getTextDimensions(options.text);
11070      var textRect = this.ctx.transform.applyToRectangle(new Rectangle(options.x, options.y, textDimensions.w, textDimensions.h));
11071      var textXRect = matrix.applyToRectangle(new Rectangle(options.x, options.y - textDimensions.h, textDimensions.w, textDimensions.h));
11072      var pageArray = getPagesByPath.call(this, textXRect);
11073      var pages = [];
11074
11075      for (var ii = 0; ii < pageArray.length; ii += 1) {
11076        if (pages.indexOf(pageArray[ii]) === -1) {
11077          pages.push(pageArray[ii]);
11078        }
11079      }
11080
11081      pages.sort();
11082      var clipPath;
11083
11084      if (this.autoPaging === true) {
11085        var min = pages[0];
11086        var max = pages[pages.length - 1];
11087
11088        for (var i = min; i < max + 1; i++) {
11089          this.pdf.setPage(i);
11090
11091          if (this.ctx.clip_path.length !== 0) {
11092            var tmpPaths = this.path;
11093            clipPath = JSON.parse(JSON.stringify(this.ctx.clip_path));
11094            this.path = pathPositionRedo(clipPath, this.posX, -1 * this.pdf.internal.pageSize.height * (i - 1) + this.posY);
11095            drawPaths.call(this, 'fill', true);
11096            this.path = tmpPaths;
11097          }
11098
11099          var tmpRect = JSON.parse(JSON.stringify(textRect));
11100          tmpRect = pathPositionRedo([tmpRect], this.posX, -1 * this.pdf.internal.pageSize.height * (i - 1) + this.posY)[0];
11101
11102          if (options.scale >= 0.01) {
11103            var oldSize = this.pdf.internal.getFontSize();
11104            this.pdf.setFontSize(oldSize * options.scale);
11105          }
11106
11107          this.pdf.text(options.text, tmpRect.x, tmpRect.y, {
11108            angle: options.angle,
11109            align: textAlign,
11110            renderingMode: options.renderingMode,
11111            maxWidth: options.maxWidth
11112          });
11113
11114          if (options.scale >= 0.01) {
11115            this.pdf.setFontSize(oldSize);
11116          }
11117        }
11118      } else {
11119        if (options.scale >= 0.01) {
11120          var oldSize = this.pdf.internal.getFontSize();
11121          this.pdf.setFontSize(oldSize * options.scale);
11122        }
11123
11124        this.pdf.text(options.text, pt.x + this.posX, pt.y + this.posY, {
11125          angle: options.angle,
11126          align: textAlign,
11127          renderingMode: options.renderingMode,
11128          maxWidth: options.maxWidth
11129        });
11130
11131        if (options.scale >= 0.01) {
11132          this.pdf.setFontSize(oldSize);
11133        }
11134      }
11135    };
11136
11137    var drawLine = function drawLine(x, y, prevX, prevY) {
11138      prevX = prevX || 0;
11139      prevY = prevY || 0;
11140      this.pdf.internal.out(getHorizontalCoordinateString(x + prevX) + ' ' + getVerticalCoordinateString(y + prevY) + ' l');
11141    };
11142
11143    var drawLines = function drawLines(lines, x, y) {
11144      return this.pdf.lines(lines, x, y, null, null);
11145    };
11146
11147    var drawCurve = function drawCurve(x, y, x1, y1, x2, y2, x3, y3) {
11148      this.pdf.internal.out([f2(getHorizontalCoordinate(x1 + x)), f2(getVerticalCoordinate(y1 + y)), f2(getHorizontalCoordinate(x2 + x)), f2(getVerticalCoordinate(y2 + y)), f2(getHorizontalCoordinate(x3 + x)), f2(getVerticalCoordinate(y3 + y)), 'c'].join(' '));
11149    };
11150    /**
11151    * 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.
11152    *
11153    * 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 cub
11153ic bezier's control points.
11154    * @function createArc
11155    */
11156
11157
11158    var createArc = function createArc(radius, startAngle, endAngle, anticlockwise) {
11159      var EPSILON = 0.00001; // Roughly 1/1000th of a degree, see below        // normalize startAngle, endAngle to [-2PI, 2PI]
11160
11161      var twoPI = Math.PI * 2;
11162      var startAngleN = startAngle;
11163
11164      if (startAngleN < twoPI || startAngleN > twoPI) {
11165        startAngleN = startAngleN % twoPI;
11166      }
11167
11168      var endAngleN = endAngle;
11169
11170      if (endAngleN < twoPI || endAngleN > twoPI) {
11171        endAngleN = endAngleN % twoPI;
11172      } // Compute the sequence of arc curves, up to PI/2 at a time.        // Total arc angle is less than 2PI.
11173
11174
11175      var curves = [];
11176      var piOverTwo = Math.PI / 2.0; //var sgn = (startAngle < endAngle) ? +1 : -1; // clockwise or counterclockwise
11177
11178      var sgn = anticlockwise ? -1 : +1;
11179      var a1 = startAngle;
11180
11181      for (var totalAngle = Math.min(twoPI, Math.abs(endAngleN - startAngleN)); totalAngle > EPSILON;) {
11182        var a2 = a1 + sgn * Math.min(totalAngle, piOverTwo);
11183        curves.push(createSmallArc.call(this, radius, a1, a2));
11184        totalAngle -= Math.abs(a2 - a1);
11185        a1 = a2;
11186      }
11187
11188      return curves;
11189    };
11190    /**
11191    * 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.
11192    *
11193    * 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.
11194    *
11195    * 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.
11196    */
11197
11198
11199    var createSmallArc = function createSmallArc(r, a1, a2) {
11200      var a = (a2 - a1) / 2.0;
11201      var x4 = r * Math.cos(a);
11202      var y4 = r * Math.sin(a);
11203      var x1 = x4;
11204      var y1 = -y4;
11205      var q1 = x1 * x1 + y1 * y1;
11206      var q2 = q1 + x1 * x4 + y1 * y4;
11207      var k2 = 4 / 3 * (Math.sqrt(2 * q1 * q2) - q2) / (x1 * y4 - y1 * x4);
11208      var x2 = x1 - k2 * y1;
11209      var y2 = y1 + k2 * x1;
11210      var x3 = x2;
11211      var y3 = -y2;
11212      var ar = a + a1;
11213      var cos_ar = Math.cos(ar);
11214      var sin_ar = Math.sin(ar);
11215      return {
11216        x1: r * Math.cos(a1),
11217        y1: r * Math.sin(a1),
11218        x2: x2 * cos_ar - y2 * sin_ar,
11219        y2: x2 * sin_ar + y2 * cos_ar,
11220        x3: x3 * cos_ar - y3 * sin_ar,
11221        y3: x3 * sin_ar + y3 * cos_ar,
11222        x4: r * Math.cos(a2),
11223        y4: r * Math.sin(a2)
11224      };
11225    };
11226
11227    var rad2deg = function rad2deg(value) {
11228      return value * 180 / Math.PI;
11229    };
11230
11231    var deg2rad = function deg2rad(deg) {
11232      return deg * Math.PI / 180;
11233    };
11234
11235    var getQuadraticCurveBoundary = function getQuadraticCurveBoundary(sx, sy, cpx, cpy, ex, ey) {
11236      var midX1 = sx + (cpx - sx) * 0.50;
11237      var midY1 = sy + (cpy - sy) * 0.50;
11238      var midX2 = ex + (cpx - ex) * 0.50;
11239      var midY2 = ey + (cpy - ey) * 0.50;
11240      var resultX1 = Math.min(sx, ex, midX1, midX2);
11241      var resultX2 = Math.max(sx, ex, midX1, midX2);
11242      var resultY1 = Math.min(sy, ey, midY1, midY2);
11243      var resultY2 = Math.max(sy, ey, midY1, midY2);
11244      return new Rectangle(resultX1, resultY1, resultX2 - resultX1, resultY2 - resultY1);
11245    }; //De Casteljau algorithm
11246
11247
11248    var getBezierCurveBoundary = function getBezierCurveBoundary(ax, ay, bx, by, cx, cy, dx, dy) {
11249      var tobx = bx - ax;
11250      var toby = by - ay;
11251      var tocx = cx - bx;
11252      var tocy = cy - by;
11253      var todx = dx - cx;
11254      var tody = dy - cy;
11255      var precision = 40;
11256      var d, px, py, qx, qy, rx, ry, tx, ty, sx, sy, x, y, i, minx, miny, maxx, maxy, toqx, toqy, torx, tory, totx, toty;
11257
11258      for (var i = 0; i < precision + 1; i++) {
11259        d = i / precision;
11260        px = ax + d * tobx;
11261        py = ay + d * toby;
11262        qx = bx + d * tocx;
11263        qy = by + d * tocy;
11264        rx = cx + d * todx;
11265        ry = cy + d * tody;
11266        toqx = qx - px;
11267        toqy = qy - py;
11268        torx = rx - qx;
11269        tory = ry - qy;
11270        sx = px + d * toqx;
11271        sy = py + d * toqy;
11272        tx = qx + d * torx;
11273        ty = qy + d * tory;
11274        totx = tx - sx;
11275        toty = ty - sy;
11276        x = sx + d * totx;
11277        y = sy + d * toty;
11278
11279        if (i == 0) {
11280          minx = x;
11281          miny = y;
11282          maxx = x;
11283          maxy = y;
11284        } else {
11285          minx = Math.min(minx, x);
11286          miny = Math.min(miny, y);
11287          maxx = Math.max(maxx, x);
11288          maxy = Math.max(maxy, y);
11289        }
11290      }
11291
11292      return new Rectangle(Math.round(minx), Math.round(miny), Math.round(maxx - minx), Math.round(maxy - miny));
11293    };
11294
11295    var Point = function Point(x, y) {
11296      var _x = x || 0;
11297
11298      Object.defineProperty(this, 'x', {
11299        enumerable: true,
11300        get: function get() {
11301          return _x;
11302        },
11303        set: function set(value) {
11304          if (!isNaN(value)) {
11305            _x = parseFloat(value);
11306          }
11307        }
11308      });
11309
11310      var _y = y || 0;
11311
11312      Object.defineProperty(this, 'y', {
11313        enumerable: true,
11314        get: function get() {
11315          return _y;
11316        },
11317        set: function set(value) {
11318          if (!isNaN(value)) {
11319            _y = parseFloat(value);
11320          }
11321        }
11322      });
11323      var _type = 'pt';
11324      Object.defineProperty(this, 'type', {
11325        enumerable: true,
11326        get: function get() {
11327          return _type;
11328        },
11329        set: function set(value) {
11330          _type = value.toString();
11331        }
11332      });
11333      return this;
11334    };
11335
11336    var Rectangle = function Rectangle(x, y, w, h) {
11337      Point.call(this, x, y);
11338      this.type = 'rect';
11339
11340      var _w = w || 0;
11341
11342      Object.defineProperty(this, 'w', {
11343        enumerable: true,
11344        get: function get() {
11345          return _w;
11346        },
11347        set: function set(value) {
11348          if (!isNaN(value)) {
11349            _w = parseFloat(value);
11350          }
11351        }
11352      });
11353
11354      var _h = h || 0;
11355
11356      Object.defineProperty(this, 'h', {
11357        enumerable: true,
11358        get: function get() {
11359          return _h;
11360        },
11361        set: function set(value) {
11362          if (!isNaN(value)) {
11363            _h = parseFloat(value);
11364          }
11365        }
11366      });
11367      return this;
11368    };
11369
11370    var Matrix = function Matrix(sx, shy, shx, sy, tx, ty) {
11371      var _matrix = [];
11372      Object.defineProperty(this, 'sx', {
11373        get: function get() {
11374          return _matrix[0];
11375        },
11376        set: function set(value) {
11377          _matrix[0] = Math.round(value * 100000) / 100000;
11378        }
11379      });
11380      Object.defineProperty(this, 'shy', {
11381        get: function get() {
11382          return _matrix[1];
11383        },
11384        set: function set(value) {
11385          _matrix[1] = Math.round(value * 100000) / 100000;
11386        }
11387      });
11388      Object.defineProperty(this, 'shx', {
11389        get: function get() {
11390          return _matrix[2];
11391        },
11392        set: function set(value) {
11393          _matrix[2] = Math.round(value * 100000) / 100000;
11394        }
11395      });
11396      Object.defineProperty(this, 'sy', {
11397        get: function get() {
11398          return _matrix[3];
11399        },
11400        set: function set(value) {
11401          _matrix[3] = Math.round(value * 100000) / 100000;
11402        }
11403      });
11404      Object.defineProperty(this, 'tx', {
11405        get: function get() {
11406          return _matrix[4];
11407        },
11408        set: function set(value) {
11409          _matrix[4] = Math.round(value * 100000) / 100000;
11410        }
11411      });
11412      Object.defineProperty(this, 'ty', {
11413        get: function get() {
11414          return _matrix[5];
11415        },
11416        set: function set(value) {
11417          _matrix[5] = Math.round(value * 100000) / 100000;
11418        }
11419      });
11420      Object.defineProperty(this, 'rotation', {
11421        get: function get() {
11422          return Math.atan2(this.shx, this.sx);
11423        }
11424      });
11425      Object.defineProperty(this, 'scaleX', {
11426        get: function get() {
11427          return this.decompose().scale.sx;
11428        }
11429      });
11430      Object.defineProperty(this, 'scaleY', {
11431        get: function get() {
11432          return this.decompose().scale.sy;
11433        }
11434      });
11435      Object.defineProperty(this, 'isIdentity', {
11436        get: function get() {
11437          if (this.sx !== 1) {
11438            return false;
11439          }
11440
11441          if (this.shy !== 0) {
11442            return false;
11443          }
11444
11445          if (this.shx !== 0) {
11446            return false;
11447          }
11448
11449          if (this.sy !== 1) {
11450            return false;
11451          }
11452
11453          if (this.tx !== 0) {
11454            return false;
11455          }
11456
11457          if (this.ty !== 0) {
11458            return false;
11459          }
11460
11461          return true;
11462        }
11463      });
11464      this.sx = !isNaN(sx) ? sx : 1;
11465      this.shy = !isNaN(shy) ? shy : 0;
11466      this.shx = !isNaN(shx) ? shx : 0;
11467      this.sy = !isNaN(sy) ? sy : 1;
11468      this.tx = !isNaN(tx) ? tx : 0;
11469      this.ty = !isNaN(ty) ? ty : 0;
11470      return this;
11471    };
11472    /**
11473    * Multiply the matrix with given Matrix
11474    * 
11475    * @function multiply
11476    * @param matrix
11477    * @returns {Matrix}
11478    * @private
11479    * @ignore
11480    */
11481
11482
11483    Matrix.prototype.multiply = function (matrix) {
11484      var sx = matrix.sx * this.sx + matrix.shy * this.shx;
11485      var shy = matrix.sx * this.shy + matrix.shy * this.sy;
11486      var shx = matrix.shx * this.sx + matrix.sy * this.shx;
11487      var sy = matrix.shx * this.shy + matrix.sy * this.sy;
11488      var tx = matrix.tx * this.sx + matrix.ty * this.shx + this.tx;
11489      var ty = matrix.tx * this.shy + matrix.ty * this.sy + this.ty;
11490      return new Matrix(sx, shy, shx, sy, tx, ty);
11491    };
11492    /**
11493    * @function decompose
11494    * @private
11495    * @ignore
11496    */
11497
11498
11499    Matrix.prototype.decompose = function () {
11500      var a = this.sx;
11501      var b = this.shy;
11502      var c = this.shx;
11503      var d = this.sy;
11504      var e = this.tx;
11505      var f = this.ty;
11506      var scaleX = Math.sqrt(a * a + b * b);
11507      a /= scaleX;
11508      b /= scaleX;
11509      var shear = a * c + b * d;
11510      c -= a * shear;
11511      d -= b * shear;
11512      var scaleY = Math.sqrt(c * c + d * d);
11513      c /= scaleY;
11514      d /= scaleY;
11515      shear /= scaleY;
11516
11517      if (a * d < b * c) {
11518        a = -a;
11519        b = -b;
11520        shear = -shear;
11521        scaleX = -scaleX;
11522      }
11523
11524      return {
11525        scale: new Matrix(scaleX, 0, 0, scaleY, 0, 0),
11526        translate: new Matrix(1, 0, 0, 1, e, f),
11527        rotate: new Matrix(a, b, -b, a, 0, 0),
11528        skew: new Matrix(1, 0, shear, 1, 0, 0)
11529      };
11530    };
11531    /**
11532    * @function applyToPoint
11533    * @private
11534    * @ignore
11535    */
11536
11537
11538    Matrix.prototype.applyToPoint = function (pt) {
11539      var x = pt.x * this.sx + pt.y * this.shx + this.tx;
11540      var y = pt.x * this.shy + pt.y * this.sy + this.ty;
11541      return new Point(x, y);
11542    };
11543    /**
11544    * @function applyToRectangle
11545    * @private
11546    * @ignore
11547    */
11548
11549
11550    Matrix.prototype.applyToRectangle = function (rect) {
11551      var pt1 = this.applyToPoint(rect);
11552      var pt2 = this.applyToPoint(new Point(rect.x + rect.w, rect.y + rect.h));
11553      return new Rectangle(pt1.x, pt1.y, pt2.x - pt1.x, pt2.y - pt1.y);
11554    };
11555    /**
11556    * @function clone
11557    * @private
11558    * @ignore
11559    */
11560
11561
11562    Matrix.prototype.clone = function () {
11563      var sx = this.sx;
11564      var shy = this.shy;
11565      var shx = this.shx;
11566      var sy = this.sy;
11567      var tx = this.tx;
11568      var ty = this.ty;
11569      return new Matrix(sx, shy, shx, sy, tx, ty);
11570    };
11571  })(jsPDF.API, typeof self !== 'undefined' && self || typeof window !== 'undefined' && window || typeof global !== 'undefined' && global || Function('return typeof this === "object" && this.content')() || Function('return this')());
11572
11573  /**
11574   * jsPDF filters PlugIn
11575   * Copyright (c) 2014 Aras Abbasi 
11576   *
11577   * Licensed under the MIT License.
11578   * http://opensource.org/licenses/mit-license
11579   */
11580  (function (jsPDFAPI) {
11581
11582    var ASCII85Encode = function ASCII85Encode(a) {
11583      var b, c, d, e, f, g, h, i, j, k;
11584
11585      for (!/[^\x00-\xFF]/.test(a), b = "\x00\x00\x00\x00".slice(a.length % 4 || 4), a += b, c = [], d = 0, e = a.length; e > d; d += 4) {
11586        f = (a.charCodeAt(d) << 24) + (a.charCodeAt(d + 1) << 16) + (a.charCodeAt(d + 2) << 8) + a.charCodeAt(d + 3), 0 !== f ? (k = f % 85, f = (f - k) / 85, j = f % 85, f = (f - j) / 85, i = f % 85, f = (f - i) / 85, h = f % 85, f = (f - h) / 85, g = f % 85, c.push(g + 33, h + 33, i + 33, j + 33, k + 33)) : c.push(122);
11587      }
11588
11589      return function (a, b) {
11590        for (var c = b; c > 0; c--) {
11591          a.pop();
11592        }
11593      }(c, b.length), String.fromCharCode.apply(String, c) + "~>";
11594    };
11595
11596    var ASCII85Decode = function ASCII85Decode(a) {
11597      var c,
11598          d,
11599          e,
11600          f,
11601          g,
11602          h = String,
11603          l = "length",
11604          w = 255,
11605          x = "charCodeAt",
11606          y = "slice",
11607          z = "replace";
11608
11609      for ("~>" === a[y](-2), a = a[y](0, -2)[z](/\s/g, "")[z]("z", "!!!!!"), c = "uuuuu"[y](a[l] % 5 || 5), a += c, e = [], f = 0, g = a[l]; g > f; f += 5) {
11610        d = 52200625 * (a[x](f) - 33) + 614125 * (a[x](f + 1) - 33) + 7225 * (a[x](f + 2) - 33) + 85 * (a[x](f + 3) - 33) + (a[x](f + 4) - 33), e.push(w & d >> 24, w & d >> 16, w & d >> 8, w & d);
11611      }
11612
11613      return function (a, b) {
11614        for (var c = b; c > 0; c--) {
11615          a.pop();
11616        }
11617      }(e, c[l]), h.fromCharCode.apply(h, e);
11618    };
11619    /**
11620    * TODO: Not Tested:
11621    //https://gist.github.com/revolunet/843889
11622    // LZW-compress a string
11623    var LZWEncode = function(s, options) {
11624      options = Object.assign({
11625        predictor: 1,
11626        colors: 1,
11627        bitsPerComponent: 8,
11628        columns: 1,
11629        earlyChange: 1
11630      }, options);
11631       var dict = {};
11632      var data = (s + "").split("");
11633      var out = [];
11634      var currChar;
11635      var phrase = data[0];
11636      var code = 256; //0xe000
11637      for (var i=1; i<data.length; i++) {
11638        currChar=data[i];
11639        if (dict['_' + phrase + currChar] != null) {
11640          phrase += currChar;
11641        }
11642        else {
11643          out.push(phrase.length > 1 ? dict['_'+phrase] : phrase.charCodeAt(0));
11644          dict['_' + phrase + currChar] = code;
11645          code++;
11646          phrase=currChar;
11647        }
11648      }
11649      out.push(phrase.length > 1 ? dict['_'+phrase] : phrase.charCodeAt(0));
11650      for (var i=0; i<out.length; i++) {
11651        out[i] = String.fromCharCode(out[i]);
11652      }
11653      return out.join("");
11654    }
11655     // Decompress an LZW-encoded string
11656    var LZWDecode = function(s, options) {
11657      options = Object.assign({
11658        predictor: 1,
11659        colors: 1,
11660        bitsPerComponent: 8,
11661        columns: 1,
11662        earlyChange: 1
11663      }, options);
11664       var dict = {};
11665      var data = (s + "").split("");
11666      var currChar = data[0];
11667      var oldPhrase = currChar;
11668      var out = [currChar];
11669      var code = 256;
11670      var phrase;
11671      for (var i=1; i<data.length; i++) {
11672        var currCode = data[i].charCodeAt(0);
11673        if (currCode < 256) {
11674          phrase = data[i];
11675        }
11676        else {
11677           phrase = dict['_'+currCode] ? dict['_'+currCode] : (oldPhrase + currChar);
11678        }
11679        out.push(phrase);
11680        currChar = phrase.charAt(0);
11681        dict['_'+code] = oldPhrase + currChar;
11682        code++;
11683        oldPhrase = phrase;
11684      }
11685      return out.join("");
11686    }
11687    */
11688
11689
11690    var ASCIIHexEncode = function ASCIIHexEncode(value) {
11691      var result = '';
11692      var i;
11693
11694      for (var i = 0; i < value.length; i += 1) {
11695        result += ("0" + value.charCodeAt(i).toString(16)).slice(-2);
11696      }
11697
11698      result += '>';
11699      return result;
11700    };
11701
11702    var ASCIIHexDecode = function ASCIIHexDecode(value) {
11703      var regexCheckIfHex = new RegExp(/^([0-9A-Fa-f]{2})+$/);
11704      value = value.replace(/\s/g, '');
11705
11706      if (value.indexOf(">") !== -1) {
11707        value = value.substr(0, value.indexOf(">"));
11708      }
11709
11710      if (value.length % 2) {
11711        value += "0";
11712      }
11713
11714      if (regexCheckIfHex.test(value) === false) {
11715        return "";
11716      }
11717
11718      var result = '';
11719      var i;
11720
11721      for (var i = 0; i < value.length; i += 2) {
11722        result += String.fromCharCode("0x" + (value[i] + value[i + 1]));
11723      }
11724
11725      return result;
11726    };
11727
11728    var FlateEncode = function FlateEncode(data, options) {
11729      options = Object.assign({
11730        predictor: 1,
11731        colors: 1,
11732        bitsPerComponent: 8,
11733        columns: 1
11734      }, options);
11735      var arr = [];
11736      var i = data.length;
11737      var adler32;
11738      var deflater;
11739
11740      while (i--) {
11741        arr[i] = data.charCodeAt(i);
11742      }
11743
11744      adler32 = jsPDFAPI.adler32cs.from(data);
11745      deflater = new Deflater(6);
11746      deflater.append(new Uint8Array(arr));
11747      data = deflater.flush();
11748      arr = new Uint8Array(data.length + 6);
11749      arr.set(new Uint8Array([120, 156])), arr.set(data, 2);
11750      arr.set(new Uint8Array([adler32 & 0xFF, adler32 >> 8 & 0xFF, adler32 >> 16 & 0xFF, adler32 >> 24 & 0xFF]), data.length + 2);
11751      data = String.fromCharCode.apply(null, arr);
11752      return data;
11753    };
11754
11755    jsPDFAPI.processDataByFilters = function (origData, filterChain) {
11756
11757      var i = 0;
11758      var data = origData || '';
11759      var reverseChain = [];
11760      filterChain = filterChain || [];
11761
11762      if (typeof filterChain === "string") {
11763        filterChain = [filterChain];
11764      }
11765
11766      for (i = 0; i < filterChain.length; i += 1) {
11767        switch (filterChain[i]) {
11768          case "ASCII85Decode":
11769          case "/ASCII85Decode":
11770            data = ASCII85Decode(data);
11771            reverseChain.push("/ASCII85Encode");
11772            break;
11773
11774          case "ASCII85Encode":
11775          case "/ASCII85Encode":
11776            data = ASCII85Encode(data);
11777            reverseChain.push("/ASCII85Decode");
11778            break;
11779
11780          case "ASCIIHexDecode":
11781          case "/ASCIIHexDecode":
11782            data = ASCIIHexDecode(data);
11783            reverseChain.push("/ASCIIHexEncode");
11784            break;
11785
11786          case "ASCIIHexEncode":
11787          case "/ASCIIHexEncode":
11788            data = ASCIIHexEncode(data);
11789            reverseChain.push("/ASCIIHexDecode");
11790            break;
11791
11792          case "FlateEncode":
11793          case "/FlateEncode":
11794            data = FlateEncode(data);
11795            reverseChain.push("/FlateDecode");
11796            break;
11797
11798          /**
11799          case "LZWDecode":
11800          case "/LZWDecode":
11801            data = LZWDecode(data);
11802            reverseChain.push("/LZWEncode");
11803            break;
11804          case "LZWEncode":
11805          case "/LZWEncode":
11806            data = LZWEncode(data);
11807            reverseChain.push("/LZWDecode");
11808            break;
11809          */
11810
11811          default:
11812            throw "The filter: \"" + filterChain[i] + "\" is not implemented";
11813        }
11814      }
11815
11816      return {
11817        data: data,
11818        reverseChain: reverseChain.reverse().join(" ")
11819      };
11820    };
11821  })(jsPDF.API);
11822
11823  /**
11824   * jsPDF fileloading PlugIn
11825   * Copyright (c) 2018 Aras Abbasi ([email protected])
11826   *
11827   * Licensed under the MIT License.
11828   * http://opensource.org/licenses/mit-license
11829   */
11830
11831  /**
11832  * @name fileloading
11833  * @module
11834  */
11835  (function (jsPDFAPI) {
11836    /**
11837    * @name loadFile
11838    * @function
11839    * @param {string} url
11840    * @param {boolean} sync
11841    * @param {function} callback
11842    * @returns {string|undefined} result
11843    */
11844
11845    jsPDFAPI.loadFile = function (url, sync, callback) {
11846      sync = sync || true;
11847
11848      callback = callback || function () {};
11849
11850      var result;
11851
11852      var xhr = function xhr(url, sync, callback) {
11853        var req = new XMLHttpRequest();
11854        var byteArray = [];
11855        var i = 0;
11856
11857        var sanitizeUnicode = function sanitizeUnicode(data) {
11858          var dataLength = data.length;
11859          var StringFromCharCode = String.fromCharCode; //Transform Unicode to ASCII
11860
11861          for (i = 0; i < dataLength; i += 1) {
11862            byteArray.push(StringFromCharCode(data.charCodeAt(i) & 0xff));
11863          }
11864
11865          return byteArray.join("");
11866        };
11867
11868        req.open('GET', url, !sync); // XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
11869
11870        req.overrideMimeType('text\/plain; charset=x-user-defined');
11871
11872        if (sync === false) {
11873          req.onload = function () {
11874            return sanitizeUnicode(this.responseText);
11875          };
11876        }
11877
11878        req.send(null);
11879
11880        if (req.status !== 200) {
11881          console.warn('Unable to load file "' + url + '"');
11882          return;
11883        }
11884
11885        if (sync) {
11886          return sanitizeUnicode(req.responseText);
11887        }
11888      };
11889
11890      try {
11891        result = xhr(url, sync, callback);
11892      } catch (e) {
11893        result = undefined;
11894      }
11895
11896      return result;
11897    };
11898    /**
11899    * @name loadImageFile
11900    * @function
11901    * @param {string} path
11902    * @param {boolean} sync
11903    * @param {function} callback
11904    */
11905
11906
11907    jsPDFAPI.loadImageFile = jsPDFAPI.loadFile;
11908  })(jsPDF.API);
11909
11910  /**
11911   * Copyright (c) 2018 Erik Koopmans
11912   * Released under the MIT License.
11913   *
11914   * Licensed under the MIT License.
11915   * http://opensource.org/licenses/mit-license
11916   */
11917
11918  /**
11919   * jsPDF html PlugIn
11920   *
11921   * @name html
11922   * @module
11923   */
11924  (function (jsPDFAPI, global) {
11925    /**
11926    * Determine the type of a variable/object.
11927    * 
11928    * @private
11929    * @ignore
11930    */
11931
11932    var objType = function objType(obj) {
11933      var type = _typeof(obj);
11934
11935      if (type === 'undefined') return 'undefined';else if (type === 'string' || obj instanceof String) return 'string';else if (type === 'number' || obj instanceof Number) return 'number';else if (type === 'function' || obj instanceof Function) return 'function';else if (!!obj && obj.constructor === Array) return 'array';else if (obj && obj.nodeType === 1) return 'element';else if (type === 'object') return 'object';else return 'unknown';
11936    };
11937    /**
11938    * Create an HTML element with optional className, innerHTML, and style.
11939    * 
11940    * @private
11941    * @ignore
11942    */
11943
11944
11945    var createElement = function createElement(tagName, opt) {
11946      var el = document.createElement(tagName);
11947      if (opt.className) el.className = opt.className;
11948
11949      if (opt.innerHTML) {
11950        el.innerHTML = opt.innerHTML;
11951        var scripts = el.getElementsByTagName('script');
11952
11953        for (var i = scripts.length; i-- > 0; null) {
11954          scripts[i].parentNode.removeChild(scripts[i]);
11955        }
11956      }
11957
11958      for (var key in opt.style) {
11959        el.style[key] = opt.style[key];
11960      }
11961
11962      return el;
11963    };
11964    /**
11965    * Deep-clone a node and preserve contents/properties.
11966    * 
11967    * @private
11968    * @ignore
11969    */
11970
11971
11972    var cloneNode = function cloneNode(node, javascriptEnabled) {
11973      // Recursively clone the node.
11974      var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
11975
11976      for (var child = node.firstChild; child; child = child.nextSibling) {
11977        if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== 'SCRIPT') {
11978          clone.appendChild(cloneNode(child, javascriptEnabled));
11979        }
11980      }
11981
11982      if (node.nodeType === 1) {
11983        // Preserve contents/properties of special nodes.
11984        if (node.nodeName === 'CANVAS') {
11985          clone.width = node.width;
11986          clone.height = node.height;
11987          clone.getContext('2d').drawImage(node, 0, 0);
11988        } else if (node.nodeName === 'TEXTAREA' || node.nodeName === 'SELECT') {
11989          clone.value = node.value;
11990        } // Preserve the node's scroll position when it loads.
11991
11992
11993        clone.addEventListener('load', function () {
11994          clone.scrollTop = node.scrollTop;
11995          clone.scrollLeft = node.scrollLeft;
11996        }, true);
11997      }
vendor: 15,810 bytes, lines 11997-12483
11997 // Return the cloned node.
11998
11999
12000      return clone;
12001    };
12002    /* ----- CONSTRUCTOR ----- */
12003
12004
12005    var Worker = function Worker(opt) {
12006      // Create the root parent for the proto chain, and the starting Worker.
12007      var root = Object.assign(Worker.convert(Promise.resolve()), JSON.parse(JSON.stringify(Worker.template)));
12008      var self = Worker.convert(Promise.resolve(), root); // Set progress, optional settings, and return.
12009
12010      self = self.setProgress(1, Worker, 1, [Worker]);
12011      self = self.set(opt);
12012      return self;
12013    }; // Boilerplate for subclassing Promise.
12014
12015
12016    Worker.prototype = Object.create(Promise.prototype);
12017    Worker.prototype.constructor = Worker; // Converts/casts promises into Workers.
12018
12019    Worker.convert = function convert(promise, inherit) {
12020      // Uses prototypal inheritance to receive changes made to ancestors' properties.
12021      promise.__proto__ = inherit || Worker.prototype;
12022      return promise;
12023    };
12024
12025    Worker.template = {
12026      prop: {
12027        src: null,
12028        container: null,
12029        overlay: null,
12030        canvas: null,
12031        img: null,
12032        pdf: null,
12033        pageSize: null,
12034        callback: function callback() {}
12035      },
12036      progress: {
12037        val: 0,
12038        state: null,
12039        n: 0,
12040        stack: []
12041      },
12042      opt: {
12043        filename: 'file.pdf',
12044        margin: [0, 0, 0, 0],
12045        enableLinks: true,
12046        x: 0,
12047        y: 0,
12048        html2canvas: {},
12049        jsPDF: {}
12050      }
12051    };
12052    /* ----- FROM / TO ----- */
12053
12054    Worker.prototype.from = function from(src, type) {
12055      function getType(src) {
12056        switch (objType(src)) {
12057          case 'string':
12058            return 'string';
12059
12060          case 'element':
12061            return src.nodeName.toLowerCase === 'canvas' ? 'canvas' : 'element';
12062
12063          default:
12064            return 'unknown';
12065        }
12066      }
12067
12068      return this.then(function from_main() {
12069        type = type || getType(src);
12070
12071        switch (type) {
12072          case 'string':
12073            return this.set({
12074              src: createElement('div', {
12075                innerHTML: src
12076              })
12077            });
12078
12079          case 'element':
12080            return this.set({
12081              src: src
12082            });
12083
12084          case 'canvas':
12085            return this.set({
12086              canvas: src
12087            });
12088
12089          case 'img':
12090            return this.set({
12091              img: src
12092            });
12093
12094          default:
12095            return this.error('Unknown source type.');
12096        }
12097      });
12098    };
12099
12100    Worker.prototype.to = function to(target) {
12101      // Route the 'to' request to the appropriate method.
12102      switch (target) {
12103        case 'container':
12104          return this.toContainer();
12105
12106        case 'canvas':
12107          return this.toCanvas();
12108
12109        case 'img':
12110          return this.toImg();
12111
12112        case 'pdf':
12113          return this.toPdf();
12114
12115        default:
12116          return this.error('Invalid target.');
12117      }
12118    };
12119
12120    Worker.prototype.toContainer = function toContainer() {
12121      // Set up function prerequisites.
12122      var prereqs = [function checkSrc() {
12123        return this.prop.src || this.error('Cannot duplicate - no source HTML.');
12124      }, function checkPageSize() {
12125        return this.prop.pageSize || this.setPageSize();
12126      }];
12127      return this.thenList(prereqs).then(function toContainer_main() {
12128        // Define the CSS styles for the container and its overlay parent.
12129        var overlayCSS = {
12130          position: 'fixed',
12131          overflow: 'hidden',
12132          zIndex: 1000,
12133          left: '-100000px',
12134          right: 0,
12135          bottom: 0,
12136          top: 0
12137        };
12138        var containerCSS = {
12139          position: 'relative',
12140          display: 'inline-block',
12141          width: Math.max(this.prop.src.clientWidth, this.prop.src.scrollWidth, this.prop.src.offsetWidth) + 'px',
12142          left: 0,
12143          right: 0,
12144          top: 0,
12145          margin: 'auto',
12146          backgroundColor: 'white'
12147        }; // Set the overlay to hidden (could be changed in the future to provide a print preview).
12148
12149        var source = cloneNode(this.prop.src, this.opt.html2canvas.javascriptEnabled);
12150
12151        if (source.tagName === 'BODY') {
12152          containerCSS.height = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight) + 'px';
12153        }
12154
12155        this.prop.overlay = createElement('div', {
12156          className: 'html2pdf__overlay',
12157          style: overlayCSS
12158        });
12159        this.prop.container = createElement('div', {
12160          className: 'html2pdf__container',
12161          style: containerCSS
12162        });
12163        this.prop.container.appendChild(source);
12164        this.prop.container.firstChild.appendChild(createElement('div', {
12165          style: {
12166            clear: 'both',
12167            border: '0 none transparent',
12168            margin: 0,
12169            padding: 0,
12170            height: 0
12171          }
12172        }));
12173        this.prop.container.style.float = 'none';
12174        this.prop.overlay.appendChild(this.prop.container);
12175        document.body.appendChild(this.prop.overlay);
12176        this.prop.container.firstChild.style.position = 'relative';
12177        this.prop.container.height = Math.max(this.prop.container.firstChild.clientHeight, this.prop.container.firstChild.scrollHeight, this.prop.container.firstChild.offsetHeight) + 'px';
12178      });
12179    };
12180
12181    Worker.prototype.toCanvas = function toCanvas() {
12182      // Set up function prerequisites.
12183      var prereqs = [function checkContainer() {
12184        return document.body.contains(this.prop.container) || this.toContainer();
12185      }]; // Fulfill prereqs then create the canvas.
12186
12187      return this.thenList(prereqs).then(function toCanvas_main() {
12188        // Handle old-fashioned 'onrendered' argument.
12189        var options = Object.assign({}, this.opt.html2canvas);
12190        delete options.onrendered;
12191
12192        if (!this.isHtml2CanvasLoaded()) {
12193          return;
12194        }
12195
12196        return html2canvas(this.prop.container, options);
12197      }).then(function toCanvas_post(canvas) {
12198        // Handle old-fashioned 'onrendered' argument.
12199        var onRendered = this.opt.html2canvas.onrendered || function () {};
12200
12201        onRendered(canvas);
12202        this.prop.canvas = canvas;
12203        document.body.removeChild(this.prop.overlay);
12204      });
12205    };
12206
12207    Worker.prototype.toContext2d = function toContext2d() {
12208      // Set up function prerequisites.
12209      var prereqs = [function checkContainer() {
12210        return document.body.contains(this.prop.container) || this.toContainer();
12211      }]; // Fulfill prereqs then create the canvas.
12212
12213      return this.thenList(prereqs).then(function toContext2d_main() {
12214        // Handle old-fashioned 'onrendered' argument.
12215        var pdf = this.opt.jsPDF;
12216        var options = Object.assign({
12217          async: true,
12218          allowTaint: true,
12219          backgroundColor: '#ffffff',
12220          imageTimeout: 15000,
12221          logging: true,
12222          proxy: null,
12223          removeContainer: true,
12224          foreignObjectRendering: false,
12225          useCORS: false
12226        }, this.opt.html2canvas);
12227        delete options.onrendered;
12228        pdf.context2d.autoPaging = true;
12229        pdf.context2d.posX = this.opt.x;
12230        pdf.context2d.posY = this.opt.y;
12231        options.windowHeight = options.windowHeight || 0;
12232        options.windowHeight = options.windowHeight == 0 ? Math.max(this.prop.container.clientHeight, this.prop.container.scrollHeight, this.prop.container.offsetHeight) : options.windowHeight;
12233
12234        if (!this.isHtml2CanvasLoaded()) {
12235          return;
12236        }
12237
12238        return html2canvas(this.prop.container, options);
12239      }).then(function toContext2d_post(canvas) {
12240        // Handle old-fashioned 'onrendered' argument.
12241        var onRendered = this.opt.html2canvas.onrendered || function () {};
12242
12243        onRendered(canvas);
12244        this.prop.canvas = canvas;
12245        document.body.removeChild(this.prop.overlay);
12246      });
12247    };
12248
12249    Worker.prototype.toImg = function toImg() {
12250      // Set up function prerequisites.
12251      var prereqs = [function checkCanvas() {
12252        return this.prop.canvas || this.toCanvas();
12253      }]; // Fulfill prereqs then create the image.
12254
12255      return this.thenList(prereqs).then(function toImg_main() {
12256        var imgData = this.prop.canvas.toDataURL('image/' + this.opt.image.type, this.opt.image.quality);
12257        this.prop.img = document.createElement('img');
12258        this.prop.img.src = imgData;
12259      });
12260    };
12261
12262    Worker.prototype.toPdf = function toPdf() {
12263      // Set up function prerequisites.
12264      var prereqs = [function checkContext2d() {
12265        return this.toContext2d();
12266      } //function checkCanvas() { return this.prop.canvas || this.toCanvas(); }
12267      ]; // Fulfill prereqs then create the image.
12268
12269      return this.thenList(prereqs).then(function toPdf_main() {
12270        // Create local copies of frequently used properties.
12271        this.prop.pdf = this.prop.pdf || this.opt.jsPDF;
12272      });
12273    };
12274    /* ----- OUTPUT / SAVE ----- */
12275
12276
12277    Worker.prototype.output = function output(type, options, src) {
12278      // Redirect requests to the correct function (outputPdf / outputImg).
12279      src = src || 'pdf';
12280
12281      if (src.toLowerCase() === 'img' || src.toLowerCase() === 'image') {
12282        return this.outputImg(type, options);
12283      } else {
12284        return this.outputPdf(type, options);
12285      }
12286    };
12287
12288    Worker.prototype.outputPdf = function outputPdf(type, options) {
12289      // Set up function prerequisites.
12290      var prereqs = [function checkPdf() {
12291        return this.prop.pdf || this.toPdf();
12292      }]; // Fulfill prereqs then perform the appropriate output.
12293
12294      return this.thenList(prereqs).then(function outputPdf_main() {
12295        /* Currently implemented output types:
12296         *    https://rawgit.com/MrRio/jsPDF/master/docs/jspdf.js.html#line992
12297         *  save(options), arraybuffer, blob, bloburi/bloburl,
12298         *  datauristring/dataurlstring, dataurlnewwindow, datauri/dataurl
12299         */
12300        return this.prop.pdf.output(type, options);
12301      });
12302    };
12303
12304    Worker.prototype.outputImg = function outputImg(type, options) {
12305      // Set up function prerequisites.
12306      var prereqs = [function checkImg() {
12307        return this.prop.img || this.toImg();
12308      }]; // Fulfill prereqs then perform the appropriate output.
12309
12310      return this.thenList(prereqs).then(function outputImg_main() {
12311        switch (type) {
12312          case undefined:
12313          case 'img':
12314            return this.prop.img;
12315
12316          case 'datauristring':
12317          case 'dataurlstring':
12318            return this.prop.img.src;
12319
12320          case 'datauri':
12321          case 'dataurl':
12322            return document.location.href = this.prop.img.src;
12323
12324          default:
12325            throw 'Image output type "' + type + '" is not supported.';
12326        }
12327      });
12328    };
12329
12330    Worker.prototype.isHtml2CanvasLoaded = function () {
12331      var result = typeof global.html2canvas !== "undefined";
12332
12333      if (!result) {
12334        console.error("html2canvas not loaded.");
12335      }
12336
12337      return result;
12338    };
12339
12340    Worker.prototype.save = function save(filename) {
12341      // Set up function prerequisites.
12342      var prereqs = [function checkPdf() {
12343        return this.prop.pdf || this.toPdf();
12344      }];
12345
12346      if (!this.isHtml2CanvasLoaded()) {
12347        return;
12348      } // Fulfill prereqs, update the filename (if provided), and save the PDF.
12349
12350
12351      return this.thenList(prereqs).set(filename ? {
12352        filename: filename
12353      } : null).then(function save_main() {
12354        this.prop.pdf.save(this.opt.filename);
12355      });
12356    };
12357
12358    Worker.prototype.doCallback = function doCallback(filename) {
12359      // Set up function prerequisites.
12360      var prereqs = [function checkPdf() {
12361        return this.prop.pdf || this.toPdf();
12362      }];
12363
12364      if (!this.isHtml2CanvasLoaded()) {
12365        return;
12366      } // Fulfill prereqs, update the filename (if provided), and save the PDF.
12367
12368
12369      return this.thenList(prereqs).then(function doCallback_main() {
12370        this.prop.callback(this.prop.pdf);
12371      });
12372    };
12373    /* ----- SET / GET ----- */
12374
12375
12376    Worker.prototype.set = function set(opt) {
12377      // TODO: Implement ordered pairs?
12378      // Silently ignore invalid or empty input.
12379      if (objType(opt) !== 'object') {
12380        return this;
12381      } // Build an array of setter functions to queue.
12382
12383
12384      var fns = Object.keys(opt || {}).map(function (key) {
12385        if (key in Worker.template.prop) {
12386          // Set pre-defined properties.
12387          return function set_prop() {
12388            this.prop[key] = opt[key];
12389          };
12390        } else {
12391          switch (key) {
12392            case 'margin':
12393              return this.setMargin.bind(this, opt.margin);
12394
12395            case 'jsPDF':
12396              return function set_jsPDF() {
12397                this.opt.jsPDF = opt.jsPDF;
12398                return this.setPageSize();
12399              };
12400
12401            case 'pageSize':
12402              return this.setPageSize.bind(this, opt.pageSize);
12403
12404            default:
12405              // Set any other properties in opt.
12406              return function set_opt() {
12407                this.opt[key] = opt[key];
12408              };
12409          }
12410        }
12411      }, this); // Set properties within the promise chain.
12412
12413      return this.then(function set_main() {
12414        return this.thenList(fns);
12415      });
12416    };
12417
12418    Worker.prototype.get = function get(key, cbk) {
12419      return this.then(function get_main() {
12420        // Fetch the requested property, either as a predefined prop or in opt.
12421        var val = key in Worker.template.prop ? this.prop[key] : this.opt[key];
12422        return cbk ? cbk(val) : val;
12423      });
12424    };
12425
12426    Worker.prototype.setMargin = function setMargin(margin) {
12427      return this.then(function setMargin_main() {
12428        // Parse the margin property.
12429        switch (objType(margin)) {
12430          case 'number':
12431            margin = [margin, margin, margin, margin];
12432
12433          case 'array':
12434            if (margin.length === 2) {
12435              margin = [margin[0], margin[1], margin[0], margin[1]];
12436            }
12437
12438            if (margin.length === 4) {
12439              break;
12440            }
12441
12442          default:
12443            return this.error('Invalid margin array.');
12444        } // Set the margin property, then update pageSize.
12445
12446
12447        this.opt.margin = margin;
12448      }).then(this.setPageSize);
12449    };
12450
12451    Worker.prototype.setPageSize = function setPageSize(pageSize) {
12452      function toPx(val, k) {
12453        return Math.floor(val * k / 72 * 96);
12454      }
12455
12456      return this.then(function setPageSize_main() {
12457        // Retrieve page-size based on jsPDF settings, if not explicitly provided.
12458        pageSize = pageSize || jsPDF.getPageSize(this.opt.jsPDF); // Add 'inner' field if not present.
12459
12460        if (!pageSize.hasOwnProperty('inner')) {
12461          pageSize.inner = {
12462            width: pageSize.width - this.opt.margin[1] - this.opt.margin[3],
12463            height: pageSize.height - this.opt.margin[0] - this.opt.margin[2]
12464          };
12465          pageSize.inner.px = {
12466            width: toPx(pageSize.inner.width, pageSize.k),
12467            height: toPx(pageSize.inner.height, pageSize.k)
12468          };
12469          pageSize.inner.ratio = pageSize.inner.height / pageSize.inner.width;
12470        } // Attach pageSize to this.
12471
12472
12473        this.prop.pageSize = pageSize;
12474      });
12475    };
12476
12477    Worker.prototype.setProgress = function setProgress(val, state, n, stack) {
12478      // Immediately update all progress values.
12479      if (val != null) this.progress.val = val;
12480      if (state != null) this.progress.state = state;
12481      if (n != null) this.progress.n = n;
12482      if (stack != null) this.progress.stack = stack;
12483      this.progress.ratio = this.progress.val / this.progress.state;
vendor: 7,634 bytes, lines 12483-12721
12483 // Return this for command chaining.
12484
12485      return this;
12486    };
12487
12488    Worker.prototype.updateProgress = function updateProgress(val, state, n, stack) {
12489      // Immediately update all progress values, using setProgress.
12490      return this.setProgress(val ? this.progress.val + val : null, state ? state : null, n ? this.progress.n + n : null, stack ? this.progress.stack.concat(stack) : null);
12491    };
12492    /* ----- PROMISE MAPPING ----- */
12493
12494
12495    Worker.prototype.then = function then(onFulfilled, onRejected) {
12496      // Wrap `this` for encapsulation.
12497      var self = this;
12498      return this.thenCore(onFulfilled, onRejected, function then_main(onFulfilled, onRejected) {
12499        // Update progress while queuing, calling, and resolving `then`.
12500        self.updateProgress(null, null, 1, [onFulfilled]);
12501        return Promise.prototype.then.call(this, function then_pre(val) {
12502          self.updateProgress(null, onFulfilled);
12503          return val;
12504        }).then(onFulfilled, onRejected).then(function then_post(val) {
12505          self.updateProgress(1);
12506          return val;
12507        });
12508      });
12509    };
12510
12511    Worker.prototype.thenCore = function thenCore(onFulfilled, onRejected, thenBase) {
12512      // Handle optional thenBase parameter.
12513      thenBase = thenBase || Promise.prototype.then; // Wrap `this` for encapsulation and bind it to the promise handlers.
12514
12515      var self = this;
12516
12517      if (onFulfilled) {
12518        onFulfilled = onFulfilled.bind(self);
12519      }
12520
12521      if (onRejected) {
12522        onRejected = onRejected.bind(self);
12523      } // Cast self into a Promise to avoid polyfills recursively defining `then`.
12524
12525
12526      var isNative = Promise.toString().indexOf('[native code]') !== -1 && Promise.name === 'Promise';
12527      var selfPromise = isNative ? self : Worker.convert(Object.assign({}, self), Promise.prototype); // Return the promise, after casting it into a Worker and preserving props.
12528
12529      var returnVal = thenBase.call(selfPromise, onFulfilled, onRejected);
12530      return Worker.convert(returnVal, self.__proto__);
12531    };
12532
12533    Worker.prototype.thenExternal = function thenExternal(onFulfilled, onRejected) {
12534      // Call `then` and return a standard promise (exits the Worker chain).
12535      return Promise.prototype.then.call(this, onFulfilled, onRejected);
12536    };
12537
12538    Worker.prototype.thenList = function thenList(fns) {
12539      // Queue a series of promise 'factories' into the promise chain.
12540      var self = this;
12541      fns.forEach(function thenList_forEach(fn) {
12542        self = self.thenCore(fn);
12543      });
12544      return self;
12545    };
12546
12547    Worker.prototype['catch'] = function (onRejected) {
12548      // Bind `this` to the promise handler, call `catch`, and return a Worker.
12549      if (onRejected) {
12550        onRejected = onRejected.bind(this);
12551      }
12552
12553      var returnVal = Promise.prototype['catch'].call(this, onRejected);
12554      return Worker.convert(returnVal, this);
12555    };
12556
12557    Worker.prototype.catchExternal = function catchExternal(onRejected) {
12558      // Call `catch` and return a standard promise (exits the Worker chain).
12559      return Promise.prototype['catch'].call(this, onRejected);
12560    };
12561
12562    Worker.prototype.error = function error(msg) {
12563      // Throw the error in the Promise chain.
12564      return this.then(function error_main() {
12565        throw new Error(msg);
12566      });
12567    };
12568    /* ----- ALIASES ----- */
12569
12570
12571    Worker.prototype.using = Worker.prototype.set;
12572    Worker.prototype.saveAs = Worker.prototype.save;
12573    Worker.prototype.export = Worker.prototype.output;
12574    Worker.prototype.run = Worker.prototype.then; // Get dimensions of a PDF page, as determined by jsPDF.
12575
12576    jsPDF.getPageSize = function (orientation, unit, format) {
12577      // Decode options object
12578      if (_typeof(orientation) === 'object') {
12579        var options = orientation;
12580        orientation = options.orientation;
12581        unit = options.unit || unit;
12582        format = options.format || format;
12583      } // Default options
12584
12585
12586      unit = unit || 'mm';
12587      format = format || 'a4';
12588      orientation = ('' + (orientation || 'P')).toLowerCase();
12589      var format_as_string = ('' + format).toLowerCase(); // Size in pt of various paper formats
12590
12591      var pageFormats = {
12592        'a0': [2383.94, 3370.39],
12593        'a1': [1683.78, 2383.94],
12594        'a2': [1190.55, 1683.78],
12595        'a3': [841.89, 1190.55],
12596        'a4': [595.28, 841.89],
12597        'a5': [419.53, 595.28],
12598        'a6': [297.64, 419.53],
12599        'a7': [209.76, 297.64],
12600        'a8': [147.40, 209.76],
12601        'a9': [104.88, 147.40],
12602        'a10': [73.70, 104.88],
12603        'b0': [2834.65, 4008.19],
12604        'b1': [2004.09, 2834.65],
12605        'b2': [1417.32, 2004.09],
12606        'b3': [1000.63, 1417.32],
12607        'b4': [708.66, 1000.63],
12608        'b5': [498.90, 708.66],
12609        'b6': [354.33, 498.90],
12610        'b7': [249.45, 354.33],
12611        'b8': [175.75, 249.45],
12612        'b9': [124.72, 175.75],
12613        'b10': [87.87, 124.72],
12614        'c0': [2599.37, 3676.54],
12615        'c1': [1836.85, 2599.37],
12616        'c2': [1298.27, 1836.85],
12617        'c3': [918.43, 1298.27],
12618        'c4': [649.13, 918.43],
12619        'c5': [459.21, 649.13],
12620        'c6': [323.15, 459.21],
12621        'c7': [229.61, 323.15],
12622        'c8': [161.57, 229.61],
12623        'c9': [113.39, 161.57],
12624        'c10': [79.37, 113.39],
12625        'dl': [311.81, 623.62],
12626        'letter': [612, 792],
12627        'government-letter': [576, 756],
12628        'legal': [612, 1008],
12629        'junior-legal': [576, 360],
12630        'ledger': [1224, 792],
12631        'tabloid': [792, 1224],
12632        'credit-card': [153, 243]
12633      }; // Unit conversion
12634
12635      switch (unit) {
12636        case 'pt':
12637          var k = 1;
12638          break;
12639
12640        case 'mm':
12641          var k = 72 / 25.4;
12642          break;
12643
12644        case 'cm':
12645          var k = 72 / 2.54;
12646          break;
12647
12648        case 'in':
12649          var k = 72;
12650          break;
12651
12652        case 'px':
12653          var k = 72 / 96;
12654          break;
12655
12656        case 'pc':
12657          var k = 12;
12658          break;
12659
12660        case 'em':
12661          var k = 12;
12662          break;
12663
12664        case 'ex':
12665          var k = 6;
12666          break;
12667
12668        default:
12669          throw 'Invalid unit: ' + unit;
12670      } // Dimensions are stored as user units and converted to points on output
12671
12672
12673      if (pageFormats.hasOwnProperty(format_as_string)) {
12674        var pageHeight = pageFormats[format_as_string][1] / k;
12675        var pageWidth = pageFormats[format_as_string][0] / k;
12676      } else {
12677        try {
12678          var pageHeight = format[1];
12679          var pageWidth = format[0];
12680        } catch (err) {
12681          throw new Error('Invalid format: ' + format);
12682        }
12683      } // Handle page orientation
12684
12685
12686      if (orientation === 'p' || orientation === 'portrait') {
12687        orientation = 'p';
12688
12689        if (pageWidth > pageHeight) {
12690          var tmp = pageWidth;
12691          pageWidth = pageHeight;
12692          pageHeight = tmp;
12693        }
12694      } else if (orientation === 'l' || orientation === 'landscape') {
12695        orientation = 'l';
12696
12697        if (pageHeight > pageWidth) {
12698          var tmp = pageWidth;
12699          pageWidth = pageHeight;
12700          pageHeight = tmp;
12701        }
12702      } else {
12703        throw 'Invalid orientation: ' + orientation;
12704      } // Return information (k is the unit conversion ratio from pts)
12705
12706
12707      var info = {
12708        'width': pageWidth,
12709        'height': pageHeight,
12710        'unit': unit,
12711        'k': k
12712      };
12713      return info;
12714    };
12715    /**
12716     * Generate a PDF from an HTML element or string using.
12717     *
12718     * @name html
12719     * @function
12720     * @param {Element|string} source The source element or HTML string.
12721     * @param {Object=} options An object of optional settings.
12722     * @description The Plugin needs html2canvas from niklasvh
12723     */
12724
12725
12726    jsPDFAPI.html = function (src, options) {
12727
12728      options = options || {};
12729
12730      options.callback = options.callback || function () {};
12731
12732      options.html2canvas = options.html2canvas || {};
12733      options.html2canvas.canvas = options.html2canvas.canvas || this.canvas;
12734      options.jsPDF = options.jsPDF || this; // Create a new worker with the given options.
12735
12736      var pdf = options.jsPDF;
12737      var worker = new Worker(options);
12738
12739      if (!options.worker) {
12740        // If worker is not set to true, perform the traditional 'simple' operation.
12741        return worker.from(src).doCallback();
12742      } else {
12743        // Otherwise, return the worker for new Promise-based operation.
12744        return worker;
12745      }
12746
12747      return this;
12748    };
12749  })(jsPDF.API, typeof window !== "undefined" && window || typeof global !== "undefined" && global);
12750
12751  /**
12752   * @license
12753   * ==================================================================== 
12754   * Copyright (c) 2013 Youssef Beddad, [email protected]
12755   * 
12756   * 
12757   * ====================================================================
12758   */
12759
12760  /*global jsPDF */
12761
12762  /**
12763   * jsPDF JavaScript plugin
12764   *
12765   * @name javascript
12766   * @module
12767  */
12768  (function (jsPDFAPI) {
12769
12770    var jsNamesObj, jsJsObj, text;
12771    /**
12772    * @name addJS
12773    * @function
12774    * @param {string} javascript The javascript to be embedded into the PDF-file.
12775    * @returns {jsPDF}
12776    */
12777
12778    jsPDFAPI.addJS = function (javascript) {
12779      text = javascript;
12780      this.internal.events.subscribe('postPutResources', function (javascript) {
12781        jsNamesObj = this.internal.newObject();
12782        this.internal.out('<<');
12783        this.internal.out('/Names [(EmbeddedJS) ' + (jsNamesObj + 1) + ' 0 R]');
12784        this.internal.out('>>');
12785        this.internal.out('endobj');
12786        jsJsObj = this.internal.newObject();
12787        this.internal.out('<<');
12788        this.internal.out('/S /JavaScript');
12789        this.internal.out('/JS (' + text + ')');
12790        this.internal.out('>>');
12791        this.internal.out('endobj');
12792      });
12793      this.internal.events.subscribe('putCatalog', function () {
12794        if (jsNamesObj !== undefined && jsJsObj !== undefined) {
12795          this.internal.out('/Names <</JavaScript ' + jsNamesObj + ' 0 R>>');
12796        }
12797      });
12798      return this;
12799    };
12800  })(jsPDF.API);
12801
12802  /**
12803   * @license
12804   * Copyright (c) 2014 Steven Spungin (TwelveTone LLC)  [email protected]
12805   *
12806   * Licensed under the MIT License.
12807   * http://opensource.org/licenses/mit-license
12808   */
12809
12810  (function (jsPDFAPI) {
12811
12812    jsPDFAPI.events.push(['postPutResources', function () {
12813      var pdf = this;
12814      var rx = /^(\d+) 0 obj$/; // Write action goto objects for each page
12815      // this.outline.destsGoto = [];
12816      // for (var i = 0; i < totalPages; i++) {
12817      // var id = pdf.internal.newObject();
12818      // this.outline.destsGoto.push(id);
12819      // pdf.internal.write("<</D[" + (i * 2 + 3) + " 0 R /XYZ null
12820      // null null]/S/GoTo>> endobj");
12821      // }
12822      //
12823      // for (var i = 0; i < dests.length; i++) {
12824      // pdf.internal.write("(page_" + (i + 1) + ")" + dests[i] + " 0
12825      // R");
12826      // }
12827      //				
12828
12829      if (this.outline.root.children.length > 0) {
12830        var lines = pdf.outline.render().split(/\r\n/);
12831
12832        for (var i = 0; i < lines.length; i++) {
12833          var line = lines[i];
12834          var m = rx.exec(line);
12835
12836          if (m != null) {
12837            var oid = m[1];
12838            pdf.internal.newObjectDeferredBegin(oid, false);
12839          }
12840
12841          pdf.internal.write(line);
12842        }
12843      } // This code will write named destination for each page reference
12844      // (page_1, etc)
12845
12846
12847      if (this.outline.createNamedDestinations) {
12848        var totalPages = this.internal.pages.length; // WARNING: this assumes jsPDF starts on page 3 and pageIDs
12849        // follow 5, 7, 9, etc
12850        // Write destination objects for each page
12851
12852        var dests = [];
12853
12854        for (var i = 0; i < totalPages; i++) {
12855          var id = pdf.internal.newObject();
12856          dests.push(id);
12857          var info = pdf.internal.getPageInfo(i + 1);
12858          pdf.internal.write("<< /D[" + info.objId + " 0 R /XYZ null null null]>> endobj");
12859        } // assign a name for each destination
12860
12861
12862        var names2Oid = pdf.internal.newObject();
vendor: 7,147 bytes, lines 12863-13087
12863        pdf.internal.write('<< /Names [ ');
12864
12865        for (var i = 0; i < dests.length; i++) {
12866          pdf.internal.write("(page_" + (i + 1) + ")" + dests[i] + " 0 R");
12867        }
12868
12869        pdf.internal.write(' ] >>', 'endobj'); // var kids = pdf.internal.newObject();
12870        // pdf.internal.write('<< /Kids [ ' + names2Oid + ' 0 R');
12871        // pdf.internal.write(' ] >>', 'endobj');
12872
12873        var namesOid = pdf.internal.newObject();
12874        pdf.internal.write('<< /Dests ' + names2Oid + " 0 R");
12875        pdf.internal.write('>>', 'endobj');
12876      }
12877    }]);
12878    jsPDFAPI.events.push(['putCatalog', function () {
12879      var pdf = this;
12880
12881      if (pdf.outline.root.children.length > 0) {
12882        pdf.internal.write("/Outlines", this.outline.makeRef(this.outline.root));
12883
12884        if (this.outline.createNamedDestinations) {
12885          pdf.internal.write("/Names " + namesOid + " 0 R");
12886        } // Open with Bookmarks showing
12887        // pdf.internal.write("/PageMode /UseOutlines");
12888
12889      }
12890    }]);
12891    jsPDFAPI.events.push(['initialized', function () {
12892      var pdf = this;
12893      pdf.outline = {
12894        createNamedDestinations: false,
12895        root: {
12896          children: []
12897        }
12898      };
12899      /**
12900       * Options: pageNumber
12901       */
12902
12903      pdf.outline.add = function (parent, title, options) {
12904        var item = {
12905          title: title,
12906          options: options,
12907          children: []
12908        };
12909
12910        if (parent == null) {
12911          parent = this.root;
12912        }
12913
12914        parent.children.push(item);
12915        return item;
12916      };
12917
12918      pdf.outline.render = function () {
12919        this.ctx = {};
12920        this.ctx.val = '';
12921        this.ctx.pdf = pdf;
12922        this.genIds_r(this.root);
12923        this.renderRoot(this.root);
12924        this.renderItems(this.root);
12925        return this.ctx.val;
12926      };
12927
12928      pdf.outline.genIds_r = function (node) {
12929        node.id = pdf.internal.newObjectDeferred();
12930
12931        for (var i = 0; i < node.children.length; i++) {
12932          this.genIds_r(node.children[i]);
12933        }
12934      };
12935
12936      pdf.outline.renderRoot = function (node) {
12937        this.objStart(node);
12938        this.line('/Type /Outlines');
12939
12940        if (node.children.length > 0) {
12941          this.line('/First ' + this.makeRef(node.children[0]));
12942          this.line('/Last ' + this.makeRef(node.children[node.children.length - 1]));
12943        }
12944
12945        this.line('/Count ' + this.count_r({
12946          count: 0
12947        }, node));
12948        this.objEnd();
12949      };
12950
12951      pdf.outline.renderItems = function (node) {
12952        var getHorizontalCoordinateString = this.ctx.pdf.internal.getCoordinateString;
12953        var getVerticalCoordinateString = this.ctx.pdf.internal.getVerticalCoordinateString;
12954
12955        for (var i = 0; i < node.children.length; i++) {
12956          var item = node.children[i];
12957          this.objStart(item);
12958          this.line('/Title ' + this.makeString(item.title));
12959          this.line('/Parent ' + this.makeRef(node));
12960
12961          if (i > 0) {
12962            this.line('/Prev ' + this.makeRef(node.children[i - 1]));
12963          }
12964
12965          if (i < node.children.length - 1) {
12966            this.line('/Next ' + this.makeRef(node.children[i + 1]));
12967          }
12968
12969          if (item.children.length > 0) {
12970            this.line('/First ' + this.makeRef(item.children[0]));
12971            this.line('/Last ' + this.makeRef(item.children[item.children.length - 1]));
12972          }
12973
12974          var count = this.count = this.count_r({
12975            count: 0
12976          }, item);
12977
12978          if (count > 0) {
12979            this.line('/Count ' + count);
12980          }
12981
12982          if (item.options) {
12983            if (item.options.pageNumber) {
12984              // Explicit Destination
12985              //WARNING this assumes page ids are 3,5,7, etc.
12986              var info = pdf.internal.getPageInfo(item.options.pageNumber);
12987              this.line('/Dest ' + '[' + info.objId + ' 0 R /XYZ 0 ' + getVerticalCoordinateString(0) + ' 0]'); // this line does not work on all clients (pageNumber instead of page ref)
12988              //this.line('/Dest ' + '[' + (item.options.pageNumber - 1) + ' /XYZ 0 ' + this.ctx.pdf.internal.pageSize.getHeight() + ' 0]');
12989              // Named Destination
12990              // this.line('/Dest (page_' + (item.options.pageNumber) + ')');
12991              // Action Destination
12992              // var id = pdf.internal.newObject();
12993              // pdf.internal.write('<</D[' + (item.options.pageNumber - 1) + ' /XYZ null null null]/S/GoTo>> endobj');
12994              // this.line('/A ' + id + ' 0 R' );
12995            }
12996          }
12997
12998          this.objEnd();
12999        }
13000
13001        for (var i = 0; i < node.children.length; i++) {
13002          var item = node.children[i];
13003          this.renderItems(item);
13004        }
13005      };
13006
13007      pdf.outline.line = function (text) {
13008        this.ctx.val += text + '\r\n';
13009      };
13010
13011      pdf.outline.makeRef = function (node) {
13012        return node.id + ' 0 R';
13013      };
13014
13015      pdf.outline.makeString = function (val) {
13016        return '(' + pdf.internal.pdfEscape(val) + ')';
13017      };
13018
13019      pdf.outline.objStart = function (node) {
13020        this.ctx.val += '\r\n' + node.id + ' 0 obj' + '\r\n<<\r\n';
13021      };
13022
13023      pdf.outline.objEnd = function (node) {
13024        this.ctx.val += '>> \r\n' + 'endobj' + '\r\n';
13025      };
13026
13027      pdf.outline.count_r = function (ctx, node) {
13028        for (var i = 0; i < node.children.length; i++) {
13029          ctx.count++;
13030          this.count_r(ctx, node.children[i]);
13031        }
13032
13033        return ctx.count;
13034      };
13035    }]);
13036    return this;
13037  })(jsPDF.API);
13038
13039  /**
13040   * @license
13041   * 
13042   * Copyright (c) 2014 James Robb, https://github.com/jamesbrobb
13043   *
13044   * 
13045   * ====================================================================
13046   */
13047
13048  /**
13049  * jsPDF PNG PlugIn
13050  * @name png_support
13051  * @module
13052  */
13053  (function (jsPDFAPI) {
13054    /*
13055     * @see http://www.w3.org/TR/PNG-Chunks.html
13056     *
13057     Color    Allowed      Interpretation
13058     Type     Bit Depths
13059    	   0       1,2,4,8,16  Each pixel is a grayscale sample.
13060    	   2       8,16        Each pixel is an R,G,B triple.
13061    	   3       1,2,4,8     Each pixel is a palette index;
13062                           a PLTE chunk must appear.
13063    	   4       8,16        Each pixel is a grayscale sample,
13064                           followed by an alpha sample.
13065    	   6       8,16        Each pixel is an R,G,B triple,
13066                           followed by an alpha sample.
13067    */
13068
13069    /*
13070     * PNG filter method types
13071     *
13072     * @see http://www.w3.org/TR/PNG-Filters.html
13073     * @see http://www.libpng.org/pub/png/book/chapter09.html
13074     *
13075     * This is what the value 'Predictor' in decode params relates to
13076     *
13077     * 15 is "optimal prediction", which means the prediction algorithm can change from line to line.
13078     * 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.
13079     *
13080       0       None
13081       1       Sub
13082       2       Up
13083       3       Average
13084       4       Paeth
13085     */
13086
13087    var doesNotHavePngJS = function doesNotHavePngJS() {
13088      return typeof PNG !== 'function' || typeof FlateStream !== 'function';
13089    },
13090        canCompress = function canCompress(value) {
13091      return value !== jsPDFAPI.image_compression.NONE && hasCompressionJS();
13092    },
13093        hasCompressionJS = function hasCompressionJS() {
13094      var inst = typeof Deflater === 'function';
13095      if (!inst) throw new Error("requires deflate.js for compression");
13096      return inst;
13097    },
13098        compressBytes = function compressBytes(bytes, lineLength, colorsPerPixel, compression) {
13099      var level = 5,
13100          filter_method = filterUp;
13101
13102      switch (compression) {
13103        case jsPDFAPI.image_compression.FAST:
13104          level = 3;
13105          filter_method = filterSub;
13106          break;
13107
13108        case jsPDFAPI.image_compression.MEDIUM:
13109          level = 6;
13110          filter_method = filterAverage;
13111          break;
13112
13113        case jsPDFAPI.image_compression.SLOW:
13114          level = 9;
13115          filter_method = filterPaeth; //uses to sum to choose best filter for each line
13116
13117          break;
13118      }
13119
13120      bytes = applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method);
13121      var header = new Uint8Array(createZlibHeader(level));
13122      var checksum = adler32(bytes);
13123      var deflate = new Deflater(level);
13124      var a = deflate.append(bytes);
13125      var cBytes = deflate.flush();
13126      var len = header.length + a.length + cBytes.length;
13127      var cmpd = new Uint8Array(len + 4);
13128      cmpd.set(header);
13129      cmpd.set(a, header.length);
13130      cmpd.set(cBytes, header.length + a.length);
13131      cmpd[len++] = checksum >>> 24 & 0xff;
13132      cmpd[len++] = checksum >>> 16 & 0xff;
13133      cmpd[len++] = checksum >>> 8 & 0xff;
13134      cmpd[len++] = checksum & 0xff;
13135      return jsPDFAPI.arrayBufferToBinaryString(cmpd);
13136    },
13137        createZlibHeader = function createZlibHeader(bytes, level) {
13138      /*
13139       * @see http://www.ietf.org/rfc/rfc1950.txt for zlib header
13140       */
13141      var cm = 8;
13142      var cinfo = Math.LOG2E * Math.log(0x8000) - 8;
13143      var cmf = cinfo << 4 | cm;
13144      var hdr = cmf << 8;
13145      var flevel = Math.min(3, (level - 1 & 0xff) >> 1);
13146      hdr |= flevel << 6;
13147      hdr |= 0; //FDICT
13148
13149      hdr += 31 - hdr % 31;
13150      return [cmf, hdr & 0xff & 0xff];
13151    },
13152        adler32 = function adler32(array, param) {
13153      var adler = 1;
13154      var s1 = adler & 0xffff,
13155          s2 = adler >>> 16 & 0xffff;
13156      var len = array.length;
13157      var tlen;
13158      var i = 0;
13159
13160      while (len > 0) {
13161        tlen = len > param ? param : len;
13162        len -= tlen;
13163
13164        do {
13165          s1 += array[i++];
13166          s2 += s1;
13167        } while (--tlen);
13168
13169        s1 %= 65521;
13170        s2 %= 65521;
13171      }
13172
13173      return (s2 << 16 | s1) >>> 0;
13174    },
13175        applyPngFilterMethod = function applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method) {
13176      var lines = bytes.length / lineLength,
13177          result = new Uint8Array(bytes.length + lines),
13178          filter_methods = getFilterMethods(),
13179          i = 0,
13180          line,
13181          prevLine,
13182          offset;
13183
13184      for (; i < lines; i++) {
13185        offset = i * lineLength;
13186        line = bytes.subarray(offset, offset + lineLength);
13187
13188        if (filter_method) {
13189          result.set(filter_method(line, colorsPerPixel, prevLine), offset + i);
13190        } else {
13191          var j = 0,
13192              len = filter_methods.length,
13193              results = [];
13194
13195          for (; j < len; j++) {
13196            results[j] = filter_methods[j](line, colorsPerPixel, prevLine);
13197          }
13198
13199          var ind = getIndexOfSmallestSum(results.concat());
13200          result.set(results[ind], offset + i);
13201        }
13202
13203        prevLine = line;
13204      }
13205
13206      return result;
13207    },
13208        filterNone = function filterNone(line, colorsPerPixel, prevLine) {
13209      /*var result = new Uint8Array(line.length + 1);
13210      result[0] = 0;
13211      result.set(line, 1);*/
13212      var result = Array.apply([], line);
13213      result.unshift(0);
13214      return result;
13215    },
13216        filterSub = function filterSub(line, colorsPerPixel, prevLine) {
13217      var result = [],
13218          i = 0,
13219          len = line.length,
13220          left;
13221      result[0] = 1;
13222
13223      for (; i < len; i++) {
13224        left = line[i - colorsPerPixel] || 0;
13225        result[i + 1] = line[i] - left + 0x0100 & 0xff;
13226      }
13227
13228      return result;
13229    },
13230        filterUp = function filterUp(line, colorsPerPixel, prevLine) {
13231      var result = [],
13232          i = 0,
13233          len = line.length,
13234          up;
13235      result[0] = 2;
13236
13237      for (; i < len; i++) {
13238        up = prevLine && prevLine[i] || 0;
13239        result[i + 1] = line[i] - up + 0x0100 & 0xff;
13240      }
13241
13242      return result;
13243    },
13244        filterAverage = function filterAverage(line, colorsPerPixel, prevLine) {
13245      var result = [],
13246          i = 0,
13247          len = line.length,
13248          left,
13249          up;
13250      result[0] = 3;
13251
13252      for (; i < len; i++) {
13253        left = line[i - colorsPerPixel] || 0;
13254        up = prevLine && prevLine[i] || 0;
13255        result[i + 1] = line[i] + 0x0100 - (left + up >>> 1) & 0xff;
13256      }
13257
13258      return result;
13259    },
13260        filterPaeth = function filterPaeth(line, colorsPerPixel, prevLine) {
13261      var result = [],
13262          i = 0,
13263          len = line.length,
13264          left,
13265          up,
13266          upLeft,
13267          paeth;
13268      result[0] = 4;
13269
13270      for (; i < len; i++) {
13271        left = line[i - colorsPerPixel] || 0;
13272        up = prevLine && prevLine[i] || 0;
13273        upLeft = prevLine && prevLine[i - colorsPerPixel] || 0;
13274        paeth = paethPredictor(left, up, upLeft);
13275        result[i + 1] = line[i] - paeth + 0x0100 & 0xff;
13276      }
13277
13278      return result;
13279    },
13280        paethPredictor = function paethPredictor(left, up, upLeft) {
13281      var p = left + up - upLeft,
13282          pLeft = Math.abs(p - left),
13283          pUp = Math.abs(p - up),
13284          pUpLeft = Math.abs(p - upLeft);
13285      return pLeft <= pUp && pLeft <= pUpLeft ? left : pUp <= pUpLeft ? up : upLeft;
13286    },
13287        getFilterMethods = function getFilterMethods() {
13288      return [filterNone, filterSub, filterUp, filterAverage, filterPaeth];
13289    },
13290        getIndexOfSmallestSum = function getIndexOfSmallestSum(arrays) {
13291      var i = 0,
13292          len = arrays.length,
13293          sum,
13294          min,
13295          ind;
13296
13297      while (i < len) {
13298        sum = absSum(arrays[i].slice(1));
13299
13300        if (sum < min || !min) {
13301          min = sum;
13302          ind = i;
13303        }
13304
13305        i++;
13306      }
13307
13308      return ind;
13309    },
13310        absSum = function absSum(array) {
13311      var i = 0,
13312          len = array.length,
13313          sum = 0;
13314
13315      while (i < len) {
13316        sum += Math.abs(array[i++]);
13317      }
13318
13319      return sum;
13320    },
13321        getPredictorFromCompression = function getPredictorFromCompression(compression) {
13322      var predictor;
13323
13324      switch (compression) {
13325        case jsPDFAPI.image_compression.FAST:
13326          predictor = 11;
13327          break;
13328
13329        case jsPDFAPI.image_compression.MEDIUM:
13330          predictor = 13;
13331          break;
13332
13333        case jsPDFAPI.image_compression.SLOW:
13334          predictor = 14;
13335          break;
13336
13337        default:
13338          predictor = 12;
13339          break;
13340      }
13341
13342      return predictor;
13343    };
13344    /**
13345    *
13346    * @name processPNG
13347    * @function
13348    * @ignore
13349    */
13350
13351
13352    jsPDFAPI.processPNG = function (imageData, imageIndex, alias, compression, dataAsBinaryString) {
13353
13354      var colorSpace = this.color_spaces.DEVICE_RGB,
13355          decode = this.decode.FLATE_DECODE,
13356          bpc = 8,
13357          img,
13358          dp,
13359          trns,
13360          colors,
13361          pal,
13362          smask;
13363      /*	if(this.isString(imageData)) {
13364      		}*/
13365
13366      if (this.isArrayBuffer(imageData)) imageData = new Uint8Array(imageData);
13367
13368      if (this.isArrayBufferView(imageData)) {
13369        if (doesNotHavePngJS()) throw new Error("PNG support requires png.js and zlib.js");
13370        img = new PNG(imageData);
13371        imageData = img.imgData;
13372        bpc = img.bits;
13373        colorSpace = img.colorSpace;
13374        colors = img.colors; //logImg(img);
13375
13376        /*
13377         * colorType 6 - Each pixel is an R,G,B triple, followed by an alpha sample.
13378         *
13379         * colorType 4 - Each pixel is a grayscale sample, followed by an alpha sample.
13380         *
13381         * Extract alpha to create two separate images, using the alpha as a sMask
13382         */
13383
13384        if ([4, 6].indexOf(img.colorType) !== -1) {
13385          /*
13386           * processes 8 bit RGBA and grayscale + alpha images
13387           */
13388          if (img.bits === 8) {
13389            var pixels = img.pixelBitlength == 32 ? new Uint32Array(img.decodePixels().buffer) : img.pixelBitlength == 16 ? new Uint16Array(img.decodePixels().buffer) : new Uint8Array(img.decodePixels().buffer),
13390                len = pixels.length,
13391                imgData = new Uint8Array(len * img.colors),
13392                alphaData = new Uint8Array(len),
13393                pDiff = img.pixelBitlength - img.bits,
13394                i = 0,
13395                n = 0,
13396                pixel,
13397                pbl;
13398
13399            for (; i < len; i++) {
13400              pixel = pixels[i];
13401              pbl = 0;
13402
13403              while (pbl < pDiff) {
13404                imgData[n++] = pixel >>> pbl & 0xff;
13405                pbl = pbl + img.bits;
13406              }
13407
13408              alphaData[i] = pixel >>> pbl & 0xff;
13409            }
13410          }
13411          /*
13412           * processes 16 bit RGBA and grayscale + alpha images
13413           */
13414
13415
13416          if (img.bits === 16) {
13417            var pixels = new Uint32Array(img.decodePixels().buffer),
13418                len = pixels.length,
13419                imgData = new Uint8Array(len * (32 / img.pixelBitlength) * img.colors),
13420                alphaData = new Uint8Array(len * (32 / img.pixelBitlength)),
13421                hasColors = img.colors > 1,
13422                i = 0,
13423                n = 0,
13424                a = 0,
13425                pixel;
13426
13427            while (i < len) {
13428              pixel = pixels[i++];
13429              imgData[n++] = pixel >>> 0 & 0xFF;
13430
13431              if (hasColors) {
13432                imgData[n++] = pixel >>> 16 & 0xFF;
13433                pixel = pixels[i++];
13434                imgData[n++] = pixel >>> 0 & 0xFF;
13435              }
13436
13437              alphaData[a++] = pixel >>> 16 & 0xFF;
13438            }
13439
13440            bpc = 8;
13441          }
13442
13443          if (canCompress(compression)) {
13444            imageData = compressBytes(imgData, img.width * img.colors, img.colors, compression);
13445            smask = compressBytes(alphaData, img.width, 1, compression);
13446          } else {
13447            imageData = imgData;
13448            smask = alphaData;
13449            decode = null;
13450          }
13451        }
13452        /*
13453         * Indexed png. Each pixel is a palette index.
13454         */
13455
13456
13457        if (img.colorType === 3) {
13458          colorSpace = this.color_spaces.INDEXED;
13459          pal = img.palette;
13460
13461          if (img.transparency.indexed) {
13462            var trans = img.transparency.indexed;
13463            var total = 0,
13464                i = 0,
13465                len = trans.length;
13466
13467            for (; i < len; ++i) {
13468              total += trans[i];
13469            }
13470
13471            total = total / 255;
13472            /*
13473             * a single color is specified as 100% transparent (0),
13474             * so we set trns to use a /Mask with that index
13475             */
13476
13477            if (total === len - 1 && trans.indexOf(0) !== -1) {
13478              trns = [trans.indexOf(0)];
13479              /*
13480               * there's more than one colour within the palette that specifies
13481               * a transparency value less than 255, so we unroll the pixels to create an image sMask
13482               */
13483            } else if (total !== len) {
13484              var pixels = img.decodePixels(),
13485                  alphaData = new Uint8Array(pixels.length),
13486                  i = 0,
13487                  len = pixels.length;
13488
13489              for (; i < len; i++) {
13490                alphaData[i] = trans[pixels[i]];
13491              }
13492
13493              smask = compressBytes(alphaData, img.width, 1);
13494            }
13495          }
13496        }
13497
13498        var predictor = getPredictorFromCompression(compression);
13499        if (decode === this.decode.FLATE_DECODE) dp = '/Predictor ' + predictor + ' /Colors ' + colors + ' /BitsPerComponent ' + bpc + ' /Columns ' + img.width;else //remove 'Predictor' as it applies to the type of png filter applied to its IDAT - we only apply with compression
13500          dp = '/Colors ' + colors + ' /BitsPerComponent ' + bpc + ' /Columns ' + img.width;
13501        if (this.isArrayBuffer(imageData) || this.isArrayBufferView(imageData)) imageData = this.arrayBufferToBinaryString(imageData);
13502        if (smask && this.isArrayBuffer(smask) || this.isArrayBufferView(smask)) smask = this.arrayBufferToBinaryString(smask);
13503        return this.createImageInfo(imageData, img.width, img.height, colorSpace, bpc, decode, imageIndex, alias, dp, trns, pal, smask, predictor);
13504      }
13505
13506      throw new Error("Unsupported PNG image data, try using JPEG instead.");
13507    };
13508  })(jsPDF.API);
13509
13510  /**
13511   * @license
13512   * Copyright (c) 2017 Aras Abbasi 
13513   *
13514   * Licensed under the MIT License.
13515   * http://opensource.org/licenses/mit-license
13516   */
13517
13518  /**
13519  * jsPDF gif Support PlugIn
13520  *
13521  * @name gif_support
13522  * @module
13523  */
vendor: 4,364 bytes, lines 13524-13673
13524  (function (jsPDFAPI) {
13525
13526    jsPDFAPI.processGIF89A = function (imageData, imageIndex, alias, compression, dataAsBinaryString) {
13527      var reader = new GifReader(imageData);
13528      var width = reader.width,
13529          height = reader.height;
13530      var qu = 100;
13531      var pixels = [];
13532      reader.decodeAndBlitFrameRGBA(0, pixels);
13533      var rawImageData = {
13534        data: pixels,
13535        width: width,
13536        height: height
13537      };
13538      var encoder = new JPEGEncoder(qu);
13539      var data = encoder.encode(rawImageData, qu);
13540      return jsPDFAPI.processJPEG.call(this, data, imageIndex, alias, compression);
13541    };
13542
13543    jsPDFAPI.processGIF87A = jsPDFAPI.processGIF89A;
13544  })(jsPDF.API);
13545
13546  /**
13547   * Copyright (c) 2018 Aras Abbasi 
13548   *
13549   * Licensed under the MIT License.
13550   * http://opensource.org/licenses/mit-license
13551   */
13552
13553  /**
13554  * jsPDF bmp Support PlugIn
13555  * @name bmp_support
13556  * @module
13557  */
13558  (function (jsPDFAPI) {
13559
13560    jsPDFAPI.processBMP = function (imageData, imageIndex, alias, compression, dataAsBinaryString) {
13561      var reader = new BmpDecoder(imageData, false);
13562      var width = reader.width,
13563          height = reader.height;
13564      var qu = 100;
13565      var pixels = reader.getData();
13566      var rawImageData = {
13567        data: pixels,
13568        width: width,
13569        height: height
13570      };
13571      var encoder = new JPEGEncoder(qu);
13572      var data = encoder.encode(rawImageData, qu);
13573      return jsPDFAPI.processJPEG.call(this, data, imageIndex, alias, compression);
13574    };
13575  })(jsPDF.API);
13576
13577  /**
13578   * @license
13579   * Licensed under the MIT License.
13580   * http://opensource.org/licenses/mit-license
13581   */
13582
13583  /**
13584   * jsPDF setLanguage Plugin
13585   *
13586   * @name setLanguage
13587   * @module
13588   */
13589  (function (jsPDFAPI) {
13590    /**
13591    * Add Language Tag to the generated PDF
13592    *
13593    * @name setLanguage
13594    * @function 
13595    * @param {string} langCode The Language code as ISO-639-1 (e.g. 'en') or as country language code (e.g. 'en-GB'). 
13596    * @returns {jsPDF}
13597    * @example
13598    * var doc = new jsPDF()
13599    * doc.text(10, 10, 'This is a test')
13600    * doc.setLanguage("en-US")
13601    * doc.save('english.pdf')
13602    */
13603
13604    jsPDFAPI.setLanguage = function (langCode) {
13605
13606      var langCodes = {
13607        "af": "Afrikaans",
13608        "sq": "Albanian",
13609        "ar": "Arabic (Standard)",
13610        "ar-DZ": "Arabic (Algeria)",
13611        "ar-BH": "Arabic (Bahrain)",
13612        "ar-EG": "Arabic (Egypt)",
13613        "ar-IQ": "Arabic (Iraq)",
13614        "ar-JO": "Arabic (Jordan)",
13615        "ar-KW": "Arabic (Kuwait)",
13616        "ar-LB": "Arabic (Lebanon)",
13617        "ar-LY": "Arabic (Libya)",
13618        "ar-MA": "Arabic (Morocco)",
13619        "ar-OM": "Arabic (Oman)",
13620        "ar-QA": "Arabic (Qatar)",
13621        "ar-SA": "Arabic (Saudi Arabia)",
13622        "ar-SY": "Arabic (Syria)",
13623        "ar-TN": "Arabic (Tunisia)",
13624        "ar-AE": "Arabic (U.A.E.)",
13625        "ar-YE": "Arabic (Yemen)",
13626        "an": "Aragonese",
13627        "hy": "Armenian",
13628        "as": "Assamese",
13629        "ast": "Asturian",
13630        "az": "Azerbaijani",
13631        "eu": "Basque",
13632        "be": "Belarusian",
13633        "bn": "Bengali",
13634        "bs": "Bosnian",
13635        "br": "Breton",
13636        "bg": "Bulgarian",
13637        "my": "Burmese",
13638        "ca": "Catalan",
13639        "ch": "Chamorro",
13640        "ce": "Chechen",
13641        "zh": "Chinese",
13642        "zh-HK": "Chinese (Hong Kong)",
13643        "zh-CN": "Chinese (PRC)",
13644        "zh-SG": "Chinese (Singapore)",
13645        "zh-TW": "Chinese (Taiwan)",
13646        "cv": "Chuvash",
13647        "co": "Corsican",
13648        "cr": "Cree",
13649        "hr": "Croatian",
13650        "cs": "Czech",
13651        "da": "Danish",
13652        "nl": "Dutch (Standard)",
13653        "nl-BE": "Dutch (Belgian)",
13654        "en": "English",
13655        "en-AU": "English (Australia)",
13656        "en-BZ": "English (Belize)",
13657        "en-CA": "English (Canada)",
13658        "en-IE": "English (Ireland)",
13659        "en-JM": "English (Jamaica)",
13660        "en-NZ": "English (New Zealand)",
13661        "en-PH": "English (Philippines)",
13662        "en-ZA": "English (South Africa)",
13663        "en-TT": "English (Trinidad & Tobago)",
13664        "en-GB": "English (United Kingdom)",
13665        "en-US": "English (United States)",
13666        "en-ZW": "English (Zimbabwe)",
13667        "eo": "Esperanto",
13668        "et": "Estonian",
13669        "fo": "Faeroese",
13670        "fj": "Fijian",
13671        "fi": "Finnish",
13672        "fr": "French (Standard)",
13673        "fr-BE": "French (Belgium)",
13674        "fr-CA": "French (Canada)",
13675        "fr-FR": "French (France)",
13676        "fr-LU": "French (Luxembourg)",
13677        "fr-MC": "French (Monaco)",
13678        "fr-CH": "French (Switzerland)",
13679        "fy": "Frisian",
13680        "fur": "Friulian",
13681        "gd": "Gaelic (Scots)",
13682        "gd-IE": "Gaelic (Irish)",
13683        "gl": "Galacian",
13684        "ka": "Georgian",
13685        "de": "German (Standard)",
13686        "de-AT": "German (Austria)",
13687        "de-DE": "German (Germany)",
13688        "de-LI": "German (Liechtenstein)",
13689        "de-LU": "German (Luxembourg)",
13690        "de-CH": "German (Switzerland)",
13691        "el": "Greek",
13692        "gu": "Gujurati",
13693        "ht": "Haitian",
13694        "he": "Hebrew",
13695        "hi": "Hindi",
13696        "hu": "Hungarian",
13697        "is": "Icelandic",
13698        "id": "Indonesian",
13699        "iu": "Inuktitut",
13700        "ga": "Irish",
13701        "it": "Italian (Standard)",
13702        "it-CH": "Italian (Switzerland)",
13703        "ja": "Japanese",
13704        "kn": "Kannada",
13705        "ks": "Kashmiri",
13706        "kk": "Kazakh",
13707        "km": "Khmer",
13708        "ky": "Kirghiz",
13709        "tlh": "Klingon",
13710        "ko": "Korean",
13711        "ko-KP": "Korean (North Korea)",
13712        "ko-KR": "Korean (South Korea)",
13713        "la": "Latin",
13714        "lv": "Latvian",
13715        "lt": "Lithuanian",
13716        "lb": "Luxembourgish",
13717        "mk": "FYRO Macedonian",
13718        "ms": "Malay",
13719        "ml": "Malayalam",
13720        "mt": "Maltese",
13721        "mi": "Maori",
13722        "mr": "Marathi",
13723        "mo": "Moldavian",
13724        "nv": "Navajo",
13725        "ng": "Ndonga",
13726        "ne": "Nepali",
13727        "no": "Norwegian",
13728        "nb": "Norwegian (Bokmal)",
13729        "nn": "Norwegian (Nynorsk)",
13730        "oc": "Occitan",
13731        "or": "Oriya",
13732        "om": "Oromo",
13733        "fa": "Persian",
13734        "fa-IR": "Persian/Iran",
13735        "pl": "Polish",
13736        "pt": "Portuguese",
13737        "pt-BR": "Portuguese (Brazil)",
13738        "pa": "Punjabi",
13739        "pa-IN": "Punjabi (India)",
13740        "pa-PK": "Punjabi (Pakistan)",
13741        "qu": "Quechua",
13742        "rm": "Rhaeto-Romanic",
13743        "ro": "Romanian",
13744        "ro-MO": "Romanian (Moldavia)",
13745        "ru": "Russian",
13746        "ru-MO": "Russian (Moldavia)",
13747        "sz": "Sami (Lappish)",
13748        "sg": "Sango",
13749        "sa": "Sanskrit",
13750        "sc": "Sardinian",
13751        "sd": "Sindhi",
13752        "si": "Singhalese",
13753        "sr": "Serbian",
13754        "sk": "Slovak",
13755        "sl": "Slovenian",
13756        "so": "Somani",
13757        "sb": "Sorbian",
13758        "es": "Spanish",
13759        "es-AR": "Spanish (Argentina)",
13760        "es-BO": "Spanish (Bolivia)",
13761        "es-CL": "Spanish (Chile)",
13762        "es-CO": "Spanish (Colombia)",
13763        "es-CR": "Spanish (Costa Rica)",
13764        "es-DO": "Spanish (Dominican Republic)",
13765        "es-EC": "Spanish (Ecuador)",
13766        "es-SV": "Spanish (El Salvador)",
13767        "es-GT": "Spanish (Guatemala)",
13768        "es-HN": "Spanish (Honduras)",
13769        "es-MX": "Spanish (Mexico)",
13770        "es-NI": "Spanish (Nicaragua)",
13771        "es-PA": "Spanish (Panama)",
13772        "es-PY": "Spanish (Paraguay)",
13773        "es-PE": "Spanish (Peru)",
13774        "es-PR": "Spanish (Puerto Rico)",
13775        "es-ES": "Spanish (Spain)",
13776        "es-UY": "Spanish (Uruguay)",
13777        "es-VE": "Spanish (Venezuela)",
13778        "sx": "Sutu",
13779        "sw": "Swahili",
13780        "sv": "Swedish",
13781        "sv-FI": "Swedish (Finland)",
13782        "sv-SV": "Swedish (Sweden)",
13783        "ta": "Tamil",
13784        "tt": "Tatar",
13785        "te": "Teluga",
13786        "th": "Thai",
13787        "tig": "Tigre",
13788        "ts": "Tsonga",
13789        "tn": "Tswana",
13790        "tr": "Turkish",
13791        "tk": "Turkmen",
13792        "uk": "Ukrainian",
13793        "hsb": "Upper Sorbian",
13794        "ur": "Urdu",
13795        "ve": "Venda",
13796        "vi": "Vietnamese",
13797        "vo": "Volapuk",
13798        "wa": "Walloon",
13799        "cy": "Welsh",
13800        "xh": "Xhosa",
13801        "ji": "Yiddish",
13802        "zu": "Zulu"
13803      };
13804
13805      if (this.internal.languageSettings === undefined) {
13806        this.internal.languageSettings = {};
13807        this.internal.languageSettings.isSubscribed = false;
13808      }
13809
13810      if (langCodes[langCode] !== undefined) {
13811        this.internal.languageSettings.languageCode = langCode;
13812
13813        if (this.internal.languageSettings.isSubscribed === false) {
13814          this.internal.events.subscribe("putCatalog", function () {
13815            this.internal.write("/Lang (" + this.internal.languageSettings.languageCode + ")");
13816          });
13817          this.internal.languageSettings.isSubscribed = true;
13818        }
13819      }
13820
13821      return this;
13822    };
13823  })(jsPDF.API);
13824
13825  /** @license
13826   * MIT license.
13827   * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
13828   *               2014 Diego Casorran, https://github.com/diegocr
13829   *
13830   * 
13831   * ====================================================================
13832   */
13833
13834  /**
13835  * jsPDF split_text_to_size plugin 
13836  * 
13837  * @name split_text_to_size
13838  * @module
13839  */
13840  (function (API) {
13841    /**
13842     * Returns an array of length matching length of the 'word' string, with each
13843     * cell occupied by the width of the char in that position.
13844     * 
13845     * @name getCharWidthsArray
13846     * @function
13847     * @param {string} text
13848     * @param {Object} options
13849     * @returns {Array}
13850     */
13851
13852    var getCharWidthsArray = API.getCharWidthsArray = function (text, options) {
13853      options = options || {};
13854      var activeFont = options.font || this.internal.getFont();
13855      var fontSize = options.fontSize || this.internal.getFontSize();
13856      var charSpace = options.charSpace || this.internal.getCharSpace();
13857      var widths = options.widths ? options.widths : activeFont.metadata.Unicode.widths;
13858      var widthsFractionOf = widths.fof ? widths.fof : 1;
13859      var kerning = options.kerning ? options.kerning : activeFont.metadata.Unicode.kerning;
13860      var kerningFractionOf = kerning.fof ? kerning.fof : 1;
13861      var i;
13862      var l;
13863      var char_code;
13864      var prior_char_code = 0; //for kerning
13865
13866      var default_char_width = widths[0] || widthsFractionOf;
13867      var output = [];
13868
13869      for (i = 0, l = text.length; i < l; i++) {
13870        char_code = text.charCodeAt(i);
13871
13872        if (typeof activeFont.metadata.widthOfString === "function") {
13873          output.push((activeFont.metadata.widthOfGlyph(activeFont.metadata.characterToGlyph(char_code)) + charSpace * (1000 / fontSize) || 0) / 1000);
13874        } else {
13875          output.push((widths[char_code] || default_char_width) / widthsFractionOf + (kerning[char_code] && kerning[char_code][prior_char_code] || 0) / kerningFractionOf);
13876        }
13877
13878        prior_char_code = char_code;
13879      }
13880
13881      return output;
13882    };
13883    /**
13884     * Calculate the sum of a number-array
13885     * 
13886     * @name getArraySum
13887     * @public
13888     * @function
13889     * @param {Array} array Array of numbers
13890     * @returns {number}
13891     */
13892
13893
13894    var getArraySum = API.getArraySum = function (array) {
13895      var i = array.length,
13896          output = 0;
13897
13898      while (i) {
13899        i--;
13900        output += array[i];
13901      }
13902
13903      return output;
13904    };
13905    /**
13906    * Returns a widths of string in a given font, if the font size is set as 1 point.
13907    *
13908    * In other words, this is "proportional" value. For 1 unit of font size, the length
13909    * of the string will be that much.
13910    * 
13911    * Multiply by font size to get actual width in *points*
13912    * Then divide by 72 to get inches or divide by (72/25.6) to get 'mm' etc.
13913    * 
13914    * @name getStringUnitWidth
13915    * @public
13916    * @function
13917    * @param {string} text
13918    * @param {string} options
13919    * @returns {number} result
13920    */
13921
13922
13923    var getStringUnitWidth = API.getStringUnitWidth = function (text, options) {
13924      options = options || {};
13925      var fontSize = options.fontSize || this.internal.getFontSize();
13926      var font = options.font || this.internal.getFont();
13927      var charSpace = options.charSpace || this.internal.getCharSpace();
13928      var result = 0;
13929
13930      if (typeof font.metadata.widthOfString === "function") {
13931        result = font.metadata.widthOfString(text, fontSize, charSpace) / fontSize;
13932      } else {
13933        result = getArraySum(getCharWidthsArray.apply(this, arguments));
13934      }
13935
13936      return result;
13937    };
13938    /**
13939    returns array of lines
13940    */
13941
13942
13943    var splitLongWord = function splitLongWord(word, widths_array, firstLineMaxLen, maxLen) {
13944      var answer = []; // 1st, chop off the piece that can fit on the hanging line.
13945
13946      var i = 0,
13947          l = word.length,
13948          workingLen = 0;
13949
13950      while (i !== l && workingLen + widths_array[i] < firstLineMaxLen) {
13951        workingLen += widths_array[i];
13952        i++;
13953      } // this is first line.
13954
13955
13956      answer.push(word.slice(0, i)); // 2nd. Split the rest into maxLen pieces.
13957
13958      var startOfLine = i;
13959      workingLen = 0;
13960
13961      while (i !== l) {
13962        if (workingLen + widths_array[i] > maxLen) {
13963          answer.push(word.slice(startOfLine, i));
13964          workingLen = 0;
13965          startOfLine = i;
13966        }
13967
13968        workingLen += widths_array[i];
13969        i++;
13970      }
13971
13972      if (startOfLine !== i) {
13973        answer.push(word.slice(startOfLine, i));
13974      }
13975
13976      return answer;
13977    }; // Note, all sizing inputs for this function must be in "font measurement units"
13978    // By default, for PDF, it's "point".
13979
13980
13981    var splitParagraphIntoLines = function splitParagraphIntoLines(text, maxlen, options) {
13982      // at this time works only on Western scripts, ones with space char
13983      // separating the words. Feel free to expand.
13984      if (!options) {
13985        options = {};
13986      }
13987
13988      var line = [],
13989          lines = [line],
13990          line_length = options.textIndent || 0,
13991          separator_length = 0,
13992          current_word_length = 0,
13993          word,
13994          widths_array,
13995          words = text.split(' '),
13996          spaceCharWidth = getCharWidthsArray.apply(this, [' ', options])[0],
13997          i,
13998          l,
13999          tmp,
14000          lineIndent;
14001
14002      if (options.lineIndent === -1) {
14003        lineIndent = words[0].length + 2;
14004      } else {
14005        lineIndent = options.lineIndent || 0;
14006      }
14007
14008      if (lineIndent) {
14009        var pad = Array(lineIndent).join(" "),
14010            wrds = [];
14011        words.map(function (wrd) {
14012          wrd = wrd.split(/\s*\n/);
14013
14014          if (wrd.length > 1) {
14015            wrds = wrds.concat(wrd.map(function (wrd, idx) {
14016              return (idx && wrd.length ? "\n" : "") + wrd;
14017            }));
14018          } else {
14019            wrds.push(wrd[0]);
14020          }
14021        });
14022        words = wrds;
14023        lineIndent = getStringUnitWidth.apply(this, [pad, options]);
14024      }
14025
14026      for (i = 0, l = words.length; i < l; i++) {
14027        var force = 0;
14028        word = words[i];
14029
14030        if (lineIndent && word[0] == "\n") {
14031          word = word.substr(1);
14032          force = 1;
14033        }
14034
14035        widths_array = getCharWidthsArray.apply(this, [word, options]);
14036        current_word_length = getArraySum(widths_array);
14037
14038        if (line_length + separator_length + current_word_length > maxlen || force) {
14039          if (current_word_length > maxlen) {
14040            // this happens when you have space-less long URLs for example.
14041            // we just chop these to size. We do NOT insert hiphens
14042            tmp = splitLongWord.apply(this, [word, widths_array, maxlen - (line_length + separator_length), maxlen]);
vendor: 6,047 bytes, lines 14042-14219
14042 // first line we add to existing line object
14043
14044            line.push(tmp.shift()); // it's ok to have extra space indicator there
14045            // last line we make into new line object
14046
14047            line = [tmp.pop()]; // lines in the middle we apped to lines object as whole lines
14048
14049            while (tmp.length) {
14050              lines.push([tmp.shift()]); // single fragment occupies whole line
14051            }
14052
14053            current_word_length = getArraySum(widths_array.slice(word.length - (line[0] ? line[0].length : 0)));
14054          } else {
14055            // just put it on a new line
14056            line = [word];
14057          } // now we attach new line to lines
14058
14059
14060          lines.push(line);
14061          line_length = current_word_length + lineIndent;
14062          separator_length = spaceCharWidth;
14063        } else {
14064          line.push(word);
14065          line_length += separator_length + current_word_length;
14066          separator_length = spaceCharWidth;
14067        }
14068      }
14069
14070      if (lineIndent) {
14071        var postProcess = function postProcess(ln, idx) {
14072          return (idx ? pad : '') + ln.join(" ");
14073        };
14074      } else {
14075        var postProcess = function postProcess(ln) {
14076          return ln.join(" ");
14077        };
14078      }
14079
14080      return lines.map(postProcess);
14081    };
14082    /**
14083    * Splits a given string into an array of strings. Uses 'size' value
14084    * (in measurement units declared as default for the jsPDF instance)
14085    * and the font's "widths" and "Kerning" tables, where available, to
14086    * determine display length of a given string for a given font.
14087    * 
14088    * We use character's 100% of unit size (height) as width when Width
14089    * table or other default width is not available.
14090    * 
14091    * @name splitTextToSize
14092    * @public
14093    * @function
14094    * @param {string} text Unencoded, regular JavaScript (Unicode, UTF-16 / UCS-2) string.
14095    * @param {number} size Nominal number, measured in units default to this instance of jsPDF.
14096    * @param {Object} options Optional flags needed for chopper to do the right thing.
14097    * @returns {Array} array Array with strings chopped to size.
14098    */
14099
14100
14101    API.splitTextToSize = function (text, maxlen, options) {
14102
14103      options = options || {};
14104
14105      var fsize = options.fontSize || this.internal.getFontSize(),
14106          newOptions = function (options) {
14107        var widths = {
14108          0: 1
14109        },
14110            kerning = {};
14111
14112        if (!options.widths || !options.kerning) {
14113          var f = this.internal.getFont(options.fontName, options.fontStyle),
14114              encoding = 'Unicode'; // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE
14115          // Actual JavaScript-native String's 16bit char codes used.
14116          // no multi-byte logic here
14117
14118          if (f.metadata[encoding]) {
14119            return {
14120              widths: f.metadata[encoding].widths || widths,
14121              kerning: f.metadata[encoding].kerning || kerning
14122            };
14123          } else {
14124            return {
14125              font: f.metadata,
14126              fontSize: this.internal.getFontSize(),
14127              charSpace: this.internal.getCharSpace()
14128            };
14129          }
14130        } else {
14131          return {
14132            widths: options.widths,
14133            kerning: options.kerning
14134          };
14135        } // then use default values
14136
14137
14138        return {
14139          widths: widths,
14140          kerning: kerning
14141        };
14142      }.call(this, options); // first we split on end-of-line chars
14143
14144
14145      var paragraphs;
14146
14147      if (Array.isArray(text)) {
14148        paragraphs = text;
14149      } else {
14150        paragraphs = text.split(/\r?\n/);
14151      } // now we convert size (max length of line) into "font size units"
14152      // at present time, the "font size unit" is always 'point'
14153      // 'proportional' means, "in proportion to font size"
14154
14155
14156      var fontUnit_maxLen = 1.0 * this.internal.scaleFactor * maxlen / fsize; // at this time, fsize is always in "points" regardless of the default measurement unit of the doc.
14157      // this may change in the future?
14158      // until then, proportional_maxlen is likely to be in 'points'
14159      // If first line is to be indented (shorter or longer) than maxLen
14160      // we indicate that by using CSS-style "text-indent" option.
14161      // here it's in font units too (which is likely 'points')
14162      // it can be negative (which makes the first line longer than maxLen)
14163
14164      newOptions.textIndent = options.textIndent ? options.textIndent * 1.0 * this.internal.scaleFactor / fsize : 0;
14165      newOptions.lineIndent = options.lineIndent;
14166      var i,
14167          l,
14168          output = [];
14169
14170      for (i = 0, l = paragraphs.length; i < l; i++) {
14171        output = output.concat(splitParagraphIntoLines.apply(this, [paragraphs[i], fontUnit_maxLen, newOptions]));
14172      }
14173
14174      return output;
14175    };
14176  })(jsPDF.API);
14177
14178  /** @license
14179   jsPDF standard_fonts_metrics plugin
14180   * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
14181   * MIT license.
14182   * 
14183   * ====================================================================
14184   */
14185
14186  (function (API) {
14187    /*
14188    # reference (Python) versions of 'compress' and 'uncompress'
14189    # only 'uncompress' function is featured lower as JavaScript
14190    # if you want to unit test "roundtrip", just transcribe the reference
14191    # 'compress' function from Python into JavaScript
14192    
14193    def compress(data):
14194    
14195    	keys =   '0123456789abcdef'
14196    	values = 'klmnopqrstuvwxyz'
14197    	mapping = dict(zip(keys, values))
14198    	vals = []
14199    	for key in data.keys():
14200    		value = data[key]
14201    		try:
14202    			keystring = hex(key)[2:]
14203    			keystring = keystring[:-1] + mapping[keystring[-1:]]
14204    		except:
14205    			keystring = key.join(["'","'"])
14206    			#print('Keystring is %s' % keystring)
14207    
14208    		try:
14209    			if value < 0:
14210    				valuestring = hex(value)[3:]
14211    				numberprefix = '-'
14212    			else:
14213    				valuestring = hex(value)[2:]
14214    				numberprefix = ''
14215    			valuestring = numberprefix + valuestring[:-1] + mapping[valuestring[-1:]]
14216    		except:
14217    			if type(value) == dict:
14218    				valuestring = compress(value)
14219    			else:
14220    				raise Exception("Don't know what to do with value type %s" % type(value))
14221    
14222    		vals.append(keystring+valuestring)
14223    	
14224    	return '{' + ''.join(vals) + '}'
14225    
14226    def uncompress(data):
14227    
14228    	decoded = '0123456789abcdef'
14229    	encoded = 'klmnopqrstuvwxyz'
14230    	mapping = dict(zip(encoded, decoded))
14231    
14232    	sign = +1
14233    	stringmode = False
14234    	stringparts = []
14235    
14236    	output = {}
14237    
14238    	activeobject = output
14239    	parentchain = []
14240    
14241    	keyparts = ''
14242    	valueparts = ''
14243    
14244    	key = None
14245    
14246    	ending = set(encoded)
14247    
14248    	i = 1
14249    	l = len(data) - 1 # stripping starting, ending {}
14250    	while i != l: # stripping {}
14251    		# -, {, }, ' are special.
14252    
14253    		ch = data[i]
14254    		i += 1
14255    
14256    		if ch == "'":
14257    			if stringmode:
14258    				# end of string mode
14259    				stringmode = False
14260    				key = ''.join(stringparts)
14261    			else:
14262    				# start of string mode
14263    				stringmode = True
14264    				stringparts = []
14265    		elif stringmode == True:
14266    			#print("Adding %s to stringpart" % ch)
14267    			stringparts.append(ch)
14268    
14269    		elif ch == '{':
14270    			# start of object
14271    			parentchain.append( [activeobject, key] )
14272    			activeobject = {}
14273    			key = None
14274    			#DEBUG = True
14275    		elif ch == '}':
14276    			# end of object
14277    			parent, key = parentchain.pop()
14278    			parent[key] = activeobject
14279    			key = None
14280    			activeobject = parent
14281    			#DEBUG = False
14282    
14283    		elif ch == '-':
14284    			sign = -1
14285    		else:
14286    			# must be number
14287    			if key == None:
14288    				#debug("In Key. It is '%s', ch is '%s'" % (keyparts, ch))
14289    				if ch in ending:
14290    					#debug("End of key")
14291    					keyparts += mapping[ch]
14292    					key = int(keyparts, 16) * sign
14293    					sign = +1
14294    					keyparts = ''
14295    				else:
14296    					keyparts += ch
14297    			else:
14298    				#debug("In value. It is '%s', ch is '%s'" % (valueparts, ch))
14299    				if ch in ending:
14300    					#debug("End of value")
14301    					valueparts += mapping[ch]
14302    					activeobject[key] = int(valueparts, 16) * sign
14303    					sign = +1
14304    					key = None
14305    					valueparts = ''
14306    				else:
14307    					valueparts += ch
14308    
14309    			#debug(activeobject)
14310    
14311    	return output
14312    
14313    */
14314
14315    /**
14316    Uncompresses data compressed into custom, base16-like format. 
14317    @public
14318    @function
14319    @param
14320    @returns {Type}
14321    */
14322
14323    var uncompress = function uncompress(data) {
14324      var decoded = '0123456789abcdef',
14325          encoded = 'klmnopqrstuvwxyz',
14326          mapping = {};
14327
14328      for (var i = 0; i < encoded.length; i++) {
14329        mapping[encoded[i]] = decoded[i];
14330      }
14331
14332      var undef,
14333          output = {},
14334          sign = 1,
14335          stringparts // undef. will be [] in string mode
14336      ,
14337          activeobject = output,
14338          parentchain = [],
14339          parent_key_pair,
14340          keyparts = '',
14341          valueparts = '',
14342          key // undef. will be Truthy when Key is resolved.
14343      ,
14344          datalen = data.length - 1 // stripping ending }
14345      ,
14346          ch;
14347      i = 1; // stripping starting {
14348
14349      while (i != datalen) {
14350        // - { } ' are special.
14351        ch = data[i];
14352        i += 1;
14353
14354        if (ch == "'") {
14355          if (stringparts) {
14356            // end of string mode
14357            key = stringparts.join('');
14358            stringparts = undef;
14359          } else {
14360            // start of string mode
14361            stringparts = [];
14362          }
14363        } else if (stringparts) {
14364          stringparts.push(ch);
14365        } else if (ch == '{') {
14366          // start of object
14367          parentchain.push([activeobject, key]);
14368          activeobject = {};
14369          key = undef;
14370        } else if (ch == '}') {
14371          // end of object
14372          parent_key_pair = parentchain.pop();
14373          parent_key_pair[0][parent_key_pair[1]] = activeobject;
14374          key = undef;
14375          activeobject = parent_key_pair[0];
14376        } else if (ch == '-') {
14377          sign = -1;
14378        } else {
14379          // must be number
14380          if (key === undef) {
14381            if (mapping.hasOwnProperty(ch)) {
14382              keyparts += mapping[ch];
14383              key = parseInt(keyparts, 16) * sign;
14384              sign = +1;
14385              keyparts = '';
14386            } else {
14387              keyparts += ch;
14388            }
14389          } else {
14390            if (mapping.hasOwnProperty(ch)) {
14391              valueparts += mapping[ch];
14392              activeobject[key] = parseInt(valueparts, 16) * sign;
14393              sign = +1;
14394              key = undef;
14395              valueparts = '';
14396            } else {
14397              valueparts += ch;
14398            }
14399          }
14400        }
14401      } // end while
14402
14403
14404      return output;
14405    }; // encoding = 'Unicode' 
14406    // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE. NO clever BOM behavior
14407    // Actual 16bit char codes used.
14408    // no multi-byte logic here
14409    // Unicode characters to WinAnsiEncoding:
14410    // {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}
14411    // as you can see, all Unicode chars are outside of 0-255 range. No char code conflicts.
14412    // this means that you can give Win cp1252 encoded strings to jsPDF for rendering directly
14413    // as well as give strings with some (supported by these fonts) Unicode characters and 
14414    // these will be mapped to win cp1252 
14415    // for example, you can send char code (cp1252) 0x80 or (unicode) 0x20AC, getting "Euro" glyph displayed in both cases.
14416
14417
14418    var encodingBlock = {
14419      'codePages': ['WinAnsiEncoding'],
14420      'WinAnsiEncoding': uncompress("{19m8n201n9q201o9r201s9l201t9m201u8m201w9n201x9o201y8o202k8q202l8r202m9p202q8p20aw8k203k8t203t8v203u9v2cq8s212m9t15m8w15n9w2dw9s16k8u16l9u17s9z17x8y17y9y}")
14421    },
14422        encodings = {
14423      'Unicode': {
14424        'Courier': encodingBlock,
14425        'Courier-Bold': encodingBlock,
14426        'Courier-BoldOblique': encodingBlock,
14427        'Courier-Oblique': encodingBlock,
14428        'Helvetica': encodingBlock,
14429        'Helvetica-Bold': encodingBlock,
14430        'Helvetica-BoldOblique': encodingBlock,
14431        'Helvetica-Oblique': encodingBlock,
14432        'Times-Roman': encodingBlock,
14433        'Times-Bold': encodingBlock,
14434        'Times-BoldItalic': encodingBlock,
14435        'Times-Italic': encodingBlock //	, 'Symbol'
14436        //	, 'ZapfDingbats'
14437
14438      }
14439    },
14440        fontMetrics = {
14441      'Unicode': {
14442        // all sizing numbers are n/fontMetricsFractionOf = one font size unit
14443        // this means that if fontMetricsFractionOf = 1000, and letter A's width is 476, it's
14444        // width is 476/1000 or 47.6% of its height (regardless of font size)
14445        // At this time this value applies to "widths" and "kerning" numbers.
14446        // char code 0 represents "default" (average) width - use it for chars missing in this table.
14447        // key 'fof' represents the "fontMetricsFractionOf" value
14448        'Courier-Oblique': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
14449        'Times-BoldItalic': uncompress("{'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}}}"),
14450        'Helvetica-Bold': uncompress("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4y
14450dn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'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}}}"),
14451        'Courier': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
14452        'Courier-BoldOblique': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
14453        'Times-Bold': uncompress("{'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}}}"),
14454        'Symbol': uncompress("{'widths'{k3uaw4r19m3m2k1t2l2l202m2y2n3m2p5n202q6o3k3m2s2l2t2l2v3r2w1t3m3m2y1t2z1wbk2sbl3r'fof'6o3n3m3o3m3p3m3q3m3r3m3s3m3t3m3u1w3v1w3w3r3x3r3y3r3z2wbp3t3l3m5v2l5x2l5z3m2q4yfr3r7v3k7w1o7x3k}'kerning'{'fof'-6o}}"),
14455        'Helvetica': uncompress("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4y
14455dn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'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}}}"),
14456        'Helvetica-BoldOblique': uncompress("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4y
14456dn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'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}}}"),
14457        'ZapfDingbats': uncompress("{'widths'{k4u2k1w'fof'6o}'kerning'{'fof'-6o}}"),
14458        'Courier-Bold': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
14459        'Times-Italic': uncompress("{'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}
14459fv{17su5tu5qs}fw{17su5tu5qs}}}"),
14460        'Times-Roman': uncompress("{'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}}}"),
14461        'Helvetica-Oblique': uncompress("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4y
14461dn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'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}}}")
14462      }
14463    };
14464    /*
14465    This event handler is fired when a new jsPDF object is initialized
14466    This event handler appends metrics data to standard fonts within
14467    that jsPDF instance. The metrics are mapped over Unicode character
14468    codes, NOT CIDs or other codes matching the StandardEncoding table of the
14469    standard PDF fonts.
14470    Future:
14471    Also included is the encoding maping table, converting Unicode (UCS-2, UTF-16)
14472    char codes to StandardEncoding character codes. The encoding table is to be used
14473    somewhere around "pdfEscape" call.
14474    */
14475
14476    API.events.push(['addFont', function (data) {
14477      var font = data.font;
14478      var metrics,
14479          unicode_section,
14480          encoding = 'Unicode',
14481          encodingBlock;
14482      metrics = fontMetrics[encoding][font.postScriptName];
14483
14484      if (metrics) {
14485        if (font.metadata[encoding]) {
14486          unicode_section = font.metadata[encoding];
14487        } else {
14488          unicode_section = font.metadata[encoding] = {};
14489        }
14490
14491        unicode_section.widths = metrics.widths;
14492        unicode_section.kerning = metrics.kerning;
14493      }
14494
14495      encodingBlock = encodings[encoding][font.postScriptName];
14496
14497      if (encodingBlock) {
14498        if (font.metadata[encoding]) {
14499          unicode_section = font.metadata[encoding];
14500        } else {
14501          unicode_section = font.metadata[encoding] = {};
14502        }
14503
14504        unicode_section.encoding = encodingBlock;
14505
14506        if (encodingBlock.codePages && encodingBlock.codePages.length) {
14507          font.encoding = encodingBlock.codePages[0];
14508        }
14509      }
14510    }]); // end of adding event handler
14511  })(jsPDF.API);
14512
14513  /**
14514   * @license
14515   * Licensed under the MIT License.
14516   * http://opensource.org/licenses/mit-license
14517   */
14518
14519  /**
14520  * @name ttfsupport
14521  * @module
14522  */
14523  (function (jsPDF, global) {
14524
14525    jsPDF.API.events.push(['addFont', function (data) {
14526      var font = data.font;
14527      var instance = data.instance;
14528
14529      if (typeof instance !== "undefined" && instance.existsFileInVFS(font.postScriptName)) {
14530        var file = instance.getFileFromVFS(font.postScriptName);
14531
14532        if (typeof file !== "string") {
14533          throw new Error("Font is not stored as string-data in vFS, import fonts or remove declaration doc.addFont('" + font.postScriptName + "').");
14534        }
14535
14536        font.metadata = jsPDF.API.TTFFont.open(font.postScriptName, font.fontName, file, font.encoding);
14537        font.metadata.Unicode = font.metadata.Unicode || {
14538          encoding: {},
14539          kerning: {},
14540          widths: []
14541        };
14542        font.metadata.glyIdsUsed = [0];
14543      } else if (font.isStandardFont === false) {
14544        throw new Error("Font does not exist in vFS, import fonts or remove declaration doc.addFont('" + font.postScriptName + "').");
14545      }
14546    }]); // end of adding event handler
14547  })(jsPDF, typeof self !== "undefined" && self || typeof global !== "undefined" && global || typeof window !== "undefined" && window || Function("return this")());
14548
14549  /** @license
14550   * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
14551   * 
14552   * 
14553   * ====================================================================
14554   */
14555
14556  (function (jsPDFAPI) {
14557    /**
14558    * Parses SVG XML and converts only some of the SVG elements into
14559    * PDF elements.
14560    *
14561    * Supports:
14562    * paths
14563    * 
14564    * @name addSvg
14565    * @public
14566    * @function 
14567    * @param {string} SVG-Data as Text
14568    * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
14569    * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
14570    * @param {number} width of SVG (in units declared at inception of PDF document)
14571    * @param {number} height of SVG (in units declared at inception of PDF document)
14572    * @returns {Object} jsPDF-instance
14573    */
14574
14575    jsPDFAPI.addSvg = function (svgtext, x, y, w, h) {
14576      // 'this' is _jsPDF object returned when jsPDF is inited (new jsPDF())
14577      var undef;
14578
14579      if (x === undef || y === undef) {
14580        throw new Error("addSVG needs values for 'x' and 'y'");
14581      }
14582
14583      function InjectCSS(cssbody, document) {
14584        var styletag = document.createElement('style');
14585        styletag.type = 'text/css';
14586
14587        if (styletag.styleSheet) {
14588          // ie
14589          styletag.styleSheet.cssText = cssbody;
14590        } else {
14591          // others
14592          styletag.appendChild(document.createTextNode(cssbody));
14593        }
14594
14595        document.getElementsByTagName("head")[0].appendChild(styletag);
14596      }
14597
14598      function createWorkerNode(document) {
14599        var frameID = 'childframe' // Date.now().toString() + '_' + (Math.random() * 100).toString()
14600        ,
14601            frame = document.createElement('iframe');
14602        InjectCSS('.jsPDF_sillysvg_iframe {display:none;position:absolute;}', document);
14603        frame.name = frameID;
14604        frame.setAttribute("width", 0);
14605        frame.setAttribute("height", 0);
14606        frame.setAttribute("frameborder", "0");
14607        frame.setAttribute("scrolling", "no");
14608        frame.setAttribute("seamless", "seamless");
14609        frame.setAttribute("class", "jsPDF_sillysvg_iframe");
14610        document.body.appendChild(frame);
14611        return frame;
14612      }
14613
14614      function attachSVGToWorkerNode(svgtext, frame) {
14615        var framedoc = (frame.contentWindow || frame.contentDocument).document;
14616        framedoc.write(svgtext);
14617        framedoc.close();
14618        return framedoc.getElementsByTagName('svg')[0];
14619      }
14620
14621      function convertPathToPDFLinesArgs(path) {
14622        // - starting coordinate pair
14623        // - array of arrays of vector shifts (2-len for line, 6 len for bezier)
14624        // - scale array [horizontal, vertical] ratios
14625        // - style (stroke, fill, both)
14626
14627        var x = parseFloat(path[1]),
14628            y = parseFloat(path[2]),
14629            vectors = [],
14630            position = 3,
14631            len = path.length;
14632
14633        while (position < len) {
14634          if (path[position] === 'c') {
14635            vectors.push([parseFloat(path[position + 1]), parseFloat(path[position + 2]), parseFloat(path[position + 3]), parseFloat(path[position + 4]), parseFloat(path[position + 5]), parseFloat(path[position + 6])]);
14636            position += 7;
14637          } else if (path[position] === 'l') {
14638            vectors.push([parseFloat(path[position + 1]), parseFloat(path[position + 2])]);
14639            position += 3;
14640          } else {
14641            position += 1;
14642          }
14643        }
14644
14645        return [x, y, vectors];
14646      }
14647
14648      var workernode = createWorkerNode(document),
14649          svgnode = attachSVGToWorkerNode(svgtext, workernode),
14650          scale = [1, 1],
14651          svgw = parseFloat(svgnode.getAttribute('width')),
14652          svgh = parseFloat(svgnode.getAttribute('height'));
14653
14654      if (svgw && svgh) {
14655        // setting both w and h makes image stretch to size.
14656        // this may distort the image, but fits your demanded size
14657        if (w && h) {
14658          scale = [w / svgw, h / svgh];
14659        } // if only one is set, that value is set as max and SVG
14660        // is scaled proportionately.
14661        else if (w) {
14662            scale = [w / svgw, w / svgw];
14663          } else if (h) {
14664            scale = [h / svgh, h / svgh];
14665          }
14666      }
14667
14668      var i,
14669          l,
14670          tmp,
14671          linesargs,
14672          items = svgnode.childNodes;
14673
14674      for (i = 0, l = items.length; i < l; i++) {
14675        tmp = items[i];
14676
14677        if (tmp.tagName && tmp.tagName.toUpperCase() === 'PATH') {
14678          linesargs = convertPathToPDFLinesArgs(tmp.getAttribute("d").split(' ')); // path start x coordinate
14679
14680          linesargs[0] = linesargs[0] * scale[0] + x; // where x is upper left X of image
14681          // path start y coordinate
14682
14683          linesargs[1] = linesargs[1] * scale[1] + y; // where y is upper left Y of image
14684          // the rest of lines are vectors. these will adjust with scale value auto.
14685
14686          this.lines.call(this, linesargs[2] // lines
14687          , linesargs[0] // starting x
14688          , linesargs[1] // starting y
14689          , scale);
14690        }
14691      } // clean up
14692      // workernode.parentNode.removeChild(workernode)
14693
14694
14695      return this;
14696    }; //fallback
14697
14698
14699    jsPDFAPI.addSVG = jsPDFAPI.addSvg;
14700    /**
14701    * Parses SVG XML and saves it as image into the PDF.
14702    *
14703    * Depends on canvas-element and canvg
14704    *
14705    * @name addSvgAsImage
14706    * @public
14707    * @function
14708    * @param {string} SVG-Data as Text
14709    * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
14710    * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
14711    * @param {number} width of SVG-Image (in units declared at inception of PDF document)
14712    * @param {number} height of SVG-Image (in units declared at inception of PDF document)
14713    * @param {string} alias of SVG-Image (if used multiple times)
14714    * @param {string} compression of the generated JPEG, can have the values 'NONE', 'FAST', 'MEDIUM' and 'SLOW'
14715    * @param {number} rotation of the image in degrees (0-359)
14716    * 
14717    * @returns jsPDF jsPDF-instance
14718    */
14719
14720    jsPDFAPI.addSvgAsImage = function (svg, x, y, w, h, alias, compression, rotation) {
14721      if (isNaN(x) || isNaN(y)) {
14722        console.error('jsPDF.addSvgAsImage: Invalid coordinates', arguments);
14723        throw new Error('Invalid coordinates passed to jsPDF.addSvgAsImage');
14724      }
14725
14726      if (isNaN(w) || isNaN(h)) {
14727        console.error('jsPDF.addSvgAsImage: Invalid measurements', arguments);
14728        throw new Error('Invalid measurements (width and/or height) passed to jsPDF.addSvgAsImage');
14729      }
14730
14731      var canvas = document.createElement('canvas');
14732      canvas.width = w;
14733      canvas.height = h;
14734      var ctx = canvas.getContext('2d');
14735      ctx.fillStyle = '#fff'; /// set white fill style
14736
14737      ctx.fillRect(0, 0, canvas.width, canvas.height); //load a svg snippet in the canvas with id = 'drawingArea'
14738
14739      canvg(canvas, svg, {
14740        ignoreMouse: true,
14741        ignoreAnimation: true,
14742        ignoreDimensions: true,
14743        ignoreClear: true
14744      });
14745      this.addImage(canvas.toDataURL("image/jpeg", 1.0), x, y, w, h, compression, rotation);
14746      return this;
14747    };
14748  })(jsPDF.API);
14749
14750  /** 
14751   * @license
14752   * ==================================================================== 
14753   * Copyright (c) 2013 Eduardo Menezes de Morais, [email protected]
14754   * 
14755   * 
14756   * ====================================================================
14757   */
14758
14759  /**
14760   * jsPDF total_pages plugin
14761   * @name total_pages
14762   * @module
14763   */
14764  (function (jsPDFAPI) {
14765    /**
14766    * @name putTotalPages
14767    * @function
14768    * @param {string} pageExpression Regular Expression
14769    * @returns {jsPDF} jsPDF-instance
14770    */
14771
14772    jsPDFAPI.putTotalPages = function (pageExpression) {
14773
14774      var replaceExpression;
14775      var totalNumberOfPages = 0;
14776
14777      if (parseInt(this.internal.getFont().id.substr(1), 10) < 15) {
14778        replaceExpression = new RegExp(pageExpression, 'g');
14779        totalNumberOfPages = this.internal.getNumberOfPages();
14780      } else {
14781        replaceExpression = new RegExp(this.pdfEscape16(pageExpression, this.internal.getFont()), 'g');
14782        totalNumberOfPages = this.pdfEscape16(this.internal.getNumberOfPages() + '', this.internal.getFont());
14783      }
14784
14785      for (var n = 1; n <= this.internal.getNumberOfPages(); n++) {
14786        for (var i = 0; i < this.internal.pages[n].length; i++) {
14787          this.internal.pages[n][i] = this.internal.pages[n][i].replace(replaceExpression, totalNumberOfPages);
14788        }
14789      }
14790
14791      return this;
14792    };
14793  })(jsPDF.API);
14794
14795  /**
14796   * jsPDF viewerPreferences Plugin
14797   * @author Aras Abbasi (github.com/arasabbasi)
14798   * Licensed under the MIT License.
14799   * http://opensource.org/licenses/mit-license
14800   */
14801
14802  /**
14803  * Adds the ability to set ViewerPreferences and by thus
14804  * controlling the way the document is to be presented on the
14805  * screen or in print.
14806  * @name viewerpreferences
14807  * @module
14808  */
14809  (function (jsPDFAPI) {
14810    /**
14811     * Set the ViewerPreferences of the generated PDF
14812     *
14813     * @name viewerPreferences
14814    * @function
14815    * @public
14816     * @param {Object} options Array with the ViewerPreferences<br />
14817     * Example: doc.viewerPreferences({"FitWindow":true});<br />
14818     * <br />
14819     * You can set following preferences:<br />
14820     * <br/>
14821     * <b>HideToolbar</b> <i>(boolean)</i><br />
14822     * Default value: false<br />
14823     * <br />
14824     * <b>HideMenubar</b> <i>(boolean)</i><br />
14825     * Default value: false.<br />
14826     * <br />
14827     * <b>HideWindowUI</b> <i>(boolean)</i><br />
14828     * Default value: false.<br />
14829     * <br />
14830     * <b>FitWindow</b> <i>(boolean)</i><br />
14831     * Default value: false.<br />
14832     * <br />
14833     * <b>CenterWindow</b> <i>(boolean)</i><br />
14834     * Default value: false<br />
14835     * <br />
14836     * <b>DisplayDocTitle</b> <i>(boolean)</i><br />
14837     * Default value: false.<br />
14838     * <br />
14839     * <b>NonFullScreenPageMode</b> <i>(string)</i><br />
14840     * Possible values: UseNone, UseOutlines, UseThumbs, UseOC<br />
14841     * Default value: UseNone<br/>
14842     * <br />
14843     * <b>Direction</b> <i>(string)</i><br />
14844     * Possible values: L2R, R2L<br />
14845     * Default value: L2R.<br />
14846     * <br />
14847     * <b>ViewArea</b> <i>(string)</i><br />
14848     * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
14849     * Default value: CropBox.<br />
14850     * <br />
14851     * <b>ViewClip</b> <i>(string)</i><br />
14852     * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
14853     * Default value: CropBox<br />
14854     * <br />
14855     * <b>PrintArea</b> <i>(string)</i><br />
14856     * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
14857     * Default value: CropBox<br />
14858     * <br />
14859     * <b>PrintClip</b> <i>(string)</i><br />
14860     * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
14861     * Default value: CropBox.<br />
14862     * <br />
14863     * <b>PrintScaling</b> <i>(string)</i><br />
14864     * Possible values: AppDefault, None<br />
14865     * Default value: AppDefault.<br />
14866     * <br />
14867     * <b>Duplex</b> <i>(string)</i><br />
14868     * Possible values: Simplex, DuplexFlipLongEdge, DuplexFlipShortEdge
14869     * Default value: none<br />
14870     * <br />
14871     * <b>PickTrayByPDFSize</b> <i>(boolean)</i><br />
14872     * Default value: false<br />
14873     * <br />
14874     * <b>PrintPageRange</b> <i>(Array)</i><br />
14875     * Example: [[1,5], [7,9]]<br />
14876     * Default value: as defined by PDF viewer application<br />
14877     * <br />
14878     * <b>NumCopies</b> <i>(Number)</i><br />
14879     * Possible values: 1, 2, 3, 4, 5<br />
14880     * Default value: 1<br />
14881     * <br />
14882     * For more information see the PDF Reference, sixth edition on Page 577
14883     * @param {boolean} doReset True to reset the settings
14884     * @function
14885     * @returns jsPDF jsPDF-instance
14886     * @example
14887     * var doc = new jsPDF()
14888     * doc.text('This is a test', 10, 10)
14889     * doc.viewerPreferences({'FitWindow': true}, true)
14890     * doc.save("viewerPreferences.pdf")
14891     *
14892     * // Example printing 10 copies, using cropbox, and hiding UI.
14893     * doc.viewerPreferences({
14894     *   'HideWindowUI': true,
14895     *   'PrintArea': 'CropBox',
14896     *   'NumCopies': 10
14897     * })
14898     */
14899
14900    jsPDFAPI.viewerPreferences = function (options, doReset) {
14901      options = options || {};
14902      doReset = doReset || false;
14903      var configuration;
14904      var configurationTemplate = {
14905        "HideToolbar": {
14906          defaultValue: false,
14907          value: false,
14908          type: "boolean",
14909          explicitSet: false,
14910          valueSet: [true, false],
14911          pdfVersion: 1.3
14912        },
14913        "HideMenubar": {
14914          defaultValue: false,
14915          value: false,
14916          type: "boolean",
14917          explicitSet: false,
14918          valueSet: [true, false],
14919          pdfVersion: 1.3
14920        },
14921        "HideWindowUI": {
14922          defaultValue: false,
14923          value: false,
14924          type: "boolean",
14925          explicitSet: false,
14926          valueSet: [true, false],
14927          pdfVersion: 1.3
14928        },
14929        "FitWindow": {
14930          defaultValue: false,
14931          value: false,
14932          type: "boolean",
14933          explicitSet: false,
14934          valueSet: [true, false],
14935          pdfVersion: 1.3
14936        },
14937        "CenterWindow": {
14938          defaultValue: false,
14939          value: false,
14940          type: "boolean",
14941          explicitSet: false,
14942          valueSet: [true, false],
14943          pdfVersion: 1.3
14944        },
14945        "DisplayDocTitle": {
14946          defaultValue: false,
14947          value: false,
14948          type: "boolean",
14949          explicitSet: false,
14950          valueSet: [true, false],
14951          pdfVersion: 1.4
14952        },
14953        "NonFullScreenPageMode": {
14954          defaultValue: "UseNone",
14955          value: "UseNone",
14956          type: "name",
14957          explicitSet: false,
14958          valueSet: ["UseNone", "UseOutlines", "UseThumbs", "UseOC"],
14959          pdfVersion: 1.3
14960        },
14961        "Direction": {
14962          defaultValue: "L2R",
14963          value: "L2R",
14964          type: "name",
14965          explicitSet: false,
14966          valueSet: ["L2R", "R2L"],
14967          pdfVersion: 1.3
14968        },
14969        "ViewArea": {
14970          defaultValue: "CropBox",
14971          value: "CropBox",
14972          type: "name",
14973          explicitSet: false,
14974          valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
14975          pdfVersion: 1.4
14976        },
14977        "ViewClip": {
14978          defaultValue: "CropBox",
14979          value: "CropBox",
14980          type: "name",
14981          explicitSet: false,
14982          valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
14983          pdfVersion: 1.4
14984        },
14985        "PrintArea": {
14986          defaultValue: "CropBox",
14987          value: "CropBox",
14988          type: "name",
14989          explicitSet: false,
14990          valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
14991          pdfVersion: 1.4
14992        },
14993        "PrintClip": {
14994          defaultValue: "CropBox",
14995          value: "CropBox",
14996          type: "name",
14997          explicitSet: false,
14998          valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
14999          pdfVersion: 1.4
15000        },
15001        "PrintScaling": {
15002          defaultValue: "AppDefault",
15003          value: "AppDefault",
15004          type: "name",
15005          explicitSet: false,
15006          valueSet: ["AppDefault", "None"],
15007          pdfVersion: 1.6
15008        },
15009        "Duplex": {
15010          defaultValue: "",
15011          value: "none",
15012          type: "name",
15013          explicitSet: false,
15014          valueSet: ["Simplex", "DuplexFlipShortEdge", "DuplexFlipLongEdge", "none"],
15015          pdfVersion: 1.7
15016        },
15017        "PickTrayByPDFSize": {
15018          defaultValue: false,
15019          value: false,
15020          type: "boolean",
15021          explicitSet: false,
15022          valueSet: [true, false],
15023          pdfVersion: 1.7
15024        },
15025        "PrintPageRange": {
15026          defaultValue: "",
15027          value: "",
15028          type: "array",
15029          explicitSet: false,
15030          valueSet: null,
15031          pdfVersion: 1.7
15032        },
vendor: 4,278 bytes, lines 15033-15161
15033        "NumCopies": {
15034          defaultValue: 1,
15035          value: 1,
15036          type: "integer",
15037          explicitSet: false,
15038          valueSet: null,
15039          pdfVersion: 1.7
15040        }
15041      };
15042      var configurationKeys = Object.keys(configurationTemplate);
15043      var rangeArray = [];
15044      var i = 0;
15045      var j = 0;
15046      var k = 0;
15047      var isValid = true;
15048      var method;
15049      var value;
15050
15051      function arrayContainsElement(array, element) {
15052        var iterator;
15053        var result = false;
15054
15055        for (iterator = 0; iterator < array.length; iterator += 1) {
15056          if (array[iterator] === element) {
15057            result = true;
15058          }
15059        }
15060
15061        return result;
15062      }
15063
15064      if (this.internal.viewerpreferences === undefined) {
15065        this.internal.viewerpreferences = {};
15066        this.internal.viewerpreferences.configuration = JSON.parse(JSON.stringify(configurationTemplate));
15067        this.internal.viewerpreferences.isSubscribed = false;
15068      }
15069
15070      configuration = this.internal.viewerpreferences.configuration;
15071
15072      if (options === "reset" || doReset === true) {
15073        var len = configurationKeys.length;
15074
15075        for (k = 0; k < len; k += 1) {
15076          configuration[configurationKeys[k]].value = configuration[configurationKeys[k]].defaultValue;
15077          configuration[configurationKeys[k]].explicitSet = false;
15078        }
15079      }
15080
15081      if (_typeof(options) === "object") {
15082        for (method in options) {
15083          value = options[method];
15084
15085          if (arrayContainsElement(configurationKeys, method) && value !== undefined) {
15086            if (configuration[method].type === "boolean" && typeof value === "boolean") {
15087              configuration[method].value = value;
15088            } else if (configuration[method].type === "name" && arrayContainsElement(configuration[method].valueSet, value)) {
15089              configuration[method].value = value;
15090            } else if (configuration[method].type === "integer" && Number.isInteger(value)) {
15091              configuration[method].value = value;
15092            } else if (configuration[method].type === "array") {
15093              for (i = 0; i < value.length; i += 1) {
15094                isValid = true;
15095
15096                if (value[i].length === 1 && typeof value[i][0] === "number") {
15097                  rangeArray.push(String(value[i] - 1));
15098                } else if (value[i].length > 1) {
15099                  for (j = 0; j < value[i].length; j += 1) {
15100                    if (typeof value[i][j] !== "number") {
15101                      isValid = false;
15102                    }
15103                  }
15104
15105                  if (isValid === true) {
15106                    rangeArray.push([value[i][0] - 1, value[i][1] - 1].join(" "));
15107                  }
15108                }
15109              }
15110
15111              configuration[method].value = "[" + rangeArray.join(" ") + "]";
15112            } else {
15113              configuration[method].value = configuration[method].defaultValue;
15114            }
15115
15116            configuration[method].explicitSet = true;
15117          }
15118        }
15119      }
15120
15121      if (this.internal.viewerpreferences.isSubscribed === false) {
15122        this.internal.events.subscribe("putCatalog", function () {
15123          var pdfDict = [];
15124          var vPref;
15125
15126          for (vPref in configuration) {
15127            if (configuration[vPref].explicitSet === true) {
15128              if (configuration[vPref].type === "name") {
15129                pdfDict.push("/" + vPref + " /" + configuration[vPref].value);
15130              } else {
15131                pdfDict.push("/" + vPref + " " + configuration[vPref].value);
15132              }
15133            }
15134          }
15135
15136          if (pdfDict.length !== 0) {
15137            this.internal.write("/ViewerPreferences\n<<\n" + pdfDict.join("\n") + "\n>>");
15138          }
15139        });
15140        this.internal.viewerpreferences.isSubscribed = true;
15141      }
15142
15143      this.internal.viewerpreferences.configuration = configuration;
15144      return this;
15145    };
15146  })(jsPDF.API);
15147
15148  /** ==================================================================== 
15149   * jsPDF XMP metadata plugin
15150   * Copyright (c) 2016 Jussi Utunen, [email protected]
15151   * 
15152   * 
15153   * ====================================================================
15154   */
15155
15156  /*global jsPDF */
15157
15158  /**
15159  * @name xmp_metadata
15160  * @module
15161  */
15162  (function (jsPDFAPI) {
15163
15164    var xmpmetadata = "";
15165    var xmpnamespaceuri = "";
15166    var metadata_object_number = "";
15167    /**
15168    * Adds XMP formatted metadata to PDF
15169    *
15170    * @name addMetadata
15171    * @function
15172    * @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.
15173    * @param {String} namespaceuri Sets the namespace URI for the metadata. Last character should be slash or hash.
15174    * @returns {jsPDF} jsPDF-instance
15175    */
15176
15177    jsPDFAPI.addMetadata = function (metadata, namespaceuri) {
15178      xmpnamespaceuri = namespaceuri || "http://jspdf.default.namespaceuri/"; //The namespace URI for an XMP name shall not be empty
15179
15180      xmpmetadata = metadata;
15181      this.internal.events.subscribe('postPutResources', function () {
15182        if (!xmpmetadata) {
15183          metadata_object_number = "";
15184        } else {
15185          var xmpmeta_beginning = '<x:xmpmeta xmlns:x="adobe:ns:meta/">';
15186          var rdf_beginning = '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="" xmlns:jspdf="' + xmpnamespaceuri + '"><jspdf:metadata>';
15187          var rdf_ending = '</jspdf:metadata></rdf:Description></rdf:RDF>';
15188          var xmpmeta_ending = '</x:xmpmeta>';
15189          var utf8_xmpmeta_beginning = unescape(encodeURIComponent(xmpmeta_beginning));
15190          var utf8_rdf_beginning = unescape(encodeURIComponent(rdf_beginning));
15191          var utf8_metadata = unescape(encodeURIComponent(xmpmetadata));
15192          var utf8_rdf_ending = unescape(encodeURIComponent(rdf_ending));
15193          var utf8_xmpmeta_ending = unescape(encodeURIComponent(xmpmeta_ending));
15194          var total_len = utf8_rdf_beginning.length + utf8_metadata.length + utf8_rdf_ending.length + utf8_xmpmeta_beginning.length + utf8_xmpmeta_ending.length;
15195          metadata_object_number = this.internal.newObject();
15196          this.internal.write('<< /Type /Metadata /Subtype /XML /Length ' + total_len + ' >>');
15197          this.internal.write('stream');
15198          this.internal.write(utf8_xmpmeta_beginning + utf8_rdf_beginning + utf8_metadata + utf8_rdf_ending + utf8_xmpmeta_ending);
15199          this.internal.write('endstream');
15200          this.internal.write('endobj');
15201        }
15202      });
15203      this.internal.events.subscribe('putCatalog', function () {
15204        if (metadata_object_number) {
15205          this.internal.write('/Metadata ' + metadata_object_number + ' 0 R');
15206        }
15207      });
15208      return this;
15209    };
15210  })(jsPDF.API);
15211
15212  /**
15213  * @name utf8
15214  * @module
15215  */
15216  (function (jsPDF, global) {
15217
15218    var jsPDFAPI = jsPDF.API;
15219    /**************************************************/
15220
15221    /* function : toHex                               */
15222
15223    /* comment : Replace str with a hex string.       */
15224
15225    /**************************************************/
15226
15227    function toHex(str) {
15228      var hex = '';
15229
15230      for (var i = 0; i < str.length; i++) {
15231        hex += '' + str.charCodeAt(i).toString(16);
15232      }
15233
15234      return hex;
15235    }
15236    /***************************************************************************************************/
15237
15238    /* function : pdfEscape16                                                                          */
15239
15240    /* comment : The character id of a 2-byte string is converted to a hexadecimal number by obtaining */
15241
15242    /*   the corresponding glyph id and width, and then adding padding to the string.                  */
15243
15244    /***************************************************************************************************/
15245
15246
15247    var pdfEscape16 = jsPDFAPI.pdfEscape16 = function (text, font) {
15248      var widths = font.metadata.Unicode.widths;
15249      var padz = ["", "0", "00", "000", "0000"];
15250      var ar = [""];
15251
15252      for (var i = 0, l = text.length, t; i < l; ++i) {
15253        t = font.metadata.characterToGlyph(text.charCodeAt(i));
15254        font.metadata.glyIdsUsed.push(t);
15255        font.metadata.toUnicode[t] = text.charCodeAt(i);
15256
15257        if (widths.indexOf(t) == -1) {
15258          widths.push(t);
15259          widths.push([parseInt(font.metadata.widthOfGlyph(t), 10)]);
15260        }
15261
15262        if (t == '0') {
15263          //Spaces are not allowed in cmap.
vendor: 10,467 bytes, lines 15264-15576
15264          return ar.join("");
15265        } else {
15266          t = t.toString(16);
15267          ar.push(padz[4 - t.length], t);
15268        }
15269      }
15270
15271      return ar.join("");
15272    };
15273
15274    var toUnicodeCmap = function toUnicodeCmap(map) {
15275      var code, codes, range, unicode, unicodeMap, _i, _len;
15276
15277      unicodeMap = '/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';
15278      codes = Object.keys(map).sort(function (a, b) {
15279        return a - b;
15280      });
15281      range = [];
15282
15283      for (_i = 0, _len = codes.length; _i < _len; _i++) {
15284        code = codes[_i];
15285
15286        if (range.length >= 100) {
15287          unicodeMap += "\n" + range.length + " beginbfchar\n" + range.join('\n') + "\nendbfchar";
15288          range = [];
15289        }
15290
15291        unicode = ('0000' + map[code].toString(16)).slice(-4);
15292        code = ('0000' + (+code).toString(16)).slice(-4);
15293        range.push("<" + code + "><" + unicode + ">");
15294      }
15295
15296      if (range.length) {
15297        unicodeMap += "\n" + range.length + " beginbfchar\n" + range.join('\n') + "\nendbfchar\n";
15298      }
15299
15300      unicodeMap += 'endcmap\nCMapName currentdict /CMap defineresource pop\nend\nend';
15301      return unicodeMap;
15302    };
15303
15304    var identityHFunction = function identityHFunction(font, out, newObject, putStream) {
15305      if (font.metadata instanceof jsPDF.API.TTFFont && font.encoding === 'Identity-H') {
15306        //Tag with Identity-H
15307        var widths = font.metadata.Unicode.widths;
15308        var data = font.metadata.subset.encode(font.metadata.glyIdsUsed, 1);
15309        var pdfOutput = data;
15310        var pdfOutput2 = "";
15311
15312        for (var i = 0; i < pdfOutput.length; i++) {
15313          pdfOutput2 += String.fromCharCode(pdfOutput[i]);
15314        }
15315
15316        var fontTable = newObject();
15317        putStream({
15318          data: pdfOutput2,
15319          addLength1: true
15320        });
15321        out('endobj');
15322        var cmap = newObject();
15323        var cmapData = toUnicodeCmap(font.metadata.toUnicode);
15324        putStream({
15325          data: cmapData,
15326          addLength1: true
15327        });
15328        out('endobj');
15329        var fontDescriptor = newObject();
15330        out('<<');
15331        out('/Type /FontDescriptor');
15332        out('/FontName /' + font.fontName);
15333        out('/FontFile2 ' + fontTable + ' 0 R');
15334        out('/FontBBox ' + jsPDF.API.PDFObject.convert(font.metadata.bbox));
15335        out('/Flags ' + font.metadata.flags);
15336        out('/StemV ' + font.metadata.stemV);
15337        out('/ItalicAngle ' + font.metadata.italicAngle);
15338        out('/Ascent ' + font.metadata.ascender);
15339        out('/Descent ' + font.metadata.decender);
15340        out('/CapHeight ' + font.metadata.capHeight);
15341        out('>>');
15342        out('endobj');
15343        var DescendantFont = newObject();
15344        out('<<');
15345        out('/Type /Font');
15346        out('/BaseFont /' + font.fontName);
15347        out('/FontDescriptor ' + fontDescriptor + ' 0 R');
15348        out('/W ' + jsPDF.API.PDFObject.convert(widths));
15349        out('/CIDToGIDMap /Identity');
15350        out('/DW 1000');
15351        out('/Subtype /CIDFontType2');
15352        out('/CIDSystemInfo');
15353        out('<<');
15354        out('/Supplement 0');
15355        out('/Registry (Adobe)');
15356        out('/Ordering (' + font.encoding + ')');
15357        out('>>');
15358        out('>>');
15359        out('endobj');
15360        font.objectNumber = newObject();
15361        out('<<');
15362        out('/Type /Font');
15363        out('/Subtype /Type0');
15364        out('/ToUnicode ' + cmap + ' 0 R');
15365        out('/BaseFont /' + font.fontName);
15366        out('/Encoding /' + font.encoding);
15367        out('/DescendantFonts [' + DescendantFont + ' 0 R]');
15368        out('>>');
15369        out('endobj');
15370        font.isAlreadyPutted = true;
15371      }
15372    };
15373
15374    jsPDFAPI.events.push(['putFont', function (args) {
15375      identityHFunction(args.font, args.out, args.newObject, args.putStream);
15376    }]);
15377
15378    var winAnsiEncodingFunction = function winAnsiEncodingFunction(font, out, newObject, putStream) {
15379      if (font.metadata instanceof jsPDF.API.TTFFont && font.encoding === 'WinAnsiEncoding') {
15380        //Tag with WinAnsi encoding
15381        var widths = font.metadata.Unicode.widths;
15382        var data = font.metadata.rawData;
15383        var pdfOutput = data;
15384        var pdfOutput2 = "";
15385
15386        for (var i = 0; i < pdfOutput.length; i++) {
15387          pdfOutput2 += String.fromCharCode(pdfOutput[i]);
15388        }
15389
15390        var fontTable = newObject();
15391        putStream({
15392          data: pdfOutput2,
15393          addLength1: true
15394        });
15395        out('endobj');
15396        var cmap = newObject();
15397        var cmapData = toUnicodeCmap(font.metadata.toUnicode);
15398        putStream({
15399          data: cmapData,
15400          addLength1: true
15401        });
15402        out('endobj');
15403        var fontDescriptor = newObject();
15404        out('<<');
15405        out('/Descent ' + font.metadata.decender);
15406        out('/CapHeight ' + font.metadata.capHeight);
15407        out('/StemV ' + font.metadata.stemV);
15408        out('/Type /FontDescriptor');
15409        out('/FontFile2 ' + fontTable + ' 0 R');
15410        out('/Flags 96');
15411        out('/FontBBox ' + jsPDF.API.PDFObject.convert(font.metadata.bbox));
15412        out('/FontName /' + font.fontName);
15413        out('/ItalicAngle ' + font.metadata.italicAngle);
15414        out('/Ascent ' + font.metadata.ascender);
15415        out('>>');
15416        out('endobj');
15417        font.objectNumber = newObject();
15418
15419        for (var i = 0; i < font.metadata.hmtx.widths.length; i++) {
15420          font.metadata.hmtx.widths[i] = parseInt(font.metadata.hmtx.widths[i] * (1000 / font.metadata.head.unitsPerEm)); //Change the width of Em units to Point units.
15421        }
15422
15423        out('<</Subtype/TrueType/Type/Font/ToUnicode ' + cmap + ' 0 R/BaseFont/' + font.fontName + '/FontDescriptor ' + fontDescriptor + ' 0 R' + '/Encoding/' + font.encoding + ' /FirstChar 29 /LastChar 255 /Widths ' + jsPDF.API.PDFObject.convert(font.metadata.hmtx.widths) + '>>');
15424        out('endobj');
15425        font.isAlreadyPutted = true;
15426      }
15427    };
15428
15429    jsPDFAPI.events.push(['putFont', function (args) {
15430      winAnsiEncodingFunction(args.font, args.out, args.newObject, args.putStream);
15431    }]);
15432
15433    var utf8TextFunction = function utf8TextFunction(args) {
15434      var text = args.text || '';
15435      var x = args.x;
15436      var y = args.y;
15437      var options = args.options || {};
15438      var mutex = args.mutex || {};
15439      var pdfEscape = mutex.pdfEscape;
15440      var activeFontKey = mutex.activeFontKey;
15441      var fonts = mutex.fonts;
15442      var key,
15443          fontSize = mutex.activeFontSize;
15444      var str = '',
15445          s = 0,
15446          cmapConfirm;
15447      var strText = '';
15448      var key = activeFontKey;
15449      var encoding = fonts[key].encoding;
15450
15451      if (fonts[key].encoding !== 'Identity-H') {
15452        return {
15453          text: text,
15454          x: x,
15455          y: y,
15456          options: options,
15457          mutex: mutex
15458        };
15459      }
15460      strText = text;
15461      key = activeFontKey;
15462
15463      if (Object.prototype.toString.call(text) === '[object Array]') {
15464        strText = text[0];
15465      }
15466
15467      for (s = 0; s < strText.length; s += 1) {
15468        if (fonts[key].metadata.hasOwnProperty('cmap')) {
15469          cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s].charCodeAt(0)];
15470          /*
15471          if (Object.prototype.toString.call(text) === '[object Array]') {
15472            var i = 0;
15473           // for (i = 0; i < text.length; i += 1) {
15474                if (Object.prototype.toString.call(text[s]) === '[object Array]') {
15475                    cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s][0].charCodeAt(0)]; //Make sure the cmap has the corresponding glyph id
15476                } else {
15477                    
15478                }
15479            //}
15480            
15481          } else {
15482            cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s].charCodeAt(0)]; //Make sure the cmap has the corresponding glyph id
15483          }*/
15484        }
15485
15486        if (!cmapConfirm) {
15487          if (strText[s].charCodeAt(0) < 256 && fonts[key].metadata.hasOwnProperty('Unicode')) {
15488            str += strText[s];
15489          } else {
15490            str += '';
15491          }
15492        } else {
15493          str += strText[s];
15494        }
15495      }
15496
15497      var result = '';
15498
15499      if (parseInt(key.slice(1)) < 14 || encoding === 'WinAnsiEncoding') {
15500        //For the default 13 font
15501        result = toHex(pdfEscape(str, key));
15502      } else if (encoding === 'Identity-H') {
15503        result = pdfEscape16(str, fonts[key]);
15504      }
15505
15506      mutex.isHex = true;
15507      return {
15508        text: result,
15509        x: x,
15510        y: y,
15511        options: options,
15512        mutex: mutex
15513      };
15514    };
15515
15516    var utf8EscapeFunction = function utf8EscapeFunction(parms) {
15517      var text = parms.text || '',
15518          x = parms.x,
15519          y = parms.y,
15520          options = parms.options,
15521          mutex = parms.mutex;
15522      var lang = options.lang;
15523      var tmpText = [];
15524      var args = {
15525        text: text,
15526        x: x,
15527        y: y,
15528        options: options,
15529        mutex: mutex
15530      };
15531
15532      if (Object.prototype.toString.call(text) === '[object Array]') {
15533        var i = 0;
15534
15535        for (i = 0; i < text.length; i += 1) {
15536          if (Object.prototype.toString.call(text[i]) === '[object Array]') {
15537            if (text[i].length === 3) {
15538              tmpText.push([utf8TextFunction(Object.assign({}, args, {
15539                text: text[i][0]
15540              })).text, text[i][1], text[i][2]]);
15541            } else {
15542              tmpText.push(utf8TextFunction(Object.assign({}, args, {
15543                text: text[i]
15544              })).text);
15545            }
15546          } else {
15547            tmpText.push(utf8TextFunction(Object.assign({}, args, {
15548              text: text[i]
15549            })).text);
15550          }
15551        }
15552
15553        parms.text = tmpText;
15554      } else {
15555        parms.text = utf8TextFunction(Object.assign({}, args, {
15556          text: text
15557        })).text;
15558      }
15559    };
15560
15561    jsPDFAPI.events.push(['postProcessText', utf8EscapeFunction]);
15562  })(jsPDF, typeof self !== "undefined" && self || typeof global !== "undefined" && global || typeof window !== "undefined" && window || Function("return this")());
15563
15564  /**
15565   * jsPDF virtual FileSystem functionality
15566   *
15567   * Licensed under the MIT License.
15568   * http://opensource.org/licenses/mit-license
15569   */
15570
15571  /**
15572  * Use the vFS to handle files
15573  * 
15574  * @name vFS
15575  * @module
15576  */
15577  (function (jsPDFAPI) {
15578
15579    var _initializeVFS = function _initializeVFS(instance) {
15580      if (typeof instance === "undefined") {
15581        return false;
15582      }
15583
15584      if (typeof instance.vFS === "undefined") {
15585        instance.vFS = {};
15586      }
15587
15588      return true;
15589    };
15590    /** 
15591    * Check if the file exists in the vFS
15592    * 
15593    * @name existsFileInVFS
15594    * @function 
15595    * @param {string} Possible filename in the vFS.
15596    * @returns {boolean}
15597    * @example
15598    * doc.existsFileInVFS("someFile.txt");
15599    */
15600
15601
15602    jsPDFAPI.existsFileInVFS = function (filename) {
15603      if (_initializeVFS(this.internal)) {
15604        return typeof this.internal.vFS[filename] !== "undefined";
15605      }
15606
15607      return false;
15608    };
15609    /**
15610    * Add a file to the vFS
15611    *
15612    * @name addFileToVFS
15613    * @function 
15614    * @param {string} filename The name of the file which should be added.
15615    * @param {string} filecontent The content of the file.
15616    * @returns {jsPDF}
15617    * @example
15618    * doc.addFileToVFS("someFile.txt", "BADFACE1");
15619    */
15620
15621
15622    jsPDFAPI.addFileToVFS = function (filename, filecontent) {
15623      _initializeVFS(this.internal);
15624
15625      this.internal.vFS[filename] = filecontent;
15626      return this;
15627    };
15628    /** 
15629    * Get the file from the vFS
15630    * 
15631    * @name getFileFromVFS
15632    * @function 
15633    * @param {string} The name of the file which gets requested.
15634    * @returns {string} 
15635    * @example
15636    * doc.getFileFromVFS("someFile.txt");
15637    */
15638
15639
15640    jsPDFAPI.getFileFromVFS = function (filename) {
15641      _initializeVFS(this.internal);
15642
15643      if (typeof this.internal.vFS[filename] !== "undefined") {
15644        return this.internal.vFS[filename];
15645      }
15646
15647      return null;
15648    };
15649  })(jsPDF.API);
15650
15651  /**
15652   * jsPDF addHTML PlugIn
15653   * Copyright (c) 2014 Diego Casorran
15654   *
15655   * Licensed under the MIT License.
15656   * http://opensource.org/licenses/mit-license
15657   */
15658  (function (jsPDFAPI) {
15659    /**
15660     * Renders an HTML element to canvas object which added to the PDF
15661     *
15662     * This feature requires [html2canvas](https://github.com/niklasvh/html2canvas)
15663     * or [rasterizeHTML](https://github.com/cburgmer/rasterizeHTML.js)
15664     *
15665     * @returns {jsPDF}
15666     * @name addHTML
15667     * @param element {Mixed} HTML Element, or anything supported by html2canvas.
15668     * @param x {Number} starting X coordinate in jsPDF instance's declared units.
15669     * @param y {Number} starting Y coordinate in jsPDF instance's declared units.
15670     * @param options {Object} Additional options, check the code below.
15671     * @param callback {Function} to call when the rendering has finished.
15672     * NOTE: Every parameter is optional except 'element' and 'callback', in such
15673     *       case the image is positioned at 0x0 covering the whole PDF document
15674     *       size. Ie, to easily take screenshots of webpages saving them to PDF.
15675     * @deprecated This is being replace with a vector-supporting API. See
15676     * [this link](https://cdn.rawgit.com/MrRio/jsPDF/master/examples/html2pdf/showcase_supported_html.html)
15677     */
15678
15679    jsPDFAPI.addHTML = function (element, x, y, options, callback) {
15680
15681      if (typeof html2canvas === 'undefined' && typeof rasterizeHTML === 'undefined') throw new Error('You need either ' + 'https://github.com/niklasvh/html2canvas' + ' or https://github.com/cburgmer/rasterizeHTML.js');
15682
15683      if (typeof x !== 'number') {
15684        options = x;
15685        callback = y;
15686      }
15687
15688      if (typeof options === 'function') {
15689        callback = options;
15690        options = null;
15691      }
15692
15693      if (typeof callback !== 'function') {
15694        callback = function callback() {};
15695      }
15696
15697      var I = this.internal,
15698          K = I.scaleFactor,
15699          W = I.pageSize.getWidth(),
15700          H = I.pageSize.getHeight();
15701      options = options || {};
15702
15703      options.onrendered = function (obj) {
15704        x = parseInt(x) || 0;
15705        y = parseInt(y) || 0;
15706        var dim = options.dim || {};
15707        var margin = Object.assign({
15708          top: 0,
15709          right: 0,
15710          bottom: 0,
15711          left: 0,
15712          useFor: 'content'
15713        }, options.margin);
15714        var h = dim.h || Math.min(H, obj.height / K);
15715        var w = dim.w || Math.min(W, obj.width / K) - x;
15716        var format = options.format || 'JPEG';
15717        var imageCompression = options.imageCompression || 'SLOW';
15718        var notFittingHeight = obj.height > H - margin.top - margin.bottom;
15719
15720        if (notFittingHeight && options.pagesplit) {
15721          var cropArea = function cropArea(parmObj, parmX, parmY, parmWidth, parmHeight) {
15722            var canvas = document.createElement('canvas');
15723            canvas.height = parmHeight;
15724            canvas.width = parmWidth;
15725            var ctx = canvas.getContext('2d');
15726            ctx.mozImageSmoothingEnabled = false;
15727            ctx.webkitImageSmoothingEnabled = false;
15728            ctx.msImageSmoothingEnabled = false;
15729            ctx.imageSmoothingEnabled = false;
15730            ctx.fillStyle = options.backgroundColor || '#ffffff';
15731            ctx.fillRect(0, 0, parmWidth, parmHeight);
15732            ctx.drawImage(parmObj, parmX, parmY, parmWidth, parmHeight, 0, 0, parmWidth, parmHeight);
15733            return canvas;
15734          };
15735
15736          var crop = function () {
15737            var cy = 0;
15738            var cx = 0;
15739            var position = {};
15740            var isOverWide = false;
15741            var width;
15742            var height;
15743
15744            while (1) {
15745              cx = 0;
15746              position.top = cy !== 0 ? margin.top : y;
15747              position.left = cy !== 0 ? margin.left : x;
15748              isOverWide = (W - margin.left - margin.right) * K < obj.width;
15749
15750              if (margin.useFor === "content") {
15751                if (cy === 0) {
15752                  width = Math.min((W - margin.left) * K, obj.width);
15753                  height = Math.min((H - margin.top) * K, obj.height - cy);
15754                } else {
15755                  width = Math.min(W * K, obj.width);
15756                  height = Math.min(H * K, obj.height - cy);
15757                  position.top = 0;
15758                }
15759              } else {
15760                width = Math.min((W - margin.left - margin.right) * K, obj.width);
15761                height = Math.min((H - margin.bottom - margin.top) * K, obj.height - cy);
15762              }
15763
15764              if (isOverWide) {
15765                while (1) {
15766                  if (margin.useFor === "content") {
15767                    if (cx === 0) {
15768                      width = Math.min((W - margin.left) * K, obj.width);
15769                    } else {
15770                      width = Math.min(W * K, obj.width - cx);
15771                      position.left = 0;
15772                    }
15773                  }
15774
15775                  var canvas = cropArea(obj, cx, cy, width, height);
15776                  var args = [canvas, position.left, position.top, canvas.width / K, canvas.height / K, format, null, imageCompression];
15777                  this.addImage.apply(this, args);
15778                  cx += width;
15779
15780                  if (cx >= obj.width) {
15781                    break;
15782                  }
15783
15784                  this.addPage();
15785                }
15786              } else {
15787                var canvas = cropArea(obj, 0, cy, width, height);
15788                var args = [canvas, position.left, position.top, canvas.width / K, canvas.height / K, format, null, imageCompression];
15789                this.addImage.apply(this, args);
15790              }
15791
15792              cy += height;
15793
15794              if (cy >= obj.height) {
15795                break;
15796              }
15797
15798              this.addPage();
15799            }
15800
15801            callback(w, cy, null, args);
15802          }.bind(this);
15803
15804          if (obj.nodeName === 'CANVAS') {
15805            var img = new Image();
15806            img.onload = crop;
15807            img.src = obj.toDataURL("image/png");
15808            obj = img;
15809          } else {
15810            crop();
15811          }
15812        } else {
15813          var alias = Math.random().toString(35);
15814          var args = [obj, x, y, w, h, format, alias, imageCompression];
15815          this.addImage.apply(this, args);
15816          callback(w, h, alias, args);
15817        }
15818      }.bind(this);
15819
15820      if (typeof html2canvas !== 'undefined' && !options.rstz) {
15821        return html2canvas(element, options);
15822      }
15823
15824      if (typeof rasterizeHTML !== 'undefined') {
15825        var meth = 'drawDocument';
15826
15827        if (typeof element === 'string') {
15828          meth = /^http/.test(element) ? 'drawURL' : 'drawHTML';
15829        }
15830
15831        options.width = options.width || W * K;
15832        return rasterizeHTML[meth](element, void 0, options).then(function (r) {
15833          options.onrendered(r.image);
15834        }, function (e) {
15835          callback(null, e);
15836        });
15837      }
15838
15839      return null;
15840    };
15841  })(jsPDF.API);
15842
15843  /**
15844   * jsPDF fromHTML plugin. BETA stage. API subject to change. Needs browser
15845   * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
15846   *               2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
15847   *               2014 Diego Casorran, https://github.com/diegocr
15848   *               2014 Daniel Husar, https://github.com/danielhusar
15849   *               2014 Wolfgang Gassler, https://github.com/woolfg
15850   *               2014 Steven Spungin, https://github.com/flamenco
15851   *
15852   * @license
15853   * 
15854   * ====================================================================
15855   */
15856  (function (jsPDFAPI) {
15857    var clone, _DrillForContent, FontNameDB, FontStyleMap, TextAlignMap, FontWeightMap, FloatMap, ClearMap, GetCSS, PurgeWhiteSpace, Renderer, ResolveFont, ResolveUnitedNumber, UnitedNumberMap, elementHandledElsewhere, images, loadImgs, checkForFooter, process, tableToJson;
15858
15859    clone = function () {
15860      return function (obj) {
15861        Clone.prototype = obj;
15862        return new Clone();
15863      };
15864
15865      function Clone() {}
15866    }();
15867
15868    PurgeWhiteSpace = function PurgeWhiteSpace(array) {
15869      var fragment, i, l, lTrimmed, r, rTrimmed, trailingSpace;
15870      i = 0;
15871      l = array.length;
15872      fragment = void 0;
15873      lTrimmed = false;
15874      rTrimmed = false;
15875
15876      while (!lTrimmed && i !== l) {
15877        fragment = array[i] = array[i].trimLeft();
15878
15879        if (fragment) {
15880          lTrimmed = true;
15881        }
15882
15883        i++;
15884      }
15885
15886      i = l - 1;
15887
15888      while (l && !rTrimmed && i !== -1) {
15889        fragment = array[i] = array[i].trimRight();
15890
15891        if (fragment) {
15892          rTrimmed = true;
15893        }
15894
15895        i--;
15896      }
15897
15898      r = /\s+$/g;
15899      trailingSpace = true;
15900      i = 0;
15901
15902      while (i !== l) {
15903        // Leave the line breaks intact
15904        if (array[i] != "\u2028") {
15905          fragment = array[i].replace(/\s+/g, " ");
15906
15907          if (trailingSpace) {
15908            fragment = fragment.trimLeft();
15909          }
15910
15911          if (fragment) {
15912            trailingSpace = r.test(fragment);
15913          }
15914
15915          array[i] = fragment;
15916        }
15917
15918        i++;
15919      }
15920
15921      return array;
15922    };
15923
15924    Renderer = function Renderer(pdf, x, y, settings) {
15925      this.pdf = pdf;
15926      this.x = x;
15927      this.y = y;
15928      this.settings = settings; //list of functions which are called after each element-rendering process
15929
15930      this.watchFunctions = [];
15931      this.init();
15932      return this;
15933    };
15934
15935    ResolveFont = function ResolveFont(css_font_family_string) {
15936      var name, part, parts;
15937      name = void 0;
15938      parts = css_font_family_string.split(",");
15939      part = parts.shift();
15940
15941      while (!name && part) {
15942        name = FontNameDB[part.trim().toLowerCase()];
15943        part = parts.shift();
15944      }
15945
15946      return name;
15947    };
15948
15949    ResolveUnitedNumber = function ResolveUnitedNumber(css_line_height_string) {
15950      //IE8 issues
15951      css_line_height_string = css_line_height_string === "auto" ? "0px" : css_line_height_string;
15952
15953      if (css_line_height_string.indexOf("em") > -1 && !isNaN(Number(css_line_height_string.replace("em", "")))) {
15954        css_line_height_string = Number(css_line_height_string.replace("em", "")) * 18.719 + "px";
15955      }
15956
15957      if (css_line_height_string.indexOf("pt") > -1 && !isNaN(Number(css_line_height_string.replace("pt", "")))) {
15958        css_line_height_string = Number(css_line_height_string.replace("pt", "")) * 1.333 + "px";
15959      }
15960
15961      var normal, undef, value;
15962      undef = void 0;
15963      normal = 16.00;
15964      value = UnitedNumberMap[css_line_height_string];
15965
15966      if (value) {
15967        return value;
15968      }
15969
15970      value = {
15971        "xx-small": 9,
15972        "x-small": 11,
15973        small: 13,
15974        medium: 16,
15975        large: 19,
15976        "x-large": 23,
15977        "xx-large": 28,
15978        auto: 0
15979      }[css_line_height_string];
15980
15981      if (value !== undef) {
15982        return UnitedNumberMap[css_line_height_string] = value / normal;
15983      }
15984
15985      if (value = parseFloat(css_line_height_string)) {
15986        return UnitedNumberMap[css_line_height_string] = value / normal;
15987      }
15988
15989      value = css_line_height_string.match(/([\d\.]+)(px)/);
15990
15991      if (Array.isArray(value) && value.length === 3) {
15992        return UnitedNumberMap[css_line_height_string] = parseFloat(value[1]) / normal;
15993      }
15994
15995      return UnitedNumberMap[css_line_height_string] = 1;
15996    };
15997
15998    GetCSS = function GetCSS(element) {
15999      var css, tmp, computedCSSElement;
16000
16001      computedCSSElement = function (el) {
16002        var compCSS;
16003
16004        compCSS = function (el) {
16005          if (document.defaultView && document.defaultView.getComputedStyle) {
16006            return document.defaultView.getComputedStyle(el, null);
16007          } else if (el.currentStyle) {
16008            return el.currentStyle;
16009          } else {
16010            return el.style;
16011          }
16012        }(el);
16013
16014        return function (prop) {
16015          prop = prop.replace(/-\D/g, function (match) {
16016            return match.charAt(1).toUpperCase();
16017          });
16018          return compCSS[prop];
16019        };
16020      }(element);
16021
16022      css = {};
16023      tmp = void 0;
16024      css["font-family"] = ResolveFont(computedCSSElement("font-family")) || "times";
16025      css["font-style"] = FontStyleMap[computedCSSElement("font-style")] || "normal";
16026      css["text-align"] = TextAlignMap[computedCSSElement("text-align")] || "left";
16027      tmp = FontWeightMap[computedCSSElement("font-weight")] || "normal";
16028
16029      if (tmp === "bold") {
16030        if (css["font-style"] === "normal") {
16031          css["font-style"] = tmp;
16032        } else {
16033          css["font-style"] = tmp + css["font-style"];
16034        }
16035      }
16036
16037      css["font-size"] = ResolveUnitedNumber(computedCSSElement("font-size")) || 1;
16038      css["line-height"] = ResolveUnitedNumber(computedCSSElement("line-height")) || 1;
16039      css["display"] = computedCSSElement("display") === "inline" ? "inline" : "block";
16040      tmp = css["display"] === "block";
16041      css["margin-top"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-top")) || 0;
16042      css["margin-bottom"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-bottom")) || 0;
16043      css["padding-top"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-top")) || 0;
16044      css["padding-bottom"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-bottom")) || 0;
16045      css["margin-left"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-left")) || 0;
16046      css["margin-right"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-right")) || 0;
16047      css["padding-left"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-left")) || 0;
16048      css["padding-right"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-right")) || 0;
16049      css["page-break-before"] = computedCSSElement("page-break-before") || "auto"; //float and clearing of floats
16050
16051      css["float"] = FloatMap[computedCSSElement("cssFloat")] || "none";
16052      css["clear"] = ClearMap[computedCSSElement("clear")] || "none";
16053      css["color"] = computedCSSElement("color");
16054      return css;
16055    };
16056
16057    elementHandledElsewhere = function elementHandledElsewhere(element, renderer, elementHandlers) {
16058      var handlers, i, isHandledElsewhere, l, classNames;
16059      isHandledElsewhere = false;
16060      i = void 0;
16061      l = void 0;
16062      handlers = elementHandlers["#" + element.id];
16063
16064      if (handlers) {
16065        if (typeof handlers === "function") {
16066          isHandledElsewhere = handlers(element, renderer);
16067        } else {
16068          i = 0;
16069          l = handlers.length;
16070
16071          while (!isHandledElsewhere && i !== l) {
16072            isHandledElsewhere = handlers[i](element, renderer);
16073            i++;
16074          }
16075        }
16076      }
16077
16078      handlers = elementHandlers[element.nodeName];
16079
16080      if (!isHandledElsewhere && handlers) {
16081        if (typeof handlers === "function") {
16082          isHandledElsewhere = handlers(element, renderer);
16083        } else {
16084          i = 0;
16085          l = handlers.length;
16086
16087          while (!isHandledElsewhere && i !== l) {
16088            isHandledElsewhere = handlers[i](element, renderer);
16089            i++;
16090          }
16091        }
16092      } // Try class names
16093
16094
16095      classNames = typeof element.className === 'string' ? element.className.split(' ') : [];
16096
16097      for (i = 0; i < classNames.length; i++) {
16098        handlers = elementHandlers['.' + classNames[i]];
16099
16100        if (!isHandledElsewhere && handlers) {
16101          if (typeof handlers === "function") {
16102            isHandledElsewhere = handlers(element, renderer);
16103          } else {
16104            i = 0;
16105            l = handlers.length;
16106
16107            while (!isHandledElsewhere && i !== l) {
16108              isHandledElsewhere = handlers[i](element, renderer);
16109              i++;
16110            }
16111          }
16112        }
16113      }
16114
16115      return isHandledElsewhere;
16116    };
16117
16118    tableToJson = function tableToJson(table, renderer) {
16119      var data, headers, i, j, rowData, tableRow, table_obj, table_with, cell, l;
16120      data = [];
16121      headers = [];
16122      i = 0;
16123      l = table.rows[0].cells.length;
16124      table_with = table.clientWidth;
16125
16126      while (i < l) {
16127        cell = table.rows[0].cells[i];
16128        headers[i] = {
16129          name: cell.textContent.toLowerCase().replace(/\s+/g, ''),
16130          prompt: cell.textContent.replace(/\r?\n/g, ''),
16131          width: cell.clientWidth / table_with * renderer.pdf.internal.pageSize.getWidth()
16132        };
16133        i++;
16134      }
16135
16136      i = 1;
16137
16138      while (i < table.rows.length) {
16139        tableRow = table.rows[i];
16140        rowData = {};
16141        j = 0;
16142
16143        while (j < tableRow.cells.length) {
16144          rowData[headers[j].name] = tableRow.cells[j].textContent.replace(/\r?\n/g, '');
16145          j++;
16146        }
16147
16148        data.push(rowData);
16149        i++;
16150      }
16151
16152      return table_obj = {
16153        rows: data,
16154        headers: headers
16155      };
16156    };
16157
16158    var SkipNode = {
16159      SCRIPT: 1,
16160      STYLE: 1,
16161      NOSCRIPT: 1,
16162      OBJECT: 1,
16163      EMBED: 1,
16164      SELECT: 1
16165    };
16166    var listCount = 1;
16167
16168    _DrillForContent = function DrillForContent(element, renderer, elementHandlers) {
16169      var cn, cns, fragmentCSS, i, isBlock, l, table2json, cb;
16170      cns = element.childNodes;
16171      cn = void 0;
16172      fragmentCSS = GetCSS(element);
16173      isBlock = fragmentCSS.display === "block";
16174
16175      if (isBlock) {
16176        renderer.setBlockBoundary();
16177        renderer.setBlockStyle(fragmentCSS);
16178      }
16179      i = 0;
16180      l = cns.length;
16181
16182      while (i < l) {
16183        cn = cns[i];
16184
16185        if (_typeof(cn) === "object") {
16186          //execute all watcher functions to e.g. reset floating
16187          renderer.executeWatchFunctions(cn);
16188          /*** HEADER rendering **/
16189
16190          if (cn.nodeType === 1 && cn.nodeName === 'HEADER') {
16191            var header = cn; //store old top margin
16192
16193            var oldMarginTop = renderer.pdf.margins_doc.top; //subscribe for new page event and render header first on every page
16194
16195            renderer.pdf.internal.events.subscribe('addPage', function (pageInfo) {
16196              //set current y position to old margin
16197              renderer.y = oldMarginTop; //render all child nodes of the header element
16198
16199              _DrillForContent(header, renderer, elementHandlers); //set margin to old margin + rendered header + 10 space to prevent overlapping
16200              //important for other plugins (e.g. table) to start rendering at correct position after header
16201
16202
16203              renderer.pdf.margins_doc.top = renderer.y + 10;
16204              renderer.y += 10;
16205            }, false);
16206          }
16207
16208          if (cn.nodeType === 8 && cn.nodeName === "#comment") {
16209            if (~cn.textContent.indexOf("ADD_PAGE")) {
16210              renderer.pdf.addPage();
16211              renderer.y = renderer.pdf.margins_doc.top;
16212            }
16213          } else if (cn.nodeType === 1 && !SkipNode[cn.nodeName]) {
16214            /*** IMAGE RENDERING ***/
16215            var cached_image;
16216
16217            if (cn.nodeName === "IMG") {
16218              var url = cn.getAttribute("src");
16219              cached_image = images[renderer.pdf.sHashCode(url) || url];
16220            }
16221
16222            if (cached_image) {
16223              if (renderer.pdf.internal.pageSize.getHeight() - renderer.pdf.margins_doc.bottom < renderer.y + cn.height && renderer.y > renderer.pdf.margins_doc.top) {
16224                renderer.pdf.addPage();
16225                renderer.y = renderer.pdf.margins_doc.top; //check if we have to set back some values due to e.g. header rendering for new page
16226
16227                renderer.executeWatchFunctions(cn);
16228              }
16229
16230              var imagesCSS = GetCSS(cn);
16231              var imageX = renderer.x;
16232              var fontToUnitRatio = 12 / renderer.pdf.internal.scaleFactor; //define additional paddings, margins which have to be taken into account for margin calculations
16233
16234              var additionalSpaceLeft = (imagesCSS["margin-left"] + imagesCSS["padding-left"]) * fontToUnitRatio;
16235              var additionalSpaceRight = (imagesCSS["margin-right"] + imagesCSS["padding-right"]) * fontToUnitRatio;
16236              var additionalSpaceTop = (imagesCSS["margin-top"] + imagesCSS["padding-top"]) * fontToUnitRatio;
16237              var additionalSpaceBottom = (imagesCSS["margin-bottom"] + imagesCSS["padding-bottom"]) * fontToUnitRatio; //if float is set to right, move the image to the right border
16238              //add space if margin is set
16239
16240              if (imagesCSS['float'] !== undefined && imagesCSS['float'] === 'right') {
16241                imageX += renderer.settings.width - cn.width - additionalSpaceRight;
16242              } else {
16243                imageX += additionalSpaceLeft;
16244              }
16245
16246              renderer.pdf.addImage(cached_image, imageX, renderer.y + additionalSpaceTop, cn.width, cn.height);
16247              cached_image = undefined; //if the float prop is specified we have to float the text around the image
16248
16249              if (imagesCSS['float'] === 'right' || imagesCSS['float'] === 'left') {
16250                //add functiont to set back coordinates after image rendering
16251                renderer.watchFunctions.push(function (diffX, thresholdY, diffWidth, el) {
16252                  //undo drawing box adaptions which were set by floating
16253                  if (renderer.y >= thresholdY) {
16254                    renderer.x += diffX;
16255                    renderer.settings.width += diffWidth;
16256                    return true;
16257                  } else if (el && el.nodeType === 1 && !SkipNode[el.nodeName] && renderer.x + el.width > renderer.pdf.margins_doc.left + renderer.pdf.margins_doc.width) {
16258                    renderer.x += diffX;
16259                    renderer.y = thresholdY;
16260                    renderer.settings.width += diffWidth;
16261                    return true;
16262                  } else {
16263                    return false;
16264                  }
16265                }.bind(this, imagesCSS['float'] === 'left' ? -cn.width - additionalSpaceLeft - additionalSpaceRight : 0, renderer.y + cn.height + additionalSpaceTop + additionalSpaceBottom, cn.width)); //reset floating by clear:both divs
16266                //just set cursorY after the floating element
16267
16268                renderer.watchFunctions.push(function (yPositionAfterFloating, pages, el) {
16269                  if (renderer.y < yPositionAfterFloating && pages === renderer.pdf.internal.getNumberOfPages()) {
16270                    if (el.nodeType === 1 && GetCSS(el).clear === 'both') {
16271                      renderer.y = yPositionAfterFloating;
16272                      return true;
16273                    } else {
16274                      return false;
16275                    }
16276                  } else {
16277                    return true;
16278                  }
16279                }.bind(this, renderer.y + cn.height, renderer.pdf.internal.getNumberOfPages())); //if floating is set we decrease the available width by the image width
16280
16281                renderer.settings.width -= cn.width + additionalSpaceLeft + additionalSpaceRight; //if left just add the image width to the X coordinate
16282
16283                if (imagesCSS['float'] === 'left') {
16284                  renderer.x += cn.width + additionalSpaceLeft + additionalSpaceRight;
16285                }
16286              } else {
16287                //if no floating is set, move the rendering cursor after the image height
16288                renderer.y += cn.height + additionalSpaceTop + additionalSpaceBottom;
16289              }
16290              /*** TABLE RENDERING ***/
16291
16292            } else if (cn.nodeName === "TABLE") {
16293              table2json = tableToJson(cn, renderer);
16294              renderer.y += 10;
16295              renderer.pdf.table(renderer.x, renderer.y, table2json.rows, table2json.headers, {
16296                autoSize: false,
16297                printHeaders: elementHandlers.printHeaders,
16298                margins: renderer.pdf.margins_doc,
16299                css: GetCSS(cn)
16300              });
16301              renderer.y = renderer.pdf.lastCellPos.y + renderer.pdf.lastCellPos.h + 20;
16302            } else if (cn.nodeName === "OL" || cn.nodeName === "UL") {
16303              listCount = 1;
16304
16305              if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
16306                _DrillForContent(cn, renderer, elementHandlers);
16307              }
16308
16309              renderer.y += 10;
16310            } else if (cn.nodeName === "LI") {
16311              var temp = renderer.x;
16312              renderer.x += 20 / renderer.pdf.internal.scaleFactor;
16313              renderer.y += 3;
16314
16315              if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
16316                _DrillForContent(cn, renderer, elementHandlers);
16317              }
16318
16319              renderer.x = temp;
16320            } else if (cn.nodeName === "BR") {
16321              renderer.y += fragmentCSS["font-size"] * renderer.pdf.internal.scaleFactor;
16322              renderer.addText("\u2028", clone(fragmentCSS));
16323            } else {
16324              if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
16325                _DrillForContent(cn, renderer, elementHandlers);
16326              }
16327            }
16328          } else if (cn.nodeType === 3) {
16329            var value = cn.nodeValue;
16330
16331            if (cn.nodeValue && cn.parentNode.nodeName === "LI") {
16332              if (cn.parentNode.parentNode.nodeName === "OL") {
16333                value = listCount++ + '. ' + value;
16334              } else {
16335                var fontSize = fragmentCSS["font-size"];
16336                var offsetX = (3 - fontSize * 0.75) * renderer.pdf.internal.scaleFactor;
16337                var offsetY = fontSize * 0.75 * renderer.pdf.internal.scaleFactor;
16338                var radius = fontSize * 1.74 / renderer.pdf.internal.scaleFactor;
16339
16340                cb = function cb(x, y) {
16341                  this.pdf.circle(x + offsetX, y + offsetY, radius, 'FD');
16342                };
16343              }
16344            } // Only add the text if the text node is in the body element
16345            // Add compatibility with IE11
16346
16347
16348            if (!!(cn.ownerDocument.body.compareDocumentPosition(cn) & 16)) {
16349              renderer.addText(value, fragmentCSS);
16350            }
16351          } else if (typeof cn === "string") {
16352            renderer.addText(cn, fragmentCSS);
16353          }
16354        }
16355
16356        i++;
16357      }
16358
16359      elementHandlers.outY = renderer.y;
16360
16361      if (isBlock) {
16362        return renderer.setBlockBoundary(cb);
16363      }
16364    };
16365
16366    images = {};
16367
16368    loadImgs = function loadImgs(element, renderer, elementHandlers, cb) {
16369      var imgs = element.getElementsByTagName('img'),
16370          l = imgs.length,
16371          found_images,
16372          x = 0;
16373
16374      function done() {
16375        renderer.pdf.internal.events.publish('imagesLoaded');
16376        cb(found_images);
16377      }
16378
16379      function loadImage(url, width, height) {
16380        if (!url) return;
16381        var img = new Image();
16382        found_images = ++x;
16383        img.crossOrigin = '';
16384
16385        img.onerror = img.onload = function () {
16386          if (img.complete) {
16387            //to support data urls in images, set width and height
16388            //as those values are not recognized automatically
16389            if (img.src.indexOf('data:image/') === 0) {
16390              img.width = width || img.width || 0;
16391              img.height = height || img.height || 0;
16392            } //if valid image add to known images array
16393
16394
16395            if (img.width + img.height) {
16396              var hash = renderer.pdf.sHashCode(url) || url;
16397              images[hash] = images[hash] || img;
16398            }
16399          }
16400
16401          if (! --x) {
16402            done();
16403          }
16404        };
16405
16406        img.src = url;
16407      }
16408
16409      while (l--) {
16410        loadImage(imgs[l].getAttribute("src"), imgs[l].width, imgs[l].height);
16411      }
16412
16413      return x || done();
16414    };
16415
16416    checkForFooter = function checkForFooter(elem, renderer, elementHandlers) {
16417      //check if we can found a <footer> element
16418      var footer = elem.getElementsByTagName("footer");
16419
16420      if (footer.length > 0) {
16421        footer = footer[0]; //bad hack to get height of footer
16422        //creat dummy out and check new y after fake rendering
16423
16424        var oldOut = renderer.pdf.internal.write;
16425        var oldY = renderer.y;
16426
16427        renderer.pdf.internal.write = function () {};
16428
16429        _DrillForContent(footer, renderer, elementHandlers);
16430
16431        var footerHeight = Math.ceil(renderer.y - oldY) + 5;
16432        renderer.y = oldY;
16433        renderer.pdf.internal.write = oldOut; //add 20% to prevent overlapping
16434
16435        renderer.pdf.margins_doc.bottom += footerHeight; //Create function render header on every page
16436
16437        var renderFooter = function renderFooter(pageInfo) {
16438          var pageNumber = pageInfo !== undefined ? pageInfo.pageNumber : 1; //set current y position to old margin
16439
16440          var oldPosition = renderer.y; //render all child nodes of the header element
16441
16442          renderer.y = renderer.pdf.internal.pageSize.getHeight() - renderer.pdf.margins_doc.bottom;
16443          renderer.pdf.margins_doc.bottom -= footerHeight; //check if we have to add page numbers
16444
16445          var spans = footer.getElementsByTagName('span');
16446
16447          for (var i = 0; i < spans.length; ++i) {
16448            //if we find some span element with class pageCounter, set the page
16449            if ((" " + spans[i].className + " ").replace(/[\n\t]/g, " ").indexOf(" pageCounter ") > -1) {
16450              spans[i].innerHTML = pageNumber;
16451            } //if we find some span element with class totalPages, set a variable which is replaced after rendering of all pages
16452
16453
16454            if ((" " + spans[i].className + " ").replace(/[\n\t]/g, " ").indexOf(" totalPages ") > -1) {
16455              spans[i].innerHTML = '###jsPDFVarTotalPages###';
16456            }
16457          } //render footer content
16458
16459
16460          _DrillForContent(footer, renderer, elementHandlers); //set bottom margin to previous height including the footer height
16461
16462
16463          renderer.pdf.margins_doc.bottom += footerHeight; //important for other plugins (e.g. table) to start rendering at correct position after header
16464
16465          renderer.y = oldPosition;
16466        }; //check if footer contains totalPages which should be replace at the disoposal of the document
16467
16468
16469        var spans = footer.getElementsByTagName('span');
16470
16471        for (var i = 0; i < spans.length; ++i) {
16472          if ((" " + spans[i].className + " ").replace(/[\n\t]/g, " ").indexOf(" totalPages ") > -1) {
16473            renderer.pdf.internal.events.subscribe('htmlRenderingFinished', renderer.pdf.putTotalPages.bind(renderer.pdf, '###jsPDFVarTotalPages###'), true);
16474          }
16475        } //register event to render footer on every new page
16476
16477
16478        renderer.pdf.internal.events.subscribe('addPage', renderFooter, false); //render footer on first page
16479
16480        renderFooter(); //prevent footer rendering
16481
16482        SkipNode['FOOTER'] = 1;
16483      }
16484    };
16485
16486    process = function process(pdf, element, x, y, settings, callback) {
16487      if (!element) return false;
16488      if (typeof element !== "string" && !element.parentNode) element = '' + element.innerHTML;
16489
16490      if (typeof element === "string") {
16491        element = function (element) {
16492          var $frame, $hiddendiv, framename, visuallyhidden;
16493          framename = "jsPDFhtmlText" + Date.now().toString() + (Math.random() * 1000).toFixed(0);
16494          visuallyhidden = "position: absolute !important;" + "clip: rect(1px 1px 1px 1px); /* IE6, IE7 */" + "clip: rect(1px, 1px, 1px, 1px);" + "padding:0 !important;" + "border:0 !important;" + "height: 1px !important;" + "width: 1px !important; " + "top:auto;" + "left:-100px;" + "overflow: hidden;";
16495          $hiddendiv = document.createElement('div');
16496          $hiddendiv.style.cssText = visuallyhidden;
16497          $hiddendiv.innerHTML = "<iframe style=\"height:1px;width:1px\" name=\"" + framename + "\" />";
16498          document.body.appendChild($hiddendiv);
16499          $frame = window.frames[framename];
16500          $frame.document.open();
16501          $frame.document.writeln(element);
16502          $frame.document.close();
16503          return $frame.document.body;
16504        }(element.replace(/<\/?script[^>]*?>/gi, ''));
16505      }
16506
16507      var r = new Renderer(pdf, x, y, settings),
16508          out; // 1. load images
16509      // 2. prepare optional footer elements
16510      // 3. render content
16511
16512      loadImgs.call(this, element, r, settings.elementHandlers, function (found_images) {
16513        checkForFooter(element, r, settings.elementHandlers);
16514
16515        _DrillForContent(element, r, settings.elementHandlers); //send event dispose for final taks (e.g. footer totalpage replacement)
16516
16517
16518        r.pdf.internal.events.publish('htmlRenderingFinished');
16519        out = r.dispose();
16520        if (typeof callback === 'function') callback(out);else if (found_images) console.error('jsPDF Warning: rendering issues? provide a callback to fromHTML!');
16521      });
16522      return out || {
16523        x: r.x,
16524        y: r.y
16525      };
16526    };
16527
16528    Renderer.prototype.init = function () {
16529      this.paragraph = {
16530        text: [],
16531        style: []
16532      };
16533      return this.pdf.internal.write("q");
16534    };
16535
16536    Renderer.prototype.dispose = function () {
16537      this.pdf.internal.write("Q");
16538      return {
16539        x: this.x,
16540        y: this.y,
16541        ready: true
16542      };
16543    };
16543 //Checks if we have to execute some watcher functions
16544    //e.g. to end text floating around an image
16545
16546
16547    Renderer.prototype.executeWatchFunctions = function (el) {
16548      var ret = false;
16549      var narray = [];
16550
16551      if (this.watchFunctions.length > 0) {
16552        for (var i = 0; i < this.watchFunctions.length; ++i) {
16553          if (this.watchFunctions[i](el) === true) {
16554            ret = true;
16555          } else {
16556            narray.push(this.watchFunctions[i]);
16557          }
16558        }
16559
16560        this.watchFunctions = narray;
16561      }
16562
16563      return ret;
16564    };
16565
16566    Renderer.prototype.splitFragmentsIntoLines = function (fragments, styles) {
16567      var currentLineLength, defaultFontSize, ff, fontMetrics, fontMetricsCache, fragment, fragmentChopped, fragmentLength, fragmentSpecificMetrics, fs, k, line, lines, maxLineLength, style;
16568      defaultFontSize = 12;
16569      k = this.pdf.internal.scaleFactor;
16570      fontMetricsCache = {};
16571      ff = void 0;
16572      fs = void 0;
16573      fontMetrics = void 0;
16574      fragment = void 0;
16575      style = void 0;
16576      fragmentSpecificMetrics = void 0;
16577      fragmentLength = void 0;
16578      fragmentChopped = void 0;
16579      line = [];
16580      lines = [line];
16581      currentLineLength = 0;
16582      maxLineLength = this.settings.width;
16583
16584      while (fragments.length) {
16585        fragment = fragments.shift();
16586        style = styles.shift();
16587
16588        if (fragment) {
16589          ff = style["font-family"];
16590          fs = style["font-style"];
16591          fontMetrics = fontMetricsCache[ff + fs];
16592
16593          if (!fontMetrics) {
16594            fontMetrics = this.pdf.internal.getFont(ff, fs).metadata.Unicode;
16595            fontMetricsCache[ff + fs] = fontMetrics;
16596          }
16597
16598          fragmentSpecificMetrics = {
16599            widths: fontMetrics.widths,
16600            kerning: fontMetrics.kerning,
16601            fontSize: style["font-size"] * defaultFontSize,
16602            textIndent: currentLineLength
16603          };
16604          fragmentLength = this.pdf.getStringUnitWidth(fragment, fragmentSpecificMetrics) * fragmentSpecificMetrics.fontSize / k;
16605
16606          if (fragment == "\u2028") {
16607            line = [];
16608            lines.push(line);
16609          } else if (currentLineLength + fragmentLength > maxLineLength) {
16610            fragmentChopped = this.pdf.splitTextToSize(fragment, maxLineLength, fragmentSpecificMetrics);
16611            line.push([fragmentChopped.shift(), style]);
16612
16613            while (fragmentChopped.length) {
16614              line = [[fragmentChopped.shift(), style]];
16615              lines.push(line);
16616            }
16617
16618            currentLineLength = this.pdf.getStringUnitWidth(line[0][0], fragmentSpecificMetrics) * fragmentSpecificMetrics.fontSize / k;
16619          } else {
16620            line.push([fragment, style]);
16621            currentLineLength += fragmentLength;
16622          }
16623        }
16624      } //if text alignment was set, set margin/indent of each line
16625
16626
16627      if (style['text-align'] !== undefined && (style['text-align'] === 'center' || style['text-align'] === 'right' || style['text-align'] === 'justify')) {
16628        for (var i = 0; i < lines.length; ++i) {
16629          var length = this.pdf.getStringUnitWidth(lines[i][0][0], fragmentSpecificMetrics) * fragmentSpecificMetrics.fontSize / k; //if there is more than on line we have to clone the style object as all lines hold a reference on this object
16630
16631          if (i > 0) {
16632            lines[i][0][1] = clone(lines[i][0][1]);
16633          }
16634
16635          var space = maxLineLength - length;
16636
16637          if (style['text-align'] === 'right') {
16638            lines[i][0][1]['margin-left'] = space; //if alignment is not right, it has to be center so split the space to the left and the right
16639          } else if (style['text-align'] === 'center') {
16640            lines[i][0][1]['margin-left'] = space / 2; //if justify was set, calculate the word spacing and define in by using the css property
16641          } else if (style['text-align'] === 'justify') {
16642            var countSpaces = lines[i][0][0].split(' ').length - 1;
16643            lines[i][0][1]['word-spacing'] = space / countSpaces; //ignore the last line in justify mode
16644
16645            if (i === lines.length - 1) {
16646              lines[i][0][1]['word-spacing'] = 0;
16647            }
16648          }
16649        }
16650      }
16651
16652      return lines;
16653    };
16654
16655    Renderer.prototype.RenderTextFragment = function (text, style) {
16656      var defaultFontSize, font, maxLineHeight;
16657      maxLineHeight = 0;
16658      defaultFontSize = 12;
16659
16660      if (this.pdf.internal.pageSize.getHeight() - this.pdf.margins_doc.bottom < this.y + this.pdf.internal.getFontSize()) {
16661        this.pdf.internal.write("ET", "Q");
16662        this.pdf.addPage();
16663        this.y = this.pdf.margins_doc.top;
16664        this.pdf.internal.write("q", "BT", this.getPdfColor(style.color), this.pdf.internal.getCoordinateString(this.x), this.pdf.internal.getVerticalCoordinateString(this.y), "Td"); //move cursor by one line on new page
16665
16666        maxLineHeight = Math.max(maxLineHeight, style["line-height"], style["font-size"]);
16667        this.pdf.internal.write(0, (-1 * defaultFontSize * maxLineHeight).toFixed(2), "Td");
16668      }
16669
16670      font = this.pdf.internal.getFont(style["font-family"], style["font-style"]); // text color
16671
16672      var pdfTextColor = this.getPdfColor(style["color"]);
16673
16674      if (pdfTextColor !== this.lastTextColor) {
16675        this.pdf.internal.write(pdfTextColor);
16676        this.lastTextColor = pdfTextColor;
16677      } //set the word spacing for e.g. justify style
16678
16679
16680      if (style['word-spacing'] !== undefined && style['word-spacing'] > 0) {
16681        this.pdf.internal.write(style['word-spacing'].toFixed(2), "Tw");
16682      }
16683
16684      this.pdf.internal.write("/" + font.id, (defaultFontSize * style["font-size"]).toFixed(2), "Tf", "(" + this.pdf.internal.pdfEscape(text) + ") Tj"); //set the word spacing back to neutral => 0
16685
16686      if (style['word-spacing'] !== undefined) {
16687        this.pdf.internal.write(0, "Tw");
16688      }
16689    }; // Accepts #FFFFFF, rgb(int,int,int), or CSS Color Name
16690
16691
16692    Renderer.prototype.getPdfColor = function (style) {
16693      var textColor;
16694      var r, g, b;
16695      var rx = /rgb\s*\(\s*(\d+),\s*(\d+),\s*(\d+\s*)\)/;
16696      var m = rx.exec(style);
16697
16698      if (m != null) {
16699        r = parseInt(m[1]);
16700        g = parseInt(m[2]);
16701        b = parseInt(m[3]);
16702      } else {
16703        if (typeof style === "string" && style.charAt(0) != '#') {
16704          var rgbColor = new RGBColor(style);
16705
16706          if (rgbColor.ok) {
16707            style = rgbColor.toHex();
16708          } else {
16709            style = '#000000';
16710          }
16711        }
16712
16713        r = style.substring(1, 3);
16714        r = parseInt(r, 16);
16715        g = style.substring(3, 5);
16716        g = parseInt(g, 16);
16717        b = style.substring(5, 7);
16718        b = parseInt(b, 16);
16719      }
16720
16721      if (typeof r === 'string' && /^#[0-9A-Fa-f]{6}$/.test(r)) {
16722        var hex = parseInt(r.substr(1), 16);
16723        r = hex >> 16 & 255;
16724        g = hex >> 8 & 255;
16725        b = hex & 255;
16726      }
16727
16728      var f3 = this.f3;
16729
16730      if (r === 0 && g === 0 && b === 0 || typeof g === 'undefined') {
16731        textColor = f3(r / 255) + ' g';
16732      } else {
16733        textColor = [f3(r / 255), f3(g / 255), f3(b / 255), 'rg'].join(' ');
16734      }
16735
16736      return textColor;
16737    };
16738
16739    Renderer.prototype.f3 = function (number) {
16740      return number.toFixed(3); // Ie, %.3f
16741    }, Renderer.prototype.renderParagraph = function (cb) {
16742      var blockstyle, defaultFontSize, fontToUnitRatio, fragments, i, l, line, lines, maxLineHeight, out, paragraphspacing_after, paragraphspacing_before, priorblockstyle, styles, fontSize;
16743      fragments = PurgeWhiteSpace(this.paragraph.text);
16744      styles = this.paragraph.style;
16745      blockstyle = this.paragraph.blockstyle;
16746      priorblockstyle = this.paragraph.priorblockstyle || {};
16747      this.paragraph = {
16748        text: [],
16749        style: [],
16750        blockstyle: {},
16751        priorblockstyle: blockstyle
16752      };
16753
16754      if (!fragments.join("").trim()) {
16755        return;
16756      }
16757
16758      lines = this.splitFragmentsIntoLines(fragments, styles);
16759      line = void 0;
16760      maxLineHeight = void 0;
16761      defaultFontSize = 12;
16762      fontToUnitRatio = defaultFontSize / this.pdf.internal.scaleFactor;
16763      this.priorMarginBottom = this.priorMarginBottom || 0;
16764      paragraphspacing_before = (Math.max((blockstyle["margin-top"] || 0) - this.priorMarginBottom, 0) + (blockstyle["padding-top"] || 0)) * fontToUnitRatio;
16765      paragraphspacing_after = ((blockstyle["margin-bottom"] || 0) + (blockstyle["padding-bottom"] || 0)) * fontToUnitRatio;
16766      this.priorMarginBottom = blockstyle["margin-bottom"] || 0;
16767
16768      if (blockstyle['page-break-before'] === 'always') {
16769        this.pdf.addPage();
16770        this.y = 0;
16771        paragraphspacing_before = ((blockstyle["margin-top"] || 0) + (blockstyle["padding-top"] || 0)) * fontToUnitRatio;
16772      }
16773
16774      out = this.pdf.internal.write;
16775      i = void 0;
16776      l = void 0;
16777      this.y += paragraphspacing_before;
16778      out("q", "BT 0 g", this.pdf.internal.getCoordinateString(this.x), this.pdf.internal.getVerticalCoordinateString(this.y), "Td"); //stores the current indent of cursor position
16779
16780      var currentIndent = 0;
16781
16782      while (lines.length) {
16783        line = lines.shift();
16784        maxLineHeight = 0;
16785        i = 0;
16786        l = line.length;
16787
16788        while (i !== l) {
16789          if (line[i][0].trim()) {
16790            maxLineHeight = Math.max(maxLineHeight, line[i][1]["line-height"], line[i][1]["font-size"]);
16791            fontSize = line[i][1]["font-size"] * 7;
16792          }
16793
16794          i++;
16795        } //if we have to move the cursor to adapt the indent
16796
16797
16798        var indentMove = 0;
16799        var wantedIndent = 0; //if a margin was added (by e.g. a text-alignment), move the cursor
16800
16801        if (line[0][1]["margin-left"] !== undefined && line[0][1]["margin-left"] > 0) {
16802          wantedIndent = this.pdf.internal.getCoordinateString(line[0][1]["margin-left"]);
16803          indentMove = wantedIndent - currentIndent;
16804          currentIndent = wantedIndent;
16805        }
16806
16807        var indentMore = Math.max(blockstyle["margin-left"] || 0, 0) * fontToUnitRatio; //move the cursor
16808
16809        out(indentMove + indentMore, (-1 * defaultFontSize * maxLineHeight).toFixed(2), "Td");
16810        i = 0;
16811        l = line.length;
16812
16813        while (i !== l) {
16814          if (line[i][0]) {
16815            this.RenderTextFragment(line[i][0], line[i][1]);
16816          }
16817
16818          i++;
16819        }
16820
16821        this.y += maxLineHeight * fontToUnitRatio; //if some watcher function was executed successful, so e.g. margin and widths were changed,
16822        //reset line drawing and calculate position and lines again
16823        //e.g. to stop text floating around an image
16824
16825        if (this.executeWatchFunctions(line[0][1]) && lines.length > 0) {
16826          var localFragments = [];
16827          var localStyles = []; //create fragment array of
16828
16829          lines.forEach(function (localLine) {
16830            var i = 0;
16831            var l = localLine.length;
16832
16833            while (i !== l) {
16834              if (localLine[i][0]) {
16835                localFragments.push(localLine[i][0] + ' ');
16836                localStyles.push(localLine[i][1]);
16837              }
16838
16839              ++i;
16840            }
16841          }); //split lines again due to possible coordinate changes
16842
16843          lines = this.splitFragmentsIntoLines(PurgeWhiteSpace(localFragments), localStyles); //reposition the current cursor
16844
16845          out("ET", "Q");
16846          out("q", "BT 0 g", this.pdf.internal.getCoordinateString(this.x), this.pdf.internal.getVerticalCoordinateString(this.y), "Td");
16847        }
16848      }
16849
16850      if (cb && typeof cb === "function") {
16851        cb.call(this, this.x - 9, this.y - fontSize / 2);
16852      }
16853
16854      out("ET", "Q");
16855      return this.y += paragraphspacing_after;
16856    };
16857
16858    Renderer.prototype.setBlockBoundary = function (cb) {
16859      return this.renderParagraph(cb);
16860    };
16861
16862    Renderer.prototype.setBlockStyle = function (css) {
16863      return this.paragraph.blockstyle = css;
16864    };
16865
16866    Renderer.prototype.addText = function (text, css) {
16867      this.paragraph.text.push(text);
16868      return this.paragraph.style.push(css);
16869    };
16870
16871    FontNameDB = {
16872      helvetica: "helvetica",
16873      "sans-serif": "helvetica",
16874      "times new roman": "times",
16875      serif: "times",
16876      times: "times",
16877      monospace: "courier",
16878      courier: "courier"
16879    };
16880    FontWeightMap = {
16881      100: "normal",
16882      200: "normal",
16883      300: "normal",
16884      400: "normal",
16885      500: "bold",
16886      600: "bold",
16887      700: "bold",
16888      800: "bold",
16889      900: "bold",
16890      normal: "normal",
16891      bold: "bold",
16892      bolder: "bold",
16893      lighter: "normal"
16894    };
16895    FontStyleMap = {
16896      normal: "normal",
16897      italic: "italic",
16898      oblique: "italic"
16899    };
16900    TextAlignMap = {
16901      left: "left",
16902      right: "right",
16903      center: "center",
16904      justify: "justify"
16905    };
16906    FloatMap = {
16907      none: 'none',
16908      right: 'right',
16909      left: 'left'
16910    };
16911    ClearMap = {
16912      none: 'none',
16913      both: 'both'
16914    };
16915    UnitedNumberMap = {
16916      normal: 1
16917    };
16918    /**
16919     * Converts HTML-formatted text into formatted PDF text.
16920     *
16921     * Notes:
16922     * 2012-07-18
16923     * Plugin relies on having browser, DOM around. The HTML is pushed into dom and traversed.
16924     * Plugin relies on jQuery for CSS extraction.
16925     * Targeting HTML output from Markdown templating, which is a very simple
16926     * markup - div, span, em, strong, p. No br-based paragraph separation supported explicitly (but still may work.)
16927     * Images, tables are NOT supported.
16928     *
16929     * @public
16930     * @function
16931     * @param HTML {String|Object} HTML-formatted text, or pointer to DOM element that is to be rendered into PDF.
16932     * @param x {Number} starting X coordinate in jsPDF instance's declared units.
16933     * @param y {Number} starting Y coordinate in jsPDF instance's declared units.
16934     * @param settings {Object} Additional / optional variables controlling parsing, rendering.
16935     * @returns {Object} jsPDF instance
16936     */
16937
16938    jsPDFAPI.fromHTML = function (HTML, x, y, settings, callback, margins) {
16939
16940      this.margins_doc = margins || {
16941        top: 0,
16942        bottom: 0
16943      };
16944      if (!settings) settings = {};
16945      if (!settings.elementHandlers) settings.elementHandlers = {};
16946      return process(this, HTML, isNaN(x) ? 4 : x, isNaN(y) ? 4 : y, settings, callback);
16947    };
16948  })(jsPDF.API);
16949
16950  /**
16951   * html2pdf.js
16952   * Copyright (c) 2014 Steven Spungin (TwelveTone LLC)  [email protected]
16953   *
16954   * Licensed under the MIT License.
16955   * http://opensource.org/licenses/mit-license
16956   */
16957  (function (jsPDFAPI, globalObj) {
16958    globalObj.html2pdf = function (html, pdf, callback) {
16959      var canvas = pdf.canvas;
16960
16961      if (!canvas) {
16962        alert('jsPDF canvas plugin not installed');
16963        return;
16964      }
16965
16966      canvas.pdf = pdf;
16967      pdf.annotations = {
16968        _nameMap: [],
16969        createAnnotation: function createAnnotation(href, bounds) {
16970          var x = pdf.context2d._wrapX(bounds.left);
16971
16972          var y = pdf.context2d._wrapY(bounds.top);
16973
16974          var page = pdf.context2d._page(bounds.top);
16975
16976          var options;
16977          var index = href.indexOf('#');
16978
16979          if (index >= 0) {
16980            options = {
16981              name: href.substring(index + 1)
16982            };
16983          } else {
16984            options = {
16985              url: href
16986            };
16987          }
16988
16989          pdf.link(x, y, bounds.right - bounds.left, bounds.bottom - bounds.top, options);
16990        },
16991        setName: function setName(name, bounds) {
16992          var x = pdf.context2d._wrapX(bounds.left);
16993
16994          var y = pdf.context2d._wrapY(bounds.top);
16995
16996          var page = pdf.context2d._page(bounds.top);
16997
16998          this._nameMap[name] = {
16999            page: page,
17000            x: x,
17001            y: y
17002          };
17003        }
17004      };
17005      canvas.annotations = pdf.annotations;
17006
17007      pdf.context2d._pageBreakAt = function (y) {
17008        this.pageBreaks.push(y);
17009      };
17010
17011      pdf.context2d._gotoPage = function (pageOneBased) {
17012        while (pdf.internal.getNumberOfPages() < pageOneBased) {
17013          pdf.addPage();
17014        }
17015
17016        pdf.setPage(pageOneBased);
17017      };
17018
17019      var htmlElement;
17020      var height;
17021
17022      if (typeof html === 'string') {
17023        // remove all scripts
17024        html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
17025        var iframe = document.createElement('iframe'); //iframe.style.width = canvas.width;
17026        //iframe.src = "";
17027        //iframe.document.domain =
17028
17029        document.body.appendChild(iframe);
17030        var doc;
17031        var body;
17032        doc = iframe.contentDocument;
17033
17034        if (doc == undefined || doc == null) {
17035          doc = iframe.contentWindow.document;
17036        } //iframe.setAttribute('style', 'position:absolute;right:0; top:0; bottom:0; height:100%; width:500px');
17037
17038
17039        doc.open();
17040        doc.write(html);
17041        doc.close();
17042        htmlElement = doc.body;
17043        body = doc.body || {}, html = doc.documentElement || {};
17044        height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
17045      } else {
17046        htmlElement = html;
17047        body = html.body || {}, height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
17048      }
17049
17050      height = pdf.internal.pageSize.getHeight();
17051      var options = {
17052        async: true,
17053        allowTaint: true,
17054        backgroundColor: '#ffffff',
17055        canvas: canvas,
17056        imageTimeout: 15000,
17057        logging: true,
17058        proxy: null,
17059        removeContainer: true,
17060        foreignObjectRendering: false,
17061        useCORS: false,
17062        windowHeight: height,
17063        scrollY: height
17064      };
17065      pdf.context2d.pageWrapYEnabled = true;
17066      pdf.context2d.pageWrapY = pdf.internal.pageSize.getHeight();
17067      var promise = html2canvas(htmlElement, options).then(function (canvas) {
17068        if (callback) {
17069          if (iframe) {
17070            iframe.parentElement.removeChild(iframe);
17071          }
17072
17073          callback(pdf);
17074        }
17075      });
17076    };
17077  })(jsPDF.API, typeof window !== "undefined" && window || typeof global !== "undefined" && global);
17078  /*rollup-keeper-start*/
17079
17080
17081  window.tmp = html2pdf;
17082  /*rollup-keeper-end*/
17083
17084  /* Blob.js
17085   * A Blob, File, FileReader & URL implementation.
17086   * 2018-08-09
17087   *
17088   * By Eli Grey, http://eligrey.com
17089   * By Jimmy Wärting, https://github.com/jimmywarting
17090   * License: MIT
17091   *   See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
17092   */
17093
17094  (function (global) {
17095    var BlobBuilder = global.BlobBuilder || global.WebKitBlobBuilder || global.MSBlobBuilder || global.MozBlobBuilder;
17096
17097    global.URL = global.URL || global.webkitURL || function (href, a) {
17098      a = document.createElement('a');
17099      a.href = href;
17100      return a;
17101    };
17102
17103    var origBlob = global.Blob;
17104    var createObjectURL = URL.createObjectURL;
17105    var revokeObjectURL = URL.revokeObjectURL;
17106    var strTag = global.Symbol && global.Symbol.toStringTag;
17107    var blobSupported = false;
17108    var blobSupportsArrayBufferView = false;
17109    var arrayBufferSupported = !!global.ArrayBuffer;
17110    var blobBuilderSupported = BlobBuilder && BlobBuilder.prototype.append && BlobBuilder.prototype.getBlob;
17111
17112    try {
17113      // Check if Blob constructor is supported
17114      blobSupported = new Blob(['ä']).size === 2; // Check if Blob constructor supports ArrayBufferViews
17115      // Fails in Safari 6, so we need to map to ArrayBuffers there.
17116
17117      blobSupportsArrayBufferView = new Blob([new Uint8Array([1, 2])]).size === 2;
17118    } catch (e) {}
17119    /**
17120     * Helper function that maps ArrayBufferViews to ArrayBuffers
17121     * Used by BlobBuilder constructor and old browsers that didn't
17122     * support it in the Blob constructor.
17123     */
17124
17125
17126    function mapArrayBufferViews(ary) {
17127      return ary.map(function (chunk) {
17128        if (chunk.buffer instanceof ArrayBuffer) {
17129          var buf = chunk.buffer; // if this is a subarray, make a copy so we only
17130          // include the subarray region from the underlying buffer
17131
17132          if (chunk.byteLength !== buf.byteLength) {
17133            var copy = new Uint8Array(chunk.byteLength);
17134            copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength));
17135            buf = copy.buffer;
17136          }
17137
17138          return buf;
17139        }
17140
17141        return chunk;
17142      });
17143    }
17144
17145    function BlobBuilderConstructor(ary, options) {
17146      options = options || {};
17147      var bb = new BlobBuilder();
17148      mapArrayBufferViews(ary).forEach(function (part) {
17149        bb.append(part);
17150      });
17151      return options.type ? bb.getBlob(options.type) : bb.getBlob();
17152    }
17153
17154    function BlobConstructor(ary, options) {
17155      return new origBlob(mapArrayBufferViews(ary), options || {});
17156    }
17157
17158    if (global.Blob) {
17159      BlobBuilderConstructor.prototype = Blob.prototype;
17160      BlobConstructor.prototype = Blob.prototype;
17161    }
17162
17163    function FakeBlobBuilder() {
17164      function toUTF8Array(str) {
17165        var utf8 = [];
17166
17167        for (var i = 0; i < str.length; i++) {
17168          var charcode = str.charCodeAt(i);
17169          if (charcode < 0x80) utf8.push(charcode);else if (charcode < 0x800) {
17170            utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f);
17171          } else if (charcode < 0xd800 || charcode >= 0xe000) {
17172            utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f);
17173          } // surrogate pair
17174          else {
17175              i++; // UTF-16 encodes 0x10000-0x10FFFF by
17176              // subtracting 0x10000 and splitting the
17177              // 20 bits of 0x0-0xFFFFF into two halves
17178
17179              charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff);
17180              utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f);
17181            }
17182        }
17183
17184        return utf8;
17185      }
17186
17187      function fromUtf8Array(array) {
17188        var out, i, len, c;
17189        var char2, char3;
17190        out = "";
17191        len = array.length;
17192        i = 0;
17193
17194        while (i < len) {
17195          c = array[i++];
17196
17197          switch (c >> 4) {
17198            case 0:
17199            case 1:
17200            case 2:
17201            case 3:
17202            case 4:
17203            case 5:
17204            case 6:
17205            case 7:
17206              // 0xxxxxxx
17207              out += String.fromCharCode(c);
17208              break;
17209
17210            case 12:
17211            case 13:
17212              // 110x xxxx   10xx xxxx
17213              char2 = array[i++];
17214              out += String.fromCharCode((c & 0x1F) << 6 | char2 & 0x3F);
17215              break;
17216
17217            case 14:
17218              // 1110 xxxx  10xx xxxx  10xx xxxx
17219              char2 = array[i++];
17220              char3 = array[i++];
17221              out += String.fromCharCode((c & 0x0F) << 12 | (char2 & 0x3F) << 6 | (char3 & 0x3F) << 0);
17222              break;
17223          }
17224        }
17225
17226        return out;
17227      }
17228
17229      function isDataView(obj) {
17230        return obj && DataView.prototype.isPrototypeOf(obj);
17231      }
17232
17233      function bufferClone(buf) {
17234        var view = new Array(buf.byteLength);
17235        var array = new Uint8Array(buf);
17236        var i = view.length;
17237
17238        while (i--) {
17239          view[i] = array[i];
17240        }
17241
17242        return view;
17243      }
17244
17245      function encodeByteArray(input) {
17246        var byteToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
17247        var output = [];
17248
17249        for (var i = 0; i < input.length; i += 3) {
17250          var byte1 = input[i];
17251          var haveByte2 = i + 1 < input.length;
17252          var byte2 = haveByte2 ? input[i + 1] : 0;
17253          var haveByte3 = i + 2 < input.length;
17254          var byte3 = haveByte3 ? input[i + 2] : 0;
17255          var outByte1 = byte1 >> 2;
17256          var outByte2 = (byte1 & 0x03) << 4 | byte2 >> 4;
17257          var outByte3 = (byte2 & 0x0F) << 2 | byte3 >> 6;
17258          var outByte4 = byte3 & 0x3F;
17259
17260          if (!haveByte3) {
17261            outByte4 = 64;
17262
17263            if (!haveByte2) {
17264              outByte3 = 64;
17265            }
17266          }
17267
17268          output.push(byteToCharMap[outByte1], byteToCharMap[outByte2], byteToCharMap[outByte3], byteToCharMap[outByte4]);
17269        }
17270
17271        return output.join('');
17272      }
17273
17274      var create = Object.create || function (a) {
17275        function c() {}
17276
17277        c.prototype = a;
17278        return new c();
17279      };
17280
17281      if (arrayBufferSupported) {
17282        var viewClasses = ['[object Int8Array]', '[object Uint8Array]', '[object Uint8ClampedArray]', '[object Int16Array]', '[object Uint16Array]', '[object Int32Array]', '[object Uint32Array]', '[object Float32Array]', '[object Float64Array]'];
17283
17284        var isArrayBufferView = ArrayBuffer.isView || function (obj) {
17285          return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1;
17286        };
17287      }
17288      /********************************************************/
17289
17290      /*                   Blob constructor                   */
17291
17292      /********************************************************/
17293
17294
17295      function Blob(chunks, opts) {
17296        chunks = chunks || [];
17297
17298        for (var i = 0, len = chunks.length; i < len; i++) {
17299          var chunk = chunks[i];
17300
17301          if (chunk instanceof Blob) {
17302            chunks[i] = chunk._buffer;
17303          } else if (typeof chunk === 'string') {
17304            chunks[i] = toUTF8Array(chunk);
17305          } else if (arrayBufferSupported && (ArrayBuffer.prototype.isPrototypeOf(chunk) || isArrayBufferView(chunk))) {
17306            chunks[i] = bufferClone(chunk);
17307          } else if (arrayBufferSupported && isDataView(chunk)) {
17308            chunks[i] = bufferClone(chunk.buffer);
17309          } else {
17310            chunks[i] = toUTF8Array(String(chunk));
17311          }
17312        }
17313
17314        this._buffer = [].concat.apply([], chunks);
17315        this.size = this._buffer.length;
17316        this.type = opts ? opts.type || '' : '';
17317      }
17318
17319      Blob.prototype.slice = function (start, end, type) {
17320        var slice = this._buffer.slice(start || 0, end || this._buffer.length);
17321
17322        return new Blob([slice], {
17323          type: type
17324        });
17325      };
17326
17327      Blob.prototype.toString = function () {
17328        return '[object Blob]';
17329      };
17330      /********************************************************/
17331
17332      /*                   File constructor                   */
17333
17334      /********************************************************/
17335
17336
17337      function File(chunks, name, opts) {
17338        opts = opts || {};
17339        var a = Blob.call(this, chunks, opts) || this;
17340        a.name = name;
17341        a.lastModifiedDate = opts.lastModified ? new Date(opts.lastModified) : new Date();
17342        a.lastModified = +a.lastModifiedDate;
17343        return a;
17344      }
17345
17346      File.prototype = create(Blob.prototype);
17347      File.prototype.constructor = File;
17348      if (Object.setPrototypeOf) Object.setPrototypeOf(File, Blob);else {
17349        try {
17350          File.__proto__ = Blob;
17351        } catch (e) {}
17352      }
17353
17354      File.prototype.toString = function () {
17355        return '[object File]';
17356      };
17357      /********************************************************/
17358
17359      /*                FileReader constructor                */
17360
17361      /********************************************************/
17362
17363
17364      function FileReader() {
17365        if (!(this instanceof FileReader)) throw new TypeError("Failed to construct 'FileReader': Please use the 'new' operator, this DOM object c
17365onstructor cannot be called as a function.");
17366        var delegate = document.createDocumentFragment();
17367        this.addEventListener = delegate.addEventListener;
17368
17369        this.dispatchEvent = function (evt) {
17370          var local = this['on' + evt.type];
17371          if (typeof local === 'function') local(evt);
17372          delegate.dispatchEvent(evt);
17373        };
17374
17375        this.removeEventListener = delegate.removeEventListener;
17376      }
17377
17378      function _read(fr, blob, kind) {
17379        if (!(blob instanceof Blob)) throw new TypeError("Failed to execute '" + kind + "' on 'FileReader': parameter 1 is not of type 'Blob'.");
17380        fr.result = '';
17381        setTimeout(function () {
17382          this.readyState = FileReader.LOADING;
17383          fr.dispatchEvent(new Event('load'));
17384          fr.dispatchEvent(new Event('loadend'));
17385        });
17386      }
17387
17388      FileReader.EMPTY = 0;
17389      FileReader.LOADING = 1;
17390      FileReader.DONE = 2;
17391      FileReader.prototype.error = null;
17392      FileReader.prototype.onabort = null;
17393      FileReader.prototype.onerror = null;
17394      FileReader.prototype.onload = null;
17395      FileReader.prototype.onloadend = null;
17396      FileReader.prototype.onloadstart = null;
17397      FileReader.prototype.onprogress = null;
17398
17399      FileReader.prototype.readAsDataURL = function (blob) {
17400        _read(this, blob, 'readAsDataURL');
17401
17402        this.result = 'data:' + blob.type + ';base64,' + encodeByteArray(blob._buffer);
17403      };
17404
17405      FileReader.prototype.readAsText = function (blob) {
17406        _read(this, blob, 'readAsText');
17407
17408        this.result = fromUtf8Array(blob._buffer);
17409      };
17410
17411      FileReader.prototype.readAsArrayBuffer = function (blob) {
17412        _read(this, blob, 'readAsText');
17413
17414        this.result = blob._buffer.slice();
17415      };
17416
17417      FileReader.prototype.abort = function () {};
17418      /********************************************************/
17419
17420      /*                         URL                          */
17421
17422      /********************************************************/
17423
17424
17425      URL.createObjectURL = function (blob) {
17426        return blob instanceof Blob ? 'data:' + blob.type + ';base64,' + encodeByteArray(blob._buffer) : createObjectURL.call(URL, blob);
17427      };
17428
17429      URL.revokeObjectURL = function (url) {
17430        revokeObjectURL && revokeObjectURL.call(URL, url);
17431      };
17432      /********************************************************/
17433
17434      /*                         XHR                          */
17435
17436      /********************************************************/
17437
17438
17439      var _send = global.XMLHttpRequest && global.XMLHttpRequest.prototype.send;
17440
17441      if (_send) {
17442        XMLHttpRequest.prototype.send = function (data) {
17443          if (data instanceof Blob) {
17444            this.setRequestHeader('Content-Type', data.type);
17445
17446            _send.call(this, fromUtf8Array(data._buffer));
17447          } else {
17448            _send.call(this, data);
17449          }
17450        };
17451      }
17452
17453      global.FileReader = FileReader;
17454      global.File = File;
17455      global.Blob = Blob;
17456    }
17457
17458    if (strTag) {
17459      try {
17460        File.prototype[strTag] = 'File';
17461        Blob.prototype[strTag] = 'Blob';
17462        FileReader.prototype[strTag] = 'FileReader';
17463      } catch (e) {}
17464    }
17465
17466    function fixFileAndXHR() {
17467      var isIE = !!global.ActiveXObject || '-ms-scroll-limit' in document.documentElement.style && '-ms-ime-align' in document.documentElement.style; // Monkey patched 
17468      // IE don't set Content-Type header on XHR whose body is a typed Blob
17469      // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/6047383
17470
17471      var _send = global.XMLHttpRequest && global.XMLHttpRequest.prototype.send;
17472
17473      if (isIE && _send) {
17474        XMLHttpRequest.prototype.send = function (data) {
17475          if (data instanceof Blob) {
17476            this.setRequestHeader('Content-Type', data.type);
17477
17478            _send.call(this, data);
17479          } else {
17480            _send.call(this, data);
17481          }
17482        };
17483      }
17484
17485      try {
17486        new File([], '');
17487      } catch (e) {
17488        try {
17489          var klass = new Function('class File extends Blob {' + 'constructor(chunks, name, opts) {' + 'opts = opts || {};' + 'super(chunks, opts || {});' + 'this.name = name;' + 'this.lastModifiedDate = opts.lastModified ? new Date(opts.lastModified) : new Date;' + 'this.lastModified = +this.lastModifiedDate;' + '}};' + 'return new File([], ""), File')();
17490          global.File = klass;
17491        } catch (e) {
17492          var klass = function klass(b, d, c) {
17493            var blob = new Blob(b, c);
17494            var t = c && void 0 !== c.lastModified ? new Date(c.lastModified) : new Date();
17495            blob.name = d;
17496            blob.lastModifiedDate = t;
17497            blob.lastModified = +t;
17498
17499            blob.toString = function () {
17500              return '[object File]';
17501            };
17502
17503            if (strTag) blob[strTag] = 'File';
17504            return blob;
17505          };
17506
17507          global.File = klass;
17508        }
17509      }
17510    }
17511
17512    if (blobSupported) {
17513      fixFileAndXHR();
17514      global.Blob = blobSupportsArrayBufferView ? global.Blob : BlobConstructor;
17515    } else if (blobBuilderSupported) {
17516      fixFileAndXHR();
17517      global.Blob = BlobBuilderConstructor;
17518    } else {
17519      FakeBlobBuilder();
17520    }
17521  })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function('return this')());
17522
17523  /* FileSaver.js
17524   * A saveAs() FileSaver implementation.
17525   * 1.3.8
17526   * 2018-03-22 14:03:47
17527   *
17528   * By Eli Grey, https://eligrey.com
17529   * License: MIT
17530   *   See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
17531   */
17532
17533  /*global self */
17534
17535  /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
17536
17537  /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/src/FileSaver.js */
vendor: 4,498 bytes, lines 17538-17667
17538  var saveAs = saveAs || function (view) {
17539
17540    if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
17541      return;
17542    }
17543
17544    var doc = view.document // only get URL when necessary in case Blob.js hasn't overridden it yet
17545    ,
17546        get_URL = function () {
17547      return view.URL || view.webkitURL || view;
17548    },
17549        save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"),
17550        can_use_save_link = "download" in save_link,
17551        click = function (node) {
17552      var event = new MouseEvent("click");
17553      node.dispatchEvent(event);
17554    },
17555        is_safari = /constructor/i.test(view.HTMLElement) || view.safari,
17556        is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent),
17557        setImmediate = view.setImmediate || view.setTimeout,
17558        throw_outside = function (ex) {
17559      setImmediate(function () {
17560        throw ex;
17561      }, 0);
17562    },
17563        force_saveable_type = "application/octet-stream" // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
17564    ,
17565        arbitrary_revoke_timeout = 1000 * 40 // in ms
17566    ,
17567        revoke = function (file) {
17568      var revoker = function () {
17569        if (typeof file === "string") {
17570          // file is an object URL
17571          get_URL().revokeObjectURL(file);
17572        } else {
17573          // file is a File
17574          file.remove();
17575        }
17576      };
17577
17578      setTimeout(revoker, arbitrary_revoke_timeout);
17579    },
17580        dispatch = function (filesaver, event_types, event) {
17581      event_types = [].concat(event_types);
17582      var i = event_types.length;
17583
17584      while (i--) {
17585        var listener = filesaver["on" + event_types[i]];
17586
17587        if (typeof listener === "function") {
17588          try {
17589            listener.call(filesaver, event || filesaver);
17590          } catch (ex) {
17591            throw_outside(ex);
17592          }
17593        }
17594      }
17595    },
17596        auto_bom = function (blob) {
17597      // prepend BOM for UTF-8 XML and text/* types (including HTML)
17598      // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
17599      if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
17600        return new Blob([String.fromCharCode(0xFEFF), blob], {
17601          type: blob.type
17602        });
17603      }
17604
17605      return blob;
17606    },
17607        FileSaver = function (blob, name, no_auto_bom) {
17608      if (!no_auto_bom) {
17609        blob = auto_bom(blob);
17610      } // First try a.download, then web filesystem, then object URLs
17611
17612
17613      var filesaver = this,
17614          type = blob.type,
17615          force = type === force_saveable_type,
17616          object_url,
17617          dispatch_all = function () {
17618        dispatch(filesaver, "writestart progress write writeend".split(" "));
17619      } // on any filesys errors revert to saving with object URLs
17620      ,
17621          fs_error = function () {
17622        if ((is_chrome_ios || force && is_safari) && view.FileReader) {
17623          // Safari doesn't allow downloading of blob urls
17624          var reader = new FileReader();
17625
17626          reader.onloadend = function () {
17627            var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
17628            var popup = view.open(url, '_blank');
17629            if (!popup) view.location.href = url;
17630            url = undefined; // release reference before dispatching
17631
17632            filesaver.readyState = filesaver.DONE;
17633            dispatch_all();
17634          };
17635
17636          reader.readAsDataURL(blob);
17637          filesaver.readyState = filesaver.INIT;
17638          return;
17639        } // don't create more object URLs than needed
17640
17641
17642        if (!object_url) {
17643          object_url = get_URL().createObjectURL(blob);
17644        }
17645
17646        if (force) {
17647          view.location.href = object_url;
17648        } else {
17649          var opened = view.open(object_url, "_blank");
17650
17651          if (!opened) {
17652            // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
17653            view.location.href = object_url;
17654          }
17655        }
17656
17657        filesaver.readyState = filesaver.DONE;
17658        dispatch_all();
17659        revoke(object_url);
17660      };
17661
17662      filesaver.readyState = filesaver.INIT;
17663
17664      if (can_use_save_link) {
17665        object_url = get_URL().createObjectURL(blob);
17666        setImmediate(function () {
17667          save_link.href = object_url;
17668          save_link.download = name;
17669          click(save_link);
17670          dispatch_all();
17671          revoke(object_url);
17672          filesaver.readyState = filesaver.DONE;
17673        }, 0);
17674        return;
17675      }
17676
17677      fs_error();
17678    },
17679        FS_proto = FileSaver.prototype,
17680        saveAs = function (blob, name, no_auto_bom) {
17681      return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
17682    }; // IE 10+ (native saveAs)
17683
17684
17685    if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
17686      return function (blob, name, no_auto_bom) {
17687        name = name || blob.name || "download";
17688
17689        if (!no_auto_bom) {
17690          blob = auto_bom(blob);
17691        }
17692
17693        return navigator.msSaveOrOpenBlob(blob, name);
17694      };
17695    } // todo: detect chrome extensions & packaged apps
17696    //save_link.target = "_blank";
17697
17698
17699    FS_proto.abort = function () {};
17700
17701    FS_proto.readyState = FS_proto.INIT = 0;
17702    FS_proto.WRITING = 1;
17703    FS_proto.DONE = 2;
17704    FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null;
17705    return saveAs;
17706  }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || undefined);
17707
17708  // (c) Dean McNamee <[email protected]>, 2013.
17709  //
17710  // https://github.com/deanm/omggif
17711  //
17712  // 
17713  //
17714  // omggif is a JavaScript implementation of a GIF 89a encoder and decoder,
17715  // including animation and compression.  It does not rely on any specific
17716  // underlying system, so should run in the browser, Node, or Plask.
17717  function GifWriter(buf, width, height, gopts) {
17718    var p = 0;
17719    var gopts = gopts === undefined ? {} : gopts;
17720    var loop_count = gopts.loop === undefined ? null : gopts.loop;
17721    var global_palette = gopts.palette === undefined ? null : gopts.palette;
17722    if (width <= 0 || height <= 0 || width > 65535 || height > 65535) throw "Width/Height invalid.";
17723
17724    function check_palette_and_num_colors(palette) {
17725      var num_colors = palette.length;
17726      if (num_colors < 2 || num_colors > 256 || num_colors & num_colors - 1) throw "Invalid code/color length, must be power of 2 and 2 .. 256.";
17727      return num_colors;
17728    } // - Header.
17729
17730
17731    buf[p++] = 0x47;
17732    buf[p++] = 0x49;
17733    buf[p++] = 0x46; // GIF
17734
17735    buf[p++] = 0x38;
17736    buf[p++] = 0x39;
17737    buf[p++] = 0x61; // 89a
17738    // Handling of Global Color Table (palette) and background index.
17739
17740    var gp_num_colors_pow2 = 0;
17741    var background = 0;
17742
17743    if (global_palette !== null) {
17744      var gp_num_colors = check_palette_and_num_colors(global_palette);
17745
17746      while (gp_num_colors >>= 1) ++gp_num_colors_pow2;
17747
17748      gp_num_colors = 1 << gp_num_colors_pow2;
17749      --gp_num_colors_pow2;
17750
17751      if (gopts.background !== undefined) {
17752        background = gopts.background;
17753        if (background >= gp_num_colors) throw "Background index out of range."; // The GIF spec states that a background index of 0 should be ignored, so
17754        // this is probably a mistake and you really want to set it to another
17755        // slot in the palette.  But actually in the end most browsers, etc end
17756        // up ignoring this almost completely (including for dispose background).
17757
17758        if (background === 0) throw "Background index explicitly passed as 0.";
17759      }
17760    } // - Logical Screen Descriptor.
17761    // NOTE(deanm): w/h apparently ignored by implementations, but set anyway.
17762
17763
17764    buf[p++] = width & 0xff;
17765    buf[p++] = width >> 8 & 0xff;
17766    buf[p++] = height & 0xff;
17767    buf[p++] = height >> 8 & 0xff; // NOTE: Indicates 0-bpp original color resolution (unused?).
17768
17769    buf[p++] = (global_palette !== null ? 0x80 : 0) | // Global Color Table Flag.
17770    gp_num_colors_pow2; // NOTE: No sort flag (unused?).
17771
17772    buf[p++] = background; // Background Color Index.
17773
17774    buf[p++] = 0; // Pixel aspect ratio (unused?).
17775    // - Global Color Table
17776
17777    if (global_palette !== null) {
17778      for (var i = 0, il = global_palette.length; i < il; ++i) {
17779        var rgb = global_palette[i];
17780        buf[p++] = rgb >> 16 & 0xff;
17781        buf[p++] = rgb >> 8 & 0xff;
17782        buf[p++] = rgb & 0xff;
17783      }
17784    }
17785
17786    if (loop_count !== null) {
17787      // Netscape block for looping.
17788      if (loop_count < 0 || loop_count > 65535) throw "Loop count invalid."; // Extension code, label, and length.
17789
17790      buf[p++] = 0x21;
17791      buf[p++] = 0xff;
17792      buf[p++] = 0x0b;
vendor: 4,450 bytes, lines 17792-17924
17792 // NETSCAPE2.0
17793
17794      buf[p++] = 0x4e;
17795      buf[p++] = 0x45;
17796      buf[p++] = 0x54;
17797      buf[p++] = 0x53;
17798      buf[p++] = 0x43;
17799      buf[p++] = 0x41;
17800      buf[p++] = 0x50;
17801      buf[p++] = 0x45;
17802      buf[p++] = 0x32;
17803      buf[p++] = 0x2e;
17804      buf[p++] = 0x30; // Sub-block
17805
17806      buf[p++] = 0x03;
17807      buf[p++] = 0x01;
17808      buf[p++] = loop_count & 0xff;
17809      buf[p++] = loop_count >> 8 & 0xff;
17810      buf[p++] = 0x00; // Terminator.
17811    }
17812
17813    var ended = false;
17814
17815    this.addFrame = function (x, y, w, h, indexed_pixels, opts) {
17816      if (ended === true) {
17817        --p;
17818        ended = false;
17819      } // Un-end.
17820
17821
17822      opts = opts === undefined ? {} : opts; // TODO(deanm): Bounds check x, y.  Do they need to be within the virtual
17823      // canvas width/height, I imagine?
17824
17825      if (x < 0 || y < 0 || x > 65535 || y > 65535) throw "x/y invalid.";
17826      if (w <= 0 || h <= 0 || w > 65535 || h > 65535) throw "Width/Height invalid.";
17827      if (indexed_pixels.length < w * h) throw "Not enough pixels for the frame size.";
17828      var using_local_palette = true;
17829      var palette = opts.palette;
17830
17831      if (palette === undefined || palette === null) {
17832        using_local_palette = false;
17833        palette = global_palette;
17834      }
17835
17836      if (palette === undefined || palette === null) throw "Must supply either a local or global palette.";
17837      var num_colors = check_palette_and_num_colors(palette); // Compute the min_code_size (power of 2), destroying num_colors.
17838
17839      var min_code_size = 0;
17840
17841      while (num_colors >>= 1) ++min_code_size;
17842
17843      num_colors = 1 << min_code_size; // Now we can easily get it back.
17844
17845      var delay = opts.delay === undefined ? 0 : opts.delay; // From the spec:
17846      //     0 -   No disposal specified. The decoder is
17847      //           not required to take any action.
17848      //     1 -   Do not dispose. The graphic is to be left
17849      //           in place.
17850      //     2 -   Restore to background color. The area used by the
17851      //           graphic must be restored to the background color.
17852      //     3 -   Restore to previous. The decoder is required to
17853      //           restore the area overwritten by the graphic with
17854      //           what was there prior to rendering the graphic.
17855      //  4-7 -    To be defined.
17856      // NOTE(deanm): Dispose background doesn't really work, apparently most
17857      // browsers ignore the background palette index and clear to transparency.
17858
17859      var disposal = opts.disposal === undefined ? 0 : opts.disposal;
17860      if (disposal < 0 || disposal > 3) // 4-7 is reserved.
17861        throw "Disposal out of range.";
17862      var use_transparency = false;
17863      var transparent_index = 0;
17864
17865      if (opts.transparent !== undefined && opts.transparent !== null) {
17866        use_transparency = true;
17867        transparent_index = opts.transparent;
17868        if (transparent_index < 0 || transparent_index >= num_colors) throw "Transparent color index.";
17869      }
17870
17871      if (disposal !== 0 || use_transparency || delay !== 0) {
17872        // - Graphics Control Extension
17873        buf[p++] = 0x21;
17874        buf[p++] = 0xf9; // Extension / Label.
17875
17876        buf[p++] = 4; // Byte size.
17877
17878        buf[p++] = disposal << 2 | (use_transparency === true ? 1 : 0);
17879        buf[p++] = delay & 0xff;
17880        buf[p++] = delay >> 8 & 0xff;
17881        buf[p++] = transparent_index; // Transparent color index.
17882
17883        buf[p++] = 0; // Block Terminator.
17884      } // - Image Descriptor
17885
17886
17887      buf[p++] = 0x2c; // Image Seperator.
17888
17889      buf[p++] = x & 0xff;
17890      buf[p++] = x >> 8 & 0xff; // Left.
17891
17892      buf[p++] = y & 0xff;
17893      buf[p++] = y >> 8 & 0xff; // Top.
17894
17895      buf[p++] = w & 0xff;
17896      buf[p++] = w >> 8 & 0xff;
17897      buf[p++] = h & 0xff;
17898      buf[p++] = h >> 8 & 0xff; // NOTE: No sort flag (unused?).
17899      // TODO(deanm): Support interlace.
17900
17901      buf[p++] = using_local_palette === true ? 0x80 | min_code_size - 1 : 0; // - Local Color Table
17902
17903      if (using_local_palette === true) {
17904        for (var i = 0, il = palette.length; i < il; ++i) {
17905          var rgb = palette[i];
17906          buf[p++] = rgb >> 16 & 0xff;
17907          buf[p++] = rgb >> 8 & 0xff;
17908          buf[p++] = rgb & 0xff;
17909        }
17910      }
17911
17912      p = GifWriterOutputLZWCodeStream(buf, p, min_code_size < 2 ? 2 : min_code_size, indexed_pixels);
17913    };
17914
17915    this.end = function () {
17916      if (ended === false) {
17917        buf[p++] = 0x3b; // Trailer.
17918
17919        ended = true;
17920      }
17921
17922      return p;
17923    };
17924  }
vendor: 14,349 bytes, lines 17924-18289
17924 // Main compression routine, palette indexes -> LZW code stream.
17925  // |index_stream| must have at least one entry.
17926
17927
17928  function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) {
17929    buf[p++] = min_code_size;
17930    var cur_subblock = p++; // Pointing at the length field.
17931
17932    var clear_code = 1 << min_code_size;
17933    var code_mask = clear_code - 1;
17934    var eoi_code = clear_code + 1;
17935    var next_code = eoi_code + 1;
17936    var cur_code_size = min_code_size + 1; // Number of bits per code.
17937
17938    var cur_shift = 0; // We have at most 12-bit codes, so we should have to hold a max of 19
17939    // bits here (and then we would write out).
17940
17941    var cur = 0;
17942
17943    function emit_bytes_to_buffer(bit_block_size) {
17944      while (cur_shift >= bit_block_size) {
17945        buf[p++] = cur & 0xff;
17946        cur >>= 8;
17947        cur_shift -= 8;
17948
17949        if (p === cur_subblock + 256) {
17950          // Finished a subblock.
17951          buf[cur_subblock] = 255;
17952          cur_subblock = p++;
17953        }
17954      }
17955    }
17956
17957    function emit_code(c) {
17958      cur |= c << cur_shift;
17959      cur_shift += cur_code_size;
17960      emit_bytes_to_buffer(8);
17961    } // I am not an expert on the topic, and I don't want to write a thesis.
17962    // However, it is good to outline here the basic algorithm and the few data
17963    // structures and optimizations here that make this implementation fast.
17964    // The basic idea behind LZW is to build a table of previously seen runs
17965    // addressed by a short id (herein called output code).  All data is
17966    // referenced by a code, which represents one or more values from the
17967    // original input stream.  All input bytes can be referenced as the same
17968    // value as an output code.  So if you didn't want any compression, you
17969    // could more or less just output the original bytes as codes (there are
17970    // some details to this, but it is the idea).  In order to achieve
17971    // compression, values greater then the input range (codes can be up to
17972    // 12-bit while input only 8-bit) represent a sequence of previously seen
17973    // inputs.  The decompressor is able to build the same mapping while
17974    // decoding, so there is always a shared common knowledge between the
17975    // encoding and decoder, which is also important for "timing" aspects like
17976    // how to handle variable bit width code encoding.
17977    //
17978    // One obvious but very important consequence of the table system is there
17979    // is always a unique id (at most 12-bits) to map the runs.  'A' might be
17980    // 4, then 'AA' might be 10, 'AAA' 11, 'AAAA' 12, etc.  This relationship
17981    // can be used for an effecient lookup strategy for the code mapping.  We
17982    // need to know if a run has been seen before, and be able to map that run
17983    // to the output code.  Since we start with known unique ids (input bytes),
17984    // and then from those build more unique ids (table entries), we can
17985    // continue this chain (almost like a linked list) to always have small
17986    // integer values that represent the current byte chains in the encoder.
17987    // This means instead of tracking the input bytes (AAAABCD) to know our
17988    // current state, we can track the table entry for AAAABC (it is guaranteed
17989    // to exist by the nature of the algorithm) and the next character D.
17990    // Therefor the tuple of (table_entry, byte) is guaranteed to also be
17991    // unique.  This allows us to create a simple lookup key for mapping input
17992    // sequences to codes (table indices) without having to store or search
17993    // any of the code sequences.  So if 'AAAA' has a table entry of 12, the
17994    // tuple of ('AAAA', K) for any input byte K will be unique, and can be our
17995    // key.  This leads to a integer value at most 20-bits, which can always
17996    // fit in an SMI value and be used as a fast sparse array / object key.
17997    // Output code for the current contents of the index buffer.
17998
17999
18000    var ib_code = index_stream[0] & code_mask; // Load first input index.
18001
18002    var code_table = {}; // Key'd on our 20-bit "tuple".
18003
18004    emit_code(clear_code); // Spec says first code should be a clear code.
18005    // First index already loaded, process the rest of the stream.
18006
18007    for (var i = 1, il = index_stream.length; i < il; ++i) {
18008      var k = index_stream[i] & code_mask;
18009      var cur_key = ib_code << 8 | k; // (prev, k) unique tuple.
18010
18011      var cur_code = code_table[cur_key]; // buffer + k.
18012      // Check if we have to create a new code table entry.
18013
18014      if (cur_code === undefined) {
18015        // We don't have buffer + k.
18016        // Emit index buffer (without k).
18017        // This is an inline version of emit_code, because this is the core
18018        // writing routine of the compressor (and V8 cannot inline emit_code
18019        // because it is a closure here in a different context).  Additionally
18020        // we can call emit_byte_to_buffer less often, because we can have
18021        // 30-bits (from our 31-bit signed SMI), and we know our codes will only
18022        // be 12-bits, so can safely have 18-bits there without overflow.
18023        // emit_code(ib_code);
18024        cur |= ib_code << cur_shift;
18025        cur_shift += cur_code_size;
18026
18027        while (cur_shift >= 8) {
18028          buf[p++] = cur & 0xff;
18029          cur >>= 8;
18030          cur_shift -= 8;
18031
18032          if (p === cur_subblock + 256) {
18033            // Finished a subblock.
18034            buf[cur_subblock] = 255;
18035            cur_subblock = p++;
18036          }
18037        }
18038
18039        if (next_code === 4096) {
18040          // Table full, need a clear.
18041          emit_code(clear_code);
18042          next_code = eoi_code + 1;
18043          cur_code_size = min_code_size + 1;
18044          code_table = {};
18045        } else {
18046          // Table not full, insert a new entry.
18047          // Increase our variable bit code sizes if necessary.  This is a bit
18048          // tricky as it is based on "timing" between the encoding and
18049          // decoder.  From the encoders perspective this should happen after
18050          // we've already emitted the index buffer and are about to create the
18051          // first table entry that would overflow our current code bit size.
18052          if (next_code >= 1 << cur_code_size) ++cur_code_size;
18053          code_table[cur_key] = next_code++; // Insert into code table.
18054        }
18055
18056        ib_code = k; // Index buffer to single input k.
18057      } else {
18058        ib_code = cur_code; // Index buffer to sequence in code table.
18059      }
18060    }
18061
18062    emit_code(ib_code); // There will still be something in the index buffer.
18063
18064    emit_code(eoi_code); // End Of Information.
18065    // Flush / finalize the sub-blocks stream to the buffer.
18066
18067    emit_bytes_to_buffer(1); // Finish the sub-blocks, writing out any unfinished lengths and
18068    // terminating with a sub-block of length 0.  If we have already started
18069    // but not yet used a sub-block it can just become the terminator.
18070
18071    if (cur_subblock + 1 === p) {
18072      // Started but unused.
18073      buf[cur_subblock] = 0;
18074    } else {
18075      // Started and used, write length and additional terminator block.
18076      buf[cur_subblock] = p - cur_subblock - 1;
18077      buf[p++] = 0;
18078    }
18079
18080    return p;
18081  }
18082
18083  function GifReader(buf) {
18084    var p = 0; // - Header (GIF87a or GIF89a).
18085
18086    if (buf[p++] !== 0x47 || buf[p++] !== 0x49 || buf[p++] !== 0x46 || buf[p++] !== 0x38 || (buf[p++] + 1 & 0xfd) !== 0x38 || buf[p++] !== 0x61) {
18087      throw "Invalid GIF 87a/89a header.";
18088    } // - Logical Screen Descriptor.
18089
18090
18091    var width = buf[p++] | buf[p++] << 8;
18092    var height = buf[p++] | buf[p++] << 8;
18093    var pf0 = buf[p++]; // <Packed Fields>.
18094
18095    var global_palette_flag = pf0 >> 7;
18096    var num_global_colors_pow2 = pf0 & 0x7;
18097    var num_global_colors = 1 << num_global_colors_pow2 + 1;
18098    var background = buf[p++];
18099    buf[p++]; // Pixel aspect ratio (unused?).
18100
18101    var global_palette_offset = null;
18102
18103    if (global_palette_flag) {
18104      global_palette_offset = p;
18105      p += num_global_colors * 3; // Seek past palette.
18106    }
18107
18108    var no_eof = true;
18109    var frames = [];
18110    var delay = 0;
18111    var transparent_index = null;
18112    var disposal = 0; // 0 - No disposal specified.
18113
18114    var loop_count = null;
18115    this.width = width;
18116    this.height = height;
18117
18118    while (no_eof && p < buf.length) {
18119      switch (buf[p++]) {
18120        case 0x21:
18121          // Graphics Control Extension Block
18122          switch (buf[p++]) {
18123            case 0xff:
18124              // Application specific block
18125              // Try if it's a Netscape block (with animation loop counter).
18126              if (buf[p] !== 0x0b || // 21 FF already read, check block size.
18127              // NETSCAPE2.0
18128              buf[p + 1] == 0x4e && buf[p + 2] == 0x45 && buf[p + 3] == 0x54 && buf[p + 4] == 0x53 && buf[p + 5] == 0x43 && buf[p + 6] == 0x41 && buf[p + 7] == 0x50 && buf[p + 8] == 0x45 && buf[p + 9] == 0x32 && buf[p + 10] == 0x2e && buf[p + 11] == 0x30 && // Sub-block
18129              buf[p + 12] == 0x03 && buf[p + 13] == 0x01 && buf[p + 16] == 0) {
18130                p += 14;
18131                loop_count = buf[p++] | buf[p++] << 8;
18132                p++; // Skip terminator.
18133              } else {
18134                // We don't know what it is, just try to get past it.
18135                p += 12;
18136
18137                while (true) {
18138                  // Seek through subblocks.
18139                  var block_size = buf[p++];
18140                  if (block_size === 0) break;
18141                  p += block_size;
18142                }
18143              }
18144
18145              break;
18146
18147            case 0xf9:
18148              // Graphics Control Extension
18149              if (buf[p++] !== 0x4 || buf[p + 4] !== 0) throw "Invalid graphics extension block.";
18150              var pf1 = buf[p++];
18151              delay = buf[p++] | buf[p++] << 8;
18152              transparent_index = buf[p++];
18153              if ((pf1 & 1) === 0) transparent_index = null;
18154              disposal = pf1 >> 2 & 0x7;
18155              p++; // Skip terminator.
18156
18157              break;
18158
18159            case 0xfe:
18160              // Comment Extension.
18161              while (true) {
18162                // Seek through subblocks.
18163                var block_size = buf[p++];
18164                if (block_size === 0) break; // console.log(buf.slice(p, p+block_size).toString('ascii'));
18165
18166                p += block_size;
18167              }
18168
18169              break;
18170
18171            default:
18172              throw "Unknown graphic control label: 0x" + buf[p - 1].toString(16);
18173          }
18174
18175          break;
18176
18177        case 0x2c:
18178          // Image Descriptor.
18179          var x = buf[p++] | buf[p++] << 8;
18180          var y = buf[p++] | buf[p++] << 8;
18181          var w = buf[p++] | buf[p++] << 8;
18182          var h = buf[p++] | buf[p++] << 8;
18183          var pf2 = buf[p++];
18184          var local_palette_flag = pf2 >> 7;
18185          var interlace_flag = pf2 >> 6 & 1;
18186          var num_local_colors_pow2 = pf2 & 0x7;
18187          var num_local_colors = 1 << num_local_colors_pow2 + 1;
18188          var palette_offset = global_palette_offset;
18189          var has_local_palette = false;
18190
18191          if (local_palette_flag) {
18192            var has_local_palette = true;
18193            palette_offset = p; // Override with local palette.
18194
18195            p += num_local_colors * 3; // Seek past palette.
18196          }
18197
18198          var data_offset = p;
18199          p++; // codesize
18200
18201          while (true) {
18202            var block_size = buf[p++];
18203            if (block_size === 0) break;
18204            p += block_size;
18205          }
18206
18207          frames.push({
18208            x: x,
18209            y: y,
18210            width: w,
18211            height: h,
18212            has_local_palette: has_local_palette,
18213            palette_offset: palette_offset,
18214            data_offset: data_offset,
18215            data_length: p - data_offset,
18216            transparent_index: transparent_index,
18217            interlaced: !!interlace_flag,
18218            delay: delay,
18219            disposal: disposal
18220          });
18221          break;
18222
18223        case 0x3b:
18224          // Trailer Marker (end of file).
18225          no_eof = false;
18226          break;
18227
18228        default:
18229          throw "Unknown gif block: 0x" + buf[p - 1].toString(16);
18230          break;
18231      }
18232    }
18233
18234    this.numFrames = function () {
18235      return frames.length;
18236    };
18237
18238    this.loopCount = function () {
18239      return loop_count;
18240    };
18241
18242    this.frameInfo = function (frame_num) {
18243      if (frame_num < 0 || frame_num >= frames.length) throw "Frame index out of range.";
18244      return frames[frame_num];
18245    };
18246
18247    this.decodeAndBlitFrameBGRA = function (frame_num, pixels) {
18248      var frame = this.frameInfo(frame_num);
18249      var num_pixels = frame.width * frame.height;
18250      var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices.
18251
18252      GifReaderLZWOutputIndexStream(buf, frame.data_offset, index_stream, num_pixels);
18253      var palette_offset = frame.palette_offset; // NOTE(deanm): It seems to be much faster to compare index to 256 than
18254      // to === null.  Not sure why, but CompareStub_EQ_STRICT shows up high in
18255      // the profile, not sure if it's related to using a Uint8Array.
18256
18257      var trans = frame.transparent_index;
18258      if (trans === null) trans = 256; // We are possibly just blitting to a portion of the entire frame.
18259      // That is a subrect within the framerect, so the additional pixels
18260      // must be skipped over after we finished a scanline.
18261
18262      var framewidth = frame.width;
18263      var framestride = width - framewidth;
18264      var xleft = framewidth; // Number of subrect pixels left in scanline.
18265      // Output indicies of the top left and bottom right corners of the subrect.
18266
18267      var opbeg = (frame.y * width + frame.x) * 4;
18268      var opend = ((frame.y + frame.height) * width + frame.x) * 4;
18269      var op = opbeg;
18270      var scanstride = framestride * 4; // Use scanstride to skip past the rows when interlacing.  This is skipping
18271      // 7 rows for the first two passes, then 3 then 1.
18272
18273      if (frame.interlaced === true) {
18274        scanstride += (framewidth + framestride) * 4 * 7; // Pass 1.
18275      }
18276
18277      var interlaceskip = 8; // Tracking the row interval in the current pass.
18278
18279      for (var i = 0, il = index_stream.length; i < il; ++i) {
18280        var index = index_stream[i];
18281
18282        if (xleft === 0) {
18283          // Beginning of new scan line
18284          op += scanstride;
18285          xleft = framewidth;
18286
18287          if (op >= opend) {
18288            // Catch the wrap to switch passes when interlacing.
18289            scanstride = framestride + (framewidth + framestride) * 4 * (interlaceskip - 1);
vendor: 4,733 bytes, lines 18289-18418
18289 // interlaceskip / 2 * 4 is interlaceskip << 1.
18290
18291            op = opbeg + (framewidth + framestride) * (interlaceskip << 1);
18292            interlaceskip >>= 1;
18293          }
18294        }
18295
18296        if (index === trans) {
18297          op += 4;
18298        } else {
18299          var r = buf[palette_offset + index * 3];
18300          var g = buf[palette_offset + index * 3 + 1];
18301          var b = buf[palette_offset + index * 3 + 2];
18302          pixels[op++] = b;
18303          pixels[op++] = g;
18304          pixels[op++] = r;
18305          pixels[op++] = 255;
18306        }
18307
18308        --xleft;
18309      }
18310    }; // I will go to copy and paste hell one day...
18311
18312
18313    this.decodeAndBlitFrameRGBA = function (frame_num, pixels) {
18314      var frame = this.frameInfo(frame_num);
18315      var num_pixels = frame.width * frame.height;
18316      var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices.
18317
18318      GifReaderLZWOutputIndexStream(buf, frame.data_offset, index_stream, num_pixels);
18319      var palette_offset = frame.palette_offset; // NOTE(deanm): It seems to be much faster to compare index to 256 than
18320      // to === null.  Not sure why, but CompareStub_EQ_STRICT shows up high in
18321      // the profile, not sure if it's related to using a Uint8Array.
18322
18323      var trans = frame.transparent_index;
18324      if (trans === null) trans = 256; // We are possibly just blitting to a portion of the entire frame.
18325      // That is a subrect within the framerect, so the additional pixels
18326      // must be skipped over after we finished a scanline.
18327
18328      var framewidth = frame.width;
18329      var framestride = width - framewidth;
18330      var xleft = framewidth; // Number of subrect pixels left in scanline.
18331      // Output indicies of the top left and bottom right corners of the subrect.
18332
18333      var opbeg = (frame.y * width + frame.x) * 4;
18334      var opend = ((frame.y + frame.height) * width + frame.x) * 4;
18335      var op = opbeg;
18336      var scanstride = framestride * 4; // Use scanstride to skip past the rows when interlacing.  This is skipping
18337      // 7 rows for the first two passes, then 3 then 1.
18338
18339      if (frame.interlaced === true) {
18340        scanstride += (framewidth + framestride) * 4 * 7; // Pass 1.
18341      }
18342
18343      var interlaceskip = 8; // Tracking the row interval in the current pass.
18344
18345      for (var i = 0, il = index_stream.length; i < il; ++i) {
18346        var index = index_stream[i];
18347
18348        if (xleft === 0) {
18349          // Beginning of new scan line
18350          op += scanstride;
18351          xleft = framewidth;
18352
18353          if (op >= opend) {
18354            // Catch the wrap to switch passes when interlacing.
18355            scanstride = framestride + (framewidth + framestride) * 4 * (interlaceskip - 1); // interlaceskip / 2 * 4 is interlaceskip << 1.
18356
18357            op = opbeg + (framewidth + framestride) * (interlaceskip << 1);
18358            interlaceskip >>= 1;
18359          }
18360        }
18361
18362        if (index === trans) {
18363          op += 4;
18364        } else {
18365          var r = buf[palette_offset + index * 3];
18366          var g = buf[palette_offset + index * 3 + 1];
18367          var b = buf[palette_offset + index * 3 + 2];
18368          pixels[op++] = r;
18369          pixels[op++] = g;
18370          pixels[op++] = b;
18371          pixels[op++] = 255;
18372        }
18373
18374        --xleft;
18375      }
18376    };
18377  }
18378
18379  function GifReaderLZWOutputIndexStream(code_stream, p, output, output_length) {
18380    var min_code_size = code_stream[p++];
18381    var clear_code = 1 << min_code_size;
18382    var eoi_code = clear_code + 1;
18383    var next_code = eoi_code + 1;
18384    var cur_code_size = min_code_size + 1; // Number of bits per code.
18385    // NOTE: This shares the same name as the encoder, but has a different
18386    // meaning here.  Here this masks each code coming from the code stream.
18387
18388    var code_mask = (1 << cur_code_size) - 1;
18389    var cur_shift = 0;
18390    var cur = 0;
18391    var op = 0; // Output pointer.
18392
18393    var subblock_size = code_stream[p++]; // TODO(deanm): Would using a TypedArray be any faster?  At least it would
18394    // solve the fast mode / backing store uncertainty.
18395    // var code_table = Array(4096);
18396
18397    var code_table = new Int32Array(4096); // Can be signed, we only use 20 bits.
18398
18399    var prev_code = null; // Track code-1.
18400
18401    while (true) {
18402      // Read up to two bytes, making sure we always 12-bits for max sized code.
18403      while (cur_shift < 16) {
18404        if (subblock_size === 0) break; // No more data to be read.
18405
18406        cur |= code_stream[p++] << cur_shift;
18407        cur_shift += 8;
18408
18409        if (subblock_size === 1) {
18410          // Never let it get to 0 to hold logic above.
18411          subblock_size = code_stream[p++]; // Next subblock.
18412        } else {
18413          --subblock_size;
18414        }
18415      } // TODO(deanm): We should never really get here, we should have received
18416      // and EOI.
18417
18418
18419      if (cur_shift < cur_code_size) break;
18420      var code = cur & code_mask;
18421      cur >>= cur_code_size;
18422      cur_shift -= cur_code_size; // TODO(deanm): Maybe should check that the first code was a clear code,
18423      // at least this is what you're supposed to do.  But actually our encoder
18424      // now doesn't emit a clear code first anyway.
18425
18426      if (code === clear_code) {
18427        // We don't actually have to clear the table.  This could be a good idea
18428        // for greater error checking, but we don't really do any anyway.  We
18429        // will just track it with next_code and overwrite old entries.
18430        next_code = eoi_code + 1;
18431        cur_code_size = min_code_size + 1;
18432        code_mask = (1 << cur_code_size) - 1; // Don't update prev_code ?
18433
18434        prev_code = null;
18435        continue;
18436      } else if (code === eoi_code) {
18437        break;
18438      } // We have a similar situation as the decoder, where we want to store
18439      // variable length entries (code table entries), but we want to do in a
18440      // faster manner than an array of arrays.  The code below stores sort of a
18441      // linked list within the code table, and then "chases" through it to
18442      // construct the dictionary entries.  When a new entry is created, just the
18443      // last byte is stored, and the rest (prefix) of the entry is only
18444      // referenced by its table entry.  Then the code chases through the
18445      // prefixes until it reaches a single byte code.  We have to chase twice,
18446      // first to compute the length, and then to actually copy the data to the
18447      // output (backwards, since we know the length).  The alternative would be
18448      // storing something in an intermediate stack, but that doesn't make any
18449      // more sense.  I implemented an approach where it also stored the length
18450      // in the code table, although it's a bit tricky because you run out of
18451      // bits (12 + 12 + 8), but I didn't measure much improvements (the table
18452      // entries are generally not the long).  Even when I created benchmarks for
18453      // very long table entries the complexity did not seem worth it.
18454      // The code table stores the prefix entry in 12 bits and then the suffix
18455      // byte in 8 bits, so each entry is 20 bits.
18456
18457
18458      var chase_code = code < next_code ? code : prev_code; // Chase what we will output, either {CODE} or {CODE-1}.
18459
18460      var chase_length = 0;
18461      var chase = chase_code;
18462
18463      while (chase > clear_code) {
18464        chase = code_table[chase] >> 8;
18465        ++chase_length;
18466      }
18467
18468      var k = chase;
18469      var op_end = op + chase_length + (chase_code !== code ? 1 : 0);
18470
18471      if (op_end > output_length) {
18472        console.log("Warning, gif stream longer than expected.");
18473        return;
18474      } // Already have the first byte from the chase, might as well write it fast.
18475
18476
18477      output[op++] = k;
18478      op += chase_length;
18479      var b = op; // Track pointer, writing backwards.
18480
18481      if (chase_code !== code) // The case of emitting {CODE-1} + k.
18482        output[op++] = k;
18483      chase = chase_code;
18484
18485      while (chase_length--) {
18486        chase = code_table[chase];
18487        output[--b] = chase & 0xff; // Write backwards.
18488
18489        chase >>= 8; // Pull down to the prefix code.
18490      }
18491
18492      if (prev_code !== null && next_code < 4096) {
18493        code_table[next_code++] = prev_code << 8 | k; // TODO(deanm): Figure out this clearing vs code growth logic better.  I
18494        // have an feeling that it should just happen somewhere else, for now it
18495        // is awkward between when we grow past the max and then hit a clear code.
18496        // For now just check if we hit the max 12-bits (then a clear code should
18497        // follow, also of course encoded in 12-bits).
18498
18499        if (next_code >= code_mask + 1 && cur_code_size < 12) {
18500          ++cur_code_size;
18501          code_mask = code_mask << 1 | 1;
18502        }
18503      }
18504
18505      prev_code = code;
18506    }
18507
18508    if (op !== output_length) {
18509      console.log("Warning, gif stream shorter than expected.");
18510    }
18511
18512    return output;
18513  }
18514
18515  try {
18516    exports.GifWriter = GifWriter;
18517    exports.GifReader = GifReader;
18518  } catch (e) {} // CommonJS.
18519
18520  /*rollup-keeper-start*/
18521
18522
18523  window.tmp = GifReader;
18524  /*rollup-keeper-end*/
18525
18526  /*
18527   * Copyright (c) 2012 chick307 <[email protected]>
18528   *
18529   * Licensed under the MIT License.
18530   * http://opensource.org/licenses/mit-license
18531   */
18532  (function (jsPDF, callback) {
18533    jsPDF.API.adler32cs = callback();
18534  })(jsPDF, function () {
18535    var _hasArrayBuffer = typeof ArrayBuffer === 'function' && typeof Uint8Array === 'function';
18536
18537    var _Buffer = null,
18538        _isBuffer = function () {
18539      if (!_hasArrayBuffer) return function _isBuffer() {
18540        return false;
18541      };
18542
18543      try {
18544        var buffer = {};
18545        if (typeof buffer.Buffer === 'function') _Buffer = buffer.Buffer;
18546      } catch (error) {}
18547
18548      return function _isBuffer(value) {
18549        return value instanceof ArrayBuffer || _Buffer !== null && value instanceof _Buffer;
18550      };
18551    }();
18552
18553    var _utf8ToBinary = function () {
18554      if (_Buffer !== null) {
18555        return function _utf8ToBinary(utf8String) {
18556          return new _Buffer(utf8String, 'utf8').toString('binary');
18557        };
18558      } else {
18559        return function _utf8ToBinary(utf8String) {
18560          return unescape(encodeURIComponent(utf8String));
18561        };
18562      }
18563    }();
18564
18565    var MOD = 65521;
18566
18567    var _update = function _update(checksum, binaryString) {
18568      var a = checksum & 0xFFFF,
18569          b = checksum >>> 16;
18570
18571      for (var i = 0, length = binaryString.length; i < length; i++) {
18572        a = (a + (binaryString.charCodeAt(i) & 0xFF)) % MOD;
18573        b = (b + a) % MOD;
18574      }
18575
18576      return (b << 16 | a) >>> 0;
18577    };
18578
18579    var _updateUint8Array = function _updateUint8Array(checksum, uint8Array) {
18580      var a = checksum & 0xFFFF,
18581          b = checksum >>> 16;
18582
18583      for (var i = 0, length = uint8Array.length; i < length; i++) {
18584        a = (a + uint8Array[i]) % MOD;
18585        b = (b + a) % MOD;
18586      }
18587
18588      return (b << 16 | a) >>> 0;
18589    };
18590
18591    var exports = {};
18592
18593    var Adler32 = exports.Adler32 = function () {
18594      var ctor = function Adler32(checksum) {
18595        if (!(this instanceof ctor)) {
18596          throw new TypeError('Constructor cannot called be as a function.');
18597        }
18598
18599        if (!isFinite(checksum = checksum == null ? 1 : +checksum)) {
18600          throw new Error('First arguments needs to be a finite number.');
18601        }
18602
18603        this.checksum = checksum >>> 0;
18604      };
18605
18606      var proto = ctor.prototype = {};
18607      proto.constructor = ctor;
18608
18609      ctor.from = function (from) {
18610        from.prototype = proto;
18611        return from;
18612      }(function from(binaryString) {
18613        if (!(this instanceof ctor)) {
18614          throw new TypeError('Constructor cannot called be as a function.');
18615        }
18616
18617        if (binaryString == null) throw new Error('First argument needs to be a string.');
18618        this.checksum = _update(1, binaryString.toString());
18619      });
18620
18621      ctor.fromUtf8 = function (fromUtf8) {
18622        fromUtf8.prototype = proto;
18623        return fromUtf8;
18624      }(function fromUtf8(utf8String) {
18625        if (!(this instanceof ctor)) {
18626          throw new TypeError('Constructor cannot called be as a function.');
18627        }
18628
18629        if (utf8String == null) throw new Error('First argument needs to be a string.');
18630
18631        var binaryString = _utf8ToBinary(utf8String.toString());
18632
18633        this.checksum = _update(1, binaryString);
18634      });
18635
18636      if (_hasArrayBuffer) {
18637        ctor.fromBuffer = function (fromBuffer) {
18638          fromBuffer.prototype = proto;
18639          return fromBuffer;
18640        }(function fromBuffer(buffer) {
18641          if (!(this instanceof ctor)) {
18642            throw new TypeError('Constructor cannot called be as a function.');
18643          }
18644
18645          if (!_isBuffer(buffer)) throw new Error('First argument needs to be ArrayBuffer.');
18646          var array = new Uint8Array(buffer);
18647          return this.checksum = _updateUint8Array(1, array);
18648        });
18649      }
18650
18651      proto.update = function update(binaryString) {
18652        if (binaryString == null) throw new Error('First argument needs to be a string.');
18653        binaryString = binaryString.toString();
18654        return this.checksum = _update(this.checksum, binaryString);
18655      };
18656
18657      proto.updateUtf8 = function updateUtf8(utf8String) {
18658        if (utf8String == null) throw new Error('First argument needs to be a string.');
18659
18660        var binaryString = _utf8ToBinary(utf8String.toString());
18661
18662        return this.checksum = _update(this.checksum, binaryString);
18663      };
18664
18665      if (_hasArrayBuffer) {
18666        proto.updateBuffer = function updateBuffer(buffer) {
18667          if (!_isBuffer(buffer)) throw new Error('First argument needs to be ArrayBuffer.');
18668          var array = new Uint8Array(buffer);
18669          return this.checksum = _updateUint8Array(this.checksum, array);
18670        };
18671      }
18672
18673      proto.clone = function clone() {
18674        return new Adler32(this.checksum);
18675      };
18676
18677      return ctor;
18678    }();
18679
18680    exports.from = function from(binaryString) {
18681      if (binaryString == null) throw new Error('First argument needs to be a string.');
18682      return _update(1, binaryString.toString());
18683    };
18684
18685    exports.fromUtf8 = function fromUtf8(utf8String) {
18686      if (utf8String == null) throw new Error('First argument needs to be a string.');
18687
18688      var binaryString = _utf8ToBinary(utf8String.toString());
18689
18690      return _update(1, binaryString);
18691    };
18692
18693    if (_hasArrayBuffer) {
18694      exports.fromBuffer = function fromBuffer(buffer) {
18695        if (!_isBuffer(buffer)) throw new Error('First argument need to be ArrayBuffer.');
18696        var array = new Uint8Array(buffer);
18697        return _updateUint8Array(1, array);
18698      };
18699    }
18700
18701    return exports;
18702  });
18703
18704  /**
18705  * Unicode Bidi Engine based on the work of Alex Shensis (@asthensis)
18706  * MIT License
18707  */
18708  (function (jsPDF) {
18709    /**
18710     * Table of Unicode types.
18711     *
18712     * Generated by:
18713     *
18714     * var bidi = require("./bidi/index");
18715     * var bidi_accumulate = bidi.slice(0, 256).concat(bidi.slice(0x0500, 0x0500 + 256 * 3)).
18716     * concat(bidi.slice(0x2000, 0x2000 + 256)).concat(bidi.slice(0xFB00, 0xFB00 + 256)).
18717     * concat(bidi.slice(0xFE00, 0xFE00 + 2 * 256));
18718     *
18719     * for( var i = 0; i < bidi_accumulate.length; i++) {
18720     * 	if(bidi_accumulate[i] === undefined || bidi_accumulate[i] === 'ON')
18721     * 		bidi_accumulate[i] = 'N'; //mark as neutral to conserve space and substitute undefined
18722     * }
18723     * var bidiAccumulateStr = 'return [ "' + bidi_accumulate.toString().replace(/,/g, '", "') + '" ];';
18724     * require("fs").writeFile('unicode-types.js', bidiAccumulateStr);
18725     *
18726     * Based on:
18727     * https://github.com/mathiasbynens/unicode-8.0.0
18728     */
18729
18730    var bidiUnicodeTypes = ["BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "S", "B", "S", "WS", "B", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "B", "B", "B", "S", "WS", "N", "N", "ET", "ET", "ET", "N", "N", "N", "N", "N", "ES", "CS", "ES", "CS", "CS", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "CS", "N", "N", "N", "N", "N", "N", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "N", "N", "N", "N", "N", "N", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "N", "N", "N", "N", "BN", "BN", "BN", "BN", "BN", "BN", "B", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "CS", "N", "ET", "ET", "ET", "ET", "N", "N", "N", "N", "L", "N", "N", "BN", "N", "N", "ET", "ET", "EN", "EN", "N", "L", "N", "N", "N", "EN", "L", "N", "N", "N", "N", "N", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "N", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "N", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "N", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "N", "N", "L", "L", "L", "L", "L", "L", "L", "N", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "N", "L", "N", "N", "N", "N", "N", "ET", "N", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "R", "NSM", "R", "NSM", "NSM", "R", "NSM", "NSM", "R", "NSM", "N", "N", "N", "N", "N", "N", "N", "N", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "N", "N", "N", "N", "N", "R", "R", "R", "R", "R", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "AN", "AN", "AN", "AN", "AN", "AN", "N", "N", "AL", "ET", "ET", "AL", "CS", "AL", "N", "N", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "N", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "ET", "AN", "AN", "AL", "AL", "AL", "NSM", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AN", "N", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "NSM", "NSM", "N", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "N", "AL", "AL", "NSM", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "N", "N", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AL", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "R", "R", "N", "N", "N", "N", "R", "N", "N", "N", "N", "N", "WS", "WS", "WS", "WS", "WS", "WS", "WS", "WS", "WS", "WS", "WS", "BN", "BN", "BN", "L", "R", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "WS", "B", "LRE", "RLE", "PDF", "LRO", "RLO", "CS", "ET", "ET", "ET", "ET", "ET", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "CS", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "WS", "BN", "BN", "BN", "BN", "BN", "N", "LRI", "RLI", "FSI", "PDI", "BN", "BN", "BN", "BN", "BN", "BN", "EN", "L", "N", "N", "EN", "EN", "EN", "EN", "EN", "EN", "ES", "ES", "N", "N", "N", "L", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "ES", "ES", "N", "N", "N", "N", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "N", "N", "N", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "ET", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "L", "L", "L", "L", "L", "L", "L", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "L", "L", "L", "L", "L", "N", "N", "N", "N", "N", "R", "NSM", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "ES", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "N", "R", "R", "R", "R", "R", "N", "R", "N", "R", "R", "N", "R", "R", "N", "R", "R", "R", "R", "R", "R", "R", "R", "R", "R", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "CS", "N", "CS", "N", "N", "CS", "N", "N", "N", "N", "N", "N", "N", "N", "N", "ET", "N", "N", "ES", "ES", "N", "N", "N", "N", "N", "ET", "ET", "N", "N", "N", "N", "N", "AL", "AL", "AL", "AL", "AL", "N", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "N", "N", "BN", "N", "N", "N", "ET", "ET", "ET", "N", "N", "N", "N", "N", "ES", "CS", "ES", "CS", "CS", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "CS", "N", "N", "N", "N", "N", "N", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "N", "N", "N", "N", "N", "N", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "N", "N", "N", "L", "L", "L", "L", "L", "L", "N", "N", "L", "L", "L", "L", "L", "L", "N", "N", "L", "L", "L", "L", "L", "L", "N", "N", "L", "L", "L", "N", "N", "N", "ET", "ET", "N", "N", "N", "ET", "ET", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N"];
18731    /**
18732     * Unicode Bidi algorithm compliant Bidi engine.
18733     * For reference see http://unicode.org/reports/tr9/
18734    */
18735
18736    /**
18737     * constructor ( options )
18738     *
18739     * Initializes Bidi engine
18740     *
18741     * @param {Object} See 'setOptions' below for detailed description.
18742     * options are cashed between invocation of 'doBidiReorder' method
18743     *
18744     * sample usage pattern of BidiEngine:
18745     * var opt = {
18746     * 	isInputVisual: true,
18747     * 	isInputRtl: false,
18748     * 	isOutputVisual: false,
18749     * 	isOutputRtl: false,
18750     * 	isSymmetricSwapping: true
18751     * }
18752     * var sourceToTarget = [], levels = [];
18753     * var bidiEng = Globalize.bidiEngine(opt);
vendor: 18,181 bytes, lines 18754-19328
18754     * var src = "text string to be reordered";
18755     * var ret = bidiEng.doBidiReorder(src, sourceToTarget, levels);
18756     */
18757
18758    jsPDF.__bidiEngine__ = jsPDF.prototype.__bidiEngine__ = function (options) {
18759      var _UNICODE_TYPES = _bidiUnicodeTypes;
18760      var _STATE_TABLE_LTR = [[0, 3, 0, 1, 0, 0, 0], [0, 3, 0, 1, 2, 2, 0], [0, 3, 0, 0x11, 2, 0, 1], [0, 3, 5, 5, 4, 1, 0], [0, 3, 0x15, 0x15, 4, 0, 1], [0, 3, 5, 5, 4, 2, 0]];
18761      var _STATE_TABLE_RTL = [[2, 0, 1, 1, 0, 1, 0], [2, 0, 1, 1, 0, 2, 0], [2, 0, 2, 1, 3, 2, 0], [2, 0, 2, 0x21, 3, 1, 1]];
18762      var _TYPE_NAMES_MAP = {
18763        "L": 0,
18764        "R": 1,
18765        "EN": 2,
18766        "AN": 3,
18767        "N": 4,
18768        "B": 5,
18769        "S": 6
18770      };
18771      var _UNICODE_RANGES_MAP = {
18772        0: 0,
18773        5: 1,
18774        6: 2,
18775        7: 3,
18776        0x20: 4,
18777        0xFB: 5,
18778        0xFE: 6,
18779        0xFF: 7
18780      };
18781      var _SWAP_TABLE = ["(", ")", "(", "<", ">", "<", "[", "]", "[", "{", "}", "{", "\xAB", "\xBB", "\xAB", "\u2039", "\u203A", "\u2039", "\u2045", "\u2046", "\u2045", "\u207D", "\u207E", "\u207D", "\u208D", "\u208E", "\u208D", "\u2264", "\u2265", "\u2264", "\u2329", "\u232A", "\u2329", "\uFE59", "\uFE5A", "\uFE59", "\uFE5B", "\uFE5C", "\uFE5B", "\uFE5D", "\uFE5E", "\uFE5D", "\uFE64", "\uFE65", "\uFE64"];
18782
18783      var _LTR_RANGES_REG_EXPR = new RegExp(/^([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)$/);
18784
18785      var _lastArabic = false,
18786          _hasUbatB,
18787          _hasUbatS,
18788          DIR_LTR = 0,
18789          DIR_RTL = 1,
18790          _isInVisual,
18791          _isInRtl,
18792          _isOutVisual,
18793          _isOutRtl,
18794          _isSymmetricSwapping,
18795          _dir = DIR_LTR;
18796
18797      this.__bidiEngine__ = {};
18798
18799      var _init = function _init(text, sourceToTargetMap) {
18800        if (sourceToTargetMap) {
18801          for (var i = 0; i < text.length; i++) {
18802            sourceToTargetMap[i] = i;
18803          }
18804        }
18805
18806        if (_isInRtl === undefined) {
18807          _isInRtl = _isContextualDirRtl(text);
18808        }
18809
18810        if (_isOutRtl === undefined) {
18811          _isOutRtl = _isContextualDirRtl(text);
18812        }
18813      }; // for reference see 3.2 in http://unicode.org/reports/tr9/
18814      //
18815
18816
18817      var _getCharType = function _getCharType(ch) {
18818        var charCode = ch.charCodeAt(),
18819            range = charCode >> 8,
18820            rangeIdx = _UNICODE_RANGES_MAP[range];
18821
18822        if (rangeIdx !== undefined) {
18823          return _UNICODE_TYPES[rangeIdx * 256 + (charCode & 0xFF)];
18824        } else if (range === 0xFC || range === 0xFD) {
18825          return "AL";
18826        } else if (_LTR_RANGES_REG_EXPR.test(range)) {
18827          //unlikely case
18828          return "L";
18829        } else if (range === 8) {
18830          // even less likely
18831          return "R";
18832        }
18833
18834        return "N"; //undefined type, mark as neutral
18835      };
18836
18837      var _isContextualDirRtl = function _isContextualDirRtl(text) {
18838        for (var i = 0, charType; i < text.length; i++) {
18839          charType = _getCharType(text.charAt(i));
18840
18841          if (charType === "L") {
18842            return false;
18843          } else if (charType === "R") {
18844            return true;
18845          }
18846        }
18847
18848        return false;
18849      }; // for reference see 3.3.4 & 3.3.5 in http://unicode.org/reports/tr9/
18850      //
18851
18852
18853      var _resolveCharType = function _resolveCharType(chars, types, resolvedTypes, index) {
18854        var cType = types[index],
18855            wType,
18856            nType,
18857            i,
18858            len;
18859
18860        switch (cType) {
18861          case "L":
18862          case "R":
18863            _lastArabic = false;
18864            break;
18865
18866          case "N":
18867          case "AN":
18868            break;
18869
18870          case "EN":
18871            if (_lastArabic) {
18872              cType = "AN";
18873            }
18874
18875            break;
18876
18877          case "AL":
18878            _lastArabic = true;
18879            cType = "R";
18880            break;
18881
18882          case "WS":
18883            cType = "N";
18884            break;
18885
18886          case "CS":
18887            if (index < 1 || index + 1 >= types.length || (wType = resolvedTypes[index - 1]) !== "EN" && wType !== "AN" || (nType = types[index + 1]) !== "EN" && nType !== "AN") {
18888              cType = "N";
18889            } else if (_lastArabic) {
18890              nType = "AN";
18891            }
18892
18893            cType = nType === wType ? nType : "N";
18894            break;
18895
18896          case "ES":
18897            wType = index > 0 ? resolvedTypes[index - 1] : "B";
18898            cType = wType === "EN" && index + 1 < types.length && types[index + 1] === "EN" ? "EN" : "N";
18899            break;
18900
18901          case "ET":
18902            if (index > 0 && resolvedTypes[index - 1] === "EN") {
18903              cType = "EN";
18904              break;
18905            } else if (_lastArabic) {
18906              cType = "N";
18907              break;
18908            }
18909
18910            i = index + 1;
18911            len = types.length;
18912
18913            while (i < len && types[i] === "ET") {
18914              i++;
18915            }
18916
18917            if (i < len && types[i] === "EN") {
18918              cType = "EN";
18919            } else {
18920              cType = "N";
18921            }
18922
18923            break;
18924
18925          case "NSM":
18926            if (_isInVisual && !_isInRtl) {
18927              //V->L
18928              len = types.length;
18929              i = index + 1;
18930
18931              while (i < len && types[i] === "NSM") {
18932                i++;
18933              }
18934
18935              if (i < len) {
18936                var c = chars[index];
18937                var rtlCandidate = c >= 0x0591 && c <= 0x08FF || c === 0xFB1E;
18938                wType = types[i];
18939
18940                if (rtlCandidate && (wType === "R" || wType === "AL")) {
18941                  cType = "R";
18942                  break;
18943                }
18944              }
18945            }
18946
18947            if (index < 1 || (wType = types[index - 1]) === "B") {
18948              cType = "N";
18949            } else {
18950              cType = resolvedTypes[index - 1];
18951            }
18952
18953            break;
18954
18955          case "B":
18956            _lastArabic = false;
18957            _hasUbatB = true;
18958            cType = _dir;
18959            break;
18960
18961          case "S":
18962            _hasUbatS = true;
18963            cType = "N";
18964            break;
18965
18966          case "LRE":
18967          case "RLE":
18968          case "LRO":
18969          case "RLO":
18970          case "PDF":
18971            _lastArabic = false;
18972            break;
18973
18974          case "BN":
18975            cType = "N";
18976            break;
18977        }
18978
18979        return cType;
18980      };
18981
18982      var _handleUbatS = function _handleUbatS(types, levels, length) {
18983        for (var i = 0; i < length; i++) {
18984          if (types[i] === "S") {
18985            levels[i] = _dir;
18986
18987            for (var j = i - 1; j >= 0; j--) {
18988              if (types[j] === "WS") {
18989                levels[j] = _dir;
18990              } else {
18991                break;
18992              }
18993            }
18994          }
18995        }
18996      };
18997
18998      var _invertString = function _invertString(text, sourceToTargetMap, levels) {
18999        var charArray = text.split("");
19000
19001        if (levels) {
19002          _computeLevels(charArray, levels, {
19003            hiLevel: _dir
19004          });
19005        }
19006
19007        charArray.reverse();
19008        sourceToTargetMap && sourceToTargetMap.reverse();
19009        return charArray.join("");
19010      }; // For reference see 3.3 in http://unicode.org/reports/tr9/
19011      //
19012
19013
19014      var _computeLevels = function _computeLevels(chars, levels, params) {
19015        var action,
19016            condition,
19017            i,
19018            index,
19019            newLevel,
19020            prevState,
19021            condPos = -1,
19022            len = chars.length,
19023            newState = 0,
19024            resolvedTypes = [],
19025            stateTable = _dir ? _STATE_TABLE_RTL : _STATE_TABLE_LTR,
19026            types = [];
19027        _lastArabic = false;
19028        _hasUbatB = false;
19029        _hasUbatS = false;
19030
19031        for (i = 0; i < len; i++) {
19032          types[i] = _getCharType(chars[i]);
19033        }
19034
19035        for (index = 0; index < len; index++) {
19036          prevState = newState;
19037          resolvedTypes[index] = _resolveCharType(chars, types, resolvedTypes, index);
19038          newState = stateTable[prevState][_TYPE_NAMES_MAP[resolvedTypes[index]]];
19039          action = newState & 0xF0;
19040          newState &= 0x0F;
19041          levels[index] = newLevel = stateTable[newState][5];
19042
19043          if (action > 0) {
19044            if (action === 0x10) {
19045              for (i = condPos; i < index; i++) {
19046                levels[i] = 1;
19047              }
19048
19049              condPos = -1;
19050            } else {
19051              condPos = -1;
19052            }
19053          }
19054
19055          condition = stateTable[newState][6];
19056
19057          if (condition) {
19058            if (condPos === -1) {
19059              condPos = index;
19060            }
19061          } else {
19062            if (condPos > -1) {
19063              for (i = condPos; i < index; i++) {
19064                levels[i] = newLevel;
19065              }
19066
19067              condPos = -1;
19068            }
19069          }
19070
19071          if (types[index] === "B") {
19072            levels[index] = 0;
19073          }
19074
19075          params.hiLevel |= newLevel;
19076        }
19077
19078        if (_hasUbatS) {
19079          _handleUbatS(types, levels, len);
19080        }
19081      }; // for reference see 3.4 in http://unicode.org/reports/tr9/
19082      //
19083
19084
19085      var _invertByLevel = function _invertByLevel(level, charArray, sourceToTargetMap, levels, params) {
19086        if (params.hiLevel < level) {
19087          return;
19088        }
19089
19090        if (level === 1 && _dir === DIR_RTL && !_hasUbatB) {
19091          charArray.reverse();
19092          sourceToTargetMap && sourceToTargetMap.reverse();
19093          return;
19094        }
19095
19096        var ch,
19097            high,
19098            end,
19099            low,
19100            len = charArray.length,
19101            start = 0;
19102
19103        while (start < len) {
19104          if (levels[start] >= level) {
19105            end = start + 1;
19106
19107            while (end < len && levels[end] >= level) {
19108              end++;
19109            }
19110
19111            for (low = start, high = end - 1; low < high; low++, high--) {
19112              ch = charArray[low];
19113              charArray[low] = charArray[high];
19114              charArray[high] = ch;
19115
19116              if (sourceToTargetMap) {
19117                ch = sourceToTargetMap[low];
19118                sourceToTargetMap[low] = sourceToTargetMap[high];
19119                sourceToTargetMap[high] = ch;
19120              }
19121            }
19122
19123            start = end;
19124          }
19125
19126          start++;
19127        }
19128      }; // for reference see 7 & BD16 in http://unicode.org/reports/tr9/
19129      //
19130
19131
19132      var _symmetricSwap = function _symmetricSwap(charArray, levels, params) {
19133        if (params.hiLevel !== 0 && _isSymmetricSwapping) {
19134          for (var i = 0, index; i < charArray.length; i++) {
19135            if (levels[i] === 1) {
19136              index = _SWAP_TABLE.indexOf(charArray[i]);
19137
19138              if (index >= 0) {
19139                charArray[i] = _SWAP_TABLE[index + 1];
19140              }
19141            }
19142          }
19143        }
19144      };
19145
19146      var _reorder = function _reorder(text, sourceToTargetMap, levels) {
19147        var charArray = text.split(""),
19148            params = {
19149          hiLevel: _dir
19150        };
19151
19152        if (!levels) {
19153          levels = [];
19154        }
19155
19156        _computeLevels(charArray, levels, params);
19157
19158        _symmetricSwap(charArray, levels, params);
19159
19160        _invertByLevel(DIR_RTL + 1, charArray, sourceToTargetMap, levels, params);
19161
19162        _invertByLevel(DIR_RTL, charArray, sourceToTargetMap, levels, params);
19163
19164        return charArray.join("");
19165      }; // doBidiReorder( text, sourceToTargetMap, levels )
19166      // Performs Bidi reordering by implementing Unicode Bidi algorithm.
19167      // Returns reordered string
19168      // @text [String]:
19169      // - input string to be reordered, this is input parameter
19170      // $sourceToTargetMap [Array] (optional)
19171      // - resultant mapping between input and output strings, this is output parameter
19172      // $levels [Array] (optional)
19173      // - array of calculated Bidi levels, , this is output parameter
19174
19175
19176      this.__bidiEngine__.doBidiReorder = function (text, sourceToTargetMap, levels) {
19177        _init(text, sourceToTargetMap);
19178
19179        if (!_isInVisual && _isOutVisual && !_isOutRtl) {
19180          // LLTR->VLTR, LRTL->VLTR
19181          _dir = _isInRtl ? DIR_RTL : DIR_LTR;
19182          text = _reorder(text, sourceToTargetMap, levels);
19183        } else if (_isInVisual && _isOutVisual && _isInRtl ^ _isOutRtl) {
19184          // VRTL->VLTR, VLTR->VRTL
19185          _dir = _isInRtl ? DIR_RTL : DIR_LTR;
19186          text = _invertString(text, sourceToTargetMap, levels);
19187        } else if (!_isInVisual && _isOutVisual && _isOutRtl) {
19188          // LLTR->VRTL, LRTL->VRTL
19189          _dir = _isInRtl ? DIR_RTL : DIR_LTR;
19190          text = _reorder(text, sourceToTargetMap, levels);
19191          text = _invertString(text, sourceToTargetMap);
19192        } else if (_isInVisual && !_isInRtl && !_isOutVisual && !_isOutRtl) {
19193          // VLTR->LLTR
19194          _dir = DIR_LTR;
19195          text = _reorder(text, sourceToTargetMap, levels);
19196        } else if (_isInVisual && !_isOutVisual && _isInRtl ^ _isOutRtl) {
19197          // VLTR->LRTL, VRTL->LLTR
19198          text = _invertString(text, sourceToTargetMap);
19199
19200          if (_isInRtl) {
19201            //LLTR -> VLTR
19202            _dir = DIR_LTR;
19203            text = _reorder(text, sourceToTargetMap, levels);
19204          } else {
19205            //LRTL -> VRTL
19206            _dir = DIR_RTL;
19207            text = _reorder(text, sourceToTargetMap, levels);
19208            text = _invertString(text, sourceToTargetMap);
19209          }
19210        } else if (_isInVisual && _isInRtl && !_isOutVisual && _isOutRtl) {
19211          //  VRTL->LRTL
19212          _dir = DIR_RTL;
19213          text = _reorder(text, sourceToTargetMap, levels);
19214          text = _invertString(text, sourceToTargetMap);
19215        } else if (!_isInVisual && !_isOutVisual && _isInRtl ^ _isOutRtl) {
19216          // LRTL->LLTR, LLTR->LRTL
19217          var isSymmetricSwappingOrig = _isSymmetricSwapping;
19218
19219          if (_isInRtl) {
19220            //LRTL->LLTR
19221            _dir = DIR_RTL;
19222            text = _reorder(text, sourceToTargetMap, levels);
19223            _dir = DIR_LTR;
19224            _isSymmetricSwapping = false;
19225            text = _reorder(text, sourceToTargetMap, levels);
19226            _isSymmetricSwapping = isSymmetricSwappingOrig;
19227          } else {
19228            //LLTR->LRTL
19229            _dir = DIR_LTR;
19230            text = _reorder(text, sourceToTargetMap, levels);
19231            text = _invertString(text, sourceToTargetMap);
19232            _dir = DIR_RTL;
19233            _isSymmetricSwapping = false;
19234            text = _reorder(text, sourceToTargetMap, levels);
19235            _isSymmetricSwapping = isSymmetricSwappingOrig;
19236            text = _invertString(text, sourceToTargetMap);
19237          }
19238        }
19239
19240        return text;
19241      };
19242      /**
19243      * @name setOptions( options )
19244      * @function 
19245      * Sets options for Bidi conversion
19246      * @param {Object}:
19247      * - isInputVisual {boolean} (defaults to false): allowed values: true(Visual mode), false(Logical mode)
19248      * - 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)
19249      * - isOutputVisual {boolean} (defaults to false): allowed values: true(Visual mode), false(Logical mode)
19250      * - 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)
19251      * - isSymmetricSwapping {boolean} (defaults to false): allowed values true(needs symmetric swapping), false (no need in symmetric swapping),
19252      */
19253
19254
19255      this.__bidiEngine__.setOptions = function (options) {
19256        if (options) {
19257          _isInVisual = options.isInputVisual;
19258          _isOutVisual = options.isOutputVisual;
19259          _isInRtl = options.isInputRtl;
19260          _isOutRtl = options.isOutputRtl;
19261          _isSymmetricSwapping = options.isSymmetricSwapping;
19262        }
19263      };
19264
19265      this.__bidiEngine__.setOptions(options);
19266
19267      return this.__bidiEngine__;
19268    };
19269
19270    var _bidiUnicodeTypes = bidiUnicodeTypes;
19271    var bidiEngine = new jsPDF.__bidiEngine__({
19272      isInputVisual: true
19273    });
19274
19275    var bidiEngineFunction = function bidiEngineFunction(args) {
19276      var text = args.text;
19277      var x = args.x;
19278      var y = args.y;
19279      var options = args.options || {};
19280      var mutex = args.mutex || {};
19281      var lang = options.lang;
19282      var tmpText = [];
19283
19284      if (Object.prototype.toString.call(text) === '[object Array]') {
19285        var i = 0;
19286        tmpText = [];
19287
19288        for (i = 0; i < text.length; i += 1) {
19289          if (Object.prototype.toString.call(text[i]) === '[object Array]') {
19290            tmpText.push([bidiEngine.doBidiReorder(text[i][0]), text[i][1], text[i][2]]);
19291          } else {
19292            tmpText.push([bidiEngine.doBidiReorder(text[i])]);
19293          }
19294        }
19295
19296        args.text = tmpText;
19297      } else {
19298        args.text = bidiEngine.doBidiReorder(text);
19299      }
19300    };
19301
19302    jsPDF.API.events.push(['postProcessText', bidiEngineFunction]);
19303  })(jsPDF);
19304
19305  /*
19306    Copyright (c) 2008, Adobe Systems Incorporated
19307    All rights reserved.
19308
19309    Redistribution and use in source and binary forms, with or without 
19310    modification, are permitted provided that the following conditions are
19311    met:
19312
19313    * Redistributions of source code must retain the above copyright notice, 
19314      this list of conditions and the following disclaimer.
19315    
19316    * Redistributions in binary form must reproduce the above copyright
19317      notice, this list of conditions and the following disclaimer in the 
19318      documentation and/or other materials provided with the distribution.
19319    
19320    * Neither the name of Adobe Systems Incorporated nor the names of its 
19321      contributors may be used to endorse or promote products derived from 
19322      this software without specific prior written permission.
19323
19324    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
19325    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19326    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19327    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
19328    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19329    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19330    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19331    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19332    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
19333    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19334    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19335  */
19336
19337  /*
19338  JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009
19339
19340  Basic GUI blocking jpeg encoder
19341  */
19342  function JPEGEncoder(quality) {
19343    var ffloor = Math.floor;
19344    var YTable = new Array(64);
19345    var UVTable = new Array(64);
19346    var fdtbl_Y = new Array(64);
19347    var fdtbl_UV = new Array(64);
19348    var YDC_HT;
19349    var UVDC_HT;
19350    var YAC_HT;
19351    var UVAC_HT;
19352    var bitcode = new Array(65535);
19353    var category = new Array(65535);
19354    var outputfDCTQuant = new Array(64);
19355    var DU = new Array(64);
19356    var byteout = [];
19357    var bytenew = 0;
19358    var bytepos = 7;
19359    var YDU = new Array(64);
19360    var UDU = new Array(64);
19361    var VDU = new Array(64);
19362    var clt = new Array(256);
19363    var RGB_YUV_TABLE = new Array(2048);
19364    var currentQuality;
19365    var ZigZag = [0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63];
19366    var std_dc_luminance_nrcodes = [0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0];
19367    var std_dc_luminance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
19368    var std_ac_luminance_nrcodes = [0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d];
19369    var std_ac_luminance_values = [0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa];
19370    var std_dc_chrominance_nrcodes = [0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0];
19371    var std_dc_chrominance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
19372    var std_ac_chrominance_nrcodes = [0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77];
19373    var std_ac_chrominance_values = [0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa];
19374
19375    function initQuantTables(sf) {
19376      var YQT = [16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 
vendor: 11,745 bytes, lines 19376-19864
19376121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99];
19377
19378      for (var i = 0; i < 64; i++) {
19379        var t = ffloor((YQT[i] * sf + 50) / 100);
19380
19381        if (t < 1) {
19382          t = 1;
19383        } else if (t > 255) {
19384          t = 255;
19385        }
19386
19387        YTable[ZigZag[i]] = t;
19388      }
19389
19390      var UVQT = [17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99];
19391
19392      for (var j = 0; j < 64; j++) {
19393        var u = ffloor((UVQT[j] * sf + 50) / 100);
19394
19395        if (u < 1) {
19396          u = 1;
19397        } else if (u > 255) {
19398          u = 255;
19399        }
19400
19401        UVTable[ZigZag[j]] = u;
19402      }
19403
19404      var aasf = [1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 0.785694958, 0.541196100, 0.275899379];
19405      var k = 0;
19406
19407      for (var row = 0; row < 8; row++) {
19408        for (var col = 0; col < 8; col++) {
19409          fdtbl_Y[k] = 1.0 / (YTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0);
19410          fdtbl_UV[k] = 1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0);
19411          k++;
19412        }
19413      }
19414    }
19415
19416    function computeHuffmanTbl(nrcodes, std_table) {
19417      var codevalue = 0;
19418      var pos_in_table = 0;
19419      var HT = new Array();
19420
19421      for (var k = 1; k <= 16; k++) {
19422        for (var j = 1; j <= nrcodes[k]; j++) {
19423          HT[std_table[pos_in_table]] = [];
19424          HT[std_table[pos_in_table]][0] = codevalue;
19425          HT[std_table[pos_in_table]][1] = k;
19426          pos_in_table++;
19427          codevalue++;
19428        }
19429
19430        codevalue *= 2;
19431      }
19432
19433      return HT;
19434    }
19435
19436    function initHuffmanTbl() {
19437      YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes, std_dc_luminance_values);
19438      UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes, std_dc_chrominance_values);
19439      YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes, std_ac_luminance_values);
19440      UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes, std_ac_chrominance_values);
19441    }
19442
19443    function initCategoryNumber() {
19444      var nrlower = 1;
19445      var nrupper = 2;
19446
19447      for (var cat = 1; cat <= 15; cat++) {
19448        //Positive numbers
19449        for (var nr = nrlower; nr < nrupper; nr++) {
19450          category[32767 + nr] = cat;
19451          bitcode[32767 + nr] = [];
19452          bitcode[32767 + nr][1] = cat;
19453          bitcode[32767 + nr][0] = nr;
19454        } //Negative numbers
19455
19456
19457        for (var nrneg = -(nrupper - 1); nrneg <= -nrlower; nrneg++) {
19458          category[32767 + nrneg] = cat;
19459          bitcode[32767 + nrneg] = [];
19460          bitcode[32767 + nrneg][1] = cat;
19461          bitcode[32767 + nrneg][0] = nrupper - 1 + nrneg;
19462        }
19463
19464        nrlower <<= 1;
19465        nrupper <<= 1;
19466      }
19467    }
19468
19469    function initRGBYUVTable() {
19470      for (var i = 0; i < 256; i++) {
19471        RGB_YUV_TABLE[i] = 19595 * i;
19472        RGB_YUV_TABLE[i + 256 >> 0] = 38470 * i;
19473        RGB_YUV_TABLE[i + 512 >> 0] = 7471 * i + 0x8000;
19474        RGB_YUV_TABLE[i + 768 >> 0] = -11059 * i;
19475        RGB_YUV_TABLE[i + 1024 >> 0] = -21709 * i;
19476        RGB_YUV_TABLE[i + 1280 >> 0] = 32768 * i + 0x807FFF;
19477        RGB_YUV_TABLE[i + 1536 >> 0] = -27439 * i;
19478        RGB_YUV_TABLE[i + 1792 >> 0] = -5329 * i;
19479      }
19480    } // IO functions
19481
19482
19483    function writeBits(bs) {
19484      var value = bs[0];
19485      var posval = bs[1] - 1;
19486
19487      while (posval >= 0) {
19488        if (value & 1 << posval) {
19489          bytenew |= 1 << bytepos;
19490        }
19491
19492        posval--;
19493        bytepos--;
19494
19495        if (bytepos < 0) {
19496          if (bytenew == 0xFF) {
19497            writeByte(0xFF);
19498            writeByte(0);
19499          } else {
19500            writeByte(bytenew);
19501          }
19502
19503          bytepos = 7;
19504          bytenew = 0;
19505        }
19506      }
19507    }
19508
19509    function writeByte(value) {
19510      //byteout.push(clt[value]); // write char directly instead of converting later
19511      byteout.push(value);
19512    }
19513
19514    function writeWord(value) {
19515      writeByte(value >> 8 & 0xFF);
19516      writeByte(value & 0xFF);
19517    } // DCT & quantization core
19518
19519
19520    function fDCTQuant(data, fdtbl) {
19521      var d0, d1, d2, d3, d4, d5, d6, d7;
19522      /* Pass 1: process rows. */
19523
19524      var dataOff = 0;
19525      var i;
19526      var I8 = 8;
19527      var I64 = 64;
19528
19529      for (i = 0; i < I8; ++i) {
19530        d0 = data[dataOff];
19531        d1 = data[dataOff + 1];
19532        d2 = data[dataOff + 2];
19533        d3 = data[dataOff + 3];
19534        d4 = data[dataOff + 4];
19535        d5 = data[dataOff + 5];
19536        d6 = data[dataOff + 6];
19537        d7 = data[dataOff + 7];
19538        var tmp0 = d0 + d7;
19539        var tmp7 = d0 - d7;
19540        var tmp1 = d1 + d6;
19541        var tmp6 = d1 - d6;
19542        var tmp2 = d2 + d5;
19543        var tmp5 = d2 - d5;
19544        var tmp3 = d3 + d4;
19545        var tmp4 = d3 - d4;
19546        /* Even part */
19547
19548        var tmp10 = tmp0 + tmp3;
19549        /* phase 2 */
19550
19551        var tmp13 = tmp0 - tmp3;
19552        var tmp11 = tmp1 + tmp2;
19553        var tmp12 = tmp1 - tmp2;
19554        data[dataOff] = tmp10 + tmp11;
19555        /* phase 3 */
19556
19557        data[dataOff + 4] = tmp10 - tmp11;
19558        var z1 = (tmp12 + tmp13) * 0.707106781;
19559        /* c4 */
19560
19561        data[dataOff + 2] = tmp13 + z1;
19562        /* phase 5 */
19563
19564        data[dataOff + 6] = tmp13 - z1;
19565        /* Odd part */
19566
19567        tmp10 = tmp4 + tmp5;
19568        /* phase 2 */
19569
19570        tmp11 = tmp5 + tmp6;
19571        tmp12 = tmp6 + tmp7;
19572        /* The rotator is modified from fig 4-8 to avoid extra negations. */
19573
19574        var z5 = (tmp10 - tmp12) * 0.382683433;
19575        /* c6 */
19576
19577        var z2 = 0.541196100 * tmp10 + z5;
19578        /* c2-c6 */
19579
19580        var z4 = 1.306562965 * tmp12 + z5;
19581        /* c2+c6 */
19582
19583        var z3 = tmp11 * 0.707106781;
19584        /* c4 */
19585
19586        var z11 = tmp7 + z3;
19587        /* phase 5 */
19588
19589        var z13 = tmp7 - z3;
19590        data[dataOff + 5] = z13 + z2;
19591        /* phase 6 */
19592
19593        data[dataOff + 3] = z13 - z2;
19594        data[dataOff + 1] = z11 + z4;
19595        data[dataOff + 7] = z11 - z4;
19596        dataOff += 8;
19597        /* advance pointer to next row */
19598      }
19599      /* Pass 2: process columns. */
19600
19601
19602      dataOff = 0;
19603
19604      for (i = 0; i < I8; ++i) {
19605        d0 = data[dataOff];
19606        d1 = data[dataOff + 8];
19607        d2 = data[dataOff + 16];
19608        d3 = data[dataOff + 24];
19609        d4 = data[dataOff + 32];
19610        d5 = data[dataOff + 40];
19611        d6 = data[dataOff + 48];
19612        d7 = data[dataOff + 56];
19613        var tmp0p2 = d0 + d7;
19614        var tmp7p2 = d0 - d7;
19615        var tmp1p2 = d1 + d6;
19616        var tmp6p2 = d1 - d6;
19617        var tmp2p2 = d2 + d5;
19618        var tmp5p2 = d2 - d5;
19619        var tmp3p2 = d3 + d4;
19620        var tmp4p2 = d3 - d4;
19621        /* Even part */
19622
19623        var tmp10p2 = tmp0p2 + tmp3p2;
19624        /* phase 2 */
19625
19626        var tmp13p2 = tmp0p2 - tmp3p2;
19627        var tmp11p2 = tmp1p2 + tmp2p2;
19628        var tmp12p2 = tmp1p2 - tmp2p2;
19629        data[dataOff] = tmp10p2 + tmp11p2;
19630        /* phase 3 */
19631
19632        data[dataOff + 32] = tmp10p2 - tmp11p2;
19633        var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781;
19634        /* c4 */
19635
19636        data[dataOff + 16] = tmp13p2 + z1p2;
19637        /* phase 5 */
19638
19639        data[dataOff + 48] = tmp13p2 - z1p2;
19640        /* Odd part */
19641
19642        tmp10p2 = tmp4p2 + tmp5p2;
19643        /* phase 2 */
19644
19645        tmp11p2 = tmp5p2 + tmp6p2;
19646        tmp12p2 = tmp6p2 + tmp7p2;
19647        /* The rotator is modified from fig 4-8 to avoid extra negations. */
19648
19649        var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433;
19650        /* c6 */
19651
19652        var z2p2 = 0.541196100 * tmp10p2 + z5p2;
19653        /* c2-c6 */
19654
19655        var z4p2 = 1.306562965 * tmp12p2 + z5p2;
19656        /* c2+c6 */
19657
19658        var z3p2 = tmp11p2 * 0.707106781;
19659        /* c4 */
19660
19661        var z11p2 = tmp7p2 + z3p2;
19662        /* phase 5 */
19663
19664        var z13p2 = tmp7p2 - z3p2;
19665        data[dataOff + 40] = z13p2 + z2p2;
19666        /* phase 6 */
19667
19668        data[dataOff + 24] = z13p2 - z2p2;
19669        data[dataOff + 8] = z11p2 + z4p2;
19670        data[dataOff + 56] = z11p2 - z4p2;
19671        dataOff++;
19672        /* advance pointer to next column */
19673      } // Quantize/descale the coefficients
19674
19675
19676      var fDCTQuant;
19677
19678      for (i = 0; i < I64; ++i) {
19679        // Apply the quantization and scaling factor & Round to nearest integer
19680        fDCTQuant = data[i] * fdtbl[i];
19681        outputfDCTQuant[i] = fDCTQuant > 0.0 ? fDCTQuant + 0.5 | 0 : fDCTQuant - 0.5 | 0; //outputfDCTQuant[i] = fround(fDCTQuant);
19682      }
19683
19684      return outputfDCTQuant;
19685    }
19686
19687    function writeAPP0() {
19688      writeWord(0xFFE0); // marker
19689
19690      writeWord(16); // length
19691
19692      writeByte(0x4A); // J
19693
19694      writeByte(0x46); // F
19695
19696      writeByte(0x49); // I
19697
19698      writeByte(0x46); // F
19699
19700      writeByte(0); // = "JFIF",'\0'
19701
19702      writeByte(1); // versionhi
19703
19704      writeByte(1); // versionlo
19705
19706      writeByte(0); // xyunits
19707
19708      writeWord(1); // xdensity
19709
19710      writeWord(1); // ydensity
19711
19712      writeByte(0); // thumbnwidth
19713
19714      writeByte(0); // thumbnheight
19715    }
19716
19717    function writeSOF0(width, height) {
19718      writeWord(0xFFC0); // marker
19719
19720      writeWord(17); // length, truecolor YUV JPG
19721
19722      writeByte(8); // precision
19723
19724      writeWord(height);
19725      writeWord(width);
19726      writeByte(3); // nrofcomponents
19727
19728      writeByte(1); // IdY
19729
19730      writeByte(0x11); // HVY
19731
19732      writeByte(0); // QTY
19733
19734      writeByte(2); // IdU
19735
19736      writeByte(0x11); // HVU
19737
19738      writeByte(1); // QTU
19739
19740      writeByte(3); // IdV
19741
19742      writeByte(0x11); // HVV
19743
19744      writeByte(1); // QTV
19745    }
19746
19747    function writeDQT() {
19748      writeWord(0xFFDB); // marker
19749
19750      writeWord(132); // length
19751
19752      writeByte(0);
19753
19754      for (var i = 0; i < 64; i++) {
19755        writeByte(YTable[i]);
19756      }
19757
19758      writeByte(1);
19759
19760      for (var j = 0; j < 64; j++) {
19761        writeByte(UVTable[j]);
19762      }
19763    }
19764
19765    function writeDHT() {
19766      writeWord(0xFFC4); // marker
19767
19768      writeWord(0x01A2); // length
19769
19770      writeByte(0); // HTYDCinfo
19771
19772      for (var i = 0; i < 16; i++) {
19773        writeByte(std_dc_luminance_nrcodes[i + 1]);
19774      }
19775
19776      for (var j = 0; j <= 11; j++) {
19777        writeByte(std_dc_luminance_values[j]);
19778      }
19779
19780      writeByte(0x10); // HTYACinfo
19781
19782      for (var k = 0; k < 16; k++) {
19783        writeByte(std_ac_luminance_nrcodes[k + 1]);
19784      }
19785
19786      for (var l = 0; l <= 161; l++) {
19787        writeByte(std_ac_luminance_values[l]);
19788      }
19789
19790      writeByte(1); // HTUDCinfo
19791
19792      for (var m = 0; m < 16; m++) {
19793        writeByte(std_dc_chrominance_nrcodes[m + 1]);
19794      }
19795
19796      for (var n = 0; n <= 11; n++) {
19797        writeByte(std_dc_chrominance_values[n]);
19798      }
19799
19800      writeByte(0x11); // HTUACinfo
19801
19802      for (var o = 0; o < 16; o++) {
19803        writeByte(std_ac_chrominance_nrcodes[o + 1]);
19804      }
19805
19806      for (var p = 0; p <= 161; p++) {
19807        writeByte(std_ac_chrominance_values[p]);
19808      }
19809    }
19810
19811    function writeSOS() {
19812      writeWord(0xFFDA); // marker
19813
19814      writeWord(12); // length
19815
19816      writeByte(3); // nrofcomponents
19817
19818      writeByte(1); // IdY
19819
19820      writeByte(0); // HTY
19821
19822      writeByte(2); // IdU
19823
19824      writeByte(0x11); // HTU
19825
19826      writeByte(3); // IdV
19827
19828      writeByte(0x11); // HTV
19829
19830      writeByte(0); // Ss
19831
19832      writeByte(0x3f); // Se
19833
19834      writeByte(0); // Bf
19835    }
19836
19837    function processDU(CDU, fdtbl, DC, HTDC, HTAC) {
19838      var EOB = HTAC[0x00];
19839      var M16zeroes = HTAC[0xF0];
19840      var pos;
19841      var I16 = 16;
19842      var I63 = 63;
19843      var I64 = 64;
19844      var DU_DCT = fDCTQuant(CDU, fdtbl); //ZigZag reorder
19845
19846      for (var j = 0; j < I64; ++j) {
19847        DU[ZigZag[j]] = DU_DCT[j];
19848      }
19849
19850      var Diff = DU[0] - DC;
19851      DC = DU[0]; //Encode DC
19852
19853      if (Diff == 0) {
19854        writeBits(HTDC[0]); // Diff might be 0
19855      } else {
19856        pos = 32767 + Diff;
19857        writeBits(HTDC[category[pos]]);
19858        writeBits(bitcode[pos]);
19859      } //Encode ACs
19860
19861
19862      var end0pos = 63; // was const... which is crazy
19863
19864      for (;
19864 end0pos > 0 && DU[end0pos] == 0; end0pos--) {}
19865
19866      if (end0pos == 0) {
19867        writeBits(EOB);
19868        return DC;
19869      }
19870
19871      var i = 1;
19872      var lng;
19873
19874      while (i <= end0pos) {
19875        var startpos = i;
19876
19877        for (; DU[i] == 0 && i <= end0pos; ++i) {}
19878
19879        var nrzeroes = i - startpos;
19880
19881        if (nrzeroes >= I16) {
19882          lng = nrzeroes >> 4;
19883
19884          for (var nrmarker = 1; nrmarker <= lng; ++nrmarker) {
19885            writeBits(M16zeroes);
19886          }
19887
19888          nrzeroes = nrzeroes & 0xF;
19889        }
19890
19891        pos = 32767 + DU[i];
19892        writeBits(HTAC[(nrzeroes << 4) + category[pos]]);
19893        writeBits(bitcode[pos]);
19894        i++;
19895      }
19896
19897      if (end0pos != I63) {
19898        writeBits(EOB);
19899      }
19900
19901      return DC;
19902    }
19903
19904    function initCharLookupTable() {
19905      var sfcc = String.fromCharCode;
19906
19907      for (var i = 0; i < 256; i++) {
19908        ///// ACHTUNG // 255
19909        clt[i] = sfcc(i);
19910      }
19911    }
19912
19913    this.encode = function (image, quality) // image data object
19914    {
19915      var time_start = new Date().getTime();
19916      if (quality) setQuality(quality); // Initialize bit writer
19917
19918      byteout = new Array();
19919      bytenew = 0;
19920      bytepos = 7; // Add JPEG headers
19921
19922      writeWord(0xFFD8); // SOI
19923
19924      writeAPP0();
19925      writeDQT();
19926      writeSOF0(image.width, image.height);
19927      writeDHT();
19928      writeSOS(); // Encode 8x8 macroblocks
19929
19930      var DCY = 0;
19931      var DCU = 0;
19932      var DCV = 0;
19933      bytenew = 0;
19934      bytepos = 7;
19935      this.encode.displayName = "_encode_";
19936      var imageData = image.data;
19937      var width = image.width;
19938      var height = image.height;
19939      var quadWidth = width * 4;
19940      var x,
19941          y = 0;
19942      var r, g, b;
19943      var start, p, col, row, pos;
19944
19945      while (y < height) {
19946        x = 0;
19947
19948        while (x < quadWidth) {
19949          start = quadWidth * y + x;
19950          p = start;
19951          col = -1;
19952          row = 0;
19953
19954          for (pos = 0; pos < 64; pos++) {
19955            row = pos >> 3; // /8
19956
19957            col = (pos & 7) * 4; // %8
19958
19959            p = start + row * quadWidth + col;
19960
19961            if (y + row >= height) {
19962              // padding bottom
19963              p -= quadWidth * (y + 1 + row - height);
19964            }
19965
19966            if (x + col >= quadWidth) {
19967              // padding right	
19968              p -= x + col - quadWidth + 4;
19969            }
19970
19971            r = imageData[p++];
19972            g = imageData[p++];
19973            b = imageData[p++];
19974            /* // calculate YUV values dynamically
19975            YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80
19976            UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));
19977            VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));
19978            */
19979            // use lookup table (slightly faster)
19980
19981            YDU[pos] = (RGB_YUV_TABLE[r] + RGB_YUV_TABLE[g + 256 >> 0] + RGB_YUV_TABLE[b + 512 >> 0] >> 16) - 128;
19982            UDU[pos] = (RGB_YUV_TABLE[r + 768 >> 0] + RGB_YUV_TABLE[g + 1024 >> 0] + RGB_YUV_TABLE[b + 1280 >> 0] >> 16) - 128;
19983            VDU[pos] = (RGB_YUV_TABLE[r + 1280 >> 0] + RGB_YUV_TABLE[g + 1536 >> 0] + RGB_YUV_TABLE[b + 1792 >> 0] >> 16) - 128;
19984          }
19985
19986          DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
19987          DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
19988          DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
19989          x += 32;
19990        }
19991
19992        y += 8;
19993      } ////////////////////////////////////////////////////////////////
19994      // Do the bit alignment of the EOI marker
19995
19996
19997      if (bytepos >= 0) {
19998        var fillbits = [];
19999        fillbits[1] = bytepos + 1;
20000        fillbits[0] = (1 << bytepos + 1) - 1;
20001        writeBits(fillbits);
20002      }
20003
20004      writeWord(0xFFD9); //EOI
20005
20006      return new Uint8Array(byteout);
20007    };
20008
20009    function setQuality(quality) {
20010      if (quality <= 0) {
20011        quality = 1;
20012      }
20013
20014      if (quality > 100) {
20015        quality = 100;
20016      }
20017
20018      if (currentQuality == quality) return; // don't recalc if unchanged
20019
20020      var sf = 0;
20021
20022      if (quality < 50) {
20023        sf = Math.floor(5000 / quality);
20024      } else {
20025        sf = Math.floor(200 - quality * 2);
20026      }
20027
20028      initQuantTables(sf);
20029      currentQuality = quality; //console.log('Quality set to: '+quality +'%');
20030    }
20031
20032    function init() {
20033      var time_start = new Date().getTime();
20034      if (!quality) quality = 50; // Create tables
20035
20036      initCharLookupTable();
20037      initHuffmanTbl();
20038      initCategoryNumber();
20039      initRGBYUVTable();
20040      setQuality(quality);
20041      var duration = new Date().getTime() - time_start; //console.log('Initialization '+ duration + 'ms');
20042    }
20043
20044    init();
20045  }
20046  /*rollup-keeper-start*/
20047
20048  window.tmp = JPEGEncoder;
20049  /*rollup-keeper-end*/
20050
20051  /**
20052   * @author shaozilee
20053   *
20054   * Bmp format decoder,support 1bit 4bit 8bit 24bit bmp
20055   *
20056   */
20057  function BmpDecoder(buffer, is_with_alpha) {
20058    this.pos = 0;
20059    this.buffer = buffer;
20060    this.datav = new DataView(buffer.buffer);
20061    this.is_with_alpha = !!is_with_alpha;
20062    this.bottom_up = true;
20063    this.flag = String.fromCharCode(this.buffer[0]) + String.fromCharCode(this.buffer[1]);
20064    this.pos += 2;
20065    if (["BM", "BA", "CI", "CP", "IC", "PT"].indexOf(this.flag) === -1) throw new Error("Invalid BMP File");
20066    this.parseHeader();
20067    this.parseBGR();
20068  }
20069
20070  BmpDecoder.prototype.parseHeader = function () {
20071    this.fileSize = this.datav.getUint32(this.pos, true);
20072    this.pos += 4;
20073    this.reserved = this.datav.getUint32(this.pos, true);
20074    this.pos += 4;
20075    this.offset = this.datav.getUint32(this.pos, true);
20076    this.pos += 4;
20077    this.headerSize = this.datav.getUint32(this.pos, true);
20078    this.pos += 4;
20079    this.width = this.datav.getUint32(this.pos, true);
20080    this.pos += 4;
20081    this.height = this.datav.getInt32(this.pos, true);
20082    this.pos += 4;
20083    this.planes = this.datav.getUint16(this.pos, true);
20084    this.pos += 2;
20085    this.bitPP = this.datav.getUint16(this.pos, true);
20086    this.pos += 2;
20087    this.compress = this.datav.getUint32(this.pos, true);
20088    this.pos += 4;
20089    this.rawSize = this.datav.getUint32(this.pos, true);
20090    this.pos += 4;
20091    this.hr = this.datav.getUint32(this.pos, true);
20092    this.pos += 4;
20093    this.vr = this.datav.getUint32(this.pos, true);
20094    this.pos += 4;
20095    this.colors = this.datav.getUint32(this.pos, true);
20096    this.pos += 4;
20097    this.importantColors = this.datav.getUint32(this.pos, true);
20098    this.pos += 4;
20099
20100    if (this.bitPP === 16 && this.is_with_alpha) {
20101      this.bitPP = 15;
20102    }
20103
20104    if (this.bitPP < 15) {
20105      var len = this.colors === 0 ? 1 << this.bitPP : this.colors;
20106      this.palette = new Array(len);
20107
20108      for (var i = 0; i < len; i++) {
20109        var blue = this.datav.getUint8(this.pos++, true);
20110        var green = this.datav.getUint8(this.pos++, true);
20111        var red = this.datav.getUint8(this.pos++, true);
20112        var quad = this.datav.getUint8(this.pos++, true);
20113        this.palette[i] = {
20114          red: red,
20115          green: green,
20116          blue: blue,
20117          quad: quad
20118        };
20119      }
20120    }
20121
20122    if (this.height < 0) {
20123      this.height *= -1;
20124      this.bottom_up = false;
20125    }
20126  };
20127
20128  BmpDecoder.prototype.parseBGR = function () {
20129    this.pos = this.offset;
20130
20131    try {
20132      var bitn = "bit" + this.bitPP;
20133      var len = this.width * this.height * 4;
20134      this.data = new Uint8Array(len);
20135      this[bitn]();
20136    } catch (e) {
20137      console.log("bit decode error:" + e);
20138    }
20139  };
20140
20141  BmpDecoder.prototype.bit1 = function () {
20142    var xlen = Math.ceil(this.width / 8);
20143    var mode = xlen % 4;
20144    var y = this.height >= 0 ? this.height - 1 : -this.height;
20145
20146    for (var y = this.height - 1; y >= 0; y--) {
20147      var line = this.bottom_up ? y : this.height - 1 - y;
20148
20149      for (var x = 0; x < xlen; x++) {
20150        var b = this.datav.getUint8(this.pos++, true);
20151        var location = line * this.width * 4 + x * 8 * 4;
20152
20153        for (var i = 0; i < 8; i++) {
20154          if (x * 8 + i < this.width) {
20155            var rgb = this.palette[b >> 7 - i & 0x1];
20156            this.data[location + i * 4] = rgb.blue;
20157            this.data[location + i * 4 + 1] = rgb.green;
20158            this.data[location + i * 4 + 2] = rgb.red;
20159            this.data[location + i * 4 + 3] = 0xFF;
20160          } else {
20161            break;
20162          }
20163        }
20164      }
20165
20166      if (mode != 0) {
20167        this.pos += 4 - mode;
20168      }
20169    }
20170  };
20171
20172  BmpDecoder.prototype.bit4 = function () {
20173    var xlen = Math.ceil(this.width / 2);
20174    var mode = xlen % 4;
20175
20176    for (var y = this.height - 1; y >= 0; y--) {
20177      var line = this.bottom_up ? y : this.height - 1 - y;
20178
20179      for (var x = 0; x < xlen; x++) {
20180        var b = this.datav.getUint8(this.pos++, true);
20181        var location = line * this.width * 4 + x * 2 * 4;
20182        var before = b >> 4;
20183        var after = b & 0x0F;
20184        var rgb = this.palette[before];
20185        this.data[location] = rgb.blue;
20186        this.data[location + 1] = rgb.green;
20187        this.data[location + 2] = rgb.red;
20188        this.data[location + 3] = 0xFF;
20189        if (x * 2 + 1 >= this.width) break;
20190        rgb = this.palette[after];
20191        this.data[location + 4] = rgb.blue;
20192        this.data[location + 4 + 1] = rgb.green;
20193        this.data[location + 4 + 2] = rgb.red;
20194        this.data[location + 4 + 3] = 0xFF;
20195      }
20196
20197      if (mode != 0) {
20198        this.pos += 4 - mode;
20199      }
20200    }
20201  };
20202
20203  BmpDecoder.prototype.bit8 = function () {
20204    var mode = this.width % 4;
vendor: 5,043 bytes, lines 20205-20365
20205
20206    for (var y = this.height - 1; y >= 0; y--) {
20207      var line = this.bottom_up ? y : this.height - 1 - y;
20208
20209      for (var x = 0; x < this.width; x++) {
20210        var b = this.datav.getUint8(this.pos++, true);
20211        var location = line * this.width * 4 + x * 4;
20212
20213        if (b < this.palette.length) {
20214          var rgb = this.palette[b];
20215          this.data[location] = rgb.red;
20216          this.data[location + 1] = rgb.green;
20217          this.data[location + 2] = rgb.blue;
20218          this.data[location + 3] = 0xFF;
20219        } else {
20220          this.data[location] = 0xFF;
20221          this.data[location + 1] = 0xFF;
20222          this.data[location + 2] = 0xFF;
20223          this.data[location + 3] = 0xFF;
20224        }
20225      }
20226
20227      if (mode != 0) {
20228        this.pos += 4 - mode;
20229      }
20230    }
20231  };
20232
20233  BmpDecoder.prototype.bit15 = function () {
20234    var dif_w = this.width % 3;
20235
20236    var _11111 = parseInt("11111", 2),
20237        _1_5 = _11111;
20238
20239    for (var y = this.height - 1; y >= 0; y--) {
20240      var line = this.bottom_up ? y : this.height - 1 - y;
20241
20242      for (var x = 0; x < this.width; x++) {
20243        var B = this.datav.getUint16(this.pos, true);
20244        this.pos += 2;
20245        var blue = (B & _1_5) / _1_5 * 255 | 0;
20246        var green = (B >> 5 & _1_5) / _1_5 * 255 | 0;
20247        var red = (B >> 10 & _1_5) / _1_5 * 255 | 0;
20248        var alpha = B >> 15 ? 0xFF : 0x00;
20249        var location = line * this.width * 4 + x * 4;
20250        this.data[location] = red;
20251        this.data[location + 1] = green;
20252        this.data[location + 2] = blue;
20253        this.data[location + 3] = alpha;
20254      } //skip extra bytes
20255
20256
20257      this.pos += dif_w;
20258    }
20259  };
20260
20261  BmpDecoder.prototype.bit16 = function () {
20262    var dif_w = this.width % 3;
20263
20264    var _11111 = parseInt("11111", 2),
20265        _1_5 = _11111;
20266
20267    var _111111 = parseInt("111111", 2),
20268        _1_6 = _111111;
20269
20270    for (var y = this.height - 1; y >= 0; y--) {
20271      var line = this.bottom_up ? y : this.height - 1 - y;
20272
20273      for (var x = 0; x < this.width; x++) {
20274        var B = this.datav.getUint16(this.pos, true);
20275        this.pos += 2;
20276        var alpha = 0xFF;
20277        var blue = (B & _1_5) / _1_5 * 255 | 0;
20278        var green = (B >> 5 & _1_6) / _1_6 * 255 | 0;
20279        var red = (B >> 11) / _1_5 * 255 | 0;
20280        var location = line * this.width * 4 + x * 4;
20281        this.data[location] = red;
20282        this.data[location + 1] = green;
20283        this.data[location + 2] = blue;
20284        this.data[location + 3] = alpha;
20285      } //skip extra bytes
20286
20287
20288      this.pos += dif_w;
20289    }
20290  };
20291
20292  BmpDecoder.prototype.bit24 = function () {
20293    //when height > 0
20294    for (var y = this.height - 1; y >= 0; y--) {
20295      var line = this.bottom_up ? y : this.height - 1 - y;
20296
20297      for (var x = 0; x < this.width; x++) {
20298        var blue = this.datav.getUint8(this.pos++, true);
20299        var green = this.datav.getUint8(this.pos++, true);
20300        var red = this.datav.getUint8(this.pos++, true);
20301        var location = line * this.width * 4 + x * 4;
20302        this.data[location] = red;
20303        this.data[location + 1] = green;
20304        this.data[location + 2] = blue;
20305        this.data[location + 3] = 0xFF;
20306      } //skip extra bytes
20307
20308
20309      this.pos += this.width % 4;
20310    }
20311  };
20312  /**
20313   * add 32bit decode func
20314   * @author soubok
20315   */
20316
20317
20318  BmpDecoder.prototype.bit32 = function () {
20319    //when height > 0
20320    for (var y = this.height - 1; y >= 0; y--) {
20321      var line = this.bottom_up ? y : this.height - 1 - y;
20322
20323      for (var x = 0; x < this.width; x++) {
20324        var blue = this.datav.getUint8(this.pos++, true);
20325        var green = this.datav.getUint8(this.pos++, true);
20326        var red = this.datav.getUint8(this.pos++, true);
20327        var alpha = this.datav.getUint8(this.pos++, true);
20328        var location = line * this.width * 4 + x * 4;
20329        this.data[location] = red;
20330        this.data[location + 1] = green;
20331        this.data[location + 2] = blue;
20332        this.data[location + 3] = alpha;
20333      } //skip extra bytes
20334      //this.pos += (this.width % 4);
20335
20336    }
20337  };
20338
20339  BmpDecoder.prototype.getData = function () {
20340    return this.data;
20341  };
20342  /*rollup-keeper-start*/
20343
20344
20345  window.tmp = BmpDecoder;
20346  /*rollup-keeper-end*/
20347
20348  /*
20349   Copyright (c) 2013 Gildas Lormeau. All rights reserved.
20350
20351   Redistribution and use in source and binary forms, with or without
20352   modification, are permitted provided that the following conditions are met:
20353
20354   1. Redistributions of source code must retain the above copyright notice,
20355   this list of conditions and the following disclaimer.
20356
20357   2. Redistributions in binary form must reproduce the above copyright 
20358   notice, this list of conditions and the following disclaimer in 
20359   the documentation and/or other materials provided with the distribution.
20360
20361   3. The names of the authors may not be used to endorse or promote products
20362   derived from this software without specific prior written permission.
20363
20364   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
20365   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20366   FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
20367   INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
20368   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20369   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20370   OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
20371   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20372   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
20373   EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20374   */
20375
20376  /*
20377   * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.
20378   * JZlib is based on zlib-1.1.3, so all credit should go authors
20379   * Jean-loup Gailly([email protected]) and Mark Adler([email protected])
20380   * and contributors of zlib.
20381   */
20382  (function (global) {
20383
20384    var MAX_BITS = 15;
20385    var D_CODES = 30;
20386    var BL_CODES = 19;
20387    var LENGTH_CODES = 29;
20388    var LITERALS = 256;
20389    var L_CODES = LITERALS + 1 + LENGTH_CODES;
20390    var HEAP_SIZE = 2 * L_CODES + 1;
20391    var END_BLOCK = 256; // Bit length codes must not exceed MAX_BL_BITS bits
20392
20393    var MAX_BL_BITS = 7; // repeat previous bit length 3-6 times (2 bits of repeat count)
20394
20395    var REP_3_6 = 16; // repeat a zero length 3-10 times (3 bits of repeat count)
20396
20397    var REPZ_3_10 = 17; // repeat a zero length 11-138 times (7 bits of repeat count)
20398
20399    var REPZ_11_138 = 18; // The lengths of the bit length codes are sent in order of decreasing
20400    // probability, to avoid transmitting the lengths for unused bit
20401    // length codes.
20402
20403    var Buf_size = 8 * 2; // JZlib version : "1.0.2"
20404
20405    var Z_DEFAULT_COMPRESSION = -1; // compression strategy
20406
20407    var Z_FILTERED = 1;
20408    var Z_HUFFMAN_ONLY = 2;
20409    var Z_DEFAULT_STRATEGY = 0;
20410    var Z_NO_FLUSH = 0;
20411    var Z_PARTIAL_FLUSH = 1;
20412    var Z_FULL_FLUSH = 3;
20413    var Z_FINISH = 4;
20414    var Z_OK = 0;
20415    var Z_STREAM_END = 1;
20416    var Z_NEED_DICT = 2;
20417    var Z_STREAM_ERROR = -2;
20418    var Z_DATA_ERROR = -3;
20419    var Z_BUF_ERROR = -5; // Tree
20420    // see definition of array dist_code below
20421
20422    var _dist_code = [0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29];
20423
20424    function Tree() {
20425      var that = this; // dyn_tree; // the dynamic tree
20426      // max_code; // largest code with non zero frequency
20427      // stat_desc; // the corresponding static tree
20428      // Compute the optimal bit lengths for a tree and update the total bit
20429      // length
20430      // for the current block.
20431      // IN assertion: the fields freq and dad are set, heap[heap_max] and
20432      // above are the tree nodes sorted by increasing frequency.
20433      // OUT assertions: the field len is set to the optimal bit length, the
20434      // array bl_count contains the frequencies for each bit length.
20435      // The length opt_len is updated; static_len is also updated if stree is
20436      // not null.
20437
20438      function gen_bitlen(s) {
20439        var tree = that.dyn_tree;
20440        var stree = that.stat_desc.static_tree;
20441        var extra = that.stat_desc.extra_bits;
20442        var base = that.stat_desc.extra_base;
20443        var max_length = that.stat_desc.max_length;
20444        var h; // heap index
20445
20446        var n, m; // iterate over the tree elements
20447
20448        var bits; // bit length
20449
20450        var xbits; // extra bits
20451
20452        var f; // frequency
20453
20454        var overflow = 0; // number of elements with bit length too large
20455
20456        for (bits = 0; bits <= MAX_BITS; bits++) {
20457          s.bl_count[bits] = 0;
20458        } // In a first pass, compute the optimal bit lengths (which may
20459        // overflow in the case of the bit length tree).
20460
20461
20462        tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
20463
20464        for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
20465          n = s.heap[h];
20466          bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
20467
20468          if (bits > max_length) {
20469            bits = max_length;
20470            overflow++;
20471          }
20472
20473          tree[n * 2 + 1] = bits; // We overwrite tree[n*2+1] which is no longer needed
20474
20475          if (n > that.max_code) continue; // not a leaf node
20476
20477          s.bl_count[bits]++;
20478          xbits = 0;
20479          if (n >= base) xbits = extra[n - base];
20480          f = tree[n * 2];
20481          s.opt_len += f * (bits + xbits);
20482          if (stree) s.static_len += f * (stree[n * 2 + 1] + xbits);
20483        }
20484
20485        if (overflow === 0) return; // This happens for example on obj2 and pic of the Calgary corpus
20486        // Find the first bit length which could increase:
20487
20488        do {
20489          bits = max_length - 1;
20490
20491          while (s.bl_count[bits] === 0) {
20492            bits--;
20493          }
20494
20495          s.bl_count[bits]--; // move one leaf down the tree
20496
20497          s.bl_count[bits + 1] += 2; // move one overflow item as its brother
20498
20499          s.bl_count[max_length]--; // The brother of the overflow item also moves one step up,
20500          // but this does not affect bl_count[max_length]
20501
20502          overflow -= 2;
20503        } while (overflow > 0);
20504
20505        for (bits = max_length; bits !== 0; bits--) {
20506          n = s.bl_count[bits];
20507
20508          while (n !== 0) {
20509            m = s.heap[--h];
20510            if (m > that.max_code) continue;
20511
20512            if (tree[m * 2 + 1] != bits) {
20513              s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2];
20514              tree[m * 2 + 1] = bits;
20515            }
20516
20517            n--;
20518          }
20519        }
20520      } // Reverse the first len bits of a code, using straightforward code (a
20521      // faster
20522      // method would use a table)
20523      // IN assertion: 1 <= len <= 15
20524
20525
20526      function bi_reverse(code, // the value to invert
20527      len // its bit length
20528      ) {
20529        var res = 0;
20530
20531        do {
20532          res |= code & 1;
20533          code >>>= 1;
20534          res <<= 1;
20535        } while (--len > 0);
20536
20537        return res >>> 1;
20538      } // Generate the codes for a given tree and bit counts (which need not be
20539      // optimal).
20540      // IN assertion: the array bl_count contains the bit length statistics for
20541      // the given tree and the field len is set for all tree elements.
20542      // OUT assertion: the field code is set for all tree elements of non
20543      // zero code length.
20544
20545
20546      function gen_codes(tree, // the tree to decorate
20547      max_code, // largest code with non zero frequency
20548      bl_count // number of codes at each bit length
20549      ) {
20550        var next_code = []; // next code value for each
20551        // bit length
20552
20553        var code = 0; // running code value
20554
20555        var bits; // bit index
20556
20557        var n; // code index
20558
20559        var len; // The distribution counts are first used to generate the code values
20560        // without bit reversal.
20561
20562        for (bits = 1; bits <= MAX_BITS; bits++) {
20563          next_code[bits] = code = code + bl_count[bits - 1] << 1;
20564        } // Check that the bit counts in bl_count are consistent. The last code
20565        // must be all ones.
20566        // Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
20567        // "inconsistent bit counts");
20568        // Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
20569
20570
20571        for (n = 0; n <= max_code; n++) {
20572          len = tree[n * 2 + 1];
20573          if (len === 0) continue; // Now reverse the bits
20574
20575          tree[n * 2] = bi_reverse(next_code[len]++, len);
20576        }
20577      } // Construct one Huffman tree and assigns the code bit strings and lengths.
20578      // Update the total bit length for the current block.
20579      // IN assertion: the field freq is set for all tree elements.
20580      // OUT assertions: the fields len and code are set to the optimal bit length
20581      // and corresponding code. The length opt_len is updated; static_len is
20582      // also updated if stree is not null. The field max_code is set.
20583
20584
20585      that.build_tree = function (s) {
20586        var tree = that.dyn_tree;
20587        var stree = that.stat_desc.static_tree;
20588        var elems = that.stat_desc.elems;
20589        var n, m; // iterate over heap elements
20590
20591        var max_code = -1; // largest code with non zero frequency
20592
20593        var node; // new node being created
20594        // Construct the initial heap, with least frequent element in
20595        // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
20596        // heap[0] is not used.
20597
20598        s.heap_len = 0;
20599        s.heap_max = HEAP_SIZE;
20600
20601        for (n = 0; n < elems; n++) {
20602          if (tree[n * 2] !== 0) {
20603            s.heap[++s.heap_len] = max_code = n;
20604            s.depth[n] = 0;
20605          } else {
20606            tree[n * 2 + 1] = 0;
20607          }
20608        } // The pkzip format requires that at least one distance code exists,
20609        // and that at least one bit should be sent even if there is only one
20610        // possible code. So to avoid special checks later on we force at least
20611        // two codes of non zero frequency.
20612
20613
20614        while (s.heap_len < 2) {
20615          node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0;
20616          tree[node * 2] = 1;
20617          s.depth[node] = 0;
20618          s.opt_len--;
20619          if (stree) s.static_len -= stree[node * 2 + 1]; // node is 0 or 1 so it does not have extra bits
20620        }
20621
20622        that.max_code = max_code; // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
20623        // establish sub-heaps of increasing lengths:
20624
20625        for (n = Math.floor(s.heap_len / 2); n >= 1; n--) {
20626          s.pqdownheap(tree, n);
20627        } // Construct the Huffman tree by repeatedly combining the least two
20628        // frequent nodes.
20629
20630
20631        node = elems; // next internal node of the tree
20632
20633        do {
20634          // n = node of least frequency
20635          n = s.heap[1];
20636          s.heap[1] = s.heap[s.heap_len--];
20637          s.pqdownheap(tree, 1);
20638          m = s.heap[1]; // m = node of next least frequency
20639
20640          s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
20641
20642          s.heap[--s.heap_max] = m; // Create a new node father of n and m
20643
20644          tree[node * 2] = tree[n * 2] + tree[m * 2];
20645          s.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1;
20646          tree[n * 2 + 1] = tree[m * 2 + 1] = node; // and insert the new node in the heap
20647
20648          s.heap[1] = node++;
20649          s.pqdownheap(tree, 1);
20650        } while (s.heap_len >= 2);
20651
20652        s.heap[--s.heap_max] = s.heap[1]; // At this point, the fields freq and dad are set. We can now
20653        // generate the bit lengths.
20654
20655        gen_bitlen(s); // The field len is now set, we can generate the bit codes
20656
20657        gen_codes(tree, that.max_code, s.bl_count);
20658      };
20659    }
20660
20661    Tree._length_code = [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28];
20662    Tree.base_length = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0];
20663    Tree.base_dist = [0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576]; // Mapping from a distance to a distance code. dist is the distance - 1 and
20664    // must not have side effects. _dist_code[256] and _dist_code[257] are never
20665    // used.
20666
20667    Tree.d_code = function (dist) {
20668      return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
20669    }; // extra bits for each length code
20670
20671
20672    Tree.extra_lbits = [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]; // extra bits for each distance code
20673
20674    Tree.extra_dbits = [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]; // extra bits for each bit length code
20675
20676    Tree.extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7];
20677    Tree.bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; // StaticTree
20678
20679    function StaticTree(static_tree, extra_bits, extra_base, elems, max_length) {
20680      var that = this;
20681      that.static_tree = static_tree;
20682      that.extra_bits = extra_bits;
20683      that.extra_base = extra_base;
20684      that.elems = elems;
20685      that.max_length = max_length;
20686    }
20687
20688    StaticTree.static_ltree = [12, 8, 140, 8, 76, 8, 204, 8, 44, 8, 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, 252, 8, 2, 8, 130, 8, 66, 8, 194, 8, 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, 202, 8, 42, 8, 170, 8, 106, 8, 234, 8, 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, 230, 8, 22, 8, 150, 8, 86, 8, 214, 8, 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, 110, 8, 238, 8, 30, 8, 158, 8, 94, 8, 222, 8, 62, 8, 190, 8, 126, 8, 254, 8, 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, 81, 8, 209, 8, 49, 8, 177, 8, 113, 8, 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, 121, 8, 249, 8, 5, 8, 133, 8, 69, 8, 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, 77, 8, 205, 8, 45, 8, 173, 8, 109, 8, 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, 27
206885, 9, 147, 9, 403, 9, 83, 9, 339, 9, 211, 9, 467, 9, 51, 9, 307, 9, 179, 9, 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, 171, 9, 427, 9, 107, 9, 363, 9, 235, 9, 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, 315, 9, 187, 9, 443, 9, 123, 9, 379, 9, 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, 359, 9, 231, 9, 487, 9, 23, 9, 279, 9, 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, 271, 9, 143, 9, 399, 9, 79, 9, 335, 9, 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, 351, 9, 223, 9, 479, 9, 63, 9, 319, 9, 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, 511, 9, 0, 7, 64, 7, 32, 7, 96, 7, 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, 72, 7, 40, 7, 104, 7, 24, 7, 88, 7, 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, 163, 8, 99, 8, 227, 8];
20689    StaticTree.static_dtree = [0, 5, 16, 5, 8, 5, 24, 5, 4, 5, 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, 30, 5, 1, 5, 17, 5, 9, 5, 25, 5, 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5];
20690    StaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
20691    StaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS);
20692    StaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS); // Deflate
20693
20694    var MAX_MEM_LEVEL = 9;
20695    var DEF_MEM_LEVEL = 8;
20696
20697    function Config(good_length, max_lazy, nice_length, max_chain, func) {
20698      var that = this;
20699      that.good_length = good_length;
20700      that.max_lazy = max_lazy;
20701      that.nice_length = nice_length;
20702      that.max_chain = max_chain;
20703      that.func = func;
20704    }
20705
20706    var STORED = 0;
20707    var FAST = 1;
20708    var SLOW = 2;
20709    var config_table = [new Config(0, 0, 0, 0, STORED), new Config(4, 4, 8, 4, FAST), new Config(4, 5, 16, 8, FAST), new Config(4, 6, 32, 32, FAST), new Config(4, 4, 16, 16, SLOW), new Config(8, 16, 32, 32, SLOW), new Config(8, 16, 128, 128, SLOW), new Config(8, 32, 128, 256, SLOW), new Config(32, 128, 258, 1024, SLOW), new Config(32, 258, 258, 4096, SLOW)];
20710    var z_errmsg = ["need dictionary", // Z_NEED_DICT
20711    // 2
20712    "stream end", // Z_STREAM_END 1
20713    "", // Z_OK 0
20714    "", // Z_ERRNO (-1)
20715    "stream error", // Z_STREAM_ERROR (-2)
20716    "data error", // Z_DATA_ERROR (-3)
20717    "", // Z_MEM_ERROR (-4)
20718    "buffer error", // Z_BUF_ERROR (-5)
20719    "", // Z_VERSION_ERROR (-6)
20720    ""]; // block not completed, need more input or more output
20721
20722    var NeedMore = 0; // block flush performed
20723
20724    var BlockDone = 1; // finish started, need only more output at next deflate
20725
20726    var FinishStarted = 2; // finish done, accept no more input or output
20727
20728    var FinishDone = 3; // preset dictionary flag in zlib header
20729
20730    var PRESET_DICT = 0x20;
20731    var INIT_STATE = 42;
20732    var BUSY_STATE = 113;
20733    var FINISH_STATE = 666; // The deflate compression method
20734
20735    var Z_DEFLATED = 8;
20736    var STORED_BLOCK = 0;
20737    var STATIC_TREES = 1;
20738    var DYN_TREES = 2;
20739    var MIN_MATCH = 3;
20740    var MAX_MATCH = 258;
20741    var MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1;
20742
20743    function smaller(tree, n, m, depth) {
20744      var tn2 = tree[n * 2];
20745      var tm2 = tree[m * 2];
20746      return tn2 < tm2 || tn2 == tm2 && depth[n] <= depth[m];
20747    }
20748
20749    function Deflate() {
20750      var that = this;
20751      var strm; // pointer back to this zlib stream
20752
20753      var status; // as the name implies
20754      // pending_buf; // output still pending
20755
20756      var pending_buf_size; // size of pending_buf
20757
20758      var last_flush; // value of flush param for previous deflate call
20759
20760      var w_size; // LZ77 window size (32K by default)
20761
20762      var w_bits; // log2(w_size) (8..16)
20763
20764      var w_mask; // w_size - 1
20765
20766      var window; // Sliding window. Input bytes are read into the second half of the window,
20767      // and move to the first half later to keep a dictionary of at least wSize
20768      // bytes. With this organization, matches are limited to a distance of
20769      // wSize-MAX_MATCH bytes, but this ensures that IO is always
20770      // performed with a length multiple of the block size. Also, it limits
20771      // the window size to 64K, which is quite useful on MSDOS.
20772      // To do: use the user input buffer as sliding window.
20773
20774      var window_size; // Actual size of window: 2*wSize, except when the user input buffer
20775      // is directly used as sliding window.
20776
20777      var prev; // Link to older string with same hash index. To limit the size of this
20778      // array to 64K, this link is maintained only for the last 32K strings.
20779      // An index in this array is thus a window index modulo 32K.
20780
20781      var head; // Heads of the hash chains or NIL.
20782
20783      var ins_h;
20783 // hash index of string to be inserted
20784
20785      var hash_size; // number of elements in hash table
20786
20787      var hash_bits; // log2(hash_size)
20788
20789      var hash_mask; // hash_size-1
20790      // Number of bits by which ins_h must be shifted at each input
20791      // step. It must be such that after MIN_MATCH steps, the oldest
20792      // byte no longer takes part in the hash key, that is:
20793      // hash_shift * MIN_MATCH >= hash_bits
20794
20795      var hash_shift; // Window position at the beginning of the current output block. Gets
20796      // negative when the window is moved backwards.
20797
20798      var block_start;
20799      var match_length; // length of best match
20800
20801      var prev_match; // previous match
20802
20803      var match_available; // set if previous match exists
20804
20805      var strstart; // start of string to insert
20806
20807      var match_start; // start of matching string
20808
20809      var lookahead; // number of valid bytes ahead in window
20810      // Length of the best match at previous step. Matches not greater than this
20811      // are discarded. This is used in the lazy match evaluation.
20812
20813      var prev_length; // To speed up deflation, hash chains are never searched beyond this
20814      // length. A higher limit improves compression ratio but degrades the speed.
20815
20816      var max_chain_length; // Attempt to find a better match only when the current match is strictly
20817      // smaller than this value. This mechanism is used only for compression
20818      // levels >= 4.
20819
20820      var max_lazy_match; // Insert new strings in the hash table only if the match length is not
20821      // greater than this length. This saves time but degrades compression.
20822      // max_insert_length is used only for compression levels <= 3.
20823
20824      var level; // compression level (1..9)
20825
20826      var strategy; // favor or force Huffman coding
20827      // Use a faster search when the previous match is longer than this
20828
20829      var good_match; // Stop searching when current match exceeds this
20830
20831      var nice_match;
20832      var dyn_ltree; // literal and length tree
20833
20834      var dyn_dtree; // distance tree
20835
20836      var bl_tree; // Huffman tree for bit lengths
20837
20838      var l_desc = new Tree(); // desc for literal tree
20839
20840      var d_desc = new Tree(); // desc for distance tree
20841
20842      var bl_desc = new Tree(); // desc for bit length tree
20843      // that.heap_len; // number of elements in the heap
20844      // that.heap_max; // element of largest frequency
20845      // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
20846      // The same heap array is used to build all trees.
20847      // Depth of each subtree used as tie breaker for trees of equal frequency
20848
20849      that.depth = [];
20850      var l_buf; // index for literals or lengths */
20851      // Size of match buffer for literals/lengths. There are 4 reasons for
20852      // limiting lit_bufsize to 64K:
20853      // - frequencies can be kept in 16 bit counters
20854      // - if compression is not successful for the first block, all input
20855      // data is still in the window so we can still emit a stored block even
20856      // when input comes from standard input. (This can also be done for
20857      // all blocks if lit_bufsize is not greater than 32K.)
20858      // - if compression is not successful for a file smaller than 64K, we can
20859      // even emit a stored file instead of a stored block (saving 5 bytes).
20860      // This is applicable only for zip (not gzip or zlib).
20861      // - creating new Huffman trees less frequently may not provide fast
20862      // adaptation to changes in the input data statistics. (Take for
20863      // example a binary file with poorly compressible code followed by
20864      // a highly compressible string table.) Smaller buffer sizes give
20865      // fast adaptation but have of course the overhead of transmitting
20866      // trees more frequently.
20867      // - I can't count above 4
20868
20869      var lit_bufsize;
20870      var last_lit; // running index in l_buf
20871      // Buffer for distances. To simplify the code, d_buf and l_buf have
20872      // the same number of elements. To use different lengths, an extra flag
20873      // array would be necessary.
20874
20875      var d_buf; // index of pendig_buf
20876      // that.opt_len; // bit length of current block with optimal trees
20877      // that.static_len; // bit length of current block with static trees
20878
20879      var matches; // number of string matches in current block
20880
20881      var last_eob_len; // bit length of EOB code for last block
20882      // Output buffer. bits are inserted starting at the bottom (least
20883      // significant bits).
20884
20885      var bi_buf; // Number of valid bits in bi_buf. All bits above the last valid bit
20886      // are always zero.
20887
20888      var bi_valid; // number of codes at each bit length for an optimal tree
20889
20890      that.bl_count = []; // heap used to build the Huffman trees
20891
20892      that.heap = [];
20893      dyn_ltree = [];
20894      dyn_dtree = [];
20895      bl_tree = [];
20896
20897      function lm_init() {
20898        var i;
20899        window_size = 2 * w_size;
20900        head[hash_size - 1] = 0;
20901
20902        for (i = 0; i < hash_size - 1; i++) {
20903          head[i] = 0;
20904        } // Set the default configuration parameters:
20905
20906
20907        max_lazy_match = config_table[level].max_lazy;
20908        good_match = config_table[level].good_length;
20909        nice_match = config_table[level].nice_length;
20910        max_chain_length = config_table[level].max_chain;
20911        strstart = 0;
20912        block_start = 0;
20913        lookahead = 0;
20914        match_length = prev_length = MIN_MATCH - 1;
20915        match_available = 0;
20916        ins_h = 0;
20917      }
20918
20919      function init_block() {
20920        var i; // Initialize the trees.
20921
20922        for (i = 0; i < L_CODES; i++) {
20923          dyn_ltree[i * 2] = 0;
20924        }
20925
20926        for (i = 0; i < D_CODES; i++) {
20927          dyn_dtree[i * 2] = 0;
20928        }
20929
20930        for (i = 0; i < BL_CODES; i++) {
20931          bl_tree[i * 2] = 0;
20932        }
20933
20934        dyn_ltree[END_BLOCK * 2] = 1;
20935        that.opt_len = that.static_len = 0;
20936        last_lit = matches = 0;
20937      } // Initialize the tree data structures for a new zlib stream.
20938
20939
20940      function tr_init() {
20941        l_desc.dyn_tree = dyn_ltree;
20942        l_desc.stat_desc = StaticTree.static_l_desc;
20943        d_desc.dyn_tree = dyn_dtree;
20944        d_desc.stat_desc = StaticTree.static_d_desc;
20945        bl_desc.dyn_tree = bl_tree;
20946        bl_desc.stat_desc = StaticTree.static_bl_desc;
20947        bi_buf = 0;
20948        bi_valid = 0;
20949        last_eob_len = 8; // enough lookahead for inflate
20950        // Initialize the first block of the first file:
20951
20952        init_block();
20953      } // Restore the heap property by moving down the tree starting at node k,
20954      // exchanging a node with the smallest of its two sons if necessary,
20955      // stopping
20956      // when the heap property is re-established (each father smaller than its
20957      // two sons).
20958
20959
20960      that.pqdownheap = function (tree, // the tree to restore
20961      k // node to move down
20962      ) {
20963        var heap = that.heap;
20964        var v = heap[k];
20965        var j = k << 1; // left son of k
20966
20967        while (j <= that.heap_len) {
20968          // Set j to the smallest of the two sons:
20969          if (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) {
20970            j++;
20971          } // Exit if v is smaller than both sons
20972
20973
20974          if (smaller(tree, v, heap[j], that.depth)) break; // Exchange v with the smallest son
20975
20976          heap[k] = heap[j];
20977          k = j; // And continue down the tree, setting j to the left son of k
20978
20979          j <<= 1;
20980        }
20981
20982        heap[k] = v;
20983      }; // Scan a literal or distance tree to determine the frequencies of the codes
20984      // in the bit length tree.
20985
20986
20987      function scan_tree(tree, // the tree to be scanned
20988      max_code // and its largest code of non zero frequency
20989      ) {
20990        var n; // iterates over all tree elements
20991
20992        var prevlen = -1; // last emitted length
20993
20994        var curlen; // length of current code
20995
20996        var nextlen = tree[0 * 2 + 1]; // length of next code
20997
20998        var count = 0; // repeat count of the current code
20999
21000        var max_count = 7; // max repeat count
21001
21002        var min_count = 4; // min repeat count
21003
21004        if (nextlen === 0) {
21005          max_count = 138;
21006          min_count = 3;
21007        }
21008
21009        tree[(max_code + 1) * 2 + 1] = 0xffff; // guard
21010
21011        for (n = 0; n <= max_code; n++) {
21012          curlen = nextlen;
21013          nextlen = tree[(n + 1) * 2 + 1];
21014
21015          if (++count < max_count && curlen == nextlen) {
21016            continue;
21017          } else if (count < min_count) {
21018            bl_tree[curlen * 2] += count;
21019          } else if (curlen !== 0) {
21020            if (curlen != prevlen) bl_tree[curlen * 2]++;
21021            bl_tree[REP_3_6 * 2]++;
21022          } else if (count <= 10) {
21023            bl_tree[REPZ_3_10 * 2]++;
21024          } else {
21025            bl_tree[REPZ_11_138 * 2]++;
21026          }
21027
21028          count = 0;
21029          prevlen = curlen;
21030
21031          if (nextlen === 0) {
21032            max_count = 138;
21033            min_count = 3;
21034          } else if (curlen == nextlen) {
21035            max_count = 6;
21036            min_count = 3;
21037          } else {
21038            max_count = 7;
21039            min_count = 4;
21040          }
21041        }
21042      } // Construct the Huffman tree for the bit lengths and return the index in
21043      // bl_order of the last bit length code to send.
21044
21045
21046      function build_bl_tree() {
21047        var max_blindex; // index of last bit length code of non zero freq
21048        // Determine the bit length frequencies for literal and distance trees
21049
21050        scan_tree(dyn_ltree, l_desc.max_code);
21051        scan_tree(dyn_dtree, d_desc.max_code); // Build the bit length tree:
21052
21053        bl_desc.build_tree(that); // opt_len now includes the length of the tree representations, except
21054        // the lengths of the bit lengths codes and the 5+5+4 bits for the
21055        // counts.
21056        // Determine the number of bit length codes to send. The pkzip format
21057        // requires that at least 4 bit length codes be sent. (appnote.txt says
21058        // 3 but the actual value used is 4.)
21059
21060        for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
21061          if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0) break;
21062        } // Update opt_len to include the bit length tree and counts
21063
21064
21065        that.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
21066        return max_blindex;
21067      } // Output a byte on the stream.
21068      // IN assertion: there is enough room in pending_buf.
21069
21070
21071      function put_byte(p) {
21072        that.pending_buf[that.pending++] = p;
21073      }
21074
21075      function put_short(w) {
21076        put_byte(w & 0xff);
21077        put_byte(w >>> 8 & 0xff);
21078      }
21079
21080      function putShortMSB(b) {
21081        put_byte(b >> 8 & 0xff);
21082        put_byte(b & 0xff & 0xff);
21083      }
21084
21085      function send_bits(value, length) {
21086        var val,
21087            len = length;
21088
21089        if (bi_valid > Buf_size - len) {
21090          val = value; // bi_buf |= (val << bi_valid);
21091
21092          bi_buf |= val << bi_valid & 0xffff;
21093          put_short(bi_buf);
21094          bi_buf = val >>> Buf_size - bi_valid;
21095          bi_valid += len - Buf_size;
21096        } else {
21097          // bi_buf |= (value) << bi_valid;
21098          bi_buf |= value << bi_valid & 0xffff;
21099          bi_valid += len;
21100        }
21101      }
21102
21103      function send_code(c, tree) {
21104        var c2 = c * 2;
21105        send_bits(tree[c2] & 0xffff, tree[c2 + 1] & 0xffff);
21106      } // Send a literal or distance tree in compressed form, using the codes in
21107      // bl_tree.
21108
21109
21110      function send_tree(tree, // the tree to be sent
21111      max_code // and its largest code of non zero frequency
21112      ) {
21113        var n; // iterates over all tree elements
21114
21115        var prevlen = -1; // last emitted length
21116
21117        var curlen; // length of current code
21118
21119        var nextlen = tree[0 * 2 + 1]; // length of next code
21120
21121        var count = 0; // repeat count of the current code
21122
21123        var max_count = 7; // max repeat count
21124
21125        var min_count = 4; // min repeat count
21126
21127        if (nextlen === 0) {
21128          max_count = 138;
21129          min_count = 3;
21130        }
21131
21132        for (n = 0; n <= max_code; n++) {
21133          curlen = nextlen;
21134          nextlen = tree[(n + 1) * 2 + 1];
21135
21136          if (++count < max_count && curlen == nextlen) {
21137            continue;
21138          } else if (count < min_count) {
21139            do {
21140              send_code(curlen, bl_tree);
21141            } while (--count !== 0);
21142          } else if (curlen !== 0) {
21143            if (curlen != prevlen) {
21144              send_code(curlen, bl_tree);
21145              count--;
21146            }
21147
21148            send_code(REP_3_6, bl_tree);
21149            send_bits(count - 3, 2);
21150          } else if (count <= 10) {
21151            send_code(REPZ_3_10, bl_tree);
21152            send_bits(count - 3, 3);
21153          } else {
21154            send_code(REPZ_11_138, bl_tree);
21155            send_bits(count - 11, 7);
21156          }
21157
21158          count = 0;
21159          prevlen = curlen;
21160
21161          if (nextlen === 0) {
21162            max_count = 138;
21163            min_count = 3;
21164          } else if (curlen == nextlen) {
21165            max_count = 6;
21166            min_count = 3;
21167          } else {
21168            max_count = 7;
21169            min_count = 4;
21170          }
21171        }
21172      } // Send the header for a block using dynamic Huffman trees: the counts, the
21173      // lengths of the bit length codes, the literal tree and the distance tree.
21174      // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
21175
21176
21177      function send_all_trees(lcodes, dcodes, blcodes) {
21178        var rank; // index in bl_order
21179
21180        send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
21181
21182        send_bits(dcodes - 1, 5);
21183        send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
21184
21185        for (rank = 0; rank < blcodes; rank++) {
21186          send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3);
21187        }
21188
21189        send_tree(dyn_ltree, lcodes - 1); // literal tree
21190
21191        send_tree(dyn_dtree, dcodes - 1); // distance tree
21192      } // Flush the bit buffer, keeping at most 7 bits in it.
21193
21194
21195      function bi_flush() {
21196        if (bi_valid == 16) {
21197          put_short(bi_buf);
21198          bi_buf = 0;
21199          bi_valid = 0;
21200        } else if (bi_valid >= 8) {
21201          put_byte(bi_buf & 0xff);
21202          bi_buf >>>= 8;
21203          bi_valid -= 8;
21204        }
21205      } // Send one empty static block to give enough lookahead for inflate.
21206      // This takes 10 bits, of which 7 may remain in the bit buffer.
21207      // The current inflate code requires 9 bits of lookahead. If the
21208      // last two codes for the previous block (real code plus EOB) were coded
21209      // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
21210      // the last real code. In this case we send two empty static blocks instead
21211      // of one. (There are no problems if the previous block is stored or fixed.)
21212      // To simplify the code, we assume the worst case of last real code encoded
21213      // on one bit only.
21214
21215
21216      function _tr_align() {
21217        send_bits(STATIC_TREES << 1, 3);
21218        send_code(END_BLOCK, StaticTree.static_ltree);
21219        bi_flush(); // Of the 10 bits for the empty block, we have already sent
21220        // (10 - bi_valid) bits. The lookahead for the last real code (before
21221        // the EOB of the previous block) was thus at least one plus the length
21222        // of the EOB plus what we have just sent of the empty static block.
21223
21224        if (1 + last_eob_len + 10 - bi_valid < 9) {
21225          send_bits(STATIC_TREES << 1, 3);
21226          send_code(END_BLOCK, StaticTree.static_ltree);
21227          bi_flush();
21228        }
21229
21230        last_eob_len = 7;
21231      } // Save the match info and tally the frequency counts. Return true if
21232      // the current block must be flushed.
21233
21234
21235      function _tr_tally(dist, // distance of matched string
21236      lc // match length-MIN_MATCH or unmatched char (if dist==0)
21237      ) {
21238        var out_length, in_length, dcode;
21239        that.pending_buf[d_buf + last_lit * 2] = dist >>> 8 & 0xff;
21240        that.pending_buf[d_buf + last_lit * 2 + 1] = dist & 0xff;
21241        that.pending_buf[l_buf + last_lit] = lc & 0xff;
21242        last_lit++;
21243
21244        if (dist === 0) {
21245          // lc is the unmatched char
21246          dyn_ltree[lc * 2]++;
21247        } else {
21248          matches++; // Here, lc is the match length - MIN_MATCH
21249
21250          dist--; // dist = match distance - 1
21251
21252          dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++;
21253          dyn_dtree[Tree.d_code(dist) * 2]++;
21254        }
21255
21256        if ((last_lit & 0x1fff) === 0 && level > 2) {
21257          // Compute an upper bound for the compressed length
21258          out_length = last_lit * 8;
21259          in_length = strstart - block_start;
21260
21261          for (dcode = 0; dcode < D_CODES; dcode++) {
21262            out_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]);
21263          }
21264
21265          out_length >>>= 3;
21266          if (matches < Math.floor(last_lit / 2) && out_length < Math.floor(in_length / 2)) return true;
21267        }
21268
21269        return last_lit == lit_bufsize - 1; // We avoid equality with lit_bufsize because of wraparound at 64K
21270        // on 16 bit machines and because stored blocks are restricted to
21271        // 64K-1 bytes.
21272      } // Send the block data compressed using the given Huffman trees
21273
21274
21275      function compress_block(ltree, dtree) {
21276        var dist; // distance of matched string
21277
21278        var lc; // match length or unmatched char (if dist === 0)
21279
21280        var lx = 0; // running index in l_buf
21281
21282        var code; // the code to send
21283
21284        var extra; // number of extra bits to send
21285
21286        if (last_lit !== 0) {
21287          do {
21288            dist = that.pending_buf[d_buf + lx * 2] << 8 & 0xff00 | that.pending_buf[d_buf + lx * 2 + 1] & 0xff;
21289            lc = that.pending_buf[l_buf + lx] & 0xff;
21290            lx++;
21291
21292            if (dist === 0) {
21293              send_code(lc, ltree); // send a literal byte
21294            } else {
21295              // Here, lc is the match length - MIN_MATCH
21296              code = Tree._length_code[lc];
21297              send_code(code + LITERALS + 1, ltree); // send the length
21298              // code
21299
21300              extra = Tree.extra_lbits[code];
21301
21302              if (extra !== 0) {
21303                lc -= Tree.base_length[code];
21304                send_bits(lc, extra); // send the extra length bits
21305              }
21306
21307              dist--; // dist is now the match distance - 1
21308
21309              code = Tree.d_code(dist);
21310              send_code(code, dtree); // send the distance code
21311
21312              extra = Tree.extra_dbits[code];
21313
21314              if (extra !== 0) {
21315                dist -= Tree.base_dist[code];
21316                send_bits(dist, extra); // send the extra distance bits
21317              }
21318            } // literal or match pair ?
21319            // Check that the overlay between pending_buf and d_buf+l_buf is
21320            // ok:
21321
21322          } while (lx < last_lit);
21323        }
21324
21325        send_code(END_BLOCK, ltree);
21326        last_eob_len = ltree[END_BLOCK * 2 + 1];
21327      } // Flush the bit buffer and align the output on a byte boundary
21328
21329
21330      function bi_windup() {
21331        if (bi_valid > 8) {
21332          put_short(bi_buf);
21333        } else if (bi_valid > 0) {
21334          put_byte(bi_buf & 0xff);
21335        }
21336
21337        bi_buf = 0;
21338        bi_valid = 0;
21339      } // Copy a stored block, storing first the length and its
21340      // one's complement if requested.
21341
21342
21343      function copy_block(buf, // the input data
21344      len, // its length
21345      header // true if block header must be written
21346      ) {
21347        bi_windup(); // align on byte boundary
21348
21349        last_eob_len = 8; // enough lookahead for inflate
21350
21351        if (header) {
21352          put_short(len);
21353          put_short(~len);
21354        }
21355
21356        that.pending_buf.set(window.subarray(buf, buf + len), that.pending);
21357        that.pending += len;
21358      } // Send a stored block
21359
21360
21361      function _tr_stored_block(buf, // input block
21362      stored_len, // length of input block
21363      eof // true if this is the last block for a file
21364      ) {
21365        send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
21366
21367        copy_block(buf, stored_len, true); // with header
21368      } // Determine the best encoding for the current block: dynamic trees, static
21369      // trees or store, and output the encoded block to the zip file.
21370
21371
21372      function _tr_flush_block(buf, // input block, or NULL if too old
21373      stored_len, // length of input block
21374      eof // true if this is the last block for a file
21375      ) {
21376        var opt_lenb, static_lenb; // opt_len and static_len in bytes
21377
21378        var max_blindex = 0; // index of last bit length code of non zero freq
21379        // Build the Huffman trees unless a stored block is forced
21380
21381        if (level > 0) {
21382          // Construct the literal and distance trees
21383          l_desc.build_tree(that);
21384          d_desc.build_tree(that); // At this point, opt_len and static_len are the total bit lengths
21385          // of
21386          // the compressed block data, excluding the tree representations.
21387          // Build the bit length tree for the above two trees, and get the
21388          // index
21389          // in bl_order of the last bit length code to send.
21390
21391          max_blindex = build_bl_tree(); // Determine the best encoding. Compute first the block length in
21392          // bytes
21393
21394          opt_lenb = that.opt_len + 3 + 7 >>> 3;
21395          static_lenb = that.static_len + 3 + 7 >>> 3;
21396          if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
21397        } else {
21398          opt_lenb = static_lenb = stored_len + 5; // force a stored block
21399        }
21400
21401        if (stored_len + 4 <= opt_lenb && buf != -1) {
21402          // 4: two words for the lengths
21403          // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
21404          // Otherwise we can't have processed more than WSIZE input bytes
21405          // since
21406          // the last block flush, because compression would have been
21407          // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
21408          // transform a block into a stored block.
21409          _tr_stored_block(buf, stored_len, eof);
21410        } else if (static_lenb == opt_lenb) {
21411          send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
21412          compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
21413        } else {
21414          send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
21415          send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1);
21416          compress_block(dyn_ltree, dyn_dtree);
21417        } // The above check is made mod 2^32, for files larger than 512 MB
21418        // and uLong implemented on 32 bits.
21419
21420
21421        init_block();
21422
21423        if (eof) {
21424          bi_windup();
21425        }
21426      }
21427
21428      function flush_block_only(eof) {
21429        _tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof);
21430
21431        block_start = strstart;
21432        strm.flush_pending();
21433      } // Fill the window when the lookahead becomes insufficient.
21434      // Updates strstart and lookahead.
21435      //
21436      // IN assertion: lookahead < MIN_LOOKAHEAD
21437      // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
21438      // At least one byte has been read, or avail_in === 0; reads are
21439      // performed for at least two bytes (required for the zip translate_eol
21440      // option -- not supported here).
21441
21442
21443      function fill_window() {
21444        var n, m;
21445        var p;
21446        var more; // Amount of free space at the end of the window.
21447
21448        do {
21449          more = window_size - lookahead - strstart; // Deal with !@#$% 64K limit:
21450
21451          if (more === 0 && strstart === 0 && lookahead === 0) {
21452            more = w_size;
21453          } else if (more == -1) {
21454            // Very unlikely, but possible on 16 bit machine if strstart ==
21455            // 0
21456            // and lookahead == 1 (input done one byte at time)
21457            more--; // If the window is almost full and there is insufficient
21458            // lookahead,
21459            // move the upper half to the lower one to make room in the
21460            // upper half.
21461          } else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) {
21462            window.set(window.subarray(w_size, w_size + w_size), 0);
21463            match_start -= w_size;
21464            strstart -= w_size; // we now have strstart >= MAX_DIST
21465
21466            block_start -= w_size; // Slide the hash table (could be avoided with 32 bit values
21467            // at the expense of memory usage). We slide even when level ==
21468            // 0
21469            // to keep the hash table consistent if we switch back to level
21470            // > 0
21471            // later. (Using level 0 permanently is not an optimal usage of
21472            // zlib, so we don't care about this pathological case.)
21473
21474            n = hash_size;
21475            p = n;
21476
21477            do {
21478              m = head[--p] & 0xffff;
21479              head[p] = m >= w_size ? m - w_size : 0;
21480            } while (--n !== 0);
21481
21482            n = w_size;
21483            p = n;
21484
21485            do {
21486              m = prev[--p] & 0xffff;
21487              prev[p] = m >= w_size ? m - w_size : 0; // If n is not on any hash chain, prev[n] is garbage but
21488              // its value will never be used.
21489            } while (--n !== 0);
21490
21491            more += w_size;
21492          }
21493
21494          if (strm.avail_in === 0) return; // If there was no sliding:
21495          // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
21496          // more == window_size - lookahead - strstart
21497          // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
21498          // => more >= window_size - 2*WSIZE + 2
21499          // In the BIG_MEM or MMAP case (not yet supported),
21500          // window_size == input_size + MIN_LOOKAHEAD &&
21501          // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
21502          // Otherwise, window_size == 2*WSIZE so more >= 2.
21503          // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
21504
21505          n = strm.read_buf(window, strstart + lookahead, more);
21506          lookahead += n;
21506 // Initialize the hash value now that we have some input:
21507
21508          if (lookahead >= MIN_MATCH) {
21509            ins_h = window[strstart] & 0xff;
21510            ins_h = (ins_h << hash_shift ^ window[strstart + 1] & 0xff) & hash_mask;
21511          } // If the whole input has less than MIN_MATCH bytes, ins_h is
21512          // garbage,
21513          // but this is not important since only literal bytes will be
21514          // emitted.
21515
21516        } while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0);
21517      } // Copy without compression as much as possible from the input stream,
21518      // return
21519      // the current block state.
21520      // This function does not insert new strings in the dictionary since
21521      // uncompressible data is probably not useful. This function is used
21522      // only for the level=0 compression option.
21523      // NOTE: this function should be optimized to avoid extra copying from
21524      // window to pending_buf.
21525
21526
21527      function deflate_stored(flush) {
21528        // Stored blocks are limited to 0xffff bytes, pending_buf is limited
21529        // to pending_buf_size, and each stored block has a 5 byte header:
21530        var max_block_size = 0xffff;
21531        var max_start;
21532
21533        if (max_block_size > pending_buf_size - 5) {
21534          max_block_size = pending_buf_size - 5;
21535        } // Copy as much as possible from input to output:
21536
21537
21538        while (true) {
21539          // Fill the window as much as possible:
21540          if (lookahead <= 1) {
21541            fill_window();
21542            if (lookahead === 0 && flush == Z_NO_FLUSH) return NeedMore;
21543            if (lookahead === 0) break; // flush the current block
21544          }
21545
21546          strstart += lookahead;
21547          lookahead = 0; // Emit a stored block if pending_buf will be full:
21548
21549          max_start = block_start + max_block_size;
21550
21551          if (strstart === 0 || strstart >= max_start) {
21552            // strstart === 0 is possible when wraparound on 16-bit machine
21553            lookahead = strstart - max_start;
21554            strstart = max_start;
21555            flush_block_only(false);
21556            if (strm.avail_out === 0) return NeedMore;
21557          } // Flush if we may have to slide, otherwise block_start may become
21558          // negative and the data will be gone:
21559
21560
21561          if (strstart - block_start >= w_size - MIN_LOOKAHEAD) {
21562            flush_block_only(false);
21563            if (strm.avail_out === 0) return NeedMore;
21564          }
21565        }
21566
21567        flush_block_only(flush == Z_FINISH);
21568        if (strm.avail_out === 0) return flush == Z_FINISH ? FinishStarted : NeedMore;
21569        return flush == Z_FINISH ? FinishDone : BlockDone;
21570      }
21571
21572      function longest_match(cur_match) {
21573        var chain_length = max_chain_length; // max hash chain length
21574
21575        var scan = strstart; // current string
21576
21577        var match; // matched string
21578
21579        var len; // length of current match
21580
21581        var best_len = prev_length; // best match length so far
21582
21583        var limit = strstart > w_size - MIN_LOOKAHEAD ? strstart - (w_size - MIN_LOOKAHEAD) : 0;
21584        var _nice_match = nice_match; // Stop when cur_match becomes <= limit. To simplify the code,
21585        // we prevent matches with the string of window index 0.
21586
21587        var wmask = w_mask;
21588        var strend = strstart + MAX_MATCH;
21589        var scan_end1 = window[scan + best_len - 1];
21590        var scan_end = window[scan + best_len]; // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of
21591        // 16.
21592        // It is easy to get rid of this optimization if necessary.
21593        // Do not waste too much time if we already have a good match:
21594
21595        if (prev_length >= good_match) {
21596          chain_length >>= 2;
21597        } // Do not look for matches beyond the end of the input. This is
21598        // necessary
21599        // to make deflate deterministic.
21600
21601
21602        if (_nice_match > lookahead) _nice_match = lookahead;
21603
21604        do {
21605          match = cur_match; // Skip to next match if the match length cannot increase
21606          // or if the match length is less than 2:
21607
21608          if (window[match + best_len] != scan_end || window[match + best_len - 1] != scan_end1 || window[match] != window[scan] || window[++match] != window[scan + 1]) continue; // The check at best_len-1 can be removed because it will be made
21609          // again later. (This heuristic is not always a win.)
21610          // It is not necessary to compare scan[2] and match[2] since they
21611          // are always equal when the other bytes match, given that
21612          // the hash keys are equal and that HASH_BITS >= 8.
21613
21614          scan += 2;
21615          match++; // We check for insufficient lookahead only every 8th comparison;
21616          // the 256th check will be made at strstart+258.
21617
21618          do {} while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend);
21619
21620          len = MAX_MATCH - (strend - scan);
21621          scan = strend - MAX_MATCH;
21622
21623          if (len > best_len) {
21624            match_start = cur_match;
21625            best_len = len;
21626            if (len >= _nice_match) break;
21627            scan_end1 = window[scan + best_len - 1];
21628            scan_end = window[scan + best_len];
21629          }
21630        } while ((cur_match = prev[cur_match & wmask] & 0xffff) > limit && --chain_length !== 0);
21631
21632        if (best_len <= lookahead) return best_len;
21633        return lookahead;
21634      } // Compress as much as possible from the input stream, return the current
21635      // block state.
21636      // This function does not perform lazy evaluation of matches and inserts
21637      // new strings in the dictionary only for unmatched strings or for short
21638      // matches. It is used only for the fast compression options.
21639
21640
21641      function deflate_fast(flush) {
21642        // short hash_head = 0; // head of the hash chain
21643        var hash_head = 0; // head of the hash chain
21644
21645        var bflush; // set if current block must be flushed
21646
21647        while (true) {
21648          // Make sure that we always have enough lookahead, except
21649          // at the end of the input file. We need MAX_MATCH bytes
21650          // for the next match, plus MIN_MATCH bytes to insert the
21651          // string following the next match.
21652          if (lookahead < MIN_LOOKAHEAD) {
21653            fill_window();
21654
21655            if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
21656              return NeedMore;
21657            }
21658
21659            if (lookahead === 0) break; // flush the current block
21660          } // Insert the string window[strstart .. strstart+2] in the
21661          // dictionary, and set hash_head to the head of the hash chain:
21662
21663
21664          if (lookahead >= MIN_MATCH) {
21665            ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h];
21666
21667            hash_head = head[ins_h] & 0xffff;
21668            prev[strstart & w_mask] = head[ins_h];
21669            head[ins_h] = strstart;
21670          } // Find the longest match, discarding those <= prev_length.
21671          // At this point we have always match_length < MIN_MATCH
21672
21673
21674          if (hash_head !== 0 && (strstart - hash_head & 0xffff) <= w_size - MIN_LOOKAHEAD) {
21675            // To simplify the code, we prevent matches with the string
21676            // of window index 0 (in particular we have to avoid a match
21677            // of the string with itself at the start of the input file).
21678            if (strategy != Z_HUFFMAN_ONLY) {
21679              match_length = longest_match(hash_head);
21680            } // longest_match() sets match_start
21681
21682          }
21683
21684          if (match_length >= MIN_MATCH) {
21685            // check_match(strstart, match_start, match_length);
21686            bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);
21687            lookahead -= match_length; // Insert new strings in the hash table only if the match length
21688            // is not too large. This saves time but degrades compression.
21689
21690            if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) {
21691              match_length--; // string at strstart already in hash table
21692
21693              do {
21694                strstart++;
21695                ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h];
21696
21697                hash_head = head[ins_h] & 0xffff;
21698                prev[strstart & w_mask] = head[ins_h];
21699                head[ins_h] = strstart; // strstart never exceeds WSIZE-MAX_MATCH, so there are
21700                // always MIN_MATCH bytes ahead.
21701              } while (--match_length !== 0);
21702
21703              strstart++;
21704            } else {
21705              strstart += match_length;
21706              match_length = 0;
21707              ins_h = window[strstart] & 0xff;
21708              ins_h = (ins_h << hash_shift ^ window[strstart + 1] & 0xff) & hash_mask; // If lookahead < MIN_MATCH, ins_h is garbage, but it does
21709              // not
21710              // matter since it will be recomputed at next deflate call.
21711            }
21712          } else {
21713            // No match, output a literal byte
21714            bflush = _tr_tally(0, window[strstart] & 0xff);
21715            lookahead--;
21716            strstart++;
21717          }
21718
21719          if (bflush) {
21720            flush_block_only(false);
21721            if (strm.avail_out === 0) return NeedMore;
21722          }
21723        }
21724
21725        flush_block_only(flush == Z_FINISH);
21726
21727        if (strm.avail_out === 0) {
21728          if (flush == Z_FINISH) return FinishStarted;else return NeedMore;
21729        }
21730
21731        return flush == Z_FINISH ? FinishDone : BlockDone;
21732      } // Same as above, but achieves better compression. We use a lazy
21733      // evaluation for matches: a match is finally adopted only if there is
21734      // no better match at the next window position.
21735
21736
21737      function deflate_slow(flush) {
21738        // short hash_head = 0; // head of hash chain
21739        var hash_head = 0; // head of hash chain
21740
21741        var bflush; // set if current block must be flushed
21742
21743        var max_insert; // Process the input block.
21744
21745        while (true) {
21746          // Make sure that we always have enough lookahead, except
21747          // at the end of the input file. We need MAX_MATCH bytes
21748          // for the next match, plus MIN_MATCH bytes to insert the
21749          // string following the next match.
21750          if (lookahead < MIN_LOOKAHEAD) {
21751            fill_window();
21752
21753            if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
21754              return NeedMore;
21755            }
21756
21757            if (lookahead === 0) break; // flush the current block
21758          } // Insert the string window[strstart .. strstart+2] in the
21759          // dictionary, and set hash_head to the head of the hash chain:
21760
21761
21762          if (lookahead >= MIN_MATCH) {
21763            ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask;
21763 // prev[strstart&w_mask]=hash_head=head[ins_h];
21764
21765            hash_head = head[ins_h] & 0xffff;
21766            prev[strstart & w_mask] = head[ins_h];
21767            head[ins_h] = strstart;
21768          } // Find the longest match, discarding those <= prev_length.
21769
21770
21771          prev_length = match_length;
21772          prev_match = match_start;
21773          match_length = MIN_MATCH - 1;
21774
21775          if (hash_head !== 0 && prev_length < max_lazy_match && (strstart - hash_head & 0xffff) <= w_size - MIN_LOOKAHEAD) {
21776            // To simplify the code, we prevent matches with the string
21777            // of window index 0 (in particular we have to avoid a match
21778            // of the string with itself at the start of the input file).
21779            if (strategy != Z_HUFFMAN_ONLY) {
21780              match_length = longest_match(hash_head);
21781            } // longest_match() sets match_start
21782
21783
21784            if (match_length <= 5 && (strategy == Z_FILTERED || match_length == MIN_MATCH && strstart - match_start > 4096)) {
21785              // If prev_match is also MIN_MATCH, match_start is garbage
21786              // but we will ignore the current match anyway.
21787              match_length = MIN_MATCH - 1;
21788            }
21789          } // If there was a match at the previous step and the current
21790          // match is not better, output the previous match:
21791
21792
21793          if (prev_length >= MIN_MATCH && match_length <= prev_length) {
21794            max_insert = strstart + lookahead - MIN_MATCH; // Do not insert strings in hash table beyond this.
21795            // check_match(strstart-1, prev_match, prev_length);
21796
21797            bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH); // Insert in hash table all strings up to the end of the match.
21798            // strstart-1 and strstart are already inserted. If there is not
21799            // enough lookahead, the last two strings are not inserted in
21800            // the hash table.
21801
21802            lookahead -= prev_length - 1;
21803            prev_length -= 2;
21804
21805            do {
21806              if (++strstart <= max_insert) {
21807                ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h];
21808
21809                hash_head = head[ins_h] & 0xffff;
21810                prev[strstart & w_mask] = head[ins_h];
21811                head[ins_h] = strstart;
21812              }
21813            } while (--prev_length !== 0);
21814
21815            match_available = 0;
21816            match_length = MIN_MATCH - 1;
21817            strstart++;
21818
21819            if (bflush) {
21820              flush_block_only(false);
21821              if (strm.avail_out === 0) return NeedMore;
21822            }
21823          } else if (match_available !== 0) {
21824            // If there was no match at the previous position, output a
21825            // single literal. If there was a match but the current match
21826            // is longer, truncate the previous match to a single literal.
21827            bflush = _tr_tally(0, window[strstart - 1] & 0xff);
21828
21829            if (bflush) {
21830              flush_block_only(false);
21831            }
21832
21833            strstart++;
21834            lookahead--;
21835            if (strm.avail_out === 0) return NeedMore;
21836          } else {
21837            // There is no previous match to compare with, wait for
21838            // the next step to decide.
21839            match_available = 1;
21840            strstart++;
21841            lookahead--;
21842          }
21843        }
21844
21845        if (match_available !== 0) {
21846          bflush = _tr_tally(0, window[strstart - 1] & 0xff);
21847          match_available = 0;
21848        }
21849
21850        flush_block_only(flush == Z_FINISH);
21851
21852        if (strm.avail_out === 0) {
21853          if (flush == Z_FINISH) return FinishStarted;else return NeedMore;
21854        }
21855
21856        return flush == Z_FINISH ? FinishDone : BlockDone;
21857      }
21858
21859      function deflateReset(strm) {
21860        strm.total_in = strm.total_out = 0;
21861        strm.msg = null; //
21862
21863        that.pending = 0;
21864        that.pending_out = 0;
21865        status = BUSY_STATE;
21866        last_flush = Z_NO_FLUSH;
21867        tr_init();
21868        lm_init();
21869        return Z_OK;
21870      }
21871
21872      that.deflateInit = function (strm, _level, bits, _method, memLevel, _strategy) {
21873        if (!_method) _method = Z_DEFLATED;
21874        if (!memLevel) memLevel = DEF_MEM_LEVEL;
21875        if (!_strategy) _strategy = Z_DEFAULT_STRATEGY; // byte[] my_version=ZLIB_VERSION;
21876        //
21877        // if (!version || version[0] != my_version[0]
21878        // || stream_size != sizeof(z_stream)) {
21879        // return Z_VERSION_ERROR;
21880        // }
21881
21882        strm.msg = null;
21883        if (_level == Z_DEFAULT_COMPRESSION) _level = 6;
21884
21885        if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
21886          return Z_STREAM_ERROR;
21887        }
21888
21889        strm.dstate = that;
21890        w_bits = bits;
21891        w_size = 1 << w_bits;
21892        w_mask = w_size - 1;
21893        hash_bits = memLevel + 7;
21894        hash_size = 1 << hash_bits;
21895        hash_mask = hash_size - 1;
21896        hash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH);
21897        window = new Uint8Array(w_size * 2);
21898        prev = [];
21899        head = [];
21900        lit_bufsize = 1 << memLevel + 6; // 16K elements by default
21901        // We overlay pending_buf and d_buf+l_buf. This works since the average
21902        // output size for (length,distance) codes is <= 24 bits.
21903
21904        that.pending_buf = new Uint8Array(lit_bufsize * 4);
21905        pending_buf_size = lit_bufsize * 4;
21906        d_buf = Math.floor(lit_bufsize / 2);
21907        l_buf = (1 + 2) * lit_bufsize;
21908        level = _level;
21909        strategy = _strategy;
21910        return deflateReset(strm);
21911      };
21912
21913      that.deflateEnd = function () {
21914        if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) {
21915          return Z_STREAM_ERROR;
21916        } // Deallocate in reverse order of allocations:
21917
21918
21919        that.pending_buf = null;
21920        head = null;
21921        prev = null;
21922        window = null; // free
21923
21924        that.dstate = null;
21925        return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
21926      };
21927
21928      that.deflateParams = function (strm, _level, _strategy) {
21929        var err = Z_OK;
21930
21931        if (_level == Z_DEFAULT_COMPRESSION) {
21932          _level = 6;
21933        }
21934
21935        if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
21936          return Z_STREAM_ERROR;
21937        }
21938
21939        if (config_table[level].func != config_table[_level].func && strm.total_in !== 0) {
21940          // Flush the last buffer:
21941          err = strm.deflate(Z_PARTIAL_FLUSH);
21942        }
21943
21944        if (level != _level) {
21945          level = _level;
21946          max_lazy_match = config_table[level].max_lazy;
21947          good_match = config_table[level].good_length;
21948          nice_match = config_table[level].nice_length;
21949          max_chain_length = config_table[level].max_chain;
21950        }
21951
21952        strategy = _strategy;
21953        return err;
21954      };
21955
21956      that.deflateSetDictionary = function (strm, dictionary, dictLength) {
21957        var length = dictLength;
21958        var n,
21959            index = 0;
21960        if (!dictionary || status != INIT_STATE) return Z_STREAM_ERROR;
21961        if (length < MIN_MATCH) return Z_OK;
21962
21963        if (length > w_size - MIN_LOOKAHEAD) {
21964          length = w_size - MIN_LOOKAHEAD;
21965          index = dictLength - length; // use the tail of the dictionary
21966        }
21967
21968        window.set(dictionary.subarray(index, index + length), 0);
21969        strstart = length;
21970        block_start = length; // Insert all strings in the hash table (except for the last two bytes).
21971        // s->lookahead stays null, so s->ins_h will be recomputed at the next
21972        // call of fill_window.
21973
21974        ins_h = window[0] & 0xff;
21975        ins_h = (ins_h << hash_shift ^ window[1] & 0xff) & hash_mask;
21976
21977        for (n = 0; n <= length - MIN_MATCH; n++) {
21978          ins_h = (ins_h << hash_shift ^ window[n + (MIN_MATCH - 1)] & 0xff) & hash_mask;
21979          prev[n & w_mask] = head[ins_h];
21980          head[ins_h] = n;
21981        }
21982
21983        return Z_OK;
21984      };
21985
21986      that.deflate = function (_strm, flush) {
21987        var i, header, level_flags, old_flush, bstate;
21988
21989        if (flush > Z_FINISH || flush < 0) {
21990          return Z_STREAM_ERROR;
21991        }
21992
21993        if (!_strm.next_out || !_strm.next_in && _strm.avail_in !== 0 || status == FINISH_STATE && flush != Z_FINISH) {
21994          _strm.msg = z_errmsg[Z_NEED_DICT - Z_STREAM_ERROR];
21995          return Z_STREAM_ERROR;
21996        }
21997
21998        if (_strm.avail_out === 0) {
21999          _strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR];
22000          return Z_BUF_ERROR;
22001        }
22002
22003        strm = _strm; // just in case
22004
22005        old_flush = last_flush;
22006        last_flush = flush; // Write the zlib header
22007
22008        if (status == INIT_STATE) {
22009          header = Z_DEFLATED + (w_bits - 8 << 4) << 8;
22010          level_flags = (level - 1 & 0xff) >> 1;
22011          if (level_flags > 3) level_flags = 3;
22012          header |= level_flags << 6;
22013          if (strstart !== 0) header |= PRESET_DICT;
22014          header += 31 - header % 31;
22015          status = BUSY_STATE;
22016          putShortMSB(header);
22017        } // Flush as much pending output as possible
22018
22019
22020        if (that.pending !== 0) {
22021          strm.flush_pending();
22022
22023          if (strm.avail_out === 0) {
22024            // console.log(" avail_out==0");
22025            // Since avail_out is 0, deflate will be called again with
22026            // more output space, but possibly with both pending and
22027            // avail_in equal to zero. There won't be anything to do,
22028            // but this is not an error situation so make sure we
22029            // return OK instead of BUF_ERROR at next call of deflate:
22030            last_flush = -1;
22031            return Z_OK;
22032          } // Make sure there is something to do and avoid duplicate
22033          // consecutive
22034          // flushes. For repeated and useless calls with Z_FINISH, we keep
22035          // returning Z_STREAM_END instead of Z_BUFF_ERROR.
22036
22037        } else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) {
22038          strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR];
22039          return Z_BUF_ERROR;
22040        } // User must not provide more input after the first FINISH:
22041
22042
22043        if (status == FINISH_STATE && strm.avail_in !== 0) {
22044          _strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR];
22045          return Z_BUF_ERROR;
22046        } // Start a new block or continue the current one.
22047
22048
22049        if (strm.avail_in !== 0 || lookahead !== 0 || flush != Z_NO_FLUSH && status != FINISH_STATE) {
22050          bstate = -1;
22051
22052          switch (config_table[level].func) {
22053            case STORED:
22054              bstate = deflate_stored(flush);
22055              break;
22056
22057            case FAST:
22058              bstate = deflate_fast(flush);
22059              break;
22060
22061            case SLOW:
22062              bstate = deflate_slow(flush);
22063              break;
22064
22065            default:
22066          }
22067
22068          if (bstate == FinishStarted || bstate == FinishDone) {
22069            status = FINISH_STATE;
22070          }
22071
22072          if (bstate == NeedMore || bstate == FinishStarted) {
22073            if (strm.avail_out === 0) {
22074              last_flush = -1; // avoid BUF_ERROR next call, see above
22075            }
22076
22077            return Z_OK; // If flush != Z_NO_FLUSH && avail_out === 0, the next call
22078            // of deflate should use the same flush parameter to make sure
22079            // that the flush is complete. So we don't have to output an
22080            // empty block here, this will be done at next call. This also
22081            // ensures that for a very small output buffer, we emit at most
22082            // one empty block.
22083          }
22084
22085          if (bstate == BlockDone) {
22086            if (flush == Z_PARTIAL_FLUSH) {
22087              _tr_align();
22088            } else {
22089              // FULL_FLUSH or SYNC_FLUSH
22090              _tr_stored_block(0, 0, false); // For a full flush, this empty block will be recognized
22091              // as a special marker by inflate_sync().
22092
22093
22094              if (flush == Z_FULL_FLUSH) {
22095                // state.head[s.hash_size-1]=0;
22096                for (i = 0; i < hash_size
22097                /*-1*/
22098                ; i++) {
22099                  // forget history
22100                  head[i] = 0;
22101                }
22102              }
22103            }
22104
22105            strm.flush_pending();
22106
22107            if (strm.avail_out === 0) {
22108              last_flush = -1; // avoid BUF_ERROR at next call, see above
22109
22110              return Z_OK;
22111            }
22112          }
22113        }
22114
22115        if (flush != Z_FINISH) return Z_OK;
22116        return Z_STREAM_END;
22117      };
22118    } // ZStream
22119
22120
22121    function ZStream() {
22122      var that = this;
22123      that.next_in_index = 0;
22124      that.next_out_index = 0; // that.next_in; // next input byte
22125
22126      that.avail_in = 0; // number of bytes available at next_in
22127
22128      that.total_in = 0; // total nb of input bytes read so far
22129      // that.next_out; // next output byte should be put there
22130
22131      that.avail_out = 0; // remaining free space at next_out
22132
22133      that.total_out = 0; // total nb of bytes output so far
22134      // that.msg;
22135      // that.dstate;
22136    }
22137
22138    ZStream.prototype = {
22139      deflateInit: function deflateInit(level, bits) {
22140        var that = this;
22141        that.dstate = new Deflate();
22142        if (!bits) bits = MAX_BITS;
22143        return that.dstate.deflateInit(that, level, bits);
22144      },
22145      deflate: function deflate(flush) {
22146        var that = this;
22147
22148        if (!that.dstate) {
22149          return Z_STREAM_ERROR;
22150        }
22151
22152        return that.dstate.deflate(that, flush);
22153      },
22154      deflateEnd: function deflateEnd() {
22155        var that = this;
22156        if (!that.dstate) return Z_STREAM_ERROR;
22157        var ret = that.dstate.deflateEnd();
22158        that.dstate = null;
22159        return ret;
22160      },
22161      deflateParams: function deflateParams(level, strategy) {
22162        var that = this;
22163        if (!that.dstate) return Z_STREAM_ERROR;
22164        return that.dstate.deflateParams(that, level, strategy);
22165      },
22166      deflateSetDictionary: function deflateSetDictionary(dictionary, dictLength) {
22167        var that = this;
22168        if (!that.dstate) return Z_STREAM_ERROR;
22169        return that.dstate.deflateSetDictionary(that, dictionary, dictLength);
22170      },
22171      // Read a new buffer from the current input stream, update the
22172      // total number of bytes read. All deflate() input goes through
22173      // this function so some applications may wish to modify it to avoid
22174      // allocating a large strm->next_in buffer and copying from it.
22175      // (See also flush_pending()).
22176      read_buf: function read_buf(buf, start, size) {
22177        var that = this;
22178        var len = that.avail_in;
22179        if (len > size) len = size;
22180        if (len === 0) return 0;
22181        that.avail_in -= len;
22182        buf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start);
22183        that.next_in_index += len;
22184        that.total_in += len;
22185        return len;
22186      },
22187      // Flush as much pending output as possible. All deflate() output goes
22188      // through this function so some applications may wish to modify it
22189      // to avoid allocating a large strm->next_out buffer and copying into it.
22190      // (See also read_buf()).
22191      flush_pending: function flush_pending() {
22192        var that = this;
22193        var len = that.dstate.pending;
22194        if (len > that.avail_out) len = that.avail_out;
22195        if (len === 0) return; // if (that.dstate.pending_buf.length <= that.dstate.pending_out || that.next_out.length <= that.next_out_index
22196        // || that.dstate.pending_buf.length < (that.dstate.pending_out + len) || that.next_out.length < (that.next_out_index +
22197        // len)) {
22198        // console.log(that.dstate.pending_buf.length + ", " + that.dstate.pending_out + ", " + that.next_out.length + ", " +
22199        // that.next_out_index + ", " + len);
22200        // console.log("avail_out=" + that.avail_out);
22201        // }
22202
22203        that.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index);
22204        that.next_out_index += len;
22205        that.dstate.pending_out += len;
22206        that.total_out += len;
22207        that.avail_out -= len;
22208        that.dstate.pending -= len;
22209
22210        if (that.dstate.pending === 0) {
22211          that.dstate.pending_out = 0;
22212        }
22213      }
22214    }; // Deflater
22215
22216    function Deflater(options) {
22217      var that = this;
22218      var z = new ZStream();
22219      var bufsize = 512;
22220      var flush = Z_NO_FLUSH;
22221      var buf = new Uint8Array(bufsize);
22222      var level = options ? options.level : Z_DEFAULT_COMPRESSION;
22223      if (typeof level == "undefined") level = Z_DEFAULT_COMPRESSION;
22224      z.deflateInit(level);
22225      z.next_out = buf;
22226
22227      that.append = function (data, onprogress) {
22228        var err,
22229            buffers = [],
22230            lastIndex = 0,
22231            bufferIndex = 0,
22232            bufferSize = 0,
22233            array;
22234        if (!data.length) return;
22235        z.next_in_index = 0;
22236        z.next_in = data;
22237        z.avail_in = data.length;
22238
22239        do {
22240          z.next_out_index = 0;
22241          z.avail_out = bufsize;
22242          err = z.deflate(flush);
22243          if (err != Z_OK) throw new Error("deflating: " + z.msg);
22244          if (z.next_out_index) if (z.next_out_index == bufsize) buffers.push(new Uint8Array(buf));else buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
22245          bufferSize += z.next_out_index;
22246
22247          if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
22248            onprogress(z.next_in_index);
22249            lastIndex = z.next_in_index;
22250          }
22251        } while (z.avail_in > 0 || z.avail_out === 0);
22252
22253        array = new Uint8Array(bufferSize);
22254        buffers.forEach(function (chunk) {
22255          array.set(chunk, bufferIndex);
22256          bufferIndex += chunk.length;
22257        });
22258        return array;
22259      };
22260
22261      that.flush = function () {
22262        var err,
22263            buffers = [],
22264            bufferIndex = 0,
22265            bufferSize = 0,
22266            array;
22267
22268        do {
22269          z.next_out_index = 0;
22270          z.avail_out = bufsize;
22271          err = z.deflate(Z_FINISH);
22272          if (err != Z_STREAM_END && err != Z_OK) throw new Error("deflating: " + z.msg);
22273          if (bufsize - z.avail_out > 0) buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
22274          bufferSize += z.next_out_index;
22275        } while (z.avail_in > 0 || z.avail_out === 0);
22276
22277        z.deflateEnd();
22278        array = new Uint8Array(bufferSize);
22279        buffers.forEach(function (chunk) {
22280          array.set(chunk, bufferIndex);
22281          bufferIndex += chunk.length;
22282        });
22283        return array;
22284      };
22285    } // 'zip' may not be defined in z-worker and some tests
22286
22287
22288    var env = global.zip || global;
22289    env.Deflater = env._jzlib_Deflater = Deflater;
22290  })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function('return this')()); // `self` is undefined in Firefox for Android content script context
22291  // while `this` is nsIContentFrameMessageManager
22292  // with an attribute `content` that corresponds to the window
22293
22294  /**
22295   * A class to parse color values
22296   * @author Stoyan Stefanov <[email protected]>
22297   * {@link   http://www.phpied.com/rgb-color-parser-in-javascript/}
22298   * @license Use it if you like it
22299   */
22300  (function (global) {
22301
22302    function RGBColor(color_string) {
22303      color_string = color_string || '';
22304      this.ok = false; // strip any leading #
22305
22306      if (color_string.charAt(0) == '#') {
22307        // remove # if any
22308        color_string = color_string.substr(1, 6);
22309      }
22310
22311      color_string = color_string.replace(/ /g, '');
22312      color_string = color_string.toLowerCase();
22313      var channels; // before getting into regexps, try simple matches
22314      // and overwrite the input
22315
22316      var simple_colors = {
22317        aliceblue: 'f0f8ff',
22318        antiquewhite: 'faebd7',
22319        aqua: '00ffff',
22320        aquamarine: '7fffd4',
22321        azure: 'f0ffff',
22322        beige: 'f5f5dc',
22323        bisque: 'ffe4c4',
22324        black: '000000',
22325        blanchedalmond: 'ffebcd',
22326        blue: '0000ff',
22327        blueviolet: '8a2be2',
22328        brown: 'a52a2a',
22329        burlywood: 'deb887',
22330        cadetblue: '5f9ea0',
22331        chartreuse: '7fff00',
22332        chocolate: 'd2691e',
22333        coral: 'ff7f50',
22334        cornflowerblue: '6495ed',
22335        cornsilk: 'fff8dc',
22336        crimson: 'dc143c',
22337        cyan: '00ffff',
22338        darkblue: '00008b',
22339        darkcyan: '008b8b',
22340        darkgoldenrod: 'b8860b',
22341        darkgray: 'a9a9a9',
22342        darkgreen: '006400',
22343        darkkhaki: 'bdb76b',
22344        darkmagenta: '8b008b',
22345        darkolivegreen: '556b2f',
22346        darkorange: 'ff8c00',
22347        darkorchid: '9932cc',
22348        darkred: '8b0000',
22349        darksalmon: 'e9967a',
22350        darkseagreen: '8fbc8f',
22351        darkslateblue: '483d8b',
22352        darkslategray: '2f4f4f',
22353        darkturquoise: '00ced1',
22354        darkviolet: '9400d3',
22355        deeppink: 'ff1493',
22356        deepskyblue: '00bfff',
22357        dimgray: '696969',
22358        dodgerblue: '1e90ff',
22359        feldspar: 'd19275',
22360        firebrick: 'b22222',
22361        floralwhite: 'fffaf0',
22362        forestgreen: '228b22',
22363        fuchsia: 'ff00ff',
22364        gainsboro: 'dcdcdc',
22365        ghostwhite: 'f8f8ff',
22366        gold: 'ffd700',
22367        goldenrod: 'daa520',
22368        gray: '808080',
22369        green: '008000',
22370        greenyellow: 'adff2f',
22371        honeydew: 'f0fff0',
22372        hotpink: 'ff69b4',
22373        indianred: 'cd5c5c',
22374        indigo: '4b0082',
22375        ivory: 'fffff0',
22376        khaki: 'f0e68c',
22377        lavender: 'e6e6fa',
22378        lavenderblush: 'fff0f5',
22379        lawngreen: '7cfc00',
22380        lemonchiffon: 'fffacd',
22381        lightblue: 'add8e6',
22382        lightcoral: 'f08080',
22383        lightcyan: 'e0ffff',
22384        lightgoldenrodyellow: 'fafad2',
22385        lightgrey: 'd3d3d3',
22386        lightgreen: '90ee90',
22387        lightpink: 'ffb6c1',
22388        lightsalmon: 'ffa07a',
22389        lightseagreen: '20b2aa',
22390        lightskyblue: '87cefa',
22391        lightslateblue: '8470ff',
22392        lightslategray: '778899',
22393        lightsteelblue: 'b0c4de',
22394        lightyellow: 'ffffe0',
22395        lime: '00ff00',
22396        limegreen: '32cd32',
22397        linen: 'faf0e6',
22398        magenta: 'ff00ff',
22399        maroon: '800000',
22400        mediumaquamarine: '66cdaa',
22401        mediumblue: '0000cd',
22402        mediumorchid: 'ba55d3',
22403        mediumpurple: '9370d8',
22404        mediumseagreen: '3cb371',
22405        mediumslateblue: '7b68ee',
22406        mediumspringgreen: '00fa9a',
22407        mediumturquoise: '48d1cc',
22408        mediumvioletred: 'c71585',
22409        midnightblue: '191970',
22410        mintcream: 'f5fffa',
22411        mistyrose: 'ffe4e1',
22412        moccasin: 'ffe4b5',
22413        navajowhite: 'ffdead',
22414        navy: '000080',
22415        oldlace: 'fdf5e6',
22416        olive: '808000',
22417        olivedrab: '6b8e23',
22418        orange: 'ffa500',
22419        orangered: 'ff4500',
22420        orchid: 'da70d6',
22421        palegoldenrod: 'eee8aa',
22422        palegreen: '98fb98',
22423        paleturquoise: 'afeeee',
22424        palevioletred: 'd87093',
22425        papayawhip: 'ffefd5',
22426        peachpuff: 'ffdab9',
22427        peru: 'cd853f',
22428        pink: 'ffc0cb',
22429        plum: 'dda0dd',
22430        powderblue: 'b0e0e6',
22431        purple: '800080',
22432        red: 'ff0000',
22433        rosybrown: 'bc8f8f',
22434        royalblue: '4169e1',
22435        saddlebrown: '8b4513',
22436        salmon: 'fa8072',
22437        sandybrown: 'f4a460',
22438        seagreen: '2e8b57',
22439        seashell: 'fff5ee',
22440        sienna: 'a0522d',
22441        silver: 'c0c0c0',
22442        skyblue: '87ceeb',
22443        slateblue: '6a5acd',
22444        slategray: '708090',
22445        snow: 'fffafa',
22446        springgreen: '00ff7f',
22447        steelblue: '4682b4',
22448        tan: 'd2b48c',
22449        teal: '008080',
22450        thistle: 'd8bfd8',
22451        tomato: 'ff6347',
22452        turquoise: '40e0d0',
22453        violet: 'ee82ee',
22454        violetred: 'd02090',
22455        wheat: 'f5deb3',
22456        white: 'ffffff',
22457        whitesmoke: 'f5f5f5',
22458        yellow: 'ffff00',
22459        yellowgreen: '9acd32'
22460      };
22461
22462      for (var key in simple_colors) {
22463        if (color_string == key) {
22464          color_string = simple_colors[key];
22465        }
22466      } // emd of simple type-in colors
22467      // array of color definition objects
22468
22469
22470      var color_defs = [{
22471        re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
22472        example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
22473        process: function process(bits) {
22474          return [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3])];
22475        }
22476      }, {
22477        re: /^(\w{2})(\w{2})(\w{2})$/,
22478        example: ['#00ff00', '336699'],
22479        process: function process(bits) {
22480          return [parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16)];
22481        }
22482      }, {
22483        re: /^(\w{1})(\w{1})(\w{1})$/,
22484        example: ['#fb0', 'f0f'],
22485        process: function process(bits) {
22486          return [parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16)];
22487        }
22488      }]; // search through the definitions to find a match
22489
22490      for (var i = 0; i < color_defs.length; i++) {
22491        var re = color_defs[i].re;
22492        var processor = color_defs[i].process;
22493        var bits = re.exec(color_string);
22494
22495        if (bits) {
22496          channels = processor(bits);
22497          this.r = channels[0];
22498          this.g = channels[1];
22499          this.b = channels[2];
22500          this.ok = true;
22501        }
22502      } // validate/cleanup values
22503
22504
22505      this.r = this.r < 0 || isNaN(this.r) ? 0 : this.r > 255 ? 255 : this.r;
22506      this.g = this.g < 0 || isNaN(this.g) ? 0 : this.g > 255 ? 255 : this.g;
22507      this.b = this.b < 0 || isNaN(this.b) ? 0 : this.b > 255 ? 255 : this.b; // some getters
22508
22509      this.toRGB = function () {
22510        return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
22511      };
22512
22513      this.toHex = function () {
22514        var r = this.r.toString(16);
22515        var g = this.g.toString(16);
22516        var b = this.b.toString(16);
22517        if (r.length == 1) r = '0' + r;
22518        if (g.length == 1) g = '0' + g;
22519        if (b.length == 1) b = '0' + b;
22520        return '#' + r + g + b;
22521      };
22522    }
22523
22524    global.RGBColor = RGBColor;
22525  })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function('return this')()); // `self` is undefined in Firefox for Android content script context
22526  // while `this` is nsIContentFrameMessageManager
22527  // with an attribute `content` that corresponds to the window
22528
22529  /************************************************
22530   * Title : custom font                          *
22531   * Start Data : 2017. 01. 22.                   *
22532   * Comment : TEXT API                           *
22533   ************************************************/
22534
22535  /******************************
22536   * jsPDF extension API Design *
22537   * ****************************/
22538  (function (jsPDF) {
22539
22540    var PLUS = '+'.charCodeAt(0);
22541    var SLASH = '/'.charCodeAt(0);
22542    var NUMBER = '0'.charCodeAt(0);
22543    var LOWER = 'a'.charCodeAt(0);
22544    var UPPER = 'A'.charCodeAt(0);
22545    var PLUS_URL_SAFE = '-'.charCodeAt(0);
22546    var SLASH_URL_SAFE = '_'.charCodeAt(0);
22547    /*****************************************************************/
22548
22549    /* function : b64ToByteArray                                     */
22550
22551    /* comment : Base64 encoded TTF file contents (b64) are decoded  */
22552
22553    /*     by Byte array and stored.                                 */
22554
22555    /*****************************************************************/
22556
22557    var b64ToByteArray = function b64ToByteArray(b64) {
22558      var i, j, l, tmp, placeHolders, arr;
22559
22560      if (b64.length % 4 > 0) {
22561        throw new Error('Invalid string. Length must be a multiple of 4');
22562      } // the number of equal signs (place holders)
22563      // if there are two placeholders, than the two characters before it
22564      // represent one byte
22565      // if there is only one, then the three characters before it represent 2 bytes
22566      // this is just a cheap hack to not do indexOf twice
22567
22568
22569      var len = b64.length;
22570      placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0; // base64 is 4/3 + up to two characters of the original data
22571
22572      arr = new Uint8Array(b64.length * 3 / 4 - placeHolders); // if there are placeholders, only get up to the last complete 4 chars
22573
22574      l = placeHolders > 0 ? b64.length - 4 : b64.length;
22575      var L = 0;
22576
22577      function push(v) {
22578        arr[L++] = v;
22579      }
22580
22581      for (i = 0, j = 0; i < l; i += 4, j += 3) {
22582        tmp = decode(b64.charAt(i)) << 18 | decode(b64.charAt(i + 1)) << 12 | decode(b64.charAt(i + 2)) << 6 | decode(b64.charAt(i + 3));
22583        push((tmp & 0xFF0000) >> 16);
22584        push((tmp & 0xFF00) >> 8);
22585        push(tmp & 0xFF);
22586      }
22587
22588      if (placeHolders === 2) {
22589        tmp = decode(b64.charAt(i)) << 2 | decode(b64.charAt(i + 1)) >> 4;
22590        push(tmp & 0xFF);
22591      } else if (placeHolders === 1) {
22592        tmp = decode(b64.charAt(i)) << 10 | decode(b64.charAt(i + 1)) << 4 | decode(b64.charAt(i + 2)) >> 2;
22593        push(tmp >> 8 & 0xFF);
22594        push(tmp & 0xFF);
22595      }
22596
22597      return arr;
22598    };
22599    /***************************************************************/
22600
22601    /* function : decode                                           */
22602
22603    /* comment : Change the base64 encoded font's content to match */
22604
22605    /*   the base64 index value.                                   */
22606
22607    /***************************************************************/
22608
22609
22610    var decode = function decode(elt) {
22611      var code = elt.charCodeAt(0);
22612      if (code === PLUS || code === PLUS_URL_SAFE) return 62; // '+'
22613
22614      if (code === SLASH || code === SLASH_URL_SAFE) return 63; // '/'
22615
22616      if (code < NUMBER) return -1; //no match
22617
22618      if (code < NUMBER + 10) return code - NUMBER + 26 + 26;
22619      if (code < UPPER + 26) return code - UPPER;
22620      if (code < LOWER + 26) return code - LOWER + 26;
22621    };
22622
22623    jsPDF.API.TTFFont = function () {
22624      /************************************************************************/
22625
22626      /* function : open                                                       */
22627
22628      /* comment : Decode the encoded ttf content and create a TTFFont object. */
22629
22630      /************************************************************************/
22631      TTFFont.open = function (filename, name, vfs, encoding) {
22632        var contents;
22633
22634        if (typeof vfs !== "string") {
22635          throw new Error('Invalid argument supplied in TTFFont.open');
22636        }
22637
22638        contents = b64ToByteArray(vfs);
22639        return new TTFFont(contents, name, encoding);
22640      };
22641      /***************************************************************/
22642
22643      /* function : TTFFont gernerator                               */
22644
22645      /* comment : Decode TTF contents are parsed, Data,             */
22646
22647      /* Subset object is created, and registerTTF function is called.*/
22648
22649      /***************************************************************/
22650
22651
22652      function TTFFont(rawData, name, encoding) {
22653        var data;
22654
22655        this.rawData = rawData;
22656        data = this.contents = new Data(rawData);
22657        this.contents.pos = 4;
22658
22659        if (data.readString(4) === 'ttcf') {
22660          if (!name) {
vendor: 59,301 bytes, lines 22661-24580
22661            throw new Error("Must specify a font name for TTC files.");
22662          }
22663          throw new Error("Font " + name + " not found in TTC file.");
22664        } else {
22665          data.pos = 0;
22666          this.parse();
22667          this.subset = new Subset(this);
22668          this.registerTTF();
22669        }
22670      }
22671      /********************************************************/
22672
22673      /* function : parse                                     */
22674
22675      /* comment : TTF Parses the file contents by each table.*/
22676
22677      /********************************************************/
22678
22679
22680      TTFFont.prototype.parse = function () {
22681        this.directory = new Directory(this.contents);
22682        this.head = new HeadTable(this);
22683        this.name = new NameTable(this);
22684        this.cmap = new CmapTable(this);
22685        this.toUnicode = new Map();
22686        this.hhea = new HheaTable(this);
22687        this.maxp = new MaxpTable(this);
22688        this.hmtx = new HmtxTable(this);
22689        this.post = new PostTable(this);
22690        this.os2 = new OS2Table(this);
22691        this.loca = new LocaTable(this);
22692        this.glyf = new GlyfTable(this);
22693        this.ascender = this.os2.exists && this.os2.ascender || this.hhea.ascender;
22694        this.decender = this.os2.exists && this.os2.decender || this.hhea.decender;
22695        this.lineGap = this.os2.exists && this.os2.lineGap || this.hhea.lineGap;
22696        return this.bbox = [this.head.xMin, this.head.yMin, this.head.xMax, this.head.yMax];
22697      };
22698      /***************************************************************/
22699
22700      /* function : registerTTF                                      */
22701
22702      /* comment : Get the value to assign pdf font descriptors.     */
22703
22704      /***************************************************************/
22705
22706
22707      TTFFont.prototype.registerTTF = function () {
22708        var e, hi, low, raw, _ref;
22709
22710        this.scaleFactor = 1000.0 / this.head.unitsPerEm;
22711
22712        this.bbox = function () {
22713          var _i, _len, _ref, _results;
22714
22715          _ref = this.bbox;
22716          _results = [];
22717
22718          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
22719            e = _ref[_i];
22720
22721            _results.push(Math.round(e * this.scaleFactor));
22722          }
22723
22724          return _results;
22725        }.call(this);
22726
22727        this.stemV = 0;
22728
22729        if (this.post.exists) {
22730          raw = this.post.italic_angle;
22731          hi = raw >> 16;
22732          low = raw & 0xFF;
22733
22734          if (hi & 0x8000 !== 0) {
22735            hi = -((hi ^ 0xFFFF) + 1);
22736          }
22737
22738          this.italicAngle = +("" + hi + "." + low);
22739        } else {
22740          this.italicAngle = 0;
22741        }
22742
22743        this.ascender = Math.round(this.ascender * this.scaleFactor);
22744        this.decender = Math.round(this.decender * this.scaleFactor);
22745        this.lineGap = Math.round(this.lineGap * this.scaleFactor);
22746        this.capHeight = this.os2.exists && this.os2.capHeight || this.ascender;
22747        this.xHeight = this.os2.exists && this.os2.xHeight || 0;
22748        this.familyClass = (this.os2.exists && this.os2.familyClass || 0) >> 8;
22749        this.isSerif = (_ref = this.familyClass) === 1 || _ref === 2 || _ref === 3 || _ref === 4 || _ref === 5 || _ref === 7;
22750        this.isScript = this.familyClass === 10;
22751        this.flags = 0;
22752
22753        if (this.post.isFixedPitch) {
22754          this.flags |= 1 << 0;
22755        }
22756
22757        if (this.isSerif) {
22758          this.flags |= 1 << 1;
22759        }
22760
22761        if (this.isScript) {
22762          this.flags |= 1 << 3;
22763        }
22764
22765        if (this.italicAngle !== 0) {
22766          this.flags |= 1 << 6;
22767        }
22768
22769        this.flags |= 1 << 5;
22770
22771        if (!this.cmap.unicode) {
22772          throw new Error('No unicode cmap for font');
22773        }
22774      };
22775
22776      TTFFont.prototype.characterToGlyph = function (character) {
22777        var _ref;
22778
22779        return ((_ref = this.cmap.unicode) != null ? _ref.codeMap[character] : void 0) || 0;
22780      };
22781
22782      TTFFont.prototype.widthOfGlyph = function (glyph) {
22783        var scale;
22784        scale = 1000.0 / this.head.unitsPerEm;
22785        return this.hmtx.forGlyph(glyph).advance * scale;
22786      };
22787
22788      TTFFont.prototype.widthOfString = function (string, size, charSpace) {
22789        var charCode, i, scale, width, _i, _ref, charSpace;
22790
22791        string = '' + string;
22792        width = 0;
22793
22794        for (i = _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
22795          charCode = string.charCodeAt(i);
22796          width += this.widthOfGlyph(this.characterToGlyph(charCode)) + charSpace * (1000 / size) || 0;
22797        }
22798
22799        scale = size / 1000;
22800        return width * scale;
22801      };
22802
22803      TTFFont.prototype.lineHeight = function (size, includeGap) {
22804        var gap;
22805
22806        if (includeGap == null) {
22807          includeGap = false;
22808        }
22809
22810        gap = includeGap ? this.lineGap : 0;
22811        return (this.ascender + gap - this.decender) / 1000 * size;
22812      };
22813
22814      return TTFFont;
22815    }();
22816    /************************************************************************************************/
22817
22818    /* function : Data                                                                              */
22819
22820    /* comment : The ttf data decoded and stored in an array is read and written to the Data object.*/
22821
22822    /************************************************************************************************/
22823
22824
22825    var Data = function () {
22826      function Data(data) {
22827        this.data = data != null ? data : [];
22828        this.pos = 0;
22829        this.length = this.data.length;
22830      }
22831
22832      Data.prototype.readByte = function () {
22833        return this.data[this.pos++];
22834      };
22835
22836      Data.prototype.writeByte = function (byte) {
22837        return this.data[this.pos++] = byte;
22838      };
22839
22840      Data.prototype.readUInt32 = function () {
22841        var b1, b2, b3, b4;
22842        b1 = this.readByte() * 0x1000000;
22843        b2 = this.readByte() << 16;
22844        b3 = this.readByte() << 8;
22845        b4 = this.readByte();
22846        return b1 + b2 + b3 + b4;
22847      };
22848
22849      Data.prototype.writeUInt32 = function (val) {
22850        this.writeByte(val >>> 24 & 0xff);
22851        this.writeByte(val >> 16 & 0xff);
22852        this.writeByte(val >> 8 & 0xff);
22853        return this.writeByte(val & 0xff);
22854      };
22855
22856      Data.prototype.readInt32 = function () {
22857        var int;
22858        int = this.readUInt32();
22859
22860        if (int >= 0x80000000) {
22861          return int - 0x100000000;
22862        } else {
22863          return int;
22864        }
22865      };
22866
22867      Data.prototype.writeInt32 = function (val) {
22868        if (val < 0) {
22869          val += 0x100000000;
22870        }
22871
22872        return this.writeUInt32(val);
22873      };
22874
22875      Data.prototype.readUInt16 = function () {
22876        var b1, b2;
22877        b1 = this.readByte() << 8;
22878        b2 = this.readByte();
22879        return b1 | b2;
22880      };
22881
22882      Data.prototype.writeUInt16 = function (val) {
22883        this.writeByte(val >> 8 & 0xff);
22884        return this.writeByte(val & 0xff);
22885      };
22886
22887      Data.prototype.readInt16 = function () {
22888        var int;
22889        int = this.readUInt16();
22890
22891        if (int >= 0x8000) {
22892          return int - 0x10000;
22893        } else {
22894          return int;
22895        }
22896      };
22897
22898      Data.prototype.writeInt16 = function (val) {
22899        if (val < 0) {
22900          val += 0x10000;
22901        }
22902
22903        return this.writeUInt16(val);
22904      };
22905
22906      Data.prototype.readString = function (length) {
22907        var i, ret, _i;
22908
22909        ret = [];
22910
22911        for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) {
22912          ret[i] = String.fromCharCode(this.readByte());
22913        }
22914
22915        return ret.join('');
22916      };
22917
22918      Data.prototype.writeString = function (val) {
22919        var i, _i, _ref, _results;
22920
22921        _results = [];
22922
22923        for (i = _i = 0, _ref = val.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
22924          _results.push(this.writeByte(val.charCodeAt(i)));
22925        }
22926
22927        return _results;
22928      };
22929      /*Data.prototype.stringAt = function (pos, length) {
22930          this.pos = pos;
22931          return this.readString(length);
22932      };*/
22933
22934
22935      Data.prototype.readShort = function () {
22936        return this.readInt16();
22937      };
22938
22939      Data.prototype.writeShort = function (val) {
22940        return this.writeInt16(val);
22941      };
22942
22943      Data.prototype.readLongLong = function () {
22944        var b1, b2, b3, b4, b5, b6, b7, b8;
22945        b1 = this.readByte();
22946        b2 = this.readByte();
22947        b3 = this.readByte();
22948        b4 = this.readByte();
22949        b5 = this.readByte();
22950        b6 = this.readByte();
22951        b7 = this.readByte();
22952        b8 = this.readByte();
22953
22954        if (b1 & 0x80) {
22955          return ((b1 ^ 0xff) * 0x100000000000000 + (b2 ^ 0xff) * 0x1000000000000 + (b3 ^ 0xff) * 0x10000000000 + (b4 ^ 0xff) * 0x100000000 + (b5 ^ 0xff) * 0x1000000 + (b6 ^ 0xff) * 0x10000 + (b7 ^ 0xff) * 0x100 + (b8 ^ 0xff) + 1) * -1;
22956        }
22957
22958        return b1 * 0x100000000000000 + b2 * 0x1000000000000 + b3 * 0x10000000000 + b4 * 0x100000000 + b5 * 0x1000000 + b6 * 0x10000 + b7 * 0x100 + b8;
22959      };
22960
22961      Data.prototype.writeLongLong = function (val) {
22962        var high, low;
22963        high = Math.floor(val / 0x100000000);
22964        low = val & 0xffffffff;
22965        this.writeByte(high >> 24 & 0xff);
22966        this.writeByte(high >> 16 & 0xff);
22967        this.writeByte(high >> 8 & 0xff);
22968        this.writeByte(high & 0xff);
22969        this.writeByte(low >> 24 & 0xff);
22970        this.writeByte(low >> 16 & 0xff);
22971        this.writeByte(low >> 8 & 0xff);
22972        return this.writeByte(low & 0xff);
22973      };
22974
22975      Data.prototype.readInt = function () {
22976        return this.readInt32();
22977      };
22978
22979      Data.prototype.writeInt = function (val) {
22980        return this.writeInt32(val);
22981      };
22982      /*Data.prototype.slice = function (start, end) {
22983          return this.data.slice(start, end);
22984      };*/
22985
22986
22987      Data.prototype.read = function (bytes) {
22988        var buf, i, _i;
22989
22990        buf = [];
22991
22992        for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) {
22993          buf.push(this.readByte());
22994        }
22995
22996        return buf;
22997      };
22998
22999      Data.prototype.write = function (bytes) {
23000        var byte, _i, _len, _results;
23001
23002        _results = [];
23003
23004        for (_i = 0, _len = bytes.length; _i < _len; _i++) {
23005          byte = bytes[_i];
23006
23007          _results.push(this.writeByte(byte));
23008        }
23009
23010        return _results;
23011      };
23012
23013      return Data;
23014    }();
23015
23016    var Directory = function () {
23017      var checksum;
23018      /*****************************************************************************************************/
23019
23020      /* function : Directory generator                                                                    */
23021
23022      /* comment : Initialize the offset, tag, length, and checksum for each table for the font to be used.*/
23023
23024      /*****************************************************************************************************/
23025
23026      function Directory(data) {
23027        var entry, i, _i, _ref;
23028
23029        this.scalarType = data.readInt();
23030        this.tableCount = data.readShort();
23031        this.searchRange = data.readShort();
23032        this.entrySelector = data.readShort();
23033        this.rangeShift = data.readShort();
23034        this.tables = {};
23035
23036        for (i = _i = 0, _ref = this.tableCount; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
23037          entry = {
23038            tag: data.readString(4),
23039            checksum: data.readInt(),
23040            offset: data.readInt(),
23041            length: data.readInt()
23042          };
23043          this.tables[entry.tag] = entry;
23044        }
23045      }
23046      /********************************************************************************************************/
23047
23048      /* function : encode                                                                                    */
23049
23050      /* comment : It encodes and stores the font table object and information used for the directory object. */
23051
23052      /********************************************************************************************************/
23053
23054
23055      Directory.prototype.encode = function (tables) {
23056        var adjustment, directory, directoryLength, entrySelector, headOffset, log2, offset, rangeShift, searchRange, sum, table, tableCount, tableData, tag;
23057        tableCount = Object.keys(tables).length;
23058        log2 = Math.log(2);
23059        searchRange = Math.floor(Math.log(tableCount) / log2) * 16;
23060        entrySelector = Math.floor(searchRange / log2);
23061        rangeShift = tableCount * 16 - searchRange;
23062        directory = new Data();
23063        directory.writeInt(this.scalarType);
23064        directory.writeShort(tableCount);
23065        directory.writeShort(searchRange);
23066        directory.writeShort(entrySelector);
23067        directory.writeShort(rangeShift);
23068        directoryLength = tableCount * 16;
23069        offset = directory.pos + directoryLength;
23070        headOffset = null;
23071        tableData = [];
23072
23073        for (tag in tables) {
23074          table = tables[tag];
23075          directory.writeString(tag);
23076          directory.writeInt(checksum(table));
23077          directory.writeInt(offset);
23078          directory.writeInt(table.length);
23079          tableData = tableData.concat(table);
23080
23081          if (tag === 'head') {
23082            headOffset = offset;
23083          }
23084
23085          offset += table.length;
23086
23087          while (offset % 4) {
23088            tableData.push(0);
23089            offset++;
23090          }
23091        }
23092
23093        directory.write(tableData);
23094        sum = checksum(directory.data);
23095        adjustment = 0xB1B0AFBA - sum;
23096        directory.pos = headOffset + 8;
23097        directory.writeUInt32(adjustment);
23098        return directory.data;
23099      };
23100      /***************************************************************/
23101
23102      /* function : checksum                                         */
23103
23104      /* comment : Duplicate the table for the tag.                  */
23105
23106      /***************************************************************/
23107
23108
23109      checksum = function checksum(data) {
23110        var i, sum, tmp, _i, _ref;
23111
23112        data = __slice.call(data);
23113
23114        while (data.length % 4) {
23115          data.push(0);
23116        }
23117
23118        tmp = new Data(data);
23119        sum = 0;
23120
23121        for (i = _i = 0, _ref = data.length; _i < _ref; i = _i += 4) {
23122          sum += tmp.readUInt32();
23123        }
23124
23125        return sum & 0xFFFFFFFF;
23126      };
23127
23128      return Directory;
23129    }();
23130
23131    var Table,
23132        __hasProp = {}.hasOwnProperty,
23133        __extends = function __extends(child, parent) {
23134      for (var key in parent) {
23135        if (__hasProp.call(parent, key)) child[key] = parent[key];
23136      }
23137
23138      function ctor() {
23139        this.constructor = child;
23140      }
23141
23142      ctor.prototype = parent.prototype;
23143      child.prototype = new ctor();
23144      child.__super__ = parent.prototype;
23145      return child;
23146    };
23147    /***************************************************************/
23148
23149    /* function : Table                                            */
23150
23151    /* comment : Save info for each table, and parse the table.    */
23152
23153    /***************************************************************/
23154
23155    Table = function () {
23156      function Table(file) {
23157        var info;
23158        this.file = file;
23159        info = this.file.directory.tables[this.tag];
23160        this.exists = !!info;
23161
23162        if (info) {
23163          this.offset = info.offset, this.length = info.length;
23164          this.parse(this.file.contents);
23165        }
23166      }
23167
23168      Table.prototype.parse = function () {};
23169
23170      Table.prototype.encode = function () {};
23171
23172      Table.prototype.raw = function () {
23173        if (!this.exists) {
23174          return null;
23175        }
23176
23177        this.file.contents.pos = this.offset;
23178        return this.file.contents.read(this.length);
23179      };
23180
23181      return Table;
23182    }();
23183
23184    var HeadTable = function (_super) {
23185      __extends(HeadTable, _super);
23186
23187      function HeadTable() {
23188        return HeadTable.__super__.constructor.apply(this, arguments);
23189      }
23190
23191      HeadTable.prototype.tag = 'head';
23192
23193      HeadTable.prototype.parse = function (data) {
23194        data.pos = this.offset;
23195        this.version = data.readInt();
23196        this.revision = data.readInt();
23197        this.checkSumAdjustment = data.readInt();
23198        this.magicNumber = data.readInt();
23199        this.flags = data.readShort();
23200        this.unitsPerEm = data.readShort();
23201        this.created = data.readLongLong();
23202        this.modified = data.readLongLong();
23203        this.xMin = data.readShort();
23204        this.yMin = data.readShort();
23205        this.xMax = data.readShort();
23206        this.yMax = data.readShort();
23207        this.macStyle = data.readShort();
23208        this.lowestRecPPEM = data.readShort();
23209        this.fontDirectionHint = data.readShort();
23210        this.indexToLocFormat = data.readShort();
23211        return this.glyphDataFormat = data.readShort();
23212      };
23213
23214      HeadTable.prototype.encode = function (indexToLocFormat) {
23215        var table;
23216        table = new Data();
23217        table.writeInt(this.version);
23218        table.writeInt(this.revision);
23219        table.writeInt(this.checkSumAdjustment);
23220        table.writeInt(this.magicNumber);
23221        table.writeShort(this.flags);
23222        table.writeShort(this.unitsPerEm);
23223        table.writeLongLong(this.created);
23224        table.writeLongLong(this.modified);
23225        table.writeShort(this.xMin);
23226        table.writeShort(this.yMin);
23227        table.writeShort(this.xMax);
23228        table.writeShort(this.yMax);
23229        table.writeShort(this.macStyle);
23230        table.writeShort(this.lowestRecPPEM);
23231        table.writeShort(this.fontDirectionHint);
23232        table.writeShort(indexToLocFormat);
23233        table.writeShort(this.glyphDataFormat);
23234        return table.data;
23235      };
23236
23237      return HeadTable;
23238    }(Table);
23239    /************************************************************************************/
23240
23241    /* function : CmapEntry                                                             */
23242
23243    /* comment : Cmap Initializes and encodes object information (required by pdf spec).*/
23244
23245    /************************************************************************************/
23246
23247
23248    var CmapEntry = function () {
23249      function CmapEntry(data, offset) {
23250        var code, count, endCode, glyphId, glyphIds, i, idDelta, idRangeOffset, index, saveOffset, segCount, segCountX2, start, startCode, tail, _i, _j, _k, _len;
23251
23252        this.platformID = data.readUInt16();
23253        this.encodingID = data.readShort();
23254        this.offset = offset + data.readInt();
23255        saveOffset = data.pos;
23256        data.pos = this.offset;
23257        this.format = data.readUInt16();
23258        this.length = data.readUInt16();
23259        this.language = data.readUInt16();
23260        this.isUnicode = this.platformID === 3 && this.encodingID === 1 && this.format === 4 || this.platformID === 0 && this.format === 4;
23261        this.codeMap = {};
23262
23263        switch (this.format) {
23264          case 0:
23265            for (i = _i = 0; _i < 256; i = ++_i) {
23266              this.codeMap[i] = data.readByte();
23267            }
23268
23269            break;
23270
23271          case 4:
23272            segCountX2 = data.readUInt16();
23273            segCount = segCountX2 / 2;
23274            data.pos += 6;
23275
23276            endCode = function () {
23277              var _j, _results;
23278
23279              _results = [];
23280
23281              for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) {
23282                _results.push(data.readUInt16());
23283              }
23284
23285              return _results;
23286            }();
23287
23288            data.pos += 2;
23289
23290            startCode = function () {
23291              var _j, _results;
23292
23293              _results = [];
23294
23295              for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) {
23296                _results.push(data.readUInt16());
23297              }
23298
23299              return _results;
23300            }();
23301
23302            idDelta = function () {
23303              var _j, _results;
23304
23305              _results = [];
23306
23307              for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) {
23308                _results.push(data.readUInt16());
23309              }
23310
23311              return _results;
23312            }();
23313
23314            idRangeOffset = function () {
23315              var _j, _results;
23316
23317              _results = [];
23318
23319              for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) {
23320                _results.push(data.readUInt16());
23321              }
23322
23323              return _results;
23324            }();
23325
23326            count = (this.length - data.pos + this.offset) / 2;
23327
23328            glyphIds = function () {
23329              var _j, _results;
23330
23331              _results = [];
23332
23333              for (i = _j = 0; 0 <= count ? _j < count : _j > count; i = 0 <= count ? ++_j : --_j) {
23334                _results.push(data.readUInt16());
23335              }
23336
23337              return _results;
23338            }();
23339
23340            for (i = _j = 0, _len = endCode.length; _j < _len; i = ++_j) {
23341              tail = endCode[i];
23342              start = startCode[i];
23343
23344              for (code = _k = start; start <= tail ? _k <= tail : _k >= tail; code = start <= tail ? ++_k : --_k) {
23345                if (idRangeOffset[i] === 0) {
23346                  glyphId = code + idDelta[i];
23347                } else {
23348                  index = idRangeOffset[i] / 2 + (code - start) - (segCount - i);
23349                  glyphId = glyphIds[index] || 0;
23350
23351                  if (glyphId !== 0) {
23352                    glyphId += idDelta[i];
23353                  }
23354                }
23355
23356                this.codeMap[code] = glyphId & 0xFFFF;
23357              }
23358            }
23359
23360        }
23361
23362        data.pos = saveOffset;
23363      }
23364
23365      CmapEntry.encode = function (charmap, encoding) {
23366        var charMap, code, codeMap, codes, delta, deltas, diff, endCode, endCodes, entrySelector, glyphIDs, i, id, indexes, last, map, nextID, offset, old, rangeOffsets, rangeShift, result, searchRange, segCount, segCountX2, startCode, startCodes, startGlyph, subtable, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _len6, _len7, _m, _n, _name, _o, _p, _q;
23367
23368        subtable = new Data();
23369        codes = Object.keys(charmap).sort(function (a, b) {
23370          return a - b;
23371        });
23372
23373        switch (encoding) {
23374          case 'macroman':
23375            id = 0;
23376
23377            indexes = function () {
23378              var _i, _results;
23379
23380              _results = [];
23381
23382              for (i = _i = 0; _i < 256; i = ++_i) {
23383                _results.push(0);
23384              }
23385
23386              return _results;
23387            }();
23388
23389            map = {
23390              0: 0
23391            };
23392            codeMap = {};
23393
23394            for (_i = 0, _len = codes.length; _i < _len; _i++) {
23395              code = codes[_i];
23396
23397              if (map[_name = charmap[code]] == null) {
23398                map[_name] = ++id;
23399              }
23400
23401              codeMap[code] = {
23402                old: charmap[code],
23403                "new": map[charmap[code]]
23404              };
23405              indexes[code] = map[charmap[code]];
23406            }
23407
23408            subtable.writeUInt16(1);
23409            subtable.writeUInt16(0);
23410            subtable.writeUInt32(12);
23411            subtable.writeUInt16(0);
23412            subtable.writeUInt16(262);
23413            subtable.writeUInt16(0);
23414            subtable.write(indexes);
23415            return result = {
23416              charMap: codeMap,
23417              subtable: subtable.data,
23418              maxGlyphID: id + 1
23419            };
23420
23421          case 'unicode':
23422            startCodes = [];
23423            endCodes = [];
23424            nextID = 0;
23425            map = {};
23426            charMap = {};
23427            last = diff = null;
23428
23429            for (_j = 0, _len1 = codes.length; _j < _len1; _j++) {
23430              code = codes[_j];
23431              old = charmap[code];
23432
23433              if (map[old] == null) {
23434                map[old] = ++nextID;
23435              }
23436
23437              charMap[code] = {
23438                old: old,
23439                "new": map[old]
23440              };
23441              delta = map[old] - code;
23442
23443              if (last == null || delta !== diff) {
23444                if (last) {
23445                  endCodes.push(last);
23446                }
23447
23448                startCodes.push(code);
23449                diff = delta;
23450              }
23451
23452              last = code;
23453            }
23454
23455            if (last) {
23456              endCodes.push(last);
23457            }
23458
23459            endCodes.push(0xFFFF);
23460            startCodes.push(0xFFFF);
23461            segCount = startCodes.length;
23462            segCountX2 = segCount * 2;
23463            searchRange = 2 * Math.pow(Math.log(segCount) / Math.LN2, 2);
23464            entrySelector = Math.log(searchRange / 2) / Math.LN2;
23465            rangeShift = 2 * segCount - searchRange;
23466            deltas = [];
23467            rangeOffsets = [];
23468            glyphIDs = [];
23469
23470            for (i = _k = 0, _len2 = startCodes.length; _k < _len2; i = ++_k) {
23471              startCode = startCodes[i];
23472              endCode = endCodes[i];
23473
23474              if (startCode === 0xFFFF) {
23475                deltas.push(0);
23476                rangeOffsets.push(0);
23477                break;
23478              }
23479
23480              startGlyph = charMap[startCode]["new"];
23481
23482              if (startCode - startGlyph >= 0x8000) {
23483                deltas.push(0);
23484                rangeOffsets.push(2 * (glyphIDs.length + segCount - i));
23485
23486                for (code = _l = startCode; startCode <= endCode ? _l <= endCode : _l >= endCode; code = startCode <= endCode ? ++_l : --_l) {
23487                  glyphIDs.push(charMap[code]["new"]);
23488                }
23489              } else {
23490                deltas.push(startGlyph - startCode);
23491                rangeOffsets.push(0);
23492              }
23493            }
23494
23495            subtable.writeUInt16(3);
23496            subtable.writeUInt16(1);
23497            subtable.writeUInt32(12);
23498            subtable.writeUInt16(4);
23499            subtable.writeUInt16(16 + segCount * 8 + glyphIDs.length * 2);
23500            subtable.writeUInt16(0);
23501            subtable.writeUInt16(segCountX2);
23502            subtable.writeUInt16(searchRange);
23503            subtable.writeUInt16(entrySelector);
23504            subtable.writeUInt16(rangeShift);
23505
23506            for (_m = 0, _len3 = endCodes.length; _m < _len3; _m++) {
23507              code = endCodes[_m];
23508              subtable.writeUInt16(code);
23509            }
23510
23511            subtable.writeUInt16(0);
23512
23513            for (_n = 0, _len4 = startCodes.length; _n < _len4; _n++) {
23514              code = startCodes[_n];
23515              subtable.writeUInt16(code);
23516            }
23517
23518            for (_o = 0, _len5 = deltas.length; _o < _len5; _o++) {
23519              delta = deltas[_o];
23520              subtable.writeUInt16(delta);
23521            }
23522
23523            for (_p = 0, _len6 = rangeOffsets.length; _p < _len6; _p++) {
23524              offset = rangeOffsets[_p];
23525              subtable.writeUInt16(offset);
23526            }
23527
23528            for (_q = 0, _len7 = glyphIDs.length; _q < _len7; _q++) {
23529              id = glyphIDs[_q];
23530              subtable.writeUInt16(id);
23531            }
23532
23533            return result = {
23534              charMap: charMap,
23535              subtable: subtable.data,
23536              maxGlyphID: nextID + 1
23537            };
23538        }
23539      };
23540
23541      return CmapEntry;
23542    }();
23543
23544    var CmapTable = function (_super) {
23545      __extends(CmapTable, _super);
23546
23547      function CmapTable() {
23548        return CmapTable.__super__.constructor.apply(this, arguments);
23549      }
23550
23551      CmapTable.prototype.tag = 'cmap';
23552
23553      CmapTable.prototype.parse = function (data) {
23554        var entry, i, tableCount, _i;
23555
23556        data.pos = this.offset;
23557        this.version = data.readUInt16();
23558        tableCount = data.readUInt16();
23559        this.tables = [];
23560        this.unicode = null;
23561
23562        for (i = _i = 0; 0 <= tableCount ? _i < tableCount : _i > tableCount; i = 0 <= tableCount ? ++_i : --_i) {
23563          entry = new CmapEntry(data, this.offset);
23564          this.tables.push(entry);
23565
23566          if (entry.isUnicode) {
23567            if (this.unicode == null) {
23568              this.unicode = entry;
23569            }
23570          }
23571        }
23572
23573        return true;
23574      };
23575      /*************************************************************************/
23576
23577      /* function : encode                                                     */
23578
23579      /* comment : Encode the cmap table corresponding to the input character. */
23580
23581      /*************************************************************************/
23582
23583
23584      CmapTable.encode = function (charmap, encoding) {
23585        var result, table;
23586
23587        if (encoding == null) {
23588          encoding = 'macroman';
23589        }
23590
23591        result = CmapEntry.encode(charmap, encoding);
23592        table = new Data();
23593        table.writeUInt16(0);
23594        table.writeUInt16(1);
23595        result.table = table.data.concat(result.subtable);
23596        return result;
23597      };
23598
23599      return CmapTable;
23600    }(Table);
23601
23602    var HheaTable = function (_super) {
23603      __extends(HheaTable, _super);
23604
23605      function HheaTable() {
23606        return HheaTable.__super__.constructor.apply(this, arguments);
23607      }
23608
23609      HheaTable.prototype.tag = 'hhea';
23610
23611      HheaTable.prototype.parse = function (data) {
23612        data.pos = this.offset;
23613        this.version = data.readInt();
23614        this.ascender = data.readShort();
23615        this.decender = data.readShort();
23616        this.lineGap = data.readShort();
23617        this.advanceWidthMax = data.readShort();
23618        this.minLeftSideBearing = data.readShort();
23619        this.minRightSideBearing = data.readShort();
23620        this.xMaxExtent = data.readShort();
23621        this.caretSlopeRise = data.readShort();
23622        this.caretSlopeRun = data.readShort();
23623        this.caretOffset = data.readShort();
23624        data.pos += 4 * 2;
23625        this.metricDataFormat = data.readShort();
23626        return this.numberOfMetrics = data.readUInt16();
23627      };
23628      /*HheaTable.prototype.encode = function (ids) {
23629          var i, table, _i, _ref;
23630          table = new Data;
23631          table.writeInt(this.version);
23632          table.writeShort(this.ascender);
23633          table.writeShort(this.decender);
23634          table.writeShort(this.lineGap);
23635          table.writeShort(this.advanceWidthMax);
23636          table.writeShort(this.minLeftSideBearing);
23637          table.writeShort(this.minRightSideBearing);
23638          table.writeShort(this.xMaxExtent);
23639          table.writeShort(this.caretSlopeRise);
23640          table.writeShort(this.caretSlopeRun);
23641          table.writeShort(this.caretOffset);
23642          for (i = _i = 0, _ref = 4 * 2; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
23643              table.writeByte(0);
23644          }
23645          table.writeShort(this.metricDataFormat);
23646          table.writeUInt16(ids.length);
23647          return table.data;
23648      };*/
23649
23650
23651      return HheaTable;
23652    }(Table);
23653
23654    var OS2Table = function (_super) {
23655      __extends(OS2Table, _super);
23656
23657      function OS2Table() {
23658        return OS2Table.__super__.constructor.apply(this, arguments);
23659      }
23660
23661      OS2Table.prototype.tag = 'OS/2';
23662
23663      OS2Table.prototype.parse = function (data) {
23664        var i;
23665        data.pos = this.offset;
23666        this.version = data.readUInt16();
23667        this.averageCharWidth = data.readShort();
23668        this.weightClass = data.readUInt16();
23669        this.widthClass = data.readUInt16();
23670        this.type = data.readShort();
23671        this.ySubscriptXSize = data.readShort();
23672        this.ySubscriptYSize = data.readShort();
23673        this.ySubscriptXOffset = data.readShort();
23674        this.ySubscriptYOffset = data.readShort();
23675        this.ySuperscriptXSize = data.readShort();
23676        this.ySuperscriptYSize = data.readShort();
23677        this.ySuperscriptXOffset = data.readShort();
23678        this.ySuperscriptYOffset = data.readShort();
23679        this.yStrikeoutSize = data.readShort();
23680        this.yStrikeoutPosition = data.readShort();
23681        this.familyClass = data.readShort();
23682
23683        this.panose = function () {
23684          var _i, _results;
23685
23686          _results = [];
23687
23688          for (i = _i = 0; _i < 10; i = ++_i) {
23689            _results.push(data.readByte());
23690          }
23691
23692          return _results;
23693        }();
23694
23695        this.charRange = function () {
23696          var _i, _results;
23697
23698          _results = [];
23699
23700          for (i = _i = 0; _i < 4; i = ++_i) {
23701            _results.push(data.readInt());
23702          }
23703
23704          return _results;
23705        }();
23706
23707        this.vendorID = data.readString(4);
23708        this.selection = data.readShort();
23709        this.firstCharIndex = data.readShort();
23710        this.lastCharIndex = data.readShort();
23711
23712        if (this.version > 0) {
23713          this.ascent = data.readShort();
23714          this.descent = data.readShort();
23715          this.lineGap = data.readShort();
23716          this.winAscent = data.readShort();
23717          this.winDescent = data.readShort();
23718
23719          this.codePageRange = function () {
23720            var _i, _results;
23721
23722            _results = [];
23723
23724            for (i = _i = 0; _i < 2; i = ++_i) {
23725              _results.push(data.readInt());
23726            }
23727
23728            return _results;
23729          }();
23730
23731          if (this.version > 1) {
23732            this.xHeight = data.readShort();
23733            this.capHeight = data.readShort();
23734            this.defaultChar = data.readShort();
23735            this.breakChar = data.readShort();
23736            return this.maxContext = data.readShort();
23737          }
23738        }
23739      };
23740      /*OS2Table.prototype.encode = function () {
23741          return this.raw();
23742      };*/
23743
23744
23745      return OS2Table;
23746    }(Table);
23747
23748    var PostTable = function (_super) {
23749
23750      __extends(PostTable, _super);
23751
23752      function PostTable() {
23753        return PostTable.__super__.constructor.apply(this, arguments);
23754      }
23755
23756      PostTable.prototype.tag = 'post';
23757
23758      PostTable.prototype.parse = function (data) {
23759        var i, length, numberOfGlyphs, _i, _results;
23760
23761        data.pos = this.offset;
23762        this.format = data.readInt();
23763        this.italicAngle = data.readInt();
23764        this.underlinePosition = data.readShort();
23765        this.underlineThickness = data.readShort();
23766        this.isFixedPitch = data.readInt();
23767        this.minMemType42 = data.readInt();
23768        this.maxMemType42 = data.readInt();
23769        this.minMemType1 = data.readInt();
23770        this.maxMemType1 = data.readInt();
23771
23772        switch (this.format) {
23773          case 0x00010000:
23774            break;
23775
23776          case 0x00020000:
23777            numberOfGlyphs = data.readUInt16();
23778            this.glyphNameIndex = [];
23779
23780            for (i = _i = 0; 0 <= numberOfGlyphs ? _i < numberOfGlyphs : _i > numberOfGlyphs; i = 0 <= numberOfGlyphs ? ++_i : --_i) {
23781              this.glyphNameIndex.push(data.readUInt16());
23782            }
23783
23784            this.names = [];
23785            _results = [];
23786
23787            while (data.pos < this.offset + this.length) {
23788              length = data.readByte();
23789
23790              _results.push(this.names.push(data.readString(length)));
23791            }
23792
23793            return _results;
23794            break;
23795
23796          case 0x00025000:
23797            numberOfGlyphs = data.readUInt16();
23798            return this.offsets = data.read(numberOfGlyphs);
23799
23800          case 0x00030000:
23801            break;
23802
23803          case 0x00040000:
23804            return this.map = function () {
23805              var _j, _ref, _results1;
23806
23807              _results1 = [];
23808
23809              for (i = _j = 0, _ref = this.file.maxp.numGlyphs; 0 <= _ref ? _j < _ref : _j > _ref; i = 0 <= _ref ? ++_j : --_j) {
23810                _results1.push(data.readUInt32());
23811              }
23812
23813              return _results1;
23814            }.call(this);
23815        }
23816      };
23817      return PostTable;
23818    }(Table);
23819    /*********************************************************************************************************/
23820
23821    /* function : NameEntry                                                                                  */
23822
23823    /* comment : Store copyright information, platformID, encodingID, and languageID in the NameEntry object.*/
23824
23825    /*********************************************************************************************************/
23826
23827
23828    var NameEntry = function () {
23829      function NameEntry(raw, entry) {
23830        this.raw = raw;
23831        this.length = raw.length;
23832        this.platformID = entry.platformID;
23833        this.encodingID = entry.encodingID;
23834        this.languageID = entry.languageID;
23835      }
23836
23837      return NameEntry;
23838    }();
23839
23840    var NameTable = function (_super) {
23841
23842      __extends(NameTable, _super);
23843
23844      function NameTable() {
23845        return NameTable.__super__.constructor.apply(this, arguments);
23846      }
23847
23848      NameTable.prototype.tag = 'name';
23849
23850      NameTable.prototype.parse = function (data) {
23851        var count, entries, entry, format, i, name, stringOffset, strings, text, _i, _j, _len, _name;
23852
23853        data.pos = this.offset;
23854        format = data.readShort();
23855        count = data.readShort();
23856        stringOffset = data.readShort();
23857        entries = [];
23858
23859        for (i = _i = 0; 0 <= count ? _i < count : _i > count; i = 0 <= count ? ++_i : --_i) {
23860          entries.push({
23861            platformID: data.readShort(),
23862            encodingID: data.readShort(),
23863            languageID: data.readShort(),
23864            nameID: data.readShort(),
23865            length: data.readShort(),
23866            offset: this.offset + stringOffset + data.readShort()
23867          });
23868        }
23869
23870        strings = {};
23871
23872        for (i = _j = 0, _len = entries.length; _j < _len; i = ++_j) {
23873          entry = entries[i];
23874          data.pos = entry.offset;
23875          text = data.readString(entry.length);
23876          name = new NameEntry(text, entry);
23877
23878          if (strings[_name = entry.nameID] == null) {
23879            strings[_name] = [];
23880          }
23881
23882          strings[entry.nameID].push(name);
23883        }
23884
23885        this.strings = strings;
23886        this.copyright = strings[0];
23887        this.fontFamily = strings[1];
23888        this.fontSubfamily = strings[2];
23889        this.uniqueSubfamily = strings[3];
23890        this.fontName = strings[4];
23891        this.version = strings[5];
23892
23893        try {
23894          this.postscriptName = strings[6][0].raw.replace(/[\x00-\x19\x80-\xff]/g, "");
23895        } catch (e) {
23896          this.postscriptName = strings[4][0].raw.replace(/[\x00-\x19\x80-\xff]/g, "");
23897        }
23898
23899        this.trademark = strings[7];
23900        this.manufacturer = strings[8];
23901        this.designer = strings[9];
23902        this.description = strings[10];
23903        this.vendorUrl = strings[11];
23904        this.designerUrl = strings[12];
23905        this.license = strings[13];
23906        this.licenseUrl = strings[14];
23907        this.preferredFamily = strings[15];
23908        this.preferredSubfamily = strings[17];
23909        this.compatibleFull = strings[18];
23910        return this.sampleText = strings[19];
23911      };
23912      /*NameTable.prototype.encode = function () {
23913          var id, list, nameID, nameTable, postscriptName, strCount, strTable, string, strings, table, val, _i, _len, _ref;
23914          strings = {};
23915          _ref = this.strings;
23916          for (id in _ref) {
23917              val = _ref[id];
23918              strings[id] = val;
23919          }
23920          postscriptName = new NameEntry("" + subsetTag + "+" + this.postscriptName, {
23921              platformID: 1
23922              , encodingID: 0
23923              , languageID: 0
23924          });
23925          strings[6] = [postscriptName];
23926          subsetTag = successorOf(subsetTag);
23927          strCount = 0;
23928          for (id in strings) {
23929              list = strings[id];
23930              if (list != null) {
23931                  strCount += list.length;
23932              }
23933          }
23934          table = new Data;
23935          strTable = new Data;
23936          table.writeShort(0);
23937          table.writeShort(strCount);
23938          table.writeShort(6 + 12 * strCount);
23939          for (nameID in strings) {
23940              list = strings[nameID];
23941              if (list != null) {
23942                  for (_i = 0, _len = list.length; _i < _len; _i++) {
23943                      string = list[_i];
23944                      table.writeShort(string.platformID);
23945                      table.writeShort(string.encodingID);
23946                      table.writeShort(string.languageID);
23947                      table.writeShort(nameID);
23948                      table.writeShort(string.length);
23949                      table.writeShort(strTable.pos);
23950                      strTable.writeString(string.raw);
23951                  }
23952              }
23953          }
23954          return nameTable = {
23955              postscriptName: postscriptName.raw
23956              , table: table.data.concat(strTable.data)
23957          };
23958      };*/
23959
23960      return NameTable;
23961    }(Table);
23962
23963    var MaxpTable = function (_super) {
23964      __extends(MaxpTable, _super);
23965
23966      function MaxpTable() {
23967        return MaxpTable.__super__.constructor.apply(this, arguments);
23968      }
23969
23970      MaxpTable.prototype.tag = 'maxp';
23971
23972      MaxpTable.prototype.parse = function (data) {
23973        data.pos = this.offset;
23974        this.version = data.readInt();
23975        this.numGlyphs = data.readUInt16();
23976        this.maxPoints = data.readUInt16();
23977        this.maxContours = data.readUInt16();
23978        this.maxCompositePoints = data.readUInt16();
23979        this.maxComponentContours = data.readUInt16();
23980        this.maxZones = data.readUInt16();
23981        this.maxTwilightPoints = data.readUInt16();
23982        this.maxStorage = data.readUInt16();
23983        this.maxFunctionDefs = data.readUInt16();
23984        this.maxInstructionDefs = data.readUInt16();
23985        this.maxStackElements = data.readUInt16();
23986        this.maxSizeOfInstructions = data.readUInt16();
23987        this.maxComponentElements = data.readUInt16();
23988        return this.maxComponentDepth = data.readUInt16();
23989      };
23990      /*MaxpTable.prototype.encode = function (ids) {
23991          var table;
23992          table = new Data;
23993          table.writeInt(this.version);
23994          table.writeUInt16(ids.length);
23995          table.writeUInt16(this.maxPoints);
23996          table.writeUInt16(this.maxContours);
23997          table.writeUInt16(this.maxCompositePoints);
23998          table.writeUInt16(this.maxComponentContours);
23999          table.writeUInt16(this.maxZones);
24000          table.writeUInt16(this.maxTwilightPoints);
24001          table.writeUInt16(this.maxStorage);
24002          table.writeUInt16(this.maxFunctionDefs);
24003          table.writeUInt16(this.maxInstructionDefs);
24004          table.writeUInt16(this.maxStackElements);
24005          table.writeUInt16(this.maxSizeOfInstructions);
24006          table.writeUInt16(this.maxComponentElements);
24007          table.writeUInt16(this.maxComponentDepth);
24008          return table.data;
24009      };*/
24010
24011
24012      return MaxpTable;
24013    }(Table);
24014
24015    var HmtxTable = function (_super) {
24016      __extends(HmtxTable, _super);
24017
24018      function HmtxTable() {
24019        return HmtxTable.__super__.constructor.apply(this, arguments);
24020      }
24021
24022      HmtxTable.prototype.tag = 'hmtx';
24023
24024      HmtxTable.prototype.parse = function (data) {
24025        var i, last, lsbCount, m, _i, _j, _ref, _results;
24026
24027        data.pos = this.offset;
24028        this.metrics = [];
24029
24030        for (i = _i = 0, _ref = this.file.hhea.numberOfMetrics; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
24031          this.metrics.push({
24032            advance: data.readUInt16(),
24033            lsb: data.readInt16()
24034          });
24035        }
24036
24037        lsbCount = this.file.maxp.numGlyphs - this.file.hhea.numberOfMetrics;
24038
24039        this.leftSideBearings = function () {
24040          var _j, _results;
24041
24042          _results = [];
24043
24044          for (i = _j = 0; 0 <= lsbCount ? _j < lsbCount : _j > lsbCount; i = 0 <= lsbCount ? ++_j : --_j) {
24045            _results.push(data.readInt16());
24046          }
24047
24048          return _results;
24049        }();
24050
24051        this.widths = function () {
24052          var _j, _len, _ref1, _results;
24053
24054          _ref1 = this.metrics;
24055          _results = [];
24056
24057          for (_j = 0, _len = _ref1.length; _j < _len; _j++) {
24058            m = _ref1[_j];
24059
24060            _results.push(m.advance);
24061          }
24062
24063          return _results;
24064        }.call(this);
24065
24066        last = this.widths[this.widths.length - 1];
24067        _results = [];
24068
24069        for (i = _j = 0; 0 <= lsbCount ? _j < lsbCount : _j > lsbCount; i = 0 <= lsbCount ? ++_j : --_j) {
24070          _results.push(this.widths.push(last));
24071        }
24072
24073        return _results;
24074      };
24075      /***************************************************************/
24076
24077      /* function : forGlyph                                         */
24078
24079      /* comment : Returns the advance width and lsb for this glyph. */
24080
24081      /***************************************************************/
24082
24083
24084      HmtxTable.prototype.forGlyph = function (id) {
24085        var metrics;
24086
24087        if (id in this.metrics) {
24088          return this.metrics[id];
24089        }
24090
24091        return metrics = {
24092          advance: this.metrics[this.metrics.length - 1].advance,
24093          lsb: this.leftSideBearings[id - this.metrics.length]
24094        };
24095      };
24096      /*HmtxTable.prototype.encode = function (mapping) {
24097          var id, metric, table, _i, _len;
24098          table = new Data;
24099          for (_i = 0, _len = mapping.length; _i < _len; _i++) {
24100              id = mapping[_i];
24101              metric = this.forGlyph(id);
24102              table.writeUInt16(metric.advance);
24103              table.writeUInt16(metric.lsb);
24104          }
24105          return table.data;
24106      };*/
24107
24108
24109      return HmtxTable;
24110    }(Table);
24111
24112    var __slice = [].slice;
24113
24114    var GlyfTable = function (_super) {
24115      __extends(GlyfTable, _super);
24116
24117      function GlyfTable() {
24118        return GlyfTable.__super__.constructor.apply(this, arguments);
24119      }
24120
24121      GlyfTable.prototype.tag = 'glyf';
24122
24123      GlyfTable.prototype.parse = function (data) {
24124        return this.cache = {};
24125      };
24126
24127      GlyfTable.prototype.glyphFor = function (id) {
24128        id = id;
24129        var data, index, length, loca, numberOfContours, raw, xMax, xMin, yMax, yMin;
24130
24131        if (id in this.cache) {
24132          return this.cache[id];
24133        }
24134
24135        loca = this.file.loca;
24136        data = this.file.contents;
24137        index = loca.indexOf(id);
24138        length = loca.lengthOf(id);
24139
24140        if (length === 0) {
24141          return this.cache[id] = null;
24142        }
24143
24144        data.pos = this.offset + index;
24145        raw = new Data(data.read(length));
24146        numberOfContours = raw.readShort();
24147        xMin = raw.readShort();
24148        yMin = raw.readShort();
24149        xMax = raw.readShort();
24150        yMax = raw.readShort();
24151
24152        if (numberOfContours === -1) {
24153          this.cache[id] = new CompoundGlyph(raw, xMin, yMin, xMax, yMax);
24154        } else {
24155          this.cache[id] = new SimpleGlyph(raw, numberOfContours, xMin, yMin, xMax, yMax);
24156        }
24157
24158        return this.cache[id];
24159      };
24160
24161      GlyfTable.prototype.encode = function (glyphs, mapping, old2new) {
24162        var glyph, id, offsets, table, _i, _len;
24163
24164        table = [];
24165        offsets = [];
24166
24167        for (_i = 0, _len = mapping.length; _i < _len; _i++) {
24168          id = mapping[_i];
24169          glyph = glyphs[id];
24170          offsets.push(table.length);
24171
24172          if (glyph) {
24173            table = table.concat(glyph.encode(old2new));
24174          }
24175        }
24176
24177        offsets.push(table.length);
24178        return {
24179          table: table,
24180          offsets: offsets
24181        };
24182      };
24183
24184      return GlyfTable;
24185    }(Table);
24186
24187    var SimpleGlyph = function () {
24188      /**************************************************************************/
24189
24190      /* function : SimpleGlyph                                                 */
24191
24192      /* comment : Stores raw, xMin, yMin, xMax, and yMax values for this glyph.*/
24193
24194      /**************************************************************************/
24195      function SimpleGlyph(raw, numberOfContours, xMin, yMin, xMax, yMax) {
24196        this.raw = raw;
24197        this.numberOfContours = numberOfContours;
24198        this.xMin = xMin;
24199        this.yMin = yMin;
24200        this.xMax = xMax;
24201        this.yMax = yMax;
24202        this.compound = false;
24203      }
24204
24205      SimpleGlyph.prototype.encode = function () {
24206        return this.raw.data;
24207      };
24208
24209      return SimpleGlyph;
24210    }();
24211
24212    var CompoundGlyph = function () {
24213      var ARG_1_AND_2_ARE_WORDS, MORE_COMPONENTS, WE_HAVE_AN_X_AND_Y_SCALE, WE_HAVE_A_SCALE, WE_HAVE_A_TWO_BY_TWO;
24214      ARG_1_AND_2_ARE_WORDS = 0x0001;
24215      WE_HAVE_A_SCALE = 0x0008;
24216      MORE_COMPONENTS = 0x0020;
24217      WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
24218      WE_HAVE_A_TWO_BY_TWO = 0x0080;
24219      /********************************************************************************************************************/
24220
24221      /* function : CompoundGlypg generator                                                                               */
24222
24223      /* comment : It stores raw, xMin, yMin, xMax, yMax, glyph id, and glyph offset for the corresponding compound glyph.*/
24224
24225      /********************************************************************************************************************/
24226
24227      function CompoundGlyph(raw, xMin, yMin, xMax, yMax) {
24228        var data, flags;
24229        this.raw = raw;
24230        this.xMin = xMin;
24231        this.yMin = yMin;
24232        this.xMax = xMax;
24233        this.yMax = yMax;
24234        this.compound = true;
24235        this.glyphIDs = [];
24236        this.glyphOffsets = [];
24237        data = this.raw;
24238
24239        while (true) {
24240          flags = data.readShort();
24241          this.glyphOffsets.push(data.pos);
24242          this.glyphIDs.push(data.readShort());
24243
24244          if (!(flags & MORE_COMPONENTS)) {
24245            break;
24246          }
24247
24248          if (flags & ARG_1_AND_2_ARE_WORDS) {
24249            data.pos += 4;
24250          } else {
24251            data.pos += 2;
24252          }
24253
24254          if (flags & WE_HAVE_A_TWO_BY_TWO) {
24255            data.pos += 8;
24256          } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
24257            data.pos += 4;
24258          } else if (flags & WE_HAVE_A_SCALE) {
24259            data.pos += 2;
24260          }
24261        }
24262      }
24263      /****************************************************************************************************************/
24264
24265      /* function : CompoundGlypg encode                                                                              */
24266
24267      /* comment : After creating a table for the characters you typed, you call directory.encode to encode the table.*/
24268
24269      /****************************************************************************************************************/
24270
24271
24272      CompoundGlyph.prototype.encode = function (mapping) {
24273        var i, id, result, _i, _len, _ref;
24274
24275        result = new Data(__slice.call(this.raw.data));
24276        _ref = this.glyphIDs;
24277
24278        for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
24279          id = _ref[i];
24280          result.pos = this.glyphOffsets[i];
24281        }
24282
24283        return result.data;
24284      };
24285
24286      return CompoundGlyph;
24287    }();
24288
24289    var LocaTable = function (_super) {
24290      __extends(LocaTable, _super);
24291
24292      function LocaTable() {
24293        return LocaTable.__super__.constructor.apply(this, arguments);
24294      }
24295
24296      LocaTable.prototype.tag = 'loca';
24297
24298      LocaTable.prototype.parse = function (data) {
24299        var format, i;
24300        data.pos = this.offset;
24301        format = this.file.head.indexToLocFormat;
24302
24303        if (format === 0) {
24304          return this.offsets = function () {
24305            var _i, _ref, _results;
24306
24307            _results = [];
24308
24309            for (i = _i = 0, _ref = this.length; _i < _ref; i = _i += 2) {
24310              _results.push(data.readUInt16() * 2);
24311            }
24312
24313            return _results;
24314          }.call(this);
24315        } else {
24316          return this.offsets = function () {
24317            var _i, _ref, _results;
24318
24319            _results = [];
24320
24321            for (i = _i = 0, _ref = this.length; _i < _ref; i = _i += 4) {
24322              _results.push(data.readUInt32());
24323            }
24324
24325            return _results;
24326          }.call(this);
24327        }
24328      };
24329
24330      LocaTable.prototype.indexOf = function (id) {
24331        return this.offsets[id];
24332      };
24333
24334      LocaTable.prototype.lengthOf = function (id) {
24335        return this.offsets[id + 1] - this.offsets[id];
24336      };
24337
24338      LocaTable.prototype.encode = function (offsets, activeGlyphs) {
24339        var LocaTable = new Uint32Array(this.offsets.length);
24340        var glyfPtr = 0;
24341        var listGlyf = 0;
24342
24343        for (var k = 0; k < LocaTable.length; ++k) {
24344          LocaTable[k] = glyfPtr;
24345
24346          if (listGlyf < activeGlyphs.length && activeGlyphs[listGlyf] == k) {
24347            ++listGlyf;
24348            LocaTable[k] = glyfPtr;
24349            var start = this.offsets[k];
24350            var len = this.offsets[k + 1] - start;
24351
24352            if (len > 0) {
24353              glyfPtr += len;
24354            }
24355          }
24356        }
24357
24358        var newLocaTable = new Array(LocaTable.length * 4);
24359
24360        for (var j = 0; j < LocaTable.length; ++j) {
24361          newLocaTable[4 * j + 3] = LocaTable[j] & 0x000000ff;
24362          newLocaTable[4 * j + 2] = (LocaTable[j] & 0x0000ff00) >> 8;
24363          newLocaTable[4 * j + 1] = (LocaTable[j] & 0x00ff0000) >> 16;
24364          newLocaTable[4 * j] = (LocaTable[j] & 0xff000000) >> 24;
24365        }
24366
24367        return newLocaTable;
24368      };
24369
24370      return LocaTable;
24371    }(Table);
24372    /************************************************************************************/
24373
24374    /* function : invert                                                                */
24375
24376    /* comment : Change the object's (key: value) to create an object with (value: key).*/
24377
24378    /************************************************************************************/
24379
24380
24381    var invert = function invert(object) {
24382      var key, ret, val;
24383      ret = {};
24384
24385      for (key in object) {
24386        val = object[key];
24387        ret[val] = key;
24388      }
24389
24390      return ret;
24391    };
24392    /*var successorOf = function (input) {
24393        var added, alphabet, carry, i, index, isUpperCase, last, length, next, result;
24394        alphabet = 'abcdefghijklmnopqrstuvwxyz';
24395        length = alphabet.length;
24396        result = input;
24397        i = input.length;
24398        while (i >= 0) {
24399            last = input.charAt(--i);
24400            if (isNaN(last)) {
24401                index = alphabet.indexOf(last.toLowerCase());
24402                if (index === -1) {
24403                    next = last;
24404                    carry = true;
24405                }
24406                else {
24407                    next = alphabet.charAt((index + 1) % length);
24408                    isUpperCase = last === last.toUpperCase();
24409                    if (isUpperCase) {
24410                        next = next.toUpperCase();
24411                    }
24412                    carry = index + 1 >= length;
24413                    if (carry && i === 0) {
24414                        added = isUpperCase ? 'A' : 'a';
24415                        result = added + next + result.slice(1);
24416                        break;
24417                    }
24418                }
24419            }
24420            else {
24421                next = +last + 1;
24422                carry = next > 9;
24423                if (carry) {
24424                    next = 0;
24425                }
24426                if (carry && i === 0) {
24427                    result = '1' + next + result.slice(1);
24428                    break;
24429                }
24430            }
24431            result = result.slice(0, i) + next + result.slice(i + 1);
24432            if (!carry) {
24433                break;
24434            }
24435        }
24436        return result;
24437    };*/
24438
24439
24440    var Subset = function () {
24441      function Subset(font) {
24442        this.font = font;
24443        this.subset = {};
24444        this.unicodes = {};
24445        this.next = 33;
24446      }
24447      /*Subset.prototype.use = function (character) {
24448          var i, _i, _ref;
24449          if (typeof character === 'string') {
24450              for (i = _i = 0, _ref = character.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
24451                  this.use(character.charCodeAt(i));
24452              }
24453              return;
24454          }
24455          if (!this.unicodes[character]) {
24456              this.subset[this.next] = character;
24457              return this.unicodes[character] = this.next++;
24458          }
24459      };*/
24460
24461      /*Subset.prototype.encodeText = function (text) {
24462          var char, i, string, _i, _ref;
24463          string = '';
24464          for (i = _i = 0, _ref = text.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
24465              char = this.unicodes[text.charCodeAt(i)];
24466              string += String.fromCharCode(char);
24467          }
24468          return string;
24469      };*/
24470
24471      /***************************************************************/
24472
24473      /* function : generateCmap                                     */
24474
24475      /* comment : Returns the unicode cmap for this font.         */
24476
24477      /***************************************************************/
24478
24479
24480      Subset.prototype.generateCmap = function () {
24481        var mapping, roman, unicode, unicodeCmap, _ref;
24482
24483        unicodeCmap = this.font.cmap.tables[0].codeMap;
24484        mapping = {};
24485        _ref = this.subset;
24486
24487        for (roman in _ref) {
24488          unicode = _ref[roman];
24489          mapping[roman] = unicodeCmap[unicode];
24490        }
24491
24492        return mapping;
24493      };
24494      /*Subset.prototype.glyphIDs = function () {
24495          var ret, roman, unicode, unicodeCmap, val, _ref;
24496          unicodeCmap = this.font.cmap.tables[0].codeMap;
24497          ret = [0];
24498          _ref = this.subset;
24499          for (roman in _ref) {
24500              unicode = _ref[roman];
24501              val = unicodeCmap[unicode];
24502              if ((val != null) && __indexOf.call(ret, val) < 0) {
24503                  ret.push(val);
24504              }
24505          }
24506          return ret.sort();
24507      };*/
24508
24509      /******************************************************************/
24510
24511      /* function : glyphsFor                                           */
24512
24513      /* comment : Returns simple glyph objects for the input character.*/
24514
24515      /******************************************************************/
24516
24517
24518      Subset.prototype.glyphsFor = function (glyphIDs) {
24519        var additionalIDs, glyph, glyphs, id, _i, _len, _ref;
24520
24521        glyphs = {};
24522
24523        for (_i = 0, _len = glyphIDs.length; _i < _len; _i++) {
24524          id = glyphIDs[_i];
24525          glyphs[id] = this.font.glyf.glyphFor(id);
24526        }
24527
24528        additionalIDs = [];
24529
24530        for (id in glyphs) {
24531          glyph = glyphs[id];
24532
24533          if (glyph != null ? glyph.compound : void 0) {
24534            additionalIDs.push.apply(additionalIDs, glyph.glyphIDs);
24535          }
24536        }
24537
24538        if (additionalIDs.length > 0) {
24539          _ref = this.glyphsFor(additionalIDs);
24540
24541          for (id in _ref) {
24542            glyph = _ref[id];
24543            glyphs[id] = glyph;
24544          }
24545        }
24546
24547        return glyphs;
24548      };
24549      /***************************************************************/
24550
24551      /* function : encode                                           */
24552
24553      /* comment : Encode various tables for the characters you use. */
24554
24555      /***************************************************************/
24556
24557
24558      Subset.prototype.encode = function (glyID, indexToLocFormat) {
24559        var cmap, code, glyf, glyphs, id, ids, loca, new2old, newIDs, nextGlyphID, old2new, oldID, oldIDs, tables, _ref;
24560
24561        cmap = CmapTable.encode(this.generateCmap(), 'unicode');
24562        glyphs = this.glyphsFor(glyID);
24563        old2new = {
24564          0: 0
24565        };
24566        _ref = cmap.charMap;
24567
24568        for (code in _ref) {
24569          ids = _ref[code];
24570          old2new[ids.old] = ids["new"];
24571        }
24572
24573        nextGlyphID = cmap.maxGlyphID;
24574
24575        for (oldID in glyphs) {
24576          if (!(oldID in old2new)) {
24577            old2new[oldID] = nextGlyphID++;
24578          }
24579        }
24580
24581        new2old = invert(old2new);
24582        newIDs = Object.keys(new2old).sort(function (a, b) {
24583          return a - b;
24584        });
24585
24586        oldIDs = function () {
24587          var _i, _len, _results;
24588
24589          _results = [];
24590
24591          for (_i = 0, _len = newIDs.length; _i < _len; _i++) {
24592            id = newIDs[_i];
24593
24594            _results.push(new2old[id]);
24595          }
24596
24597          return _results;
24598        }();
24599
24600        glyf = this.font.glyf.encode(glyphs, oldIDs, old2new);
24601        loca = this.font.loca.encode(glyf.offsets, oldIDs);
24602        tables = {
24603          cmap: this.font.cmap.raw(),
24604          glyf: glyf.table,
24605          loca: loca,
24606          hmtx: this.font.hmtx.raw(),
24607          hhea: this.font.hhea.raw(),
24608          maxp: this.font.maxp.raw(),
24609          post: this.font.post.raw(),
24610          name: this.font.name.raw(),
24611          head: this.font.head.encode(indexToLocFormat)
24612        };
24613
24614        if (this.font.os2.exists) {
24615          tables['OS/2'] = this.font.os2.raw();
24616        }
24617
24618        return this.font.directory.encode(tables);
24619      };
24620
24621      return Subset;
24622    }();
24623
24624    jsPDF.API.PDFObject = function () {
24625      var pad;
24626
24627      function PDFObject() {}
24628
24629      pad = function pad(str, length) {
24630        return (Array(length + 1).join('0') + str).slice(-length);
24631      };
24632      /*****************************************************************************/
24633
24634      /* function : convert                                                        */
24635
24636      /* comment :Converts pdf tag's / FontBBox and array values in / W to strings */
24637
24638      /*****************************************************************************/
24639
24640
24641      PDFObject.convert = function (object) {
24642        var e, items, key, out, val;
24643
24644        if (Array.isArray(object)) {
24645          items = function () {
24646            var _i, _len, _results;
24647
24648            _results = [];
24649
24650            for (_i = 0, _len = object.length; _i < _len; _i++) {
24651              e = object[_i];
24652
24653              _results.push(PDFObject.convert(e));
24654            }
24655
24656            return _results;
24657          }().join(' ');
24658
24659          return '[' + items + ']';
24660        } else if (typeof object === 'string') {
24661          return '/' + object;
24662        } else if (object != null ? object.isString : void 0) {
24663          return '(' + object + ')';
24664        } else if (object instanceof Date) {
24665          return '(D:' + pad(object.getUTCFullYear(), 4) + pad(object.getUTCMonth(), 2) + pad(object.getUTCDate(), 2) + pad(object.getUTCHours(), 2) + pad(object.getUTCMinutes(), 2) + pad(object.getUTCSeconds(), 2) + 'Z)';
24666        } else if ({}.toString.call(object) === '[object Object]') {
24667          out = ['<<'];
24668
24669          for (key in object) {
24670            val = object[key];
24671            out.push('/' + key + ' ' + PDFObject.convert(val));
24672          }
24673
24674          out.push('>>');
24675          return out.join('\n');
24676        } else {
24677          return '' + object;
24678        }
24679      };
24680
24681      return PDFObject;
24682    }();
24683  })(jsPDF);
24684
24685  // Generated by CoffeeScript 1.4.0
24686
24687  /*
24688  # PNG.js
24689  # Copyright (c) 2011 Devon Govett
24690  # MIT LICENSE
24691  # 
24692  # 
24693  */
24694  (function (global) {
24695    var PNG;
24696
24697    PNG = function () {
24698      var APNG_BLEND_OP_SOURCE, APNG_DISPOSE_OP_BACKGROUND, APNG_DISPOSE_OP_PREVIOUS, makeImage, scratchCanvas, scratchCtx;
24699
24700      PNG.load = function (url, canvas, callback) {
24701        var xhr;
24702
24703        if (typeof canvas === 'function') {
24704          callback = canvas;
24705        }
24706
24707        xhr = new XMLHttpRequest();
24708        xhr.open("GET", url, true);
24709        xhr.responseType = "arraybuffer";
24710
24711        xhr.onload = function () {
24712          var data, png;
24713          data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
24714          png = new PNG(data);
24715
24716          if (typeof (canvas != null ? canvas.getContext : void 0) === 'function') {
24717            png.render(canvas);
24718          }
24719
24720          return typeof callback === "function" ? callback(png) : void 0;
24721        };
24722
24723        return xhr.send(null);
24724      };
24725      APNG_DISPOSE_OP_BACKGROUND = 1;
24726      APNG_DISPOSE_OP_PREVIOUS = 2;
24727      APNG_BLEND_OP_SOURCE = 0;
24728
24729      function PNG(data) {
24730        var chunkSize, colors, palLen, delayDen, delayNum, frame, i, index, key, section, palShort, text, _i, _j, _ref;
24731
24732        this.data = data;
24733        this.pos = 8;
24734        this.palette = [];
24735        this.imgData = [];
24736        this.transparency = {};
24737        this.animation = null;
24738        this.text = {};
24739        frame = null;
24740
24741        while (true) {
24742          chunkSize = this.readUInt32();
24743
24744          section = function () {
24745            var _i, _results;
24746
24747            _results = [];
24748
24749            for (i = _i = 0; _i < 4; i = ++_i) {
24750              _results.push(String.fromCharCode(this.data[this.pos++]));
24751            }
24752
24753            return _results;
24754          }.call(this).join('');
24755
24756          switch (section) {
24757            case 'IHDR':
24758              this.width = this.readUInt32();
24759              this.height = this.readUInt32();
24760              this.bits = this.data[this.pos++];
24761              this.colorType = this.data[this.pos++];
24762              this.compressionMethod = this.data[this.pos++];
24763              this.filterMethod = this.data[this.pos++];
24764              this.interlaceMethod = this.data[this.pos++];
24765              break;
24766
24767            case 'acTL':
24768              this.animation = {
24769                numFrames: this.readUInt32(),
24770                numPlays: this.readUInt32() || Infinity,
24771                frames: []
24772              };
24773              break;
24774
24775            case 'PLTE':
24776              this.palette = this.read(chunkSize);
24777              break;
24778
24779            case 'fcTL':
24780              if (frame) {
24781                this.animation.frames.push(frame);
24782              }
24783
24784              this.pos += 4;
24785              frame = {
24786                width: this.readUInt32(),
24787                height: this.readUInt32(),
24788                xOffset: this.readUInt32(),
24789                yOffset: this.readUInt32()
24790              };
24791              delayNum = this.readUInt16();
24792              delayDen = this.readUInt16() || 100;
24793              frame.delay = 1000 * delayNum / delayDen;
24794              frame.disposeOp = this.data[this.pos++];
24795              frame.blendOp = this.data[this.pos++];
24796              frame.data = [];
24797              break;
24798
24799            case 'IDAT':
24800            case 'fdAT':
24801              if (section === 'fdAT') {
24802                this.pos += 4;
24803                chunkSize -= 4;
24804              }
24805
24806              data = (frame != null ? frame.data : void 0) || this.imgData;
24807
24808              for (i = _i = 0; 0 <= chunkSize ? _i < chunkSize : _i > chunkSize; i = 0 <= chunkSize ? ++_i : --_i) {
24809                data.push(this.data[this.pos++]);
24810              }
24811
24812              break;
24813
24814            case 'tRNS':
24815              this.transparency = {};
24816
24817              switch (this.colorType) {
24818                case 3:
24819                  palLen = this.palette.length / 3;
24820                  this.transparency.indexed = this.read(chunkSize);
24821                  if (this.transparency.indexed.length > palLen) throw new Error('More transparent colors than palette size');
24822                  /*
24823                   * According to the PNG spec trns should be increased to the same size as palette if shorter
24824                   */
24825                  //palShort = 255 - this.transparency.indexed.length;
24826
24827                  palShort = palLen - this.transparency.indexed.length;
24828
24829                  if (palShort > 0) {
24830                    for (i = _j = 0; 0 <= palShort ? _j < palShort : _j > palShort; i = 0 <= palShort ? ++_j : --_j) {
24831                      this.transparency.indexed.push(255);
24832                    }
24833                  }
24834
24835                  break;
24836
24837                case 0:
24838                  this.transparency.grayscale = this.read(chunkSize)[0];
24839                  break;
24840
24841                case 2:
24842                  this.transparency.rgb = this.read(chunkSize);
24843              }
24844
24845              break;
24846
24847            case 'tEXt':
24848              text = this.read(chunkSize);
24849              index = text.indexOf(0);
24850              key = String.fromCharCode.apply(String, text.slice(0, index));
24851              this.text[key] = String.fromCharCode.apply(String, text.slice(index + 1));
24852              break;
24853
24854            case 'IEND':
24855              if (frame) {
24856                this.animation.frames.push(frame);
24857              }
24858
24859              this.colors = function () {
24860                switch (this.colorType) {
24861                  case 0:
24862                  case 3:
24863                  case 4:
24864                    return 1;
24865
24866                  case 2:
24867                  case 6:
24868                    return 3;
24869                }
24870              }.call(this);
24871
24872              this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6;
24873              colors = this.colors + (this.hasAlphaChannel ? 1 : 0);
24874              this.pixelBitlength = this.bits * colors;
24875
24876              this.colorSpace = function () {
24877                switch (this.colors) {
24878                  case 1:
24879                    return 'DeviceGray';
24880
24881                  case 3:
24882                    return 'DeviceRGB';
24883                }
24884              }.call(this);
24885
24886              this.imgData = new Uint8Array(this.imgData);
24887              return;
24888
24889            default:
24890              this.pos += chunkSize;
24891          }
24892
24893          this.pos += 4;
24894
24895          if (this.pos > this.data.length) {
24896            throw new Error("Incomplete or corrupt PNG file");
24897          }
24898        }
24899
24900        return;
24901      }
24902
24903      PNG.prototype.read = function (bytes) {
24904        var i, _i, _results;
24905
24906        _results = [];
24907
24908        for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) {
24909          _results.push(this.data[this.pos++]);
24910        }
24911
24912        return _results;
24913      };
24914
24915      PNG.prototype.readUInt32 = function () {
24916        var b1, b2, b3, b4;
24917        b1 = this.data[this.pos++] << 24;
24918        b2 = this.data[this.pos++] << 16;
24919        b3 = this.data[this.pos++] << 8;
24920        b4 = this.data[this.pos++];
24921        return b1 | b2 | b3 | b4;
24922      };
24923
24924      PNG.prototype.readUInt16 = function () {
24925        var b1, b2;
24926        b1 = this.data[this.pos++] << 8;
24927        b2 = this.data[this.pos++];
24928        return b1 | b2;
24929      };
24930
24931      PNG.prototype.decodePixels = function (data) {
24932        var pixelBytes = this.pixelBitlength / 8;
24933        var fullPixels = new Uint8Array(this.width * this.height * pixelBytes);
24934        var pos = 0;
24935
24936        var _this = this;
24937
24938        if (data == null) {
24939          data = this.imgData;
24940        }
24941
24942        if (data.length === 0) {
24943          return new Uint8Array(0);
24944        }
24945
24946        data = new FlateStream(data);
24947        data = data.getBytes();
24948
24949        function pass(x0, y0, dx, dy) {
24950          var abyte, c, col, i, left, length, p, pa, paeth, pb, pc, pixels, row, scanlineLength, upper, upperLeft, _i, _j, _k, _l, _m;
24951
24952          var w = Math.ceil((_this.width - x0) / dx),
24953              h = Math.ceil((_this.height - y0) / dy);
24954          var isFull = _this.width == w && _this.height == h;
24955          scanlineLength = pixelBytes * w;
24956          pixels = isFull ? fullPixels : new Uint8Array(scanlineLength * h);
24957          length = data.length;
24958          row = 0;
24959          c = 0;
24960
24961          while (row < h && pos < length) {
24962            switch (data[pos++]) {
24963              case 0:
24964                for (i = _i = 0; _i < scanlineLength; i = _i += 1) {
24965                  pixels[c++] = data[pos++];
24966                }
24967
24968                break;
24969
24970              case 1:
24971                for (i = _j = 0; _j < scanlineLength; i = _j += 1) {
24972                  abyte = data[pos++];
24973                  left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
24974                  pixels[c++] = (abyte + left) % 256;
24975                }
24976
24977                break;
24978
24979              case 2:
24980                for (i = _k = 0; _k < scanlineLength; i = _k += 1) {
24981                  abyte = data[pos++];
24982                  col = (i - i % pixelBytes) / pixelBytes;
24983                  upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes];
24984                  pixels[c++] = (upper + abyte) % 256;
24985                }
24986
24987                break;
24988
24989              case 3:
24990                for (i = _l = 0; _l < scanlineLength; i = _l += 1) {
24991                  abyte = data[pos++];
24992                  col = (i - i % pixelBytes) / pixelBytes;
24993                  left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
24994                  upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes];
24995                  pixels[c++] = (abyte + Math.floor((left + upper) / 2)) % 256;
24996                }
24997
24998                break;
24999
25000              case 4:
25001                for (i = _m = 0; _m < scanlineLength; i = _m += 1) {
25002                  abyte = data[pos++];
25003                  col = (i - i % pixelBytes) / pixelBytes;
25004                  left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
25005
25006                  if (row === 0) {
25007                    upper = upperLeft = 0;
25008                  } else {
25009                    upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes];
25010                    upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + i % pixelBytes];
25011                  }
25012
25013                  p = left + upper - upperLeft;
25014                  pa = Math.abs(p - left);
25015                  pb = Math.abs(p - upper);
25016                  pc = Math.abs(p - upperLeft);
25017
25018                  if (pa <= pb && pa <= pc) {
25019                    paeth = left;
25020                  } else if (pb <= pc) {
25021                    paeth = upper;
25022                  } else {
25023                    paeth = upperLeft;
25024                  }
25025
25026                  pixels[c++] = (abyte + paeth) % 256;
25027                }
25028
25029                break;
25030
25031              default:
25032                throw new Error("Invalid filter algorithm: " + data[pos - 1]);
25033            }
25034
25035            if (!isFull) {
25036              var fullPos = ((y0 + row * dy) * _this.width + x0) * pixelBytes;
25037              var partPos = row * scanlineLength;
25038
25039              for (i = 0; i < w; i += 1) {
25040                for (var j = 0; j < pixelBytes; j += 1) {
25041                  fullPixels[fullPos++] = pixels[partPos++];
25042                }
25043
25044                fullPos += (dx - 1) * pixelBytes;
25045              }
25046            }
25047
25048            row++;
25049          }
25050        }
25051
25052        if (_this.interlaceMethod == 1) {
25053          /*
25054            1 6 4 6 2 6 4 6
25055            7 7 7 7 7 7 7 7
25056            5 6 5 6 5 6 5 6
25057            7 7 7 7 7 7 7 7
25058            3 6 4 6 3 6 4 6
25059            7 7 7 7 7 7 7 7
25060            5 6 5 6 5 6 5 6
25061            7 7 7 7 7 7 7 7
25062          */
25063          pass(0, 0, 8, 8); // 1
25064
25065          /* NOTE these seem to follow the pattern:
25066           * pass(x, 0, 2*x, 2*x);
25067           * pass(0, x,   x, 2*x);
25068           * with x being 4, 2, 1.
25069           */
25070
25071          pass(4, 0, 8, 8); // 2
25072
25073          pass(0, 4, 4, 8); // 3
25074
25075          pass(2, 0, 4, 4); // 4
25076
25077          pass(0, 2, 2, 4); // 5
25078
25079          pass(1, 0, 2, 2); // 6
25080
25081          pass(0, 1, 1, 2); // 7
25082        } else {
25083          pass(0, 0, 1, 1);
25084        }
25085
25086        return fullPixels;
25087      };
25088
25089      PNG.prototype.decodePalette = function () {
25090        var c, i, length, palette, pos, ret, transparency, _i, _ref, _ref1;
25091
25092        palette = this.palette;
25093        transparency = this.transparency.indexed || [];
25094        ret = new Uint8Array((transparency.length || 0) + palette.length);
25095        pos = 0;
25096        length = palette.length;
25097        c = 0;
25098
25099        for (i = _i = 0, _ref = palette.length; _i < _ref; i = _i += 3) {
25100          ret[pos++] = palette[i];
25101          ret[pos++] = palette[i + 1];
25102          ret[pos++] = palette[i + 2];
25103          ret[pos++] = (_ref1 = transparency[c++]) != null ? _ref1 : 255;
25104        }
25105
25106        return ret;
25107      };
25108
25109      PNG.prototype.copyToImageData = function (imageData, pixels) {
25110        var alpha, colors, data, i, input, j, k, length, palette, v, _ref;
25111
25112        colors = this.colors;
25113        palette = null;
25114        alpha = this.hasAlphaChannel;
25115
25116        if (this.palette.length) {
25117          palette = (_ref = this._decodedPalette) != null ? _ref : this._decodedPalette = this.decodePalette();
25118          colors = 4;
25119          alpha = true;
25120        }
25121
25122        data = imageData.data || imageData;
25123        length = data.length;
25124        input = palette || pixels;
25125        i = j = 0;
25126
25127        if (colors === 1) {
25128          while (i < length) {
25129            k = palette ? pixels[i / 4] * 4 : j;
25130            v = input[k++];
25131            data[i++] = v;
25132            data[i++] = v;
25133            data[i++] = v;
25134            data[i++] = alpha ? input[k++] : 255;
25135            j = k;
25136          }
25137        } else {
25138          while (i < length) {
25139            k = palette ? pixels[i / 4] * 4 : j;
25140            data[i++] = input[k++];
25141            data[i++] = input[k++];
25142            data[i++] = input[k++];
25143            data[i++] = alpha ? input[k++] : 255;
25144            j = k;
25145          }
25146        }
25147      };
25148
25149      PNG.prototype.decode = function () {
25150        var ret;
25151        ret = new Uint8Array(this.width * this.height * 4);
25152        this.copyToImageData(ret, this.decodePixels());
25153        return ret;
25154      };
25155
25156      try {
25157        scratchCanvas = global.document.createElement('canvas');
25158        scratchCtx = scratchCanvas.getContext('2d');
25159      } catch (e) {
25160        return -1;
25161      }
25162
25163      makeImage = function makeImage(imageData) {
25164        var img;
25165        scratchCtx.width = imageData.width;
25166        scratchCtx.height = imageData.height;
25167        scratchCtx.clearRect(0, 0, imageData.width, imageData.height);
25168        scratchCtx.putImageData(imageData, 0, 0);
25169        img = new Image();
25170        img.src = scratchCanvas.toDataURL();
25171        return img;
25172      };
25173
25174      PNG.prototype.decodeFrames = function (ctx) {
25175        var frame, i, imageData, pixels, _i, _len, _ref, _results;
25176
25177        if (!this.animation) {
25178          return;
25179        }
25180
25181        _ref = this.animation.frames;
25182        _results = [];
25183
25184        for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
25185          frame = _ref[i];
25186          imageData = ctx.createImageData(frame.width, frame.height);
25187          pixels = this.decodePixels(new Uint8Array(frame.data));
25188          this.copyToImageData(imageData, pixels);
25189          frame.imageData = imageData;
25190
25191          _results.push(frame.image = makeImage(imageData));
25192        }
25193
25194        return _results;
25195      };
25196
25197      PNG.prototype.renderFrame = function (ctx, number) {
25198        var frame, frames, prev;
25199        frames = this.animation.frames;
25200        frame = frames[number];
25201        prev = frames[number - 1];
25202
25203        if (number === 0) {
25204          ctx.clearRect(0, 0, this.width, this.height);
25205        }
25206
25207        if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_BACKGROUND) {
25208          ctx.clearRect(prev.xOffset, prev.yOffset, prev.width, prev.height);
25209        } else if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_PREVIOUS) {
25210          ctx.putImageData(prev.imageData, prev.xOffset, prev.yOffset);
25211        }
25212
25213        if (frame.blendOp === APNG_BLEND_OP_SOURCE) {
25214          ctx.clearRect(frame.xOffset, frame.yOffset, frame.width, frame.height);
25215        }
25216
25217        return ctx.drawImage(frame.image, frame.xOffset, frame.yOffset);
25218      };
25219
25220      PNG.prototype.animate = function (ctx) {
25221        var _doFrame,
25222            frameNumber,
25223            frames,
25224            numFrames,
25225            numPlays,
25226            _ref,
25227            _this = this;
25228
25229        frameNumber = 0;
25230        _ref = this.animation, numFrames = _ref.numFrames, frames = _ref.frames, numPlays = _ref.numPlays;
25231        return (_doFrame = function doFrame() {
25232          var f, frame;
25233          f = frameNumber++ % numFrames;
25234          frame = frames[f];
25235
25236          _this.renderFrame(ctx, f);
25237
25238          if (numFrames > 1 && frameNumber / numFrames < numPlays) {
25239            return _this.animation._timeout = setTimeout(_doFrame, frame.delay);
25240          }
25241        })();
25242      };
25243
25244      PNG.prototype.stopAnimation = function () {
25245        var _ref;
25246
25247        return clearTimeout((_ref = this.animation) != null ? _ref._timeout : void 0);
25248      };
25249
25250      PNG.prototype.render = function (canvas) {
25251        var ctx, data;
25252
25253        if (canvas._png) {
25254          canvas._png.stopAnimation();
25255        }
25256
25257        canvas._png = this;
25258        canvas.width = this.width;
25259        canvas.height = this.height;
25260        ctx = canvas.getContext("2d");
25261
25262        if (this.animation) {
25263          this.decodeFrames(ctx);
25264          return this.animate(ctx);
25265        } else {
25266          data = ctx.createImageData(this.width, this.height);
25267          this.copyToImageData(data, this.decodePixels());
25268          return ctx.putImageData(data, 0, 0);
25269        }
25270      };
25271
25272      return PNG;
25273    }();
25274
25275    global.PNG = PNG;
25276  })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function('return this')()); // `self` is undefined in Firefox for Android content script context
25277  // while `this` is nsIContentFrameMessageManager
25278  // with an attribute `content` that corresponds to the window
25279
25280  /*
25281   * Extracted from pdf.js
25282   * https://github.com/andreasgal/pdf.js
25283   *
25284   * Copyright (c) 2011 Mozilla Foundation
25285   *
25286   * Contributors: Andreas Gal <[email protected]>
25287   *               Chris G Jones <[email protected]>
25288   *               Shaon Barman <[email protected]>
25289   *               Vivien Nicolas <[email protected]>
25290   *               Justin D'Arcangelo <[email protected]>
25291   *               Yury Delendik
25292   *
25293   * 
25294   */
25295  var DecodeStream = function () {
25296    function constructor() {
25297      this.pos = 0;
25298      this.bufferLength = 0;
25299      this.eof = false;
25300      this.buffer = null;
25301    }
25302
25303    constructor.prototype = {
25304      ensureBuffer: function decodestream_ensureBuffer(requested) {
25305        var buffer = this.buffer;
25306        var current = buffer ? buffer.byteLength : 0;
25307        if (requested < current) return buffer;
25308        var size = 512;
25309
25310        while (size < requested) {
25311          size <<= 1;
25312        }
25313
25314        var buffer2 = new Uint8Array(size);
25315
25316        for (var i = 0; i < current; ++i) {
25317          buffer2[i] = buffer[i];
25318        }
25319
25320        return this.buffer = buffer2;
25321      },
25322      getByte: function decodestream_getByte() {
25323        var pos = this.pos;
25324
25325        while (this.bufferLength <= pos) {
25326          if (this.eof) return null;
25327          this.readBlock();
25328        }
25329
25330        return this.buffer[this.pos++];
25331      },
25332      getBytes: function decodestream_getBytes(length) {
25333        var pos = this.pos;
25334
25335        if (length) {
25336          this.ensureBuffer(pos + length);
25337          var end = pos + length;
25338
25339          while (!this.eof && this.bufferLength < end) {
25340            this.readBlock();
25341          }
25342
25343          var bufEnd = this.bufferLength;
25344          if (end > bufEnd) end = bufEnd;
25345        } else {
25346          while (!this.eof) {
25347            this.readBlock();
25348          }
25349
25350          var end = this.bufferLength;
25351        }
25352
25353        this.pos = end;
25354        return this.buffer.subarray(pos, end);
25355      },
25356      lookChar: function decodestream_lookChar() {
25357        var pos = this.pos;
25358
25359        while (this.bufferLength <= pos) {
25360          if (this.eof) return null;
25361          this.readBlock();
25362        }
25363
25364        return String.fromCharCode(this.buffer[this.pos]);
25365      },
25366      getChar: function decodestream_getChar() {
25367        var pos = this.pos;
25368
25369        while (this.bufferLength <= pos) {
25370          if (this.eof) return null;
25371          this.readBlock();
25372        }
25373
25374        return String.fromCharCode(this.buffer[this.pos++]);
25375      },
25376      makeSubStream: function decodestream_makeSubstream(start, length, dict) {
25377        var end = start + length;
25378
25379        while (this.bufferLength <= end && !this.eof) {
25380          this.readBlock();
25381        }
25382
25383        return new Stream(this.buffer, start, length, dict);
25384      },
25385      skip: function decodestream_skip(n) {
25386        if (!n) n = 1;
25387        this.pos += n;
25388      },
25389      reset: function decodestream_reset() {
25390        this.pos = 0;
25391      }
25392    };
25393    return constructor;
25394  }();
25395
25396  var FlateStream = function () {
25397    if (typeof Uint32Array === 'undefined') {
25398      return undefined;
25399    }
25400
25401    var codeLenCodeMap = new Uint32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
25402    var lengthDecode = new Uint32Array([0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102]);
25403    var distDecode = new Uint32Array([0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001]);
25404    var fixedLitCodeTab = [new Uint32Array([0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 
254040x900f6, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff]), 9];
25405    var fixedDistCodeTab = [new Uint32Array([0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000]), 5];
25406
25407    function error(e) {
25408      throw new Error(e);
25409    }
25410
25411    function constructor(bytes) {
25412      //var bytes = stream.getBytes();
25413      var bytesPos = 0;
25414      var cmf = bytes[bytesPos++];
25415      var flg = bytes[bytesPos++];
25416      if (cmf == -1 || flg == -1) error('Invalid header in flate stream');
25417      if ((cmf & 0x0f) != 0x08) error('Unknown compression method in flate stream');
25418      if (((cmf << 8) + flg) % 31 != 0) error('Bad FCHECK in flate stream');
25419      if (flg & 0x20) error('FDICT bit set in flate stream');
25420      this.bytes = bytes;
25421      this.bytesPos = bytesPos;
25422      this.codeSize = 0;
25423      this.codeBuf = 0;
25424      DecodeStream.call(this);
25425    }
25426
25427    constructor.prototype = Object.create(DecodeStream.prototype);
25428
25429    constructor.prototype.getBits = function (bits) {
25430      var codeSize = this.codeSize;
25431      var codeBuf = this.codeBuf;
25432      var bytes = this.bytes;
25433      var bytesPos = this.bytesPos;
25434      var b;
25435
25436      while (codeSize < bits) {
25437        if (typeof (b = bytes[bytesPos++]) == 'undefined') error('Bad encoding in flate stream');
25438        codeBuf |= b << codeSize;
25439        codeSize += 8;
25440      }
25441
25442      b = codeBuf & (1 << bits) - 1;
25443      this.codeBuf = codeBuf >> bits;
25444      this.codeSize = codeSize -= bits;
25445      this.bytesPos = bytesPos;
25446      return b;
25447    };
25448
25449    constructor.prototype.getCode = function (table) {
25450      var codes = table[0];
25451      var maxLen = table[1];
25452      var codeSize = this.codeSize;
25453      var codeBuf = this.codeBuf;
25454      var bytes = this.bytes;
25455      var bytesPos = this.bytesPos;
25456
25457      while (codeSize < maxLen) {
25458        var b;
25459        if (typeof (b = bytes[bytesPos++]) == 'undefined') error('Bad encoding in flate stream');
25460        codeBuf |= b << codeSize;
25461        codeSize += 8;
25462      }
25463
25464      var code = codes[codeBuf & (1 << maxLen) - 1];
25465      var codeLen = code >> 16;
25466      var codeVal = code & 0xffff;
25467      if (codeSize == 0 || codeSize < codeLen || codeLen == 0) error('Bad encoding in flate stream');
25468      this.codeBuf = codeBuf >> codeLen;
25469      this.codeSize = codeSize - codeLen;
25470      this.bytesPos = bytesPos;
25471      return codeVal;
25472    };
25473
25474    constructor.prototype.generateHuffmanTable = function (lengths) {
25475      var n = lengths.length; // find max code length
25476
25477      var maxLen = 0;
25478
25479      for (var i = 0; i < n; ++i) {
25480        if (lengths[i] > maxLen) maxLen = lengths[i];
25481      } // build the table
25482
25483
25484      var size = 1 << maxLen;
25485      var codes = new Uint32Array(size);
25486
25487      for (var len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) {
25488        for (var val = 0; val < n; ++val) {
25489          if (lengths[val] == len) {
25490            // bit-reverse the code
25491            var code2 = 0;
25492            var t = code;
25493
25494            for (var i = 0; i < len; ++i) {
25495              code2 = code2 << 1 | t & 1;
25496              t >>= 1;
25497            } // fill the table entries
25498
25499
25500            for (var i = code2; i < size; i += skip) {
25501              codes[i] = len << 16 | val;
25502            }
25503
25504            ++code;
25505          }
25506        }
25507      }
25508
25509      return [codes, maxLen];
25510    };
25511
25512    constructor.prototype.readBlock = function () {
25513      function repeat(stream, array, len, offset, what) {
25514        var repeat = stream.getBits(len) + offset;
25515
25516        while (repeat-- > 0) {
25517          array[i++] = what;
25518        }
25519      } // read block header
25520
25521
25522      var hdr = this.getBits(3);
25523      if (hdr & 1) this.eof = true;
25524      hdr >>= 1;
25525
25526      if (hdr == 0) {
25527        // uncompressed block
25528        var bytes = this.bytes;
25529        var bytesPos = this.bytesPos;
25530        var b;
25531        if (typeof (b = bytes[bytesPos++]) == 'undefined') error('Bad block header in flate stream');
25532        var blockLen = b;
25533        if (typeof (b = bytes[bytesPos++]) == 'undefined') error('Bad block header in flate stream');
25534        blockLen |= b << 8;
25535        if (typeof (b = bytes[bytesPos++]) == 'undefined') error('Bad block header in flate stream');
25536        var check = b;
25537        if (typeof (b = bytes[bytesPos++]) == 'undefined') error('Bad block header in flate stream');
25538        check |= b << 8;
25539        if (check != (~blockLen & 0xffff)) error('Bad uncompressed block length in flate stream');
25540        this.codeBuf = 0;
25541        this.codeSize = 0;
25542        var bufferLength = this.bufferLength;
25543        var buffer = this.ensureBuffer(bufferLength + blockLen);
25544        var end = bufferLength + blockLen;
25545        this.bufferLength = end;
25546
25547        for (var n = bufferLength; n < end; ++n) {
25548          if (typeof (b = bytes[bytesPos++]) == 'undefined') {
25549            this.eof = true;
25550            break;
25551          }
25552
25553          buffer[n] = b;
25554        }
25555
25556        this.bytesPos = bytesPos;
25557        return;
25558      }
25559
25560      var litCodeTable;
25561      var distCodeTable;
25562
25563      if (hdr == 1) {
25564        // compressed block, fixed codes
25565        litCodeTable = fixedLitCodeTab;
25566        distCodeTable = fixedDistCodeTab;
25567      } else if (hdr == 2) {
25568        // compressed block, dynamic codes
25569        var numLitCodes = this.getBits(5) + 257;
25570        var numDistCodes = this.getBits(5) + 1;
25571        var numCodeLenCodes = this.getBits(4) + 4; // build the code lengths code table
25572
25573        var codeLenCodeLengths = Array(codeLenCodeMap.length);
25574        var i = 0;
25575
25576        while (i < numCodeLenCodes) {
25577          codeLenCodeLengths[codeLenCodeMap[i++]] = this.getBits(3);
25578        }
25579
25580        var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); // build the literal and distance code tables
25581
25582        var len = 0;
25583        var i = 0;
25584        var codes = numLitCodes + numDistCodes;
25585        var codeLengths = new Array(codes);
25586
25587        while (i < codes) {
25588          var code = this.getCode(codeLenCodeTab);
25589
25590          if (code == 16) {
25591            repeat(this, codeLengths, 2, 3, len);
25592          } else if (code == 17) {
25593            repeat(this, codeLengths, 3, 3, len = 0);
25594          } else if (code == 18) {
25595            repeat(this, codeLengths, 7, 11, len = 0);
25596          } else {
25597            codeLengths[i++] = len = code;
25598          }
25599        }
25600
25601        litCodeTable = this.generateHuffmanTable(codeLengths.slice(0, numLitCodes));
25602        distCodeTable = this.generateHuffmanTable(codeLengths.slice(numLitCodes, codes));
25603      } else {
25604        error('Unknown block type in flate stream');
25605      }
25606
25607      var buffer = this.buffer;
25608      var limit = buffer ? buffer.length : 0;
25609      var pos = this.bufferLength;
25610
25611      while (true) {
25612        var code1 = this.getCode(litCodeTable);
25613
25614        if (code1 < 256) {
25615          if (pos + 1 >= limit) {
25616            buffer = this.ensureBuffer(pos + 1);
25617            limit = buffer.length;
25618          }
25619
25620          buffer[pos++] = code1;
25621          continue;
25622        }
25623
25624        if (code1 == 256) {
25625          this.bufferLength = pos;
25626          return;
25627        }
25628
25629        code1 -= 257;
25630        code1 = lengthDecode[code1];
25631        var code2 = code1 >> 16;
25632        if (code2 > 0) code2 = this.getBits(code2);
25633        var len = (code1 & 0xffff) + code2;
25634        code1 = this.getCode(distCodeTable);
25635        code1 = distDecode[code1];
25636        code2 = code1 >> 16;
25637        if (code2 > 0) code2 = this.getBits(code2);
25638        var dist = (code1 & 0xffff) + code2;
25639
25640        if (pos + len >= limit) {
25641          buffer = this.ensureBuffer(pos + len);
25642          limit = buffer.length;
25643        }
25644
25645        for (var k = 0; k < len; ++k, ++pos) {
25646          buffer[pos] = buffer[pos - dist];
25647        }
25648      }
25649    };
25650
25651    return constructor;
25652  }();
25653  /*rollup-keeper-start*/
25654
25655
25656  window.tmp = FlateStream;
25657  /*rollup-keeper-end*/
25658
25659}));
25660
25661try {
25662module.exports = jsPDF;
25663}
25664catch (e) {}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.