You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

9293 lines
386 KiB

  1. /** @preserve
  2. * jsPDF - PDF Document creation from JavaScript
  3. * Version 1.0.272-git Built on 2014-09-29T15:09
  4. * CommitID d4770725ca
  5. *
  6. * Copyright (c) 2010-2014 James Hall, https://github.com/MrRio/jsPDF
  7. * 2010 Aaron Spike, https://github.com/acspike
  8. * 2012 Willow Systems Corporation, willow-systems.com
  9. * 2012 Pablo Hess, https://github.com/pablohess
  10. * 2012 Florian Jenett, https://github.com/fjenett
  11. * 2013 Warren Weckesser, https://github.com/warrenweckesser
  12. * 2013 Youssef Beddad, https://github.com/lifof
  13. * 2013 Lee Driscoll, https://github.com/lsdriscoll
  14. * 2013 Stefan Slonevskiy, https://github.com/stefslon
  15. * 2013 Jeremy Morel, https://github.com/jmorel
  16. * 2013 Christoph Hartmann, https://github.com/chris-rock
  17. * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
  18. * 2014 James Makes, https://github.com/dollaruw
  19. * 2014 Diego Casorran, https://github.com/diegocr
  20. *
  21. * Permission is hereby granted, free of charge, to any person obtaining
  22. * a copy of this software and associated documentation files (the
  23. * "Software"), to deal in the Software without restriction, including
  24. * without limitation the rights to use, copy, modify, merge, publish,
  25. * distribute, sublicense, and/or sell copies of the Software, and to
  26. * permit persons to whom the Software is furnished to do so, subject to
  27. * the following conditions:
  28. *
  29. * The above copyright notice and this permission notice shall be
  30. * included in all copies or substantial portions of the Software.
  31. *
  32. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  33. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  34. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  35. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  36. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  37. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  38. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  39. *
  40. * Contributor(s):
  41. * siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango,
  42. * kim3er, mfo, alnorth,
  43. */
  44. /**
  45. * Creates new jsPDF document object instance.
  46. *
  47. * @class
  48. * @param orientation One of "portrait" or "landscape" (or shortcuts "p" (Default), "l")
  49. * @param unit Measurement unit to be used when coordinates are specified.
  50. * One of "pt" (points), "mm" (Default), "cm", "in"
  51. * @param format One of 'pageFormats' as shown below, default: a4
  52. * @returns {jsPDF}
  53. * @name jsPDF
  54. */
  55. var jsPDF = (function (global) {
  56. 'use strict';
  57. var pdfVersion = '1.3',
  58. pageFormats = { // Size in pt of various paper formats
  59. 'a0': [2383.94, 3370.39], 'a1': [1683.78, 2383.94],
  60. 'a2': [1190.55, 1683.78], 'a3': [841.89, 1190.55],
  61. 'a4': [595.28, 841.89], 'a5': [419.53, 595.28],
  62. 'a6': [297.64, 419.53], 'a7': [209.76, 297.64],
  63. 'a8': [147.40, 209.76], 'a9': [104.88, 147.40],
  64. 'a10': [73.70, 104.88], 'b0': [2834.65, 4008.19],
  65. 'b1': [2004.09, 2834.65], 'b2': [1417.32, 2004.09],
  66. 'b3': [1000.63, 1417.32], 'b4': [708.66, 1000.63],
  67. 'b5': [498.90, 708.66], 'b6': [354.33, 498.90],
  68. 'b7': [249.45, 354.33], 'b8': [175.75, 249.45],
  69. 'b9': [124.72, 175.75], 'b10': [87.87, 124.72],
  70. 'c0': [2599.37, 3676.54], 'c1': [1836.85, 2599.37],
  71. 'c2': [1298.27, 1836.85], 'c3': [918.43, 1298.27],
  72. 'c4': [649.13, 918.43], 'c5': [459.21, 649.13],
  73. 'c6': [323.15, 459.21], 'c7': [229.61, 323.15],
  74. 'c8': [161.57, 229.61], 'c9': [113.39, 161.57],
  75. 'c10': [79.37, 113.39], 'dl': [311.81, 623.62],
  76. 'letter': [612, 792],
  77. 'government-letter': [576, 756],
  78. 'legal': [612, 1008],
  79. 'junior-legal': [576, 360],
  80. 'ledger': [1224, 792],
  81. 'tabloid': [792, 1224],
  82. 'credit-card': [153, 243]
  83. };
  84. /**
  85. * jsPDF's Internal PubSub Implementation.
  86. * See mrrio.github.io/jsPDF/doc/symbols/PubSub.html
  87. * Backward compatible rewritten on 2014 by
  88. * Diego Casorran, https://github.com/diegocr
  89. *
  90. * @class
  91. * @name PubSub
  92. */
  93. function PubSub(context) {
  94. var topics = {};
  95. this.subscribe = function (topic, callback, once) {
  96. if (typeof callback !== 'function') {
  97. return false;
  98. }
  99. if (!topics.hasOwnProperty(topic)) {
  100. topics[topic] = {};
  101. }
  102. var id = Math.random().toString(35);
  103. topics[topic][id] = [callback, !!once];
  104. return id;
  105. };
  106. this.unsubscribe = function (token) {
  107. for (var topic in topics) {
  108. if (topics[topic][token]) {
  109. delete topics[topic][token];
  110. return true;
  111. }
  112. }
  113. return false;
  114. };
  115. this.publish = function (topic) {
  116. if (topics.hasOwnProperty(topic)) {
  117. var args = Array.prototype.slice.call(arguments, 1), idr = [];
  118. for (var id in topics[topic]) {
  119. var sub = topics[topic][id];
  120. try {
  121. sub[0].apply(context, args);
  122. } catch (ex) {
  123. if (global.console) {
  124. console.error('jsPDF PubSub Error', ex.message, ex);
  125. }
  126. }
  127. if (sub[1]) idr.push(id);
  128. }
  129. if (idr.length) idr.forEach(this.unsubscribe);
  130. }
  131. };
  132. }
  133. /**
  134. * @constructor
  135. * @private
  136. */
  137. function jsPDF(orientation, unit, format, compressPdf) {
  138. var options = {};
  139. if (typeof orientation === 'object') {
  140. options = orientation;
  141. orientation = options.orientation;
  142. unit = options.unit || unit;
  143. format = options.format || format;
  144. compressPdf = options.compress || options.compressPdf || compressPdf;
  145. }
  146. // Default options
  147. unit = unit || 'mm';
  148. format = format || 'a4';
  149. orientation = ('' + (orientation || 'P')).toLowerCase();
  150. var format_as_string = ('' + format).toLowerCase(),
  151. compress = !!compressPdf && typeof Uint8Array === 'function',
  152. textColor = options.textColor || '0 g',
  153. drawColor = options.drawColor || '0 G',
  154. activeFontSize = options.fontSize || 16,
  155. lineHeightProportion = options.lineHeight || 1.15,
  156. lineWidth = options.lineWidth || 0.200025, // 2mm
  157. objectNumber = 2, // 'n' Current object number
  158. outToPages = !1, // switches where out() prints. outToPages true = push to pages obj. outToPages false = doc builder content
  159. offsets = [], // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes.
  160. fonts = {}, // collection of font objects, where key is fontKey - a dynamically created label for a given font.
  161. fontmap = {}, // mapping structure fontName > fontStyle > font key - performance layer. See addFont()
  162. activeFontKey, // will be string representing the KEY of the font as combination of fontName + fontStyle
  163. k, // Scale factor
  164. tmp,
  165. page = 0,
  166. currentPage,
  167. pages = [],
  168. pagedim = {},
  169. content = [],
  170. lineCapID = 0,
  171. lineJoinID = 0,
  172. content_length = 0,
  173. pageWidth,
  174. pageHeight,
  175. pageMode,
  176. zoomMode,
  177. layoutMode,
  178. documentProperties = {
  179. 'title': '',
  180. 'subject': '',
  181. 'author': '',
  182. 'keywords': '',
  183. 'creator': ''
  184. },
  185. API = {},
  186. events = new PubSub(API),
  187. /////////////////////
  188. // Private functions
  189. /////////////////////
  190. f2 = function (number) {
  191. return number.toFixed(2); // Ie, %.2f
  192. },
  193. f3 = function (number) {
  194. return number.toFixed(3); // Ie, %.3f
  195. },
  196. padd2 = function (number) {
  197. return ('0' + parseInt(number)).slice(-2);
  198. },
  199. out = function (string) {
  200. if (outToPages) {
  201. /* set by beginPage */
  202. pages[currentPage].push(string);
  203. } else {
  204. // +1 for '\n' that will be used to join 'content'
  205. content_length += string.length + 1;
  206. content.push(string);
  207. }
  208. },
  209. newObject = function () {
  210. // Begin a new object
  211. objectNumber++;
  212. offsets[objectNumber] = content_length;
  213. out(objectNumber + ' 0 obj');
  214. return objectNumber;
  215. },
  216. putStream = function (str) {
  217. out('stream');
  218. out(str);
  219. out('endstream');
  220. },
  221. putPages = function () {
  222. var n, p, arr, i, deflater, adler32, adler32cs, wPt, hPt;
  223. adler32cs = global.adler32cs || jsPDF.adler32cs;
  224. if (compress && typeof adler32cs === 'undefined') {
  225. compress = false;
  226. }
  227. // outToPages = false as set in endDocument(). out() writes to content.
  228. for (n = 1; n <= page; n++) {
  229. newObject();
  230. wPt = (pageWidth = pagedim[n].width) * k;
  231. hPt = (pageHeight = pagedim[n].height) * k;
  232. out('<</Type /Page');
  233. out('/Parent 1 0 R');
  234. out('/Resources 2 0 R');
  235. out('/MediaBox [0 0 ' + f2(wPt) + ' ' + f2(hPt) + ']');
  236. out('/Contents ' + (objectNumber + 1) + ' 0 R>>');
  237. out('endobj');
  238. // Page content
  239. p = pages[n].join('\n');
  240. newObject();
  241. if (compress) {
  242. arr = [];
  243. i = p.length;
  244. while (i--) {
  245. arr[i] = p.charCodeAt(i);
  246. }
  247. adler32 = adler32cs.from(p);
  248. deflater = new Deflater(6);
  249. deflater.append(new Uint8Array(arr));
  250. p = deflater.flush();
  251. arr = new Uint8Array(p.length + 6);
  252. arr.set(new Uint8Array([120, 156])),
  253. arr.set(p, 2);
  254. arr.set(new Uint8Array([adler32 & 0xFF, (adler32 >> 8) & 0xFF, (adler32 >> 16) & 0xFF, (adler32 >> 24) & 0xFF]), p.length + 2);
  255. p = String.fromCharCode.apply(null, arr);
  256. out('<</Length ' + p.length + ' /Filter [/FlateDecode]>>');
  257. } else {
  258. out('<</Length ' + p.length + '>>');
  259. }
  260. putStream(p);
  261. out('endobj');
  262. }
  263. offsets[1] = content_length;
  264. out('1 0 obj');
  265. out('<</Type /Pages');
  266. var kids = '/Kids [';
  267. for (i = 0; i < page; i++) {
  268. kids += (3 + 2 * i) + ' 0 R ';
  269. }
  270. out(kids + ']');
  271. out('/Count ' + page);
  272. out('>>');
  273. out('endobj');
  274. },
  275. putFont = function (font) {
  276. font.objectNumber = newObject();
  277. out('<</BaseFont/' + font.PostScriptName + '/Type/Font');
  278. if (typeof font.encoding === 'string') {
  279. out('/Encoding/' + font.encoding);
  280. }
  281. out('/Subtype/Type1>>');
  282. out('endobj');
  283. },
  284. putFonts = function () {
  285. for (var fontKey in fonts) {
  286. if (fonts.hasOwnProperty(fontKey)) {
  287. putFont(fonts[fontKey]);
  288. }
  289. }
  290. },
  291. putXobjectDict = function () {
  292. // Loop through images, or other data objects
  293. events.publish('putXobjectDict');
  294. },
  295. putResourceDictionary = function () {
  296. out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
  297. out('/Font <<');
  298. // Do this for each font, the '1' bit is the index of the font
  299. for (var fontKey in fonts) {
  300. if (fonts.hasOwnProperty(fontKey)) {
  301. out('/' + fontKey + ' ' + fonts[fontKey].objectNumber + ' 0 R');
  302. }
  303. }
  304. out('>>');
  305. out('/XObject <<');
  306. putXobjectDict();
  307. out('>>');
  308. },
  309. putResources = function () {
  310. putFonts();
  311. events.publish('putResources');
  312. // Resource dictionary
  313. offsets[2] = content_length;
  314. out('2 0 obj');
  315. out('<<');
  316. putResourceDictionary();
  317. out('>>');
  318. out('endobj');
  319. events.publish('postPutResources');
  320. },
  321. addToFontDictionary = function (fontKey, fontName, fontStyle) {
  322. // this is mapping structure for quick font key lookup.
  323. // returns the KEY of the font (ex: "F1") for a given
  324. // pair of font name and type (ex: "Arial". "Italic")
  325. if (!fontmap.hasOwnProperty(fontName)) {
  326. fontmap[fontName] = {};
  327. }
  328. fontmap[fontName][fontStyle] = fontKey;
  329. },
  330. /**
  331. * FontObject describes a particular font as member of an instnace of jsPDF
  332. *
  333. * It's a collection of properties like 'id' (to be used in PDF stream),
  334. * 'fontName' (font's family name), 'fontStyle' (font's style variant label)
  335. *
  336. * @class
  337. * @public
  338. * @property id {String} PDF-document-instance-specific label assinged to the font.
  339. * @property PostScriptName {String} PDF specification full name for the font
  340. * @property encoding {Object} Encoding_name-to-Font_metrics_object mapping.
  341. * @name FontObject
  342. */
  343. addFont = function (PostScriptName, fontName, fontStyle, encoding) {
  344. var fontKey = 'F' + (Object.keys(fonts).length + 1).toString(10),
  345. // This is FontObject
  346. font = fonts[fontKey] = {
  347. 'id': fontKey,
  348. 'PostScriptName': PostScriptName,
  349. 'fontName': fontName,
  350. 'fontStyle': fontStyle,
  351. 'encoding': encoding,
  352. 'metadata': {}
  353. };
  354. addToFontDictionary(fontKey, fontName, fontStyle);
  355. events.publish('addFont', font);
  356. return fontKey;
  357. },
  358. addFonts = function () {
  359. var HELVETICA = "helvetica",
  360. TIMES = "times",
  361. COURIER = "courier",
  362. NORMAL = "normal",
  363. BOLD = "bold",
  364. ITALIC = "italic",
  365. BOLD_ITALIC = "bolditalic",
  366. encoding = 'StandardEncoding',
  367. standardFonts = [
  368. ['Helvetica', HELVETICA, NORMAL],
  369. ['Helvetica-Bold', HELVETICA, BOLD],
  370. ['Helvetica-Oblique', HELVETICA, ITALIC],
  371. ['Helvetica-BoldOblique', HELVETICA, BOLD_ITALIC],
  372. ['Courier', COURIER, NORMAL],
  373. ['Courier-Bold', COURIER, BOLD],
  374. ['Courier-Oblique', COURIER, ITALIC],
  375. ['Courier-BoldOblique', COURIER, BOLD_ITALIC],
  376. ['Times-Roman', TIMES, NORMAL],
  377. ['Times-Bold', TIMES, BOLD],
  378. ['Times-Italic', TIMES, ITALIC],
  379. ['Times-BoldItalic', TIMES, BOLD_ITALIC]
  380. ];
  381. for (var i = 0, l = standardFonts.length; i < l; i++) {
  382. var fontKey = addFont(
  383. standardFonts[i][0],
  384. standardFonts[i][1],
  385. standardFonts[i][2],
  386. encoding);
  387. // adding aliases for standard fonts, this time matching the capitalization
  388. var parts = standardFonts[i][0].split('-');
  389. addToFontDictionary(fontKey, parts[0], parts[1] || '');
  390. }
  391. events.publish('addFonts', { fonts: fonts, dictionary: fontmap });
  392. },
  393. SAFE = function __safeCall(fn) {
  394. fn.foo = function __safeCallWrapper() {
  395. try {
  396. return fn.apply(this, arguments);
  397. } catch (e) {
  398. var stack = e.stack || '';
  399. if (~stack.indexOf(' at ')) stack = stack.split(" at ")[1];
  400. var m = "Error in function " + stack.split("\n")[0].split('<')[0] + ": " + e.message;
  401. if (global.console) {
  402. global.console.error(m, e);
  403. if (global.alert) alert(m);
  404. } else {
  405. throw new Error(m);
  406. }
  407. }
  408. };
  409. fn.foo.bar = fn;
  410. return fn.foo;
  411. },
  412. to8bitStream = function (text, flags) {
  413. /**
  414. * PDF 1.3 spec:
  415. * "For text strings encoded in Unicode, the first two bytes must be 254 followed by
  416. * 255, representing the Unicode byte order marker, U+FEFF. (This sequence conflicts
  417. * with the PDFDocEncoding character sequence thorn ydieresis, which is unlikely
  418. * to be a meaningful beginning of a word or phrase.) The remainder of the
  419. * string consists of Unicode character codes, according to the UTF-16 encoding
  420. * specified in the Unicode standard, version 2.0. Commonly used Unicode values
  421. * are represented as 2 bytes per character, with the high-order byte appearing first
  422. * in the string."
  423. *
  424. * In other words, if there are chars in a string with char code above 255, we
  425. * recode the string to UCS2 BE - string doubles in length and BOM is prepended.
  426. *
  427. * HOWEVER!
  428. * Actual *content* (body) text (as opposed to strings used in document properties etc)
  429. * does NOT expect BOM. There, it is treated as a literal GID (Glyph ID)
  430. *
  431. * Because of Adobe's focus on "you subset your fonts!" you are not supposed to have
  432. * a font that maps directly Unicode (UCS2 / UTF16BE) code to font GID, but you could
  433. * fudge it with "Identity-H" encoding and custom CIDtoGID map that mimics Unicode
  434. * code page. There, however, all characters in the stream are treated as GIDs,
  435. * including BOM, which is the reason we need to skip BOM in content text (i.e. that
  436. * that is tied to a font).
  437. *
  438. * To signal this "special" PDFEscape / to8bitStream handling mode,
  439. * API.text() function sets (unless you overwrite it with manual values
  440. * given to API.text(.., flags) )
  441. * flags.autoencode = true
  442. * flags.noBOM = true
  443. *
  444. * ===================================================================================
  445. * `flags` properties relied upon:
  446. * .sourceEncoding = string with encoding label.
  447. * "Unicode" by default. = encoding of the incoming text.
  448. * pass some non-existing encoding name
  449. * (ex: 'Do not touch my strings! I know what I am doing.')
  450. * to make encoding code skip the encoding step.
  451. * .outputEncoding = Either valid PDF encoding name
  452. * (must be supported by jsPDF font metrics, otherwise no encoding)
  453. * or a JS object, where key = sourceCharCode, value = outputCharCode
  454. * missing keys will be treated as: sourceCharCode === outputCharCode
  455. * .noBOM
  456. * See comment higher above for explanation for why this is important
  457. * .autoencode
  458. * See comment higher above for explanation for why this is important
  459. */
  460. var i, l, sourceEncoding, encodingBlock, outputEncoding, newtext, isUnicode, ch, bch;
  461. flags = flags || {};
  462. sourceEncoding = flags.sourceEncoding || 'Unicode';
  463. outputEncoding = flags.outputEncoding;
  464. // This 'encoding' section relies on font metrics format
  465. // attached to font objects by, among others,
  466. // "Willow Systems' standard_font_metrics plugin"
  467. // see jspdf.plugin.standard_font_metrics.js for format
  468. // of the font.metadata.encoding Object.
  469. // It should be something like
  470. // .encoding = {'codePages':['WinANSI....'], 'WinANSI...':{code:code, ...}}
  471. // .widths = {0:width, code:width, ..., 'fof':divisor}
  472. // .kerning = {code:{previous_char_code:shift, ..., 'fof':-divisor},...}
  473. if ((flags.autoencode || outputEncoding) &&
  474. fonts[activeFontKey].metadata &&
  475. fonts[activeFontKey].metadata[sourceEncoding] &&
  476. fonts[activeFontKey].metadata[sourceEncoding].encoding) {
  477. encodingBlock = fonts[activeFontKey].metadata[sourceEncoding].encoding;
  478. // each font has default encoding. Some have it clearly defined.
  479. if (!outputEncoding && fonts[activeFontKey].encoding) {
  480. outputEncoding = fonts[activeFontKey].encoding;
  481. }
  482. // Hmmm, the above did not work? Let's try again, in different place.
  483. if (!outputEncoding && encodingBlock.codePages) {
  484. outputEncoding = encodingBlock.codePages[0]; // let's say, first one is the default
  485. }
  486. if (typeof outputEncoding === 'string') {
  487. outputEncoding = encodingBlock[outputEncoding];
  488. }
  489. // we want output encoding to be a JS Object, where
  490. // key = sourceEncoding's character code and
  491. // value = outputEncoding's character code.
  492. if (outputEncoding) {
  493. isUnicode = false;
  494. newtext = [];
  495. for (i = 0, l = text.length; i < l; i++) {
  496. ch = outputEncoding[text.charCodeAt(i)];
  497. if (ch) {
  498. newtext.push(
  499. String.fromCharCode(ch));
  500. } else {
  501. newtext.push(
  502. text[i]);
  503. }
  504. // since we are looping over chars anyway, might as well
  505. // check for residual unicodeness
  506. if (newtext[i].charCodeAt(0) >> 8) {
  507. /* more than 255 */
  508. isUnicode = true;
  509. }
  510. }
  511. text = newtext.join('');
  512. }
  513. }
  514. i = text.length;
  515. // isUnicode may be set to false above. Hence the triple-equal to undefined
  516. while (isUnicode === undefined && i !== 0) {
  517. if (text.charCodeAt(i - 1) >> 8) {
  518. /* more than 255 */
  519. isUnicode = true;
  520. }
  521. i--;
  522. }
  523. if (!isUnicode) {
  524. return text;
  525. }
  526. newtext = flags.noBOM ? [] : [254, 255];
  527. for (i = 0, l = text.length; i < l; i++) {
  528. ch = text.charCodeAt(i);
  529. bch = ch >> 8; // divide by 256
  530. if (bch >> 8) {
  531. /* something left after dividing by 256 second time */
  532. throw new Error("Character at position " + i + " of string '"
  533. + text + "' exceeds 16bits. Cannot be encoded into UCS-2 BE");
  534. }
  535. newtext.push(bch);
  536. newtext.push(ch - (bch << 8));
  537. }
  538. return String.fromCharCode.apply(undefined, newtext);
  539. },
  540. pdfEscape = function (text, flags) {
  541. /**
  542. * Replace '/', '(', and ')' with pdf-safe versions
  543. *
  544. * Doing to8bitStream does NOT make this PDF display unicode text. For that
  545. * we also need to reference a unicode font and embed it - royal pain in the rear.
  546. *
  547. * There is still a benefit to to8bitStream - PDF simply cannot handle 16bit chars,
  548. * which JavaScript Strings are happy to provide. So, while we still cannot display
  549. * 2-byte characters property, at least CONDITIONALLY converting (entire string containing)
  550. * 16bit chars to (USC-2-BE) 2-bytes per char + BOM streams we ensure that entire PDF
  551. * is still parseable.
  552. * This will allow immediate support for unicode in document properties strings.
  553. */
  554. return to8bitStream(text, flags).replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
  555. },
  556. putInfo = function () {
  557. out('/Producer (jsPDF ' + jsPDF.version + ')');
  558. for (var key in documentProperties) {
  559. if (documentProperties.hasOwnProperty(key) && documentProperties[key]) {
  560. out('/' + key.substr(0, 1).toUpperCase() + key.substr(1)
  561. + ' (' + pdfEscape(documentProperties[key]) + ')');
  562. }
  563. }
  564. var created = new Date(),
  565. tzoffset = created.getTimezoneOffset(),
  566. tzsign = tzoffset < 0 ? '+' : '-',
  567. tzhour = Math.floor(Math.abs(tzoffset / 60)),
  568. tzmin = Math.abs(tzoffset % 60),
  569. tzstr = [tzsign, padd2(tzhour), "'", padd2(tzmin), "'"].join('');
  570. out(['/CreationDate (D:',
  571. created.getFullYear(),
  572. padd2(created.getMonth() + 1),
  573. padd2(created.getDate()),
  574. padd2(created.getHours()),
  575. padd2(created.getMinutes()),
  576. padd2(created.getSeconds()), tzstr, ')'].join(''));
  577. },
  578. putCatalog = function () {
  579. out('/Type /Catalog');
  580. out('/Pages 1 0 R');
  581. // PDF13ref Section 7.2.1
  582. if (!zoomMode) zoomMode = 'fullwidth';
  583. switch (zoomMode) {
  584. case 'fullwidth': out('/OpenAction [3 0 R /FitH null]'); break;
  585. case 'fullheight': out('/OpenAction [3 0 R /FitV null]'); break;
  586. case 'fullpage': out('/OpenAction [3 0 R /Fit]'); break;
  587. case 'original': out('/OpenAction [3 0 R /XYZ null null 1]'); break;
  588. default:
  589. var pcn = '' + zoomMode;
  590. if (pcn.substr(pcn.length - 1) === '%')
  591. zoomMode = parseInt(zoomMode) / 100;
  592. if (typeof zoomMode === 'number') {
  593. out('/OpenAction [3 0 R /XYZ null null ' + f2(zoomMode) + ']');
  594. }
  595. }
  596. if (!layoutMode) layoutMode = 'continuous';
  597. switch (layoutMode) {
  598. case 'continuous': out('/PageLayout /OneColumn'); break;
  599. case 'single': out('/PageLayout /SinglePage'); break;
  600. case 'two':
  601. case 'twoleft': out('/PageLayout /TwoColumnLeft'); break;
  602. case 'tworight': out('/PageLayout /TwoColumnRight'); break;
  603. }
  604. if (pageMode) {
  605. /**
  606. * A name object specifying how the document should be displayed when opened:
  607. * UseNone : Neither document outline nor thumbnail images visible -- DEFAULT
  608. * UseOutlines : Document outline visible
  609. * UseThumbs : Thumbnail images visible
  610. * FullScreen : Full-screen mode, with no menu bar, window controls, or any other window visible
  611. */
  612. out('/PageMode /' + pageMode);
  613. }
  614. events.publish('putCatalog');
  615. },
  616. putTrailer = function () {
  617. out('/Size ' + (objectNumber + 1));
  618. out('/Root ' + objectNumber + ' 0 R');
  619. out('/Info ' + (objectNumber - 1) + ' 0 R');
  620. },
  621. beginPage = function (width, height) {
  622. // Dimensions are stored as user units and converted to points on output
  623. var orientation = typeof height === 'string' && height.toLowerCase();
  624. if (typeof width === 'string') {
  625. var format = width.toLowerCase();
  626. if (pageFormats.hasOwnProperty(format)) {
  627. width = pageFormats[format][0] / k;
  628. height = pageFormats[format][1] / k;
  629. }
  630. }
  631. if (Array.isArray(width)) {
  632. height = width[1];
  633. width = width[0];
  634. }
  635. if (orientation) {
  636. switch (orientation.substr(0, 1)) {
  637. case 'l': if (height > width) orientation = 's'; break;
  638. case 'p': if (width > height) orientation = 's'; break;
  639. }
  640. if (orientation === 's') { tmp = width; width = height; height = tmp; }
  641. }
  642. outToPages = true;
  643. pages[++page] = [];
  644. pagedim[page] = {
  645. width: Number(width) || pageWidth,
  646. height: Number(height) || pageHeight
  647. };
  648. _setPage(page);
  649. },
  650. _addPage = function () {
  651. beginPage.apply(this, arguments);
  652. // Set line width
  653. out(f2(lineWidth * k) + ' w');
  654. // Set draw color
  655. out(drawColor);
  656. // resurrecting non-default line caps, joins
  657. if (lineCapID !== 0) {
  658. out(lineCapID + ' J');
  659. }
  660. if (lineJoinID !== 0) {
  661. out(lineJoinID + ' j');
  662. }
  663. events.publish('addPage', { pageNumber: page });
  664. },
  665. _setPage = function (n) {
  666. if (n > 0 && n <= page) {
  667. currentPage = n;
  668. pageWidth = pagedim[n].width;
  669. pageHeight = pagedim[n].height;
  670. }
  671. },
  672. /**
  673. * Returns a document-specific font key - a label assigned to a
  674. * font name + font type combination at the time the font was added
  675. * to the font inventory.
  676. *
  677. * Font key is used as label for the desired font for a block of text
  678. * to be added to the PDF document stream.
  679. * @private
  680. * @function
  681. * @param fontName {String} can be undefined on "falthy" to indicate "use current"
  682. * @param fontStyle {String} can be undefined on "falthy" to indicate "use current"
  683. * @returns {String} Font key.
  684. */
  685. getFont = function (fontName, fontStyle) {
  686. var key;
  687. fontName = fontName !== undefined ? fontName : fonts[activeFontKey].fontName;
  688. fontStyle = fontStyle !== undefined ? fontStyle : fonts[activeFontKey].fontStyle;
  689. try {
  690. // get a string like 'F3' - the KEY corresponding tot he font + type combination.
  691. key = fontmap[fontName][fontStyle];
  692. } catch (e) { }
  693. if (!key) {
  694. throw new Error("Unable to look up font label for font '" + fontName + "', '"
  695. + fontStyle + "'. Refer to getFontList() for available fonts.");
  696. }
  697. return key;
  698. },
  699. buildDocument = function () {
  700. outToPages = false; // switches out() to content
  701. objectNumber = 2;
  702. content = [];
  703. offsets = [];
  704. // putHeader()
  705. out('%PDF-' + pdfVersion);
  706. putPages();
  707. putResources();
  708. // Info
  709. newObject();
  710. out('<<');
  711. putInfo();
  712. out('>>');
  713. out('endobj');
  714. // Catalog
  715. newObject();
  716. out('<<');
  717. putCatalog();
  718. out('>>');
  719. out('endobj');
  720. // Cross-ref
  721. var o = content_length, i, p = "0000000000";
  722. out('xref');
  723. out('0 ' + (objectNumber + 1));
  724. out(p + ' 65535 f ');
  725. for (i = 1; i <= objectNumber; i++) {
  726. out((p + offsets[i]).slice(-10) + ' 00000 n ');
  727. }
  728. // Trailer
  729. out('trailer');
  730. out('<<');
  731. putTrailer();
  732. out('>>');
  733. out('startxref');
  734. out(o);
  735. out('%%EOF');
  736. outToPages = true;
  737. return content.join('\n');
  738. },
  739. getStyle = function (style) {
  740. // see path-painting operators in PDF spec
  741. var op = 'S'; // stroke
  742. if (style === 'F') {
  743. op = 'f'; // fill
  744. } else if (style === 'FD' || style === 'DF') {
  745. op = 'B'; // both
  746. } else if (style === 'f' || style === 'f*' || style === 'B' || style === 'B*') {
  747. /*
  748. Allow direct use of these PDF path-painting operators:
  749. - f fill using nonzero winding number rule
  750. - f* fill using even-odd rule
  751. - B fill then stroke with fill using non-zero winding number rule
  752. - B* fill then stroke with fill using even-odd rule
  753. */
  754. op = style;
  755. }
  756. return op;
  757. },
  758. getArrayBuffer = function () {
  759. var data = buildDocument(), len = data.length,
  760. ab = new ArrayBuffer(len), u8 = new Uint8Array(ab);
  761. while (len--) u8[len] = data.charCodeAt(len);
  762. return ab;
  763. },
  764. getBlob = function () {
  765. return new Blob([getArrayBuffer()], { type: "application/pdf" });
  766. },
  767. /**
  768. * Generates the PDF document.
  769. *
  770. * If `type` argument is undefined, output is raw body of resulting PDF returned as a string.
  771. *
  772. * @param {String} type A string identifying one of the possible output types.
  773. * @param {Object} options An object providing some additional signalling to PDF generator.
  774. * @function
  775. * @returns {jsPDF}
  776. * @methodOf jsPDF#
  777. * @name output
  778. */
  779. output = SAFE(function (type, options) {
  780. var datauri = ('' + type).substr(0, 6) === 'dataur'
  781. ? 'data:application/pdf;base64,' + btoa(buildDocument()) : 0;
  782. switch (type) {
  783. case undefined:
  784. return buildDocument();
  785. case 'save':
  786. if (navigator.getUserMedia) {
  787. if (global.URL === undefined
  788. || global.URL.createObjectURL === undefined) {
  789. return API.output('dataurlnewwindow');
  790. }
  791. }
  792. saveAs(getBlob(), options);
  793. if (typeof saveAs.unload === 'function') {
  794. if (global.setTimeout) {
  795. setTimeout(saveAs.unload, 911);
  796. }
  797. }
  798. break;
  799. case 'arraybuffer':
  800. return getArrayBuffer();
  801. case 'blob':
  802. return getBlob();
  803. case 'bloburi':
  804. case 'bloburl':
  805. // User is responsible of calling revokeObjectURL
  806. return global.URL && global.URL.createObjectURL(getBlob()) || void 0;
  807. case 'datauristring':
  808. case 'dataurlstring':
  809. return datauri;
  810. case 'dataurlnewwindow':
  811. var nW = global.open(datauri);
  812. if (nW || typeof safari === "undefined") return nW;
  813. /* pass through */
  814. case 'datauri':
  815. case 'dataurl':
  816. return global.document.location.href = datauri;
  817. default:
  818. throw new Error('Output type "' + type + '" is not supported.');
  819. }
  820. // @TODO: Add different output options
  821. });
  822. switch (unit) {
  823. case 'pt': k = 1; break;
  824. case 'mm': k = 72 / 25.4; break;
  825. case 'cm': k = 72 / 2.54; break;
  826. case 'in': k = 72; break;
  827. case 'px': k = 96 / 72; break;
  828. case 'pc': k = 12; break;
  829. case 'em': k = 12; break;
  830. case 'ex': k = 6; break;
  831. default:
  832. throw ('Invalid unit: ' + unit);
  833. }
  834. //---------------------------------------
  835. // Public API
  836. /**
  837. * Object exposing internal API to plugins
  838. * @public
  839. */
  840. API.internal = {
  841. 'pdfEscape': pdfEscape,
  842. 'getStyle': getStyle,
  843. /**
  844. * Returns {FontObject} describing a particular font.
  845. * @public
  846. * @function
  847. * @param fontName {String} (Optional) Font's family name
  848. * @param fontStyle {String} (Optional) Font's style variation name (Example:"Italic")
  849. * @returns {FontObject}
  850. */
  851. 'getFont': function () {
  852. return fonts[getFont.apply(API, arguments)];
  853. },
  854. 'getFontSize': function () {
  855. return activeFontSize;
  856. },
  857. 'getLineHeight': function () {
  858. return activeFontSize * lineHeightProportion;
  859. },
  860. 'write': function (string1 /*, string2, string3, etc */) {
  861. out(arguments.length === 1 ? string1 : Array.prototype.join.call(arguments, ' '));
  862. },
  863. 'getCoordinateString': function (value) {
  864. return f2(value * k);
  865. },
  866. 'getVerticalCoordinateString': function (value) {
  867. return f2((pageHeight - value) * k);
  868. },
  869. 'collections': {},
  870. 'newObject': newObject,
  871. 'putStream': putStream,
  872. 'events': events,
  873. // ratio that you use in multiplication of a given "size" number to arrive to 'point'
  874. // units of measurement.
  875. // scaleFactor is set at initialization of the document and calculated against the stated
  876. // default measurement units for the document.
  877. // If default is "mm", k is the number that will turn number in 'mm' into 'points' number.
  878. // through multiplication.
  879. 'scaleFactor': k,
  880. 'pageSize': {
  881. get width() {
  882. return pageWidth
  883. },
  884. get height() {
  885. return pageHeight
  886. }
  887. },
  888. 'output': function (type, options) {
  889. return output(type, options);
  890. },
  891. 'getNumberOfPages': function () {
  892. return pages.length - 1;
  893. },
  894. 'pages': pages
  895. };
  896. /**
  897. * Adds (and transfers the focus to) new page to the PDF document.
  898. * @function
  899. * @returns {jsPDF}
  900. *
  901. * @methodOf jsPDF#
  902. * @name addPage
  903. */
  904. API.addPage = function () {
  905. _addPage.apply(this, arguments);
  906. return this;
  907. };
  908. API.setPage = function () {
  909. _setPage.apply(this, arguments);
  910. return this;
  911. };
  912. API.setDisplayMode = function (zoom, layout, pmode) {
  913. zoomMode = zoom;
  914. layoutMode = layout;
  915. pageMode = pmode;
  916. return this;
  917. },
  918. /**
  919. * Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings.
  920. *
  921. * @function
  922. * @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.
  923. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  924. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  925. * @param {Object} flags Collection of settings signalling how the text must be encoded. Defaults are sane. If you think you want to pass some flags, you likely can read the source.
  926. * @returns {jsPDF}
  927. * @methodOf jsPDF#
  928. * @name text
  929. */
  930. API.text = function (text, x, y, flags, angle) {
  931. /**
  932. * Inserts something like this into PDF
  933. * BT
  934. * /F1 16 Tf % Font name + size
  935. * 16 TL % How many units down for next line in multiline text
  936. * 0 g % color
  937. * 28.35 813.54 Td % position
  938. * (line one) Tj
  939. * T* (line two) Tj
  940. * T* (line three) Tj
  941. * ET
  942. */
  943. function ESC(s) {
  944. s = s.split("\t").join(Array(options.TabLen || 9).join(" "));
  945. return pdfEscape(s, flags);
  946. }
  947. // Pre-August-2012 the order of arguments was function(x, y, text, flags)
  948. // in effort to make all calls have similar signature like
  949. // function(data, coordinates... , miscellaneous)
  950. // this method had its args flipped.
  951. // code below allows backward compatibility with old arg order.
  952. if (typeof text === 'number') {
  953. tmp = y;
  954. y = x;
  955. x = text;
  956. text = tmp;
  957. }
  958. // If there are any newlines in text, we assume
  959. // the user wanted to print multiple lines, so break the
  960. // text up into an array. If the text is already an array,
  961. // we assume the user knows what they are doing.
  962. if (typeof text === 'string' && text.match(/[\n\r]/)) {
  963. text = text.split(/\r\n|\r|\n/g);
  964. }
  965. if (typeof flags === 'number') {
  966. angle = flags;
  967. flags = null;
  968. }
  969. var xtra = '', mode = 'Td', todo;
  970. if (angle) {
  971. angle *= (Math.PI / 180);
  972. var c = Math.cos(angle),
  973. s = Math.sin(angle);
  974. xtra = [f2(c), f2(s), f2(s * -1), f2(c), ''].join(" ");
  975. mode = 'Tm';
  976. }
  977. flags = flags || {};
  978. if (!('noBOM' in flags))
  979. flags.noBOM = true;
  980. if (!('autoencode' in flags))
  981. flags.autoencode = true;
  982. if (typeof text === 'string') {
  983. text = ESC(text);
  984. } else if (text instanceof Array) {
  985. // we don't want to destroy original text array, so cloning it
  986. var sa = text.concat(), da = [], len = sa.length;
  987. // we do array.join('text that must not be PDFescaped")
  988. // thus, pdfEscape each component separately
  989. while (len--) {
  990. da.push(ESC(sa.shift()));
  991. }
  992. var linesLeft = Math.ceil((pageHeight - y) * k / (activeFontSize * lineHeightProportion));
  993. if (0 <= linesLeft && linesLeft < da.length + 1) {
  994. todo = da.splice(linesLeft - 1);
  995. }
  996. text = da.join(") Tj\nT* (");
  997. } else {
  998. throw new Error('Type of text must be string or Array. "' + text + '" is not recognized.');
  999. }
  1000. // Using "'" ("go next line and render text" mark) would save space but would complicate our rendering code, templates
  1001. // BT .. ET does NOT have default settings for Tf. You must state that explicitely every time for BT .. ET
  1002. // if you want text transformation matrix (+ multiline) to work reliably (which reads sizes of things from font declarations)
  1003. // Thus, there is NO useful, *reliable* concept of "default" font for a page.
  1004. // The fact that "default" (reuse font used before) font worked before in basic cases is an accident
  1005. // - readers dealing smartly with brokenness of jsPDF's markup.
  1006. out(
  1007. 'BT\n/' +
  1008. activeFontKey + ' ' + activeFontSize + ' Tf\n' + // font face, style, size
  1009. (activeFontSize * lineHeightProportion) + ' TL\n' + // line spacing
  1010. textColor +
  1011. '\n' + xtra + f2(x * k) + ' ' + f2((pageHeight - y) * k) + ' ' + mode + '\n(' +
  1012. text +
  1013. ') Tj\nET');
  1014. if (todo) {
  1015. this.addPage();
  1016. this.text(todo, x, activeFontSize * 1.7 / k);
  1017. }
  1018. return this;
  1019. };
  1020. API.lstext = function (text, x, y, spacing) {
  1021. for (var i = 0, len = text.length; i < len; i++ , x += spacing) this.text(text[i], x, y);
  1022. };
  1023. API.line = function (x1, y1, x2, y2) {
  1024. return this.lines([[x2 - x1, y2 - y1]], x1, y1);
  1025. };
  1026. API.clip = function () {
  1027. // By patrick-roberts, github.com/MrRio/jsPDF/issues/328
  1028. // Call .clip() after calling .rect() with a style argument of null
  1029. out('W') // clip
  1030. out('S') // stroke path; necessary for clip to work
  1031. };
  1032. /**
  1033. * Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates.
  1034. * All data points in `lines` are relative to last line origin.
  1035. * `x`, `y` become x1,y1 for first line / curve in the set.
  1036. * For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point.
  1037. * 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.
  1038. *
  1039. * @example .lines([[2,2],[-2,2],[1,1,2,2,3,3],[2,1]], 212,110, 10) // line, line, bezier curve, line
  1040. * @param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves).
  1041. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  1042. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  1043. * @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.
  1044. * @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.
  1045. * @param {Boolean} closed If true, the path is closed with a straight line from the end of the last curve to the starting point.
  1046. * @function
  1047. * @returns {jsPDF}
  1048. * @methodOf jsPDF#
  1049. * @name lines
  1050. */
  1051. API.lines = function (lines, x, y, scale, style, closed) {
  1052. var scalex, scaley, i, l, leg, x2, y2, x3, y3, x4, y4;
  1053. // Pre-August-2012 the order of arguments was function(x, y, lines, scale, style)
  1054. // in effort to make all calls have similar signature like
  1055. // function(content, coordinateX, coordinateY , miscellaneous)
  1056. // this method had its args flipped.
  1057. // code below allows backward compatibility with old arg order.
  1058. if (typeof lines === 'number') {
  1059. tmp = y;
  1060. y = x;
  1061. x = lines;
  1062. lines = tmp;
  1063. }
  1064. scale = scale || [1, 1];
  1065. // starting point
  1066. out(f3(x * k) + ' ' + f3((pageHeight - y) * k) + ' m ');
  1067. scalex = scale[0];
  1068. scaley = scale[1];
  1069. l = lines.length;
  1070. //, x2, y2 // bezier only. In page default measurement "units", *after* scaling
  1071. //, x3, y3 // bezier only. In page default measurement "units", *after* scaling
  1072. // ending point for all, lines and bezier. . In page default measurement "units", *after* scaling
  1073. x4 = x; // last / ending point = starting point for first item.
  1074. y4 = y; // last / ending point = starting point for first item.
  1075. for (i = 0; i < l; i++) {
  1076. leg = lines[i];
  1077. if (leg.length === 2) {
  1078. // simple line
  1079. x4 = leg[0] * scalex + x4; // here last x4 was prior ending point
  1080. y4 = leg[1] * scaley + y4; // here last y4 was prior ending point
  1081. out(f3(x4 * k) + ' ' + f3((pageHeight - y4) * k) + ' l');
  1082. } else {
  1083. // bezier curve
  1084. x2 = leg[0] * scalex + x4; // here last x4 is prior ending point
  1085. y2 = leg[1] * scaley + y4; // here last y4 is prior ending point
  1086. x3 = leg[2] * scalex + x4; // here last x4 is prior ending point
  1087. y3 = leg[3] * scaley + y4; // here last y4 is prior ending point
  1088. x4 = leg[4] * scalex + x4; // here last x4 was prior ending point
  1089. y4 = leg[5] * scaley + y4; // here last y4 was prior ending point
  1090. out(
  1091. f3(x2 * k) + ' ' +
  1092. f3((pageHeight - y2) * k) + ' ' +
  1093. f3(x3 * k) + ' ' +
  1094. f3((pageHeight - y3) * k) + ' ' +
  1095. f3(x4 * k) + ' ' +
  1096. f3((pageHeight - y4) * k) + ' c');
  1097. }
  1098. }
  1099. if (closed) {
  1100. out(' h');
  1101. }
  1102. // stroking / filling / both the path
  1103. if (style !== null) {
  1104. out(getStyle(style));
  1105. }
  1106. return this;
  1107. };
  1108. /**
  1109. * Adds a rectangle to PDF
  1110. *
  1111. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  1112. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  1113. * @param {Number} w Width (in units declared at inception of PDF document)
  1114. * @param {Number} h Height (in units declared at inception of PDF document)
  1115. * @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.
  1116. * @function
  1117. * @returns {jsPDF}
  1118. * @methodOf jsPDF#
  1119. * @name rect
  1120. */
  1121. API.rect = function (x, y, w, h, style) {
  1122. var op = getStyle(style);
  1123. out([
  1124. f2(x * k),
  1125. f2((pageHeight - y) * k),
  1126. f2(w * k),
  1127. f2(-h * k),
  1128. 're'
  1129. ].join(' '));
  1130. if (style !== null) {
  1131. out(getStyle(style));
  1132. }
  1133. return this;
  1134. };
  1135. /**
  1136. * Adds a triangle to PDF
  1137. *
  1138. * @param {Number} x1 Coordinate (in units declared at inception of PDF document) against left edge of the page
  1139. * @param {Number} y1 Coordinate (in units declared at inception of PDF document) against upper edge of the page
  1140. * @param {Number} x2 Coordinate (in units declared at inception of PDF document) against left edge of the page
  1141. * @param {Number} y2 Coordinate (in units declared at inception of PDF document) against upper edge of the page
  1142. * @param {Number} x3 Coordinate (in units declared at inception of PDF document) against left edge of the page
  1143. * @param {Number} y3 Coordinate (in units declared at inception of PDF document) against upper edge of the page
  1144. * @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.
  1145. * @function
  1146. * @returns {jsPDF}
  1147. * @methodOf jsPDF#
  1148. * @name triangle
  1149. */
  1150. API.triangle = function (x1, y1, x2, y2, x3, y3, style) {
  1151. this.lines(
  1152. [
  1153. [x2 - x1, y2 - y1], // vector to point 2
  1154. [x3 - x2, y3 - y2], // vector to point 3
  1155. [x1 - x3, y1 - y3]// closing vector back to point 1
  1156. ],
  1157. x1,
  1158. y1, // start of path
  1159. [1, 1],
  1160. style,
  1161. true);
  1162. return this;
  1163. };
  1164. /**
  1165. * Adds a rectangle with rounded corners to PDF
  1166. *
  1167. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  1168. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  1169. * @param {Number} w Width (in units declared at inception of PDF document)
  1170. * @param {Number} h Height (in units declared at inception of PDF document)
  1171. * @param {Number} rx Radius along x axis (in units declared at inception of PDF document)
  1172. * @param {Number} rx Radius along y axis (in units declared at inception of PDF document)
  1173. * @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.
  1174. * @function
  1175. * @returns {jsPDF}
  1176. * @methodOf jsPDF#
  1177. * @name roundedRect
  1178. */
  1179. API.roundedRect = function (x, y, w, h, rx, ry, style) {
  1180. var MyArc = 4 / 3 * (Math.SQRT2 - 1);
  1181. this.lines(
  1182. [
  1183. [(w - 2 * rx), 0],
  1184. [(rx * MyArc), 0, rx, ry - (ry * MyArc), rx, ry],
  1185. [0, (h - 2 * ry)],
  1186. [0, (ry * MyArc), - (rx * MyArc), ry, -rx, ry],
  1187. [(-w + 2 * rx), 0],
  1188. [- (rx * MyArc), 0, -rx, - (ry * MyArc), -rx, -ry],
  1189. [0, (-h + 2 * ry)],
  1190. [0, - (ry * MyArc), (rx * MyArc), -ry, rx, -ry]
  1191. ],
  1192. x + rx,
  1193. y, // start of path
  1194. [1, 1],
  1195. style);
  1196. return this;
  1197. };
  1198. /**
  1199. * Adds an ellipse to PDF
  1200. *
  1201. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  1202. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  1203. * @param {Number} rx Radius along x axis (in units declared at inception of PDF document)
  1204. * @param {Number} rx Radius along y axis (in units declared at inception of PDF document)
  1205. * @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.
  1206. * @function
  1207. * @returns {jsPDF}
  1208. * @methodOf jsPDF#
  1209. * @name ellipse
  1210. */
  1211. API.ellipse = function (x, y, rx, ry, style) {
  1212. var lx = 4 / 3 * (Math.SQRT2 - 1) * rx,
  1213. ly = 4 / 3 * (Math.SQRT2 - 1) * ry;
  1214. out([
  1215. f2((x + rx) * k),
  1216. f2((pageHeight - y) * k),
  1217. 'm',
  1218. f2((x + rx) * k),
  1219. f2((pageHeight - (y - ly)) * k),
  1220. f2((x + lx) * k),
  1221. f2((pageHeight - (y - ry)) * k),
  1222. f2(x * k),
  1223. f2((pageHeight - (y - ry)) * k),
  1224. 'c'
  1225. ].join(' '));
  1226. out([
  1227. f2((x - lx) * k),
  1228. f2((pageHeight - (y - ry)) * k),
  1229. f2((x - rx) * k),
  1230. f2((pageHeight - (y - ly)) * k),
  1231. f2((x - rx) * k),
  1232. f2((pageHeight - y) * k),
  1233. 'c'
  1234. ].join(' '));
  1235. out([
  1236. f2((x - rx) * k),
  1237. f2((pageHeight - (y + ly)) * k),
  1238. f2((x - lx) * k),
  1239. f2((pageHeight - (y + ry)) * k),
  1240. f2(x * k),
  1241. f2((pageHeight - (y + ry)) * k),
  1242. 'c'
  1243. ].join(' '));
  1244. out([
  1245. f2((x + lx) * k),
  1246. f2((pageHeight - (y + ry)) * k),
  1247. f2((x + rx) * k),
  1248. f2((pageHeight - (y + ly)) * k),
  1249. f2((x + rx) * k),
  1250. f2((pageHeight - y) * k),
  1251. 'c'
  1252. ].join(' '));
  1253. if (style !== null) {
  1254. out(getStyle(style));
  1255. }
  1256. return this;
  1257. };
  1258. /**
  1259. * Adds an circle to PDF
  1260. *
  1261. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  1262. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  1263. * @param {Number} r Radius (in units declared at inception of PDF document)
  1264. * @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.
  1265. * @function
  1266. * @returns {jsPDF}
  1267. * @methodOf jsPDF#
  1268. * @name circle
  1269. */
  1270. API.circle = function (x, y, r, style) {
  1271. return this.ellipse(x, y, r, r, style);
  1272. };
  1273. /**
  1274. * Adds a properties to the PDF document
  1275. *
  1276. * @param {Object} A property_name-to-property_value object structure.
  1277. * @function
  1278. * @returns {jsPDF}
  1279. * @methodOf jsPDF#
  1280. * @name setProperties
  1281. */
  1282. API.setProperties = function (properties) {
  1283. // copying only those properties we can render.
  1284. for (var property in documentProperties) {
  1285. if (documentProperties.hasOwnProperty(property) && properties[property]) {
  1286. documentProperties[property] = properties[property];
  1287. }
  1288. }
  1289. return this;
  1290. };
  1291. /**
  1292. * Sets font size for upcoming text elements.
  1293. *
  1294. * @param {Number} size Font size in points.
  1295. * @function
  1296. * @returns {jsPDF}
  1297. * @methodOf jsPDF#
  1298. * @name setFontSize
  1299. */
  1300. API.setFontSize = function (size) {
  1301. activeFontSize = size;
  1302. return this;
  1303. };
  1304. /**
  1305. * Sets text font face, variant for upcoming text elements.
  1306. * See output of jsPDF.getFontList() for possible font names, styles.
  1307. *
  1308. * @param {String} fontName Font name or family. Example: "times"
  1309. * @param {String} fontStyle Font style or variant. Example: "italic"
  1310. * @function
  1311. * @returns {jsPDF}
  1312. * @methodOf jsPDF#
  1313. * @name setFont
  1314. */
  1315. API.setFont = function (fontName, fontStyle) {
  1316. activeFontKey = getFont(fontName, fontStyle);
  1317. // if font is not found, the above line blows up and we never go further
  1318. return this;
  1319. };
  1320. /**
  1321. * Switches font style or variant for upcoming text elements,
  1322. * while keeping the font face or family same.
  1323. * See output of jsPDF.getFontList() for possible font names, styles.
  1324. *
  1325. * @param {String} style Font style or variant. Example: "italic"
  1326. * @function
  1327. * @returns {jsPDF}
  1328. * @methodOf jsPDF#
  1329. * @name setFontStyle
  1330. */
  1331. API.setFontStyle = API.setFontType = function (style) {
  1332. activeFontKey = getFont(undefined, style);
  1333. // if font is not found, the above line blows up and we never go further
  1334. return this;
  1335. };
  1336. /**
  1337. * Returns an object - a tree of fontName to fontStyle relationships available to
  1338. * active PDF document.
  1339. *
  1340. * @public
  1341. * @function
  1342. * @returns {Object} Like {'times':['normal', 'italic', ... ], 'arial':['normal', 'bold', ... ], ... }
  1343. * @methodOf jsPDF#
  1344. * @name getFontList
  1345. */
  1346. API.getFontList = function () {
  1347. // TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added.
  1348. var list = {}, fontName, fontStyle, tmp;
  1349. for (fontName in fontmap) {
  1350. if (fontmap.hasOwnProperty(fontName)) {
  1351. list[fontName] = tmp = [];
  1352. for (fontStyle in fontmap[fontName]) {
  1353. if (fontmap[fontName].hasOwnProperty(fontStyle)) {
  1354. tmp.push(fontStyle);
  1355. }
  1356. }
  1357. }
  1358. }
  1359. return list;
  1360. };
  1361. /**
  1362. * Sets line width for upcoming lines.
  1363. *
  1364. * @param {Number} width Line width (in units declared at inception of PDF document)
  1365. * @function
  1366. * @returns {jsPDF}
  1367. * @methodOf jsPDF#
  1368. * @name setLineWidth
  1369. */
  1370. API.setLineWidth = function (width) {
  1371. out((width * k).toFixed(2) + ' w');
  1372. return this;
  1373. };
  1374. /**
  1375. * Sets the stroke color for upcoming elements.
  1376. *
  1377. * Depending on the number of arguments given, Gray, RGB, or CMYK
  1378. * color space is implied.
  1379. *
  1380. * When only ch1 is given, "Gray" color space is implied and it
  1381. * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
  1382. * if values are communicated as String types, or in range from 0 (black)
  1383. * to 255 (white) if communicated as Number type.
  1384. * The RGB-like 0-255 range is provided for backward compatibility.
  1385. *
  1386. * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
  1387. * value must be in the range from 0.00 (minimum intensity) to to 1.00
  1388. * (max intensity) if values are communicated as String types, or
  1389. * from 0 (min intensity) to to 255 (max intensity) if values are communicated
  1390. * as Number types.
  1391. * The RGB-like 0-255 range is provided for backward compatibility.
  1392. *
  1393. * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
  1394. * value must be a in the range from 0.00 (0% concentration) to to
  1395. * 1.00 (100% concentration)
  1396. *
  1397. * Because JavaScript treats fixed point numbers badly (rounds to
  1398. * floating point nearest to binary representation) it is highly advised to
  1399. * communicate the fractional numbers as String types, not JavaScript Number type.
  1400. *
  1401. * @param {Number|String} ch1 Color channel value
  1402. * @param {Number|String} ch2 Color channel value
  1403. * @param {Number|String} ch3 Color channel value
  1404. * @param {Number|String} ch4 Color channel value
  1405. *
  1406. * @function
  1407. * @returns {jsPDF}
  1408. * @methodOf jsPDF#
  1409. * @name setDrawColor
  1410. */
  1411. API.setDrawColor = function (ch1, ch2, ch3, ch4) {
  1412. var color;
  1413. if (ch2 === undefined || (ch4 === undefined && ch1 === ch2 === ch3)) {
  1414. // Gray color space.
  1415. if (typeof ch1 === 'string') {
  1416. color = ch1 + ' G';
  1417. } else {
  1418. color = f2(ch1 / 255) + ' G';
  1419. }
  1420. } else if (ch4 === undefined) {
  1421. // RGB
  1422. if (typeof ch1 === 'string') {
  1423. color = [ch1, ch2, ch3, 'RG'].join(' ');
  1424. } else {
  1425. color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), 'RG'].join(' ');
  1426. }
  1427. } else {
  1428. // CMYK
  1429. if (typeof ch1 === 'string') {
  1430. color = [ch1, ch2, ch3, ch4, 'K'].join(' ');
  1431. } else {
  1432. color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), 'K'].join(' ');
  1433. }
  1434. }
  1435. out(color);
  1436. return this;
  1437. };
  1438. /**
  1439. * Sets the fill color for upcoming elements.
  1440. *
  1441. * Depending on the number of arguments given, Gray, RGB, or CMYK
  1442. * color space is implied.
  1443. *
  1444. * When only ch1 is given, "Gray" color space is implied and it
  1445. * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
  1446. * if values are communicated as String types, or in range from 0 (black)
  1447. * to 255 (white) if communicated as Number type.
  1448. * The RGB-like 0-255 range is provided for backward compatibility.
  1449. *
  1450. * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
  1451. * value must be in the range from 0.00 (minimum intensity) to to 1.00
  1452. * (max intensity) if values are communicated as String types, or
  1453. * from 0 (min intensity) to to 255 (max intensity) if values are communicated
  1454. * as Number types.
  1455. * The RGB-like 0-255 range is provided for backward compatibility.
  1456. *
  1457. * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
  1458. * value must be a in the range from 0.00 (0% concentration) to to
  1459. * 1.00 (100% concentration)
  1460. *
  1461. * Because JavaScript treats fixed point numbers badly (rounds to
  1462. * floating point nearest to binary representation) it is highly advised to
  1463. * communicate the fractional numbers as String types, not JavaScript Number type.
  1464. *
  1465. * @param {Number|String} ch1 Color channel value
  1466. * @param {Number|String} ch2 Color channel value
  1467. * @param {Number|String} ch3 Color channel value
  1468. * @param {Number|String} ch4 Color channel value
  1469. *
  1470. * @function
  1471. * @returns {jsPDF}
  1472. * @methodOf jsPDF#
  1473. * @name setFillColor
  1474. */
  1475. API.setFillColor = function (ch1, ch2, ch3, ch4) {
  1476. var color;
  1477. if (ch2 === undefined || (ch4 === undefined && ch1 === ch2 === ch3)) {
  1478. // Gray color space.
  1479. if (typeof ch1 === 'string') {
  1480. color = ch1 + ' g';
  1481. } else {
  1482. color = f2(ch1 / 255) + ' g';
  1483. }
  1484. } else if (ch4 === undefined) {
  1485. // RGB
  1486. if (typeof ch1 === 'string') {
  1487. color = [ch1, ch2, ch3, 'rg'].join(' ');
  1488. } else {
  1489. color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), 'rg'].join(' ');
  1490. }
  1491. } else {
  1492. // CMYK
  1493. if (typeof ch1 === 'string') {
  1494. color = [ch1, ch2, ch3, ch4, 'k'].join(' ');
  1495. } else {
  1496. color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), 'k'].join(' ');
  1497. }
  1498. }
  1499. out(color);
  1500. return this;
  1501. };
  1502. /**
  1503. * Sets the text color for upcoming elements.
  1504. * If only one, first argument is given,
  1505. * treats the value as gray-scale color value.
  1506. *
  1507. * @param {Number} r Red channel color value in range 0-255 or {String} r color value in hexadecimal, example: '#FFFFFF'
  1508. * @param {Number} g Green channel color value in range 0-255
  1509. * @param {Number} b Blue channel color value in range 0-255
  1510. * @function
  1511. * @returns {jsPDF}
  1512. * @methodOf jsPDF#
  1513. * @name setTextColor
  1514. */
  1515. API.setTextColor = function (r, g, b) {
  1516. if ((typeof r === 'string') && /^#[0-9A-Fa-f]{6}$/.test(r)) {
  1517. var hex = parseInt(r.substr(1), 16);
  1518. r = (hex >> 16) & 255;
  1519. g = (hex >> 8) & 255;
  1520. b = (hex & 255);
  1521. }
  1522. if ((r === 0 && g === 0 && b === 0) || (typeof g === 'undefined')) {
  1523. textColor = f3(r / 255) + ' g';
  1524. } else {
  1525. textColor = [f3(r / 255), f3(g / 255), f3(b / 255), 'rg'].join(' ');
  1526. }
  1527. return this;
  1528. };
  1529. /**
  1530. * Is an Object providing a mapping from human-readable to
  1531. * integer flag values designating the varieties of line cap
  1532. * and join styles.
  1533. *
  1534. * @returns {Object}
  1535. * @fieldOf jsPDF#
  1536. * @name CapJoinStyles
  1537. */
  1538. API.CapJoinStyles = {
  1539. 0: 0,
  1540. 'butt': 0,
  1541. 'but': 0,
  1542. 'miter': 0,
  1543. 1: 1,
  1544. 'round': 1,
  1545. 'rounded': 1,
  1546. 'circle': 1,
  1547. 2: 2,
  1548. 'projecting': 2,
  1549. 'project': 2,
  1550. 'square': 2,
  1551. 'bevel': 2
  1552. };
  1553. /**
  1554. * Sets the line cap styles
  1555. * See {jsPDF.CapJoinStyles} for variants
  1556. *
  1557. * @param {String|Number} style A string or number identifying the type of line cap
  1558. * @function
  1559. * @returns {jsPDF}
  1560. * @methodOf jsPDF#
  1561. * @name setLineCap
  1562. */
  1563. API.setLineCap = function (style) {
  1564. var id = this.CapJoinStyles[style];
  1565. if (id === undefined) {
  1566. throw new Error("Line cap style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
  1567. }
  1568. lineCapID = id;
  1569. out(id + ' J');
  1570. return this;
  1571. };
  1572. /**
  1573. * Sets the line join styles
  1574. * See {jsPDF.CapJoinStyles} for variants
  1575. *
  1576. * @param {String|Number} style A string or number identifying the type of line join
  1577. * @function
  1578. * @returns {jsPDF}
  1579. * @methodOf jsPDF#
  1580. * @name setLineJoin
  1581. */
  1582. API.setLineJoin = function (style) {
  1583. var id = this.CapJoinStyles[style];
  1584. if (id === undefined) {
  1585. throw new Error("Line join style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
  1586. }
  1587. lineJoinID = id;
  1588. out(id + ' j');
  1589. return this;
  1590. };
  1591. // Output is both an internal (for plugins) and external function
  1592. API.output = output;
  1593. /**
  1594. * Saves as PDF document. An alias of jsPDF.output('save', 'filename.pdf')
  1595. * @param {String} filename The filename including extension.
  1596. *
  1597. * @function
  1598. * @returns {jsPDF}
  1599. * @methodOf jsPDF#
  1600. * @name save
  1601. */
  1602. API.save = function (filename) {
  1603. API.output('save', filename);
  1604. };
  1605. // applying plugins (more methods) ON TOP of built-in API.
  1606. // this is intentional as we allow plugins to override
  1607. // built-ins
  1608. for (var plugin in jsPDF.API) {
  1609. if (jsPDF.API.hasOwnProperty(plugin)) {
  1610. if (plugin === 'events' && jsPDF.API.events.length) {
  1611. (function (events, newEvents) {
  1612. // jsPDF.API.events is a JS Array of Arrays
  1613. // where each Array is a pair of event name, handler
  1614. // Events were added by plugins to the jsPDF instantiator.
  1615. // These are always added to the new instance and some ran
  1616. // during instantiation.
  1617. var eventname, handler_and_args, i;
  1618. for (i = newEvents.length - 1; i !== -1; i--) {
  1619. // subscribe takes 3 args: 'topic', function, runonce_flag
  1620. // if undefined, runonce is false.
  1621. // users can attach callback directly,
  1622. // or they can attach an array with [callback, runonce_flag]
  1623. // that's what the "apply" magic is for below.
  1624. eventname = newEvents[i][0];
  1625. handler_and_args = newEvents[i][1];
  1626. events.subscribe.apply(
  1627. events,
  1628. [eventname].concat(
  1629. typeof handler_and_args === 'function' ?
  1630. [handler_and_args] : handler_and_args));
  1631. }
  1632. }(events, jsPDF.API.events));
  1633. } else {
  1634. API[plugin] = jsPDF.API[plugin];
  1635. }
  1636. }
  1637. }
  1638. //////////////////////////////////////////////////////
  1639. // continuing initialization of jsPDF Document object
  1640. //////////////////////////////////////////////////////
  1641. // Add the first page automatically
  1642. addFonts();
  1643. activeFontKey = 'F1';
  1644. _addPage(format, orientation);
  1645. events.publish('initialized');
  1646. return API;
  1647. }
  1648. /**
  1649. * jsPDF.API is a STATIC property of jsPDF class.
  1650. * jsPDF.API is an object you can add methods and properties to.
  1651. * The methods / properties you add will show up in new jsPDF objects.
  1652. *
  1653. * One property is prepopulated. It is the 'events' Object. Plugin authors can add topics,
  1654. * callbacks to this object. These will be reassigned to all new instances of jsPDF.
  1655. * Examples:
  1656. * jsPDF.API.events['initialized'] = function(){ 'this' is API object }
  1657. * jsPDF.API.events['addFont'] = function(added_font_object){ 'this' is API object }
  1658. *
  1659. * @static
  1660. * @public
  1661. * @memberOf jsPDF
  1662. * @name API
  1663. *
  1664. * @example
  1665. * jsPDF.API.mymethod = function(){
  1666. * // 'this' will be ref to internal API object. see jsPDF source
  1667. * // , so you can refer to built-in methods like so:
  1668. * // this.line(....)
  1669. * // this.text(....)
  1670. * }
  1671. * var pdfdoc = new jsPDF()
  1672. * pdfdoc.mymethod() // <- !!!!!!
  1673. */
  1674. jsPDF.API = { events: [] };
  1675. jsPDF.version = "1.0.272-debug 2014-09-29T15:09:diegocr";
  1676. if (typeof define === 'function' && define.amd) {
  1677. define('jsPDF', function () {
  1678. return jsPDF;
  1679. });
  1680. } else {
  1681. global.jsPDF = jsPDF;
  1682. }
  1683. return jsPDF;
  1684. }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this));
  1685. /**
  1686. * jsPDF addHTML PlugIn
  1687. * Copyright (c) 2014 Diego Casorran
  1688. *
  1689. * Licensed under the MIT License.
  1690. * http://opensource.org/licenses/mit-license
  1691. */
  1692. (function (jsPDFAPI) {
  1693. 'use strict';
  1694. /**
  1695. * Renders an HTML element to canvas object which added as an image to the PDF
  1696. *
  1697. * This PlugIn requires html2canvas: https://github.com/niklasvh/html2canvas
  1698. * OR rasterizeHTML: https://github.com/cburgmer/rasterizeHTML.js
  1699. *
  1700. * @public
  1701. * @function
  1702. * @param element {Mixed} HTML Element, or anything supported by html2canvas.
  1703. * @param x {Number} starting X coordinate in jsPDF instance's declared units.
  1704. * @param y {Number} starting Y coordinate in jsPDF instance's declared units.
  1705. * @param options {Object} Additional options, check the code below.
  1706. * @param callback {Function} to call when the rendering has finished.
  1707. *
  1708. * NOTE: Every parameter is optional except 'element' and 'callback', in such
  1709. * case the image is positioned at 0x0 covering the whole PDF document
  1710. * size. Ie, to easily take screenshoots of webpages saving them to PDF.
  1711. */
  1712. jsPDFAPI.addHTML = function (element, x, y, options, callback) {
  1713. 'use strict';
  1714. if (typeof html2canvas === 'undefined' && typeof rasterizeHTML === 'undefined')
  1715. throw new Error('You need either '
  1716. + 'https://github.com/niklasvh/html2canvas'
  1717. + ' or https://github.com/cburgmer/rasterizeHTML.js');
  1718. if (typeof x !== 'number') {
  1719. options = x;
  1720. callback = y;
  1721. }
  1722. if (typeof options === 'function') {
  1723. callback = options;
  1724. options = null;
  1725. }
  1726. var I = this.internal, K = I.scaleFactor, W = I.pageSize.width, H = I.pageSize.height;
  1727. options = options || {};
  1728. options.onrendered = function (obj) {
  1729. x = parseInt(x) || 0;
  1730. y = parseInt(y) || 0;
  1731. var dim = options.dim || {};
  1732. var h = dim.h || 0;
  1733. var w = dim.w || Math.min(W, obj.width / K) - x;
  1734. var format = 'JPEG';
  1735. if (options.format)
  1736. format = options.format;
  1737. if (obj.height > H && options.pagesplit) {
  1738. var crop = function () {
  1739. var cy = 0;
  1740. while (1) {
  1741. var canvas = document.createElement('canvas');
  1742. canvas.width = Math.min(W * K, obj.width);
  1743. canvas.height = Math.min(H * K, obj.height - cy);
  1744. var ctx = canvas.getContext('2d');
  1745. ctx.drawImage(obj, 0, cy, obj.width, canvas.height, 0, 0, canvas.width, canvas.height);
  1746. var args = [canvas, x, cy ? 0 : y, canvas.width / K, canvas.height / K, format, null, 'SLOW'];
  1747. this.addImage.apply(this, args);
  1748. cy += canvas.height;
  1749. if (cy >= obj.height) break;
  1750. this.addPage();
  1751. }
  1752. callback(w, cy, null, args);
  1753. }.bind(this);
  1754. if (obj.nodeName === 'CANVAS') {
  1755. var img = new Image();
  1756. img.onload = crop;
  1757. img.src = obj.toDataURL("image/png");
  1758. obj = img;
  1759. } else {
  1760. crop();
  1761. }
  1762. } else {
  1763. var alias = Math.random().toString(35);
  1764. var args = [obj, x, y, w, h, format, alias, 'SLOW'];
  1765. this.addImage.apply(this, args);
  1766. callback(w, h, alias, args);
  1767. }
  1768. }.bind(this);
  1769. if (typeof html2canvas !== 'undefined' && !options.rstz) {
  1770. return html2canvas(element, options);
  1771. }
  1772. if (typeof rasterizeHTML !== 'undefined') {
  1773. var meth = 'drawDocument';
  1774. if (typeof element === 'string') {
  1775. meth = /^http/.test(element) ? 'drawURL' : 'drawHTML';
  1776. }
  1777. options.width = options.width || (W * K);
  1778. return rasterizeHTML[meth](element, void 0, options).then(function (r) {
  1779. options.onrendered(r.image);
  1780. }, function (e) {
  1781. callback(null, e);
  1782. });
  1783. }
  1784. return null;
  1785. };
  1786. })(jsPDF.API);
  1787. /** @preserve
  1788. * jsPDF addImage plugin
  1789. * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/
  1790. * 2013 Chris Dowling, https://github.com/gingerchris
  1791. * 2013 Trinh Ho, https://github.com/ineedfat
  1792. * 2013 Edwin Alejandro Perez, https://github.com/eaparango
  1793. * 2013 Norah Smith, https://github.com/burnburnrocket
  1794. * 2014 Diego Casorran, https://github.com/diegocr
  1795. * 2014 James Robb, https://github.com/jamesbrobb
  1796. *
  1797. * Permission is hereby granted, free of charge, to any person obtaining
  1798. * a copy of this software and associated documentation files (the
  1799. * "Software"), to deal in the Software without restriction, including
  1800. * without limitation the rights to use, copy, modify, merge, publish,
  1801. * distribute, sublicense, and/or sell copies of the Software, and to
  1802. * permit persons to whom the Software is furnished to do so, subject to
  1803. * the following conditions:
  1804. *
  1805. * The above copyright notice and this permission notice shall be
  1806. * included in all copies or substantial portions of the Software.
  1807. *
  1808. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  1809. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  1810. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  1811. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  1812. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  1813. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  1814. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  1815. */
  1816. ; (function (jsPDFAPI) {
  1817. 'use strict'
  1818. var namespace = 'addImage_',
  1819. supported_image_types = ['jpeg', 'jpg', 'png'];
  1820. // Image functionality ported from pdf.js
  1821. var putImage = function (img) {
  1822. var objectNumber = this.internal.newObject()
  1823. , out = this.internal.write
  1824. , putStream = this.internal.putStream
  1825. img['n'] = objectNumber
  1826. out('<</Type /XObject')
  1827. out('/Subtype /Image')
  1828. out('/Width ' + img['w'])
  1829. out('/Height ' + img['h'])
  1830. if (img['cs'] === this.color_spaces.INDEXED) {
  1831. out('/ColorSpace [/Indexed /DeviceRGB '
  1832. // if an indexed png defines more than one colour with transparency, we've created a smask
  1833. + (img['pal'].length / 3 - 1) + ' ' + ('smask' in img ? objectNumber + 2 : objectNumber + 1)
  1834. + ' 0 R]');
  1835. } else {
  1836. out('/ColorSpace /' + img['cs']);
  1837. if (img['cs'] === this.color_spaces.DEVICE_CMYK) {
  1838. out('/Decode [1 0 1 0 1 0 1 0]');
  1839. }
  1840. }
  1841. out('/BitsPerComponent ' + img['bpc']);
  1842. if ('f' in img) {
  1843. out('/Filter /' + img['f']);
  1844. }
  1845. if ('dp' in img) {
  1846. out('/DecodeParms <<' + img['dp'] + '>>');
  1847. }
  1848. if ('trns' in img && img['trns'].constructor == Array) {
  1849. var trns = '',
  1850. i = 0,
  1851. len = img['trns'].length;
  1852. for (; i < len; i++)
  1853. trns += (img['trns'][i] + ' ' + img['trns'][i] + ' ');
  1854. out('/Mask [' + trns + ']');
  1855. }
  1856. if ('smask' in img) {
  1857. out('/SMask ' + (objectNumber + 1) + ' 0 R');
  1858. }
  1859. out('/Length ' + img['data'].length + '>>');
  1860. putStream(img['data']);
  1861. out('endobj');
  1862. // Soft mask
  1863. if ('smask' in img) {
  1864. var dp = '/Predictor 15 /Colors 1 /BitsPerComponent ' + img['bpc'] + ' /Columns ' + img['w'];
  1865. var smask = { 'w': img['w'], 'h': img['h'], 'cs': 'DeviceGray', 'bpc': img['bpc'], 'dp': dp, 'data': img['smask'] };
  1866. if ('f' in img)
  1867. smask.f = img['f'];
  1868. putImage.call(this, smask);
  1869. }
  1870. //Palette
  1871. if (img['cs'] === this.color_spaces.INDEXED) {
  1872. this.internal.newObject();
  1873. //out('<< /Filter / ' + img['f'] +' /Length ' + img['pal'].length + '>>');
  1874. //putStream(zlib.compress(img['pal']));
  1875. out('<< /Length ' + img['pal'].length + '>>');
  1876. putStream(this.arrayBufferToBinaryString(new Uint8Array(img['pal'])));
  1877. out('endobj');
  1878. }
  1879. }
  1880. , putResourcesCallback = function () {
  1881. var images = this.internal.collections[namespace + 'images']
  1882. for (var i in images) {
  1883. putImage.call(this, images[i])
  1884. }
  1885. }
  1886. , putXObjectsDictCallback = function () {
  1887. var images = this.internal.collections[namespace + 'images']
  1888. , out = this.internal.write
  1889. , image
  1890. for (var i in images) {
  1891. image = images[i]
  1892. out(
  1893. '/I' + image['i']
  1894. , image['n']
  1895. , '0'
  1896. , 'R'
  1897. )
  1898. }
  1899. }
  1900. , checkCompressValue = function (value) {
  1901. if (value && typeof value === 'string')
  1902. value = value.toUpperCase();
  1903. return value in jsPDFAPI.image_compression ? value : jsPDFAPI.image_compression.NONE;
  1904. }
  1905. , getImages = function () {
  1906. var images = this.internal.collections[namespace + 'images'];
  1907. //first run, so initialise stuff
  1908. if (!images) {
  1909. this.internal.collections[namespace + 'images'] = images = {};
  1910. this.internal.events.subscribe('putResources', putResourcesCallback);
  1911. this.internal.events.subscribe('putXobjectDict', putXObjectsDictCallback);
  1912. }
  1913. return images;
  1914. }
  1915. , getImageIndex = function (images) {
  1916. var imageIndex = 0;
  1917. if (images) {
  1918. // this is NOT the first time this method is ran on this instance of jsPDF object.
  1919. imageIndex = Object.keys ?
  1920. Object.keys(images).length :
  1921. (function (o) {
  1922. var i = 0
  1923. for (var e in o) { if (o.hasOwnProperty(e)) { i++ } }
  1924. return i
  1925. })(images)
  1926. }
  1927. return imageIndex;
  1928. }
  1929. , notDefined = function (value) {
  1930. return typeof value === 'undefined' || value === null;
  1931. }
  1932. , generateAliasFromData = function (data) {
  1933. return typeof data === 'string' && jsPDFAPI.sHashCode(data);
  1934. }
  1935. , doesNotSupportImageType = function (type) {
  1936. return supported_image_types.indexOf(type) === -1;
  1937. }
  1938. , processMethodNotEnabled = function (type) {
  1939. return typeof jsPDFAPI['process' + type.toUpperCase()] !== 'function';
  1940. }
  1941. , isDOMElement = function (object) {
  1942. return typeof object === 'object' && object.nodeType === 1;
  1943. }
  1944. , createDataURIFromElement = function (element, format, angle) {
  1945. //if element is an image which uses data url defintion, just return the dataurl
  1946. if (element.nodeName === 'IMG' && element.hasAttribute('src')) {
  1947. var src = '' + element.getAttribute('src');
  1948. if (!angle && src.indexOf('data:image/') === 0) return src;
  1949. // only if the user doesn't care about a format
  1950. if (!format && /\.png(?:[?#].*)?$/i.test(src)) format = 'png';
  1951. }
  1952. if (element.nodeName === 'CANVAS') {
  1953. var canvas = element;
  1954. } else {
  1955. var canvas = document.createElement('canvas');
  1956. canvas.width = element.clientWidth || element.width;
  1957. canvas.height = element.clientHeight || element.height;
  1958. var ctx = canvas.getContext('2d');
  1959. if (!ctx) {
  1960. throw ('addImage requires canvas to be supported by browser.');
  1961. }
  1962. if (angle) {
  1963. var x, y, b, c, s, w, h, to_radians = Math.PI / 180, angleInRadians;
  1964. if (typeof angle === 'object') {
  1965. x = angle.x;
  1966. y = angle.y;
  1967. b = angle.bg;
  1968. angle = angle.angle;
  1969. }
  1970. angleInRadians = angle * to_radians;
  1971. c = Math.abs(Math.cos(angleInRadians));
  1972. s = Math.abs(Math.sin(angleInRadians));
  1973. w = canvas.width;
  1974. h = canvas.height;
  1975. canvas.width = h * s + w * c;
  1976. canvas.height = h * c + w * s;
  1977. if (isNaN(x)) x = canvas.width / 2;
  1978. if (isNaN(y)) y = canvas.height / 2;
  1979. ctx.clearRect(0, 0, canvas.width, canvas.height);
  1980. ctx.fillStyle = b || 'white';
  1981. ctx.fillRect(0, 0, canvas.width, canvas.height);
  1982. ctx.save();
  1983. ctx.translate(x, y);
  1984. ctx.rotate(angleInRadians);
  1985. ctx.drawImage(element, -(w / 2), -(h / 2));
  1986. ctx.rotate(-angleInRadians);
  1987. ctx.translate(-x, -y);
  1988. ctx.restore();
  1989. } else {
  1990. ctx.drawImage(element, 0, 0, canvas.width, canvas.height);
  1991. }
  1992. }
  1993. return canvas.toDataURL(('' + format).toLowerCase() == 'png' ? 'image/png' : 'image/jpeg');
  1994. }
  1995. , checkImagesForAlias = function (alias, images) {
  1996. var cached_info;
  1997. if (images) {
  1998. for (var e in images) {
  1999. if (alias === images[e].alias) {
  2000. cached_info = images[e];
  2001. break;
  2002. }
  2003. }
  2004. }
  2005. return cached_info;
  2006. }
  2007. , determineWidthAndHeight = function (w, h, info) {
  2008. if (!w && !h) {
  2009. w = -96;
  2010. h = -96;
  2011. }
  2012. if (w < 0) {
  2013. w = (-1) * info['w'] * 72 / w / this.internal.scaleFactor;
  2014. }
  2015. if (h < 0) {
  2016. h = (-1) * info['h'] * 72 / h / this.internal.scaleFactor;
  2017. }
  2018. if (w === 0) {
  2019. w = h * info['w'] / info['h'];
  2020. }
  2021. if (h === 0) {
  2022. h = w * info['h'] / info['w'];
  2023. }
  2024. return [w, h];
  2025. }
  2026. , writeImageToPDF = function (x, y, w, h, info, index, images) {
  2027. var dims = determineWidthAndHeight.call(this, w, h, info),
  2028. coord = this.internal.getCoordinateString,
  2029. vcoord = this.internal.getVerticalCoordinateString;
  2030. w = dims[0];
  2031. h = dims[1];
  2032. images[index] = info;
  2033. this.internal.write(
  2034. 'q'
  2035. , coord(w)
  2036. , '0 0'
  2037. , coord(h) // TODO: check if this should be shifted by vcoord
  2038. , coord(x)
  2039. , vcoord(y + h)
  2040. , 'cm /I' + info['i']
  2041. , 'Do Q'
  2042. )
  2043. };
  2044. /**
  2045. * COLOR SPACES
  2046. */
  2047. jsPDFAPI.color_spaces = {
  2048. DEVICE_RGB: 'DeviceRGB',
  2049. DEVICE_GRAY: 'DeviceGray',
  2050. DEVICE_CMYK: 'DeviceCMYK',
  2051. CAL_GREY: 'CalGray',
  2052. CAL_RGB: 'CalRGB',
  2053. LAB: 'Lab',
  2054. ICC_BASED: 'ICCBased',
  2055. INDEXED: 'Indexed',
  2056. PATTERN: 'Pattern',
  2057. SEPERATION: 'Seperation',
  2058. DEVICE_N: 'DeviceN'
  2059. };
  2060. /**
  2061. * DECODE METHODS
  2062. */
  2063. jsPDFAPI.decode = {
  2064. DCT_DECODE: 'DCTDecode',
  2065. FLATE_DECODE: 'FlateDecode',
  2066. LZW_DECODE: 'LZWDecode',
  2067. JPX_DECODE: 'JPXDecode',
  2068. JBIG2_DECODE: 'JBIG2Decode',
  2069. ASCII85_DECODE: 'ASCII85Decode',
  2070. ASCII_HEX_DECODE: 'ASCIIHexDecode',
  2071. RUN_LENGTH_DECODE: 'RunLengthDecode',
  2072. CCITT_FAX_DECODE: 'CCITTFaxDecode'
  2073. };
  2074. /**
  2075. * IMAGE COMPRESSION TYPES
  2076. */
  2077. jsPDFAPI.image_compression = {
  2078. NONE: 'NONE',
  2079. FAST: 'FAST',
  2080. MEDIUM: 'MEDIUM',
  2081. SLOW: 'SLOW'
  2082. };
  2083. jsPDFAPI.sHashCode = function (str) {
  2084. return Array.prototype.reduce && str.split("").reduce(function (a, b) { a = ((a << 5) - a) + b.charCodeAt(0); return a & a }, 0);
  2085. };
  2086. jsPDFAPI.isString = function (object) {
  2087. return typeof object === 'string';
  2088. };
  2089. /**
  2090. * Strips out and returns info from a valid base64 data URI
  2091. * @param {String[dataURI]} a valid data URI of format 'data:[<MIME-type>][;base64],<data>'
  2092. * @returns an Array containing the following
  2093. * [0] the complete data URI
  2094. * [1] <MIME-type>
  2095. * [2] format - the second part of the mime-type i.e 'png' in 'image/png'
  2096. * [4] <data>
  2097. */
  2098. jsPDFAPI.extractInfoFromBase64DataURI = function (dataURI) {
  2099. return /^data:([\w]+?\/([\w]+?));base64,(.+?)$/g.exec(dataURI);
  2100. };
  2101. /**
  2102. * Check to see if ArrayBuffer is supported
  2103. */
  2104. jsPDFAPI.supportsArrayBuffer = function () {
  2105. return typeof ArrayBuffer !== 'undefined' && typeof Uint8Array !== 'undefined';
  2106. };
  2107. /**
  2108. * Tests supplied object to determine if ArrayBuffer
  2109. * @param {Object[object]}
  2110. */
  2111. jsPDFAPI.isArrayBuffer = function (object) {
  2112. if (!this.supportsArrayBuffer())
  2113. return false;
  2114. return object instanceof ArrayBuffer;
  2115. };
  2116. /**
  2117. * Tests supplied object to determine if it implements the ArrayBufferView (TypedArray) interface
  2118. * @param {Object[object]}
  2119. */
  2120. jsPDFAPI.isArrayBufferView = function (object) {
  2121. if (!this.supportsArrayBuffer())
  2122. return false;
  2123. if (typeof Uint32Array === 'undefined')
  2124. return false;
  2125. return (object instanceof Int8Array ||
  2126. object instanceof Uint8Array ||
  2127. (typeof Uint8ClampedArray !== 'undefined' && object instanceof Uint8ClampedArray) ||
  2128. object instanceof Int16Array ||
  2129. object instanceof Uint16Array ||
  2130. object instanceof Int32Array ||
  2131. object instanceof Uint32Array ||
  2132. object instanceof Float32Array ||
  2133. object instanceof Float64Array);
  2134. };
  2135. /**
  2136. * Exactly what it says on the tin
  2137. */
  2138. jsPDFAPI.binaryStringToUint8Array = function (binary_string) {
  2139. /*
  2140. * not sure how efficient this will be will bigger files. Is there a native method?
  2141. */
  2142. var len = binary_string.length;
  2143. var bytes = new Uint8Array(len);
  2144. for (var i = 0; i < len; i++) {
  2145. bytes[i] = binary_string.charCodeAt(i);
  2146. }
  2147. return bytes;
  2148. };
  2149. /**
  2150. * @see this discussion
  2151. * http://stackoverflow.com/questions/6965107/converting-between-strings-and-arraybuffers
  2152. *
  2153. * As stated, i imagine the method below is highly inefficent for large files.
  2154. *
  2155. * Also of note from Mozilla,
  2156. *
  2157. * "However, this is slow and error-prone, due to the need for multiple conversions (especially if the binary data is not actually byte-format data, but, for example, 32-bit integers or floats)."
  2158. *
  2159. * https://developer.mozilla.org/en-US/Add-ons/Code_snippets/StringView
  2160. *
  2161. * Although i'm strugglig to see how StringView solves this issue? Doesn't appear to be a direct method for conversion?
  2162. *
  2163. * Async method using Blob and FileReader could be best, but i'm not sure how to fit it into the flow?
  2164. */
  2165. jsPDFAPI.arrayBufferToBinaryString = function (buffer) {
  2166. if (this.isArrayBuffer(buffer))
  2167. buffer = new Uint8Array(buffer);
  2168. var binary_string = '';
  2169. var len = buffer.byteLength;
  2170. for (var i = 0; i < len; i++) {
  2171. binary_string += String.fromCharCode(buffer[i]);
  2172. }
  2173. return binary_string;
  2174. /*
  2175. * Another solution is the method below - convert array buffer straight to base64 and then use atob
  2176. */
  2177. //return atob(this.arrayBufferToBase64(buffer));
  2178. };
  2179. /**
  2180. * Converts an ArrayBuffer directly to base64
  2181. *
  2182. * Taken from here
  2183. *
  2184. * http://jsperf.com/encoding-xhr-image-data/31
  2185. *
  2186. * Need to test if this is a better solution for larger files
  2187. *
  2188. */
  2189. jsPDFAPI.arrayBufferToBase64 = function (arrayBuffer) {
  2190. var base64 = ''
  2191. var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  2192. var bytes = new Uint8Array(arrayBuffer)
  2193. var byteLength = bytes.byteLength
  2194. var byteRemainder = byteLength % 3
  2195. var mainLength = byteLength - byteRemainder
  2196. var a, b, c, d
  2197. var chunk
  2198. // Main loop deals with bytes in chunks of 3
  2199. for (var i = 0; i < mainLength; i = i + 3) {
  2200. // Combine the three bytes into a single integer
  2201. chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
  2202. // Use bitmasks to extract 6-bit segments from the triplet
  2203. a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18
  2204. b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12
  2205. c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6
  2206. d = chunk & 63 // 63 = 2^6 - 1
  2207. // Convert the raw binary segments to the appropriate ASCII encoding
  2208. base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
  2209. }
  2210. // Deal with the remaining bytes and padding
  2211. if (byteRemainder == 1) {
  2212. chunk = bytes[mainLength]
  2213. a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2
  2214. // Set the 4 least significant bits to zero
  2215. b = (chunk & 3) << 4 // 3 = 2^2 - 1
  2216. base64 += encodings[a] + encodings[b] + '=='
  2217. } else if (byteRemainder == 2) {
  2218. chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]
  2219. a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10
  2220. b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4
  2221. // Set the 2 least significant bits to zero
  2222. c = (chunk & 15) << 2 // 15 = 2^4 - 1
  2223. base64 += encodings[a] + encodings[b] + encodings[c] + '='
  2224. }
  2225. return base64
  2226. };
  2227. jsPDFAPI.createImageInfo = function (data, wd, ht, cs, bpc, f, imageIndex, alias, dp, trns, pal, smask) {
  2228. var info = {
  2229. alias: alias,
  2230. w: wd,
  2231. h: ht,
  2232. cs: cs,
  2233. bpc: bpc,
  2234. i: imageIndex,
  2235. data: data
  2236. // n: objectNumber will be added by putImage code
  2237. };
  2238. if (f) info.f = f;
  2239. if (dp) info.dp = dp;
  2240. if (trns) info.trns = trns;
  2241. if (pal) info.pal = pal;
  2242. if (smask) info.smask = smask;
  2243. return info;
  2244. };
  2245. jsPDFAPI.addImage = function (imageData, format, x, y, w, h, alias, compression, rotation) {
  2246. 'use strict'
  2247. if (typeof format !== 'string') {
  2248. var tmp = h;
  2249. h = w;
  2250. w = y;
  2251. y = x;
  2252. x = format;
  2253. format = tmp;
  2254. }
  2255. if (typeof imageData === 'object' && !isDOMElement(imageData) && "imageData" in imageData) {
  2256. var options = imageData;
  2257. imageData = options.imageData;
  2258. format = options.format || format;
  2259. x = options.x || x || 0;
  2260. y = options.y || y || 0;
  2261. w = options.w || w;
  2262. h = options.h || h;
  2263. alias = options.alias || alias;
  2264. compression = options.compression || compression;
  2265. rotation = options.rotation || options.angle || rotation;
  2266. }
  2267. if (isNaN(x) || isNaN(y)) {
  2268. console.error('jsPDF.addImage: Invalid coordinates', arguments);
  2269. throw new Error('Invalid coordinates passed to jsPDF.addImage');
  2270. }
  2271. var images = getImages.call(this), info;
  2272. if (!(info = checkImagesForAlias(imageData, images))) {
  2273. var dataAsBinaryString;
  2274. if (isDOMElement(imageData))
  2275. imageData = createDataURIFromElement(imageData, format, rotation);
  2276. if (notDefined(alias))
  2277. alias = generateAliasFromData(imageData);
  2278. if (!(info = checkImagesForAlias(alias, images))) {
  2279. if (this.isString(imageData)) {
  2280. var base64Info = this.extractInfoFromBase64DataURI(imageData);
  2281. if (base64Info) {
  2282. format = base64Info[2];
  2283. imageData = atob(base64Info[3]);//convert to binary string
  2284. } else {
  2285. if (imageData.charCodeAt(0) === 0x89 &&
  2286. imageData.charCodeAt(1) === 0x50 &&
  2287. imageData.charCodeAt(2) === 0x4e &&
  2288. imageData.charCodeAt(3) === 0x47) format = 'png';
  2289. }
  2290. }
  2291. format = (format || 'JPEG').toLowerCase();
  2292. if (doesNotSupportImageType(format))
  2293. throw new Error('addImage currently only supports formats ' + supported_image_types + ', not \'' + format + '\'');
  2294. if (processMethodNotEnabled(format))
  2295. throw new Error('please ensure that the plugin for \'' + format + '\' support is added');
  2296. /**
  2297. * need to test if it's more efficent to convert all binary strings
  2298. * to TypedArray - or should we just leave and process as string?
  2299. */
  2300. if (this.supportsArrayBuffer()) {
  2301. dataAsBinaryString = imageData;
  2302. imageData = this.binaryStringToUint8Array(imageData);
  2303. }
  2304. info = this['process' + format.toUpperCase()](
  2305. imageData,
  2306. getImageIndex(images),
  2307. alias,
  2308. checkCompressValue(compression),
  2309. dataAsBinaryString
  2310. );
  2311. if (!info)
  2312. throw new Error('An unkwown error occurred whilst processing the image');
  2313. }
  2314. }
  2315. writeImageToPDF.call(this, x, y, w, h, info, info.i, images);
  2316. return this
  2317. };
  2318. /**
  2319. * JPEG SUPPORT
  2320. **/
  2321. //takes a string imgData containing the raw bytes of
  2322. //a jpeg image and returns [width, height]
  2323. //Algorithm from: http://www.64lines.com/jpeg-width-height
  2324. var getJpegSize = function (imgData) {
  2325. 'use strict'
  2326. var width, height, numcomponents;
  2327. // Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00
  2328. if (!imgData.charCodeAt(0) === 0xff ||
  2329. !imgData.charCodeAt(1) === 0xd8 ||
  2330. !imgData.charCodeAt(2) === 0xff ||
  2331. !imgData.charCodeAt(3) === 0xe0 ||
  2332. !imgData.charCodeAt(6) === 'J'.charCodeAt(0) ||
  2333. !imgData.charCodeAt(7) === 'F'.charCodeAt(0) ||
  2334. !imgData.charCodeAt(8) === 'I'.charCodeAt(0) ||
  2335. !imgData.charCodeAt(9) === 'F'.charCodeAt(0) ||
  2336. !imgData.charCodeAt(10) === 0x00) {
  2337. throw new Error('getJpegSize requires a binary string jpeg file')
  2338. }
  2339. var blockLength = imgData.charCodeAt(4) * 256 + imgData.charCodeAt(5);
  2340. var i = 4, len = imgData.length;
  2341. while (i < len) {
  2342. i += blockLength;
  2343. if (imgData.charCodeAt(i) !== 0xff) {
  2344. throw new Error('getJpegSize could not find the size of the image');
  2345. }
  2346. if (imgData.charCodeAt(i + 1) === 0xc0 || //(SOF) Huffman - Baseline DCT
  2347. imgData.charCodeAt(i + 1) === 0xc1 || //(SOF) Huffman - Extended sequential DCT
  2348. imgData.charCodeAt(i + 1) === 0xc2 || // Progressive DCT (SOF2)
  2349. imgData.charCodeAt(i + 1) === 0xc3 || // Spatial (sequential) lossless (SOF3)
  2350. imgData.charCodeAt(i + 1) === 0xc4 || // Differential sequential DCT (SOF5)
  2351. imgData.charCodeAt(i + 1) === 0xc5 || // Differential progressive DCT (SOF6)
  2352. imgData.charCodeAt(i + 1) === 0xc6 || // Differential spatial (SOF7)
  2353. imgData.charCodeAt(i + 1) === 0xc7) {
  2354. height = imgData.charCodeAt(i + 5) * 256 + imgData.charCodeAt(i + 6);
  2355. width = imgData.charCodeAt(i + 7) * 256 + imgData.charCodeAt(i + 8);
  2356. numcomponents = imgData.charCodeAt(i + 9);
  2357. return [width, height, numcomponents];
  2358. } else {
  2359. i += 2;
  2360. blockLength = imgData.charCodeAt(i) * 256 + imgData.charCodeAt(i + 1)
  2361. }
  2362. }
  2363. }
  2364. , getJpegSizeFromBytes = function (data) {
  2365. var hdr = (data[0] << 8) | data[1];
  2366. if (hdr !== 0xFFD8)
  2367. throw new Error('Supplied data is not a JPEG');
  2368. var len = data.length,
  2369. block = (data[4] << 8) + data[5],
  2370. pos = 4,
  2371. bytes, width, height, numcomponents;
  2372. while (pos < len) {
  2373. pos += block;
  2374. bytes = readBytes(data, pos);
  2375. block = (bytes[2] << 8) + bytes[3];
  2376. if ((bytes[1] === 0xC0 || bytes[1] === 0xC2) && bytes[0] === 0xFF && block > 7) {
  2377. bytes = readBytes(data, pos + 5);
  2378. width = (bytes[2] << 8) + bytes[3];
  2379. height = (bytes[0] << 8) + bytes[1];
  2380. numcomponents = bytes[4];
  2381. return { width: width, height: height, numcomponents: numcomponents };
  2382. }
  2383. pos += 2;
  2384. }
  2385. throw new Error('getJpegSizeFromBytes could not find the size of the image');
  2386. }
  2387. , readBytes = function (data, offset) {
  2388. return data.subarray(offset, offset + 5);
  2389. };
  2390. jsPDFAPI.processJPEG = function (data, index, alias, compression, dataAsBinaryString) {
  2391. 'use strict'
  2392. var colorSpace = this.color_spaces.DEVICE_RGB,
  2393. filter = this.decode.DCT_DECODE,
  2394. bpc = 8,
  2395. dims;
  2396. if (this.isString(data)) {
  2397. dims = getJpegSize(data);
  2398. return this.createImageInfo(data, dims[0], dims[1], dims[3] == 1 ? this.color_spaces.DEVICE_GRAY : colorSpace, bpc, filter, index, alias);
  2399. }
  2400. if (this.isArrayBuffer(data))
  2401. data = new Uint8Array(data);
  2402. if (this.isArrayBufferView(data)) {
  2403. dims = getJpegSizeFromBytes(data);
  2404. // if we already have a stored binary string rep use that
  2405. data = dataAsBinaryString || this.arrayBufferToBinaryString(data);
  2406. return this.createImageInfo(data, dims.width, dims.height, dims.numcomponents == 1 ? this.color_spaces.DEVICE_GRAY : colorSpace, bpc, filter, index, alias);
  2407. }
  2408. return null;
  2409. };
  2410. jsPDFAPI.processJPG = function (/*data, index, alias, compression, dataAsBinaryString*/) {
  2411. return this.processJPEG.apply(this, arguments);
  2412. }
  2413. })(jsPDF.API);
  2414. (function (jsPDFAPI) {
  2415. 'use strict';
  2416. jsPDFAPI.autoPrint = function () {
  2417. 'use strict'
  2418. var refAutoPrintTag;
  2419. this.internal.events.subscribe('postPutResources', function () {
  2420. refAutoPrintTag = this.internal.newObject()
  2421. this.internal.write("<< /S/Named /Type/Action /N/Print >>", "endobj");
  2422. });
  2423. this.internal.events.subscribe("putCatalog", function () {
  2424. this.internal.write("/OpenAction " + refAutoPrintTag + " 0" + " R");
  2425. });
  2426. return this;
  2427. };
  2428. })(jsPDF.API);
  2429. /** ====================================================================
  2430. * jsPDF Cell plugin
  2431. * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
  2432. * 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br
  2433. * 2013 Lee Driscoll, https://github.com/lsdriscoll
  2434. * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
  2435. * 2014 James Hall, james@parall.ax
  2436. * 2014 Diego Casorran, https://github.com/diegocr
  2437. *
  2438. * Permission is hereby granted, free of charge, to any person obtaining
  2439. * a copy of this software and associated documentation files (the
  2440. * "Software"), to deal in the Software without restriction, including
  2441. * without limitation the rights to use, copy, modify, merge, publish,
  2442. * distribute, sublicense, and/or sell copies of the Software, and to
  2443. * permit persons to whom the Software is furnished to do so, subject to
  2444. * the following conditions:
  2445. *
  2446. * The above copyright notice and this permission notice shall be
  2447. * included in all copies or substantial portions of the Software.
  2448. *
  2449. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  2450. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  2451. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  2452. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  2453. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  2454. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  2455. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  2456. * ====================================================================
  2457. */
  2458. (function (jsPDFAPI) {
  2459. 'use strict';
  2460. /*jslint browser:true */
  2461. /*global document: false, jsPDF */
  2462. var fontName,
  2463. fontSize,
  2464. fontStyle,
  2465. padding = 3,
  2466. margin = 13,
  2467. headerFunction,
  2468. lastCellPos = { x: undefined, y: undefined, w: undefined, h: undefined, ln: undefined },
  2469. pages = 1,
  2470. setLastCellPosition = function (x, y, w, h, ln) {
  2471. lastCellPos = { 'x': x, 'y': y, 'w': w, 'h': h, 'ln': ln };
  2472. },
  2473. getLastCellPosition = function () {
  2474. return lastCellPos;
  2475. },
  2476. NO_MARGINS = { left: 0, top: 0, bottom: 0 };
  2477. jsPDFAPI.setHeaderFunction = function (func) {
  2478. headerFunction = func;
  2479. };
  2480. jsPDFAPI.getTextDimensions = function (txt) {
  2481. fontName = this.internal.getFont().fontName;
  2482. fontSize = this.table_font_size || this.internal.getFontSize();
  2483. fontStyle = this.internal.getFont().fontStyle;
  2484. // 1 pixel = 0.264583 mm and 1 mm = 72/25.4 point
  2485. var px2pt = 0.264583 * 72 / 25.4,
  2486. dimensions,
  2487. text;
  2488. text = document.createElement('font');
  2489. text.id = "jsPDFCell";
  2490. text.style.fontStyle = fontStyle;
  2491. text.style.fontName = fontName;
  2492. text.style.fontSize = fontSize + 'pt';
  2493. text.textContent = txt;
  2494. document.body.appendChild(text);
  2495. dimensions = { w: (text.offsetWidth + 1) * px2pt, h: (text.offsetHeight + 1) * px2pt };
  2496. document.body.removeChild(text);
  2497. return dimensions;
  2498. };
  2499. jsPDFAPI.cellAddPage = function () {
  2500. var margins = this.margins || NO_MARGINS;
  2501. this.addPage();
  2502. setLastCellPosition(margins.left, margins.top, undefined, undefined);
  2503. //setLastCellPosition(undefined, undefined, undefined, undefined, undefined);
  2504. pages += 1;
  2505. };
  2506. jsPDFAPI.cellInitialize = function () {
  2507. lastCellPos = { x: undefined, y: undefined, w: undefined, h: undefined, ln: undefined };
  2508. pages = 1;
  2509. };
  2510. jsPDFAPI.cell = function (x, y, w, h, txt, ln, align) {
  2511. var curCell = getLastCellPosition();
  2512. // If this is not the first cell, we must change its position
  2513. if (curCell.ln !== undefined) {
  2514. if (curCell.ln === ln) {
  2515. //Same line
  2516. x = curCell.x + curCell.w;
  2517. y = curCell.y;
  2518. } else {
  2519. //New line
  2520. var margins = this.margins || NO_MARGINS;
  2521. if ((curCell.y + curCell.h + h + margin) >= this.internal.pageSize.height - margins.bottom) {
  2522. this.cellAddPage();
  2523. if (this.printHeaders && this.tableHeaderRow) {
  2524. this.printHeaderRow(ln, true);
  2525. }
  2526. }
  2527. //We ignore the passed y: the lines may have diferent heights
  2528. y = (getLastCellPosition().y + getLastCellPosition().h);
  2529. }
  2530. }
  2531. if (txt[0] !== undefined) {
  2532. if (this.printingHeaderRow) {
  2533. this.rect(x, y, w, h, 'FD');
  2534. } else {
  2535. this.rect(x, y, w, h);
  2536. }
  2537. if (align === 'right') {
  2538. if (txt instanceof Array) {
  2539. for (var i = 0; i < txt.length; i++) {
  2540. var currentLine = txt[i];
  2541. var textSize = this.getStringUnitWidth(currentLine) * this.internal.getFontSize();
  2542. this.text(currentLine, x + w - textSize - padding, y + this.internal.getLineHeight() * (i + 1));
  2543. }
  2544. }
  2545. } else {
  2546. this.text(txt, x + padding, y + this.internal.getLineHeight());
  2547. }
  2548. }
  2549. setLastCellPosition(x, y, w, h, ln);
  2550. return this;
  2551. };
  2552. /**
  2553. * Return the maximum value from an array
  2554. * @param array
  2555. * @param comparisonFn
  2556. * @returns {*}
  2557. */
  2558. jsPDFAPI.arrayMax = function (array, comparisonFn) {
  2559. var max = array[0],
  2560. i,
  2561. ln,
  2562. item;
  2563. for (i = 0, ln = array.length; i < ln; i += 1) {
  2564. item = array[i];
  2565. if (comparisonFn) {
  2566. if (comparisonFn(max, item) === -1) {
  2567. max = item;
  2568. }
  2569. } else {
  2570. if (item > max) {
  2571. max = item;
  2572. }
  2573. }
  2574. }
  2575. return max;
  2576. };
  2577. /**
  2578. * Create a table from a set of data.
  2579. * @param {Integer} [x] : left-position for top-left corner of table
  2580. * @param {Integer} [y] top-position for top-left corner of table
  2581. * @param {Object[]} [data] As array of objects containing key-value pairs corresponding to a row of data.
  2582. * @param {String[]} [headers] Omit or null to auto-generate headers at a performance cost
  2583. * @param {Object} [config.printHeaders] True to print column headers at the top of every page
  2584. * @param {Object} [config.autoSize] True to dynamically set the column widths to match the widest cell value
  2585. * @param {Object} [config.margins] margin values for left, top, bottom, and width
  2586. * @param {Object} [config.fontSize] Integer fontSize to use (optional)
  2587. */
  2588. jsPDFAPI.table = function (x, y, data, headers, config) {
  2589. if (!data) {
  2590. throw 'No data for PDF table';
  2591. }
  2592. var headerNames = [],
  2593. headerPrompts = [],
  2594. header,
  2595. i,
  2596. ln,
  2597. cln,
  2598. columnMatrix = {},
  2599. columnWidths = {},
  2600. columnData,
  2601. column,
  2602. columnMinWidths = [],
  2603. j,
  2604. tableHeaderConfigs = [],
  2605. model,
  2606. jln,
  2607. func,
  2608. //set up defaults. If a value is provided in config, defaults will be overwritten:
  2609. autoSize = false,
  2610. printHeaders = true,
  2611. fontSize = 12,
  2612. margins = NO_MARGINS;
  2613. margins.width = this.internal.pageSize.width;
  2614. if (config) {
  2615. //override config defaults if the user has specified non-default behavior:
  2616. if (config.autoSize === true) {
  2617. autoSize = true;
  2618. }
  2619. if (config.printHeaders === false) {
  2620. printHeaders = false;
  2621. }
  2622. if (config.fontSize) {
  2623. fontSize = config.fontSize;
  2624. }
  2625. if (config.margins) {
  2626. margins = config.margins;
  2627. }
  2628. }
  2629. /**
  2630. * @property {Number} lnMod
  2631. * Keep track of the current line number modifier used when creating cells
  2632. */
  2633. this.lnMod = 0;
  2634. lastCellPos = { x: undefined, y: undefined, w: undefined, h: undefined, ln: undefined },
  2635. pages = 1;
  2636. this.printHeaders = printHeaders;
  2637. this.margins = margins;
  2638. this.setFontSize(fontSize);
  2639. this.table_font_size = fontSize;
  2640. // Set header values
  2641. if (headers === undefined || (headers === null)) {
  2642. // No headers defined so we derive from data
  2643. headerNames = Object.keys(data[0]);
  2644. } else if (headers[0] && (typeof headers[0] !== 'string')) {
  2645. var px2pt = 0.264583 * 72 / 25.4;
  2646. // Split header configs into names and prompts
  2647. for (i = 0, ln = headers.length; i < ln; i += 1) {
  2648. header = headers[i];
  2649. headerNames.push(header.name);
  2650. headerPrompts.push(header.prompt);
  2651. columnWidths[header.name] = header.width * px2pt;
  2652. }
  2653. } else {
  2654. headerNames = headers;
  2655. }
  2656. if (autoSize) {
  2657. // Create a matrix of columns e.g., {column_title: [row1_Record, row2_Record]}
  2658. func = function (rec) {
  2659. return rec[header];
  2660. };
  2661. for (i = 0, ln = headerNames.length; i < ln; i += 1) {
  2662. header = headerNames[i];
  2663. columnMatrix[header] = data.map(
  2664. func
  2665. );
  2666. // get header width
  2667. columnMinWidths.push(this.getTextDimensions(headerPrompts[i] || header).w);
  2668. column = columnMatrix[header];
  2669. // get cell widths
  2670. for (j = 0, cln = column.length; j < cln; j += 1) {
  2671. columnData = column[j];
  2672. columnMinWidths.push(this.getTextDimensions(columnData).w);
  2673. }
  2674. // get final column width
  2675. columnWidths[header] = jsPDFAPI.arrayMax(columnMinWidths);
  2676. }
  2677. }
  2678. // -- Construct the table
  2679. if (printHeaders) {
  2680. var lineHeight = this.calculateLineHeight(headerNames, columnWidths, headerPrompts.length ? headerPrompts : headerNames);
  2681. // Construct the header row
  2682. for (i = 0, ln = headerNames.length; i < ln; i += 1) {
  2683. header = headerNames[i];
  2684. tableHeaderConfigs.push([x, y, columnWidths[header], lineHeight, String(headerPrompts.length ? headerPrompts[i] : header)]);
  2685. }
  2686. // Store the table header config
  2687. this.setTableHeaderRow(tableHeaderConfigs);
  2688. // Print the header for the start of the table
  2689. this.printHeaderRow(1, false);
  2690. }
  2691. // Construct the data rows
  2692. for (i = 0, ln = data.length; i < ln; i += 1) {
  2693. var lineHeight;
  2694. model = data[i];
  2695. lineHeight = this.calculateLineHeight(headerNames, columnWidths, model);
  2696. for (j = 0, jln = headerNames.length; j < jln; j += 1) {
  2697. header = headerNames[j];
  2698. this.cell(x, y, columnWidths[header], lineHeight, model[header], i + 2, header.align);
  2699. }
  2700. }
  2701. this.lastCellPos = lastCellPos;
  2702. this.table_x = x;
  2703. this.table_y = y;
  2704. return this;
  2705. };
  2706. /**
  2707. * Calculate the height for containing the highest column
  2708. * @param {String[]} headerNames is the header, used as keys to the data
  2709. * @param {Integer[]} columnWidths is size of each column
  2710. * @param {Object[]} model is the line of data we want to calculate the height of
  2711. */
  2712. jsPDFAPI.calculateLineHeight = function (headerNames, columnWidths, model) {
  2713. var header, lineHeight = 0;
  2714. for (var j = 0; j < headerNames.length; j++) {
  2715. header = headerNames[j];
  2716. model[header] = this.splitTextToSize(String(model[header]), columnWidths[header] - padding);
  2717. var h = this.internal.getLineHeight() * model[header].length + padding;
  2718. if (h > lineHeight)
  2719. lineHeight = h;
  2720. }
  2721. return lineHeight;
  2722. };
  2723. /**
  2724. * Store the config for outputting a table header
  2725. * @param {Object[]} config
  2726. * An array of cell configs that would define a header row: Each config matches the config used by jsPDFAPI.cell
  2727. * except the ln parameter is excluded
  2728. */
  2729. jsPDFAPI.setTableHeaderRow = function (config) {
  2730. this.tableHeaderRow = config;
  2731. };
  2732. /**
  2733. * Output the store header row
  2734. * @param lineNumber The line number to output the header at
  2735. */
  2736. jsPDFAPI.printHeaderRow = function (lineNumber, new_page) {
  2737. if (!this.tableHeaderRow) {
  2738. throw 'Property tableHeaderRow does not exist.';
  2739. }
  2740. var tableHeaderCell,
  2741. tmpArray,
  2742. i,
  2743. ln;
  2744. this.printingHeaderRow = true;
  2745. if (headerFunction !== undefined) {
  2746. var position = headerFunction(this, pages);
  2747. setLastCellPosition(position[0], position[1], position[2], position[3], -1);
  2748. }
  2749. this.setFontStyle('bold');
  2750. var tempHeaderConf = [];
  2751. for (i = 0, ln = this.tableHeaderRow.length; i < ln; i += 1) {
  2752. this.setFillColor(200, 200, 200);
  2753. tableHeaderCell = this.tableHeaderRow[i];
  2754. if (new_page) {
  2755. tableHeaderCell[1] = this.margins && this.margins.top || 0;
  2756. tempHeaderConf.push(tableHeaderCell);
  2757. }
  2758. tmpArray = [].concat(tableHeaderCell);
  2759. this.cell.apply(this, tmpArray.concat(lineNumber));
  2760. }
  2761. if (tempHeaderConf.length > 0) {
  2762. this.setTableHeaderRow(tempHeaderConf);
  2763. }
  2764. this.setFontStyle('normal');
  2765. this.printingHeaderRow = false;
  2766. };
  2767. })(jsPDF.API);
  2768. /** @preserve
  2769. * jsPDF fromHTML plugin. BETA stage. API subject to change. Needs browser
  2770. * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  2771. * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
  2772. * 2014 Diego Casorran, https://github.com/diegocr
  2773. * 2014 Daniel Husar, https://github.com/danielhusar
  2774. * 2014 Wolfgang Gassler, https://github.com/woolfg
  2775. *
  2776. * Permission is hereby granted, free of charge, to any person obtaining
  2777. * a copy of this software and associated documentation files (the
  2778. * "Software"), to deal in the Software without restriction, including
  2779. * without limitation the rights to use, copy, modify, merge, publish,
  2780. * distribute, sublicense, and/or sell copies of the Software, and to
  2781. * permit persons to whom the Software is furnished to do so, subject to
  2782. * the following conditions:
  2783. *
  2784. * The above copyright notice and this permission notice shall be
  2785. * included in all copies or substantial portions of the Software.
  2786. *
  2787. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  2788. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  2789. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  2790. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  2791. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  2792. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  2793. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  2794. * ====================================================================
  2795. */
  2796. (function (jsPDFAPI) {
  2797. var clone,
  2798. DrillForContent,
  2799. FontNameDB,
  2800. FontStyleMap,
  2801. FontWeightMap,
  2802. FloatMap,
  2803. ClearMap,
  2804. GetCSS,
  2805. PurgeWhiteSpace,
  2806. Renderer,
  2807. ResolveFont,
  2808. ResolveUnitedNumber,
  2809. UnitedNumberMap,
  2810. elementHandledElsewhere,
  2811. images,
  2812. loadImgs,
  2813. checkForFooter,
  2814. process,
  2815. tableToJson;
  2816. clone = (function () {
  2817. return function (obj) {
  2818. Clone.prototype = obj;
  2819. return new Clone()
  2820. };
  2821. function Clone() { }
  2822. })();
  2823. PurgeWhiteSpace = function (array) {
  2824. var fragment,
  2825. i,
  2826. l,
  2827. lTrimmed,
  2828. r,
  2829. rTrimmed,
  2830. trailingSpace;
  2831. i = 0;
  2832. l = array.length;
  2833. fragment = void 0;
  2834. lTrimmed = false;
  2835. rTrimmed = false;
  2836. while (!lTrimmed && i !== l) {
  2837. fragment = array[i] = array[i].trimLeft();
  2838. if (fragment) {
  2839. lTrimmed = true;
  2840. }
  2841. i++;
  2842. }
  2843. i = l - 1;
  2844. while (l && !rTrimmed && i !== -1) {
  2845. fragment = array[i] = array[i].trimRight();
  2846. if (fragment) {
  2847. rTrimmed = true;
  2848. }
  2849. i--;
  2850. }
  2851. r = /\s+$/g;
  2852. trailingSpace = true;
  2853. i = 0;
  2854. while (i !== l) {
  2855. fragment = array[i].replace(/\s+/g, " ");
  2856. if (trailingSpace) {
  2857. fragment = fragment.trimLeft();
  2858. }
  2859. if (fragment) {
  2860. trailingSpace = r.test(fragment);
  2861. }
  2862. array[i] = fragment;
  2863. i++;
  2864. }
  2865. return array;
  2866. };
  2867. Renderer = function (pdf, x, y, settings) {
  2868. this.pdf = pdf;
  2869. this.x = x;
  2870. this.y = y;
  2871. this.settings = settings;
  2872. //list of functions which are called after each element-rendering process
  2873. this.watchFunctions = [];
  2874. this.init();
  2875. return this;
  2876. };
  2877. ResolveFont = function (css_font_family_string) {
  2878. var name,
  2879. part,
  2880. parts;
  2881. name = void 0;
  2882. parts = css_font_family_string.split(",");
  2883. part = parts.shift();
  2884. while (!name && part) {
  2885. name = FontNameDB[part.trim().toLowerCase()];
  2886. part = parts.shift();
  2887. }
  2888. return name;
  2889. };
  2890. ResolveUnitedNumber = function (css_line_height_string) {
  2891. //IE8 issues
  2892. css_line_height_string = css_line_height_string === "auto" ? "0px" : css_line_height_string;
  2893. if (css_line_height_string.indexOf("em") > -1 && !isNaN(Number(css_line_height_string.replace("em", "")))) {
  2894. css_line_height_string = Number(css_line_height_string.replace("em", "")) * 18.719 + "px";
  2895. }
  2896. if (css_line_height_string.indexOf("pt") > -1 && !isNaN(Number(css_line_height_string.replace("pt", "")))) {
  2897. css_line_height_string = Number(css_line_height_string.replace("pt", "")) * 1.333 + "px";
  2898. }
  2899. var normal,
  2900. undef,
  2901. value;
  2902. undef = void 0;
  2903. normal = 16.00;
  2904. value = UnitedNumberMap[css_line_height_string];
  2905. if (value) {
  2906. return value;
  2907. }
  2908. value = {
  2909. "xx-small": 9,
  2910. "x-small": 11,
  2911. small: 13,
  2912. medium: 16,
  2913. large: 19,
  2914. "x-large": 23,
  2915. "xx-large": 28,
  2916. auto: 0
  2917. }[{ css_line_height_string: css_line_height_string }];
  2918. if (value !== undef) {
  2919. return UnitedNumberMap[css_line_height_string] = value / normal;
  2920. }
  2921. if (value = parseFloat(css_line_height_string)) {
  2922. return UnitedNumberMap[css_line_height_string] = value / normal;
  2923. }
  2924. value = css_line_height_string.match(/([\d\.]+)(px)/);
  2925. if (value.length === 3) {
  2926. return UnitedNumberMap[css_line_height_string] = parseFloat(value[1]) / normal;
  2927. }
  2928. return UnitedNumberMap[css_line_height_string] = 1;
  2929. };
  2930. GetCSS = function (element) {
  2931. var css, tmp, computedCSSElement;
  2932. computedCSSElement = (function (el) {
  2933. var compCSS;
  2934. compCSS = (function (el) {
  2935. if (document.defaultView && document.defaultView.getComputedStyle) {
  2936. return document.defaultView.getComputedStyle(el, null);
  2937. } else if (el.currentStyle) {
  2938. return el.currentStyle;
  2939. } else {
  2940. return el.style;
  2941. }
  2942. })(el);
  2943. return function (prop) {
  2944. prop = prop.replace(/-\D/g, function (match) {
  2945. return match.charAt(1).toUpperCase();
  2946. });
  2947. return compCSS[prop];
  2948. };
  2949. })(element);
  2950. css = {};
  2951. tmp = void 0;
  2952. css["font-family"] = ResolveFont(computedCSSElement("font-family")) || "times";
  2953. css["font-style"] = FontStyleMap[computedCSSElement("font-style")] || "normal";
  2954. css["text-align"] = TextAlignMap[computedCSSElement("text-align")] || "left";
  2955. tmp = FontWeightMap[computedCSSElement("font-weight")] || "normal";
  2956. if (tmp === "bold") {
  2957. if (css["font-style"] === "normal") {
  2958. css["font-style"] = tmp;
  2959. } else {
  2960. css["font-style"] = tmp + css["font-style"];
  2961. }
  2962. }
  2963. css["font-size"] = ResolveUnitedNumber(computedCSSElement("font-size")) || 1;
  2964. css["line-height"] = ResolveUnitedNumber(computedCSSElement("line-height")) || 1;
  2965. css["display"] = (computedCSSElement("display") === "inline" ? "inline" : "block");
  2966. tmp = (css["display"] === "block");
  2967. css["margin-top"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-top")) || 0;
  2968. css["margin-bottom"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-bottom")) || 0;
  2969. css["padding-top"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-top")) || 0;
  2970. css["padding-bottom"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-bottom")) || 0;
  2971. css["margin-left"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-left")) || 0;
  2972. css["margin-right"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-right")) || 0;
  2973. css["padding-left"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-left")) || 0;
  2974. css["padding-right"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-right")) || 0;
  2975. //float and clearing of floats
  2976. css["float"] = FloatMap[computedCSSElement("cssFloat")] || "none";
  2977. css["clear"] = ClearMap[computedCSSElement("clear")] || "none";
  2978. return css;
  2979. };
  2980. elementHandledElsewhere = function (element, renderer, elementHandlers) {
  2981. var handlers,
  2982. i,
  2983. isHandledElsewhere,
  2984. l,
  2985. t;
  2986. isHandledElsewhere = false;
  2987. i = void 0;
  2988. l = void 0;
  2989. t = void 0;
  2990. handlers = elementHandlers["#" + element.id];
  2991. if (handlers) {
  2992. if (typeof handlers === "function") {
  2993. isHandledElsewhere = handlers(element, renderer);
  2994. } else {
  2995. i = 0;
  2996. l = handlers.length;
  2997. while (!isHandledElsewhere && i !== l) {
  2998. isHandledElsewhere = handlers[i](element, renderer);
  2999. i++;
  3000. }
  3001. }
  3002. }
  3003. handlers = elementHandlers[element.nodeName];
  3004. if (!isHandledElsewhere && handlers) {
  3005. if (typeof handlers === "function") {
  3006. isHandledElsewhere = handlers(element, renderer);
  3007. } else {
  3008. i = 0;
  3009. l = handlers.length;
  3010. while (!isHandledElsewhere && i !== l) {
  3011. isHandledElsewhere = handlers[i](element, renderer);
  3012. i++;
  3013. }
  3014. }
  3015. }
  3016. return isHandledElsewhere;
  3017. };
  3018. tableToJson = function (table, renderer) {
  3019. var data,
  3020. headers,
  3021. i,
  3022. j,
  3023. rowData,
  3024. tableRow,
  3025. table_obj,
  3026. table_with,
  3027. cell,
  3028. l;
  3029. data = [];
  3030. headers = [];
  3031. i = 0;
  3032. l = table.rows[0].cells.length;
  3033. table_with = table.clientWidth;
  3034. while (i < l) {
  3035. cell = table.rows[0].cells[i];
  3036. headers[i] = {
  3037. name: cell.textContent.toLowerCase().replace(/\s+/g, ''),
  3038. prompt: cell.textContent.replace(/\r?\n/g, ''),
  3039. width: (cell.clientWidth / table_with) * renderer.pdf.internal.pageSize.width
  3040. };
  3041. i++;
  3042. }
  3043. i = 1;
  3044. while (i < table.rows.length) {
  3045. tableRow = table.rows[i];
  3046. rowData = {};
  3047. j = 0;
  3048. while (j < tableRow.cells.length) {
  3049. rowData[headers[j].name] = tableRow.cells[j].textContent.replace(/\r?\n/g, '');
  3050. j++;
  3051. }
  3052. data.push(rowData);
  3053. i++;
  3054. }
  3055. return table_obj = {
  3056. rows: data,
  3057. headers: headers
  3058. };
  3059. };
  3060. var SkipNode = {
  3061. SCRIPT: 1,
  3062. STYLE: 1,
  3063. NOSCRIPT: 1,
  3064. OBJECT: 1,
  3065. EMBED: 1,
  3066. SELECT: 1
  3067. };
  3068. var listCount = 1;
  3069. DrillForContent = function (element, renderer, elementHandlers) {
  3070. var cn,
  3071. cns,
  3072. fragmentCSS,
  3073. i,
  3074. isBlock,
  3075. l,
  3076. px2pt,
  3077. table2json,
  3078. cb;
  3079. cns = element.childNodes;
  3080. cn = void 0;
  3081. fragmentCSS = GetCSS(element);
  3082. isBlock = fragmentCSS.display === "block";
  3083. if (isBlock) {
  3084. renderer.setBlockBoundary();
  3085. renderer.setBlockStyle(fragmentCSS);
  3086. }
  3087. px2pt = 0.264583 * 72 / 25.4;
  3088. i = 0;
  3089. l = cns.length;
  3090. while (i < l) {
  3091. cn = cns[i];
  3092. if (typeof cn === "object") {
  3093. //execute all watcher functions to e.g. reset floating
  3094. renderer.executeWatchFunctions(cn);
  3095. /*** HEADER rendering **/
  3096. if (cn.nodeType === 1 && cn.nodeName === 'HEADER') {
  3097. var header = cn;
  3098. //store old top margin
  3099. var oldMarginTop = renderer.pdf.margins_doc.top;
  3100. //subscribe for new page event and render header first on every page
  3101. renderer.pdf.internal.events.subscribe('addPage', function (pageInfo) {
  3102. //set current y position to old margin
  3103. renderer.y = oldMarginTop;
  3104. //render all child nodes of the header element
  3105. DrillForContent(header, renderer, elementHandlers);
  3106. //set margin to old margin + rendered header + 10 space to prevent overlapping
  3107. //important for other plugins (e.g. table) to start rendering at correct position after header
  3108. renderer.pdf.margins_doc.top = renderer.y + 10;
  3109. renderer.y += 10;
  3110. }, false);
  3111. }
  3112. if (cn.nodeType === 8 && cn.nodeName === "#comment") {
  3113. if (~cn.textContent.indexOf("ADD_PAGE")) {
  3114. renderer.pdf.addPage();
  3115. renderer.y = renderer.pdf.margins_doc.top;
  3116. }
  3117. } else if (cn.nodeType === 1 && !SkipNode[cn.nodeName]) {
  3118. /*** IMAGE RENDERING ***/
  3119. var cached_image;
  3120. if (cn.nodeName === "IMG") {
  3121. var url = cn.getAttribute("src");
  3122. cached_image = images[renderer.pdf.sHashCode(url) || url];
  3123. }
  3124. if (cached_image) {
  3125. if ((renderer.pdf.internal.pageSize.height - renderer.pdf.margins_doc.bottom < renderer.y + cn.height) && (renderer.y > renderer.pdf.margins_doc.top)) {
  3126. renderer.pdf.addPage();
  3127. renderer.y = renderer.pdf.margins_doc.top;
  3128. //check if we have to set back some values due to e.g. header rendering for new page
  3129. renderer.executeWatchFunctions(cn);
  3130. }
  3131. var imagesCSS = GetCSS(cn);
  3132. var imageX = renderer.x;
  3133. var fontToUnitRatio = 12 / renderer.pdf.internal.scaleFactor;
  3134. //define additional paddings, margins which have to be taken into account for margin calculations
  3135. var additionalSpaceLeft = (imagesCSS["margin-left"] + imagesCSS["padding-left"]) * fontToUnitRatio;
  3136. var additionalSpaceRight = (imagesCSS["margin-right"] + imagesCSS["padding-right"]) * fontToUnitRatio;
  3137. var additionalSpaceTop = (imagesCSS["margin-top"] + imagesCSS["padding-top"]) * fontToUnitRatio;
  3138. var additionalSpaceBottom = (imagesCSS["margin-bottom"] + imagesCSS["padding-bottom"]) * fontToUnitRatio;
  3139. //if float is set to right, move the image to the right border
  3140. //add space if margin is set
  3141. if (imagesCSS['float'] !== undefined && imagesCSS['float'] === 'right') {
  3142. imageX += renderer.settings.width - cn.width - additionalSpaceRight;
  3143. } else {
  3144. imageX += additionalSpaceLeft;
  3145. }
  3146. renderer.pdf.addImage(cached_image, imageX, renderer.y + additionalSpaceTop, cn.width, cn.height);
  3147. cached_image = undefined;
  3148. //if the float prop is specified we have to float the text around the image
  3149. if (imagesCSS['float'] === 'right' || imagesCSS['float'] === 'left') {
  3150. //add functiont to set back coordinates after image rendering
  3151. renderer.watchFunctions.push((function (diffX, thresholdY, diffWidth, el) {
  3152. //undo drawing box adaptions which were set by floating
  3153. if (renderer.y >= thresholdY) {
  3154. renderer.x += diffX;
  3155. renderer.settings.width += diffWidth;
  3156. return true;
  3157. } else if (el && el.nodeType === 1 && !SkipNode[el.nodeName] && renderer.x + el.width > (renderer.pdf.margins_doc.left + renderer.pdf.margins_doc.width)) {
  3158. renderer.x += diffX;
  3159. renderer.y = thresholdY;
  3160. renderer.settings.width += diffWidth;
  3161. return true;
  3162. } else {
  3163. return false;
  3164. }
  3165. }).bind(this, (imagesCSS['float'] === 'left') ? -cn.width - additionalSpaceLeft - additionalSpaceRight : 0, renderer.y + cn.height + additionalSpaceTop + additionalSpaceBottom, cn.width));
  3166. //reset floating by clear:both divs
  3167. //just set cursorY after the floating element
  3168. renderer.watchFunctions.push((function (yPositionAfterFloating, pages, el) {
  3169. if (renderer.y < yPositionAfterFloating && pages === renderer.pdf.internal.getNumberOfPages()) {
  3170. if (el.nodeType === 1 && GetCSS(el).clear === 'both') {
  3171. renderer.y = yPositionAfterFloating;
  3172. return true;
  3173. } else {
  3174. return false;
  3175. }
  3176. } else {
  3177. return true;
  3178. }
  3179. }).bind(this, renderer.y + cn.height, renderer.pdf.internal.getNumberOfPages()));
  3180. //if floating is set we decrease the available width by the image width
  3181. renderer.settings.width -= cn.width + additionalSpaceLeft + additionalSpaceRight;
  3182. //if left just add the image width to the X coordinate
  3183. if (imagesCSS['float'] === 'left') {
  3184. renderer.x += cn.width + additionalSpaceLeft + additionalSpaceRight;
  3185. }
  3186. } else {
  3187. //if no floating is set, move the rendering cursor after the image height
  3188. renderer.y += cn.height + additionalSpaceBottom;
  3189. }
  3190. /*** TABLE RENDERING ***/
  3191. } else if (cn.nodeName === "TABLE") {
  3192. table2json = tableToJson(cn, renderer);
  3193. renderer.y += 10;
  3194. renderer.pdf.table(renderer.x, renderer.y, table2json.rows, table2json.headers, {
  3195. autoSize: false,
  3196. printHeaders: true,
  3197. margins: renderer.pdf.margins_doc
  3198. });
  3199. renderer.y = renderer.pdf.lastCellPos.y + renderer.pdf.lastCellPos.h + 20;
  3200. } else if (cn.nodeName === "OL" || cn.nodeName === "UL") {
  3201. listCount = 1;
  3202. if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
  3203. DrillForContent(cn, renderer, elementHandlers);
  3204. }
  3205. renderer.y += 10;
  3206. } else if (cn.nodeName === "LI") {
  3207. var temp = renderer.x;
  3208. renderer.x += cn.parentNode.nodeName === "UL" ? 22 : 10;
  3209. renderer.y += 3;
  3210. if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
  3211. DrillForContent(cn, renderer, elementHandlers);
  3212. }
  3213. renderer.x = temp;
  3214. } else if (cn.nodeName === "BR") {
  3215. renderer.y += fragmentCSS["font-size"] * renderer.pdf.internal.scaleFactor;
  3216. } else {
  3217. if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
  3218. DrillForContent(cn, renderer, elementHandlers);
  3219. }
  3220. }
  3221. } else if (cn.nodeType === 3) {
  3222. var value = cn.nodeValue;
  3223. if (cn.nodeValue && cn.parentNode.nodeName === "LI") {
  3224. if (cn.parentNode.parentNode.nodeName === "OL") {
  3225. value = listCount++ + '. ' + value;
  3226. } else {
  3227. var fontPx = fragmentCSS["font-size"] * 16;
  3228. var radius = 2;
  3229. if (fontPx > 20) {
  3230. radius = 3;
  3231. }
  3232. cb = function (x, y) {
  3233. this.pdf.circle(x, y, radius, 'FD');
  3234. };
  3235. }
  3236. }
  3237. renderer.addText(value, fragmentCSS);
  3238. } else if (typeof cn === "string") {
  3239. renderer.addText(cn, fragmentCSS);
  3240. }
  3241. }
  3242. i++;
  3243. }
  3244. if (isBlock) {
  3245. return renderer.setBlockBoundary(cb);
  3246. }
  3247. };
  3248. images = {};
  3249. loadImgs = function (element, renderer, elementHandlers, cb) {
  3250. var imgs = element.getElementsByTagName('img'),
  3251. l = imgs.length, found_images,
  3252. x = 0;
  3253. function done() {
  3254. renderer.pdf.internal.events.publish('imagesLoaded');
  3255. cb(found_images);
  3256. }
  3257. function loadImage(url, width, height) {
  3258. if (!url)
  3259. return;
  3260. var img = new Image();
  3261. found_images = ++x;
  3262. img.crossOrigin = '';
  3263. img.onerror = img.onload = function () {
  3264. if (img.complete) {
  3265. //to support data urls in images, set width and height
  3266. //as those values are not recognized automatically
  3267. if (img.src.indexOf('data:image/') === 0) {
  3268. img.width = width || img.width || 0;
  3269. img.height = height || img.height || 0;
  3270. }
  3271. //if valid image add to known images array
  3272. if (img.width + img.height) {
  3273. var hash = renderer.pdf.sHashCode(url) || url;
  3274. images[hash] = images[hash] || img;
  3275. }
  3276. }
  3277. if (!--x) {
  3278. done();
  3279. }
  3280. };
  3281. img.src = url;
  3282. }
  3283. while (l--)
  3284. loadImage(imgs[l].getAttribute("src"), imgs[l].width, imgs[l].height);
  3285. return x || done();
  3286. };
  3287. checkForFooter = function (elem, renderer, elementHandlers) {
  3288. //check if we can found a <footer> element
  3289. var footer = elem.getElementsByTagName("footer");
  3290. if (footer.length > 0) {
  3291. footer = footer[0];
  3292. //bad hack to get height of footer
  3293. //creat dummy out and check new y after fake rendering
  3294. var oldOut = renderer.pdf.internal.write;
  3295. var oldY = renderer.y;
  3296. renderer.pdf.internal.write = function () { };
  3297. DrillForContent(footer, renderer, elementHandlers);
  3298. var footerHeight = Math.ceil(renderer.y - oldY) + 5;
  3299. renderer.y = oldY;
  3300. renderer.pdf.internal.write = oldOut;
  3301. //add 20% to prevent overlapping
  3302. renderer.pdf.margins_doc.bottom += footerHeight;
  3303. //Create function render header on every page
  3304. var renderFooter = function (pageInfo) {
  3305. var pageNumber = pageInfo !== undefined ? pageInfo.pageNumber : 1;
  3306. //set current y position to old margin
  3307. var oldPosition = renderer.y;
  3308. //render all child nodes of the header element
  3309. renderer.y = renderer.pdf.internal.pageSize.height - renderer.pdf.margins_doc.bottom;
  3310. renderer.pdf.margins_doc.bottom -= footerHeight;
  3311. //check if we have to add page numbers
  3312. var spans = footer.getElementsByTagName('span');
  3313. for (var i = 0; i < spans.length; ++i) {
  3314. //if we find some span element with class pageCounter, set the page
  3315. if ((" " + spans[i].className + " ").replace(/[\n\t]/g, " ").indexOf(" pageCounter ") > -1) {
  3316. spans[i].innerHTML = pageNumber;
  3317. }
  3318. //if we find some span element with class totalPages, set a variable which is replaced after rendering of all pages
  3319. if ((" " + spans[i].className + " ").replace(/[\n\t]/g, " ").indexOf(" totalPages ") > -1) {
  3320. spans[i].innerHTML = '###jsPDFVarTotalPages###';
  3321. }
  3322. }
  3323. //render footer content
  3324. DrillForContent(footer, renderer, elementHandlers);
  3325. //set bottom margin to previous height including the footer height
  3326. renderer.pdf.margins_doc.bottom += footerHeight;
  3327. //important for other plugins (e.g. table) to start rendering at correct position after header
  3328. renderer.y = oldPosition;
  3329. };
  3330. //check if footer contains totalPages which shoudl be replace at the disoposal of the document
  3331. var spans = footer.getElementsByTagName('span');
  3332. for (var i = 0; i < spans.length; ++i) {
  3333. if ((" " + spans[i].className + " ").replace(/[\n\t]/g, " ").indexOf(" totalPages ") > -1) {
  3334. renderer.pdf.internal.events.subscribe('htmlRenderingFinished', renderer.pdf.putTotalPages.bind(renderer.pdf, '###jsPDFVarTotalPages###'), true);
  3335. }
  3336. }
  3337. //register event to render footer on every new page
  3338. renderer.pdf.internal.events.subscribe('addPage', renderFooter, false);
  3339. //render footer on first page
  3340. renderFooter();
  3341. //prevent footer rendering
  3342. SkipNode['FOOTER'] = 1;
  3343. }
  3344. };
  3345. process = function (pdf, element, x, y, settings, callback) {
  3346. if (!element)
  3347. return false;
  3348. if (typeof element !== "string" && !element.parentNode)
  3349. element = '' + element.innerHTML;
  3350. if (typeof element === "string") {
  3351. element = (function (element) {
  3352. var $frame,
  3353. $hiddendiv,
  3354. framename,
  3355. visuallyhidden;
  3356. framename = "jsPDFhtmlText" + Date.now().toString() + (Math.random() * 1000).toFixed(0);
  3357. 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;";
  3358. $hiddendiv = document.createElement('div');
  3359. $hiddendiv.style.cssText = visuallyhidden;
  3360. $hiddendiv.innerHTML = "<iframe style=\"height:1px;width:1px\" name=\"" + framename + "\" />";
  3361. document.body.appendChild($hiddendiv);
  3362. $frame = window.frames[framename];
  3363. $frame.document.body.innerHTML = element;
  3364. return $frame.document.body;
  3365. })(element.replace(/<\/?script[^>]*?>/gi, ''));
  3366. }
  3367. var r = new Renderer(pdf, x, y, settings), out;
  3368. // 1. load images
  3369. // 2. prepare optional footer elements
  3370. // 3. render content
  3371. loadImgs.call(this, element, r, settings.elementHandlers, function (found_images) {
  3372. checkForFooter(element, r, settings.elementHandlers);
  3373. DrillForContent(element, r, settings.elementHandlers);
  3374. //send event dispose for final taks (e.g. footer totalpage replacement)
  3375. r.pdf.internal.events.publish('htmlRenderingFinished');
  3376. out = r.dispose();
  3377. if (typeof callback === 'function') callback(out);
  3378. else if (found_images) console.error('jsPDF Warning: rendering issues? provide a callback to fromHTML!');
  3379. });
  3380. return out || { x: r.x, y: r.y };
  3381. };
  3382. Renderer.prototype.init = function () {
  3383. this.paragraph = {
  3384. text: [],
  3385. style: []
  3386. };
  3387. return this.pdf.internal.write("q");
  3388. };
  3389. Renderer.prototype.dispose = function () {
  3390. this.pdf.internal.write("Q");
  3391. return {
  3392. x: this.x,
  3393. y: this.y,
  3394. ready: true
  3395. };
  3396. };
  3397. //Checks if we have to execute some watcher functions
  3398. //e.g. to end text floating around an image
  3399. Renderer.prototype.executeWatchFunctions = function (el) {
  3400. var ret = false;
  3401. var narray = [];
  3402. if (this.watchFunctions.length > 0) {
  3403. for (var i = 0; i < this.watchFunctions.length; ++i) {
  3404. if (this.watchFunctions[i](el) === true) {
  3405. ret = true;
  3406. } else {
  3407. narray.push(this.watchFunctions[i]);
  3408. }
  3409. }
  3410. this.watchFunctions = narray;
  3411. }
  3412. return ret;
  3413. };
  3414. Renderer.prototype.splitFragmentsIntoLines = function (fragments, styles) {
  3415. var currentLineLength,
  3416. defaultFontSize,
  3417. ff,
  3418. fontMetrics,
  3419. fontMetricsCache,
  3420. fragment,
  3421. fragmentChopped,
  3422. fragmentLength,
  3423. fragmentSpecificMetrics,
  3424. fs,
  3425. k,
  3426. line,
  3427. lines,
  3428. maxLineLength,
  3429. style;
  3430. defaultFontSize = 12;
  3431. k = this.pdf.internal.scaleFactor;
  3432. fontMetricsCache = {};
  3433. ff = void 0;
  3434. fs = void 0;
  3435. fontMetrics = void 0;
  3436. fragment = void 0;
  3437. style = void 0;
  3438. fragmentSpecificMetrics = void 0;
  3439. fragmentLength = void 0;
  3440. fragmentChopped = void 0;
  3441. line = [];
  3442. lines = [line];
  3443. currentLineLength = 0;
  3444. maxLineLength = this.settings.width;
  3445. while (fragments.length) {
  3446. fragment = fragments.shift();
  3447. style = styles.shift();
  3448. if (fragment) {
  3449. ff = style["font-family"];
  3450. fs = style["font-style"];
  3451. fontMetrics = fontMetricsCache[ff + fs];
  3452. if (!fontMetrics) {
  3453. fontMetrics = this.pdf.internal.getFont(ff, fs).metadata.Unicode;
  3454. fontMetricsCache[ff + fs] = fontMetrics;
  3455. }
  3456. fragmentSpecificMetrics = {
  3457. widths: fontMetrics.widths,
  3458. kerning: fontMetrics.kerning,
  3459. fontSize: style["font-size"] * defaultFontSize,
  3460. textIndent: currentLineLength
  3461. };
  3462. fragmentLength = this.pdf.getStringUnitWidth(fragment, fragmentSpecificMetrics) * fragmentSpecificMetrics.fontSize / k;
  3463. if (currentLineLength + fragmentLength > maxLineLength) {
  3464. fragmentChopped = this.pdf.splitTextToSize(fragment, maxLineLength, fragmentSpecificMetrics);
  3465. line.push([fragmentChopped.shift(), style]);
  3466. while (fragmentChopped.length) {
  3467. line = [[fragmentChopped.shift(), style]];
  3468. lines.push(line);
  3469. }
  3470. currentLineLength = this.pdf.getStringUnitWidth(line[0][0], fragmentSpecificMetrics) * fragmentSpecificMetrics.fontSize / k;
  3471. } else {
  3472. line.push([fragment, style]);
  3473. currentLineLength += fragmentLength;
  3474. }
  3475. }
  3476. }
  3477. //if text alignment was set, set margin/indent of each line
  3478. if (style['text-align'] !== undefined && (style['text-align'] === 'center' || style['text-align'] === 'right' || style['text-align'] === 'justify')) {
  3479. for (var i = 0; i < lines.length; ++i) {
  3480. var length = this.pdf.getStringUnitWidth(lines[i][0][0], fragmentSpecificMetrics) * fragmentSpecificMetrics.fontSize / k;
  3481. //if there is more than on line we have to clone the style object as all lines hold a reference on this object
  3482. if (i > 0) {
  3483. lines[i][0][1] = clone(lines[i][0][1]);
  3484. }
  3485. var space = (maxLineLength - length);
  3486. if (style['text-align'] === 'right') {
  3487. lines[i][0][1]['margin-left'] = space;
  3488. //if alignment is not right, it has to be center so split the space to the left and the right
  3489. } else if (style['text-align'] === 'center') {
  3490. lines[i][0][1]['margin-left'] = space / 2;
  3491. //if justify was set, calculate the word spacing and define in by using the css property
  3492. } else if (style['text-align'] === 'justify') {
  3493. var countSpaces = lines[i][0][0].split(' ').length - 1;
  3494. lines[i][0][1]['word-spacing'] = space / countSpaces;
  3495. //ignore the last line in justify mode
  3496. if (i === (lines.length - 1)) {
  3497. lines[i][0][1]['word-spacing'] = 0;
  3498. }
  3499. }
  3500. }
  3501. }
  3502. return lines;
  3503. };
  3504. Renderer.prototype.RenderTextFragment = function (text, style) {
  3505. var defaultFontSize,
  3506. font,
  3507. maxLineHeight;
  3508. maxLineHeight = 0;
  3509. defaultFontSize = 12;
  3510. if (this.pdf.internal.pageSize.height - this.pdf.margins_doc.bottom < this.y + this.pdf.internal.getFontSize()) {
  3511. this.pdf.internal.write("ET", "Q");
  3512. this.pdf.addPage();
  3513. this.y = this.pdf.margins_doc.top;
  3514. this.pdf.internal.write("q", "BT 0 g", this.pdf.internal.getCoordinateString(this.x), this.pdf.internal.getVerticalCoordinateString(this.y), "Td");
  3515. //move cursor by one line on new page
  3516. maxLineHeight = Math.max(maxLineHeight, style["line-height"], style["font-size"]);
  3517. this.pdf.internal.write(0, (-1 * defaultFontSize * maxLineHeight).toFixed(2), "Td");
  3518. }
  3519. font = this.pdf.internal.getFont(style["font-family"], style["font-style"]);
  3520. //set the word spacing for e.g. justify style
  3521. if (style['word-spacing'] !== undefined && style['word-spacing'] > 0) {
  3522. this.pdf.internal.write(style['word-spacing'].toFixed(2), "Tw");
  3523. }
  3524. this.pdf.internal.write("/" + font.id, (defaultFontSize * style["font-size"]).toFixed(2), "Tf", "(" + this.pdf.internal.pdfEscape(text) + ") Tj");
  3525. //set the word spacing back to neutral => 0
  3526. if (style['word-spacing'] !== undefined) {
  3527. this.pdf.internal.write(0, "Tw");
  3528. }
  3529. };
  3530. Renderer.prototype.renderParagraph = function (cb) {
  3531. var blockstyle,
  3532. defaultFontSize,
  3533. fontToUnitRatio,
  3534. fragments,
  3535. i,
  3536. l,
  3537. line,
  3538. lines,
  3539. maxLineHeight,
  3540. out,
  3541. paragraphspacing_after,
  3542. paragraphspacing_before,
  3543. priorblockstype,
  3544. styles,
  3545. fontSize;
  3546. fragments = PurgeWhiteSpace(this.paragraph.text);
  3547. styles = this.paragraph.style;
  3548. blockstyle = this.paragraph.blockstyle;
  3549. priorblockstype = this.paragraph.blockstyle || {};
  3550. this.paragraph = {
  3551. text: [],
  3552. style: [],
  3553. blockstyle: {},
  3554. priorblockstyle: blockstyle
  3555. };
  3556. if (!fragments.join("").trim()) {
  3557. return;
  3558. }
  3559. lines = this.splitFragmentsIntoLines(fragments, styles);
  3560. line = void 0;
  3561. maxLineHeight = void 0;
  3562. defaultFontSize = 12;
  3563. fontToUnitRatio = defaultFontSize / this.pdf.internal.scaleFactor;
  3564. paragraphspacing_before = (Math.max((blockstyle["margin-top"] || 0) - (priorblockstype["margin-bottom"] || 0), 0) + (blockstyle["padding-top"] || 0)) * fontToUnitRatio;
  3565. paragraphspacing_after = ((blockstyle["margin-bottom"] || 0) + (blockstyle["padding-bottom"] || 0)) * fontToUnitRatio;
  3566. out = this.pdf.internal.write;
  3567. i = void 0;
  3568. l = void 0;
  3569. this.y += paragraphspacing_before;
  3570. out("q", "BT 0 g", this.pdf.internal.getCoordinateString(this.x), this.pdf.internal.getVerticalCoordinateString(this.y), "Td");
  3571. //stores the current indent of cursor position
  3572. var currentIndent = 0;
  3573. while (lines.length) {
  3574. line = lines.shift();
  3575. maxLineHeight = 0;
  3576. i = 0;
  3577. l = line.length;
  3578. while (i !== l) {
  3579. if (line[i][0].trim()) {
  3580. maxLineHeight = Math.max(maxLineHeight, line[i][1]["line-height"], line[i][1]["font-size"]);
  3581. fontSize = line[i][1]["font-size"] * 7;
  3582. }
  3583. i++;
  3584. }
  3585. //if we have to move the cursor to adapt the indent
  3586. var indentMove = 0;
  3587. //if a margin was added (by e.g. a text-alignment), move the cursor
  3588. if (line[0][1]["margin-left"] !== undefined && line[0][1]["margin-left"] > 0) {
  3589. wantedIndent = this.pdf.internal.getCoordinateString(line[0][1]["margin-left"]);
  3590. indentMove = wantedIndent - currentIndent;
  3591. currentIndent = wantedIndent;
  3592. }
  3593. //move the cursor
  3594. out(indentMove, (-1 * defaultFontSize * maxLineHeight).toFixed(2), "Td");
  3595. i = 0;
  3596. l = line.length;
  3597. while (i !== l) {
  3598. if (line[i][0]) {
  3599. this.RenderTextFragment(line[i][0], line[i][1]);
  3600. }
  3601. i++;
  3602. }
  3603. this.y += maxLineHeight * fontToUnitRatio;
  3604. //if some watcher function was executed sucessful, so e.g. margin and widths were changed,
  3605. //reset line drawing and calculate position and lines again
  3606. //e.g. to stop text floating around an image
  3607. if (this.executeWatchFunctions(line[0][1]) && lines.length > 0) {
  3608. var localFragments = [];
  3609. var localStyles = [];
  3610. //create fragement array of
  3611. lines.forEach(function (localLine) {
  3612. var i = 0;
  3613. var l = localLine.length;
  3614. while (i !== l) {
  3615. if (localLine[i][0]) {
  3616. localFragments.push(localLine[i][0] + ' ');
  3617. localStyles.push(localLine[i][1]);
  3618. }
  3619. ++i;
  3620. }
  3621. });
  3622. //split lines again due to possible coordinate changes
  3623. lines = this.splitFragmentsIntoLines(PurgeWhiteSpace(localFragments), localStyles);
  3624. //reposition the current cursor
  3625. out("ET", "Q");
  3626. out("q", "BT 0 g", this.pdf.internal.getCoordinateString(this.x), this.pdf.internal.getVerticalCoordinateString(this.y), "Td");
  3627. }
  3628. }
  3629. if (cb && typeof cb === "function") {
  3630. cb.call(this, this.x - 9, this.y - fontSize / 2);
  3631. }
  3632. out("ET", "Q");
  3633. return this.y += paragraphspacing_after;
  3634. };
  3635. Renderer.prototype.setBlockBoundary = function (cb) {
  3636. return this.renderParagraph(cb);
  3637. };
  3638. Renderer.prototype.setBlockStyle = function (css) {
  3639. return this.paragraph.blockstyle = css;
  3640. };
  3641. Renderer.prototype.addText = function (text, css) {
  3642. this.paragraph.text.push(text);
  3643. return this.paragraph.style.push(css);
  3644. };
  3645. FontNameDB = {
  3646. helvetica: "helvetica",
  3647. "sans-serif": "helvetica",
  3648. "times new roman": "times",
  3649. serif: "times",
  3650. times: "times",
  3651. monospace: "courier",
  3652. courier: "courier"
  3653. };
  3654. FontWeightMap = {
  3655. 100: "normal",
  3656. 200: "normal",
  3657. 300: "normal",
  3658. 400: "normal",
  3659. 500: "bold",
  3660. 600: "bold",
  3661. 700: "bold",
  3662. 800: "bold",
  3663. 900: "bold",
  3664. normal: "normal",
  3665. bold: "bold",
  3666. bolder: "bold",
  3667. lighter: "normal"
  3668. };
  3669. FontStyleMap = {
  3670. normal: "normal",
  3671. italic: "italic",
  3672. oblique: "italic"
  3673. };
  3674. TextAlignMap = {
  3675. left: "left",
  3676. right: "right",
  3677. center: "center",
  3678. justify: "justify"
  3679. };
  3680. FloatMap = {
  3681. none: 'none',
  3682. right: 'right',
  3683. left: 'left'
  3684. };
  3685. ClearMap = {
  3686. none: 'none',
  3687. both: 'both'
  3688. };
  3689. UnitedNumberMap = {
  3690. normal: 1
  3691. };
  3692. /**
  3693. * Converts HTML-formatted text into formatted PDF text.
  3694. *
  3695. * Notes:
  3696. * 2012-07-18
  3697. * Plugin relies on having browser, DOM around. The HTML is pushed into dom and traversed.
  3698. * Plugin relies on jQuery for CSS extraction.
  3699. * Targeting HTML output from Markdown templating, which is a very simple
  3700. * markup - div, span, em, strong, p. No br-based paragraph separation supported explicitly (but still may work.)
  3701. * Images, tables are NOT supported.
  3702. *
  3703. * @public
  3704. * @function
  3705. * @param HTML {String or DOM Element} HTML-formatted text, or pointer to DOM element that is to be rendered into PDF.
  3706. * @param x {Number} starting X coordinate in jsPDF instance's declared units.
  3707. * @param y {Number} starting Y coordinate in jsPDF instance's declared units.
  3708. * @param settings {Object} Additional / optional variables controlling parsing, rendering.
  3709. * @returns {Object} jsPDF instance
  3710. */
  3711. jsPDFAPI.fromHTML = function (HTML, x, y, settings, callback, margins) {
  3712. "use strict";
  3713. this.margins_doc = margins || {
  3714. top: 0,
  3715. bottom: 0
  3716. };
  3717. if (!settings)
  3718. settings = {};
  3719. if (!settings.elementHandlers)
  3720. settings.elementHandlers = {};
  3721. return process(this, HTML, isNaN(x) ? 4 : x, isNaN(y) ? 4 : y, settings, callback);
  3722. };
  3723. })(jsPDF.API);
  3724. /** ====================================================================
  3725. * jsPDF JavaScript plugin
  3726. * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
  3727. *
  3728. * Permission is hereby granted, free of charge, to any person obtaining
  3729. * a copy of this software and associated documentation files (the
  3730. * "Software"), to deal in the Software without restriction, including
  3731. * without limitation the rights to use, copy, modify, merge, publish,
  3732. * distribute, sublicense, and/or sell copies of the Software, and to
  3733. * permit persons to whom the Software is furnished to do so, subject to
  3734. * the following conditions:
  3735. *
  3736. * The above copyright notice and this permission notice shall be
  3737. * included in all copies or substantial portions of the Software.
  3738. *
  3739. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  3740. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  3741. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  3742. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  3743. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  3744. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  3745. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  3746. * ====================================================================
  3747. */
  3748. /*global jsPDF */
  3749. (function (jsPDFAPI) {
  3750. 'use strict';
  3751. var jsNamesObj, jsJsObj, text;
  3752. jsPDFAPI.addJS = function (txt) {
  3753. text = txt;
  3754. this.internal.events.subscribe(
  3755. 'postPutResources',
  3756. function (txt) {
  3757. jsNamesObj = this.internal.newObject();
  3758. this.internal.write('<< /Names [(EmbeddedJS) ' + (jsNamesObj + 1) + ' 0 R] >>', 'endobj');
  3759. jsJsObj = this.internal.newObject();
  3760. this.internal.write('<< /S /JavaScript /JS (', text, ') >>', 'endobj');
  3761. }
  3762. );
  3763. this.internal.events.subscribe(
  3764. 'putCatalog',
  3765. function () {
  3766. if (jsNamesObj !== undefined && jsJsObj !== undefined) {
  3767. this.internal.write('/Names <</JavaScript ' + jsNamesObj + ' 0 R>>');
  3768. }
  3769. }
  3770. );
  3771. return this;
  3772. };
  3773. }(jsPDF.API));
  3774. /**@preserve
  3775. * ====================================================================
  3776. * jsPDF PNG PlugIn
  3777. * Copyright (c) 2014 James Robb, https://github.com/jamesbrobb
  3778. *
  3779. * Permission is hereby granted, free of charge, to any person obtaining
  3780. * a copy of this software and associated documentation files (the
  3781. * "Software"), to deal in the Software without restriction, including
  3782. * without limitation the rights to use, copy, modify, merge, publish,
  3783. * distribute, sublicense, and/or sell copies of the Software, and to
  3784. * permit persons to whom the Software is furnished to do so, subject to
  3785. * the following conditions:
  3786. *
  3787. * The above copyright notice and this permission notice shall be
  3788. * included in all copies or substantial portions of the Software.
  3789. *
  3790. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  3791. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  3792. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  3793. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  3794. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  3795. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  3796. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  3797. * ====================================================================
  3798. */
  3799. (function (jsPDFAPI) {
  3800. 'use strict'
  3801. /*
  3802. * @see http://www.w3.org/TR/PNG-Chunks.html
  3803. *
  3804. Color Allowed Interpretation
  3805. Type Bit Depths
  3806. 0 1,2,4,8,16 Each pixel is a grayscale sample.
  3807. 2 8,16 Each pixel is an R,G,B triple.
  3808. 3 1,2,4,8 Each pixel is a palette index;
  3809. a PLTE chunk must appear.
  3810. 4 8,16 Each pixel is a grayscale sample,
  3811. followed by an alpha sample.
  3812. 6 8,16 Each pixel is an R,G,B triple,
  3813. followed by an alpha sample.
  3814. */
  3815. /*
  3816. * PNG filter method types
  3817. *
  3818. * @see http://www.w3.org/TR/PNG-Filters.html
  3819. * @see http://www.libpng.org/pub/png/book/chapter09.html
  3820. *
  3821. * This is what the value 'Predictor' in decode params relates to
  3822. *
  3823. * 15 is "optimal prediction", which means the prediction algorithm can change from line to line.
  3824. * 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.
  3825. *
  3826. 0 None
  3827. 1 Sub
  3828. 2 Up
  3829. 3 Average
  3830. 4 Paeth
  3831. */
  3832. var doesNotHavePngJS = function () {
  3833. return typeof PNG !== 'function' || typeof FlateStream !== 'function';
  3834. }
  3835. , canCompress = function (value) {
  3836. return value !== jsPDFAPI.image_compression.NONE && hasCompressionJS();
  3837. }
  3838. , hasCompressionJS = function () {
  3839. var inst = typeof Deflater === 'function';
  3840. if (!inst)
  3841. throw new Error("requires deflate.js for compression")
  3842. return inst;
  3843. }
  3844. , compressBytes = function (bytes, lineLength, colorsPerPixel, compression) {
  3845. var level = 5,
  3846. filter_method = filterUp;
  3847. switch (compression) {
  3848. case jsPDFAPI.image_compression.FAST:
  3849. level = 3;
  3850. filter_method = filterSub;
  3851. break;
  3852. case jsPDFAPI.image_compression.MEDIUM:
  3853. level = 6;
  3854. filter_method = filterAverage;
  3855. break;
  3856. case jsPDFAPI.image_compression.SLOW:
  3857. level = 9;
  3858. filter_method = filterPaeth;//uses to sum to choose best filter for each line
  3859. break;
  3860. }
  3861. bytes = applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method);
  3862. var header = new Uint8Array(createZlibHeader(level));
  3863. var checksum = adler32(bytes);
  3864. var deflate = new Deflater(level);
  3865. var a = deflate.append(bytes);
  3866. var cBytes = deflate.flush();
  3867. var len = header.length + a.length + cBytes.length;
  3868. var cmpd = new Uint8Array(len + 4);
  3869. cmpd.set(header);
  3870. cmpd.set(a, header.length);
  3871. cmpd.set(cBytes, header.length + a.length);
  3872. cmpd[len++] = (checksum >>> 24) & 0xff;
  3873. cmpd[len++] = (checksum >>> 16) & 0xff;
  3874. cmpd[len++] = (checksum >>> 8) & 0xff;
  3875. cmpd[len++] = checksum & 0xff;
  3876. return jsPDFAPI.arrayBufferToBinaryString(cmpd);
  3877. }
  3878. , createZlibHeader = function (bytes, level) {
  3879. /*
  3880. * @see http://www.ietf.org/rfc/rfc1950.txt for zlib header
  3881. */
  3882. var cm = 8;
  3883. var cinfo = Math.LOG2E * Math.log(0x8000) - 8;
  3884. var cmf = (cinfo << 4) | cm;
  3885. var hdr = cmf << 8;
  3886. var flevel = Math.min(3, ((level - 1) & 0xff) >> 1);
  3887. hdr |= (flevel << 6);
  3888. hdr |= 0;//FDICT
  3889. hdr += 31 - (hdr % 31);
  3890. return [cmf, (hdr & 0xff) & 0xff];
  3891. }
  3892. , adler32 = function (array, param) {
  3893. var adler = 1;
  3894. var s1 = adler & 0xffff,
  3895. s2 = (adler >>> 16) & 0xffff;
  3896. var len = array.length;
  3897. var tlen;
  3898. var i = 0;
  3899. while (len > 0) {
  3900. tlen = len > param ? param : len;
  3901. len -= tlen;
  3902. do {
  3903. s1 += array[i++];
  3904. s2 += s1;
  3905. } while (--tlen);
  3906. s1 %= 65521;
  3907. s2 %= 65521;
  3908. }
  3909. return ((s2 << 16) | s1) >>> 0;
  3910. }
  3911. , applyPngFilterMethod = function (bytes, lineLength, colorsPerPixel, filter_method) {
  3912. var lines = bytes.length / lineLength,
  3913. result = new Uint8Array(bytes.length + lines),
  3914. filter_methods = getFilterMethods(),
  3915. i = 0, line, prevLine, offset;
  3916. for (; i < lines; i++) {
  3917. offset = i * lineLength;
  3918. line = bytes.subarray(offset, offset + lineLength);
  3919. if (filter_method) {
  3920. result.set(filter_method(line, colorsPerPixel, prevLine), offset + i);
  3921. } else {
  3922. var j = 0,
  3923. len = filter_methods.length,
  3924. results = [];
  3925. for (; j < len; j++)
  3926. results[j] = filter_methods[j](line, colorsPerPixel, prevLine);
  3927. var ind = getIndexOfSmallestSum(results.concat());
  3928. result.set(results[ind], offset + i);
  3929. }
  3930. prevLine = line;
  3931. }
  3932. return result;
  3933. }
  3934. , filterNone = function (line, colorsPerPixel, prevLine) {
  3935. /*var result = new Uint8Array(line.length + 1);
  3936. result[0] = 0;
  3937. result.set(line, 1);*/
  3938. var result = Array.apply([], line);
  3939. result.unshift(0);
  3940. return result;
  3941. }
  3942. , filterSub = function (line, colorsPerPixel, prevLine) {
  3943. var result = [],
  3944. i = 0,
  3945. len = line.length,
  3946. left;
  3947. result[0] = 1;
  3948. for (; i < len; i++) {
  3949. left = line[i - colorsPerPixel] || 0;
  3950. result[i + 1] = (line[i] - left + 0x0100) & 0xff;
  3951. }
  3952. return result;
  3953. }
  3954. , filterUp = function (line, colorsPerPixel, prevLine) {
  3955. var result = [],
  3956. i = 0,
  3957. len = line.length,
  3958. up;
  3959. result[0] = 2;
  3960. for (; i < len; i++) {
  3961. up = prevLine && prevLine[i] || 0;
  3962. result[i + 1] = (line[i] - up + 0x0100) & 0xff;
  3963. }
  3964. return result;
  3965. }
  3966. , filterAverage = function (line, colorsPerPixel, prevLine) {
  3967. var result = [],
  3968. i = 0,
  3969. len = line.length,
  3970. left,
  3971. up;
  3972. result[0] = 3;
  3973. for (; i < len; i++) {
  3974. left = line[i - colorsPerPixel] || 0;
  3975. up = prevLine && prevLine[i] || 0;
  3976. result[i + 1] = (line[i] + 0x0100 - ((left + up) >>> 1)) & 0xff;
  3977. }
  3978. return result;
  3979. }
  3980. , filterPaeth = function (line, colorsPerPixel, prevLine) {
  3981. var result = [],
  3982. i = 0,
  3983. len = line.length,
  3984. left,
  3985. up,
  3986. upLeft,
  3987. paeth;
  3988. result[0] = 4;
  3989. for (; i < len; i++) {
  3990. left = line[i - colorsPerPixel] || 0;
  3991. up = prevLine && prevLine[i] || 0;
  3992. upLeft = prevLine && prevLine[i - colorsPerPixel] || 0;
  3993. paeth = paethPredictor(left, up, upLeft);
  3994. result[i + 1] = (line[i] - paeth + 0x0100) & 0xff;
  3995. }
  3996. return result;
  3997. }
  3998. , paethPredictor = function (left, up, upLeft) {
  3999. var p = left + up - upLeft,
  4000. pLeft = Math.abs(p - left),
  4001. pUp = Math.abs(p - up),
  4002. pUpLeft = Math.abs(p - upLeft);
  4003. return (pLeft <= pUp && pLeft <= pUpLeft) ? left : (pUp <= pUpLeft) ? up : upLeft;
  4004. }
  4005. , getFilterMethods = function () {
  4006. return [filterNone, filterSub, filterUp, filterAverage, filterPaeth];
  4007. }
  4008. , getIndexOfSmallestSum = function (arrays) {
  4009. var i = 0,
  4010. len = arrays.length,
  4011. sum, min, ind;
  4012. while (i < len) {
  4013. sum = absSum(arrays[i].slice(1));
  4014. if (sum < min || !min) {
  4015. min = sum;
  4016. ind = i;
  4017. }
  4018. i++;
  4019. }
  4020. return ind;
  4021. }
  4022. , absSum = function (array) {
  4023. var i = 0,
  4024. len = array.length,
  4025. sum = 0;
  4026. while (i < len)
  4027. sum += Math.abs(array[i++]);
  4028. return sum;
  4029. }
  4030. , logImg = function (img) {
  4031. console.log("width: " + img.width);
  4032. console.log("height: " + img.height);
  4033. console.log("bits: " + img.bits);
  4034. console.log("colorType: " + img.colorType);
  4035. console.log("transparency:");
  4036. console.log(img.transparency);
  4037. console.log("text:");
  4038. console.log(img.text);
  4039. console.log("compressionMethod: " + img.compressionMethod);
  4040. console.log("filterMethod: " + img.filterMethod);
  4041. console.log("interlaceMethod: " + img.interlaceMethod);
  4042. console.log("imgData:");
  4043. console.log(img.imgData);
  4044. console.log("palette:");
  4045. console.log(img.palette);
  4046. console.log("colors: " + img.colors);
  4047. console.log("colorSpace: " + img.colorSpace);
  4048. console.log("pixelBitlength: " + img.pixelBitlength);
  4049. console.log("hasAlphaChannel: " + img.hasAlphaChannel);
  4050. };
  4051. jsPDFAPI.processPNG = function (imageData, imageIndex, alias, compression, dataAsBinaryString) {
  4052. 'use strict'
  4053. var colorSpace = this.color_spaces.DEVICE_RGB,
  4054. decode = this.decode.FLATE_DECODE,
  4055. bpc = 8,
  4056. img, dp, trns,
  4057. colors, pal, smask;
  4058. /* if(this.isString(imageData)) {
  4059. }*/
  4060. if (this.isArrayBuffer(imageData))
  4061. imageData = new Uint8Array(imageData);
  4062. if (this.isArrayBufferView(imageData)) {
  4063. if (doesNotHavePngJS())
  4064. throw new Error("PNG support requires png.js and zlib.js");
  4065. img = new PNG(imageData);
  4066. imageData = img.imgData;
  4067. bpc = img.bits;
  4068. colorSpace = img.colorSpace;
  4069. colors = img.colors;
  4070. //logImg(img);
  4071. /*
  4072. * colorType 6 - Each pixel is an R,G,B triple, followed by an alpha sample.
  4073. *
  4074. * colorType 4 - Each pixel is a grayscale sample, followed by an alpha sample.
  4075. *
  4076. * Extract alpha to create two separate images, using the alpha as a sMask
  4077. */
  4078. if ([4, 6].indexOf(img.colorType) !== -1) {
  4079. /*
  4080. * processes 8 bit RGBA and grayscale + alpha images
  4081. */
  4082. if (img.bits === 8) {
  4083. var pixelsArrayType = window['Uint' + img.pixelBitlength + 'Array'],
  4084. pixels = new pixelsArrayType(img.decodePixels().buffer),
  4085. len = pixels.length,
  4086. imgData = new Uint8Array(len * img.colors),
  4087. alphaData = new Uint8Array(len),
  4088. pDiff = img.pixelBitlength - img.bits,
  4089. i = 0, n = 0, pixel, pbl;
  4090. for (; i < len; i++) {
  4091. pixel = pixels[i];
  4092. pbl = 0;
  4093. while (pbl < pDiff) {
  4094. imgData[n++] = (pixel >>> pbl) & 0xff;
  4095. pbl = pbl + img.bits;
  4096. }
  4097. alphaData[i] = (pixel >>> pbl) & 0xff;
  4098. }
  4099. }
  4100. /*
  4101. * processes 16 bit RGBA and grayscale + alpha images
  4102. */
  4103. if (img.bits === 16) {
  4104. var pixels = new Uint32Array(img.decodePixels().buffer),
  4105. len = pixels.length,
  4106. imgData = new Uint8Array((len * (32 / img.pixelBitlength)) * img.colors),
  4107. alphaData = new Uint8Array(len * (32 / img.pixelBitlength)),
  4108. hasColors = img.colors > 1,
  4109. i = 0, n = 0, a = 0, pixel;
  4110. while (i < len) {
  4111. pixel = pixels[i++];
  4112. imgData[n++] = (pixel >>> 0) & 0xFF;
  4113. if (hasColors) {
  4114. imgData[n++] = (pixel >>> 16) & 0xFF;
  4115. pixel = pixels[i++];
  4116. imgData[n++] = (pixel >>> 0) & 0xFF;
  4117. }
  4118. alphaData[a++] = (pixel >>> 16) & 0xFF;
  4119. }
  4120. bpc = 8;
  4121. }
  4122. if (canCompress(compression)) {
  4123. imageData = compressBytes(imgData, img.width * img.colors, img.colors, compression);
  4124. smask = compressBytes(alphaData, img.width, 1, compression);
  4125. } else {
  4126. imageData = imgData;
  4127. smask = alphaData;
  4128. decode = null;
  4129. }
  4130. }
  4131. /*
  4132. * Indexed png. Each pixel is a palette index.
  4133. */
  4134. if (img.colorType === 3) {
  4135. colorSpace = this.color_spaces.INDEXED;
  4136. pal = img.palette;
  4137. if (img.transparency.indexed) {
  4138. var trans = img.transparency.indexed;
  4139. var total = 0,
  4140. i = 0,
  4141. len = trans.length;
  4142. for (; i < len; ++i)
  4143. total += trans[i];
  4144. total = total / 255;
  4145. /*
  4146. * a single color is specified as 100% transparent (0),
  4147. * so we set trns to use a /Mask with that index
  4148. */
  4149. if (total === len - 1 && trans.indexOf(0) !== -1) {
  4150. trns = [trans.indexOf(0)];
  4151. /*
  4152. * there's more than one colour within the palette that specifies
  4153. * a transparency value less than 255, so we unroll the pixels to create an image sMask
  4154. */
  4155. } else if (total !== len) {
  4156. var pixels = img.decodePixels(),
  4157. alphaData = new Uint8Array(pixels.length),
  4158. i = 0,
  4159. len = pixels.length;
  4160. for (; i < len; i++)
  4161. alphaData[i] = trans[pixels[i]];
  4162. smask = compressBytes(alphaData, img.width, 1);
  4163. }
  4164. }
  4165. }
  4166. if (decode === this.decode.FLATE_DECODE)
  4167. dp = '/Predictor 15 /Colors ' + colors + ' /BitsPerComponent ' + bpc + ' /Columns ' + img.width;
  4168. else
  4169. //remove 'Predictor' as it applies to the type of png filter applied to its IDAT - we only apply with compression
  4170. dp = '/Colors ' + colors + ' /BitsPerComponent ' + bpc + ' /Columns ' + img.width;
  4171. if (this.isArrayBuffer(imageData) || this.isArrayBufferView(imageData))
  4172. imageData = this.arrayBufferToBinaryString(imageData);
  4173. if (smask && this.isArrayBuffer(smask) || this.isArrayBufferView(smask))
  4174. smask = this.arrayBufferToBinaryString(smask);
  4175. return this.createImageInfo(imageData, img.width, img.height, colorSpace,
  4176. bpc, decode, imageIndex, alias, dp, trns, pal, smask);
  4177. }
  4178. throw new Error("Unsupported PNG image data, try using JPEG instead.");
  4179. }
  4180. })(jsPDF.API)
  4181. /** @preserve
  4182. jsPDF Silly SVG plugin
  4183. Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  4184. */
  4185. /**
  4186. * Permission is hereby granted, free of charge, to any person obtaining
  4187. * a copy of this software and associated documentation files (the
  4188. * "Software"), to deal in the Software without restriction, including
  4189. * without limitation the rights to use, copy, modify, merge, publish,
  4190. * distribute, sublicense, and/or sell copies of the Software, and to
  4191. * permit persons to whom the Software is furnished to do so, subject to
  4192. * the following conditions:
  4193. *
  4194. * The above copyright notice and this permission notice shall be
  4195. * included in all copies or substantial portions of the Software.
  4196. *
  4197. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  4198. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  4199. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  4200. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  4201. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  4202. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  4203. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  4204. * ====================================================================
  4205. */
  4206. ; (function (jsPDFAPI) {
  4207. 'use strict'
  4208. /**
  4209. Parses SVG XML and converts only some of the SVG elements into
  4210. PDF elements.
  4211. Supports:
  4212. paths
  4213. @public
  4214. @function
  4215. @param
  4216. @returns {Type}
  4217. */
  4218. jsPDFAPI.addSVG = function (svgtext, x, y, w, h) {
  4219. // 'this' is _jsPDF object returned when jsPDF is inited (new jsPDF())
  4220. var undef
  4221. if (x === undef || y === undef) {
  4222. throw new Error("addSVG needs values for 'x' and 'y'");
  4223. }
  4224. function InjectCSS(cssbody, document) {
  4225. var styletag = document.createElement('style');
  4226. styletag.type = 'text/css';
  4227. if (styletag.styleSheet) {
  4228. // ie
  4229. styletag.styleSheet.cssText = cssbody;
  4230. } else {
  4231. // others
  4232. styletag.appendChild(document.createTextNode(cssbody));
  4233. }
  4234. document.getElementsByTagName("head")[0].appendChild(styletag);
  4235. }
  4236. function createWorkerNode(document) {
  4237. var frameID = 'childframe' // Date.now().toString() + '_' + (Math.random() * 100).toString()
  4238. , frame = document.createElement('iframe')
  4239. InjectCSS(
  4240. '.jsPDF_sillysvg_iframe {display:none;position:absolute;}'
  4241. , document
  4242. )
  4243. frame.name = frameID
  4244. frame.setAttribute("width", 0)
  4245. frame.setAttribute("height", 0)
  4246. frame.setAttribute("frameborder", "0")
  4247. frame.setAttribute("scrolling", "no")
  4248. frame.setAttribute("seamless", "seamless")
  4249. frame.setAttribute("class", "jsPDF_sillysvg_iframe")
  4250. document.body.appendChild(frame)
  4251. return frame
  4252. }
  4253. function attachSVGToWorkerNode(svgtext, frame) {
  4254. var framedoc = (frame.contentWindow || frame.contentDocument).document
  4255. framedoc.write(svgtext)
  4256. framedoc.close()
  4257. return framedoc.getElementsByTagName('svg')[0]
  4258. }
  4259. function convertPathToPDFLinesArgs(path) {
  4260. 'use strict'
  4261. // we will use 'lines' method call. it needs:
  4262. // - starting coordinate pair
  4263. // - array of arrays of vector shifts (2-len for line, 6 len for bezier)
  4264. // - scale array [horizontal, vertical] ratios
  4265. // - style (stroke, fill, both)
  4266. var x = parseFloat(path[1])
  4267. , y = parseFloat(path[2])
  4268. , vectors = []
  4269. , position = 3
  4270. , len = path.length
  4271. while (position < len) {
  4272. if (path[position] === 'c') {
  4273. vectors.push([
  4274. parseFloat(path[position + 1])
  4275. , parseFloat(path[position + 2])
  4276. , parseFloat(path[position + 3])
  4277. , parseFloat(path[position + 4])
  4278. , parseFloat(path[position + 5])
  4279. , parseFloat(path[position + 6])
  4280. ])
  4281. position += 7
  4282. } else if (path[position] === 'l') {
  4283. vectors.push([
  4284. parseFloat(path[position + 1])
  4285. , parseFloat(path[position + 2])
  4286. ])
  4287. position += 3
  4288. } else {
  4289. position += 1
  4290. }
  4291. }
  4292. return [x, y, vectors]
  4293. }
  4294. var workernode = createWorkerNode(document)
  4295. , svgnode = attachSVGToWorkerNode(svgtext, workernode)
  4296. , scale = [1, 1]
  4297. , svgw = parseFloat(svgnode.getAttribute('width'))
  4298. , svgh = parseFloat(svgnode.getAttribute('height'))
  4299. if (svgw && svgh) {
  4300. // setting both w and h makes image stretch to size.
  4301. // this may distort the image, but fits your demanded size
  4302. if (w && h) {
  4303. scale = [w / svgw, h / svgh]
  4304. }
  4305. // if only one is set, that value is set as max and SVG
  4306. // is scaled proportionately.
  4307. else if (w) {
  4308. scale = [w / svgw, w / svgw]
  4309. } else if (h) {
  4310. scale = [h / svgh, h / svgh]
  4311. }
  4312. }
  4313. var i, l, tmp
  4314. , linesargs
  4315. , items = svgnode.childNodes
  4316. for (i = 0, l = items.length; i < l; i++) {
  4317. tmp = items[i]
  4318. if (tmp.tagName && tmp.tagName.toUpperCase() === 'PATH') {
  4319. linesargs = convertPathToPDFLinesArgs(tmp.getAttribute("d").split(' '))
  4320. // path start x coordinate
  4321. linesargs[0] = linesargs[0] * scale[0] + x // where x is upper left X of image
  4322. // path start y coordinate
  4323. linesargs[1] = linesargs[1] * scale[1] + y // where y is upper left Y of image
  4324. // the rest of lines are vectors. these will adjust with scale value auto.
  4325. this.lines.call(
  4326. this
  4327. , linesargs[2] // lines
  4328. , linesargs[0] // starting x
  4329. , linesargs[1] // starting y
  4330. , scale
  4331. )
  4332. }
  4333. }
  4334. // clean up
  4335. // workernode.parentNode.removeChild(workernode)
  4336. return this
  4337. }
  4338. })(jsPDF.API);
  4339. /** @preserve
  4340. * jsPDF split_text_to_size plugin - MIT license.
  4341. * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  4342. * 2014 Diego Casorran, https://github.com/diegocr
  4343. */
  4344. /**
  4345. * Permission is hereby granted, free of charge, to any person obtaining
  4346. * a copy of this software and associated documentation files (the
  4347. * "Software"), to deal in the Software without restriction, including
  4348. * without limitation the rights to use, copy, modify, merge, publish,
  4349. * distribute, sublicense, and/or sell copies of the Software, and to
  4350. * permit persons to whom the Software is furnished to do so, subject to
  4351. * the following conditions:
  4352. *
  4353. * The above copyright notice and this permission notice shall be
  4354. * included in all copies or substantial portions of the Software.
  4355. *
  4356. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  4357. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  4358. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  4359. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  4360. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  4361. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  4362. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  4363. * ====================================================================
  4364. */
  4365. ; (function (API) {
  4366. 'use strict'
  4367. /**
  4368. Returns an array of length matching length of the 'word' string, with each
  4369. cell ocupied by the width of the char in that position.
  4370. @function
  4371. @param word {String}
  4372. @param widths {Object}
  4373. @param kerning {Object}
  4374. @returns {Array}
  4375. */
  4376. var getCharWidthsArray = API.getCharWidthsArray = function (text, options) {
  4377. if (!options) {
  4378. options = {}
  4379. }
  4380. var widths = options.widths ? options.widths : this.internal.getFont().metadata.Unicode.widths
  4381. , widthsFractionOf = widths.fof ? widths.fof : 1
  4382. , kerning = options.kerning ? options.kerning : this.internal.getFont().metadata.Unicode.kerning
  4383. , kerningFractionOf = kerning.fof ? kerning.fof : 1
  4384. // console.log("widths, kergnings", widths, kerning)
  4385. var i, l
  4386. , char_code
  4387. , prior_char_code = 0 // for kerning
  4388. , default_char_width = widths[0] || widthsFractionOf
  4389. , output = []
  4390. for (i = 0, l = text.length; i < l; i++) {
  4391. char_code = text.charCodeAt(i)
  4392. output.push(
  4393. (widths[char_code] || default_char_width) / widthsFractionOf +
  4394. (kerning[char_code] && kerning[char_code][prior_char_code] || 0) / kerningFractionOf
  4395. )
  4396. prior_char_code = char_code
  4397. }
  4398. return output
  4399. }
  4400. var getArraySum = function (array) {
  4401. var i = array.length
  4402. , output = 0
  4403. while (i) {
  4404. ; i--;
  4405. output += array[i]
  4406. }
  4407. return output
  4408. }
  4409. /**
  4410. Returns a widths of string in a given font, if the font size is set as 1 point.
  4411. In other words, this is "proportional" value. For 1 unit of font size, the length
  4412. of the string will be that much.
  4413. Multiply by font size to get actual width in *points*
  4414. Then divide by 72 to get inches or divide by (72/25.6) to get 'mm' etc.
  4415. @public
  4416. @function
  4417. @param
  4418. @returns {Type}
  4419. */
  4420. var getStringUnitWidth = API.getStringUnitWidth = function (text, options) {
  4421. return getArraySum(getCharWidthsArray.call(this, text, options))
  4422. }
  4423. /**
  4424. returns array of lines
  4425. */
  4426. var splitLongWord = function (word, widths_array, firstLineMaxLen, maxLen) {
  4427. var answer = []
  4428. // 1st, chop off the piece that can fit on the hanging line.
  4429. var i = 0
  4430. , l = word.length
  4431. , workingLen = 0
  4432. while (i !== l && workingLen + widths_array[i] < firstLineMaxLen) {
  4433. workingLen += widths_array[i]
  4434. ; i++;
  4435. }
  4436. // this is first line.
  4437. answer.push(word.slice(0, i))
  4438. // 2nd. Split the rest into maxLen pieces.
  4439. var startOfLine = i
  4440. workingLen = 0
  4441. while (i !== l) {
  4442. if (workingLen + widths_array[i] > maxLen) {
  4443. answer.push(word.slice(startOfLine, i))
  4444. workingLen = 0
  4445. startOfLine = i
  4446. }
  4447. workingLen += widths_array[i]
  4448. ; i++;
  4449. }
  4450. if (startOfLine !== i) {
  4451. answer.push(word.slice(startOfLine, i))
  4452. }
  4453. return answer
  4454. }
  4455. // Note, all sizing inputs for this function must be in "font measurement units"
  4456. // By default, for PDF, it's "point".
  4457. var splitParagraphIntoLines = function (text, maxlen, options) {
  4458. // at this time works only on Western scripts, ones with space char
  4459. // separating the words. Feel free to expand.
  4460. if (!options) {
  4461. options = {}
  4462. }
  4463. var line = []
  4464. , lines = [line]
  4465. , line_length = options.textIndent || 0
  4466. , separator_length = 0
  4467. , current_word_length = 0
  4468. , word
  4469. , widths_array
  4470. , words = text.split(' ')
  4471. , spaceCharWidth = getCharWidthsArray(' ', options)[0]
  4472. , i, l, tmp, lineIndent
  4473. if (options.lineIndent === -1) {
  4474. lineIndent = words[0].length + 2;
  4475. } else {
  4476. lineIndent = options.lineIndent || 0;
  4477. }
  4478. if (lineIndent) {
  4479. var pad = Array(lineIndent).join(" "), wrds = [];
  4480. words.map(function (wrd) {
  4481. wrd = wrd.split(/\s*\n/);
  4482. if (wrd.length > 1) {
  4483. wrds = wrds.concat(wrd.map(function (wrd, idx) {
  4484. return (idx && wrd.length ? "\n" : "") + wrd;
  4485. }));
  4486. } else {
  4487. wrds.push(wrd[0]);
  4488. }
  4489. });
  4490. words = wrds;
  4491. lineIndent = getStringUnitWidth(pad, options);
  4492. }
  4493. for (i = 0, l = words.length; i < l; i++) {
  4494. var force = 0;
  4495. word = words[i]
  4496. if (lineIndent && word[0] == "\n") {
  4497. word = word.substr(1);
  4498. force = 1;
  4499. }
  4500. widths_array = getCharWidthsArray(word, options)
  4501. current_word_length = getArraySum(widths_array)
  4502. if (line_length + separator_length + current_word_length > maxlen || force) {
  4503. if (current_word_length > maxlen) {
  4504. // this happens when you have space-less long URLs for example.
  4505. // we just chop these to size. We do NOT insert hiphens
  4506. tmp = splitLongWord(word, widths_array, maxlen - (line_length + separator_length), maxlen)
  4507. // first line we add to existing line object
  4508. line.push(tmp.shift()) // it's ok to have extra space indicator there
  4509. // last line we make into new line object
  4510. line = [tmp.pop()]
  4511. // lines in the middle we apped to lines object as whole lines
  4512. while (tmp.length) {
  4513. lines.push([tmp.shift()]) // single fragment occupies whole line
  4514. }
  4515. current_word_length = getArraySum(widths_array.slice(word.length - line[0].length))
  4516. } else {
  4517. // just put it on a new line
  4518. line = [word]
  4519. }
  4520. // now we attach new line to lines
  4521. lines.push(line)
  4522. line_length = current_word_length + lineIndent
  4523. separator_length = spaceCharWidth
  4524. } else {
  4525. line.push(word)
  4526. line_length += separator_length + current_word_length
  4527. separator_length = spaceCharWidth
  4528. }
  4529. }
  4530. if (lineIndent) {
  4531. var postProcess = function (ln, idx) {
  4532. return (idx ? pad : '') + ln.join(" ");
  4533. };
  4534. } else {
  4535. var postProcess = function (ln) { return ln.join(" ") };
  4536. }
  4537. return lines.map(postProcess);
  4538. }
  4539. /**
  4540. Splits a given string into an array of strings. Uses 'size' value
  4541. (in measurement units declared as default for the jsPDF instance)
  4542. and the font's "widths" and "Kerning" tables, where availabe, to
  4543. determine display length of a given string for a given font.
  4544. We use character's 100% of unit size (height) as width when Width
  4545. table or other default width is not available.
  4546. @public
  4547. @function
  4548. @param text {String} Unencoded, regular JavaScript (Unicode, UTF-16 / UCS-2) string.
  4549. @param size {Number} Nominal number, measured in units default to this instance of jsPDF.
  4550. @param options {Object} Optional flags needed for chopper to do the right thing.
  4551. @returns {Array} with strings chopped to size.
  4552. */
  4553. API.splitTextToSize = function (text, maxlen, options) {
  4554. 'use strict'
  4555. if (!options) {
  4556. options = {}
  4557. }
  4558. var fsize = options.fontSize || this.internal.getFontSize()
  4559. , newOptions = (function (options) {
  4560. var widths = { 0: 1 }
  4561. , kerning = {}
  4562. if (!options.widths || !options.kerning) {
  4563. var f = this.internal.getFont(options.fontName, options.fontStyle)
  4564. , encoding = 'Unicode'
  4565. // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE
  4566. // Actual JavaScript-native String's 16bit char codes used.
  4567. // no multi-byte logic here
  4568. if (f.metadata[encoding]) {
  4569. return {
  4570. widths: f.metadata[encoding].widths || widths
  4571. , kerning: f.metadata[encoding].kerning || kerning
  4572. }
  4573. }
  4574. } else {
  4575. return {
  4576. widths: options.widths
  4577. , kerning: options.kerning
  4578. }
  4579. }
  4580. // then use default values
  4581. return {
  4582. widths: widths
  4583. , kerning: kerning
  4584. }
  4585. }).call(this, options)
  4586. // first we split on end-of-line chars
  4587. var paragraphs
  4588. if (Array.isArray(text)) {
  4589. paragraphs = text;
  4590. } else {
  4591. paragraphs = text.split(/\r?\n/);
  4592. }
  4593. // now we convert size (max length of line) into "font size units"
  4594. // at present time, the "font size unit" is always 'point'
  4595. // 'proportional' means, "in proportion to font size"
  4596. var fontUnit_maxLen = 1.0 * this.internal.scaleFactor * maxlen / fsize
  4597. // at this time, fsize is always in "points" regardless of the default measurement unit of the doc.
  4598. // this may change in the future?
  4599. // until then, proportional_maxlen is likely to be in 'points'
  4600. // If first line is to be indented (shorter or longer) than maxLen
  4601. // we indicate that by using CSS-style "text-indent" option.
  4602. // here it's in font units too (which is likely 'points')
  4603. // it can be negative (which makes the first line longer than maxLen)
  4604. newOptions.textIndent = options.textIndent ?
  4605. options.textIndent * 1.0 * this.internal.scaleFactor / fsize :
  4606. 0
  4607. newOptions.lineIndent = options.lineIndent;
  4608. var i, l
  4609. , output = []
  4610. for (i = 0, l = paragraphs.length; i < l; i++) {
  4611. output = output.concat(
  4612. splitParagraphIntoLines(
  4613. paragraphs[i]
  4614. , fontUnit_maxLen
  4615. , newOptions
  4616. )
  4617. )
  4618. }
  4619. return output
  4620. }
  4621. })(jsPDF.API);
  4622. /** @preserve
  4623. jsPDF standard_fonts_metrics plugin
  4624. Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  4625. MIT license.
  4626. */
  4627. /**
  4628. * Permission is hereby granted, free of charge, to any person obtaining
  4629. * a copy of this software and associated documentation files (the
  4630. * "Software"), to deal in the Software without restriction, including
  4631. * without limitation the rights to use, copy, modify, merge, publish,
  4632. * distribute, sublicense, and/or sell copies of the Software, and to
  4633. * permit persons to whom the Software is furnished to do so, subject to
  4634. * the following conditions:
  4635. *
  4636. * The above copyright notice and this permission notice shall be
  4637. * included in all copies or substantial portions of the Software.
  4638. *
  4639. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  4640. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  4641. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  4642. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  4643. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  4644. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  4645. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  4646. * ====================================================================
  4647. */
  4648. ; (function (API) {
  4649. 'use strict'
  4650. /*
  4651. # reference (Python) versions of 'compress' and 'uncompress'
  4652. # only 'uncompress' function is featured lower as JavaScript
  4653. # if you want to unit test "roundtrip", just transcribe the reference
  4654. # 'compress' function from Python into JavaScript
  4655. def compress(data):
  4656. keys = '0123456789abcdef'
  4657. values = 'klmnopqrstuvwxyz'
  4658. mapping = dict(zip(keys, values))
  4659. vals = []
  4660. for key in data.keys():
  4661. value = data[key]
  4662. try:
  4663. keystring = hex(key)[2:]
  4664. keystring = keystring[:-1] + mapping[keystring[-1:]]
  4665. except:
  4666. keystring = key.join(["'","'"])
  4667. #print('Keystring is %s' % keystring)
  4668. try:
  4669. if value < 0:
  4670. valuestring = hex(value)[3:]
  4671. numberprefix = '-'
  4672. else:
  4673. valuestring = hex(value)[2:]
  4674. numberprefix = ''
  4675. valuestring = numberprefix + valuestring[:-1] + mapping[valuestring[-1:]]
  4676. except:
  4677. if type(value) == dict:
  4678. valuestring = compress(value)
  4679. else:
  4680. raise Exception("Don't know what to do with value type %s" % type(value))
  4681. vals.append(keystring+valuestring)
  4682. return '{' + ''.join(vals) + '}'
  4683. def uncompress(data):
  4684. decoded = '0123456789abcdef'
  4685. encoded = 'klmnopqrstuvwxyz'
  4686. mapping = dict(zip(encoded, decoded))
  4687. sign = +1
  4688. stringmode = False
  4689. stringparts = []
  4690. output = {}
  4691. activeobject = output
  4692. parentchain = []
  4693. keyparts = ''
  4694. valueparts = ''
  4695. key = None
  4696. ending = set(encoded)
  4697. i = 1
  4698. l = len(data) - 1 # stripping starting, ending {}
  4699. while i != l: # stripping {}
  4700. # -, {, }, ' are special.
  4701. ch = data[i]
  4702. i += 1
  4703. if ch == "'":
  4704. if stringmode:
  4705. # end of string mode
  4706. stringmode = False
  4707. key = ''.join(stringparts)
  4708. else:
  4709. # start of string mode
  4710. stringmode = True
  4711. stringparts = []
  4712. elif stringmode == True:
  4713. #print("Adding %s to stringpart" % ch)
  4714. stringparts.append(ch)
  4715. elif ch == '{':
  4716. # start of object
  4717. parentchain.append( [activeobject, key] )
  4718. activeobject = {}
  4719. key = None
  4720. #DEBUG = True
  4721. elif ch == '}':
  4722. # end of object
  4723. parent, key = parentchain.pop()
  4724. parent[key] = activeobject
  4725. key = None
  4726. activeobject = parent
  4727. #DEBUG = False
  4728. elif ch == '-':
  4729. sign = -1
  4730. else:
  4731. # must be number
  4732. if key == None:
  4733. #debug("In Key. It is '%s', ch is '%s'" % (keyparts, ch))
  4734. if ch in ending:
  4735. #debug("End of key")
  4736. keyparts += mapping[ch]
  4737. key = int(keyparts, 16) * sign
  4738. sign = +1
  4739. keyparts = ''
  4740. else:
  4741. keyparts += ch
  4742. else:
  4743. #debug("In value. It is '%s', ch is '%s'" % (valueparts, ch))
  4744. if ch in ending:
  4745. #debug("End of value")
  4746. valueparts += mapping[ch]
  4747. activeobject[key] = int(valueparts, 16) * sign
  4748. sign = +1
  4749. key = None
  4750. valueparts = ''
  4751. else:
  4752. valueparts += ch
  4753. #debug(activeobject)
  4754. return output
  4755. */
  4756. /**
  4757. Uncompresses data compressed into custom, base16-like format.
  4758. @public
  4759. @function
  4760. @param
  4761. @returns {Type}
  4762. */
  4763. var uncompress = function (data) {
  4764. var decoded = '0123456789abcdef'
  4765. , encoded = 'klmnopqrstuvwxyz'
  4766. , mapping = {}
  4767. for (var i = 0; i < encoded.length; i++) {
  4768. mapping[encoded[i]] = decoded[i]
  4769. }
  4770. var undef
  4771. , output = {}
  4772. , sign = 1
  4773. , stringparts // undef. will be [] in string mode
  4774. , activeobject = output
  4775. , parentchain = []
  4776. , parent_key_pair
  4777. , keyparts = ''
  4778. , valueparts = ''
  4779. , key // undef. will be Truthy when Key is resolved.
  4780. , datalen = data.length - 1 // stripping ending }
  4781. , ch
  4782. i = 1 // stripping starting {
  4783. while (i != datalen) {
  4784. // - { } ' are special.
  4785. ch = data[i]
  4786. i += 1
  4787. if (ch == "'") {
  4788. if (stringparts) {
  4789. // end of string mode
  4790. key = stringparts.join('')
  4791. stringparts = undef
  4792. } else {
  4793. // start of string mode
  4794. stringparts = []
  4795. }
  4796. } else if (stringparts) {
  4797. stringparts.push(ch)
  4798. } else if (ch == '{') {
  4799. // start of object
  4800. parentchain.push([activeobject, key])
  4801. activeobject = {}
  4802. key = undef
  4803. } else if (ch == '}') {
  4804. // end of object
  4805. parent_key_pair = parentchain.pop()
  4806. parent_key_pair[0][parent_key_pair[1]] = activeobject
  4807. key = undef
  4808. activeobject = parent_key_pair[0]
  4809. } else if (ch == '-') {
  4810. sign = -1
  4811. } else {
  4812. // must be number
  4813. if (key === undef) {
  4814. if (mapping.hasOwnProperty(ch)) {
  4815. keyparts += mapping[ch]
  4816. key = parseInt(keyparts, 16) * sign
  4817. sign = +1
  4818. keyparts = ''
  4819. } else {
  4820. keyparts += ch
  4821. }
  4822. } else {
  4823. if (mapping.hasOwnProperty(ch)) {
  4824. valueparts += mapping[ch]
  4825. activeobject[key] = parseInt(valueparts, 16) * sign
  4826. sign = +1
  4827. key = undef
  4828. valueparts = ''
  4829. } else {
  4830. valueparts += ch
  4831. }
  4832. }
  4833. }
  4834. } // end while
  4835. return output
  4836. }
  4837. // encoding = 'Unicode'
  4838. // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE. NO clever BOM behavior
  4839. // Actual 16bit char codes used.
  4840. // no multi-byte logic here
  4841. // Unicode characters to WinAnsiEncoding:
  4842. // {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}
  4843. // as you can see, all Unicode chars are outside of 0-255 range. No char code conflicts.
  4844. // this means that you can give Win cp1252 encoded strings to jsPDF for rendering directly
  4845. // as well as give strings with some (supported by these fonts) Unicode characters and
  4846. // these will be mapped to win cp1252
  4847. // for example, you can send char code (cp1252) 0x80 or (unicode) 0x20AC, getting "Euro" glyph displayed in both cases.
  4848. var encodingBlock = {
  4849. 'codePages': ['WinAnsiEncoding']
  4850. , 'WinAnsiEncoding': uncompress("{19m8n201n9q201o9r201s9l201t9m201u8m201w9n201x9o201y8o202k8q202l8r202m9p202q8p20aw8k203k8t203t8v203u9v2cq8s212m9t15m8w15n9w2dw9s16k8u16l9u17s9z17x8y17y9y}")
  4851. }
  4852. , encodings = {
  4853. 'Unicode': {
  4854. 'Courier': encodingBlock
  4855. , 'Courier-Bold': encodingBlock
  4856. , 'Courier-BoldOblique': encodingBlock
  4857. , 'Courier-Oblique': encodingBlock
  4858. , 'Helvetica': encodingBlock
  4859. , 'Helvetica-Bold': encodingBlock
  4860. , 'Helvetica-BoldOblique': encodingBlock
  4861. , 'Helvetica-Oblique': encodingBlock
  4862. , 'Times-Roman': encodingBlock
  4863. , 'Times-Bold': encodingBlock
  4864. , 'Times-BoldItalic': encodingBlock
  4865. , 'Times-Italic': encodingBlock
  4866. // , 'Symbol'
  4867. // , 'ZapfDingbats'
  4868. }
  4869. }
  4870. /**
  4871. Resources:
  4872. Font metrics data is reprocessed derivative of contents of
  4873. "Font Metrics for PDF Core 14 Fonts" package, which exhibits the following copyright and license:
  4874. Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
  4875. This file and the 14 PostScript(R) AFM files it accompanies may be used,
  4876. copied, and distributed for any purpose and without charge, with or without
  4877. modification, provided that all copyright notices are retained; that the AFM
  4878. files are not distributed without this file; that all modifications to this
  4879. file or any of the AFM files are prominently noted in the modified file(s);
  4880. and that this paragraph is not modified. Adobe Systems has no responsibility
  4881. or obligation to support the use of the AFM files.
  4882. */
  4883. , fontMetrics = {
  4884. 'Unicode': {
  4885. // all sizing numbers are n/fontMetricsFractionOf = one font size unit
  4886. // this means that if fontMetricsFractionOf = 1000, and letter A's width is 476, it's
  4887. // width is 476/1000 or 47.6% of its height (regardless of font size)
  4888. // At this time this value applies to "widths" and "kerning" numbers.
  4889. // char code 0 represents "default" (average) width - use it for chars missing in this table.
  4890. // key 'fof' represents the "fontMetricsFractionOf" value
  4891. 'Courier-Oblique': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
  4892. , '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}}}")
  4893. , 'Helvetica-Bold': uncompress("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}")
  4894. , 'Courier': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
  4895. , 'Courier-BoldOblique': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
  4896. , '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}}}")
  4897. //, 'Symbol': uncompress("{'widths'{k3uaw4r19m3m2k1t2l2l202m2y2n3m2p5n202q6o3k3m2s2l2t2l2v3r2w1t3m3m2y1t2z1wbk2sbl3r'fof'6o3n3m3o3m3p3m3q3m3r3m3s3m3t3m3u1w3v1w3w3r3x3r3y3r3z2wbp3t3l3m5v2l5x2l5z3m2q4yfr3r7v3k7w1o7x3k}'kerning'{'fof'-6o}}")
  4898. , 'Helvetica': uncompress("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}")
  4899. , 'Helvetica-BoldOblique': uncompress("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}")
  4900. //, 'ZapfDingbats': uncompress("{'widths'{k4u2k1w'fof'6o}'kerning'{'fof'-6o}}")
  4901. , 'Courier-Bold': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
  4902. , '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}fv{17su5tu5qs}fw{17su5tu5qs}}}")
  4903. , '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}}}")
  4904. , 'Helvetica-Oblique': uncompress("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}")
  4905. }
  4906. };
  4907. /*
  4908. This event handler is fired when a new jsPDF object is initialized
  4909. This event handler appends metrics data to standard fonts within
  4910. that jsPDF instance. The metrics are mapped over Unicode character
  4911. codes, NOT CIDs or other codes matching the StandardEncoding table of the
  4912. standard PDF fonts.
  4913. Future:
  4914. Also included is the encoding maping table, converting Unicode (UCS-2, UTF-16)
  4915. char codes to StandardEncoding character codes. The encoding table is to be used
  4916. somewhere around "pdfEscape" call.
  4917. */
  4918. API.events.push([
  4919. 'addFonts'
  4920. , function (fontManagementObjects) {
  4921. // fontManagementObjects is {
  4922. // 'fonts':font_ID-keyed hash of font objects
  4923. // , 'dictionary': lookup object, linking ["FontFamily"]['Style'] to font ID
  4924. //}
  4925. var font
  4926. , fontID
  4927. , metrics
  4928. , unicode_section
  4929. , encoding = 'Unicode'
  4930. , encodingBlock
  4931. for (fontID in fontManagementObjects.fonts) {
  4932. if (fontManagementObjects.fonts.hasOwnProperty(fontID)) {
  4933. font = fontManagementObjects.fonts[fontID]
  4934. // // we only ship 'Unicode' mappings and metrics. No need for loop.
  4935. // // still, leaving this for the future.
  4936. // for (encoding in fontMetrics){
  4937. // if (fontMetrics.hasOwnProperty(encoding)) {
  4938. metrics = fontMetrics[encoding][font.PostScriptName]
  4939. if (metrics) {
  4940. if (font.metadata[encoding]) {
  4941. unicode_section = font.metadata[encoding]
  4942. } else {
  4943. unicode_section = font.metadata[encoding] = {}
  4944. }
  4945. unicode_section.widths = metrics.widths
  4946. unicode_section.kerning = metrics.kerning
  4947. }
  4948. // }
  4949. // }
  4950. // for (encoding in encodings){
  4951. // if (encodings.hasOwnProperty(encoding)) {
  4952. encodingBlock = encodings[encoding][font.PostScriptName]
  4953. if (encodingBlock) {
  4954. if (font.metadata[encoding]) {
  4955. unicode_section = font.metadata[encoding]
  4956. } else {
  4957. unicode_section = font.metadata[encoding] = {}
  4958. }
  4959. unicode_section.encoding = encodingBlock
  4960. if (encodingBlock.codePages && encodingBlock.codePages.length) {
  4961. font.encoding = encodingBlock.codePages[0]
  4962. }
  4963. }
  4964. // }
  4965. // }
  4966. }
  4967. }
  4968. }
  4969. ]) // end of adding event handler
  4970. })(jsPDF.API);
  4971. /** ====================================================================
  4972. * jsPDF total_pages plugin
  4973. * Copyright (c) 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br
  4974. *
  4975. * Permission is hereby granted, free of charge, to any person obtaining
  4976. * a copy of this software and associated documentation files (the
  4977. * "Software"), to deal in the Software without restriction, including
  4978. * without limitation the rights to use, copy, modify, merge, publish,
  4979. * distribute, sublicense, and/or sell copies of the Software, and to
  4980. * permit persons to whom the Software is furnished to do so, subject to
  4981. * the following conditions:
  4982. *
  4983. * The above copyright notice and this permission notice shall be
  4984. * included in all copies or substantial portions of the Software.
  4985. *
  4986. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  4987. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  4988. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  4989. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  4990. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  4991. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  4992. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  4993. * ====================================================================
  4994. */
  4995. (function (jsPDFAPI) {
  4996. 'use strict';
  4997. jsPDFAPI.putTotalPages = function (pageExpression) {
  4998. 'use strict';
  4999. var replaceExpression = new RegExp(pageExpression, 'g');
  5000. for (var n = 1; n <= this.internal.getNumberOfPages(); n++) {
  5001. for (var i = 0; i < this.internal.pages[n].length; i++)
  5002. this.internal.pages[n][i] = this.internal.pages[n][i].replace(replaceExpression, this.internal.getNumberOfPages());
  5003. }
  5004. return this;
  5005. };
  5006. })(jsPDF.API);
  5007. /* Blob.js
  5008. * A Blob implementation.
  5009. * 2014-07-24
  5010. *
  5011. * By Eli Grey, http://eligrey.com
  5012. * By Devin Samarin, https://github.com/dsamarin
  5013. * License: X11/MIT
  5014. * See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
  5015. */
  5016. /*global self, unescape */
  5017. /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
  5018. plusplus: true */
  5019. /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
  5020. (function (view) {
  5021. "use strict";
  5022. view.URL = view.URL || view.webkitURL;
  5023. if (view.Blob && view.URL) {
  5024. try {
  5025. new Blob;
  5026. return;
  5027. } catch (e) { }
  5028. }
  5029. // Internally we use a BlobBuilder implementation to base Blob off of
  5030. // in order to support older browsers that only have BlobBuilder
  5031. var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function (view) {
  5032. var
  5033. get_class = function (object) {
  5034. return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
  5035. }
  5036. , FakeBlobBuilder = function BlobBuilder() {
  5037. this.data = [];
  5038. }
  5039. , FakeBlob = function Blob(data, type, encoding) {
  5040. this.data = data;
  5041. this.size = data.length;
  5042. this.type = type;
  5043. this.encoding = encoding;
  5044. }
  5045. , FBB_proto = FakeBlobBuilder.prototype
  5046. , FB_proto = FakeBlob.prototype
  5047. , FileReaderSync = view.FileReaderSync
  5048. , FileException = function (type) {
  5049. this.code = this[this.name = type];
  5050. }
  5051. , file_ex_codes = (
  5052. "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
  5053. + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
  5054. ).split(" ")
  5055. , file_ex_code = file_ex_codes.length
  5056. , real_URL = view.URL || view.webkitURL || view
  5057. , real_create_object_URL = real_URL.createObjectURL
  5058. , real_revoke_object_URL = real_URL.revokeObjectURL
  5059. , URL = real_URL
  5060. , btoa = view.btoa
  5061. , atob = view.atob
  5062. , ArrayBuffer = view.ArrayBuffer
  5063. , Uint8Array = view.Uint8Array
  5064. , origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/
  5065. ;
  5066. FakeBlob.fake = FB_proto.fake = true;
  5067. while (file_ex_code--) {
  5068. FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
  5069. }
  5070. // Polyfill URL
  5071. if (!real_URL.createObjectURL) {
  5072. URL = view.URL = function (uri) {
  5073. var
  5074. uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
  5075. , uri_origin
  5076. ;
  5077. uri_info.href = uri;
  5078. if (!("origin" in uri_info)) {
  5079. if (uri_info.protocol.toLowerCase() === "data:") {
  5080. uri_info.origin = null;
  5081. } else {
  5082. uri_origin = uri.match(origin);
  5083. uri_info.origin = uri_origin && uri_origin[1];
  5084. }
  5085. }
  5086. return uri_info;
  5087. };
  5088. }
  5089. URL.createObjectURL = function (blob) {
  5090. var
  5091. type = blob.type
  5092. , data_URI_header
  5093. ;
  5094. if (type === null) {
  5095. type = "application/octet-stream";
  5096. }
  5097. if (blob instanceof FakeBlob) {
  5098. data_URI_header = "data:" + type;
  5099. if (blob.encoding === "base64") {
  5100. return data_URI_header + ";base64," + blob.data;
  5101. } else if (blob.encoding === "URI") {
  5102. return data_URI_header + "," + decodeURIComponent(blob.data);
  5103. } if (btoa) {
  5104. return data_URI_header + ";base64," + btoa(blob.data);
  5105. } else {
  5106. return data_URI_header + "," + encodeURIComponent(blob.data);
  5107. }
  5108. } else if (real_create_object_URL) {
  5109. return real_create_object_URL.call(real_URL, blob);
  5110. }
  5111. };
  5112. URL.revokeObjectURL = function (object_URL) {
  5113. if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
  5114. real_revoke_object_URL.call(real_URL, object_URL);
  5115. }
  5116. };
  5117. FBB_proto.append = function (data/*, endings*/) {
  5118. var bb = this.data;
  5119. // decode data to a binary string
  5120. if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
  5121. var
  5122. str = ""
  5123. , buf = new Uint8Array(data)
  5124. , i = 0
  5125. , buf_len = buf.length
  5126. ;
  5127. for (; i < buf_len; i++) {
  5128. str += String.fromCharCode(buf[i]);
  5129. }
  5130. bb.push(str);
  5131. } else if (get_class(data) === "Blob" || get_class(data) === "File") {
  5132. if (FileReaderSync) {
  5133. var fr = new FileReaderSync;
  5134. bb.push(fr.readAsBinaryString(data));
  5135. } else {
  5136. // async FileReader won't work as BlobBuilder is sync
  5137. throw new FileException("NOT_READABLE_ERR");
  5138. }
  5139. } else if (data instanceof FakeBlob) {
  5140. if (data.encoding === "base64" && atob) {
  5141. bb.push(atob(data.data));
  5142. } else if (data.encoding === "URI") {
  5143. bb.push(decodeURIComponent(data.data));
  5144. } else if (data.encoding === "raw") {
  5145. bb.push(data.data);
  5146. }
  5147. } else {
  5148. if (typeof data !== "string") {
  5149. data += ""; // convert unsupported types to strings
  5150. }
  5151. // decode UTF-16 to binary string
  5152. bb.push(unescape(encodeURIComponent(data)));
  5153. }
  5154. };
  5155. FBB_proto.getBlob = function (type) {
  5156. if (!arguments.length) {
  5157. type = null;
  5158. }
  5159. return new FakeBlob(this.data.join(""), type, "raw");
  5160. };
  5161. FBB_proto.toString = function () {
  5162. return "[object BlobBuilder]";
  5163. };
  5164. FB_proto.slice = function (start, end, type) {
  5165. var args = arguments.length;
  5166. if (args < 3) {
  5167. type = null;
  5168. }
  5169. return new FakeBlob(
  5170. this.data.slice(start, args > 1 ? end : this.data.length)
  5171. , type
  5172. , this.encoding
  5173. );
  5174. };
  5175. FB_proto.toString = function () {
  5176. return "[object Blob]";
  5177. };
  5178. FB_proto.close = function () {
  5179. this.size = 0;
  5180. delete this.data;
  5181. };
  5182. return FakeBlobBuilder;
  5183. }(view));
  5184. view.Blob = function (blobParts, options) {
  5185. var type = options ? (options.type || "") : "";
  5186. var builder = new BlobBuilder();
  5187. if (blobParts) {
  5188. for (var i = 0, len = blobParts.length; i < len; i++) {
  5189. builder.append(blobParts[i]);
  5190. }
  5191. }
  5192. return builder.getBlob(type);
  5193. };
  5194. }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));
  5195. /* FileSaver.js
  5196. * A saveAs() FileSaver implementation.
  5197. * 2014-08-29
  5198. *
  5199. * By Eli Grey, http://eligrey.com
  5200. * License: X11/MIT
  5201. * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
  5202. */
  5203. /*global self */
  5204. /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
  5205. /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
  5206. var saveAs = saveAs
  5207. // IE 10+ (native saveAs)
  5208. || (typeof navigator !== "undefined" &&
  5209. navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
  5210. // Everyone else
  5211. || (function (view) {
  5212. "use strict";
  5213. // IE <10 is explicitly unsupported
  5214. if (typeof navigator !== "undefined" &&
  5215. /MSIE [1-9]\./.test(navigator.userAgent)) {
  5216. return;
  5217. }
  5218. var
  5219. doc = view.document
  5220. // only get URL when necessary in case Blob.js hasn't overridden it yet
  5221. , get_URL = function () {
  5222. return view.URL || view.webkitURL || view;
  5223. }
  5224. , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
  5225. , can_use_save_link = "download" in save_link
  5226. , click = function (node) {
  5227. var event = doc.createEvent("MouseEvents");
  5228. event.initMouseEvent(
  5229. "click", true, false, view, 0, 0, 0, 0, 0
  5230. , false, false, false, false, 0, null
  5231. );
  5232. node.dispatchEvent(event);
  5233. }
  5234. , webkit_req_fs = view.webkitRequestFileSystem
  5235. , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
  5236. , throw_outside = function (ex) {
  5237. (view.setImmediate || view.setTimeout)(function () {
  5238. throw ex;
  5239. }, 0);
  5240. }
  5241. , force_saveable_type = "application/octet-stream"
  5242. , fs_min_size = 0
  5243. // See https://code.google.com/p/chromium/issues/detail?id=375297#c7 for
  5244. // the reasoning behind the timeout and revocation flow
  5245. , arbitrary_revoke_timeout = 10
  5246. , revoke = function (file) {
  5247. var revoker = function () {
  5248. if (typeof file === "string") { // file is an object URL
  5249. get_URL().revokeObjectURL(file);
  5250. } else { // file is a File
  5251. file.remove();
  5252. }
  5253. };
  5254. if (view.chrome) {
  5255. revoker();
  5256. } else {
  5257. setTimeout(revoker, arbitrary_revoke_timeout);
  5258. }
  5259. }
  5260. , dispatch = function (filesaver, event_types, event) {
  5261. event_types = [].concat(event_types);
  5262. var i = event_types.length;
  5263. while (i--) {
  5264. var listener = filesaver["on" + event_types[i]];
  5265. if (typeof listener === "function") {
  5266. try {
  5267. listener.call(filesaver, event || filesaver);
  5268. } catch (ex) {
  5269. throw_outside(ex);
  5270. }
  5271. }
  5272. }
  5273. }
  5274. , FileSaver = function (blob, name) {
  5275. // First try a.download, then web filesystem, then object URLs
  5276. var
  5277. filesaver = this
  5278. , type = blob.type
  5279. , blob_changed = false
  5280. , object_url
  5281. , target_view
  5282. , dispatch_all = function () {
  5283. dispatch(filesaver, "writestart progress write writeend".split(" "));
  5284. }
  5285. // on any filesys errors revert to saving with object URLs
  5286. , fs_error = function () {
  5287. // don't create more object URLs than needed
  5288. if (blob_changed || !object_url) {
  5289. object_url = get_URL().createObjectURL(blob);
  5290. }
  5291. if (target_view) {
  5292. target_view.location.href = object_url;
  5293. } else {
  5294. var new_tab = view.open(object_url, "_blank");
  5295. if (new_tab == undefined && typeof safari !== "undefined") {
  5296. //Apple do not allow window.open, see http://bit.ly/1kZffRI
  5297. view.location.href = object_url
  5298. }
  5299. }
  5300. filesaver.readyState = filesaver.DONE;
  5301. dispatch_all();
  5302. revoke(object_url);
  5303. }
  5304. , abortable = function (func) {
  5305. return function () {
  5306. if (filesaver.readyState !== filesaver.DONE) {
  5307. return func.apply(this, arguments);
  5308. }
  5309. };
  5310. }
  5311. , create_if_not_found = { create: true, exclusive: false }
  5312. , slice
  5313. ;
  5314. filesaver.readyState = filesaver.INIT;
  5315. if (!name) {
  5316. name = "download";
  5317. }
  5318. if (can_use_save_link) {
  5319. object_url = get_URL().createObjectURL(blob);
  5320. save_link.href = object_url;
  5321. save_link.download = name;
  5322. click(save_link);
  5323. filesaver.readyState = filesaver.DONE;
  5324. dispatch_all();
  5325. revoke(object_url);
  5326. return;
  5327. }
  5328. // Object and web filesystem URLs have a problem saving in Google Chrome when
  5329. // viewed in a tab, so I force save with application/octet-stream
  5330. // http://code.google.com/p/chromium/issues/detail?id=91158
  5331. // Update: Google errantly closed 91158, I submitted it again:
  5332. // https://code.google.com/p/chromium/issues/detail?id=389642
  5333. if (view.chrome && type && type !== force_saveable_type) {
  5334. slice = blob.slice || blob.webkitSlice;
  5335. blob = slice.call(blob, 0, blob.size, force_saveable_type);
  5336. blob_changed = true;
  5337. }
  5338. // Since I can't be sure that the guessed media type will trigger a download
  5339. // in WebKit, I append .download to the filename.
  5340. // https://bugs.webkit.org/show_bug.cgi?id=65440
  5341. if (webkit_req_fs && name !== "download") {
  5342. name += ".download";
  5343. }
  5344. if (type === force_saveable_type || webkit_req_fs) {
  5345. target_view = view;
  5346. }
  5347. if (!req_fs) {
  5348. fs_error();
  5349. return;
  5350. }
  5351. fs_min_size += blob.size;
  5352. req_fs(view.TEMPORARY, fs_min_size, abortable(function (fs) {
  5353. fs.root.getDirectory("saved", create_if_not_found, abortable(function (dir) {
  5354. var save = function () {
  5355. dir.getFile(name, create_if_not_found, abortable(function (file) {
  5356. file.createWriter(abortable(function (writer) {
  5357. writer.onwriteend = function (event) {
  5358. target_view.location.href = file.toURL();
  5359. filesaver.readyState = filesaver.DONE;
  5360. dispatch(filesaver, "writeend", event);
  5361. revoke(file);
  5362. };
  5363. writer.onerror = function () {
  5364. var error = writer.error;
  5365. if (error.code !== error.ABORT_ERR) {
  5366. fs_error();
  5367. }
  5368. };
  5369. "writestart progress write abort".split(" ").forEach(function (event) {
  5370. writer["on" + event] = filesaver["on" + event];
  5371. });
  5372. writer.write(blob);
  5373. filesaver.abort = function () {
  5374. writer.abort();
  5375. filesaver.readyState = filesaver.DONE;
  5376. };
  5377. filesaver.readyState = filesaver.WRITING;
  5378. }), fs_error);
  5379. }), fs_error);
  5380. };
  5381. dir.getFile(name, { create: false }, abortable(function (file) {
  5382. // delete file if it already exists
  5383. file.remove();
  5384. save();
  5385. }), abortable(function (ex) {
  5386. if (ex.code === ex.NOT_FOUND_ERR) {
  5387. save();
  5388. } else {
  5389. fs_error();
  5390. }
  5391. }));
  5392. }), fs_error);
  5393. }), fs_error);
  5394. }
  5395. , FS_proto = FileSaver.prototype
  5396. , saveAs = function (blob, name) {
  5397. return new FileSaver(blob, name);
  5398. }
  5399. ;
  5400. FS_proto.abort = function () {
  5401. var filesaver = this;
  5402. filesaver.readyState = filesaver.DONE;
  5403. dispatch(filesaver, "abort");
  5404. };
  5405. FS_proto.readyState = FS_proto.INIT = 0;
  5406. FS_proto.WRITING = 1;
  5407. FS_proto.DONE = 2;
  5408. FS_proto.error =
  5409. FS_proto.onwritestart =
  5410. FS_proto.onprogress =
  5411. FS_proto.onwrite =
  5412. FS_proto.onabort =
  5413. FS_proto.onerror =
  5414. FS_proto.onwriteend =
  5415. null;
  5416. return saveAs;
  5417. }(
  5418. typeof self !== "undefined" && self
  5419. || typeof window !== "undefined" && window
  5420. || this.content
  5421. ));
  5422. // `self` is undefined in Firefox for Android content script context
  5423. // while `this` is nsIContentFrameMessageManager
  5424. // with an attribute `content` that corresponds to the window
  5425. if (typeof module !== "undefined" && module !== null) {
  5426. module.exports = saveAs;
  5427. } else if ((typeof define !== "undefined" && 0)) {
  5428. define([], function () {
  5429. return saveAs;
  5430. });
  5431. }
  5432. /*
  5433. * Copyright (c) 2012 chick307 <chick307@gmail.com>
  5434. *
  5435. * Licensed under the MIT License.
  5436. * http://opensource.org/licenses/mit-license
  5437. */
  5438. void function (global, callback) {
  5439. if (typeof module === 'object') {
  5440. module.exports = callback();
  5441. } else if (0 === 'function') {
  5442. define(callback);
  5443. } else {
  5444. global.adler32cs = callback();
  5445. }
  5446. }(jsPDF, function () {
  5447. var _hasArrayBuffer = typeof ArrayBuffer === 'function' &&
  5448. typeof Uint8Array === 'function';
  5449. var _Buffer = null, _isBuffer = (function () {
  5450. if (!_hasArrayBuffer)
  5451. return function _isBuffer() { return false };
  5452. try {
  5453. var buffer = require('buffer');
  5454. if (typeof buffer.Buffer === 'function')
  5455. _Buffer = buffer.Buffer;
  5456. } catch (error) { }
  5457. return function _isBuffer(value) {
  5458. return value instanceof ArrayBuffer ||
  5459. _Buffer !== null && value instanceof _Buffer;
  5460. };
  5461. }());
  5462. var _utf8ToBinary = (function () {
  5463. if (_Buffer !== null) {
  5464. return function _utf8ToBinary(utf8String) {
  5465. return new _Buffer(utf8String, 'utf8').toString('binary');
  5466. };
  5467. } else {
  5468. return function _utf8ToBinary(utf8String) {
  5469. return unescape(encodeURIComponent(utf8String));
  5470. };
  5471. }
  5472. }());
  5473. var MOD = 65521;
  5474. var _update = function _update(checksum, binaryString) {
  5475. var a = checksum & 0xFFFF, b = checksum >>> 16;
  5476. for (var i = 0, length = binaryString.length; i < length; i++) {
  5477. a = (a + (binaryString.charCodeAt(i) & 0xFF)) % MOD;
  5478. b = (b + a) % MOD;
  5479. }
  5480. return (b << 16 | a) >>> 0;
  5481. };
  5482. var _updateUint8Array = function _updateUint8Array(checksum, uint8Array) {
  5483. var a = checksum & 0xFFFF, b = checksum >>> 16;
  5484. for (var i = 0, length = uint8Array.length, x; i < length; i++) {
  5485. a = (a + uint8Array[i]) % MOD;
  5486. b = (b + a) % MOD;
  5487. }
  5488. return (b << 16 | a) >>> 0
  5489. };
  5490. var exports = {};
  5491. var Adler32 = exports.Adler32 = (function () {
  5492. var ctor = function Adler32(checksum) {
  5493. if (!(this instanceof ctor)) {
  5494. throw new TypeError(
  5495. 'Constructor cannot called be as a function.');
  5496. }
  5497. if (!isFinite(checksum = checksum == null ? 1 : +checksum)) {
  5498. throw new Error(
  5499. 'First arguments needs to be a finite number.');
  5500. }
  5501. this.checksum = checksum >>> 0;
  5502. };
  5503. var proto = ctor.prototype = {};
  5504. proto.constructor = ctor;
  5505. ctor.from = function (from) {
  5506. from.prototype = proto;
  5507. return from;
  5508. }(function from(binaryString) {
  5509. if (!(this instanceof ctor)) {
  5510. throw new TypeError(
  5511. 'Constructor cannot called be as a function.');
  5512. }
  5513. if (binaryString == null)
  5514. throw new Error('First argument needs to be a string.');
  5515. this.checksum = _update(1, binaryString.toString());
  5516. });
  5517. ctor.fromUtf8 = function (fromUtf8) {
  5518. fromUtf8.prototype = proto;
  5519. return fromUtf8;
  5520. }(function fromUtf8(utf8String) {
  5521. if (!(this instanceof ctor)) {
  5522. throw new TypeError(
  5523. 'Constructor cannot called be as a function.');
  5524. }
  5525. if (utf8String == null)
  5526. throw new Error('First argument needs to be a string.');
  5527. var binaryString = _utf8ToBinary(utf8String.toString());
  5528. this.checksum = _update(1, binaryString);
  5529. });
  5530. if (_hasArrayBuffer) {
  5531. ctor.fromBuffer = function (fromBuffer) {
  5532. fromBuffer.prototype = proto;
  5533. return fromBuffer;
  5534. }(function fromBuffer(buffer) {
  5535. if (!(this instanceof ctor)) {
  5536. throw new TypeError(
  5537. 'Constructor cannot called be as a function.');
  5538. }
  5539. if (!_isBuffer(buffer))
  5540. throw new Error('First argument needs to be ArrayBuffer.');
  5541. var array = new Uint8Array(buffer);
  5542. return this.checksum = _updateUint8Array(1, array);
  5543. });
  5544. }
  5545. proto.update = function update(binaryString) {
  5546. if (binaryString == null)
  5547. throw new Error('First argument needs to be a string.');
  5548. binaryString = binaryString.toString();
  5549. return this.checksum = _update(this.checksum, binaryString);
  5550. };
  5551. proto.updateUtf8 = function updateUtf8(utf8String) {
  5552. if (utf8String == null)
  5553. throw new Error('First argument needs to be a string.');
  5554. var binaryString = _utf8ToBinary(utf8String.toString());
  5555. return this.checksum = _update(this.checksum, binaryString);
  5556. };
  5557. if (_hasArrayBuffer) {
  5558. proto.updateBuffer = function updateBuffer(buffer) {
  5559. if (!_isBuffer(buffer))
  5560. throw new Error('First argument needs to be ArrayBuffer.');
  5561. var array = new Uint8Array(buffer);
  5562. return this.checksum = _updateUint8Array(this.checksum, array);
  5563. };
  5564. }
  5565. proto.clone = function clone() {
  5566. return new Adler32(this.checksum);
  5567. };
  5568. return ctor;
  5569. }());
  5570. exports.from = function from(binaryString) {
  5571. if (binaryString == null)
  5572. throw new Error('First argument needs to be a string.');
  5573. return _update(1, binaryString.toString());
  5574. };
  5575. exports.fromUtf8 = function fromUtf8(utf8String) {
  5576. if (utf8String == null)
  5577. throw new Error('First argument needs to be a string.');
  5578. var binaryString = _utf8ToBinary(utf8String.toString());
  5579. return _update(1, binaryString);
  5580. };
  5581. if (_hasArrayBuffer) {
  5582. exports.fromBuffer = function fromBuffer(buffer) {
  5583. if (!_isBuffer(buffer))
  5584. throw new Error('First argument need to be ArrayBuffer.');
  5585. var array = new Uint8Array(buffer);
  5586. return _updateUint8Array(1, array);
  5587. };
  5588. }
  5589. return exports;
  5590. });
  5591. /*
  5592. Deflate.js - https://github.com/gildas-lormeau/zip.js
  5593. Copyright (c) 2013 Gildas Lormeau. All rights reserved.
  5594. Redistribution and use in source and binary forms, with or without
  5595. modification, are permitted provided that the following conditions are met:
  5596. 1. Redistributions of source code must retain the above copyright notice,
  5597. this list of conditions and the following disclaimer.
  5598. 2. Redistributions in binary form must reproduce the above copyright
  5599. notice, this list of conditions and the following disclaimer in
  5600. the documentation and/or other materials provided with the distribution.
  5601. 3. The names of the authors may not be used to endorse or promote products
  5602. derived from this software without specific prior written permission.
  5603. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  5604. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  5605. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
  5606. INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
  5607. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  5608. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  5609. OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  5610. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  5611. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  5612. EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  5613. */
  5614. /*
  5615. * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.
  5616. * JZlib is based on zlib-1.1.3, so all credit should go authors
  5617. * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
  5618. * and contributors of zlib.
  5619. */
  5620. var Deflater = (function (obj) {
  5621. // Global
  5622. var MAX_BITS = 15;
  5623. var D_CODES = 30;
  5624. var BL_CODES = 19;
  5625. var LENGTH_CODES = 29;
  5626. var LITERALS = 256;
  5627. var L_CODES = (LITERALS + 1 + LENGTH_CODES);
  5628. var HEAP_SIZE = (2 * L_CODES + 1);
  5629. var END_BLOCK = 256;
  5630. // Bit length codes must not exceed MAX_BL_BITS bits
  5631. var MAX_BL_BITS = 7;
  5632. // repeat previous bit length 3-6 times (2 bits of repeat count)
  5633. var REP_3_6 = 16;
  5634. // repeat a zero length 3-10 times (3 bits of repeat count)
  5635. var REPZ_3_10 = 17;
  5636. // repeat a zero length 11-138 times (7 bits of repeat count)
  5637. var REPZ_11_138 = 18;
  5638. // The lengths of the bit length codes are sent in order of decreasing
  5639. // probability, to avoid transmitting the lengths for unused bit
  5640. // length codes.
  5641. var Buf_size = 8 * 2;
  5642. // JZlib version : "1.0.2"
  5643. var Z_DEFAULT_COMPRESSION = -1;
  5644. // compression strategy
  5645. var Z_FILTERED = 1;
  5646. var Z_HUFFMAN_ONLY = 2;
  5647. var Z_DEFAULT_STRATEGY = 0;
  5648. var Z_NO_FLUSH = 0;
  5649. var Z_PARTIAL_FLUSH = 1;
  5650. var Z_FULL_FLUSH = 3;
  5651. var Z_FINISH = 4;
  5652. var Z_OK = 0;
  5653. var Z_STREAM_END = 1;
  5654. var Z_NEED_DICT = 2;
  5655. var Z_STREAM_ERROR = -2;
  5656. var Z_DATA_ERROR = -3;
  5657. var Z_BUF_ERROR = -5;
  5658. // Tree
  5659. // see definition of array dist_code below
  5660. 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,
  5661. 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,
  5662. 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,
  5663. 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,
  5664. 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,
  5665. 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,
  5666. 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,
  5667. 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,
  5668. 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,
  5669. 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,
  5670. 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,
  5671. 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,
  5672. 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,
  5673. 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];
  5674. function Tree() {
  5675. var that = this;
  5676. // dyn_tree; // the dynamic tree
  5677. // max_code; // largest code with non zero frequency
  5678. // stat_desc; // the corresponding static tree
  5679. // Compute the optimal bit lengths for a tree and update the total bit
  5680. // length
  5681. // for the current block.
  5682. // IN assertion: the fields freq and dad are set, heap[heap_max] and
  5683. // above are the tree nodes sorted by increasing frequency.
  5684. // OUT assertions: the field len is set to the optimal bit length, the
  5685. // array bl_count contains the frequencies for each bit length.
  5686. // The length opt_len is updated; static_len is also updated if stree is
  5687. // not null.
  5688. function gen_bitlen(s) {
  5689. var tree = that.dyn_tree;
  5690. var stree = that.stat_desc.static_tree;
  5691. var extra = that.stat_desc.extra_bits;
  5692. var base = that.stat_desc.extra_base;
  5693. var max_length = that.stat_desc.max_length;
  5694. var h; // heap index
  5695. var n, m; // iterate over the tree elements
  5696. var bits; // bit length
  5697. var xbits; // extra bits
  5698. var f; // frequency
  5699. var overflow = 0; // number of elements with bit length too large
  5700. for (bits = 0; bits <= MAX_BITS; bits++)
  5701. s.bl_count[bits] = 0;
  5702. // In a first pass, compute the optimal bit lengths (which may
  5703. // overflow in the case of the bit length tree).
  5704. tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
  5705. for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
  5706. n = s.heap[h];
  5707. bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
  5708. if (bits > max_length) {
  5709. bits = max_length;
  5710. overflow++;
  5711. }
  5712. tree[n * 2 + 1] = bits;
  5713. // We overwrite tree[n*2+1] which is no longer needed
  5714. if (n > that.max_code)
  5715. continue; // not a leaf node
  5716. s.bl_count[bits]++;
  5717. xbits = 0;
  5718. if (n >= base)
  5719. xbits = extra[n - base];
  5720. f = tree[n * 2];
  5721. s.opt_len += f * (bits + xbits);
  5722. if (stree)
  5723. s.static_len += f * (stree[n * 2 + 1] + xbits);
  5724. }
  5725. if (overflow === 0)
  5726. return;
  5727. // This happens for example on obj2 and pic of the Calgary corpus
  5728. // Find the first bit length which could increase:
  5729. do {
  5730. bits = max_length - 1;
  5731. while (s.bl_count[bits] === 0)
  5732. bits--;
  5733. s.bl_count[bits]--; // move one leaf down the tree
  5734. s.bl_count[bits + 1] += 2; // move one overflow item as its brother
  5735. s.bl_count[max_length]--;
  5736. // The brother of the overflow item also moves one step up,
  5737. // but this does not affect bl_count[max_length]
  5738. overflow -= 2;
  5739. } while (overflow > 0);
  5740. for (bits = max_length; bits !== 0; bits--) {
  5741. n = s.bl_count[bits];
  5742. while (n !== 0) {
  5743. m = s.heap[--h];
  5744. if (m > that.max_code)
  5745. continue;
  5746. if (tree[m * 2 + 1] != bits) {
  5747. s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2];
  5748. tree[m * 2 + 1] = bits;
  5749. }
  5750. n--;
  5751. }
  5752. }
  5753. }
  5754. // Reverse the first len bits of a code, using straightforward code (a
  5755. // faster
  5756. // method would use a table)
  5757. // IN assertion: 1 <= len <= 15
  5758. function bi_reverse(code, // the value to invert
  5759. len // its bit length
  5760. ) {
  5761. var res = 0;
  5762. do {
  5763. res |= code & 1;
  5764. code >>>= 1;
  5765. res <<= 1;
  5766. } while (--len > 0);
  5767. return res >>> 1;
  5768. }
  5769. // Generate the codes for a given tree and bit counts (which need not be
  5770. // optimal).
  5771. // IN assertion: the array bl_count contains the bit length statistics for
  5772. // the given tree and the field len is set for all tree elements.
  5773. // OUT assertion: the field code is set for all tree elements of non
  5774. // zero code length.
  5775. function gen_codes(tree, // the tree to decorate
  5776. max_code, // largest code with non zero frequency
  5777. bl_count // number of codes at each bit length
  5778. ) {
  5779. var next_code = []; // next code value for each
  5780. // bit length
  5781. var code = 0; // running code value
  5782. var bits; // bit index
  5783. var n; // code index
  5784. var len;
  5785. // The distribution counts are first used to generate the code values
  5786. // without bit reversal.
  5787. for (bits = 1; bits <= MAX_BITS; bits++) {
  5788. next_code[bits] = code = ((code + bl_count[bits - 1]) << 1);
  5789. }
  5790. // Check that the bit counts in bl_count are consistent. The last code
  5791. // must be all ones.
  5792. // Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
  5793. // "inconsistent bit counts");
  5794. // Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
  5795. for (n = 0; n <= max_code; n++) {
  5796. len = tree[n * 2 + 1];
  5797. if (len === 0)
  5798. continue;
  5799. // Now reverse the bits
  5800. tree[n * 2] = bi_reverse(next_code[len]++, len);
  5801. }
  5802. }
  5803. // Construct one Huffman tree and assigns the code bit strings and lengths.
  5804. // Update the total bit length for the current block.
  5805. // IN assertion: the field freq is set for all tree elements.
  5806. // OUT assertions: the fields len and code are set to the optimal bit length
  5807. // and corresponding code. The length opt_len is updated; static_len is
  5808. // also updated if stree is not null. The field max_code is set.
  5809. that.build_tree = function (s) {
  5810. var tree = that.dyn_tree;
  5811. var stree = that.stat_desc.static_tree;
  5812. var elems = that.stat_desc.elems;
  5813. var n, m; // iterate over heap elements
  5814. var max_code = -1; // largest code with non zero frequency
  5815. var node; // new node being created
  5816. // Construct the initial heap, with least frequent element in
  5817. // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
  5818. // heap[0] is not used.
  5819. s.heap_len = 0;
  5820. s.heap_max = HEAP_SIZE;
  5821. for (n = 0; n < elems; n++) {
  5822. if (tree[n * 2] !== 0) {
  5823. s.heap[++s.heap_len] = max_code = n;
  5824. s.depth[n] = 0;
  5825. } else {
  5826. tree[n * 2 + 1] = 0;
  5827. }
  5828. }
  5829. // The pkzip format requires that at least one distance code exists,
  5830. // and that at least one bit should be sent even if there is only one
  5831. // possible code. So to avoid special checks later on we force at least
  5832. // two codes of non zero frequency.
  5833. while (s.heap_len < 2) {
  5834. node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0;
  5835. tree[node * 2] = 1;
  5836. s.depth[node] = 0;
  5837. s.opt_len--;
  5838. if (stree)
  5839. s.static_len -= stree[node * 2 + 1];
  5840. // node is 0 or 1 so it does not have extra bits
  5841. }
  5842. that.max_code = max_code;
  5843. // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
  5844. // establish sub-heaps of increasing lengths:
  5845. for (n = Math.floor(s.heap_len / 2); n >= 1; n--)
  5846. s.pqdownheap(tree, n);
  5847. // Construct the Huffman tree by repeatedly combining the least two
  5848. // frequent nodes.
  5849. node = elems; // next internal node of the tree
  5850. do {
  5851. // n = node of least frequency
  5852. n = s.heap[1];
  5853. s.heap[1] = s.heap[s.heap_len--];
  5854. s.pqdownheap(tree, 1);
  5855. m = s.heap[1]; // m = node of next least frequency
  5856. s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
  5857. s.heap[--s.heap_max] = m;
  5858. // Create a new node father of n and m
  5859. tree[node * 2] = (tree[n * 2] + tree[m * 2]);
  5860. s.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1;
  5861. tree[n * 2 + 1] = tree[m * 2 + 1] = node;
  5862. // and insert the new node in the heap
  5863. s.heap[1] = node++;
  5864. s.pqdownheap(tree, 1);
  5865. } while (s.heap_len >= 2);
  5866. s.heap[--s.heap_max] = s.heap[1];
  5867. // At this point, the fields freq and dad are set. We can now
  5868. // generate the bit lengths.
  5869. gen_bitlen(s);
  5870. // The field len is now set, we can generate the bit codes
  5871. gen_codes(tree, that.max_code, s.bl_count);
  5872. };
  5873. }
  5874. 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,
  5875. 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,
  5876. 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,
  5877. 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,
  5878. 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,
  5879. 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,
  5880. 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];
  5881. 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];
  5882. 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,
  5883. 24576];
  5884. // Mapping from a distance to a distance code. dist is the distance - 1 and
  5885. // must not have side effects. _dist_code[256] and _dist_code[257] are never
  5886. // used.
  5887. Tree.d_code = function (dist) {
  5888. return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >>> 7)]);
  5889. };
  5890. // extra bits for each length code
  5891. 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];
  5892. // extra bits for each distance code
  5893. 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];
  5894. // extra bits for each bit length code
  5895. Tree.extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7];
  5896. Tree.bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
  5897. // StaticTree
  5898. function StaticTree(static_tree, extra_bits, extra_base, elems, max_length) {
  5899. var that = this;
  5900. that.static_tree = static_tree;
  5901. that.extra_bits = extra_bits;
  5902. that.extra_base = extra_base;
  5903. that.elems = elems;
  5904. that.max_length = max_length;
  5905. }
  5906. 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,
  5907. 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,
  5908. 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,
  5909. 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,
  5910. 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,
  5911. 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,
  5912. 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,
  5913. 173, 8, 109, 8, 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, 211, 9, 467, 9,
  5914. 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,
  5915. 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,
  5916. 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,
  5917. 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,
  5918. 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,
  5919. 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,
  5920. 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,
  5921. 99, 8, 227, 8];
  5922. 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,
  5923. 25, 5, 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5];
  5924. StaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
  5925. StaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS);
  5926. StaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
  5927. // Deflate
  5928. var MAX_MEM_LEVEL = 9;
  5929. var DEF_MEM_LEVEL = 8;
  5930. function Config(good_length, max_lazy, nice_length, max_chain, func) {
  5931. var that = this;
  5932. that.good_length = good_length;
  5933. that.max_lazy = max_lazy;
  5934. that.nice_length = nice_length;
  5935. that.max_chain = max_chain;
  5936. that.func = func;
  5937. }
  5938. var STORED = 0;
  5939. var FAST = 1;
  5940. var SLOW = 2;
  5941. 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),
  5942. 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),
  5943. new Config(32, 128, 258, 1024, SLOW), new Config(32, 258, 258, 4096, SLOW)];
  5944. var z_errmsg = ["need dictionary", // Z_NEED_DICT
  5945. // 2
  5946. "stream end", // Z_STREAM_END 1
  5947. "", // Z_OK 0
  5948. "", // Z_ERRNO (-1)
  5949. "stream error", // Z_STREAM_ERROR (-2)
  5950. "data error", // Z_DATA_ERROR (-3)
  5951. "", // Z_MEM_ERROR (-4)
  5952. "buffer error", // Z_BUF_ERROR (-5)
  5953. "",// Z_VERSION_ERROR (-6)
  5954. ""];
  5955. // block not completed, need more input or more output
  5956. var NeedMore = 0;
  5957. // block flush performed
  5958. var BlockDone = 1;
  5959. // finish started, need only more output at next deflate
  5960. var FinishStarted = 2;
  5961. // finish done, accept no more input or output
  5962. var FinishDone = 3;
  5963. // preset dictionary flag in zlib header
  5964. var PRESET_DICT = 0x20;
  5965. var INIT_STATE = 42;
  5966. var BUSY_STATE = 113;
  5967. var FINISH_STATE = 666;
  5968. // The deflate compression method
  5969. var Z_DEFLATED = 8;
  5970. var STORED_BLOCK = 0;
  5971. var STATIC_TREES = 1;
  5972. var DYN_TREES = 2;
  5973. var MIN_MATCH = 3;
  5974. var MAX_MATCH = 258;
  5975. var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
  5976. function smaller(tree, n, m, depth) {
  5977. var tn2 = tree[n * 2];
  5978. var tm2 = tree[m * 2];
  5979. return (tn2 < tm2 || (tn2 == tm2 && depth[n] <= depth[m]));
  5980. }
  5981. function Deflate() {
  5982. var that = this;
  5983. var strm; // pointer back to this zlib stream
  5984. var status; // as the name implies
  5985. // pending_buf; // output still pending
  5986. var pending_buf_size; // size of pending_buf
  5987. // pending_out; // next pending byte to output to the stream
  5988. // pending; // nb of bytes in the pending buffer
  5989. var method; // STORED (for zip only) or DEFLATED
  5990. var last_flush; // value of flush param for previous deflate call
  5991. var w_size; // LZ77 window size (32K by default)
  5992. var w_bits; // log2(w_size) (8..16)
  5993. var w_mask; // w_size - 1
  5994. var window;
  5995. // Sliding window. Input bytes are read into the second half of the window,
  5996. // and move to the first half later to keep a dictionary of at least wSize
  5997. // bytes. With this organization, matches are limited to a distance of
  5998. // wSize-MAX_MATCH bytes, but this ensures that IO is always
  5999. // performed with a length multiple of the block size. Also, it limits
  6000. // the window size to 64K, which is quite useful on MSDOS.
  6001. // To do: use the user input buffer as sliding window.
  6002. var window_size;
  6003. // Actual size of window: 2*wSize, except when the user input buffer
  6004. // is directly used as sliding window.
  6005. var prev;
  6006. // Link to older string with same hash index. To limit the size of this
  6007. // array to 64K, this link is maintained only for the last 32K strings.
  6008. // An index in this array is thus a window index modulo 32K.
  6009. var head; // Heads of the hash chains or NIL.
  6010. var ins_h; // hash index of string to be inserted
  6011. var hash_size; // number of elements in hash table
  6012. var hash_bits; // log2(hash_size)
  6013. var hash_mask; // hash_size-1
  6014. // Number of bits by which ins_h must be shifted at each input
  6015. // step. It must be such that after MIN_MATCH steps, the oldest
  6016. // byte no longer takes part in the hash key, that is:
  6017. // hash_shift * MIN_MATCH >= hash_bits
  6018. var hash_shift;
  6019. // Window position at the beginning of the current output block. Gets
  6020. // negative when the window is moved backwards.
  6021. var block_start;
  6022. var match_length; // length of best match
  6023. var prev_match; // previous match
  6024. var match_available; // set if previous match exists
  6025. var strstart; // start of string to insert
  6026. var match_start; // start of matching string
  6027. var lookahead; // number of valid bytes ahead in window
  6028. // Length of the best match at previous step. Matches not greater than this
  6029. // are discarded. This is used in the lazy match evaluation.
  6030. var prev_length;
  6031. // To speed up deflation, hash chains are never searched beyond this
  6032. // length. A higher limit improves compression ratio but degrades the speed.
  6033. var max_chain_length;
  6034. // Attempt to find a better match only when the current match is strictly
  6035. // smaller than this value. This mechanism is used only for compression
  6036. // levels >= 4.
  6037. var max_lazy_match;
  6038. // Insert new strings in the hash table only if the match length is not
  6039. // greater than this length. This saves time but degrades compression.
  6040. // max_insert_length is used only for compression levels <= 3.
  6041. var level; // compression level (1..9)
  6042. var strategy; // favor or force Huffman coding
  6043. // Use a faster search when the previous match is longer than this
  6044. var good_match;
  6045. // Stop searching when current match exceeds this
  6046. var nice_match;
  6047. var dyn_ltree; // literal and length tree
  6048. var dyn_dtree; // distance tree
  6049. var bl_tree; // Huffman tree for bit lengths
  6050. var l_desc = new Tree(); // desc for literal tree
  6051. var d_desc = new Tree(); // desc for distance tree
  6052. var bl_desc = new Tree(); // desc for bit length tree
  6053. // that.heap_len; // number of elements in the heap
  6054. // that.heap_max; // element of largest frequency
  6055. // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
  6056. // The same heap array is used to build all trees.
  6057. // Depth of each subtree used as tie breaker for trees of equal frequency
  6058. that.depth = [];
  6059. var l_buf; // index for literals or lengths */
  6060. // Size of match buffer for literals/lengths. There are 4 reasons for
  6061. // limiting lit_bufsize to 64K:
  6062. // - frequencies can be kept in 16 bit counters
  6063. // - if compression is not successful for the first block, all input
  6064. // data is still in the window so we can still emit a stored block even
  6065. // when input comes from standard input. (This can also be done for
  6066. // all blocks if lit_bufsize is not greater than 32K.)
  6067. // - if compression is not successful for a file smaller than 64K, we can
  6068. // even emit a stored file instead of a stored block (saving 5 bytes).
  6069. // This is applicable only for zip (not gzip or zlib).
  6070. // - creating new Huffman trees less frequently may not provide fast
  6071. // adaptation to changes in the input data statistics. (Take for
  6072. // example a binary file with poorly compressible code followed by
  6073. // a highly compressible string table.) Smaller buffer sizes give
  6074. // fast adaptation but have of course the overhead of transmitting
  6075. // trees more frequently.
  6076. // - I can't count above 4
  6077. var lit_bufsize;
  6078. var last_lit; // running index in l_buf
  6079. // Buffer for distances. To simplify the code, d_buf and l_buf have
  6080. // the same number of elements. To use different lengths, an extra flag
  6081. // array would be necessary.
  6082. var d_buf; // index of pendig_buf
  6083. // that.opt_len; // bit length of current block with optimal trees
  6084. // that.static_len; // bit length of current block with static trees
  6085. var matches; // number of string matches in current block
  6086. var last_eob_len; // bit length of EOB code for last block
  6087. // Output buffer. bits are inserted starting at the bottom (least
  6088. // significant bits).
  6089. var bi_buf;
  6090. // Number of valid bits in bi_buf. All bits above the last valid bit
  6091. // are always zero.
  6092. var bi_valid;
  6093. // number of codes at each bit length for an optimal tree
  6094. that.bl_count = [];
  6095. // heap used to build the Huffman trees
  6096. that.heap = [];
  6097. dyn_ltree = [];
  6098. dyn_dtree = [];
  6099. bl_tree = [];
  6100. function lm_init() {
  6101. var i;
  6102. window_size = 2 * w_size;
  6103. head[hash_size - 1] = 0;
  6104. for (i = 0; i < hash_size - 1; i++) {
  6105. head[i] = 0;
  6106. }
  6107. // Set the default configuration parameters:
  6108. max_lazy_match = config_table[level].max_lazy;
  6109. good_match = config_table[level].good_length;
  6110. nice_match = config_table[level].nice_length;
  6111. max_chain_length = config_table[level].max_chain;
  6112. strstart = 0;
  6113. block_start = 0;
  6114. lookahead = 0;
  6115. match_length = prev_length = MIN_MATCH - 1;
  6116. match_available = 0;
  6117. ins_h = 0;
  6118. }
  6119. function init_block() {
  6120. var i;
  6121. // Initialize the trees.
  6122. for (i = 0; i < L_CODES; i++)
  6123. dyn_ltree[i * 2] = 0;
  6124. for (i = 0; i < D_CODES; i++)
  6125. dyn_dtree[i * 2] = 0;
  6126. for (i = 0; i < BL_CODES; i++)
  6127. bl_tree[i * 2] = 0;
  6128. dyn_ltree[END_BLOCK * 2] = 1;
  6129. that.opt_len = that.static_len = 0;
  6130. last_lit = matches = 0;
  6131. }
  6132. // Initialize the tree data structures for a new zlib stream.
  6133. function tr_init() {
  6134. l_desc.dyn_tree = dyn_ltree;
  6135. l_desc.stat_desc = StaticTree.static_l_desc;
  6136. d_desc.dyn_tree = dyn_dtree;
  6137. d_desc.stat_desc = StaticTree.static_d_desc;
  6138. bl_desc.dyn_tree = bl_tree;
  6139. bl_desc.stat_desc = StaticTree.static_bl_desc;
  6140. bi_buf = 0;
  6141. bi_valid = 0;
  6142. last_eob_len = 8; // enough lookahead for inflate
  6143. // Initialize the first block of the first file:
  6144. init_block();
  6145. }
  6146. // Restore the heap property by moving down the tree starting at node k,
  6147. // exchanging a node with the smallest of its two sons if necessary,
  6148. // stopping
  6149. // when the heap property is re-established (each father smaller than its
  6150. // two sons).
  6151. that.pqdownheap = function (tree, // the tree to restore
  6152. k // node to move down
  6153. ) {
  6154. var heap = that.heap;
  6155. var v = heap[k];
  6156. var j = k << 1; // left son of k
  6157. while (j <= that.heap_len) {
  6158. // Set j to the smallest of the two sons:
  6159. if (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) {
  6160. j++;
  6161. }
  6162. // Exit if v is smaller than both sons
  6163. if (smaller(tree, v, heap[j], that.depth))
  6164. break;
  6165. // Exchange v with the smallest son
  6166. heap[k] = heap[j];
  6167. k = j;
  6168. // And continue down the tree, setting j to the left son of k
  6169. j <<= 1;
  6170. }
  6171. heap[k] = v;
  6172. };
  6173. // Scan a literal or distance tree to determine the frequencies of the codes
  6174. // in the bit length tree.
  6175. function scan_tree(tree,// the tree to be scanned
  6176. max_code // and its largest code of non zero frequency
  6177. ) {
  6178. var n; // iterates over all tree elements
  6179. var prevlen = -1; // last emitted length
  6180. var curlen; // length of current code
  6181. var nextlen = tree[0 * 2 + 1]; // length of next code
  6182. var count = 0; // repeat count of the current code
  6183. var max_count = 7; // max repeat count
  6184. var min_count = 4; // min repeat count
  6185. if (nextlen === 0) {
  6186. max_count = 138;
  6187. min_count = 3;
  6188. }
  6189. tree[(max_code + 1) * 2 + 1] = 0xffff; // guard
  6190. for (n = 0; n <= max_code; n++) {
  6191. curlen = nextlen;
  6192. nextlen = tree[(n + 1) * 2 + 1];
  6193. if (++count < max_count && curlen == nextlen) {
  6194. continue;
  6195. } else if (count < min_count) {
  6196. bl_tree[curlen * 2] += count;
  6197. } else if (curlen !== 0) {
  6198. if (curlen != prevlen)
  6199. bl_tree[curlen * 2]++;
  6200. bl_tree[REP_3_6 * 2]++;
  6201. } else if (count <= 10) {
  6202. bl_tree[REPZ_3_10 * 2]++;
  6203. } else {
  6204. bl_tree[REPZ_11_138 * 2]++;
  6205. }
  6206. count = 0;
  6207. prevlen = curlen;
  6208. if (nextlen === 0) {
  6209. max_count = 138;
  6210. min_count = 3;
  6211. } else if (curlen == nextlen) {
  6212. max_count = 6;
  6213. min_count = 3;
  6214. } else {
  6215. max_count = 7;
  6216. min_count = 4;
  6217. }
  6218. }
  6219. }
  6220. // Construct the Huffman tree for the bit lengths and return the index in
  6221. // bl_order of the last bit length code to send.
  6222. function build_bl_tree() {
  6223. var max_blindex; // index of last bit length code of non zero freq
  6224. // Determine the bit length frequencies for literal and distance trees
  6225. scan_tree(dyn_ltree, l_desc.max_code);
  6226. scan_tree(dyn_dtree, d_desc.max_code);
  6227. // Build the bit length tree:
  6228. bl_desc.build_tree(that);
  6229. // opt_len now includes the length of the tree representations, except
  6230. // the lengths of the bit lengths codes and the 5+5+4 bits for the
  6231. // counts.
  6232. // Determine the number of bit length codes to send. The pkzip format
  6233. // requires that at least 4 bit length codes be sent. (appnote.txt says
  6234. // 3 but the actual value used is 4.)
  6235. for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
  6236. if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0)
  6237. break;
  6238. }
  6239. // Update opt_len to include the bit length tree and counts
  6240. that.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
  6241. return max_blindex;
  6242. }
  6243. // Output a byte on the stream.
  6244. // IN assertion: there is enough room in pending_buf.
  6245. function put_byte(p) {
  6246. that.pending_buf[that.pending++] = p;
  6247. }
  6248. function put_short(w) {
  6249. put_byte(w & 0xff);
  6250. put_byte((w >>> 8) & 0xff);
  6251. }
  6252. function putShortMSB(b) {
  6253. put_byte((b >> 8) & 0xff);
  6254. put_byte((b & 0xff) & 0xff);
  6255. }
  6256. function send_bits(value, length) {
  6257. var val, len = length;
  6258. if (bi_valid > Buf_size - len) {
  6259. val = value;
  6260. // bi_buf |= (val << bi_valid);
  6261. bi_buf |= ((val << bi_valid) & 0xffff);
  6262. put_short(bi_buf);
  6263. bi_buf = val >>> (Buf_size - bi_valid);
  6264. bi_valid += len - Buf_size;
  6265. } else {
  6266. // bi_buf |= (value) << bi_valid;
  6267. bi_buf |= (((value) << bi_valid) & 0xffff);
  6268. bi_valid += len;
  6269. }
  6270. }
  6271. function send_code(c, tree) {
  6272. var c2 = c * 2;
  6273. send_bits(tree[c2] & 0xffff, tree[c2 + 1] & 0xffff);
  6274. }
  6275. // Send a literal or distance tree in compressed form, using the codes in
  6276. // bl_tree.
  6277. function send_tree(tree,// the tree to be sent
  6278. max_code // and its largest code of non zero frequency
  6279. ) {
  6280. var n; // iterates over all tree elements
  6281. var prevlen = -1; // last emitted length
  6282. var curlen; // length of current code
  6283. var nextlen = tree[0 * 2 + 1]; // length of next code
  6284. var count = 0; // repeat count of the current code
  6285. var max_count = 7; // max repeat count
  6286. var min_count = 4; // min repeat count
  6287. if (nextlen === 0) {
  6288. max_count = 138;
  6289. min_count = 3;
  6290. }
  6291. for (n = 0; n <= max_code; n++) {
  6292. curlen = nextlen;
  6293. nextlen = tree[(n + 1) * 2 + 1];
  6294. if (++count < max_count && curlen == nextlen) {
  6295. continue;
  6296. } else if (count < min_count) {
  6297. do {
  6298. send_code(curlen, bl_tree);
  6299. } while (--count !== 0);
  6300. } else if (curlen !== 0) {
  6301. if (curlen != prevlen) {
  6302. send_code(curlen, bl_tree);
  6303. count--;
  6304. }
  6305. send_code(REP_3_6, bl_tree);
  6306. send_bits(count - 3, 2);
  6307. } else if (count <= 10) {
  6308. send_code(REPZ_3_10, bl_tree);
  6309. send_bits(count - 3, 3);
  6310. } else {
  6311. send_code(REPZ_11_138, bl_tree);
  6312. send_bits(count - 11, 7);
  6313. }
  6314. count = 0;
  6315. prevlen = curlen;
  6316. if (nextlen === 0) {
  6317. max_count = 138;
  6318. min_count = 3;
  6319. } else if (curlen == nextlen) {
  6320. max_count = 6;
  6321. min_count = 3;
  6322. } else {
  6323. max_count = 7;
  6324. min_count = 4;
  6325. }
  6326. }
  6327. }
  6328. // Send the header for a block using dynamic Huffman trees: the counts, the
  6329. // lengths of the bit length codes, the literal tree and the distance tree.
  6330. // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
  6331. function send_all_trees(lcodes, dcodes, blcodes) {
  6332. var rank; // index in bl_order
  6333. send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
  6334. send_bits(dcodes - 1, 5);
  6335. send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
  6336. for (rank = 0; rank < blcodes; rank++) {
  6337. send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3);
  6338. }
  6339. send_tree(dyn_ltree, lcodes - 1); // literal tree
  6340. send_tree(dyn_dtree, dcodes - 1); // distance tree
  6341. }
  6342. // Flush the bit buffer, keeping at most 7 bits in it.
  6343. function bi_flush() {
  6344. if (bi_valid == 16) {
  6345. put_short(bi_buf);
  6346. bi_buf = 0;
  6347. bi_valid = 0;
  6348. } else if (bi_valid >= 8) {
  6349. put_byte(bi_buf & 0xff);
  6350. bi_buf >>>= 8;
  6351. bi_valid -= 8;
  6352. }
  6353. }
  6354. // Send one empty static block to give enough lookahead for inflate.
  6355. // This takes 10 bits, of which 7 may remain in the bit buffer.
  6356. // The current inflate code requires 9 bits of lookahead. If the
  6357. // last two codes for the previous block (real code plus EOB) were coded
  6358. // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
  6359. // the last real code. In this case we send two empty static blocks instead
  6360. // of one. (There are no problems if the previous block is stored or fixed.)
  6361. // To simplify the code, we assume the worst case of last real code encoded
  6362. // on one bit only.
  6363. function _tr_align() {
  6364. send_bits(STATIC_TREES << 1, 3);
  6365. send_code(END_BLOCK, StaticTree.static_ltree);
  6366. bi_flush();
  6367. // Of the 10 bits for the empty block, we have already sent
  6368. // (10 - bi_valid) bits. The lookahead for the last real code (before
  6369. // the EOB of the previous block) was thus at least one plus the length
  6370. // of the EOB plus what we have just sent of the empty static block.
  6371. if (1 + last_eob_len + 10 - bi_valid < 9) {
  6372. send_bits(STATIC_TREES << 1, 3);
  6373. send_code(END_BLOCK, StaticTree.static_ltree);
  6374. bi_flush();
  6375. }
  6376. last_eob_len = 7;
  6377. }
  6378. // Save the match info and tally the frequency counts. Return true if
  6379. // the current block must be flushed.
  6380. function _tr_tally(dist, // distance of matched string
  6381. lc // match length-MIN_MATCH or unmatched char (if dist==0)
  6382. ) {
  6383. var out_length, in_length, dcode;
  6384. that.pending_buf[d_buf + last_lit * 2] = (dist >>> 8) & 0xff;
  6385. that.pending_buf[d_buf + last_lit * 2 + 1] = dist & 0xff;
  6386. that.pending_buf[l_buf + last_lit] = lc & 0xff;
  6387. last_lit++;
  6388. if (dist === 0) {
  6389. // lc is the unmatched char
  6390. dyn_ltree[lc * 2]++;
  6391. } else {
  6392. matches++;
  6393. // Here, lc is the match length - MIN_MATCH
  6394. dist--; // dist = match distance - 1
  6395. dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++;
  6396. dyn_dtree[Tree.d_code(dist) * 2]++;
  6397. }
  6398. if ((last_lit & 0x1fff) === 0 && level > 2) {
  6399. // Compute an upper bound for the compressed length
  6400. out_length = last_lit * 8;
  6401. in_length = strstart - block_start;
  6402. for (dcode = 0; dcode < D_CODES; dcode++) {
  6403. out_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]);
  6404. }
  6405. out_length >>>= 3;
  6406. if ((matches < Math.floor(last_lit / 2)) && out_length < Math.floor(in_length / 2))
  6407. return true;
  6408. }
  6409. return (last_lit == lit_bufsize - 1);
  6410. // We avoid equality with lit_bufsize because of wraparound at 64K
  6411. // on 16 bit machines and because stored blocks are restricted to
  6412. // 64K-1 bytes.
  6413. }
  6414. // Send the block data compressed using the given Huffman trees
  6415. function compress_block(ltree, dtree) {
  6416. var dist; // distance of matched string
  6417. var lc; // match length or unmatched char (if dist === 0)
  6418. var lx = 0; // running index in l_buf
  6419. var code; // the code to send
  6420. var extra; // number of extra bits to send
  6421. if (last_lit !== 0) {
  6422. do {
  6423. dist = ((that.pending_buf[d_buf + lx * 2] << 8) & 0xff00) | (that.pending_buf[d_buf + lx * 2 + 1] & 0xff);
  6424. lc = (that.pending_buf[l_buf + lx]) & 0xff;
  6425. lx++;
  6426. if (dist === 0) {
  6427. send_code(lc, ltree); // send a literal byte
  6428. } else {
  6429. // Here, lc is the match length - MIN_MATCH
  6430. code = Tree._length_code[lc];
  6431. send_code(code + LITERALS + 1, ltree); // send the length
  6432. // code
  6433. extra = Tree.extra_lbits[code];
  6434. if (extra !== 0) {
  6435. lc -= Tree.base_length[code];
  6436. send_bits(lc, extra); // send the extra length bits
  6437. }
  6438. dist--; // dist is now the match distance - 1
  6439. code = Tree.d_code(dist);
  6440. send_code(code, dtree); // send the distance code
  6441. extra = Tree.extra_dbits[code];
  6442. if (extra !== 0) {
  6443. dist -= Tree.base_dist[code];
  6444. send_bits(dist, extra); // send the extra distance bits
  6445. }
  6446. } // literal or match pair ?
  6447. // Check that the overlay between pending_buf and d_buf+l_buf is
  6448. // ok:
  6449. } while (lx < last_lit);
  6450. }
  6451. send_code(END_BLOCK, ltree);
  6452. last_eob_len = ltree[END_BLOCK * 2 + 1];
  6453. }
  6454. // Flush the bit buffer and align the output on a byte boundary
  6455. function bi_windup() {
  6456. if (bi_valid > 8) {
  6457. put_short(bi_buf);
  6458. } else if (bi_valid > 0) {
  6459. put_byte(bi_buf & 0xff);
  6460. }
  6461. bi_buf = 0;
  6462. bi_valid = 0;
  6463. }
  6464. // Copy a stored block, storing first the length and its
  6465. // one's complement if requested.
  6466. function copy_block(buf, // the input data
  6467. len, // its length
  6468. header // true if block header must be written
  6469. ) {
  6470. bi_windup(); // align on byte boundary
  6471. last_eob_len = 8; // enough lookahead for inflate
  6472. if (header) {
  6473. put_short(len);
  6474. put_short(~len);
  6475. }
  6476. that.pending_buf.set(window.subarray(buf, buf + len), that.pending);
  6477. that.pending += len;
  6478. }
  6479. // Send a stored block
  6480. function _tr_stored_block(buf, // input block
  6481. stored_len, // length of input block
  6482. eof // true if this is the last block for a file
  6483. ) {
  6484. send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
  6485. copy_block(buf, stored_len, true); // with header
  6486. }
  6487. // Determine the best encoding for the current block: dynamic trees, static
  6488. // trees or store, and output the encoded block to the zip file.
  6489. function _tr_flush_block(buf, // input block, or NULL if too old
  6490. stored_len, // length of input block
  6491. eof // true if this is the last block for a file
  6492. ) {
  6493. var opt_lenb, static_lenb;// opt_len and static_len in bytes
  6494. var max_blindex = 0; // index of last bit length code of non zero freq
  6495. // Build the Huffman trees unless a stored block is forced
  6496. if (level > 0) {
  6497. // Construct the literal and distance trees
  6498. l_desc.build_tree(that);
  6499. d_desc.build_tree(that);
  6500. // At this point, opt_len and static_len are the total bit lengths
  6501. // of
  6502. // the compressed block data, excluding the tree representations.
  6503. // Build the bit length tree for the above two trees, and get the
  6504. // index
  6505. // in bl_order of the last bit length code to send.
  6506. max_blindex = build_bl_tree();
  6507. // Determine the best encoding. Compute first the block length in
  6508. // bytes
  6509. opt_lenb = (that.opt_len + 3 + 7) >>> 3;
  6510. static_lenb = (that.static_len + 3 + 7) >>> 3;
  6511. if (static_lenb <= opt_lenb)
  6512. opt_lenb = static_lenb;
  6513. } else {
  6514. opt_lenb = static_lenb = stored_len + 5; // force a stored block
  6515. }
  6516. if ((stored_len + 4 <= opt_lenb) && buf != -1) {
  6517. // 4: two words for the lengths
  6518. // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
  6519. // Otherwise we can't have processed more than WSIZE input bytes
  6520. // since
  6521. // the last block flush, because compression would have been
  6522. // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
  6523. // transform a block into a stored block.
  6524. _tr_stored_block(buf, stored_len, eof);
  6525. } else if (static_lenb == opt_lenb) {
  6526. send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
  6527. compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
  6528. } else {
  6529. send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
  6530. send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1);
  6531. compress_block(dyn_ltree, dyn_dtree);
  6532. }
  6533. // The above check is made mod 2^32, for files larger than 512 MB
  6534. // and uLong implemented on 32 bits.
  6535. init_block();
  6536. if (eof) {
  6537. bi_windup();
  6538. }
  6539. }
  6540. function flush_block_only(eof) {
  6541. _tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof);
  6542. block_start = strstart;
  6543. strm.flush_pending();
  6544. }
  6545. // Fill the window when the lookahead becomes insufficient.
  6546. // Updates strstart and lookahead.
  6547. //
  6548. // IN assertion: lookahead < MIN_LOOKAHEAD
  6549. // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
  6550. // At least one byte has been read, or avail_in === 0; reads are
  6551. // performed for at least two bytes (required for the zip translate_eol
  6552. // option -- not supported here).
  6553. function fill_window() {
  6554. var n, m;
  6555. var p;
  6556. var more; // Amount of free space at the end of the window.
  6557. do {
  6558. more = (window_size - lookahead - strstart);
  6559. // Deal with !@#$% 64K limit:
  6560. if (more === 0 && strstart === 0 && lookahead === 0) {
  6561. more = w_size;
  6562. } else if (more == -1) {
  6563. // Very unlikely, but possible on 16 bit machine if strstart ==
  6564. // 0
  6565. // and lookahead == 1 (input done one byte at time)
  6566. more--;
  6567. // If the window is almost full and there is insufficient
  6568. // lookahead,
  6569. // move the upper half to the lower one to make room in the
  6570. // upper half.
  6571. } else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) {
  6572. window.set(window.subarray(w_size, w_size + w_size), 0);
  6573. match_start -= w_size;
  6574. strstart -= w_size; // we now have strstart >= MAX_DIST
  6575. block_start -= w_size;
  6576. // Slide the hash table (could be avoided with 32 bit values
  6577. // at the expense of memory usage). We slide even when level ==
  6578. // 0
  6579. // to keep the hash table consistent if we switch back to level
  6580. // > 0
  6581. // later. (Using level 0 permanently is not an optimal usage of
  6582. // zlib, so we don't care about this pathological case.)
  6583. n = hash_size;
  6584. p = n;
  6585. do {
  6586. m = (head[--p] & 0xffff);
  6587. head[p] = (m >= w_size ? m - w_size : 0);
  6588. } while (--n !== 0);
  6589. n = w_size;
  6590. p = n;
  6591. do {
  6592. m = (prev[--p] & 0xffff);
  6593. prev[p] = (m >= w_size ? m - w_size : 0);
  6594. // If n is not on any hash chain, prev[n] is garbage but
  6595. // its value will never be used.
  6596. } while (--n !== 0);
  6597. more += w_size;
  6598. }
  6599. if (strm.avail_in === 0)
  6600. return;
  6601. // If there was no sliding:
  6602. // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
  6603. // more == window_size - lookahead - strstart
  6604. // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
  6605. // => more >= window_size - 2*WSIZE + 2
  6606. // In the BIG_MEM or MMAP case (not yet supported),
  6607. // window_size == input_size + MIN_LOOKAHEAD &&
  6608. // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
  6609. // Otherwise, window_size == 2*WSIZE so more >= 2.
  6610. // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
  6611. n = strm.read_buf(window, strstart + lookahead, more);
  6612. lookahead += n;
  6613. // Initialize the hash value now that we have some input:
  6614. if (lookahead >= MIN_MATCH) {
  6615. ins_h = window[strstart] & 0xff;
  6616. ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
  6617. }
  6618. // If the whole input has less than MIN_MATCH bytes, ins_h is
  6619. // garbage,
  6620. // but this is not important since only literal bytes will be
  6621. // emitted.
  6622. } while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0);
  6623. }
  6624. // Copy without compression as much as possible from the input stream,
  6625. // return
  6626. // the current block state.
  6627. // This function does not insert new strings in the dictionary since
  6628. // uncompressible data is probably not useful. This function is used
  6629. // only for the level=0 compression option.
  6630. // NOTE: this function should be optimized to avoid extra copying from
  6631. // window to pending_buf.
  6632. function deflate_stored(flush) {
  6633. // Stored blocks are limited to 0xffff bytes, pending_buf is limited
  6634. // to pending_buf_size, and each stored block has a 5 byte header:
  6635. var max_block_size = 0xffff;
  6636. var max_start;
  6637. if (max_block_size > pending_buf_size - 5) {
  6638. max_block_size = pending_buf_size - 5;
  6639. }
  6640. // Copy as much as possible from input to output:
  6641. while (true) {
  6642. // Fill the window as much as possible:
  6643. if (lookahead <= 1) {
  6644. fill_window();
  6645. if (lookahead === 0 && flush == Z_NO_FLUSH)
  6646. return NeedMore;
  6647. if (lookahead === 0)
  6648. break; // flush the current block
  6649. }
  6650. strstart += lookahead;
  6651. lookahead = 0;
  6652. // Emit a stored block if pending_buf will be full:
  6653. max_start = block_start + max_block_size;
  6654. if (strstart === 0 || strstart >= max_start) {
  6655. // strstart === 0 is possible when wraparound on 16-bit machine
  6656. lookahead = (strstart - max_start);
  6657. strstart = max_start;
  6658. flush_block_only(false);
  6659. if (strm.avail_out === 0)
  6660. return NeedMore;
  6661. }
  6662. // Flush if we may have to slide, otherwise block_start may become
  6663. // negative and the data will be gone:
  6664. if (strstart - block_start >= w_size - MIN_LOOKAHEAD) {
  6665. flush_block_only(false);
  6666. if (strm.avail_out === 0)
  6667. return NeedMore;
  6668. }
  6669. }
  6670. flush_block_only(flush == Z_FINISH);
  6671. if (strm.avail_out === 0)
  6672. return (flush == Z_FINISH) ? FinishStarted : NeedMore;
  6673. return flush == Z_FINISH ? FinishDone : BlockDone;
  6674. }
  6675. function longest_match(cur_match) {
  6676. var chain_length = max_chain_length; // max hash chain length
  6677. var scan = strstart; // current string
  6678. var match; // matched string
  6679. var len; // length of current match
  6680. var best_len = prev_length; // best match length so far
  6681. var limit = strstart > (w_size - MIN_LOOKAHEAD) ? strstart - (w_size - MIN_LOOKAHEAD) : 0;
  6682. var _nice_match = nice_match;
  6683. // Stop when cur_match becomes <= limit. To simplify the code,
  6684. // we prevent matches with the string of window index 0.
  6685. var wmask = w_mask;
  6686. var strend = strstart + MAX_MATCH;
  6687. var scan_end1 = window[scan + best_len - 1];
  6688. var scan_end = window[scan + best_len];
  6689. // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of
  6690. // 16.
  6691. // It is easy to get rid of this optimization if necessary.
  6692. // Do not waste too much time if we already have a good match:
  6693. if (prev_length >= good_match) {
  6694. chain_length >>= 2;
  6695. }
  6696. // Do not look for matches beyond the end of the input. This is
  6697. // necessary
  6698. // to make deflate deterministic.
  6699. if (_nice_match > lookahead)
  6700. _nice_match = lookahead;
  6701. do {
  6702. match = cur_match;
  6703. // Skip to next match if the match length cannot increase
  6704. // or if the match length is less than 2:
  6705. if (window[match + best_len] != scan_end || window[match + best_len - 1] != scan_end1 || window[match] != window[scan]
  6706. || window[++match] != window[scan + 1])
  6707. continue;
  6708. // The check at best_len-1 can be removed because it will be made
  6709. // again later. (This heuristic is not always a win.)
  6710. // It is not necessary to compare scan[2] and match[2] since they
  6711. // are always equal when the other bytes match, given that
  6712. // the hash keys are equal and that HASH_BITS >= 8.
  6713. scan += 2;
  6714. match++;
  6715. // We check for insufficient lookahead only every 8th comparison;
  6716. // the 256th check will be made at strstart+258.
  6717. do {
  6718. } while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]
  6719. && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]
  6720. && window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend);
  6721. len = MAX_MATCH - (strend - scan);
  6722. scan = strend - MAX_MATCH;
  6723. if (len > best_len) {
  6724. match_start = cur_match;
  6725. best_len = len;
  6726. if (len >= _nice_match)
  6727. break;
  6728. scan_end1 = window[scan + best_len - 1];
  6729. scan_end = window[scan + best_len];
  6730. }
  6731. } while ((cur_match = (prev[cur_match & wmask] & 0xffff)) > limit && --chain_length !== 0);
  6732. if (best_len <= lookahead)
  6733. return best_len;
  6734. return lookahead;
  6735. }
  6736. // Compress as much as possible from the input stream, return the current
  6737. // block state.
  6738. // This function does not perform lazy evaluation of matches and inserts
  6739. // new strings in the dictionary only for unmatched strings or for short
  6740. // matches. It is used only for the fast compression options.
  6741. function deflate_fast(flush) {
  6742. // short hash_head = 0; // head of the hash chain
  6743. var hash_head = 0; // head of the hash chain
  6744. var bflush; // set if current block must be flushed
  6745. while (true) {
  6746. // Make sure that we always have enough lookahead, except
  6747. // at the end of the input file. We need MAX_MATCH bytes
  6748. // for the next match, plus MIN_MATCH bytes to insert the
  6749. // string following the next match.
  6750. if (lookahead < MIN_LOOKAHEAD) {
  6751. fill_window();
  6752. if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
  6753. return NeedMore;
  6754. }
  6755. if (lookahead === 0)
  6756. break; // flush the current block
  6757. }
  6758. // Insert the string window[strstart .. strstart+2] in the
  6759. // dictionary, and set hash_head to the head of the hash chain:
  6760. if (lookahead >= MIN_MATCH) {
  6761. ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
  6762. // prev[strstart&w_mask]=hash_head=head[ins_h];
  6763. hash_head = (head[ins_h] & 0xffff);
  6764. prev[strstart & w_mask] = head[ins_h];
  6765. head[ins_h] = strstart;
  6766. }
  6767. // Find the longest match, discarding those <= prev_length.
  6768. // At this point we have always match_length < MIN_MATCH
  6769. if (hash_head !== 0 && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {
  6770. // To simplify the code, we prevent matches with the string
  6771. // of window index 0 (in particular we have to avoid a match
  6772. // of the string with itself at the start of the input file).
  6773. if (strategy != Z_HUFFMAN_ONLY) {
  6774. match_length = longest_match(hash_head);
  6775. }
  6776. // longest_match() sets match_start
  6777. }
  6778. if (match_length >= MIN_MATCH) {
  6779. // check_match(strstart, match_start, match_length);
  6780. bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);
  6781. lookahead -= match_length;
  6782. // Insert new strings in the hash table only if the match length
  6783. // is not too large. This saves time but degrades compression.
  6784. if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) {
  6785. match_length--; // string at strstart already in hash table
  6786. do {
  6787. strstart++;
  6788. ins_h = ((ins_h << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
  6789. // prev[strstart&w_mask]=hash_head=head[ins_h];
  6790. hash_head = (head[ins_h] & 0xffff);
  6791. prev[strstart & w_mask] = head[ins_h];
  6792. head[ins_h] = strstart;
  6793. // strstart never exceeds WSIZE-MAX_MATCH, so there are
  6794. // always MIN_MATCH bytes ahead.
  6795. } while (--match_length !== 0);
  6796. strstart++;
  6797. } else {
  6798. strstart += match_length;
  6799. match_length = 0;
  6800. ins_h = window[strstart] & 0xff;
  6801. ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
  6802. // If lookahead < MIN_MATCH, ins_h is garbage, but it does
  6803. // not
  6804. // matter since it will be recomputed at next deflate call.
  6805. }
  6806. } else {
  6807. // No match, output a literal byte
  6808. bflush = _tr_tally(0, window[strstart] & 0xff);
  6809. lookahead--;
  6810. strstart++;
  6811. }
  6812. if (bflush) {
  6813. flush_block_only(false);
  6814. if (strm.avail_out === 0)
  6815. return NeedMore;
  6816. }
  6817. }
  6818. flush_block_only(flush == Z_FINISH);
  6819. if (strm.avail_out === 0) {
  6820. if (flush == Z_FINISH)
  6821. return FinishStarted;
  6822. else
  6823. return NeedMore;
  6824. }
  6825. return flush == Z_FINISH ? FinishDone : BlockDone;
  6826. }
  6827. // Same as above, but achieves better compression. We use a lazy
  6828. // evaluation for matches: a match is finally adopted only if there is
  6829. // no better match at the next window position.
  6830. function deflate_slow(flush) {
  6831. // short hash_head = 0; // head of hash chain
  6832. var hash_head = 0; // head of hash chain
  6833. var bflush; // set if current block must be flushed
  6834. var max_insert;
  6835. // Process the input block.
  6836. while (true) {
  6837. // Make sure that we always have enough lookahead, except
  6838. // at the end of the input file. We need MAX_MATCH bytes
  6839. // for the next match, plus MIN_MATCH bytes to insert the
  6840. // string following the next match.
  6841. if (lookahead < MIN_LOOKAHEAD) {
  6842. fill_window();
  6843. if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
  6844. return NeedMore;
  6845. }
  6846. if (lookahead === 0)
  6847. break; // flush the current block
  6848. }
  6849. // Insert the string window[strstart .. strstart+2] in the
  6850. // dictionary, and set hash_head to the head of the hash chain:
  6851. if (lookahead >= MIN_MATCH) {
  6852. ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
  6853. // prev[strstart&w_mask]=hash_head=head[ins_h];
  6854. hash_head = (head[ins_h] & 0xffff);
  6855. prev[strstart & w_mask] = head[ins_h];
  6856. head[ins_h] = strstart;
  6857. }
  6858. // Find the longest match, discarding those <= prev_length.
  6859. prev_length = match_length;
  6860. prev_match = match_start;
  6861. match_length = MIN_MATCH - 1;
  6862. if (hash_head !== 0 && prev_length < max_lazy_match && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {
  6863. // To simplify the code, we prevent matches with the string
  6864. // of window index 0 (in particular we have to avoid a match
  6865. // of the string with itself at the start of the input file).
  6866. if (strategy != Z_HUFFMAN_ONLY) {
  6867. match_length = longest_match(hash_head);
  6868. }
  6869. // longest_match() sets match_start
  6870. if (match_length <= 5 && (strategy == Z_FILTERED || (match_length == MIN_MATCH && strstart - match_start > 4096))) {
  6871. // If prev_match is also MIN_MATCH, match_start is garbage
  6872. // but we will ignore the current match anyway.
  6873. match_length = MIN_MATCH - 1;
  6874. }
  6875. }
  6876. // If there was a match at the previous step and the current
  6877. // match is not better, output the previous match:
  6878. if (prev_length >= MIN_MATCH && match_length <= prev_length) {
  6879. max_insert = strstart + lookahead - MIN_MATCH;
  6880. // Do not insert strings in hash table beyond this.
  6881. // check_match(strstart-1, prev_match, prev_length);
  6882. bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
  6883. // Insert in hash table all strings up to the end of the match.
  6884. // strstart-1 and strstart are already inserted. If there is not
  6885. // enough lookahead, the last two strings are not inserted in
  6886. // the hash table.
  6887. lookahead -= prev_length - 1;
  6888. prev_length -= 2;
  6889. do {
  6890. if (++strstart <= max_insert) {
  6891. ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
  6892. // prev[strstart&w_mask]=hash_head=head[ins_h];
  6893. hash_head = (head[ins_h] & 0xffff);
  6894. prev[strstart & w_mask] = head[ins_h];
  6895. head[ins_h] = strstart;
  6896. }
  6897. } while (--prev_length !== 0);
  6898. match_available = 0;
  6899. match_length = MIN_MATCH - 1;
  6900. strstart++;
  6901. if (bflush) {
  6902. flush_block_only(false);
  6903. if (strm.avail_out === 0)
  6904. return NeedMore;
  6905. }
  6906. } else if (match_available !== 0) {
  6907. // If there was no match at the previous position, output a
  6908. // single literal. If there was a match but the current match
  6909. // is longer, truncate the previous match to a single literal.
  6910. bflush = _tr_tally(0, window[strstart - 1] & 0xff);
  6911. if (bflush) {
  6912. flush_block_only(false);
  6913. }
  6914. strstart++;
  6915. lookahead--;
  6916. if (strm.avail_out === 0)
  6917. return NeedMore;
  6918. } else {
  6919. // There is no previous match to compare with, wait for
  6920. // the next step to decide.
  6921. match_available = 1;
  6922. strstart++;
  6923. lookahead--;
  6924. }
  6925. }
  6926. if (match_available !== 0) {
  6927. bflush = _tr_tally(0, window[strstart - 1] & 0xff);
  6928. match_available = 0;
  6929. }
  6930. flush_block_only(flush == Z_FINISH);
  6931. if (strm.avail_out === 0) {
  6932. if (flush == Z_FINISH)
  6933. return FinishStarted;
  6934. else
  6935. return NeedMore;
  6936. }
  6937. return flush == Z_FINISH ? FinishDone : BlockDone;
  6938. }
  6939. function deflateReset(strm) {
  6940. strm.total_in = strm.total_out = 0;
  6941. strm.msg = null; //
  6942. that.pending = 0;
  6943. that.pending_out = 0;
  6944. status = BUSY_STATE;
  6945. last_flush = Z_NO_FLUSH;
  6946. tr_init();
  6947. lm_init();
  6948. return Z_OK;
  6949. }
  6950. that.deflateInit = function (strm, _level, bits, _method, memLevel, _strategy) {
  6951. if (!_method)
  6952. _method = Z_DEFLATED;
  6953. if (!memLevel)
  6954. memLevel = DEF_MEM_LEVEL;
  6955. if (!_strategy)
  6956. _strategy = Z_DEFAULT_STRATEGY;
  6957. // byte[] my_version=ZLIB_VERSION;
  6958. //
  6959. // if (!version || version[0] != my_version[0]
  6960. // || stream_size != sizeof(z_stream)) {
  6961. // return Z_VERSION_ERROR;
  6962. // }
  6963. strm.msg = null;
  6964. if (_level == Z_DEFAULT_COMPRESSION)
  6965. _level = 6;
  6966. if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0
  6967. || _strategy > Z_HUFFMAN_ONLY) {
  6968. return Z_STREAM_ERROR;
  6969. }
  6970. strm.dstate = that;
  6971. w_bits = bits;
  6972. w_size = 1 << w_bits;
  6973. w_mask = w_size - 1;
  6974. hash_bits = memLevel + 7;
  6975. hash_size = 1 << hash_bits;
  6976. hash_mask = hash_size - 1;
  6977. hash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH);
  6978. window = new Uint8Array(w_size * 2);
  6979. prev = [];
  6980. head = [];
  6981. lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
  6982. // We overlay pending_buf and d_buf+l_buf. This works since the average
  6983. // output size for (length,distance) codes is <= 24 bits.
  6984. that.pending_buf = new Uint8Array(lit_bufsize * 4);
  6985. pending_buf_size = lit_bufsize * 4;
  6986. d_buf = Math.floor(lit_bufsize / 2);
  6987. l_buf = (1 + 2) * lit_bufsize;
  6988. level = _level;
  6989. strategy = _strategy;
  6990. method = _method & 0xff;
  6991. return deflateReset(strm);
  6992. };
  6993. that.deflateEnd = function () {
  6994. if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) {
  6995. return Z_STREAM_ERROR;
  6996. }
  6997. // Deallocate in reverse order of allocations:
  6998. that.pending_buf = null;
  6999. head = null;
  7000. prev = null;
  7001. window = null;
  7002. // free
  7003. that.dstate = null;
  7004. return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
  7005. };
  7006. that.deflateParams = function (strm, _level, _strategy) {
  7007. var err = Z_OK;
  7008. if (_level == Z_DEFAULT_COMPRESSION) {
  7009. _level = 6;
  7010. }
  7011. if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
  7012. return Z_STREAM_ERROR;
  7013. }
  7014. if (config_table[level].func != config_table[_level].func && strm.total_in !== 0) {
  7015. // Flush the last buffer:
  7016. err = strm.deflate(Z_PARTIAL_FLUSH);
  7017. }
  7018. if (level != _level) {
  7019. level = _level;
  7020. max_lazy_match = config_table[level].max_lazy;
  7021. good_match = config_table[level].good_length;
  7022. nice_match = config_table[level].nice_length;
  7023. max_chain_length = config_table[level].max_chain;
  7024. }
  7025. strategy = _strategy;
  7026. return err;
  7027. };
  7028. that.deflateSetDictionary = function (strm, dictionary, dictLength) {
  7029. var length = dictLength;
  7030. var n, index = 0;
  7031. if (!dictionary || status != INIT_STATE)
  7032. return Z_STREAM_ERROR;
  7033. if (length < MIN_MATCH)
  7034. return Z_OK;
  7035. if (length > w_size - MIN_LOOKAHEAD) {
  7036. length = w_size - MIN_LOOKAHEAD;
  7037. index = dictLength - length; // use the tail of the dictionary
  7038. }
  7039. window.set(dictionary.subarray(index, index + length), 0);
  7040. strstart = length;
  7041. block_start = length;
  7042. // Insert all strings in the hash table (except for the last two bytes).
  7043. // s->lookahead stays null, so s->ins_h will be recomputed at the next
  7044. // call of fill_window.
  7045. ins_h = window[0] & 0xff;
  7046. ins_h = (((ins_h) << hash_shift) ^ (window[1] & 0xff)) & hash_mask;
  7047. for (n = 0; n <= length - MIN_MATCH; n++) {
  7048. ins_h = (((ins_h) << hash_shift) ^ (window[(n) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
  7049. prev[n & w_mask] = head[ins_h];
  7050. head[ins_h] = n;
  7051. }
  7052. return Z_OK;
  7053. };
  7054. that.deflate = function (_strm, flush) {
  7055. var i, header, level_flags, old_flush, bstate;
  7056. if (flush > Z_FINISH || flush < 0) {
  7057. return Z_STREAM_ERROR;
  7058. }
  7059. if (!_strm.next_out || (!_strm.next_in && _strm.avail_in !== 0) || (status == FINISH_STATE && flush != Z_FINISH)) {
  7060. _strm.msg = z_errmsg[Z_NEED_DICT - (Z_STREAM_ERROR)];
  7061. return Z_STREAM_ERROR;
  7062. }
  7063. if (_strm.avail_out === 0) {
  7064. _strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
  7065. return Z_BUF_ERROR;
  7066. }
  7067. strm = _strm; // just in case
  7068. old_flush = last_flush;
  7069. last_flush = flush;
  7070. // Write the zlib header
  7071. if (status == INIT_STATE) {
  7072. header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8;
  7073. level_flags = ((level - 1) & 0xff) >> 1;
  7074. if (level_flags > 3)
  7075. level_flags = 3;
  7076. header |= (level_flags << 6);
  7077. if (strstart !== 0)
  7078. header |= PRESET_DICT;
  7079. header += 31 - (header % 31);
  7080. status = BUSY_STATE;
  7081. putShortMSB(header);
  7082. }
  7083. // Flush as much pending output as possible
  7084. if (that.pending !== 0) {
  7085. strm.flush_pending();
  7086. if (strm.avail_out === 0) {
  7087. // console.log(" avail_out==0");
  7088. // Since avail_out is 0, deflate will be called again with
  7089. // more output space, but possibly with both pending and
  7090. // avail_in equal to zero. There won't be anything to do,
  7091. // but this is not an error situation so make sure we
  7092. // return OK instead of BUF_ERROR at next call of deflate:
  7093. last_flush = -1;
  7094. return Z_OK;
  7095. }
  7096. // Make sure there is something to do and avoid duplicate
  7097. // consecutive
  7098. // flushes. For repeated and useless calls with Z_FINISH, we keep
  7099. // returning Z_STREAM_END instead of Z_BUFF_ERROR.
  7100. } else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) {
  7101. strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
  7102. return Z_BUF_ERROR;
  7103. }
  7104. // User must not provide more input after the first FINISH:
  7105. if (status == FINISH_STATE && strm.avail_in !== 0) {
  7106. _strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
  7107. return Z_BUF_ERROR;
  7108. }
  7109. // Start a new block or continue the current one.
  7110. if (strm.avail_in !== 0 || lookahead !== 0 || (flush != Z_NO_FLUSH && status != FINISH_STATE)) {
  7111. bstate = -1;
  7112. switch (config_table[level].func) {
  7113. case STORED:
  7114. bstate = deflate_stored(flush);
  7115. break;
  7116. case FAST:
  7117. bstate = deflate_fast(flush);
  7118. break;
  7119. case SLOW:
  7120. bstate = deflate_slow(flush);
  7121. break;
  7122. default:
  7123. }
  7124. if (bstate == FinishStarted || bstate == FinishDone) {
  7125. status = FINISH_STATE;
  7126. }
  7127. if (bstate == NeedMore || bstate == FinishStarted) {
  7128. if (strm.avail_out === 0) {
  7129. last_flush = -1; // avoid BUF_ERROR next call, see above
  7130. }
  7131. return Z_OK;
  7132. // If flush != Z_NO_FLUSH && avail_out === 0, the next call
  7133. // of deflate should use the same flush parameter to make sure
  7134. // that the flush is complete. So we don't have to output an
  7135. // empty block here, this will be done at next call. This also
  7136. // ensures that for a very small output buffer, we emit at most
  7137. // one empty block.
  7138. }
  7139. if (bstate == BlockDone) {
  7140. if (flush == Z_PARTIAL_FLUSH) {
  7141. _tr_align();
  7142. } else { // FULL_FLUSH or SYNC_FLUSH
  7143. _tr_stored_block(0, 0, false);
  7144. // For a full flush, this empty block will be recognized
  7145. // as a special marker by inflate_sync().
  7146. if (flush == Z_FULL_FLUSH) {
  7147. // state.head[s.hash_size-1]=0;
  7148. for (i = 0; i < hash_size/*-1*/; i++)
  7149. // forget history
  7150. head[i] = 0;
  7151. }
  7152. }
  7153. strm.flush_pending();
  7154. if (strm.avail_out === 0) {
  7155. last_flush = -1; // avoid BUF_ERROR at next call, see above
  7156. return Z_OK;
  7157. }
  7158. }
  7159. }
  7160. if (flush != Z_FINISH)
  7161. return Z_OK;
  7162. return Z_STREAM_END;
  7163. };
  7164. }
  7165. // ZStream
  7166. function ZStream() {
  7167. var that = this;
  7168. that.next_in_index = 0;
  7169. that.next_out_index = 0;
  7170. // that.next_in; // next input byte
  7171. that.avail_in = 0; // number of bytes available at next_in
  7172. that.total_in = 0; // total nb of input bytes read so far
  7173. // that.next_out; // next output byte should be put there
  7174. that.avail_out = 0; // remaining free space at next_out
  7175. that.total_out = 0; // total nb of bytes output so far
  7176. // that.msg;
  7177. // that.dstate;
  7178. }
  7179. ZStream.prototype = {
  7180. deflateInit: function (level, bits) {
  7181. var that = this;
  7182. that.dstate = new Deflate();
  7183. if (!bits)
  7184. bits = MAX_BITS;
  7185. return that.dstate.deflateInit(that, level, bits);
  7186. },
  7187. deflate: function (flush) {
  7188. var that = this;
  7189. if (!that.dstate) {
  7190. return Z_STREAM_ERROR;
  7191. }
  7192. return that.dstate.deflate(that, flush);
  7193. },
  7194. deflateEnd: function () {
  7195. var that = this;
  7196. if (!that.dstate)
  7197. return Z_STREAM_ERROR;
  7198. var ret = that.dstate.deflateEnd();
  7199. that.dstate = null;
  7200. return ret;
  7201. },
  7202. deflateParams: function (level, strategy) {
  7203. var that = this;
  7204. if (!that.dstate)
  7205. return Z_STREAM_ERROR;
  7206. return that.dstate.deflateParams(that, level, strategy);
  7207. },
  7208. deflateSetDictionary: function (dictionary, dictLength) {
  7209. var that = this;
  7210. if (!that.dstate)
  7211. return Z_STREAM_ERROR;
  7212. return that.dstate.deflateSetDictionary(that, dictionary, dictLength);
  7213. },
  7214. // Read a new buffer from the current input stream, update the
  7215. // total number of bytes read. All deflate() input goes through
  7216. // this function so some applications may wish to modify it to avoid
  7217. // allocating a large strm->next_in buffer and copying from it.
  7218. // (See also flush_pending()).
  7219. read_buf: function (buf, start, size) {
  7220. var that = this;
  7221. var len = that.avail_in;
  7222. if (len > size)
  7223. len = size;
  7224. if (len === 0)
  7225. return 0;
  7226. that.avail_in -= len;
  7227. buf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start);
  7228. that.next_in_index += len;
  7229. that.total_in += len;
  7230. return len;
  7231. },
  7232. // Flush as much pending output as possible. All deflate() output goes
  7233. // through this function so some applications may wish to modify it
  7234. // to avoid allocating a large strm->next_out buffer and copying into it.
  7235. // (See also read_buf()).
  7236. flush_pending: function () {
  7237. var that = this;
  7238. var len = that.dstate.pending;
  7239. if (len > that.avail_out)
  7240. len = that.avail_out;
  7241. if (len === 0)
  7242. return;
  7243. // if (that.dstate.pending_buf.length <= that.dstate.pending_out || that.next_out.length <= that.next_out_index
  7244. // || that.dstate.pending_buf.length < (that.dstate.pending_out + len) || that.next_out.length < (that.next_out_index +
  7245. // len)) {
  7246. // console.log(that.dstate.pending_buf.length + ", " + that.dstate.pending_out + ", " + that.next_out.length + ", " +
  7247. // that.next_out_index + ", " + len);
  7248. // console.log("avail_out=" + that.avail_out);
  7249. // }
  7250. that.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index);
  7251. that.next_out_index += len;
  7252. that.dstate.pending_out += len;
  7253. that.total_out += len;
  7254. that.avail_out -= len;
  7255. that.dstate.pending -= len;
  7256. if (that.dstate.pending === 0) {
  7257. that.dstate.pending_out = 0;
  7258. }
  7259. }
  7260. };
  7261. // Deflater
  7262. return function Deflater(level) {
  7263. var that = this;
  7264. var z = new ZStream();
  7265. var bufsize = 512;
  7266. var flush = Z_NO_FLUSH;
  7267. var buf = new Uint8Array(bufsize);
  7268. if (typeof level == "undefined")
  7269. level = Z_DEFAULT_COMPRESSION;
  7270. z.deflateInit(level);
  7271. z.next_out = buf;
  7272. that.append = function (data, onprogress) {
  7273. var err, buffers = [], lastIndex = 0, bufferIndex = 0, bufferSize = 0, array;
  7274. if (!data.length)
  7275. return;
  7276. z.next_in_index = 0;
  7277. z.next_in = data;
  7278. z.avail_in = data.length;
  7279. do {
  7280. z.next_out_index = 0;
  7281. z.avail_out = bufsize;
  7282. err = z.deflate(flush);
  7283. if (err != Z_OK)
  7284. throw "deflating: " + z.msg;
  7285. if (z.next_out_index)
  7286. if (z.next_out_index == bufsize)
  7287. buffers.push(new Uint8Array(buf));
  7288. else
  7289. buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
  7290. bufferSize += z.next_out_index;
  7291. if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
  7292. onprogress(z.next_in_index);
  7293. lastIndex = z.next_in_index;
  7294. }
  7295. } while (z.avail_in > 0 || z.avail_out === 0);
  7296. array = new Uint8Array(bufferSize);
  7297. buffers.forEach(function (chunk) {
  7298. array.set(chunk, bufferIndex);
  7299. bufferIndex += chunk.length;
  7300. });
  7301. return array;
  7302. };
  7303. that.flush = function () {
  7304. var err, buffers = [], bufferIndex = 0, bufferSize = 0, array;
  7305. do {
  7306. z.next_out_index = 0;
  7307. z.avail_out = bufsize;
  7308. err = z.deflate(Z_FINISH);
  7309. if (err != Z_STREAM_END && err != Z_OK)
  7310. throw "deflating: " + z.msg;
  7311. if (bufsize - z.avail_out > 0)
  7312. buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
  7313. bufferSize += z.next_out_index;
  7314. } while (z.avail_in > 0 || z.avail_out === 0);
  7315. z.deflateEnd();
  7316. array = new Uint8Array(bufferSize);
  7317. buffers.forEach(function (chunk) {
  7318. array.set(chunk, bufferIndex);
  7319. bufferIndex += chunk.length;
  7320. });
  7321. return array;
  7322. };
  7323. };
  7324. })(this);
  7325. // Generated by CoffeeScript 1.4.0
  7326. /*
  7327. # PNG.js
  7328. # Copyright (c) 2011 Devon Govett
  7329. # MIT LICENSE
  7330. #
  7331. # Permission is hereby granted, free of charge, to any person obtaining a copy of this
  7332. # software and associated documentation files (the "Software"), to deal in the Software
  7333. # without restriction, including without limitation the rights to use, copy, modify, merge,
  7334. # publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  7335. # to whom the Software is furnished to do so, subject to the following conditions:
  7336. #
  7337. # The above copyright notice and this permission notice shall be included in all copies or
  7338. # substantial portions of the Software.
  7339. #
  7340. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
  7341. # BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  7342. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  7343. # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  7344. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  7345. */
  7346. (function (global) {
  7347. var PNG;
  7348. PNG = (function () {
  7349. var APNG_BLEND_OP_OVER, APNG_BLEND_OP_SOURCE, APNG_DISPOSE_OP_BACKGROUND, APNG_DISPOSE_OP_NONE, APNG_DISPOSE_OP_PREVIOUS, makeImage, scratchCanvas, scratchCtx;
  7350. PNG.load = function (url, canvas, callback) {
  7351. var xhr,
  7352. _this = this;
  7353. if (typeof canvas === 'function') {
  7354. callback = canvas;
  7355. }
  7356. xhr = new XMLHttpRequest;
  7357. xhr.open("GET", url, true);
  7358. xhr.responseType = "arraybuffer";
  7359. xhr.onload = function () {
  7360. var data, png;
  7361. data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
  7362. png = new PNG(data);
  7363. if (typeof (canvas != null ? canvas.getContext : void 0) === 'function') {
  7364. png.render(canvas);
  7365. }
  7366. return typeof callback === "function" ? callback(png) : void 0;
  7367. };
  7368. return xhr.send(null);
  7369. };
  7370. APNG_DISPOSE_OP_NONE = 0;
  7371. APNG_DISPOSE_OP_BACKGROUND = 1;
  7372. APNG_DISPOSE_OP_PREVIOUS = 2;
  7373. APNG_BLEND_OP_SOURCE = 0;
  7374. APNG_BLEND_OP_OVER = 1;
  7375. function PNG(data) {
  7376. var chunkSize, colors, palLen, delayDen, delayNum, frame, i, index, key, section, palShort, text, _i, _j, _ref;
  7377. this.data = data;
  7378. this.pos = 8;
  7379. this.palette = [];
  7380. this.imgData = [];
  7381. this.transparency = {};
  7382. this.animation = null;
  7383. this.text = {};
  7384. frame = null;
  7385. while (true) {
  7386. chunkSize = this.readUInt32();
  7387. section = ((function () {
  7388. var _i, _results;
  7389. _results = [];
  7390. for (i = _i = 0; _i < 4; i = ++_i) {
  7391. _results.push(String.fromCharCode(this.data[this.pos++]));
  7392. }
  7393. return _results;
  7394. }).call(this)).join('');
  7395. switch (section) {
  7396. case 'IHDR':
  7397. this.width = this.readUInt32();
  7398. this.height = this.readUInt32();
  7399. this.bits = this.data[this.pos++];
  7400. this.colorType = this.data[this.pos++];
  7401. this.compressionMethod = this.data[this.pos++];
  7402. this.filterMethod = this.data[this.pos++];
  7403. this.interlaceMethod = this.data[this.pos++];
  7404. break;
  7405. case 'acTL':
  7406. this.animation = {
  7407. numFrames: this.readUInt32(),
  7408. numPlays: this.readUInt32() || Infinity,
  7409. frames: []
  7410. };
  7411. break;
  7412. case 'PLTE':
  7413. this.palette = this.read(chunkSize);
  7414. break;
  7415. case 'fcTL':
  7416. if (frame) {
  7417. this.animation.frames.push(frame);
  7418. }
  7419. this.pos += 4;
  7420. frame = {
  7421. width: this.readUInt32(),
  7422. height: this.readUInt32(),
  7423. xOffset: this.readUInt32(),
  7424. yOffset: this.readUInt32()
  7425. };
  7426. delayNum = this.readUInt16();
  7427. delayDen = this.readUInt16() || 100;
  7428. frame.delay = 1000 * delayNum / delayDen;
  7429. frame.disposeOp = this.data[this.pos++];
  7430. frame.blendOp = this.data[this.pos++];
  7431. frame.data = [];
  7432. break;
  7433. case 'IDAT':
  7434. case 'fdAT':
  7435. if (section === 'fdAT') {
  7436. this.pos += 4;
  7437. chunkSize -= 4;
  7438. }
  7439. data = (frame != null ? frame.data : void 0) || this.imgData;
  7440. for (i = _i = 0; 0 <= chunkSize ? _i < chunkSize : _i > chunkSize; i = 0 <= chunkSize ? ++_i : --_i) {
  7441. data.push(this.data[this.pos++]);
  7442. }
  7443. break;
  7444. case 'tRNS':
  7445. this.transparency = {};
  7446. switch (this.colorType) {
  7447. case 3:
  7448. palLen = this.palette.length / 3;
  7449. this.transparency.indexed = this.read(chunkSize);
  7450. if (this.transparency.indexed.length > palLen)
  7451. throw new Error('More transparent colors than palette size');
  7452. /*
  7453. * According to the PNG spec trns should be increased to the same size as palette if shorter
  7454. */
  7455. //palShort = 255 - this.transparency.indexed.length;
  7456. palShort = palLen - this.transparency.indexed.length;
  7457. if (palShort > 0) {
  7458. for (i = _j = 0; 0 <= palShort ? _j < palShort : _j > palShort; i = 0 <= palShort ? ++_j : --_j) {
  7459. this.transparency.indexed.push(255);
  7460. }
  7461. }
  7462. break;
  7463. case 0:
  7464. this.transparency.grayscale = this.read(chunkSize)[0];
  7465. break;
  7466. case 2:
  7467. this.transparency.rgb = this.read(chunkSize);
  7468. }
  7469. break;
  7470. case 'tEXt':
  7471. text = this.read(chunkSize);
  7472. index = text.indexOf(0);
  7473. key = String.fromCharCode.apply(String, text.slice(0, index));
  7474. this.text[key] = String.fromCharCode.apply(String, text.slice(index + 1));
  7475. break;
  7476. case 'IEND':
  7477. if (frame) {
  7478. this.animation.frames.push(frame);
  7479. }
  7480. this.colors = (function () {
  7481. switch (this.colorType) {
  7482. case 0:
  7483. case 3:
  7484. case 4:
  7485. return 1;
  7486. case 2:
  7487. case 6:
  7488. return 3;
  7489. }
  7490. }).call(this);
  7491. this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6;
  7492. colors = this.colors + (this.hasAlphaChannel ? 1 : 0);
  7493. this.pixelBitlength = this.bits * colors;
  7494. this.colorSpace = (function () {
  7495. switch (this.colors) {
  7496. case 1:
  7497. return 'DeviceGray';
  7498. case 3:
  7499. return 'DeviceRGB';
  7500. }
  7501. }).call(this);
  7502. this.imgData = new Uint8Array(this.imgData);
  7503. return;
  7504. default:
  7505. this.pos += chunkSize;
  7506. }
  7507. this.pos += 4;
  7508. if (this.pos > this.data.length) {
  7509. throw new Error("Incomplete or corrupt PNG file");
  7510. }
  7511. }
  7512. return;
  7513. }
  7514. PNG.prototype.read = function (bytes) {
  7515. var i, _i, _results;
  7516. _results = [];
  7517. for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) {
  7518. _results.push(this.data[this.pos++]);
  7519. }
  7520. return _results;
  7521. };
  7522. PNG.prototype.readUInt32 = function () {
  7523. var b1, b2, b3, b4;
  7524. b1 = this.data[this.pos++] << 24;
  7525. b2 = this.data[this.pos++] << 16;
  7526. b3 = this.data[this.pos++] << 8;
  7527. b4 = this.data[this.pos++];
  7528. return b1 | b2 | b3 | b4;
  7529. };
  7530. PNG.prototype.readUInt16 = function () {
  7531. var b1, b2;
  7532. b1 = this.data[this.pos++] << 8;
  7533. b2 = this.data[this.pos++];
  7534. return b1 | b2;
  7535. };
  7536. PNG.prototype.decodePixels = function (data) {
  7537. var abyte, c, col, i, left, length, p, pa, paeth, pb, pc, pixelBytes, pixels, pos, row, scanlineLength, upper, upperLeft, _i, _j, _k, _l, _m;
  7538. if (data == null) {
  7539. data = this.imgData;
  7540. }
  7541. if (data.length === 0) {
  7542. return new Uint8Array(0);
  7543. }
  7544. data = new FlateStream(data);
  7545. data = data.getBytes();
  7546. pixelBytes = this.pixelBitlength / 8;
  7547. scanlineLength = pixelBytes * this.width;
  7548. pixels = new Uint8Array(scanlineLength * this.height);
  7549. length = data.length;
  7550. row = 0;
  7551. pos = 0;
  7552. c = 0;
  7553. while (pos < length) {
  7554. switch (data[pos++]) {
  7555. case 0:
  7556. for (i = _i = 0; _i < scanlineLength; i = _i += 1) {
  7557. pixels[c++] = data[pos++];
  7558. }
  7559. break;
  7560. case 1:
  7561. for (i = _j = 0; _j < scanlineLength; i = _j += 1) {
  7562. abyte = data[pos++];
  7563. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  7564. pixels[c++] = (abyte + left) % 256;
  7565. }
  7566. break;
  7567. case 2:
  7568. for (i = _k = 0; _k < scanlineLength; i = _k += 1) {
  7569. abyte = data[pos++];
  7570. col = (i - (i % pixelBytes)) / pixelBytes;
  7571. upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
  7572. pixels[c++] = (upper + abyte) % 256;
  7573. }
  7574. break;
  7575. case 3:
  7576. for (i = _l = 0; _l < scanlineLength; i = _l += 1) {
  7577. abyte = data[pos++];
  7578. col = (i - (i % pixelBytes)) / pixelBytes;
  7579. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  7580. upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
  7581. pixels[c++] = (abyte + Math.floor((left + upper) / 2)) % 256;
  7582. }
  7583. break;
  7584. case 4:
  7585. for (i = _m = 0; _m < scanlineLength; i = _m += 1) {
  7586. abyte = data[pos++];
  7587. col = (i - (i % pixelBytes)) / pixelBytes;
  7588. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  7589. if (row === 0) {
  7590. upper = upperLeft = 0;
  7591. } else {
  7592. upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
  7593. upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + (i % pixelBytes)];
  7594. }
  7595. p = left + upper - upperLeft;
  7596. pa = Math.abs(p - left);
  7597. pb = Math.abs(p - upper);
  7598. pc = Math.abs(p - upperLeft);
  7599. if (pa <= pb && pa <= pc) {
  7600. paeth = left;
  7601. } else if (pb <= pc) {
  7602. paeth = upper;
  7603. } else {
  7604. paeth = upperLeft;
  7605. }
  7606. pixels[c++] = (abyte + paeth) % 256;
  7607. }
  7608. break;
  7609. default:
  7610. throw new Error("Invalid filter algorithm: " + data[pos - 1]);
  7611. }
  7612. row++;
  7613. }
  7614. return pixels;
  7615. };
  7616. PNG.prototype.decodePalette = function () {
  7617. var c, i, length, palette, pos, ret, transparency, _i, _ref, _ref1;
  7618. palette = this.palette;
  7619. transparency = this.transparency.indexed || [];
  7620. ret = new Uint8Array((transparency.length || 0) + palette.length);
  7621. pos = 0;
  7622. length = palette.length;
  7623. c = 0;
  7624. for (i = _i = 0, _ref = palette.length; _i < _ref; i = _i += 3) {
  7625. ret[pos++] = palette[i];
  7626. ret[pos++] = palette[i + 1];
  7627. ret[pos++] = palette[i + 2];
  7628. ret[pos++] = (_ref1 = transparency[c++]) != null ? _ref1 : 255;
  7629. }
  7630. return ret;
  7631. };
  7632. PNG.prototype.copyToImageData = function (imageData, pixels) {
  7633. var alpha, colors, data, i, input, j, k, length, palette, v, _ref;
  7634. colors = this.colors;
  7635. palette = null;
  7636. alpha = this.hasAlphaChannel;
  7637. if (this.palette.length) {
  7638. palette = (_ref = this._decodedPalette) != null ? _ref : this._decodedPalette = this.decodePalette();
  7639. colors = 4;
  7640. alpha = true;
  7641. }
  7642. data = imageData.data || imageData;
  7643. length = data.length;
  7644. input = palette || pixels;
  7645. i = j = 0;
  7646. if (colors === 1) {
  7647. while (i < length) {
  7648. k = palette ? pixels[i / 4] * 4 : j;
  7649. v = input[k++];
  7650. data[i++] = v;
  7651. data[i++] = v;
  7652. data[i++] = v;
  7653. data[i++] = alpha ? input[k++] : 255;
  7654. j = k;
  7655. }
  7656. } else {
  7657. while (i < length) {
  7658. k = palette ? pixels[i / 4] * 4 : j;
  7659. data[i++] = input[k++];
  7660. data[i++] = input[k++];
  7661. data[i++] = input[k++];
  7662. data[i++] = alpha ? input[k++] : 255;
  7663. j = k;
  7664. }
  7665. }
  7666. };
  7667. PNG.prototype.decode = function () {
  7668. var ret;
  7669. ret = new Uint8Array(this.width * this.height * 4);
  7670. this.copyToImageData(ret, this.decodePixels());
  7671. return ret;
  7672. };
  7673. try {
  7674. scratchCanvas = global.document.createElement('canvas');
  7675. scratchCtx = scratchCanvas.getContext('2d');
  7676. } catch (e) {
  7677. return -1;
  7678. }
  7679. makeImage = function (imageData) {
  7680. var img;
  7681. scratchCtx.width = imageData.width;
  7682. scratchCtx.height = imageData.height;
  7683. scratchCtx.clearRect(0, 0, imageData.width, imageData.height);
  7684. scratchCtx.putImageData(imageData, 0, 0);
  7685. img = new Image;
  7686. img.src = scratchCanvas.toDataURL();
  7687. return img;
  7688. };
  7689. PNG.prototype.decodeFrames = function (ctx) {
  7690. var frame, i, imageData, pixels, _i, _len, _ref, _results;
  7691. if (!this.animation) {
  7692. return;
  7693. }
  7694. _ref = this.animation.frames;
  7695. _results = [];
  7696. for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
  7697. frame = _ref[i];
  7698. imageData = ctx.createImageData(frame.width, frame.height);
  7699. pixels = this.decodePixels(new Uint8Array(frame.data));
  7700. this.copyToImageData(imageData, pixels);
  7701. frame.imageData = imageData;
  7702. _results.push(frame.image = makeImage(imageData));
  7703. }
  7704. return _results;
  7705. };
  7706. PNG.prototype.renderFrame = function (ctx, number) {
  7707. var frame, frames, prev;
  7708. frames = this.animation.frames;
  7709. frame = frames[number];
  7710. prev = frames[number - 1];
  7711. if (number === 0) {
  7712. ctx.clearRect(0, 0, this.width, this.height);
  7713. }
  7714. if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_BACKGROUND) {
  7715. ctx.clearRect(prev.xOffset, prev.yOffset, prev.width, prev.height);
  7716. } else if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_PREVIOUS) {
  7717. ctx.putImageData(prev.imageData, prev.xOffset, prev.yOffset);
  7718. }
  7719. if (frame.blendOp === APNG_BLEND_OP_SOURCE) {
  7720. ctx.clearRect(frame.xOffset, frame.yOffset, frame.width, frame.height);
  7721. }
  7722. return ctx.drawImage(frame.image, frame.xOffset, frame.yOffset);
  7723. };
  7724. PNG.prototype.animate = function (ctx) {
  7725. var doFrame, frameNumber, frames, numFrames, numPlays, _ref,
  7726. _this = this;
  7727. frameNumber = 0;
  7728. _ref = this.animation, numFrames = _ref.numFrames, frames = _ref.frames, numPlays = _ref.numPlays;
  7729. return (doFrame = function () {
  7730. var f, frame;
  7731. f = frameNumber++ % numFrames;
  7732. frame = frames[f];
  7733. _this.renderFrame(ctx, f);
  7734. if (numFrames > 1 && frameNumber / numFrames < numPlays) {
  7735. return _this.animation._timeout = setTimeout(doFrame, frame.delay);
  7736. }
  7737. })();
  7738. };
  7739. PNG.prototype.stopAnimation = function () {
  7740. var _ref;
  7741. return clearTimeout((_ref = this.animation) != null ? _ref._timeout : void 0);
  7742. };
  7743. PNG.prototype.render = function (canvas) {
  7744. var ctx, data;
  7745. if (canvas._png) {
  7746. canvas._png.stopAnimation();
  7747. }
  7748. canvas._png = this;
  7749. canvas.width = this.width;
  7750. canvas.height = this.height;
  7751. ctx = canvas.getContext("2d");
  7752. if (this.animation) {
  7753. this.decodeFrames(ctx);
  7754. return this.animate(ctx);
  7755. } else {
  7756. data = ctx.createImageData(this.width, this.height);
  7757. this.copyToImageData(data, this.decodePixels());
  7758. return ctx.putImageData(data, 0, 0);
  7759. }
  7760. };
  7761. return PNG;
  7762. })();
  7763. global.PNG = PNG;
  7764. })(typeof window !== "undefined" && window || this);
  7765. /*
  7766. * Extracted from pdf.js
  7767. * https://github.com/andreasgal/pdf.js
  7768. *
  7769. * Copyright (c) 2011 Mozilla Foundation
  7770. *
  7771. * Contributors: Andreas Gal <gal@mozilla.com>
  7772. * Chris G Jones <cjones@mozilla.com>
  7773. * Shaon Barman <shaon.barman@gmail.com>
  7774. * Vivien Nicolas <21@vingtetun.org>
  7775. * Justin D'Arcangelo <justindarc@gmail.com>
  7776. * Yury Delendik
  7777. *
  7778. * Permission is hereby granted, free of charge, to any person obtaining a
  7779. * copy of this software and associated documentation files (the "Software"),
  7780. * to deal in the Software without restriction, including without limitation
  7781. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  7782. * and/or sell copies of the Software, and to permit persons to whom the
  7783. * Software is furnished to do so, subject to the following conditions:
  7784. *
  7785. * The above copyright notice and this permission notice shall be included in
  7786. * all copies or substantial portions of the Software.
  7787. *
  7788. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  7789. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  7790. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  7791. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  7792. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  7793. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  7794. * DEALINGS IN THE SOFTWARE.
  7795. */
  7796. var DecodeStream = (function () {
  7797. function constructor() {
  7798. this.pos = 0;
  7799. this.bufferLength = 0;
  7800. this.eof = false;
  7801. this.buffer = null;
  7802. }
  7803. constructor.prototype = {
  7804. ensureBuffer: function decodestream_ensureBuffer(requested) {
  7805. var buffer = this.buffer;
  7806. var current = buffer ? buffer.byteLength : 0;
  7807. if (requested < current)
  7808. return buffer;
  7809. var size = 512;
  7810. while (size < requested)
  7811. size <<= 1;
  7812. var buffer2 = new Uint8Array(size);
  7813. for (var i = 0; i < current; ++i)
  7814. buffer2[i] = buffer[i];
  7815. return this.buffer = buffer2;
  7816. },
  7817. getByte: function decodestream_getByte() {
  7818. var pos = this.pos;
  7819. while (this.bufferLength <= pos) {
  7820. if (this.eof)
  7821. return null;
  7822. this.readBlock();
  7823. }
  7824. return this.buffer[this.pos++];
  7825. },
  7826. getBytes: function decodestream_getBytes(length) {
  7827. var pos = this.pos;
  7828. if (length) {
  7829. this.ensureBuffer(pos + length);
  7830. var end = pos + length;
  7831. while (!this.eof && this.bufferLength < end)
  7832. this.readBlock();
  7833. var bufEnd = this.bufferLength;
  7834. if (end > bufEnd)
  7835. end = bufEnd;
  7836. } else {
  7837. while (!this.eof)
  7838. this.readBlock();
  7839. var end = this.bufferLength;
  7840. }
  7841. this.pos = end;
  7842. return this.buffer.subarray(pos, end);
  7843. },
  7844. lookChar: function decodestream_lookChar() {
  7845. var pos = this.pos;
  7846. while (this.bufferLength <= pos) {
  7847. if (this.eof)
  7848. return null;
  7849. this.readBlock();
  7850. }
  7851. return String.fromCharCode(this.buffer[this.pos]);
  7852. },
  7853. getChar: function decodestream_getChar() {
  7854. var pos = this.pos;
  7855. while (this.bufferLength <= pos) {
  7856. if (this.eof)
  7857. return null;
  7858. this.readBlock();
  7859. }
  7860. return String.fromCharCode(this.buffer[this.pos++]);
  7861. },
  7862. makeSubStream: function decodestream_makeSubstream(start, length, dict) {
  7863. var end = start + length;
  7864. while (this.bufferLength <= end && !this.eof)
  7865. this.readBlock();
  7866. return new Stream(this.buffer, start, length, dict);
  7867. },
  7868. skip: function decodestream_skip(n) {
  7869. if (!n)
  7870. n = 1;
  7871. this.pos += n;
  7872. },
  7873. reset: function decodestream_reset() {
  7874. this.pos = 0;
  7875. }
  7876. };
  7877. return constructor;
  7878. })();
  7879. var FlateStream = (function () {
  7880. if (typeof Uint32Array === 'undefined') {
  7881. return undefined;
  7882. }
  7883. var codeLenCodeMap = new Uint32Array([
  7884. 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
  7885. ]);
  7886. var lengthDecode = new Uint32Array([
  7887. 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a,
  7888. 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f,
  7889. 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073,
  7890. 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102
  7891. ]);
  7892. var distDecode = new Uint32Array([
  7893. 0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d,
  7894. 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1,
  7895. 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01,
  7896. 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001
  7897. ]);
  7898. var fixedLitCodeTab = [new Uint32Array([
  7899. 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0,
  7900. 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0,
  7901. 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0,
  7902. 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0,
  7903. 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8,
  7904. 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8,
  7905. 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8,
  7906. 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8,
  7907. 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4,
  7908. 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4,
  7909. 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4,
  7910. 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4,
  7911. 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc,
  7912. 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec,
  7913. 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc,
  7914. 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc,
  7915. 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2,
  7916. 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2,
  7917. 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2,
  7918. 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2,
  7919. 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca,
  7920. 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea,
  7921. 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da,
  7922. 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa,
  7923. 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6,
  7924. 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6,
  7925. 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6,
  7926. 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6,
  7927. 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce,
  7928. 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee,
  7929. 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de,
  7930. 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe,
  7931. 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1,
  7932. 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1,
  7933. 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1,
  7934. 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1,
  7935. 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9,
  7936. 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9,
  7937. 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9,
  7938. 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9,
  7939. 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5,
  7940. 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5,
  7941. 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5,
  7942. 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5,
  7943. 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd,
  7944. 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed,
  7945. 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd,
  7946. 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd,
  7947. 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3,
  7948. 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3,
  7949. 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3,
  7950. 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3,
  7951. 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb,
  7952. 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb,
  7953. 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db,
  7954. 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb,
  7955. 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7,
  7956. 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7,
  7957. 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7,
  7958. 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7,
  7959. 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf,
  7960. 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef,
  7961. 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df,
  7962. 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff
  7963. ]), 9];
  7964. var fixedDistCodeTab = [new Uint32Array([
  7965. 0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c,
  7966. 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000,
  7967. 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d,
  7968. 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000
  7969. ]), 5];
  7970. function error(e) {
  7971. throw new Error(e)
  7972. }
  7973. function constructor(bytes) {
  7974. //var bytes = stream.getBytes();
  7975. var bytesPos = 0;
  7976. var cmf = bytes[bytesPos++];
  7977. var flg = bytes[bytesPos++];
  7978. if (cmf == -1 || flg == -1)
  7979. error('Invalid header in flate stream');
  7980. if ((cmf & 0x0f) != 0x08)
  7981. error('Unknown compression method in flate stream');
  7982. if ((((cmf << 8) + flg) % 31) != 0)
  7983. error('Bad FCHECK in flate stream');
  7984. if (flg & 0x20)
  7985. error('FDICT bit set in flate stream');
  7986. this.bytes = bytes;
  7987. this.bytesPos = bytesPos;
  7988. this.codeSize = 0;
  7989. this.codeBuf = 0;
  7990. DecodeStream.call(this);
  7991. }
  7992. constructor.prototype = Object.create(DecodeStream.prototype);
  7993. constructor.prototype.getBits = function (bits) {
  7994. var codeSize = this.codeSize;
  7995. var codeBuf = this.codeBuf;
  7996. var bytes = this.bytes;
  7997. var bytesPos = this.bytesPos;
  7998. var b;
  7999. while (codeSize < bits) {
  8000. if (typeof (b = bytes[bytesPos++]) == 'undefined')
  8001. error('Bad encoding in flate stream');
  8002. codeBuf |= b << codeSize;
  8003. codeSize += 8;
  8004. }
  8005. b = codeBuf & ((1 << bits) - 1);
  8006. this.codeBuf = codeBuf >> bits;
  8007. this.codeSize = codeSize -= bits;
  8008. this.bytesPos = bytesPos;
  8009. return b;
  8010. };
  8011. constructor.prototype.getCode = function (table) {
  8012. var codes = table[0];
  8013. var maxLen = table[1];
  8014. var codeSize = this.codeSize;
  8015. var codeBuf = this.codeBuf;
  8016. var bytes = this.bytes;
  8017. var bytesPos = this.bytesPos;
  8018. while (codeSize < maxLen) {
  8019. var b;
  8020. if (typeof (b = bytes[bytesPos++]) == 'undefined')
  8021. error('Bad encoding in flate stream');
  8022. codeBuf |= (b << codeSize);
  8023. codeSize += 8;
  8024. }
  8025. var code = codes[codeBuf & ((1 << maxLen) - 1)];
  8026. var codeLen = code >> 16;
  8027. var codeVal = code & 0xffff;
  8028. if (codeSize == 0 || codeSize < codeLen || codeLen == 0)
  8029. error('Bad encoding in flate stream');
  8030. this.codeBuf = (codeBuf >> codeLen);
  8031. this.codeSize = (codeSize - codeLen);
  8032. this.bytesPos = bytesPos;
  8033. return codeVal;
  8034. };
  8035. constructor.prototype.generateHuffmanTable = function (lengths) {
  8036. var n = lengths.length;
  8037. // find max code length
  8038. var maxLen = 0;
  8039. for (var i = 0; i < n; ++i) {
  8040. if (lengths[i] > maxLen)
  8041. maxLen = lengths[i];
  8042. }
  8043. // build the table
  8044. var size = 1 << maxLen;
  8045. var codes = new Uint32Array(size);
  8046. for (var len = 1, code = 0, skip = 2;
  8047. len <= maxLen;
  8048. ++len, code <<= 1, skip <<= 1) {
  8049. for (var val = 0; val < n; ++val) {
  8050. if (lengths[val] == len) {
  8051. // bit-reverse the code
  8052. var code2 = 0;
  8053. var t = code;
  8054. for (var i = 0; i < len; ++i) {
  8055. code2 = (code2 << 1) | (t & 1);
  8056. t >>= 1;
  8057. }
  8058. // fill the table entries
  8059. for (var i = code2; i < size; i += skip)
  8060. codes[i] = (len << 16) | val;
  8061. ++code;
  8062. }
  8063. }
  8064. }
  8065. return [codes, maxLen];
  8066. };
  8067. constructor.prototype.readBlock = function () {
  8068. function repeat(stream, array, len, offset, what) {
  8069. var repeat = stream.getBits(len) + offset;
  8070. while (repeat-- > 0)
  8071. array[i++] = what;
  8072. }
  8073. // read block header
  8074. var hdr = this.getBits(3);
  8075. if (hdr & 1)
  8076. this.eof = true;
  8077. hdr >>= 1;
  8078. if (hdr == 0) { // uncompressed block
  8079. var bytes = this.bytes;
  8080. var bytesPos = this.bytesPos;
  8081. var b;
  8082. if (typeof (b = bytes[bytesPos++]) == 'undefined')
  8083. error('Bad block header in flate stream');
  8084. var blockLen = b;
  8085. if (typeof (b = bytes[bytesPos++]) == 'undefined')
  8086. error('Bad block header in flate stream');
  8087. blockLen |= (b << 8);
  8088. if (typeof (b = bytes[bytesPos++]) == 'undefined')
  8089. error('Bad block header in flate stream');
  8090. var check = b;
  8091. if (typeof (b = bytes[bytesPos++]) == 'undefined')
  8092. error('Bad block header in flate stream');
  8093. check |= (b << 8);
  8094. if (check != (~blockLen & 0xffff))
  8095. error('Bad uncompressed block length in flate stream');
  8096. this.codeBuf = 0;
  8097. this.codeSize = 0;
  8098. var bufferLength = this.bufferLength;
  8099. var buffer = this.ensureBuffer(bufferLength + blockLen);
  8100. var end = bufferLength + blockLen;
  8101. this.bufferLength = end;
  8102. for (var n = bufferLength; n < end; ++n) {
  8103. if (typeof (b = bytes[bytesPos++]) == 'undefined') {
  8104. this.eof = true;
  8105. break;
  8106. }
  8107. buffer[n] = b;
  8108. }
  8109. this.bytesPos = bytesPos;
  8110. return;
  8111. }
  8112. var litCodeTable;
  8113. var distCodeTable;
  8114. if (hdr == 1) { // compressed block, fixed codes
  8115. litCodeTable = fixedLitCodeTab;
  8116. distCodeTable = fixedDistCodeTab;
  8117. } else if (hdr == 2) { // compressed block, dynamic codes
  8118. var numLitCodes = this.getBits(5) + 257;
  8119. var numDistCodes = this.getBits(5) + 1;
  8120. var numCodeLenCodes = this.getBits(4) + 4;
  8121. // build the code lengths code table
  8122. var codeLenCodeLengths = Array(codeLenCodeMap.length);
  8123. var i = 0;
  8124. while (i < numCodeLenCodes)
  8125. codeLenCodeLengths[codeLenCodeMap[i++]] = this.getBits(3);
  8126. var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths);
  8127. // build the literal and distance code tables
  8128. var len = 0;
  8129. var i = 0;
  8130. var codes = numLitCodes + numDistCodes;
  8131. var codeLengths = new Array(codes);
  8132. while (i < codes) {
  8133. var code = this.getCode(codeLenCodeTab);
  8134. if (code == 16) {
  8135. repeat(this, codeLengths, 2, 3, len);
  8136. } else if (code == 17) {
  8137. repeat(this, codeLengths, 3, 3, len = 0);
  8138. } else if (code == 18) {
  8139. repeat(this, codeLengths, 7, 11, len = 0);
  8140. } else {
  8141. codeLengths[i++] = len = code;
  8142. }
  8143. }
  8144. litCodeTable =
  8145. this.generateHuffmanTable(codeLengths.slice(0, numLitCodes));
  8146. distCodeTable =
  8147. this.generateHuffmanTable(codeLengths.slice(numLitCodes, codes));
  8148. } else {
  8149. error('Unknown block type in flate stream');
  8150. }
  8151. var buffer = this.buffer;
  8152. var limit = buffer ? buffer.length : 0;
  8153. var pos = this.bufferLength;
  8154. while (true) {
  8155. var code1 = this.getCode(litCodeTable);
  8156. if (code1 < 256) {
  8157. if (pos + 1 >= limit) {
  8158. buffer = this.ensureBuffer(pos + 1);
  8159. limit = buffer.length;
  8160. }
  8161. buffer[pos++] = code1;
  8162. continue;
  8163. }
  8164. if (code1 == 256) {
  8165. this.bufferLength = pos;
  8166. return;
  8167. }
  8168. code1 -= 257;
  8169. code1 = lengthDecode[code1];
  8170. var code2 = code1 >> 16;
  8171. if (code2 > 0)
  8172. code2 = this.getBits(code2);
  8173. var len = (code1 & 0xffff) + code2;
  8174. code1 = this.getCode(distCodeTable);
  8175. code1 = distDecode[code1];
  8176. code2 = code1 >> 16;
  8177. if (code2 > 0)
  8178. code2 = this.getBits(code2);
  8179. var dist = (code1 & 0xffff) + code2;
  8180. if (pos + len >= limit) {
  8181. buffer = this.ensureBuffer(pos + len);
  8182. limit = buffer.length;
  8183. }
  8184. for (var k = 0; k < len; ++k, ++pos)
  8185. buffer[pos] = buffer[pos - dist];
  8186. }
  8187. };
  8188. return constructor;
  8189. })();/**
  8190. * JavaScript Polyfill functions for jsPDF
  8191. * Collected from public resources by
  8192. * https://github.com/diegocr
  8193. */
  8194. (function (global) {
  8195. var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  8196. if (typeof global.btoa === 'undefined') {
  8197. global.btoa = function (data) {
  8198. // discuss at: http://phpjs.org/functions/base64_encode/
  8199. // original by: Tyler Akins (http://rumkin.com)
  8200. // improved by: Bayron Guevara
  8201. // improved by: Thunder.m
  8202. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  8203. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  8204. // improved by: Rafal Kukawski (http://kukawski.pl)
  8205. // bugfixed by: Pellentesque Malesuada
  8206. // example 1: base64_encode('Kevin van Zonneveld');
  8207. // returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
  8208. var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc = '', tmp_arr = [];
  8209. if (!data) {
  8210. return data;
  8211. }
  8212. do { // pack three octets into four hexets
  8213. o1 = data.charCodeAt(i++);
  8214. o2 = data.charCodeAt(i++);
  8215. o3 = data.charCodeAt(i++);
  8216. bits = o1 << 16 | o2 << 8 | o3;
  8217. h1 = bits >> 18 & 0x3f;
  8218. h2 = bits >> 12 & 0x3f;
  8219. h3 = bits >> 6 & 0x3f;
  8220. h4 = bits & 0x3f;
  8221. // use hexets to index into b64, and append result to encoded string
  8222. tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
  8223. } while (i < data.length);
  8224. enc = tmp_arr.join('');
  8225. var r = data.length % 3;
  8226. return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
  8227. };
  8228. }
  8229. if (typeof global.atob === 'undefined') {
  8230. global.atob = function (data) {
  8231. // discuss at: http://phpjs.org/functions/base64_decode/
  8232. // original by: Tyler Akins (http://rumkin.com)
  8233. // improved by: Thunder.m
  8234. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  8235. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  8236. // input by: Aman Gupta
  8237. // input by: Brett Zamir (http://brett-zamir.me)
  8238. // bugfixed by: Onno Marsman
  8239. // bugfixed by: Pellentesque Malesuada
  8240. // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  8241. // example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
  8242. // returns 1: 'Kevin van Zonneveld'
  8243. var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, dec = '', tmp_arr = [];
  8244. if (!data) {
  8245. return data;
  8246. }
  8247. data += '';
  8248. do { // unpack four hexets into three octets using index points in b64
  8249. h1 = b64.indexOf(data.charAt(i++));
  8250. h2 = b64.indexOf(data.charAt(i++));
  8251. h3 = b64.indexOf(data.charAt(i++));
  8252. h4 = b64.indexOf(data.charAt(i++));
  8253. bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
  8254. o1 = bits >> 16 & 0xff;
  8255. o2 = bits >> 8 & 0xff;
  8256. o3 = bits & 0xff;
  8257. if (h3 == 64) {
  8258. tmp_arr[ac++] = String.fromCharCode(o1);
  8259. } else if (h4 == 64) {
  8260. tmp_arr[ac++] = String.fromCharCode(o1, o2);
  8261. } else {
  8262. tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
  8263. }
  8264. } while (i < data.length);
  8265. dec = tmp_arr.join('');
  8266. return dec;
  8267. };
  8268. }
  8269. if (!Array.prototype.map) {
  8270. Array.prototype.map = function (fun /*, thisArg */) {
  8271. if (this === void 0 || this === null || typeof fun !== "function")
  8272. throw new TypeError();
  8273. var t = Object(this), len = t.length >>> 0, res = new Array(len);
  8274. var thisArg = arguments.length > 1 ? arguments[1] : void 0;
  8275. for (var i = 0; i < len; i++) {
  8276. // NOTE: Absolute correctness would demand Object.defineProperty
  8277. // be used. But this method is fairly new, and failure is
  8278. // possible only if Object.prototype or Array.prototype
  8279. // has a property |i| (very unlikely), so use a less-correct
  8280. // but more portable alternative.
  8281. if (i in t)
  8282. res[i] = fun.call(thisArg, t[i], i, t);
  8283. }
  8284. return res;
  8285. };
  8286. }
  8287. if (!Array.isArray) {
  8288. Array.isArray = function (arg) {
  8289. return Object.prototype.toString.call(arg) === '[object Array]';
  8290. };
  8291. }
  8292. if (!Array.prototype.forEach) {
  8293. Array.prototype.forEach = function (fun, thisArg) {
  8294. "use strict";
  8295. if (this === void 0 || this === null || typeof fun !== "function")
  8296. throw new TypeError();
  8297. var t = Object(this), len = t.length >>> 0;
  8298. for (var i = 0; i < len; i++) {
  8299. if (i in t)
  8300. fun.call(thisArg, t[i], i, t);
  8301. }
  8302. };
  8303. }
  8304. if (!Object.keys) {
  8305. Object.keys = (function () {
  8306. 'use strict';
  8307. var hasOwnProperty = Object.prototype.hasOwnProperty,
  8308. hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
  8309. dontEnums = ['toString', 'toLocaleString', 'valueOf', 'hasOwnProperty',
  8310. 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'],
  8311. dontEnumsLength = dontEnums.length;
  8312. return function (obj) {
  8313. if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
  8314. throw new TypeError();
  8315. }
  8316. var result = [], prop, i;
  8317. for (prop in obj) {
  8318. if (hasOwnProperty.call(obj, prop)) {
  8319. result.push(prop);
  8320. }
  8321. }
  8322. if (hasDontEnumBug) {
  8323. for (i = 0; i < dontEnumsLength; i++) {
  8324. if (hasOwnProperty.call(obj, dontEnums[i])) {
  8325. result.push(dontEnums[i]);
  8326. }
  8327. }
  8328. }
  8329. return result;
  8330. };
  8331. }());
  8332. }
  8333. if (!String.prototype.trim) {
  8334. String.prototype.trim = function () {
  8335. return this.replace(/^\s+|\s+$/g, '');
  8336. };
  8337. }
  8338. if (!String.prototype.trimLeft) {
  8339. String.prototype.trimLeft = function () {
  8340. return this.replace(/^\s+/g, "");
  8341. };
  8342. }
  8343. if (!String.prototype.trimRight) {
  8344. String.prototype.trimRight = function () {
  8345. return this.replace(/\s+$/g, "");
  8346. };
  8347. }
  8348. })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this);