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.
 
 
 
 
 
 

9359 lines
314 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. {
  2269. console.error('jsPDF.addImage: Invalid coordinates', arguments);
  2270. throw new Error('Invalid coordinates passed to jsPDF.addImage');
  2271. }
  2272. var images = getImages.call(this), info;
  2273. if (!(info = checkImagesForAlias(imageData, images))) {
  2274. var dataAsBinaryString;
  2275. if(isDOMElement(imageData))
  2276. imageData = createDataURIFromElement(imageData, format, rotation);
  2277. if(notDefined(alias))
  2278. alias = generateAliasFromData(imageData);
  2279. if (!(info = checkImagesForAlias(alias, images))) {
  2280. if(this.isString(imageData)) {
  2281. var base64Info = this.extractInfoFromBase64DataURI(imageData);
  2282. if(base64Info) {
  2283. format = base64Info[2];
  2284. imageData = atob(base64Info[3]);//convert to binary string
  2285. } else {
  2286. if (imageData.charCodeAt(0) === 0x89 &&
  2287. imageData.charCodeAt(1) === 0x50 &&
  2288. imageData.charCodeAt(2) === 0x4e &&
  2289. imageData.charCodeAt(3) === 0x47 ) format = 'png';
  2290. }
  2291. }
  2292. format = (format || 'JPEG').toLowerCase();
  2293. if(doesNotSupportImageType(format))
  2294. throw new Error('addImage currently only supports formats ' + supported_image_types + ', not \''+format+'\'');
  2295. if(processMethodNotEnabled(format))
  2296. throw new Error('please ensure that the plugin for \''+format+'\' support is added');
  2297. /**
  2298. * need to test if it's more efficent to convert all binary strings
  2299. * to TypedArray - or should we just leave and process as string?
  2300. */
  2301. if(this.supportsArrayBuffer()) {
  2302. dataAsBinaryString = imageData;
  2303. imageData = this.binaryStringToUint8Array(imageData);
  2304. }
  2305. info = this['process' + format.toUpperCase()](
  2306. imageData,
  2307. getImageIndex(images),
  2308. alias,
  2309. checkCompressValue(compression),
  2310. dataAsBinaryString
  2311. );
  2312. if(!info)
  2313. throw new Error('An unkwown error occurred whilst processing the image');
  2314. }
  2315. }
  2316. writeImageToPDF.call(this, x, y, w, h, info, info.i, images);
  2317. return this
  2318. };
  2319. /**
  2320. * JPEG SUPPORT
  2321. **/
  2322. //takes a string imgData containing the raw bytes of
  2323. //a jpeg image and returns [width, height]
  2324. //Algorithm from: http://www.64lines.com/jpeg-width-height
  2325. var getJpegSize = function(imgData) {
  2326. 'use strict'
  2327. var width, height, numcomponents;
  2328. // Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00
  2329. if (!imgData.charCodeAt(0) === 0xff ||
  2330. !imgData.charCodeAt(1) === 0xd8 ||
  2331. !imgData.charCodeAt(2) === 0xff ||
  2332. !imgData.charCodeAt(3) === 0xe0 ||
  2333. !imgData.charCodeAt(6) === 'J'.charCodeAt(0) ||
  2334. !imgData.charCodeAt(7) === 'F'.charCodeAt(0) ||
  2335. !imgData.charCodeAt(8) === 'I'.charCodeAt(0) ||
  2336. !imgData.charCodeAt(9) === 'F'.charCodeAt(0) ||
  2337. !imgData.charCodeAt(10) === 0x00) {
  2338. throw new Error('getJpegSize requires a binary string jpeg file')
  2339. }
  2340. var blockLength = imgData.charCodeAt(4)*256 + imgData.charCodeAt(5);
  2341. var i = 4, len = imgData.length;
  2342. while ( i < len ) {
  2343. i += blockLength;
  2344. if (imgData.charCodeAt(i) !== 0xff) {
  2345. throw new Error('getJpegSize could not find the size of the image');
  2346. }
  2347. if (imgData.charCodeAt(i+1) === 0xc0 || //(SOF) Huffman - Baseline DCT
  2348. imgData.charCodeAt(i+1) === 0xc1 || //(SOF) Huffman - Extended sequential DCT
  2349. imgData.charCodeAt(i+1) === 0xc2 || // Progressive DCT (SOF2)
  2350. imgData.charCodeAt(i+1) === 0xc3 || // Spatial (sequential) lossless (SOF3)
  2351. imgData.charCodeAt(i+1) === 0xc4 || // Differential sequential DCT (SOF5)
  2352. imgData.charCodeAt(i+1) === 0xc5 || // Differential progressive DCT (SOF6)
  2353. imgData.charCodeAt(i+1) === 0xc6 || // Differential spatial (SOF7)
  2354. imgData.charCodeAt(i+1) === 0xc7) {
  2355. height = imgData.charCodeAt(i+5)*256 + imgData.charCodeAt(i+6);
  2356. width = imgData.charCodeAt(i+7)*256 + imgData.charCodeAt(i+8);
  2357. numcomponents = imgData.charCodeAt(i+9);
  2358. return [width, height, numcomponents];
  2359. } else {
  2360. i += 2;
  2361. blockLength = imgData.charCodeAt(i)*256 + imgData.charCodeAt(i+1)
  2362. }
  2363. }
  2364. }
  2365. , getJpegSizeFromBytes = function(data) {
  2366. var hdr = (data[0] << 8) | data[1];
  2367. if(hdr !== 0xFFD8)
  2368. throw new Error('Supplied data is not a JPEG');
  2369. var len = data.length,
  2370. block = (data[4] << 8) + data[5],
  2371. pos = 4,
  2372. bytes, width, height, numcomponents;
  2373. while(pos < len) {
  2374. pos += block;
  2375. bytes = readBytes(data, pos);
  2376. block = (bytes[2] << 8) + bytes[3];
  2377. if((bytes[1] === 0xC0 || bytes[1] === 0xC2) && bytes[0] === 0xFF && block > 7) {
  2378. bytes = readBytes(data, pos + 5);
  2379. width = (bytes[2] << 8) + bytes[3];
  2380. height = (bytes[0] << 8) + bytes[1];
  2381. numcomponents = bytes[4];
  2382. return {width:width, height:height, numcomponents: numcomponents};
  2383. }
  2384. pos+=2;
  2385. }
  2386. throw new Error('getJpegSizeFromBytes could not find the size of the image');
  2387. }
  2388. , readBytes = function(data, offset) {
  2389. return data.subarray(offset, offset+ 5);
  2390. };
  2391. jsPDFAPI.processJPEG = function(data, index, alias, compression, dataAsBinaryString) {
  2392. 'use strict'
  2393. var colorSpace = this.color_spaces.DEVICE_RGB,
  2394. filter = this.decode.DCT_DECODE,
  2395. bpc = 8,
  2396. dims;
  2397. if(this.isString(data)) {
  2398. dims = getJpegSize(data);
  2399. return this.createImageInfo(data, dims[0], dims[1], dims[3] == 1 ? this.color_spaces.DEVICE_GRAY:colorSpace, bpc, filter, index, alias);
  2400. }
  2401. if(this.isArrayBuffer(data))
  2402. data = new Uint8Array(data);
  2403. if(this.isArrayBufferView(data)) {
  2404. dims = getJpegSizeFromBytes(data);
  2405. // if we already have a stored binary string rep use that
  2406. data = dataAsBinaryString || this.arrayBufferToBinaryString(data);
  2407. return this.createImageInfo(data, dims.width, dims.height, dims.numcomponents == 1 ? this.color_spaces.DEVICE_GRAY:colorSpace, bpc, filter, index, alias);
  2408. }
  2409. return null;
  2410. };
  2411. jsPDFAPI.processJPG = function(/*data, index, alias, compression, dataAsBinaryString*/) {
  2412. return this.processJPEG.apply(this, arguments);
  2413. }
  2414. })(jsPDF.API);
  2415. (function (jsPDFAPI) {
  2416. 'use strict';
  2417. jsPDFAPI.autoPrint = function () {
  2418. 'use strict'
  2419. var refAutoPrintTag;
  2420. this.internal.events.subscribe('postPutResources', function () {
  2421. refAutoPrintTag = this.internal.newObject()
  2422. this.internal.write("<< /S/Named /Type/Action /N/Print >>", "endobj");
  2423. });
  2424. this.internal.events.subscribe("putCatalog", function () {
  2425. this.internal.write("/OpenAction " + refAutoPrintTag + " 0" + " R");
  2426. });
  2427. return this;
  2428. };
  2429. })(jsPDF.API);
  2430. /** ====================================================================
  2431. * jsPDF Cell plugin
  2432. * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
  2433. * 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br
  2434. * 2013 Lee Driscoll, https://github.com/lsdriscoll
  2435. * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
  2436. * 2014 James Hall, james@parall.ax
  2437. * 2014 Diego Casorran, https://github.com/diegocr
  2438. *
  2439. * Permission is hereby granted, free of charge, to any person obtaining
  2440. * a copy of this software and associated documentation files (the
  2441. * "Software"), to deal in the Software without restriction, including
  2442. * without limitation the rights to use, copy, modify, merge, publish,
  2443. * distribute, sublicense, and/or sell copies of the Software, and to
  2444. * permit persons to whom the Software is furnished to do so, subject to
  2445. * the following conditions:
  2446. *
  2447. * The above copyright notice and this permission notice shall be
  2448. * included in all copies or substantial portions of the Software.
  2449. *
  2450. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  2451. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  2452. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  2453. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  2454. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  2455. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  2456. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  2457. * ====================================================================
  2458. */
  2459. (function (jsPDFAPI) {
  2460. 'use strict';
  2461. /*jslint browser:true */
  2462. /*global document: false, jsPDF */
  2463. var fontName,
  2464. fontSize,
  2465. fontStyle,
  2466. padding = 3,
  2467. margin = 13,
  2468. headerFunction,
  2469. lastCellPos = { x: undefined, y: undefined, w: undefined, h: undefined, ln: undefined },
  2470. pages = 1,
  2471. setLastCellPosition = function (x, y, w, h, ln) {
  2472. lastCellPos = { 'x': x, 'y': y, 'w': w, 'h': h, 'ln': ln };
  2473. },
  2474. getLastCellPosition = function () {
  2475. return lastCellPos;
  2476. },
  2477. NO_MARGINS = {left:0, top:0, bottom: 0};
  2478. jsPDFAPI.setHeaderFunction = function (func) {
  2479. headerFunction = func;
  2480. };
  2481. jsPDFAPI.getTextDimensions = function (txt) {
  2482. fontName = this.internal.getFont().fontName;
  2483. fontSize = this.table_font_size || this.internal.getFontSize();
  2484. fontStyle = this.internal.getFont().fontStyle;
  2485. // 1 pixel = 0.264583 mm and 1 mm = 72/25.4 point
  2486. var px2pt = 0.264583 * 72 / 25.4,
  2487. dimensions,
  2488. text;
  2489. text = document.createElement('font');
  2490. text.id = "jsPDFCell";
  2491. text.style.fontStyle = fontStyle;
  2492. text.style.fontName = fontName;
  2493. text.style.fontSize = fontSize + 'pt';
  2494. text.textContent = txt;
  2495. document.body.appendChild(text);
  2496. dimensions = { w: (text.offsetWidth + 1) * px2pt, h: (text.offsetHeight + 1) * px2pt};
  2497. document.body.removeChild(text);
  2498. return dimensions;
  2499. };
  2500. jsPDFAPI.cellAddPage = function () {
  2501. var margins = this.margins || NO_MARGINS;
  2502. this.addPage();
  2503. setLastCellPosition(margins.left, margins.top, undefined, undefined);
  2504. //setLastCellPosition(undefined, undefined, undefined, undefined, undefined);
  2505. pages += 1;
  2506. };
  2507. jsPDFAPI.cellInitialize = function () {
  2508. lastCellPos = { x: undefined, y: undefined, w: undefined, h: undefined, ln: undefined };
  2509. pages = 1;
  2510. };
  2511. jsPDFAPI.cell = function (x, y, w, h, txt, ln, align) {
  2512. var curCell = getLastCellPosition();
  2513. // If this is not the first cell, we must change its position
  2514. if (curCell.ln !== undefined) {
  2515. if (curCell.ln === ln) {
  2516. //Same line
  2517. x = curCell.x + curCell.w;
  2518. y = curCell.y;
  2519. } else {
  2520. //New line
  2521. var margins = this.margins || NO_MARGINS;
  2522. if ((curCell.y + curCell.h + h + margin) >= this.internal.pageSize.height - margins.bottom) {
  2523. this.cellAddPage();
  2524. if (this.printHeaders && this.tableHeaderRow) {
  2525. this.printHeaderRow(ln, true);
  2526. }
  2527. }
  2528. //We ignore the passed y: the lines may have diferent heights
  2529. y = (getLastCellPosition().y + getLastCellPosition().h);
  2530. }
  2531. }
  2532. if (txt[0] !== undefined) {
  2533. if (this.printingHeaderRow) {
  2534. this.rect(x, y, w, h, 'FD');
  2535. } else {
  2536. this.rect(x, y, w, h);
  2537. }
  2538. if (align === 'right') {
  2539. if (txt instanceof Array) {
  2540. for(var i = 0; i<txt.length; i++) {
  2541. var currentLine = txt[i];
  2542. var textSize = this.getStringUnitWidth(currentLine) * this.internal.getFontSize();
  2543. this.text(currentLine, x + w - textSize - padding, y + this.internal.getLineHeight()*(i+1));
  2544. }
  2545. }
  2546. } else {
  2547. this.text(txt, x + padding, y + this.internal.getLineHeight());
  2548. }
  2549. }
  2550. setLastCellPosition(x, y, w, h, ln);
  2551. return this;
  2552. };
  2553. /**
  2554. * Return the maximum value from an array
  2555. * @param array
  2556. * @param comparisonFn
  2557. * @returns {*}
  2558. */
  2559. jsPDFAPI.arrayMax = function (array, comparisonFn) {
  2560. var max = array[0],
  2561. i,
  2562. ln,
  2563. item;
  2564. for (i = 0, ln = array.length; i < ln; i += 1) {
  2565. item = array[i];
  2566. if (comparisonFn) {
  2567. if (comparisonFn(max, item) === -1) {
  2568. max = item;
  2569. }
  2570. } else {
  2571. if (item > max) {
  2572. max = item;
  2573. }
  2574. }
  2575. }
  2576. return max;
  2577. };
  2578. /**
  2579. * Create a table from a set of data.
  2580. * @param {Integer} [x] : left-position for top-left corner of table
  2581. * @param {Integer} [y] top-position for top-left corner of table
  2582. * @param {Object[]} [data] As array of objects containing key-value pairs corresponding to a row of data.
  2583. * @param {String[]} [headers] Omit or null to auto-generate headers at a performance cost
  2584. * @param {Object} [config.printHeaders] True to print column headers at the top of every page
  2585. * @param {Object} [config.autoSize] True to dynamically set the column widths to match the widest cell value
  2586. * @param {Object} [config.margins] margin values for left, top, bottom, and width
  2587. * @param {Object} [config.fontSize] Integer fontSize to use (optional)
  2588. */
  2589. jsPDFAPI.table = function (x,y, data, headers, config) {
  2590. if (!data) {
  2591. throw 'No data for PDF table';
  2592. }
  2593. var headerNames = [],
  2594. headerPrompts = [],
  2595. header,
  2596. i,
  2597. ln,
  2598. cln,
  2599. columnMatrix = {},
  2600. columnWidths = {},
  2601. columnData,
  2602. column,
  2603. columnMinWidths = [],
  2604. j,
  2605. tableHeaderConfigs = [],
  2606. model,
  2607. jln,
  2608. func,
  2609. //set up defaults. If a value is provided in config, defaults will be overwritten:
  2610. autoSize = false,
  2611. printHeaders = true,
  2612. fontSize = 12,
  2613. margins = NO_MARGINS;
  2614. margins.width = this.internal.pageSize.width;
  2615. if (config) {
  2616. //override config defaults if the user has specified non-default behavior:
  2617. if(config.autoSize === true) {
  2618. autoSize = true;
  2619. }
  2620. if(config.printHeaders === false) {
  2621. printHeaders = false;
  2622. }
  2623. if(config.fontSize){
  2624. fontSize = config.fontSize;
  2625. }
  2626. if(config.margins){
  2627. margins = config.margins;
  2628. }
  2629. }
  2630. /**
  2631. * @property {Number} lnMod
  2632. * Keep track of the current line number modifier used when creating cells
  2633. */
  2634. this.lnMod = 0;
  2635. lastCellPos = { x: undefined, y: undefined, w: undefined, h: undefined, ln: undefined },
  2636. pages = 1;
  2637. this.printHeaders = printHeaders;
  2638. this.margins = margins;
  2639. this.setFontSize(fontSize);
  2640. this.table_font_size = fontSize;
  2641. // Set header values
  2642. if (headers === undefined || (headers === null)) {
  2643. // No headers defined so we derive from data
  2644. headerNames = Object.keys(data[0]);
  2645. } else if (headers[0] && (typeof headers[0] !== 'string')) {
  2646. var px2pt = 0.264583 * 72 / 25.4;
  2647. // Split header configs into names and prompts
  2648. for (i = 0, ln = headers.length; i < ln; i += 1) {
  2649. header = headers[i];
  2650. headerNames.push(header.name);
  2651. headerPrompts.push(header.prompt);
  2652. columnWidths[header.name] = header.width *px2pt;
  2653. }
  2654. } else {
  2655. headerNames = headers;
  2656. }
  2657. if (autoSize) {
  2658. // Create a matrix of columns e.g., {column_title: [row1_Record, row2_Record]}
  2659. func = function (rec) {
  2660. return rec[header];
  2661. };
  2662. for (i = 0, ln = headerNames.length; i < ln; i += 1) {
  2663. header = headerNames[i];
  2664. columnMatrix[header] = data.map(
  2665. func
  2666. );
  2667. // get header width
  2668. columnMinWidths.push(this.getTextDimensions(headerPrompts[i] || header).w);
  2669. column = columnMatrix[header];
  2670. // get cell widths
  2671. for (j = 0, cln = column.length; j < cln; j += 1) {
  2672. columnData = column[j];
  2673. columnMinWidths.push(this.getTextDimensions(columnData).w);
  2674. }
  2675. // get final column width
  2676. columnWidths[header] = jsPDFAPI.arrayMax(columnMinWidths);
  2677. }
  2678. }
  2679. // -- Construct the table
  2680. if (printHeaders) {
  2681. var lineHeight = this.calculateLineHeight(headerNames, columnWidths, headerPrompts.length?headerPrompts:headerNames);
  2682. // Construct the header row
  2683. for (i = 0, ln = headerNames.length; i < ln; i += 1) {
  2684. header = headerNames[i];
  2685. tableHeaderConfigs.push([x, y, columnWidths[header], lineHeight, String(headerPrompts.length ? headerPrompts[i] : header)]);
  2686. }
  2687. // Store the table header config
  2688. this.setTableHeaderRow(tableHeaderConfigs);
  2689. // Print the header for the start of the table
  2690. this.printHeaderRow(1, false);
  2691. }
  2692. // Construct the data rows
  2693. for (i = 0, ln = data.length; i < ln; i += 1) {
  2694. var lineHeight;
  2695. model = data[i];
  2696. lineHeight = this.calculateLineHeight(headerNames, columnWidths, model);
  2697. for (j = 0, jln = headerNames.length; j < jln; j += 1) {
  2698. header = headerNames[j];
  2699. this.cell(x, y, columnWidths[header], lineHeight, model[header], i + 2, header.align);
  2700. }
  2701. }
  2702. this.lastCellPos = lastCellPos;
  2703. this.table_x = x;
  2704. this.table_y = y;
  2705. return this;
  2706. };
  2707. /**
  2708. * Calculate the height for containing the highest column
  2709. * @param {String[]} headerNames is the header, used as keys to the data
  2710. * @param {Integer[]} columnWidths is size of each column
  2711. * @param {Object[]} model is the line of data we want to calculate the height of
  2712. */
  2713. jsPDFAPI.calculateLineHeight = function (headerNames, columnWidths, model) {
  2714. var header, lineHeight = 0;
  2715. for (var j = 0; j < headerNames.length; j++) {
  2716. header = headerNames[j];
  2717. model[header] = this.splitTextToSize(String(model[header]), columnWidths[header] - padding);
  2718. var h = this.internal.getLineHeight() * model[header].length + padding;
  2719. if (h > lineHeight)
  2720. lineHeight = h;
  2721. }
  2722. return lineHeight;
  2723. };
  2724. /**
  2725. * Store the config for outputting a table header
  2726. * @param {Object[]} config
  2727. * An array of cell configs that would define a header row: Each config matches the config used by jsPDFAPI.cell
  2728. * except the ln parameter is excluded
  2729. */
  2730. jsPDFAPI.setTableHeaderRow = function (config) {
  2731. this.tableHeaderRow = config;
  2732. };
  2733. /**
  2734. * Output the store header row
  2735. * @param lineNumber The line number to output the header at
  2736. */
  2737. jsPDFAPI.printHeaderRow = function (lineNumber, new_page) {
  2738. if (!this.tableHeaderRow) {
  2739. throw 'Property tableHeaderRow does not exist.';
  2740. }
  2741. var tableHeaderCell,
  2742. tmpArray,
  2743. i,
  2744. ln;
  2745. this.printingHeaderRow = true;
  2746. if (headerFunction !== undefined) {
  2747. var position = headerFunction(this, pages);
  2748. setLastCellPosition(position[0], position[1], position[2], position[3], -1);
  2749. }
  2750. this.setFontStyle('bold');
  2751. var tempHeaderConf = [];
  2752. for (i = 0, ln = this.tableHeaderRow.length; i < ln; i += 1) {
  2753. this.setFillColor(200,200,200);
  2754. tableHeaderCell = this.tableHeaderRow[i];
  2755. if (new_page) {
  2756. tableHeaderCell[1] = this.margins && this.margins.top || 0;
  2757. tempHeaderConf.push(tableHeaderCell);
  2758. }
  2759. tmpArray = [].concat(tableHeaderCell);
  2760. this.cell.apply(this, tmpArray.concat(lineNumber));
  2761. }
  2762. if (tempHeaderConf.length > 0){
  2763. this.setTableHeaderRow(tempHeaderConf);
  2764. }
  2765. this.setFontStyle('normal');
  2766. this.printingHeaderRow = false;
  2767. };
  2768. })(jsPDF.API);
  2769. /** @preserve
  2770. * jsPDF fromHTML plugin. BETA stage. API subject to change. Needs browser
  2771. * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  2772. * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
  2773. * 2014 Diego Casorran, https://github.com/diegocr
  2774. * 2014 Daniel Husar, https://github.com/danielhusar
  2775. * 2014 Wolfgang Gassler, https://github.com/woolfg
  2776. *
  2777. * Permission is hereby granted, free of charge, to any person obtaining
  2778. * a copy of this software and associated documentation files (the
  2779. * "Software"), to deal in the Software without restriction, including
  2780. * without limitation the rights to use, copy, modify, merge, publish,
  2781. * distribute, sublicense, and/or sell copies of the Software, and to
  2782. * permit persons to whom the Software is furnished to do so, subject to
  2783. * the following conditions:
  2784. *
  2785. * The above copyright notice and this permission notice shall be
  2786. * included in all copies or substantial portions of the Software.
  2787. *
  2788. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  2789. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  2790. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  2791. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  2792. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  2793. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  2794. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  2795. * ====================================================================
  2796. */
  2797. (function (jsPDFAPI) {
  2798. var clone,
  2799. DrillForContent,
  2800. FontNameDB,
  2801. FontStyleMap,
  2802. FontWeightMap,
  2803. FloatMap,
  2804. ClearMap,
  2805. GetCSS,
  2806. PurgeWhiteSpace,
  2807. Renderer,
  2808. ResolveFont,
  2809. ResolveUnitedNumber,
  2810. UnitedNumberMap,
  2811. elementHandledElsewhere,
  2812. images,
  2813. loadImgs,
  2814. checkForFooter,
  2815. process,
  2816. tableToJson;
  2817. clone = (function () {
  2818. return function (obj) {
  2819. Clone.prototype = obj;
  2820. return new Clone()
  2821. };
  2822. function Clone() {}
  2823. })();
  2824. PurgeWhiteSpace = function (array) {
  2825. var fragment,
  2826. i,
  2827. l,
  2828. lTrimmed,
  2829. r,
  2830. rTrimmed,
  2831. trailingSpace;
  2832. i = 0;
  2833. l = array.length;
  2834. fragment = void 0;
  2835. lTrimmed = false;
  2836. rTrimmed = false;
  2837. while (!lTrimmed && i !== l) {
  2838. fragment = array[i] = array[i].trimLeft();
  2839. if (fragment) {
  2840. lTrimmed = true;
  2841. }
  2842. i++;
  2843. }
  2844. i = l - 1;
  2845. while (l && !rTrimmed && i !== -1) {
  2846. fragment = array[i] = array[i].trimRight();
  2847. if (fragment) {
  2848. rTrimmed = true;
  2849. }
  2850. i--;
  2851. }
  2852. r = /\s+$/g;
  2853. trailingSpace = true;
  2854. i = 0;
  2855. while (i !== l) {
  2856. fragment = array[i].replace(/\s+/g, " ");
  2857. if (trailingSpace) {
  2858. fragment = fragment.trimLeft();
  2859. }
  2860. if (fragment) {
  2861. trailingSpace = r.test(fragment);
  2862. }
  2863. array[i] = fragment;
  2864. i++;
  2865. }
  2866. return array;
  2867. };
  2868. Renderer = function (pdf, x, y, settings) {
  2869. this.pdf = pdf;
  2870. this.x = x;
  2871. this.y = y;
  2872. this.settings = settings;
  2873. //list of functions which are called after each element-rendering process
  2874. this.watchFunctions = [];
  2875. this.init();
  2876. return this;
  2877. };
  2878. ResolveFont = function (css_font_family_string) {
  2879. var name,
  2880. part,
  2881. parts;
  2882. name = void 0;
  2883. parts = css_font_family_string.split(",");
  2884. part = parts.shift();
  2885. while (!name && part) {
  2886. name = FontNameDB[part.trim().toLowerCase()];
  2887. part = parts.shift();
  2888. }
  2889. return name;
  2890. };
  2891. ResolveUnitedNumber = function (css_line_height_string) {
  2892. //IE8 issues
  2893. css_line_height_string = css_line_height_string === "auto" ? "0px" : css_line_height_string;
  2894. if (css_line_height_string.indexOf("em") > -1 && !isNaN(Number(css_line_height_string.replace("em", "")))) {
  2895. css_line_height_string = Number(css_line_height_string.replace("em", "")) * 18.719 + "px";
  2896. }
  2897. if (css_line_height_string.indexOf("pt") > -1 && !isNaN(Number(css_line_height_string.replace("pt", "")))) {
  2898. css_line_height_string = Number(css_line_height_string.replace("pt", "")) * 1.333 + "px";
  2899. }
  2900. var normal,
  2901. undef,
  2902. value;
  2903. undef = void 0;
  2904. normal = 16.00;
  2905. value = UnitedNumberMap[css_line_height_string];
  2906. if (value) {
  2907. return value;
  2908. }
  2909. value = {
  2910. "xx-small" : 9,
  2911. "x-small" : 11,
  2912. small : 13,
  2913. medium : 16,
  2914. large : 19,
  2915. "x-large" : 23,
  2916. "xx-large" : 28,
  2917. auto : 0
  2918. }[{ css_line_height_string : css_line_height_string }];
  2919. if (value !== undef) {
  2920. return UnitedNumberMap[css_line_height_string] = value / normal;
  2921. }
  2922. if (value = parseFloat(css_line_height_string)) {
  2923. return UnitedNumberMap[css_line_height_string] = value / normal;
  2924. }
  2925. value = css_line_height_string.match(/([\d\.]+)(px)/);
  2926. if (value.length === 3) {
  2927. return UnitedNumberMap[css_line_height_string] = parseFloat(value[1]) / normal;
  2928. }
  2929. return UnitedNumberMap[css_line_height_string] = 1;
  2930. };
  2931. GetCSS = function (element) {
  2932. var css,tmp,computedCSSElement;
  2933. computedCSSElement = (function (el) {
  2934. var compCSS;
  2935. compCSS = (function (el) {
  2936. if (document.defaultView && document.defaultView.getComputedStyle) {
  2937. return document.defaultView.getComputedStyle(el, null);
  2938. } else if (el.currentStyle) {
  2939. return el.currentStyle;
  2940. } else {
  2941. return el.style;
  2942. }
  2943. })(el);
  2944. return function (prop) {
  2945. prop = prop.replace(/-\D/g, function (match) {
  2946. return match.charAt(1).toUpperCase();
  2947. });
  2948. return compCSS[prop];
  2949. };
  2950. })(element);
  2951. css = {};
  2952. tmp = void 0;
  2953. css["font-family"] = ResolveFont(computedCSSElement("font-family")) || "times";
  2954. css["font-style"] = FontStyleMap[computedCSSElement("font-style")] || "normal";
  2955. css["text-align"] = TextAlignMap[computedCSSElement("text-align")] || "left";
  2956. tmp = FontWeightMap[computedCSSElement("font-weight")] || "normal";
  2957. if (tmp === "bold") {
  2958. if (css["font-style"] === "normal") {
  2959. css["font-style"] = tmp;
  2960. } else {
  2961. css["font-style"] = tmp + css["font-style"];
  2962. }
  2963. }
  2964. css["font-size"] = ResolveUnitedNumber(computedCSSElement("font-size")) || 1;
  2965. css["line-height"] = ResolveUnitedNumber(computedCSSElement("line-height")) || 1;
  2966. css["display"] = (computedCSSElement("display") === "inline" ? "inline" : "block");
  2967. tmp = (css["display"] === "block");
  2968. css["margin-top"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-top")) || 0;
  2969. css["margin-bottom"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-bottom")) || 0;
  2970. css["padding-top"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-top")) || 0;
  2971. css["padding-bottom"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-bottom")) || 0;
  2972. css["margin-left"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-left")) || 0;
  2973. css["margin-right"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-right")) || 0;
  2974. css["padding-left"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-left")) || 0;
  2975. css["padding-right"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-right")) || 0;
  2976. //float and clearing of floats
  2977. css["float"] = FloatMap[computedCSSElement("cssFloat")] || "none";
  2978. css["clear"] = ClearMap[computedCSSElement("clear")] || "none";
  2979. return css;
  2980. };
  2981. elementHandledElsewhere = function (element, renderer, elementHandlers) {
  2982. var handlers,
  2983. i,
  2984. isHandledElsewhere,
  2985. l,
  2986. t;
  2987. isHandledElsewhere = false;
  2988. i = void 0;
  2989. l = void 0;
  2990. t = void 0;
  2991. handlers = elementHandlers["#" + element.id];
  2992. if (handlers) {
  2993. if (typeof handlers === "function") {
  2994. isHandledElsewhere = handlers(element, renderer);
  2995. } else {
  2996. i = 0;
  2997. l = handlers.length;
  2998. while (!isHandledElsewhere && i !== l) {
  2999. isHandledElsewhere = handlers[i](element, renderer);
  3000. i++;
  3001. }
  3002. }
  3003. }
  3004. handlers = elementHandlers[element.nodeName];
  3005. if (!isHandledElsewhere && handlers) {
  3006. if (typeof handlers === "function") {
  3007. isHandledElsewhere = handlers(element, renderer);
  3008. } else {
  3009. i = 0;
  3010. l = handlers.length;
  3011. while (!isHandledElsewhere && i !== l) {
  3012. isHandledElsewhere = handlers[i](element, renderer);
  3013. i++;
  3014. }
  3015. }
  3016. }
  3017. return isHandledElsewhere;
  3018. };
  3019. tableToJson = function (table, renderer) {
  3020. var data,
  3021. headers,
  3022. i,
  3023. j,
  3024. rowData,
  3025. tableRow,
  3026. table_obj,
  3027. table_with,
  3028. cell,
  3029. l;
  3030. data = [];
  3031. headers = [];
  3032. i = 0;
  3033. l = table.rows[0].cells.length;
  3034. table_with = table.clientWidth;
  3035. while (i < l) {
  3036. cell = table.rows[0].cells[i];
  3037. headers[i] = {
  3038. name : cell.textContent.toLowerCase().replace(/\s+/g, ''),
  3039. prompt : cell.textContent.replace(/\r?\n/g, ''),
  3040. width : (cell.clientWidth / table_with) * renderer.pdf.internal.pageSize.width
  3041. };
  3042. i++;
  3043. }
  3044. i = 1;
  3045. while (i < table.rows.length) {
  3046. tableRow = table.rows[i];
  3047. rowData = {};
  3048. j = 0;
  3049. while (j < tableRow.cells.length) {
  3050. rowData[headers[j].name] = tableRow.cells[j].textContent.replace(/\r?\n/g, '');
  3051. j++;
  3052. }
  3053. data.push(rowData);
  3054. i++;
  3055. }
  3056. return table_obj = {
  3057. rows : data,
  3058. headers : headers
  3059. };
  3060. };
  3061. var SkipNode = {
  3062. SCRIPT : 1,
  3063. STYLE : 1,
  3064. NOSCRIPT : 1,
  3065. OBJECT : 1,
  3066. EMBED : 1,
  3067. SELECT : 1
  3068. };
  3069. var listCount = 1;
  3070. DrillForContent = function (element, renderer, elementHandlers) {
  3071. var cn,
  3072. cns,
  3073. fragmentCSS,
  3074. i,
  3075. isBlock,
  3076. l,
  3077. px2pt,
  3078. table2json,
  3079. cb;
  3080. cns = element.childNodes;
  3081. cn = void 0;
  3082. fragmentCSS = GetCSS(element);
  3083. isBlock = fragmentCSS.display === "block";
  3084. if (isBlock) {
  3085. renderer.setBlockBoundary();
  3086. renderer.setBlockStyle(fragmentCSS);
  3087. }
  3088. px2pt = 0.264583 * 72 / 25.4;
  3089. i = 0;
  3090. l = cns.length;
  3091. while (i < l) {
  3092. cn = cns[i];
  3093. if (typeof cn === "object") {
  3094. //execute all watcher functions to e.g. reset floating
  3095. renderer.executeWatchFunctions(cn);
  3096. /*** HEADER rendering **/
  3097. if (cn.nodeType === 1 && cn.nodeName === 'HEADER') {
  3098. var header = cn;
  3099. //store old top margin
  3100. var oldMarginTop = renderer.pdf.margins_doc.top;
  3101. //subscribe for new page event and render header first on every page
  3102. renderer.pdf.internal.events.subscribe('addPage', function (pageInfo) {
  3103. //set current y position to old margin
  3104. renderer.y = oldMarginTop;
  3105. //render all child nodes of the header element
  3106. DrillForContent(header, renderer, elementHandlers);
  3107. //set margin to old margin + rendered header + 10 space to prevent overlapping
  3108. //important for other plugins (e.g. table) to start rendering at correct position after header
  3109. renderer.pdf.margins_doc.top = renderer.y + 10;
  3110. renderer.y += 10;
  3111. }, false);
  3112. }
  3113. if (cn.nodeType === 8 && cn.nodeName === "#comment") {
  3114. if (~cn.textContent.indexOf("ADD_PAGE")) {
  3115. renderer.pdf.addPage();
  3116. renderer.y = renderer.pdf.margins_doc.top;
  3117. }
  3118. } else if (cn.nodeType === 1 && !SkipNode[cn.nodeName]) {
  3119. /*** IMAGE RENDERING ***/
  3120. var cached_image;
  3121. if (cn.nodeName === "IMG") {
  3122. var url = cn.getAttribute("src");
  3123. cached_image = images[renderer.pdf.sHashCode(url) || url];
  3124. }
  3125. if (cached_image) {
  3126. if ((renderer.pdf.internal.pageSize.height - renderer.pdf.margins_doc.bottom < renderer.y + cn.height) && (renderer.y > renderer.pdf.margins_doc.top)) {
  3127. renderer.pdf.addPage();
  3128. renderer.y = renderer.pdf.margins_doc.top;
  3129. //check if we have to set back some values due to e.g. header rendering for new page
  3130. renderer.executeWatchFunctions(cn);
  3131. }
  3132. var imagesCSS = GetCSS(cn);
  3133. var imageX = renderer.x;
  3134. var fontToUnitRatio = 12 / renderer.pdf.internal.scaleFactor;
  3135. //define additional paddings, margins which have to be taken into account for margin calculations
  3136. var additionalSpaceLeft = (imagesCSS["margin-left"] + imagesCSS["padding-left"])*fontToUnitRatio;
  3137. var additionalSpaceRight = (imagesCSS["margin-right"] + imagesCSS["padding-right"])*fontToUnitRatio;
  3138. var additionalSpaceTop = (imagesCSS["margin-top"] + imagesCSS["padding-top"])*fontToUnitRatio;
  3139. var additionalSpaceBottom = (imagesCSS["margin-bottom"] + imagesCSS["padding-bottom"])*fontToUnitRatio;
  3140. //if float is set to right, move the image to the right border
  3141. //add space if margin is set
  3142. if (imagesCSS['float'] !== undefined && imagesCSS['float'] === 'right') {
  3143. imageX += renderer.settings.width - cn.width - additionalSpaceRight;
  3144. } else {
  3145. imageX += additionalSpaceLeft;
  3146. }
  3147. renderer.pdf.addImage(cached_image, imageX, renderer.y + additionalSpaceTop, cn.width, cn.height);
  3148. cached_image = undefined;
  3149. //if the float prop is specified we have to float the text around the image
  3150. if (imagesCSS['float'] === 'right' || imagesCSS['float'] === 'left') {
  3151. //add functiont to set back coordinates after image rendering
  3152. renderer.watchFunctions.push((function(diffX , thresholdY, diffWidth, el) {
  3153. //undo drawing box adaptions which were set by floating
  3154. if (renderer.y >= thresholdY) {
  3155. renderer.x += diffX;
  3156. renderer.settings.width += diffWidth;
  3157. return true;
  3158. } else if(el && el.nodeType === 1 && !SkipNode[el.nodeName] && renderer.x+el.width > (renderer.pdf.margins_doc.left + renderer.pdf.margins_doc.width)) {
  3159. renderer.x += diffX;
  3160. renderer.y = thresholdY;
  3161. renderer.settings.width += diffWidth;
  3162. return true;
  3163. } else {
  3164. return false;
  3165. }
  3166. }).bind(this, (imagesCSS['float'] === 'left') ? -cn.width-additionalSpaceLeft-additionalSpaceRight : 0, renderer.y+cn.height+additionalSpaceTop+additionalSpaceBottom, cn.width));
  3167. //reset floating by clear:both divs
  3168. //just set cursorY after the floating element
  3169. renderer.watchFunctions.push((function(yPositionAfterFloating, pages, el) {
  3170. if (renderer.y < yPositionAfterFloating && pages === renderer.pdf.internal.getNumberOfPages()) {
  3171. if (el.nodeType === 1 && GetCSS(el).clear === 'both') {
  3172. renderer.y = yPositionAfterFloating;
  3173. return true;
  3174. } else {
  3175. return false;
  3176. }
  3177. } else {
  3178. return true;
  3179. }
  3180. }).bind(this, renderer.y+cn.height, renderer.pdf.internal.getNumberOfPages()));
  3181. //if floating is set we decrease the available width by the image width
  3182. renderer.settings.width -= cn.width+additionalSpaceLeft+additionalSpaceRight;
  3183. //if left just add the image width to the X coordinate
  3184. if (imagesCSS['float'] === 'left') {
  3185. renderer.x += cn.width+additionalSpaceLeft+additionalSpaceRight;
  3186. }
  3187. } else {
  3188. //if no floating is set, move the rendering cursor after the image height
  3189. renderer.y += cn.height + additionalSpaceBottom;
  3190. }
  3191. /*** TABLE RENDERING ***/
  3192. } else if (cn.nodeName === "TABLE") {
  3193. table2json = tableToJson(cn, renderer);
  3194. renderer.y += 10;
  3195. renderer.pdf.table(renderer.x, renderer.y, table2json.rows, table2json.headers, {
  3196. autoSize : false,
  3197. printHeaders : true,
  3198. margins : renderer.pdf.margins_doc
  3199. });
  3200. renderer.y = renderer.pdf.lastCellPos.y + renderer.pdf.lastCellPos.h + 20;
  3201. } else if (cn.nodeName === "OL" || cn.nodeName === "UL") {
  3202. listCount = 1;
  3203. if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
  3204. DrillForContent(cn, renderer, elementHandlers);
  3205. }
  3206. renderer.y += 10;
  3207. } else if (cn.nodeName === "LI") {
  3208. var temp = renderer.x;
  3209. renderer.x += cn.parentNode.nodeName === "UL" ? 22 : 10;
  3210. renderer.y += 3;
  3211. if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
  3212. DrillForContent(cn, renderer, elementHandlers);
  3213. }
  3214. renderer.x = temp;
  3215. } else if (cn.nodeName === "BR") {
  3216. renderer.y += fragmentCSS["font-size"] * renderer.pdf.internal.scaleFactor;
  3217. } else {
  3218. if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
  3219. DrillForContent(cn, renderer, elementHandlers);
  3220. }
  3221. }
  3222. } else if (cn.nodeType === 3) {
  3223. var value = cn.nodeValue;
  3224. if (cn.nodeValue && cn.parentNode.nodeName === "LI") {
  3225. if (cn.parentNode.parentNode.nodeName === "OL") {
  3226. value = listCount++ + '. ' + value;
  3227. } else {
  3228. var fontPx = fragmentCSS["font-size"] * 16;
  3229. var radius = 2;
  3230. if (fontPx > 20) {
  3231. radius = 3;
  3232. }
  3233. cb = function (x, y) {
  3234. this.pdf.circle(x, y, radius, 'FD');
  3235. };
  3236. }
  3237. }
  3238. renderer.addText(value, fragmentCSS);
  3239. } else if (typeof cn === "string") {
  3240. renderer.addText(cn, fragmentCSS);
  3241. }
  3242. }
  3243. i++;
  3244. }
  3245. if (isBlock) {
  3246. return renderer.setBlockBoundary(cb);
  3247. }
  3248. };
  3249. images = {};
  3250. loadImgs = function (element, renderer, elementHandlers, cb) {
  3251. var imgs = element.getElementsByTagName('img'),
  3252. l = imgs.length, found_images,
  3253. x = 0;
  3254. function done() {
  3255. renderer.pdf.internal.events.publish('imagesLoaded');
  3256. cb(found_images);
  3257. }
  3258. function loadImage(url, width, height) {
  3259. if (!url)
  3260. return;
  3261. var img = new Image();
  3262. found_images = ++x;
  3263. img.crossOrigin = '';
  3264. img.onerror = img.onload = function () {
  3265. if(img.complete) {
  3266. //to support data urls in images, set width and height
  3267. //as those values are not recognized automatically
  3268. if (img.src.indexOf('data:image/') === 0) {
  3269. img.width = width || img.width || 0;
  3270. img.height = height || img.height || 0;
  3271. }
  3272. //if valid image add to known images array
  3273. if (img.width + img.height) {
  3274. var hash = renderer.pdf.sHashCode(url) || url;
  3275. images[hash] = images[hash] || img;
  3276. }
  3277. }
  3278. if(!--x) {
  3279. done();
  3280. }
  3281. };
  3282. img.src = url;
  3283. }
  3284. while (l--)
  3285. loadImage(imgs[l].getAttribute("src"),imgs[l].width,imgs[l].height);
  3286. return x || done();
  3287. };
  3288. checkForFooter = function (elem, renderer, elementHandlers) {
  3289. //check if we can found a <footer> element
  3290. var footer = elem.getElementsByTagName("footer");
  3291. if (footer.length > 0) {
  3292. footer = footer[0];
  3293. //bad hack to get height of footer
  3294. //creat dummy out and check new y after fake rendering
  3295. var oldOut = renderer.pdf.internal.write;
  3296. var oldY = renderer.y;
  3297. renderer.pdf.internal.write = function () {};
  3298. DrillForContent(footer, renderer, elementHandlers);
  3299. var footerHeight = Math.ceil(renderer.y - oldY) + 5;
  3300. renderer.y = oldY;
  3301. renderer.pdf.internal.write = oldOut;
  3302. //add 20% to prevent overlapping
  3303. renderer.pdf.margins_doc.bottom += footerHeight;
  3304. //Create function render header on every page
  3305. var renderFooter = function (pageInfo) {
  3306. var pageNumber = pageInfo !== undefined ? pageInfo.pageNumber : 1;
  3307. //set current y position to old margin
  3308. var oldPosition = renderer.y;
  3309. //render all child nodes of the header element
  3310. renderer.y = renderer.pdf.internal.pageSize.height - renderer.pdf.margins_doc.bottom;
  3311. renderer.pdf.margins_doc.bottom -= footerHeight;
  3312. //check if we have to add page numbers
  3313. var spans = footer.getElementsByTagName('span');
  3314. for (var i = 0; i < spans.length; ++i) {
  3315. //if we find some span element with class pageCounter, set the page
  3316. if ((" " + spans[i].className + " ").replace(/[\n\t]/g, " ").indexOf(" pageCounter ") > -1) {
  3317. spans[i].innerHTML = pageNumber;
  3318. }
  3319. //if we find some span element with class totalPages, set a variable which is replaced after rendering of all pages
  3320. if ((" " + spans[i].className + " ").replace(/[\n\t]/g, " ").indexOf(" totalPages ") > -1) {
  3321. spans[i].innerHTML = '###jsPDFVarTotalPages###';
  3322. }
  3323. }
  3324. //render footer content
  3325. DrillForContent(footer, renderer, elementHandlers);
  3326. //set bottom margin to previous height including the footer height
  3327. renderer.pdf.margins_doc.bottom += footerHeight;
  3328. //important for other plugins (e.g. table) to start rendering at correct position after header
  3329. renderer.y = oldPosition;
  3330. };
  3331. //check if footer contains totalPages which shoudl be replace at the disoposal of the document
  3332. var spans = footer.getElementsByTagName('span');
  3333. for (var i = 0; i < spans.length; ++i) {
  3334. if ((" " + spans[i].className + " ").replace(/[\n\t]/g, " ").indexOf(" totalPages ") > -1) {
  3335. renderer.pdf.internal.events.subscribe('htmlRenderingFinished', renderer.pdf.putTotalPages.bind(renderer.pdf, '###jsPDFVarTotalPages###'), true);
  3336. }
  3337. }
  3338. //register event to render footer on every new page
  3339. renderer.pdf.internal.events.subscribe('addPage', renderFooter, false);
  3340. //render footer on first page
  3341. renderFooter();
  3342. //prevent footer rendering
  3343. SkipNode['FOOTER'] = 1;
  3344. }
  3345. };
  3346. process = function (pdf, element, x, y, settings, callback) {
  3347. if (!element)
  3348. return false;
  3349. if (typeof element !== "string" && !element.parentNode)
  3350. element = '' + element.innerHTML;
  3351. if (typeof element === "string") {
  3352. element = (function (element) {
  3353. var $frame,
  3354. $hiddendiv,
  3355. framename,
  3356. visuallyhidden;
  3357. framename = "jsPDFhtmlText" + Date.now().toString() + (Math.random() * 1000).toFixed(0);
  3358. 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;";
  3359. $hiddendiv = document.createElement('div');
  3360. $hiddendiv.style.cssText = visuallyhidden;
  3361. $hiddendiv.innerHTML = "<iframe style=\"height:1px;width:1px\" name=\"" + framename + "\" />";
  3362. document.body.appendChild($hiddendiv);
  3363. $frame = window.frames[framename];
  3364. $frame.document.body.innerHTML = element;
  3365. return $frame.document.body;
  3366. })(element.replace(/<\/?script[^>]*?>/gi, ''));
  3367. }
  3368. var r = new Renderer(pdf, x, y, settings), out;
  3369. // 1. load images
  3370. // 2. prepare optional footer elements
  3371. // 3. render content
  3372. loadImgs.call(this, element, r, settings.elementHandlers, function (found_images) {
  3373. checkForFooter( element, r, settings.elementHandlers);
  3374. DrillForContent(element, r, settings.elementHandlers);
  3375. //send event dispose for final taks (e.g. footer totalpage replacement)
  3376. r.pdf.internal.events.publish('htmlRenderingFinished');
  3377. out = r.dispose();
  3378. if (typeof callback === 'function') callback(out);
  3379. else if (found_images) console.error('jsPDF Warning: rendering issues? provide a callback to fromHTML!');
  3380. });
  3381. return out || {x: r.x, y:r.y};
  3382. };
  3383. Renderer.prototype.init = function () {
  3384. this.paragraph = {
  3385. text : [],
  3386. style : []
  3387. };
  3388. return this.pdf.internal.write("q");
  3389. };
  3390. Renderer.prototype.dispose = function () {
  3391. this.pdf.internal.write("Q");
  3392. return {
  3393. x : this.x,
  3394. y : this.y,
  3395. ready:true
  3396. };
  3397. };
  3398. //Checks if we have to execute some watcher functions
  3399. //e.g. to end text floating around an image
  3400. Renderer.prototype.executeWatchFunctions = function(el) {
  3401. var ret = false;
  3402. var narray = [];
  3403. if (this.watchFunctions.length > 0) {
  3404. for(var i=0; i< this.watchFunctions.length; ++i) {
  3405. if (this.watchFunctions[i](el) === true) {
  3406. ret = true;
  3407. } else {
  3408. narray.push(this.watchFunctions[i]);
  3409. }
  3410. }
  3411. this.watchFunctions = narray;
  3412. }
  3413. return ret;
  3414. };
  3415. Renderer.prototype.splitFragmentsIntoLines = function (fragments, styles) {
  3416. var currentLineLength,
  3417. defaultFontSize,
  3418. ff,
  3419. fontMetrics,
  3420. fontMetricsCache,
  3421. fragment,
  3422. fragmentChopped,
  3423. fragmentLength,
  3424. fragmentSpecificMetrics,
  3425. fs,
  3426. k,
  3427. line,
  3428. lines,
  3429. maxLineLength,
  3430. style;
  3431. defaultFontSize = 12;
  3432. k = this.pdf.internal.scaleFactor;
  3433. fontMetricsCache = {};
  3434. ff = void 0;
  3435. fs = void 0;
  3436. fontMetrics = void 0;
  3437. fragment = void 0;
  3438. style = void 0;
  3439. fragmentSpecificMetrics = void 0;
  3440. fragmentLength = void 0;
  3441. fragmentChopped = void 0;
  3442. line = [];
  3443. lines = [line];
  3444. currentLineLength = 0;
  3445. maxLineLength = this.settings.width;
  3446. while (fragments.length) {
  3447. fragment = fragments.shift();
  3448. style = styles.shift();
  3449. if (fragment) {
  3450. ff = style["font-family"];
  3451. fs = style["font-style"];
  3452. fontMetrics = fontMetricsCache[ff + fs];
  3453. if (!fontMetrics) {
  3454. fontMetrics = this.pdf.internal.getFont(ff, fs).metadata.Unicode;
  3455. fontMetricsCache[ff + fs] = fontMetrics;
  3456. }
  3457. fragmentSpecificMetrics = {
  3458. widths : fontMetrics.widths,
  3459. kerning : fontMetrics.kerning,
  3460. fontSize : style["font-size"] * defaultFontSize,
  3461. textIndent : currentLineLength
  3462. };
  3463. fragmentLength = this.pdf.getStringUnitWidth(fragment, fragmentSpecificMetrics) * fragmentSpecificMetrics.fontSize / k;
  3464. if (currentLineLength + fragmentLength > maxLineLength) {
  3465. fragmentChopped = this.pdf.splitTextToSize(fragment, maxLineLength, fragmentSpecificMetrics);
  3466. line.push([fragmentChopped.shift(), style]);
  3467. while (fragmentChopped.length) {
  3468. line = [[fragmentChopped.shift(), style]];
  3469. lines.push(line);
  3470. }
  3471. currentLineLength = this.pdf.getStringUnitWidth(line[0][0], fragmentSpecificMetrics) * fragmentSpecificMetrics.fontSize / k;
  3472. } else {
  3473. line.push([fragment, style]);
  3474. currentLineLength += fragmentLength;
  3475. }
  3476. }
  3477. }
  3478. //if text alignment was set, set margin/indent of each line
  3479. if (style['text-align'] !== undefined && (style['text-align'] === 'center' || style['text-align'] === 'right' || style['text-align'] === 'justify')) {
  3480. for (var i = 0; i < lines.length; ++i) {
  3481. var length = this.pdf.getStringUnitWidth(lines[i][0][0], fragmentSpecificMetrics) * fragmentSpecificMetrics.fontSize / k;
  3482. //if there is more than on line we have to clone the style object as all lines hold a reference on this object
  3483. if (i > 0) {
  3484. lines[i][0][1] = clone(lines[i][0][1]);
  3485. }
  3486. var space = (maxLineLength - length);
  3487. if (style['text-align'] === 'right') {
  3488. lines[i][0][1]['margin-left'] = space;
  3489. //if alignment is not right, it has to be center so split the space to the left and the right
  3490. } else if (style['text-align'] === 'center') {
  3491. lines[i][0][1]['margin-left'] = space / 2;
  3492. //if justify was set, calculate the word spacing and define in by using the css property
  3493. } else if (style['text-align'] === 'justify') {
  3494. var countSpaces = lines[i][0][0].split(' ').length - 1;
  3495. lines[i][0][1]['word-spacing'] = space / countSpaces;
  3496. //ignore the last line in justify mode
  3497. if (i === (lines.length - 1)) {
  3498. lines[i][0][1]['word-spacing'] = 0;
  3499. }
  3500. }
  3501. }
  3502. }
  3503. return lines;
  3504. };
  3505. Renderer.prototype.RenderTextFragment = function (text, style) {
  3506. var defaultFontSize,
  3507. font,
  3508. maxLineHeight;
  3509. maxLineHeight = 0;
  3510. defaultFontSize = 12;
  3511. if (this.pdf.internal.pageSize.height - this.pdf.margins_doc.bottom < this.y + this.pdf.internal.getFontSize()) {
  3512. this.pdf.internal.write("ET", "Q");
  3513. this.pdf.addPage();
  3514. this.y = this.pdf.margins_doc.top;
  3515. this.pdf.internal.write("q", "BT 0 g", this.pdf.internal.getCoordinateString(this.x), this.pdf.internal.getVerticalCoordinateString(this.y), "Td");
  3516. //move cursor by one line on new page
  3517. maxLineHeight = Math.max(maxLineHeight, style["line-height"], style["font-size"]);
  3518. this.pdf.internal.write(0, (-1 * defaultFontSize * maxLineHeight).toFixed(2), "Td");
  3519. }
  3520. font = this.pdf.internal.getFont(style["font-family"], style["font-style"]);
  3521. //set the word spacing for e.g. justify style
  3522. if (style['word-spacing'] !== undefined && style['word-spacing'] > 0) {
  3523. this.pdf.internal.write(style['word-spacing'].toFixed(2), "Tw");
  3524. }
  3525. this.pdf.internal.write("/" + font.id, (defaultFontSize * style["font-size"]).toFixed(2), "Tf", "(" + this.pdf.internal.pdfEscape(text) + ") Tj");
  3526. //set the word spacing back to neutral => 0
  3527. if (style['word-spacing'] !== undefined) {
  3528. this.pdf.internal.write(0, "Tw");
  3529. }
  3530. };
  3531. Renderer.prototype.renderParagraph = function (cb) {
  3532. var blockstyle,
  3533. defaultFontSize,
  3534. fontToUnitRatio,
  3535. fragments,
  3536. i,
  3537. l,
  3538. line,
  3539. lines,
  3540. maxLineHeight,
  3541. out,
  3542. paragraphspacing_after,
  3543. paragraphspacing_before,
  3544. priorblockstype,
  3545. styles,
  3546. fontSize;
  3547. fragments = PurgeWhiteSpace(this.paragraph.text);
  3548. styles = this.paragraph.style;
  3549. blockstyle = this.paragraph.blockstyle;
  3550. priorblockstype = this.paragraph.blockstyle || {};
  3551. this.paragraph = {
  3552. text : [],
  3553. style : [],
  3554. blockstyle : {},
  3555. priorblockstyle : blockstyle
  3556. };
  3557. if (!fragments.join("").trim()) {
  3558. return;
  3559. }
  3560. lines = this.splitFragmentsIntoLines(fragments, styles);
  3561. line = void 0;
  3562. maxLineHeight = void 0;
  3563. defaultFontSize = 12;
  3564. fontToUnitRatio = defaultFontSize / this.pdf.internal.scaleFactor;
  3565. paragraphspacing_before = (Math.max((blockstyle["margin-top"] || 0) - (priorblockstype["margin-bottom"] || 0), 0) + (blockstyle["padding-top"] || 0)) * fontToUnitRatio;
  3566. paragraphspacing_after = ((blockstyle["margin-bottom"] || 0) + (blockstyle["padding-bottom"] || 0)) * fontToUnitRatio;
  3567. out = this.pdf.internal.write;
  3568. i = void 0;
  3569. l = void 0;
  3570. this.y += paragraphspacing_before;
  3571. out("q", "BT 0 g", this.pdf.internal.getCoordinateString(this.x), this.pdf.internal.getVerticalCoordinateString(this.y), "Td");
  3572. //stores the current indent of cursor position
  3573. var currentIndent = 0;
  3574. while (lines.length) {
  3575. line = lines.shift();
  3576. maxLineHeight = 0;
  3577. i = 0;
  3578. l = line.length;
  3579. while (i !== l) {
  3580. if (line[i][0].trim()) {
  3581. maxLineHeight = Math.max(maxLineHeight, line[i][1]["line-height"], line[i][1]["font-size"]);
  3582. fontSize = line[i][1]["font-size"] * 7;
  3583. }
  3584. i++;
  3585. }
  3586. //if we have to move the cursor to adapt the indent
  3587. var indentMove = 0;
  3588. //if a margin was added (by e.g. a text-alignment), move the cursor
  3589. if (line[0][1]["margin-left"] !== undefined && line[0][1]["margin-left"] > 0) {
  3590. wantedIndent = this.pdf.internal.getCoordinateString(line[0][1]["margin-left"]);
  3591. indentMove = wantedIndent - currentIndent;
  3592. currentIndent = wantedIndent;
  3593. }
  3594. //move the cursor
  3595. out(indentMove, (-1 * defaultFontSize * maxLineHeight).toFixed(2), "Td");
  3596. i = 0;
  3597. l = line.length;
  3598. while (i !== l) {
  3599. if (line[i][0]) {
  3600. this.RenderTextFragment(line[i][0], line[i][1]);
  3601. }
  3602. i++;
  3603. }
  3604. this.y += maxLineHeight * fontToUnitRatio;
  3605. //if some watcher function was executed sucessful, so e.g. margin and widths were changed,
  3606. //reset line drawing and calculate position and lines again
  3607. //e.g. to stop text floating around an image
  3608. if (this.executeWatchFunctions(line[0][1]) && lines.length > 0) {
  3609. var localFragments = [];
  3610. var localStyles = [];
  3611. //create fragement array of
  3612. lines.forEach(function(localLine) {
  3613. var i = 0;
  3614. var l = localLine.length;
  3615. while (i !== l) {
  3616. if (localLine[i][0]) {
  3617. localFragments.push(localLine[i][0]+' ');
  3618. localStyles.push(localLine[i][1]);
  3619. }
  3620. ++i;
  3621. }
  3622. });
  3623. //split lines again due to possible coordinate changes
  3624. lines = this.splitFragmentsIntoLines(PurgeWhiteSpace(localFragments), localStyles);
  3625. //reposition the current cursor
  3626. out("ET", "Q");
  3627. out("q", "BT 0 g", this.pdf.internal.getCoordinateString(this.x), this.pdf.internal.getVerticalCoordinateString(this.y), "Td");
  3628. }
  3629. }
  3630. if (cb && typeof cb === "function") {
  3631. cb.call(this, this.x - 9, this.y - fontSize / 2);
  3632. }
  3633. out("ET", "Q");
  3634. return this.y += paragraphspacing_after;
  3635. };
  3636. Renderer.prototype.setBlockBoundary = function (cb) {
  3637. return this.renderParagraph(cb);
  3638. };
  3639. Renderer.prototype.setBlockStyle = function (css) {
  3640. return this.paragraph.blockstyle = css;
  3641. };
  3642. Renderer.prototype.addText = function (text, css) {
  3643. this.paragraph.text.push(text);
  3644. return this.paragraph.style.push(css);
  3645. };
  3646. FontNameDB = {
  3647. helvetica : "helvetica",
  3648. "sans-serif" : "helvetica",
  3649. "times new roman" : "times",
  3650. serif : "times",
  3651. times : "times",
  3652. monospace : "courier",
  3653. courier : "courier"
  3654. };
  3655. FontWeightMap = {
  3656. 100 : "normal",
  3657. 200 : "normal",
  3658. 300 : "normal",
  3659. 400 : "normal",
  3660. 500 : "bold",
  3661. 600 : "bold",
  3662. 700 : "bold",
  3663. 800 : "bold",
  3664. 900 : "bold",
  3665. normal : "normal",
  3666. bold : "bold",
  3667. bolder : "bold",
  3668. lighter : "normal"
  3669. };
  3670. FontStyleMap = {
  3671. normal : "normal",
  3672. italic : "italic",
  3673. oblique : "italic"
  3674. };
  3675. TextAlignMap = {
  3676. left : "left",
  3677. right : "right",
  3678. center : "center",
  3679. justify : "justify"
  3680. };
  3681. FloatMap = {
  3682. none : 'none',
  3683. right: 'right',
  3684. left: 'left'
  3685. };
  3686. ClearMap = {
  3687. none : 'none',
  3688. both : 'both'
  3689. };
  3690. UnitedNumberMap = {
  3691. normal : 1
  3692. };
  3693. /**
  3694. * Converts HTML-formatted text into formatted PDF text.
  3695. *
  3696. * Notes:
  3697. * 2012-07-18
  3698. * Plugin relies on having browser, DOM around. The HTML is pushed into dom and traversed.
  3699. * Plugin relies on jQuery for CSS extraction.
  3700. * Targeting HTML output from Markdown templating, which is a very simple
  3701. * markup - div, span, em, strong, p. No br-based paragraph separation supported explicitly (but still may work.)
  3702. * Images, tables are NOT supported.
  3703. *
  3704. * @public
  3705. * @function
  3706. * @param HTML {String or DOM Element} HTML-formatted text, or pointer to DOM element that is to be rendered into PDF.
  3707. * @param x {Number} starting X coordinate in jsPDF instance's declared units.
  3708. * @param y {Number} starting Y coordinate in jsPDF instance's declared units.
  3709. * @param settings {Object} Additional / optional variables controlling parsing, rendering.
  3710. * @returns {Object} jsPDF instance
  3711. */
  3712. jsPDFAPI.fromHTML = function (HTML, x, y, settings, callback, margins) {
  3713. "use strict";
  3714. this.margins_doc = margins || {
  3715. top : 0,
  3716. bottom : 0
  3717. };
  3718. if (!settings)
  3719. settings = {};
  3720. if (!settings.elementHandlers)
  3721. settings.elementHandlers = {};
  3722. return process(this, HTML, isNaN(x) ? 4 : x, isNaN(y) ? 4 : y, settings, callback);
  3723. };
  3724. })(jsPDF.API);
  3725. /** ====================================================================
  3726. * jsPDF JavaScript plugin
  3727. * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
  3728. *
  3729. * Permission is hereby granted, free of charge, to any person obtaining
  3730. * a copy of this software and associated documentation files (the
  3731. * "Software"), to deal in the Software without restriction, including
  3732. * without limitation the rights to use, copy, modify, merge, publish,
  3733. * distribute, sublicense, and/or sell copies of the Software, and to
  3734. * permit persons to whom the Software is furnished to do so, subject to
  3735. * the following conditions:
  3736. *
  3737. * The above copyright notice and this permission notice shall be
  3738. * included in all copies or substantial portions of the Software.
  3739. *
  3740. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  3741. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  3742. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  3743. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  3744. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  3745. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  3746. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  3747. * ====================================================================
  3748. */
  3749. /*global jsPDF */
  3750. (function (jsPDFAPI) {
  3751. 'use strict';
  3752. var jsNamesObj, jsJsObj, text;
  3753. jsPDFAPI.addJS = function (txt) {
  3754. text = txt;
  3755. this.internal.events.subscribe(
  3756. 'postPutResources',
  3757. function (txt) {
  3758. jsNamesObj = this.internal.newObject();
  3759. this.internal.write('<< /Names [(EmbeddedJS) ' + (jsNamesObj + 1) + ' 0 R] >>', 'endobj');
  3760. jsJsObj = this.internal.newObject();
  3761. this.internal.write('<< /S /JavaScript /JS (', text, ') >>', 'endobj');
  3762. }
  3763. );
  3764. this.internal.events.subscribe(
  3765. 'putCatalog',
  3766. function () {
  3767. if (jsNamesObj !== undefined && jsJsObj !== undefined) {
  3768. this.internal.write('/Names <</JavaScript ' + jsNamesObj + ' 0 R>>');
  3769. }
  3770. }
  3771. );
  3772. return this;
  3773. };
  3774. }(jsPDF.API));
  3775. /**@preserve
  3776. * ====================================================================
  3777. * jsPDF PNG PlugIn
  3778. * Copyright (c) 2014 James Robb, https://github.com/jamesbrobb
  3779. *
  3780. * Permission is hereby granted, free of charge, to any person obtaining
  3781. * a copy of this software and associated documentation files (the
  3782. * "Software"), to deal in the Software without restriction, including
  3783. * without limitation the rights to use, copy, modify, merge, publish,
  3784. * distribute, sublicense, and/or sell copies of the Software, and to
  3785. * permit persons to whom the Software is furnished to do so, subject to
  3786. * the following conditions:
  3787. *
  3788. * The above copyright notice and this permission notice shall be
  3789. * included in all copies or substantial portions of the Software.
  3790. *
  3791. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  3792. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  3793. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  3794. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  3795. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  3796. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  3797. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  3798. * ====================================================================
  3799. */
  3800. (function(jsPDFAPI) {
  3801. 'use strict'
  3802. /*
  3803. * @see http://www.w3.org/TR/PNG-Chunks.html
  3804. *
  3805. Color Allowed Interpretation
  3806. Type Bit Depths
  3807. 0 1,2,4,8,16 Each pixel is a grayscale sample.
  3808. 2 8,16 Each pixel is an R,G,B triple.
  3809. 3 1,2,4,8 Each pixel is a palette index;
  3810. a PLTE chunk must appear.
  3811. 4 8,16 Each pixel is a grayscale sample,
  3812. followed by an alpha sample.
  3813. 6 8,16 Each pixel is an R,G,B triple,
  3814. followed by an alpha sample.
  3815. */
  3816. /*
  3817. * PNG filter method types
  3818. *
  3819. * @see http://www.w3.org/TR/PNG-Filters.html
  3820. * @see http://www.libpng.org/pub/png/book/chapter09.html
  3821. *
  3822. * This is what the value 'Predictor' in decode params relates to
  3823. *
  3824. * 15 is "optimal prediction", which means the prediction algorithm can change from line to line.
  3825. * 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.
  3826. *
  3827. 0 None
  3828. 1 Sub
  3829. 2 Up
  3830. 3 Average
  3831. 4 Paeth
  3832. */
  3833. var doesNotHavePngJS = function() {
  3834. return typeof PNG !== 'function' || typeof FlateStream !== 'function';
  3835. }
  3836. , canCompress = function(value) {
  3837. return value !== jsPDFAPI.image_compression.NONE && hasCompressionJS();
  3838. }
  3839. , hasCompressionJS = function() {
  3840. var inst = typeof Deflater === 'function';
  3841. if(!inst)
  3842. throw new Error("requires deflate.js for compression")
  3843. return inst;
  3844. }
  3845. , compressBytes = function(bytes, lineLength, colorsPerPixel, compression) {
  3846. var level = 5,
  3847. filter_method = filterUp;
  3848. switch(compression) {
  3849. case jsPDFAPI.image_compression.FAST:
  3850. level = 3;
  3851. filter_method = filterSub;
  3852. break;
  3853. case jsPDFAPI.image_compression.MEDIUM:
  3854. level = 6;
  3855. filter_method = filterAverage;
  3856. break;
  3857. case jsPDFAPI.image_compression.SLOW:
  3858. level = 9;
  3859. filter_method = filterPaeth;//uses to sum to choose best filter for each line
  3860. break;
  3861. }
  3862. bytes = applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method);
  3863. var header = new Uint8Array(createZlibHeader(level));
  3864. var checksum = adler32(bytes);
  3865. var deflate = new Deflater(level);
  3866. var a = deflate.append(bytes);
  3867. var cBytes = deflate.flush();
  3868. var len = header.length + a.length + cBytes.length;
  3869. var cmpd = new Uint8Array(len + 4);
  3870. cmpd.set(header);
  3871. cmpd.set(a, header.length);
  3872. cmpd.set(cBytes, header.length + a.length);
  3873. cmpd[len++] = (checksum >>> 24) & 0xff;
  3874. cmpd[len++] = (checksum >>> 16) & 0xff;
  3875. cmpd[len++] = (checksum >>> 8) & 0xff;
  3876. cmpd[len++] = checksum & 0xff;
  3877. return jsPDFAPI.arrayBufferToBinaryString(cmpd);
  3878. }
  3879. , createZlibHeader = function(bytes, level){
  3880. /*
  3881. * @see http://www.ietf.org/rfc/rfc1950.txt for zlib header
  3882. */
  3883. var cm = 8;
  3884. var cinfo = Math.LOG2E * Math.log(0x8000) - 8;
  3885. var cmf = (cinfo << 4) | cm;
  3886. var hdr = cmf << 8;
  3887. var flevel = Math.min(3, ((level - 1) & 0xff) >> 1);
  3888. hdr |= (flevel << 6);
  3889. hdr |= 0;//FDICT
  3890. hdr += 31 - (hdr % 31);
  3891. return [cmf, (hdr & 0xff) & 0xff];
  3892. }
  3893. , adler32 = function(array, param) {
  3894. var adler = 1;
  3895. var s1 = adler & 0xffff,
  3896. s2 = (adler >>> 16) & 0xffff;
  3897. var len = array.length;
  3898. var tlen;
  3899. var i = 0;
  3900. while (len > 0) {
  3901. tlen = len > param ? param : len;
  3902. len -= tlen;
  3903. do {
  3904. s1 += array[i++];
  3905. s2 += s1;
  3906. } while (--tlen);
  3907. s1 %= 65521;
  3908. s2 %= 65521;
  3909. }
  3910. return ((s2 << 16) | s1) >>> 0;
  3911. }
  3912. , applyPngFilterMethod = function(bytes, lineLength, colorsPerPixel, filter_method) {
  3913. var lines = bytes.length / lineLength,
  3914. result = new Uint8Array(bytes.length + lines),
  3915. filter_methods = getFilterMethods(),
  3916. i = 0, line, prevLine, offset;
  3917. for(; i < lines; i++) {
  3918. offset = i * lineLength;
  3919. line = bytes.subarray(offset, offset + lineLength);
  3920. if(filter_method) {
  3921. result.set(filter_method(line, colorsPerPixel, prevLine), offset + i);
  3922. }else{
  3923. var j = 0,
  3924. len = filter_methods.length,
  3925. results = [];
  3926. for(; j < len; j++)
  3927. results[j] = filter_methods[j](line, colorsPerPixel, prevLine);
  3928. var ind = getIndexOfSmallestSum(results.concat());
  3929. result.set(results[ind], offset + i);
  3930. }
  3931. prevLine = line;
  3932. }
  3933. return result;
  3934. }
  3935. , filterNone = function(line, colorsPerPixel, prevLine) {
  3936. /*var result = new Uint8Array(line.length + 1);
  3937. result[0] = 0;
  3938. result.set(line, 1);*/
  3939. var result = Array.apply([], line);
  3940. result.unshift(0);
  3941. return result;
  3942. }
  3943. , filterSub = function(line, colorsPerPixel, prevLine) {
  3944. var result = [],
  3945. i = 0,
  3946. len = line.length,
  3947. left;
  3948. result[0] = 1;
  3949. for(; i < len; i++) {
  3950. left = line[i - colorsPerPixel] || 0;
  3951. result[i + 1] = (line[i] - left + 0x0100) & 0xff;
  3952. }
  3953. return result;
  3954. }
  3955. , filterUp = function(line, colorsPerPixel, prevLine) {
  3956. var result = [],
  3957. i = 0,
  3958. len = line.length,
  3959. up;
  3960. result[0] = 2;
  3961. for(; i < len; i++) {
  3962. up = prevLine && prevLine[i] || 0;
  3963. result[i + 1] = (line[i] - up + 0x0100) & 0xff;
  3964. }
  3965. return result;
  3966. }
  3967. , filterAverage = function(line, colorsPerPixel, prevLine) {
  3968. var result = [],
  3969. i = 0,
  3970. len = line.length,
  3971. left,
  3972. up;
  3973. result[0] = 3;
  3974. for(; i < len; i++) {
  3975. left = line[i - colorsPerPixel] || 0;
  3976. up = prevLine && prevLine[i] || 0;
  3977. result[i + 1] = (line[i] + 0x0100 - ((left + up) >>> 1)) & 0xff;
  3978. }
  3979. return result;
  3980. }
  3981. , filterPaeth = function(line, colorsPerPixel, prevLine) {
  3982. var result = [],
  3983. i = 0,
  3984. len = line.length,
  3985. left,
  3986. up,
  3987. upLeft,
  3988. paeth;
  3989. result[0] = 4;
  3990. for(; i < len; i++) {
  3991. left = line[i - colorsPerPixel] || 0;
  3992. up = prevLine && prevLine[i] || 0;
  3993. upLeft = prevLine && prevLine[i - colorsPerPixel] || 0;
  3994. paeth = paethPredictor(left, up, upLeft);
  3995. result[i + 1] = (line[i] - paeth + 0x0100) & 0xff;
  3996. }
  3997. return result;
  3998. }
  3999. ,paethPredictor = function(left, up, upLeft) {
  4000. var p = left + up - upLeft,
  4001. pLeft = Math.abs(p - left),
  4002. pUp = Math.abs(p - up),
  4003. pUpLeft = Math.abs(p - upLeft);
  4004. return (pLeft <= pUp && pLeft <= pUpLeft) ? left : (pUp <= pUpLeft) ? up : upLeft;
  4005. }
  4006. , getFilterMethods = function() {
  4007. return [filterNone, filterSub, filterUp, filterAverage, filterPaeth];
  4008. }
  4009. ,getIndexOfSmallestSum = function(arrays) {
  4010. var i = 0,
  4011. len = arrays.length,
  4012. sum, min, ind;
  4013. while(i < len) {
  4014. sum = absSum(arrays[i].slice(1));
  4015. if(sum < min || !min) {
  4016. min = sum;
  4017. ind = i;
  4018. }
  4019. i++;
  4020. }
  4021. return ind;
  4022. }
  4023. , absSum = function(array) {
  4024. var i = 0,
  4025. len = array.length,
  4026. sum = 0;
  4027. while(i < len)
  4028. sum += Math.abs(array[i++]);
  4029. return sum;
  4030. }
  4031. , logImg = function(img) {
  4032. console.log("width: " + img.width);
  4033. console.log("height: " + img.height);
  4034. console.log("bits: " + img.bits);
  4035. console.log("colorType: " + img.colorType);
  4036. console.log("transparency:");
  4037. console.log(img.transparency);
  4038. console.log("text:");
  4039. console.log(img.text);
  4040. console.log("compressionMethod: " + img.compressionMethod);
  4041. console.log("filterMethod: " + img.filterMethod);
  4042. console.log("interlaceMethod: " + img.interlaceMethod);
  4043. console.log("imgData:");
  4044. console.log(img.imgData);
  4045. console.log("palette:");
  4046. console.log(img.palette);
  4047. console.log("colors: " + img.colors);
  4048. console.log("colorSpace: " + img.colorSpace);
  4049. console.log("pixelBitlength: " + img.pixelBitlength);
  4050. console.log("hasAlphaChannel: " + img.hasAlphaChannel);
  4051. };
  4052. jsPDFAPI.processPNG = function(imageData, imageIndex, alias, compression, dataAsBinaryString) {
  4053. 'use strict'
  4054. var colorSpace = this.color_spaces.DEVICE_RGB,
  4055. decode = this.decode.FLATE_DECODE,
  4056. bpc = 8,
  4057. img, dp, trns,
  4058. colors, pal, smask;
  4059. /* if(this.isString(imageData)) {
  4060. }*/
  4061. if(this.isArrayBuffer(imageData))
  4062. imageData = new Uint8Array(imageData);
  4063. if(this.isArrayBufferView(imageData)) {
  4064. if(doesNotHavePngJS())
  4065. throw new Error("PNG support requires png.js and zlib.js");
  4066. img = new PNG(imageData);
  4067. imageData = img.imgData;
  4068. bpc = img.bits;
  4069. colorSpace = img.colorSpace;
  4070. colors = img.colors;
  4071. //logImg(img);
  4072. /*
  4073. * colorType 6 - Each pixel is an R,G,B triple, followed by an alpha sample.
  4074. *
  4075. * colorType 4 - Each pixel is a grayscale sample, followed by an alpha sample.
  4076. *
  4077. * Extract alpha to create two separate images, using the alpha as a sMask
  4078. */
  4079. if([4,6].indexOf(img.colorType) !== -1) {
  4080. /*
  4081. * processes 8 bit RGBA and grayscale + alpha images
  4082. */
  4083. if(img.bits === 8) {
  4084. var pixelsArrayType = window['Uint' + img.pixelBitlength + 'Array'],
  4085. pixels = new pixelsArrayType(img.decodePixels().buffer),
  4086. len = pixels.length,
  4087. imgData = new Uint8Array(len * img.colors),
  4088. alphaData = new Uint8Array(len),
  4089. pDiff = img.pixelBitlength - img.bits,
  4090. i = 0, n = 0, pixel, pbl;
  4091. for(; i < len; i++) {
  4092. pixel = pixels[i];
  4093. pbl = 0;
  4094. while(pbl < pDiff) {
  4095. imgData[n++] = ( pixel >>> pbl ) & 0xff;
  4096. pbl = pbl + img.bits;
  4097. }
  4098. alphaData[i] = ( pixel >>> pbl ) & 0xff;
  4099. }
  4100. }
  4101. /*
  4102. * processes 16 bit RGBA and grayscale + alpha images
  4103. */
  4104. if(img.bits === 16) {
  4105. var pixels = new Uint32Array(img.decodePixels().buffer),
  4106. len = pixels.length,
  4107. imgData = new Uint8Array((len * (32 / img.pixelBitlength) ) * img.colors),
  4108. alphaData = new Uint8Array(len * (32 / img.pixelBitlength) ),
  4109. hasColors = img.colors > 1,
  4110. i = 0, n = 0, a = 0, pixel;
  4111. while(i < len) {
  4112. pixel = pixels[i++];
  4113. imgData[n++] = (pixel >>> 0) & 0xFF;
  4114. if(hasColors) {
  4115. imgData[n++] = (pixel >>> 16) & 0xFF;
  4116. pixel = pixels[i++];
  4117. imgData[n++] = (pixel >>> 0) & 0xFF;
  4118. }
  4119. alphaData[a++] = (pixel >>> 16) & 0xFF;
  4120. }
  4121. bpc = 8;
  4122. }
  4123. if(canCompress(compression)) {
  4124. imageData = compressBytes(imgData, img.width * img.colors, img.colors, compression);
  4125. smask = compressBytes(alphaData, img.width, 1, compression);
  4126. }else{
  4127. imageData = imgData;
  4128. smask = alphaData;
  4129. decode = null;
  4130. }
  4131. }
  4132. /*
  4133. * Indexed png. Each pixel is a palette index.
  4134. */
  4135. if(img.colorType === 3) {
  4136. colorSpace = this.color_spaces.INDEXED;
  4137. pal = img.palette;
  4138. if(img.transparency.indexed) {
  4139. var trans = img.transparency.indexed;
  4140. var total = 0,
  4141. i = 0,
  4142. len = trans.length;
  4143. for(; i<len; ++i)
  4144. total += trans[i];
  4145. total = total / 255;
  4146. /*
  4147. * a single color is specified as 100% transparent (0),
  4148. * so we set trns to use a /Mask with that index
  4149. */
  4150. if(total === len - 1 && trans.indexOf(0) !== -1) {
  4151. trns = [trans.indexOf(0)];
  4152. /*
  4153. * there's more than one colour within the palette that specifies
  4154. * a transparency value less than 255, so we unroll the pixels to create an image sMask
  4155. */
  4156. }else if(total !== len){
  4157. var pixels = img.decodePixels(),
  4158. alphaData = new Uint8Array(pixels.length),
  4159. i = 0,
  4160. len = pixels.length;
  4161. for(; i < len; i++)
  4162. alphaData[i] = trans[pixels[i]];
  4163. smask = compressBytes(alphaData, img.width, 1);
  4164. }
  4165. }
  4166. }
  4167. if(decode === this.decode.FLATE_DECODE)
  4168. dp = '/Predictor 15 /Colors '+ colors +' /BitsPerComponent '+ bpc +' /Columns '+ img.width;
  4169. else
  4170. //remove 'Predictor' as it applies to the type of png filter applied to its IDAT - we only apply with compression
  4171. dp = '/Colors '+ colors +' /BitsPerComponent '+ bpc +' /Columns '+ img.width;
  4172. if(this.isArrayBuffer(imageData) || this.isArrayBufferView(imageData))
  4173. imageData = this.arrayBufferToBinaryString(imageData);
  4174. if(smask && this.isArrayBuffer(smask) || this.isArrayBufferView(smask))
  4175. smask = this.arrayBufferToBinaryString(smask);
  4176. return this.createImageInfo(imageData, img.width, img.height, colorSpace,
  4177. bpc, decode, imageIndex, alias, dp, trns, pal, smask);
  4178. }
  4179. throw new Error("Unsupported PNG image data, try using JPEG instead.");
  4180. }
  4181. })(jsPDF.API)
  4182. /** @preserve
  4183. jsPDF Silly SVG plugin
  4184. Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  4185. */
  4186. /**
  4187. * Permission is hereby granted, free of charge, to any person obtaining
  4188. * a copy of this software and associated documentation files (the
  4189. * "Software"), to deal in the Software without restriction, including
  4190. * without limitation the rights to use, copy, modify, merge, publish,
  4191. * distribute, sublicense, and/or sell copies of the Software, and to
  4192. * permit persons to whom the Software is furnished to do so, subject to
  4193. * the following conditions:
  4194. *
  4195. * The above copyright notice and this permission notice shall be
  4196. * included in all copies or substantial portions of the Software.
  4197. *
  4198. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  4199. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  4200. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  4201. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  4202. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  4203. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  4204. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  4205. * ====================================================================
  4206. */
  4207. ;(function(jsPDFAPI) {
  4208. 'use strict'
  4209. /**
  4210. Parses SVG XML and converts only some of the SVG elements into
  4211. PDF elements.
  4212. Supports:
  4213. paths
  4214. @public
  4215. @function
  4216. @param
  4217. @returns {Type}
  4218. */
  4219. jsPDFAPI.addSVG = function(svgtext, x, y, w, h) {
  4220. // 'this' is _jsPDF object returned when jsPDF is inited (new jsPDF())
  4221. var undef
  4222. if (x === undef || y === undef) {
  4223. throw new Error("addSVG needs values for 'x' and 'y'");
  4224. }
  4225. function InjectCSS(cssbody, document) {
  4226. var styletag = document.createElement('style');
  4227. styletag.type = 'text/css';
  4228. if (styletag.styleSheet) {
  4229. // ie
  4230. styletag.styleSheet.cssText = cssbody;
  4231. } else {
  4232. // others
  4233. styletag.appendChild(document.createTextNode(cssbody));
  4234. }
  4235. document.getElementsByTagName("head")[0].appendChild(styletag);
  4236. }
  4237. function createWorkerNode(document){
  4238. var frameID = 'childframe' // Date.now().toString() + '_' + (Math.random() * 100).toString()
  4239. , frame = document.createElement('iframe')
  4240. InjectCSS(
  4241. '.jsPDF_sillysvg_iframe {display:none;position:absolute;}'
  4242. , document
  4243. )
  4244. frame.name = frameID
  4245. frame.setAttribute("width", 0)
  4246. frame.setAttribute("height", 0)
  4247. frame.setAttribute("frameborder", "0")
  4248. frame.setAttribute("scrolling", "no")
  4249. frame.setAttribute("seamless", "seamless")
  4250. frame.setAttribute("class", "jsPDF_sillysvg_iframe")
  4251. document.body.appendChild(frame)
  4252. return frame
  4253. }
  4254. function attachSVGToWorkerNode(svgtext, frame){
  4255. var framedoc = ( frame.contentWindow || frame.contentDocument ).document
  4256. framedoc.write(svgtext)
  4257. framedoc.close()
  4258. return framedoc.getElementsByTagName('svg')[0]
  4259. }
  4260. function convertPathToPDFLinesArgs(path){
  4261. 'use strict'
  4262. // we will use 'lines' method call. it needs:
  4263. // - starting coordinate pair
  4264. // - array of arrays of vector shifts (2-len for line, 6 len for bezier)
  4265. // - scale array [horizontal, vertical] ratios
  4266. // - style (stroke, fill, both)
  4267. var x = parseFloat(path[1])
  4268. , y = parseFloat(path[2])
  4269. , vectors = []
  4270. , position = 3
  4271. , len = path.length
  4272. while (position < len){
  4273. if (path[position] === 'c'){
  4274. vectors.push([
  4275. parseFloat(path[position + 1])
  4276. , parseFloat(path[position + 2])
  4277. , parseFloat(path[position + 3])
  4278. , parseFloat(path[position + 4])
  4279. , parseFloat(path[position + 5])
  4280. , parseFloat(path[position + 6])
  4281. ])
  4282. position += 7
  4283. } else if (path[position] === 'l') {
  4284. vectors.push([
  4285. parseFloat(path[position + 1])
  4286. , parseFloat(path[position + 2])
  4287. ])
  4288. position += 3
  4289. } else {
  4290. position += 1
  4291. }
  4292. }
  4293. return [x,y,vectors]
  4294. }
  4295. var workernode = createWorkerNode(document)
  4296. , svgnode = attachSVGToWorkerNode(svgtext, workernode)
  4297. , scale = [1,1]
  4298. , svgw = parseFloat(svgnode.getAttribute('width'))
  4299. , svgh = parseFloat(svgnode.getAttribute('height'))
  4300. if (svgw && svgh) {
  4301. // setting both w and h makes image stretch to size.
  4302. // this may distort the image, but fits your demanded size
  4303. if (w && h) {
  4304. scale = [w / svgw, h / svgh]
  4305. }
  4306. // if only one is set, that value is set as max and SVG
  4307. // is scaled proportionately.
  4308. else if (w) {
  4309. scale = [w / svgw, w / svgw]
  4310. } else if (h) {
  4311. scale = [h / svgh, h / svgh]
  4312. }
  4313. }
  4314. var i, l, tmp
  4315. , linesargs
  4316. , items = svgnode.childNodes
  4317. for (i = 0, l = items.length; i < l; i++) {
  4318. tmp = items[i]
  4319. if (tmp.tagName && tmp.tagName.toUpperCase() === 'PATH') {
  4320. linesargs = convertPathToPDFLinesArgs( tmp.getAttribute("d").split(' ') )
  4321. // path start x coordinate
  4322. linesargs[0] = linesargs[0] * scale[0] + x // where x is upper left X of image
  4323. // path start y coordinate
  4324. linesargs[1] = linesargs[1] * scale[1] + y // where y is upper left Y of image
  4325. // the rest of lines are vectors. these will adjust with scale value auto.
  4326. this.lines.call(
  4327. this
  4328. , linesargs[2] // lines
  4329. , linesargs[0] // starting x
  4330. , linesargs[1] // starting y
  4331. , scale
  4332. )
  4333. }
  4334. }
  4335. // clean up
  4336. // workernode.parentNode.removeChild(workernode)
  4337. return this
  4338. }
  4339. })(jsPDF.API);
  4340. /** @preserve
  4341. * jsPDF split_text_to_size plugin - MIT license.
  4342. * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  4343. * 2014 Diego Casorran, https://github.com/diegocr
  4344. */
  4345. /**
  4346. * Permission is hereby granted, free of charge, to any person obtaining
  4347. * a copy of this software and associated documentation files (the
  4348. * "Software"), to deal in the Software without restriction, including
  4349. * without limitation the rights to use, copy, modify, merge, publish,
  4350. * distribute, sublicense, and/or sell copies of the Software, and to
  4351. * permit persons to whom the Software is furnished to do so, subject to
  4352. * the following conditions:
  4353. *
  4354. * The above copyright notice and this permission notice shall be
  4355. * included in all copies or substantial portions of the Software.
  4356. *
  4357. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  4358. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  4359. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  4360. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  4361. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  4362. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  4363. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  4364. * ====================================================================
  4365. */
  4366. ;(function(API) {
  4367. 'use strict'
  4368. /**
  4369. Returns an array of length matching length of the 'word' string, with each
  4370. cell ocupied by the width of the char in that position.
  4371. @function
  4372. @param word {String}
  4373. @param widths {Object}
  4374. @param kerning {Object}
  4375. @returns {Array}
  4376. */
  4377. var getCharWidthsArray = API.getCharWidthsArray = function(text, options){
  4378. if (!options) {
  4379. options = {}
  4380. }
  4381. var widths = options.widths ? options.widths : this.internal.getFont().metadata.Unicode.widths
  4382. , widthsFractionOf = widths.fof ? widths.fof : 1
  4383. , kerning = options.kerning ? options.kerning : this.internal.getFont().metadata.Unicode.kerning
  4384. , kerningFractionOf = kerning.fof ? kerning.fof : 1
  4385. // console.log("widths, kergnings", widths, kerning)
  4386. var i, l
  4387. , char_code
  4388. , prior_char_code = 0 // for kerning
  4389. , default_char_width = widths[0] || widthsFractionOf
  4390. , output = []
  4391. for (i = 0, l = text.length; i < l; i++) {
  4392. char_code = text.charCodeAt(i)
  4393. output.push(
  4394. ( widths[char_code] || default_char_width ) / widthsFractionOf +
  4395. ( kerning[char_code] && kerning[char_code][prior_char_code] || 0 ) / kerningFractionOf
  4396. )
  4397. prior_char_code = char_code
  4398. }
  4399. return output
  4400. }
  4401. var getArraySum = function(array){
  4402. var i = array.length
  4403. , output = 0
  4404. while(i){
  4405. ;i--;
  4406. output += array[i]
  4407. }
  4408. return output
  4409. }
  4410. /**
  4411. Returns a widths of string in a given font, if the font size is set as 1 point.
  4412. In other words, this is "proportional" value. For 1 unit of font size, the length
  4413. of the string will be that much.
  4414. Multiply by font size to get actual width in *points*
  4415. Then divide by 72 to get inches or divide by (72/25.6) to get 'mm' etc.
  4416. @public
  4417. @function
  4418. @param
  4419. @returns {Type}
  4420. */
  4421. var getStringUnitWidth = API.getStringUnitWidth = function(text, options) {
  4422. return getArraySum(getCharWidthsArray.call(this, text, options))
  4423. }
  4424. /**
  4425. returns array of lines
  4426. */
  4427. var splitLongWord = function(word, widths_array, firstLineMaxLen, maxLen){
  4428. var answer = []
  4429. // 1st, chop off the piece that can fit on the hanging line.
  4430. var i = 0
  4431. , l = word.length
  4432. , workingLen = 0
  4433. while (i !== l && workingLen + widths_array[i] < firstLineMaxLen){
  4434. workingLen += widths_array[i]
  4435. ;i++;
  4436. }
  4437. // this is first line.
  4438. answer.push(word.slice(0, i))
  4439. // 2nd. Split the rest into maxLen pieces.
  4440. var startOfLine = i
  4441. workingLen = 0
  4442. while (i !== l){
  4443. if (workingLen + widths_array[i] > maxLen) {
  4444. answer.push(word.slice(startOfLine, i))
  4445. workingLen = 0
  4446. startOfLine = i
  4447. }
  4448. workingLen += widths_array[i]
  4449. ;i++;
  4450. }
  4451. if (startOfLine !== i) {
  4452. answer.push(word.slice(startOfLine, i))
  4453. }
  4454. return answer
  4455. }
  4456. // Note, all sizing inputs for this function must be in "font measurement units"
  4457. // By default, for PDF, it's "point".
  4458. var splitParagraphIntoLines = function(text, maxlen, options){
  4459. // at this time works only on Western scripts, ones with space char
  4460. // separating the words. Feel free to expand.
  4461. if (!options) {
  4462. options = {}
  4463. }
  4464. var line = []
  4465. , lines = [line]
  4466. , line_length = options.textIndent || 0
  4467. , separator_length = 0
  4468. , current_word_length = 0
  4469. , word
  4470. , widths_array
  4471. , words = text.split(' ')
  4472. , spaceCharWidth = getCharWidthsArray(' ', options)[0]
  4473. , i, l, tmp, lineIndent
  4474. if(options.lineIndent === -1) {
  4475. lineIndent = words[0].length +2;
  4476. } else {
  4477. lineIndent = options.lineIndent || 0;
  4478. }
  4479. if(lineIndent) {
  4480. var pad = Array(lineIndent).join(" "), wrds = [];
  4481. words.map(function(wrd) {
  4482. wrd = wrd.split(/\s*\n/);
  4483. if(wrd.length > 1) {
  4484. wrds = wrds.concat(wrd.map(function(wrd, idx) {
  4485. return (idx && wrd.length ? "\n":"") + wrd;
  4486. }));
  4487. } else {
  4488. wrds.push(wrd[0]);
  4489. }
  4490. });
  4491. words = wrds;
  4492. lineIndent = getStringUnitWidth(pad, options);
  4493. }
  4494. for (i = 0, l = words.length; i < l; i++) {
  4495. var force = 0;
  4496. word = words[i]
  4497. if(lineIndent && word[0] == "\n") {
  4498. word = word.substr(1);
  4499. force = 1;
  4500. }
  4501. widths_array = getCharWidthsArray(word, options)
  4502. current_word_length = getArraySum(widths_array)
  4503. if (line_length + separator_length + current_word_length > maxlen || force) {
  4504. if (current_word_length > maxlen) {
  4505. // this happens when you have space-less long URLs for example.
  4506. // we just chop these to size. We do NOT insert hiphens
  4507. tmp = splitLongWord(word, widths_array, maxlen - (line_length + separator_length), maxlen)
  4508. // first line we add to existing line object
  4509. line.push(tmp.shift()) // it's ok to have extra space indicator there
  4510. // last line we make into new line object
  4511. line = [tmp.pop()]
  4512. // lines in the middle we apped to lines object as whole lines
  4513. while(tmp.length){
  4514. lines.push([tmp.shift()]) // single fragment occupies whole line
  4515. }
  4516. current_word_length = getArraySum( widths_array.slice(word.length - line[0].length) )
  4517. } else {
  4518. // just put it on a new line
  4519. line = [word]
  4520. }
  4521. // now we attach new line to lines
  4522. lines.push(line)
  4523. line_length = current_word_length + lineIndent
  4524. separator_length = spaceCharWidth
  4525. } else {
  4526. line.push(word)
  4527. line_length += separator_length + current_word_length
  4528. separator_length = spaceCharWidth
  4529. }
  4530. }
  4531. if(lineIndent) {
  4532. var postProcess = function(ln, idx) {
  4533. return (idx ? pad : '') + ln.join(" ");
  4534. };
  4535. } else {
  4536. var postProcess = function(ln) { return ln.join(" ")};
  4537. }
  4538. return lines.map(postProcess);
  4539. }
  4540. /**
  4541. Splits a given string into an array of strings. Uses 'size' value
  4542. (in measurement units declared as default for the jsPDF instance)
  4543. and the font's "widths" and "Kerning" tables, where availabe, to
  4544. determine display length of a given string for a given font.
  4545. We use character's 100% of unit size (height) as width when Width
  4546. table or other default width is not available.
  4547. @public
  4548. @function
  4549. @param text {String} Unencoded, regular JavaScript (Unicode, UTF-16 / UCS-2) string.
  4550. @param size {Number} Nominal number, measured in units default to this instance of jsPDF.
  4551. @param options {Object} Optional flags needed for chopper to do the right thing.
  4552. @returns {Array} with strings chopped to size.
  4553. */
  4554. API.splitTextToSize = function(text, maxlen, options) {
  4555. 'use strict'
  4556. if (!options) {
  4557. options = {}
  4558. }
  4559. var fsize = options.fontSize || this.internal.getFontSize()
  4560. , newOptions = (function(options){
  4561. var widths = {0:1}
  4562. , kerning = {}
  4563. if (!options.widths || !options.kerning) {
  4564. var f = this.internal.getFont(options.fontName, options.fontStyle)
  4565. , encoding = 'Unicode'
  4566. // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE
  4567. // Actual JavaScript-native String's 16bit char codes used.
  4568. // no multi-byte logic here
  4569. if (f.metadata[encoding]) {
  4570. return {
  4571. widths: f.metadata[encoding].widths || widths
  4572. , kerning: f.metadata[encoding].kerning || kerning
  4573. }
  4574. }
  4575. } else {
  4576. return {
  4577. widths: options.widths
  4578. , kerning: options.kerning
  4579. }
  4580. }
  4581. // then use default values
  4582. return {
  4583. widths: widths
  4584. , kerning: kerning
  4585. }
  4586. }).call(this, options)
  4587. // first we split on end-of-line chars
  4588. var paragraphs
  4589. if(Array.isArray(text)) {
  4590. paragraphs = text;
  4591. } else {
  4592. paragraphs = text.split(/\r?\n/);
  4593. }
  4594. // now we convert size (max length of line) into "font size units"
  4595. // at present time, the "font size unit" is always 'point'
  4596. // 'proportional' means, "in proportion to font size"
  4597. var fontUnit_maxLen = 1.0 * this.internal.scaleFactor * maxlen / fsize
  4598. // at this time, fsize is always in "points" regardless of the default measurement unit of the doc.
  4599. // this may change in the future?
  4600. // until then, proportional_maxlen is likely to be in 'points'
  4601. // If first line is to be indented (shorter or longer) than maxLen
  4602. // we indicate that by using CSS-style "text-indent" option.
  4603. // here it's in font units too (which is likely 'points')
  4604. // it can be negative (which makes the first line longer than maxLen)
  4605. newOptions.textIndent = options.textIndent ?
  4606. options.textIndent * 1.0 * this.internal.scaleFactor / fsize :
  4607. 0
  4608. newOptions.lineIndent = options.lineIndent;
  4609. var i, l
  4610. , output = []
  4611. for (i = 0, l = paragraphs.length; i < l; i++) {
  4612. output = output.concat(
  4613. splitParagraphIntoLines(
  4614. paragraphs[i]
  4615. , fontUnit_maxLen
  4616. , newOptions
  4617. )
  4618. )
  4619. }
  4620. return output
  4621. }
  4622. })(jsPDF.API);
  4623. /** @preserve
  4624. jsPDF standard_fonts_metrics plugin
  4625. Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  4626. MIT license.
  4627. */
  4628. /**
  4629. * Permission is hereby granted, free of charge, to any person obtaining
  4630. * a copy of this software and associated documentation files (the
  4631. * "Software"), to deal in the Software without restriction, including
  4632. * without limitation the rights to use, copy, modify, merge, publish,
  4633. * distribute, sublicense, and/or sell copies of the Software, and to
  4634. * permit persons to whom the Software is furnished to do so, subject to
  4635. * the following conditions:
  4636. *
  4637. * The above copyright notice and this permission notice shall be
  4638. * included in all copies or substantial portions of the Software.
  4639. *
  4640. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  4641. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  4642. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  4643. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  4644. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  4645. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  4646. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  4647. * ====================================================================
  4648. */
  4649. ;(function(API) {
  4650. 'use strict'
  4651. /*
  4652. # reference (Python) versions of 'compress' and 'uncompress'
  4653. # only 'uncompress' function is featured lower as JavaScript
  4654. # if you want to unit test "roundtrip", just transcribe the reference
  4655. # 'compress' function from Python into JavaScript
  4656. def compress(data):
  4657. keys = '0123456789abcdef'
  4658. values = 'klmnopqrstuvwxyz'
  4659. mapping = dict(zip(keys, values))
  4660. vals = []
  4661. for key in data.keys():
  4662. value = data[key]
  4663. try:
  4664. keystring = hex(key)[2:]
  4665. keystring = keystring[:-1] + mapping[keystring[-1:]]
  4666. except:
  4667. keystring = key.join(["'","'"])
  4668. #print('Keystring is %s' % keystring)
  4669. try:
  4670. if value < 0:
  4671. valuestring = hex(value)[3:]
  4672. numberprefix = '-'
  4673. else:
  4674. valuestring = hex(value)[2:]
  4675. numberprefix = ''
  4676. valuestring = numberprefix + valuestring[:-1] + mapping[valuestring[-1:]]
  4677. except:
  4678. if type(value) == dict:
  4679. valuestring = compress(value)
  4680. else:
  4681. raise Exception("Don't know what to do with value type %s" % type(value))
  4682. vals.append(keystring+valuestring)
  4683. return '{' + ''.join(vals) + '}'
  4684. def uncompress(data):
  4685. decoded = '0123456789abcdef'
  4686. encoded = 'klmnopqrstuvwxyz'
  4687. mapping = dict(zip(encoded, decoded))
  4688. sign = +1
  4689. stringmode = False
  4690. stringparts = []
  4691. output = {}
  4692. activeobject = output
  4693. parentchain = []
  4694. keyparts = ''
  4695. valueparts = ''
  4696. key = None
  4697. ending = set(encoded)
  4698. i = 1
  4699. l = len(data) - 1 # stripping starting, ending {}
  4700. while i != l: # stripping {}
  4701. # -, {, }, ' are special.
  4702. ch = data[i]
  4703. i += 1
  4704. if ch == "'":
  4705. if stringmode:
  4706. # end of string mode
  4707. stringmode = False
  4708. key = ''.join(stringparts)
  4709. else:
  4710. # start of string mode
  4711. stringmode = True
  4712. stringparts = []
  4713. elif stringmode == True:
  4714. #print("Adding %s to stringpart" % ch)
  4715. stringparts.append(ch)
  4716. elif ch == '{':
  4717. # start of object
  4718. parentchain.append( [activeobject, key] )
  4719. activeobject = {}
  4720. key = None
  4721. #DEBUG = True
  4722. elif ch == '}':
  4723. # end of object
  4724. parent, key = parentchain.pop()
  4725. parent[key] = activeobject
  4726. key = None
  4727. activeobject = parent
  4728. #DEBUG = False
  4729. elif ch == '-':
  4730. sign = -1
  4731. else:
  4732. # must be number
  4733. if key == None:
  4734. #debug("In Key. It is '%s', ch is '%s'" % (keyparts, ch))
  4735. if ch in ending:
  4736. #debug("End of key")
  4737. keyparts += mapping[ch]
  4738. key = int(keyparts, 16) * sign
  4739. sign = +1
  4740. keyparts = ''
  4741. else:
  4742. keyparts += ch
  4743. else:
  4744. #debug("In value. It is '%s', ch is '%s'" % (valueparts, ch))
  4745. if ch in ending:
  4746. #debug("End of value")
  4747. valueparts += mapping[ch]
  4748. activeobject[key] = int(valueparts, 16) * sign
  4749. sign = +1
  4750. key = None
  4751. valueparts = ''
  4752. else:
  4753. valueparts += ch
  4754. #debug(activeobject)
  4755. return output
  4756. */
  4757. /**
  4758. Uncompresses data compressed into custom, base16-like format.
  4759. @public
  4760. @function
  4761. @param
  4762. @returns {Type}
  4763. */
  4764. var uncompress = function(data){
  4765. var decoded = '0123456789abcdef'
  4766. , encoded = 'klmnopqrstuvwxyz'
  4767. , mapping = {}
  4768. for (var i = 0; i < encoded.length; i++){
  4769. mapping[encoded[i]] = decoded[i]
  4770. }
  4771. var undef
  4772. , output = {}
  4773. , sign = 1
  4774. , stringparts // undef. will be [] in string mode
  4775. , activeobject = output
  4776. , parentchain = []
  4777. , parent_key_pair
  4778. , keyparts = ''
  4779. , valueparts = ''
  4780. , key // undef. will be Truthy when Key is resolved.
  4781. , datalen = data.length - 1 // stripping ending }
  4782. , ch
  4783. i = 1 // stripping starting {
  4784. while (i != datalen){
  4785. // - { } ' are special.
  4786. ch = data[i]
  4787. i += 1
  4788. if (ch == "'"){
  4789. if (stringparts){
  4790. // end of string mode
  4791. key = stringparts.join('')
  4792. stringparts = undef
  4793. } else {
  4794. // start of string mode
  4795. stringparts = []
  4796. }
  4797. } else if (stringparts){
  4798. stringparts.push(ch)
  4799. } else if (ch == '{'){
  4800. // start of object
  4801. parentchain.push( [activeobject, key] )
  4802. activeobject = {}
  4803. key = undef
  4804. } else if (ch == '}'){
  4805. // end of object
  4806. parent_key_pair = parentchain.pop()
  4807. parent_key_pair[0][parent_key_pair[1]] = activeobject
  4808. key = undef
  4809. activeobject = parent_key_pair[0]
  4810. } else if (ch == '-'){
  4811. sign = -1
  4812. } else {
  4813. // must be number
  4814. if (key === undef) {
  4815. if (mapping.hasOwnProperty(ch)){
  4816. keyparts += mapping[ch]
  4817. key = parseInt(keyparts, 16) * sign
  4818. sign = +1
  4819. keyparts = ''
  4820. } else {
  4821. keyparts += ch
  4822. }
  4823. } else {
  4824. if (mapping.hasOwnProperty(ch)){
  4825. valueparts += mapping[ch]
  4826. activeobject[key] = parseInt(valueparts, 16) * sign
  4827. sign = +1
  4828. key = undef
  4829. valueparts = ''
  4830. } else {
  4831. valueparts += ch
  4832. }
  4833. }
  4834. }
  4835. } // end while
  4836. return output
  4837. }
  4838. // encoding = 'Unicode'
  4839. // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE. NO clever BOM behavior
  4840. // Actual 16bit char codes used.
  4841. // no multi-byte logic here
  4842. // Unicode characters to WinAnsiEncoding:
  4843. // {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}
  4844. // as you can see, all Unicode chars are outside of 0-255 range. No char code conflicts.
  4845. // this means that you can give Win cp1252 encoded strings to jsPDF for rendering directly
  4846. // as well as give strings with some (supported by these fonts) Unicode characters and
  4847. // these will be mapped to win cp1252
  4848. // for example, you can send char code (cp1252) 0x80 or (unicode) 0x20AC, getting "Euro" glyph displayed in both cases.
  4849. var encodingBlock = {
  4850. 'codePages': ['WinAnsiEncoding']
  4851. , 'WinAnsiEncoding': uncompress("{19m8n201n9q201o9r201s9l201t9m201u8m201w9n201x9o201y8o202k8q202l8r202m9p202q8p20aw8k203k8t203t8v203u9v2cq8s212m9t15m8w15n9w2dw9s16k8u16l9u17s9z17x8y17y9y}")
  4852. }
  4853. , encodings = {'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. Resources:
  4871. Font metrics data is reprocessed derivative of contents of
  4872. "Font Metrics for PDF Core 14 Fonts" package, which exhibits the following copyright and license:
  4873. Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
  4874. This file and the 14 PostScript(R) AFM files it accompanies may be used,
  4875. copied, and distributed for any purpose and without charge, with or without
  4876. modification, provided that all copyright notices are retained; that the AFM
  4877. files are not distributed without this file; that all modifications to this
  4878. file or any of the AFM files are prominently noted in the modified file(s);
  4879. and that this paragraph is not modified. Adobe Systems has no responsibility
  4880. or obligation to support the use of the AFM files.
  4881. */
  4882. , fontMetrics = {'Unicode':{
  4883. // all sizing numbers are n/fontMetricsFractionOf = one font size unit
  4884. // this means that if fontMetricsFractionOf = 1000, and letter A's width is 476, it's
  4885. // width is 476/1000 or 47.6% of its height (regardless of font size)
  4886. // At this time this value applies to "widths" and "kerning" numbers.
  4887. // char code 0 represents "default" (average) width - use it for chars missing in this table.
  4888. // key 'fof' represents the "fontMetricsFractionOf" value
  4889. 'Courier-Oblique': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
  4890. , '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}}}")
  4891. , '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}}}")
  4892. , 'Courier': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
  4893. , 'Courier-BoldOblique': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
  4894. , '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}}}")
  4895. //, 'Symbol': uncompress("{'widths'{k3uaw4r19m3m2k1t2l2l202m2y2n3m2p5n202q6o3k3m2s2l2t2l2v3r2w1t3m3m2y1t2z1wbk2sbl3r'fof'6o3n3m3o3m3p3m3q3m3r3m3s3m3t3m3u1w3v1w3w3r3x3r3y3r3z2wbp3t3l3m5v2l5x2l5z3m2q4yfr3r7v3k7w1o7x3k}'kerning'{'fof'-6o}}")
  4896. , '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}}}")
  4897. , '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}}}")
  4898. //, 'ZapfDingbats': uncompress("{'widths'{k4u2k1w'fof'6o}'kerning'{'fof'-6o}}")
  4899. , 'Courier-Bold': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
  4900. , '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}}}")
  4901. , '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}}}")
  4902. , '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}}}")
  4903. }};
  4904. /*
  4905. This event handler is fired when a new jsPDF object is initialized
  4906. This event handler appends metrics data to standard fonts within
  4907. that jsPDF instance. The metrics are mapped over Unicode character
  4908. codes, NOT CIDs or other codes matching the StandardEncoding table of the
  4909. standard PDF fonts.
  4910. Future:
  4911. Also included is the encoding maping table, converting Unicode (UCS-2, UTF-16)
  4912. char codes to StandardEncoding character codes. The encoding table is to be used
  4913. somewhere around "pdfEscape" call.
  4914. */
  4915. API.events.push([
  4916. 'addFonts'
  4917. ,function(fontManagementObjects) {
  4918. // fontManagementObjects is {
  4919. // 'fonts':font_ID-keyed hash of font objects
  4920. // , 'dictionary': lookup object, linking ["FontFamily"]['Style'] to font ID
  4921. //}
  4922. var font
  4923. , fontID
  4924. , metrics
  4925. , unicode_section
  4926. , encoding = 'Unicode'
  4927. , encodingBlock
  4928. for (fontID in fontManagementObjects.fonts){
  4929. if (fontManagementObjects.fonts.hasOwnProperty(fontID)) {
  4930. font = fontManagementObjects.fonts[fontID]
  4931. // // we only ship 'Unicode' mappings and metrics. No need for loop.
  4932. // // still, leaving this for the future.
  4933. // for (encoding in fontMetrics){
  4934. // if (fontMetrics.hasOwnProperty(encoding)) {
  4935. metrics = fontMetrics[encoding][font.PostScriptName]
  4936. if (metrics) {
  4937. if (font.metadata[encoding]) {
  4938. unicode_section = font.metadata[encoding]
  4939. } else {
  4940. unicode_section = font.metadata[encoding] = {}
  4941. }
  4942. unicode_section.widths = metrics.widths
  4943. unicode_section.kerning = metrics.kerning
  4944. }
  4945. // }
  4946. // }
  4947. // for (encoding in encodings){
  4948. // if (encodings.hasOwnProperty(encoding)) {
  4949. encodingBlock = encodings[encoding][font.PostScriptName]
  4950. if (encodingBlock) {
  4951. if (font.metadata[encoding]) {
  4952. unicode_section = font.metadata[encoding]
  4953. } else {
  4954. unicode_section = font.metadata[encoding] = {}
  4955. }
  4956. unicode_section.encoding = encodingBlock
  4957. if (encodingBlock.codePages && encodingBlock.codePages.length) {
  4958. font.encoding = encodingBlock.codePages[0]
  4959. }
  4960. }
  4961. // }
  4962. // }
  4963. }
  4964. }
  4965. }
  4966. ]) // end of adding event handler
  4967. })(jsPDF.API);
  4968. /** ====================================================================
  4969. * jsPDF total_pages plugin
  4970. * Copyright (c) 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br
  4971. *
  4972. * Permission is hereby granted, free of charge, to any person obtaining
  4973. * a copy of this software and associated documentation files (the
  4974. * "Software"), to deal in the Software without restriction, including
  4975. * without limitation the rights to use, copy, modify, merge, publish,
  4976. * distribute, sublicense, and/or sell copies of the Software, and to
  4977. * permit persons to whom the Software is furnished to do so, subject to
  4978. * the following conditions:
  4979. *
  4980. * The above copyright notice and this permission notice shall be
  4981. * included in all copies or substantial portions of the Software.
  4982. *
  4983. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  4984. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  4985. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  4986. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  4987. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  4988. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  4989. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  4990. * ====================================================================
  4991. */
  4992. (function(jsPDFAPI) {
  4993. 'use strict';
  4994. jsPDFAPI.putTotalPages = function(pageExpression) {
  4995. 'use strict';
  4996. var replaceExpression = new RegExp(pageExpression, 'g');
  4997. for (var n = 1; n <= this.internal.getNumberOfPages(); n++) {
  4998. for (var i = 0; i < this.internal.pages[n].length; i++)
  4999. this.internal.pages[n][i] = this.internal.pages[n][i].replace(replaceExpression, this.internal.getNumberOfPages());
  5000. }
  5001. return this;
  5002. };
  5003. })(jsPDF.API);
  5004. /* Blob.js
  5005. * A Blob implementation.
  5006. * 2014-07-24
  5007. *
  5008. * By Eli Grey, http://eligrey.com
  5009. * By Devin Samarin, https://github.com/dsamarin
  5010. * License: X11/MIT
  5011. * See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
  5012. */
  5013. /*global self, unescape */
  5014. /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
  5015. plusplus: true */
  5016. /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
  5017. (function (view) {
  5018. "use strict";
  5019. view.URL = view.URL || view.webkitURL;
  5020. if (view.Blob && view.URL) {
  5021. try {
  5022. new Blob;
  5023. return;
  5024. } catch (e) {}
  5025. }
  5026. // Internally we use a BlobBuilder implementation to base Blob off of
  5027. // in order to support older browsers that only have BlobBuilder
  5028. var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) {
  5029. var
  5030. get_class = function(object) {
  5031. return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
  5032. }
  5033. , FakeBlobBuilder = function BlobBuilder() {
  5034. this.data = [];
  5035. }
  5036. , FakeBlob = function Blob(data, type, encoding) {
  5037. this.data = data;
  5038. this.size = data.length;
  5039. this.type = type;
  5040. this.encoding = encoding;
  5041. }
  5042. , FBB_proto = FakeBlobBuilder.prototype
  5043. , FB_proto = FakeBlob.prototype
  5044. , FileReaderSync = view.FileReaderSync
  5045. , FileException = function(type) {
  5046. this.code = this[this.name = type];
  5047. }
  5048. , file_ex_codes = (
  5049. "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
  5050. + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
  5051. ).split(" ")
  5052. , file_ex_code = file_ex_codes.length
  5053. , real_URL = view.URL || view.webkitURL || view
  5054. , real_create_object_URL = real_URL.createObjectURL
  5055. , real_revoke_object_URL = real_URL.revokeObjectURL
  5056. , URL = real_URL
  5057. , btoa = view.btoa
  5058. , atob = view.atob
  5059. , ArrayBuffer = view.ArrayBuffer
  5060. , Uint8Array = view.Uint8Array
  5061. , origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/
  5062. ;
  5063. FakeBlob.fake = FB_proto.fake = true;
  5064. while (file_ex_code--) {
  5065. FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
  5066. }
  5067. // Polyfill URL
  5068. if (!real_URL.createObjectURL) {
  5069. URL = view.URL = function(uri) {
  5070. var
  5071. uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
  5072. , uri_origin
  5073. ;
  5074. uri_info.href = uri;
  5075. if (!("origin" in uri_info)) {
  5076. if (uri_info.protocol.toLowerCase() === "data:") {
  5077. uri_info.origin = null;
  5078. } else {
  5079. uri_origin = uri.match(origin);
  5080. uri_info.origin = uri_origin && uri_origin[1];
  5081. }
  5082. }
  5083. return uri_info;
  5084. };
  5085. }
  5086. URL.createObjectURL = function(blob) {
  5087. var
  5088. type = blob.type
  5089. , data_URI_header
  5090. ;
  5091. if (type === null) {
  5092. type = "application/octet-stream";
  5093. }
  5094. if (blob instanceof FakeBlob) {
  5095. data_URI_header = "data:" + type;
  5096. if (blob.encoding === "base64") {
  5097. return data_URI_header + ";base64," + blob.data;
  5098. } else if (blob.encoding === "URI") {
  5099. return data_URI_header + "," + decodeURIComponent(blob.data);
  5100. } if (btoa) {
  5101. return data_URI_header + ";base64," + btoa(blob.data);
  5102. } else {
  5103. return data_URI_header + "," + encodeURIComponent(blob.data);
  5104. }
  5105. } else if (real_create_object_URL) {
  5106. return real_create_object_URL.call(real_URL, blob);
  5107. }
  5108. };
  5109. URL.revokeObjectURL = function(object_URL) {
  5110. if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
  5111. real_revoke_object_URL.call(real_URL, object_URL);
  5112. }
  5113. };
  5114. FBB_proto.append = function(data/*, endings*/) {
  5115. var bb = this.data;
  5116. // decode data to a binary string
  5117. if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
  5118. var
  5119. str = ""
  5120. , buf = new Uint8Array(data)
  5121. , i = 0
  5122. , buf_len = buf.length
  5123. ;
  5124. for (; i < buf_len; i++) {
  5125. str += String.fromCharCode(buf[i]);
  5126. }
  5127. bb.push(str);
  5128. } else if (get_class(data) === "Blob" || get_class(data) === "File") {
  5129. if (FileReaderSync) {
  5130. var fr = new FileReaderSync;
  5131. bb.push(fr.readAsBinaryString(data));
  5132. } else {
  5133. // async FileReader won't work as BlobBuilder is sync
  5134. throw new FileException("NOT_READABLE_ERR");
  5135. }
  5136. } else if (data instanceof FakeBlob) {
  5137. if (data.encoding === "base64" && atob) {
  5138. bb.push(atob(data.data));
  5139. } else if (data.encoding === "URI") {
  5140. bb.push(decodeURIComponent(data.data));
  5141. } else if (data.encoding === "raw") {
  5142. bb.push(data.data);
  5143. }
  5144. } else {
  5145. if (typeof data !== "string") {
  5146. data += ""; // convert unsupported types to strings
  5147. }
  5148. // decode UTF-16 to binary string
  5149. bb.push(unescape(encodeURIComponent(data)));
  5150. }
  5151. };
  5152. FBB_proto.getBlob = function(type) {
  5153. if (!arguments.length) {
  5154. type = null;
  5155. }
  5156. return new FakeBlob(this.data.join(""), type, "raw");
  5157. };
  5158. FBB_proto.toString = function() {
  5159. return "[object BlobBuilder]";
  5160. };
  5161. FB_proto.slice = function(start, end, type) {
  5162. var args = arguments.length;
  5163. if (args < 3) {
  5164. type = null;
  5165. }
  5166. return new FakeBlob(
  5167. this.data.slice(start, args > 1 ? end : this.data.length)
  5168. , type
  5169. , this.encoding
  5170. );
  5171. };
  5172. FB_proto.toString = function() {
  5173. return "[object Blob]";
  5174. };
  5175. FB_proto.close = function() {
  5176. this.size = 0;
  5177. delete this.data;
  5178. };
  5179. return FakeBlobBuilder;
  5180. }(view));
  5181. view.Blob = function(blobParts, options) {
  5182. var type = options ? (options.type || "") : "";
  5183. var builder = new BlobBuilder();
  5184. if (blobParts) {
  5185. for (var i = 0, len = blobParts.length; i < len; i++) {
  5186. builder.append(blobParts[i]);
  5187. }
  5188. }
  5189. return builder.getBlob(type);
  5190. };
  5191. }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));
  5192. /* FileSaver.js
  5193. * A saveAs() FileSaver implementation.
  5194. * 2014-08-29
  5195. *
  5196. * By Eli Grey, http://eligrey.com
  5197. * License: X11/MIT
  5198. * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
  5199. */
  5200. /*global self */
  5201. /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
  5202. /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
  5203. var saveAs = saveAs
  5204. // IE 10+ (native saveAs)
  5205. || (typeof navigator !== "undefined" &&
  5206. navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
  5207. // Everyone else
  5208. || (function(view) {
  5209. "use strict";
  5210. // IE <10 is explicitly unsupported
  5211. if (typeof navigator !== "undefined" &&
  5212. /MSIE [1-9]\./.test(navigator.userAgent)) {
  5213. return;
  5214. }
  5215. var
  5216. doc = view.document
  5217. // only get URL when necessary in case Blob.js hasn't overridden it yet
  5218. , get_URL = function() {
  5219. return view.URL || view.webkitURL || view;
  5220. }
  5221. , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
  5222. , can_use_save_link = "download" in save_link
  5223. , click = function(node) {
  5224. var event = doc.createEvent("MouseEvents");
  5225. event.initMouseEvent(
  5226. "click", true, false, view, 0, 0, 0, 0, 0
  5227. , false, false, false, false, 0, null
  5228. );
  5229. node.dispatchEvent(event);
  5230. }
  5231. , webkit_req_fs = view.webkitRequestFileSystem
  5232. , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
  5233. , throw_outside = function(ex) {
  5234. (view.setImmediate || view.setTimeout)(function() {
  5235. throw ex;
  5236. }, 0);
  5237. }
  5238. , force_saveable_type = "application/octet-stream"
  5239. , fs_min_size = 0
  5240. // See https://code.google.com/p/chromium/issues/detail?id=375297#c7 for
  5241. // the reasoning behind the timeout and revocation flow
  5242. , arbitrary_revoke_timeout = 10
  5243. , revoke = function(file) {
  5244. var revoker = function() {
  5245. if (typeof file === "string") { // file is an object URL
  5246. get_URL().revokeObjectURL(file);
  5247. } else { // file is a File
  5248. file.remove();
  5249. }
  5250. };
  5251. if (view.chrome) {
  5252. revoker();
  5253. } else {
  5254. setTimeout(revoker, arbitrary_revoke_timeout);
  5255. }
  5256. }
  5257. , dispatch = function(filesaver, event_types, event) {
  5258. event_types = [].concat(event_types);
  5259. var i = event_types.length;
  5260. while (i--) {
  5261. var listener = filesaver["on" + event_types[i]];
  5262. if (typeof listener === "function") {
  5263. try {
  5264. listener.call(filesaver, event || filesaver);
  5265. } catch (ex) {
  5266. throw_outside(ex);
  5267. }
  5268. }
  5269. }
  5270. }
  5271. , FileSaver = function(blob, name) {
  5272. // First try a.download, then web filesystem, then object URLs
  5273. var
  5274. filesaver = this
  5275. , type = blob.type
  5276. , blob_changed = false
  5277. , object_url
  5278. , target_view
  5279. , dispatch_all = function() {
  5280. dispatch(filesaver, "writestart progress write writeend".split(" "));
  5281. }
  5282. // on any filesys errors revert to saving with object URLs
  5283. , fs_error = function() {
  5284. // don't create more object URLs than needed
  5285. if (blob_changed || !object_url) {
  5286. object_url = get_URL().createObjectURL(blob);
  5287. }
  5288. if (target_view) {
  5289. target_view.location.href = object_url;
  5290. } else {
  5291. var new_tab = view.open(object_url, "_blank");
  5292. if (new_tab == undefined && typeof safari !== "undefined") {
  5293. //Apple do not allow window.open, see http://bit.ly/1kZffRI
  5294. view.location.href = object_url
  5295. }
  5296. }
  5297. filesaver.readyState = filesaver.DONE;
  5298. dispatch_all();
  5299. revoke(object_url);
  5300. }
  5301. , abortable = function(func) {
  5302. return function() {
  5303. if (filesaver.readyState !== filesaver.DONE) {
  5304. return func.apply(this, arguments);
  5305. }
  5306. };
  5307. }
  5308. , create_if_not_found = {create: true, exclusive: false}
  5309. , slice
  5310. ;
  5311. filesaver.readyState = filesaver.INIT;
  5312. if (!name) {
  5313. name = "download";
  5314. }
  5315. if (can_use_save_link) {
  5316. object_url = get_URL().createObjectURL(blob);
  5317. save_link.href = object_url;
  5318. save_link.download = name;
  5319. click(save_link);
  5320. filesaver.readyState = filesaver.DONE;
  5321. dispatch_all();
  5322. revoke(object_url);
  5323. return;
  5324. }
  5325. // Object and web filesystem URLs have a problem saving in Google Chrome when
  5326. // viewed in a tab, so I force save with application/octet-stream
  5327. // http://code.google.com/p/chromium/issues/detail?id=91158
  5328. // Update: Google errantly closed 91158, I submitted it again:
  5329. // https://code.google.com/p/chromium/issues/detail?id=389642
  5330. if (view.chrome && type && type !== force_saveable_type) {
  5331. slice = blob.slice || blob.webkitSlice;
  5332. blob = slice.call(blob, 0, blob.size, force_saveable_type);
  5333. blob_changed = true;
  5334. }
  5335. // Since I can't be sure that the guessed media type will trigger a download
  5336. // in WebKit, I append .download to the filename.
  5337. // https://bugs.webkit.org/show_bug.cgi?id=65440
  5338. if (webkit_req_fs && name !== "download") {
  5339. name += ".download";
  5340. }
  5341. if (type === force_saveable_type || webkit_req_fs) {
  5342. target_view = view;
  5343. }
  5344. if (!req_fs) {
  5345. fs_error();
  5346. return;
  5347. }
  5348. fs_min_size += blob.size;
  5349. req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
  5350. fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
  5351. var save = function() {
  5352. dir.getFile(name, create_if_not_found, abortable(function(file) {
  5353. file.createWriter(abortable(function(writer) {
  5354. writer.onwriteend = function(event) {
  5355. target_view.location.href = file.toURL();
  5356. filesaver.readyState = filesaver.DONE;
  5357. dispatch(filesaver, "writeend", event);
  5358. revoke(file);
  5359. };
  5360. writer.onerror = function() {
  5361. var error = writer.error;
  5362. if (error.code !== error.ABORT_ERR) {
  5363. fs_error();
  5364. }
  5365. };
  5366. "writestart progress write abort".split(" ").forEach(function(event) {
  5367. writer["on" + event] = filesaver["on" + event];
  5368. });
  5369. writer.write(blob);
  5370. filesaver.abort = function() {
  5371. writer.abort();
  5372. filesaver.readyState = filesaver.DONE;
  5373. };
  5374. filesaver.readyState = filesaver.WRITING;
  5375. }), fs_error);
  5376. }), fs_error);
  5377. };
  5378. dir.getFile(name, {create: false}, abortable(function(file) {
  5379. // delete file if it already exists
  5380. file.remove();
  5381. save();
  5382. }), abortable(function(ex) {
  5383. if (ex.code === ex.NOT_FOUND_ERR) {
  5384. save();
  5385. } else {
  5386. fs_error();
  5387. }
  5388. }));
  5389. }), fs_error);
  5390. }), fs_error);
  5391. }
  5392. , FS_proto = FileSaver.prototype
  5393. , saveAs = function(blob, name) {
  5394. return new FileSaver(blob, name);
  5395. }
  5396. ;
  5397. FS_proto.abort = function() {
  5398. var filesaver = this;
  5399. filesaver.readyState = filesaver.DONE;
  5400. dispatch(filesaver, "abort");
  5401. };
  5402. FS_proto.readyState = FS_proto.INIT = 0;
  5403. FS_proto.WRITING = 1;
  5404. FS_proto.DONE = 2;
  5405. FS_proto.error =
  5406. FS_proto.onwritestart =
  5407. FS_proto.onprogress =
  5408. FS_proto.onwrite =
  5409. FS_proto.onabort =
  5410. FS_proto.onerror =
  5411. FS_proto.onwriteend =
  5412. null;
  5413. return saveAs;
  5414. }(
  5415. typeof self !== "undefined" && self
  5416. || typeof window !== "undefined" && window
  5417. || this.content
  5418. ));
  5419. // `self` is undefined in Firefox for Android content script context
  5420. // while `this` is nsIContentFrameMessageManager
  5421. // with an attribute `content` that corresponds to the window
  5422. if (typeof module !== "undefined" && module !== null) {
  5423. module.exports = saveAs;
  5424. } else if ((typeof define !== "undefined" && 0)) {
  5425. define([], function() {
  5426. return saveAs;
  5427. });
  5428. }
  5429. /*
  5430. * Copyright (c) 2012 chick307 <chick307@gmail.com>
  5431. *
  5432. * Licensed under the MIT License.
  5433. * http://opensource.org/licenses/mit-license
  5434. */
  5435. void function(global, callback) {
  5436. if (typeof module === 'object') {
  5437. module.exports = callback();
  5438. } else if (0 === 'function') {
  5439. define(callback);
  5440. } else {
  5441. global.adler32cs = callback();
  5442. }
  5443. }(jsPDF, function() {
  5444. var _hasArrayBuffer = typeof ArrayBuffer === 'function' &&
  5445. typeof Uint8Array === 'function';
  5446. var _Buffer = null, _isBuffer = (function() {
  5447. if (!_hasArrayBuffer)
  5448. return function _isBuffer() { return false };
  5449. try {
  5450. var buffer = require('buffer');
  5451. if (typeof buffer.Buffer === 'function')
  5452. _Buffer = buffer.Buffer;
  5453. } catch (error) {}
  5454. return function _isBuffer(value) {
  5455. return value instanceof ArrayBuffer ||
  5456. _Buffer !== null && value instanceof _Buffer;
  5457. };
  5458. }());
  5459. var _utf8ToBinary = (function() {
  5460. if (_Buffer !== null) {
  5461. return function _utf8ToBinary(utf8String) {
  5462. return new _Buffer(utf8String, 'utf8').toString('binary');
  5463. };
  5464. } else {
  5465. return function _utf8ToBinary(utf8String) {
  5466. return unescape(encodeURIComponent(utf8String));
  5467. };
  5468. }
  5469. }());
  5470. var MOD = 65521;
  5471. var _update = function _update(checksum, binaryString) {
  5472. var a = checksum & 0xFFFF, b = checksum >>> 16;
  5473. for (var i = 0, length = binaryString.length; i < length; i++) {
  5474. a = (a + (binaryString.charCodeAt(i) & 0xFF)) % MOD;
  5475. b = (b + a) % MOD;
  5476. }
  5477. return (b << 16 | a) >>> 0;
  5478. };
  5479. var _updateUint8Array = function _updateUint8Array(checksum, uint8Array) {
  5480. var a = checksum & 0xFFFF, b = checksum >>> 16;
  5481. for (var i = 0, length = uint8Array.length, x; i < length; i++) {
  5482. a = (a + uint8Array[i]) % MOD;
  5483. b = (b + a) % MOD;
  5484. }
  5485. return (b << 16 | a) >>> 0
  5486. };
  5487. var exports = {};
  5488. var Adler32 = exports.Adler32 = (function() {
  5489. var ctor = function Adler32(checksum) {
  5490. if (!(this instanceof ctor)) {
  5491. throw new TypeError(
  5492. 'Constructor cannot called be as a function.');
  5493. }
  5494. if (!isFinite(checksum = checksum == null ? 1 : +checksum)) {
  5495. throw new Error(
  5496. 'First arguments needs to be a finite number.');
  5497. }
  5498. this.checksum = checksum >>> 0;
  5499. };
  5500. var proto = ctor.prototype = {};
  5501. proto.constructor = ctor;
  5502. ctor.from = function(from) {
  5503. from.prototype = proto;
  5504. return from;
  5505. }(function from(binaryString) {
  5506. if (!(this instanceof ctor)) {
  5507. throw new TypeError(
  5508. 'Constructor cannot called be as a function.');
  5509. }
  5510. if (binaryString == null)
  5511. throw new Error('First argument needs to be a string.');
  5512. this.checksum = _update(1, binaryString.toString());
  5513. });
  5514. ctor.fromUtf8 = function(fromUtf8) {
  5515. fromUtf8.prototype = proto;
  5516. return fromUtf8;
  5517. }(function fromUtf8(utf8String) {
  5518. if (!(this instanceof ctor)) {
  5519. throw new TypeError(
  5520. 'Constructor cannot called be as a function.');
  5521. }
  5522. if (utf8String == null)
  5523. throw new Error('First argument needs to be a string.');
  5524. var binaryString = _utf8ToBinary(utf8String.toString());
  5525. this.checksum = _update(1, binaryString);
  5526. });
  5527. if (_hasArrayBuffer) {
  5528. ctor.fromBuffer = function(fromBuffer) {
  5529. fromBuffer.prototype = proto;
  5530. return fromBuffer;
  5531. }(function fromBuffer(buffer) {
  5532. if (!(this instanceof ctor)) {
  5533. throw new TypeError(
  5534. 'Constructor cannot called be as a function.');
  5535. }
  5536. if (!_isBuffer(buffer))
  5537. throw new Error('First argument needs to be ArrayBuffer.');
  5538. var array = new Uint8Array(buffer);
  5539. return this.checksum = _updateUint8Array(1, array);
  5540. });
  5541. }
  5542. proto.update = function update(binaryString) {
  5543. if (binaryString == null)
  5544. throw new Error('First argument needs to be a string.');
  5545. binaryString = binaryString.toString();
  5546. return this.checksum = _update(this.checksum, binaryString);
  5547. };
  5548. proto.updateUtf8 = function updateUtf8(utf8String) {
  5549. if (utf8String == null)
  5550. throw new Error('First argument needs to be a string.');
  5551. var binaryString = _utf8ToBinary(utf8String.toString());
  5552. return this.checksum = _update(this.checksum, binaryString);
  5553. };
  5554. if (_hasArrayBuffer) {
  5555. proto.updateBuffer = function updateBuffer(buffer) {
  5556. if (!_isBuffer(buffer))
  5557. throw new Error('First argument needs to be ArrayBuffer.');
  5558. var array = new Uint8Array(buffer);
  5559. return this.checksum = _updateUint8Array(this.checksum, array);
  5560. };
  5561. }
  5562. proto.clone = function clone() {
  5563. return new Adler32(this.checksum);
  5564. };
  5565. return ctor;
  5566. }());
  5567. exports.from = function from(binaryString) {
  5568. if (binaryString == null)
  5569. throw new Error('First argument needs to be a string.');
  5570. return _update(1, binaryString.toString());
  5571. };
  5572. exports.fromUtf8 = function fromUtf8(utf8String) {
  5573. if (utf8String == null)
  5574. throw new Error('First argument needs to be a string.');
  5575. var binaryString = _utf8ToBinary(utf8String.toString());
  5576. return _update(1, binaryString);
  5577. };
  5578. if (_hasArrayBuffer) {
  5579. exports.fromBuffer = function fromBuffer(buffer) {
  5580. if (!_isBuffer(buffer))
  5581. throw new Error('First argument need to be ArrayBuffer.');
  5582. var array = new Uint8Array(buffer);
  5583. return _updateUint8Array(1, array);
  5584. };
  5585. }
  5586. return exports;
  5587. });
  5588. /*
  5589. Deflate.js - https://github.com/gildas-lormeau/zip.js
  5590. Copyright (c) 2013 Gildas Lormeau. All rights reserved.
  5591. Redistribution and use in source and binary forms, with or without
  5592. modification, are permitted provided that the following conditions are met:
  5593. 1. Redistributions of source code must retain the above copyright notice,
  5594. this list of conditions and the following disclaimer.
  5595. 2. Redistributions in binary form must reproduce the above copyright
  5596. notice, this list of conditions and the following disclaimer in
  5597. the documentation and/or other materials provided with the distribution.
  5598. 3. The names of the authors may not be used to endorse or promote products
  5599. derived from this software without specific prior written permission.
  5600. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  5601. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  5602. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
  5603. INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
  5604. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  5605. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  5606. OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  5607. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  5608. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  5609. EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  5610. */
  5611. /*
  5612. * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.
  5613. * JZlib is based on zlib-1.1.3, so all credit should go authors
  5614. * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
  5615. * and contributors of zlib.
  5616. */
  5617. var Deflater = (function(obj) {
  5618. // Global
  5619. var MAX_BITS = 15;
  5620. var D_CODES = 30;
  5621. var BL_CODES = 19;
  5622. var LENGTH_CODES = 29;
  5623. var LITERALS = 256;
  5624. var L_CODES = (LITERALS + 1 + LENGTH_CODES);
  5625. var HEAP_SIZE = (2 * L_CODES + 1);
  5626. var END_BLOCK = 256;
  5627. // Bit length codes must not exceed MAX_BL_BITS bits
  5628. var MAX_BL_BITS = 7;
  5629. // repeat previous bit length 3-6 times (2 bits of repeat count)
  5630. var REP_3_6 = 16;
  5631. // repeat a zero length 3-10 times (3 bits of repeat count)
  5632. var REPZ_3_10 = 17;
  5633. // repeat a zero length 11-138 times (7 bits of repeat count)
  5634. var REPZ_11_138 = 18;
  5635. // The lengths of the bit length codes are sent in order of decreasing
  5636. // probability, to avoid transmitting the lengths for unused bit
  5637. // length codes.
  5638. var Buf_size = 8 * 2;
  5639. // JZlib version : "1.0.2"
  5640. var Z_DEFAULT_COMPRESSION = -1;
  5641. // compression strategy
  5642. var Z_FILTERED = 1;
  5643. var Z_HUFFMAN_ONLY = 2;
  5644. var Z_DEFAULT_STRATEGY = 0;
  5645. var Z_NO_FLUSH = 0;
  5646. var Z_PARTIAL_FLUSH = 1;
  5647. var Z_FULL_FLUSH = 3;
  5648. var Z_FINISH = 4;
  5649. var Z_OK = 0;
  5650. var Z_STREAM_END = 1;
  5651. var Z_NEED_DICT = 2;
  5652. var Z_STREAM_ERROR = -2;
  5653. var Z_DATA_ERROR = -3;
  5654. var Z_BUF_ERROR = -5;
  5655. // Tree
  5656. // see definition of array dist_code below
  5657. 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,
  5658. 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,
  5659. 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,
  5660. 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,
  5661. 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,
  5662. 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,
  5663. 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,
  5664. 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,
  5665. 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,
  5666. 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,
  5667. 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,
  5668. 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,
  5669. 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,
  5670. 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 ];
  5671. function Tree() {
  5672. var that = this;
  5673. // dyn_tree; // the dynamic tree
  5674. // max_code; // largest code with non zero frequency
  5675. // stat_desc; // the corresponding static tree
  5676. // Compute the optimal bit lengths for a tree and update the total bit
  5677. // length
  5678. // for the current block.
  5679. // IN assertion: the fields freq and dad are set, heap[heap_max] and
  5680. // above are the tree nodes sorted by increasing frequency.
  5681. // OUT assertions: the field len is set to the optimal bit length, the
  5682. // array bl_count contains the frequencies for each bit length.
  5683. // The length opt_len is updated; static_len is also updated if stree is
  5684. // not null.
  5685. function gen_bitlen(s) {
  5686. var tree = that.dyn_tree;
  5687. var stree = that.stat_desc.static_tree;
  5688. var extra = that.stat_desc.extra_bits;
  5689. var base = that.stat_desc.extra_base;
  5690. var max_length = that.stat_desc.max_length;
  5691. var h; // heap index
  5692. var n, m; // iterate over the tree elements
  5693. var bits; // bit length
  5694. var xbits; // extra bits
  5695. var f; // frequency
  5696. var overflow = 0; // number of elements with bit length too large
  5697. for (bits = 0; bits <= MAX_BITS; bits++)
  5698. s.bl_count[bits] = 0;
  5699. // In a first pass, compute the optimal bit lengths (which may
  5700. // overflow in the case of the bit length tree).
  5701. tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
  5702. for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
  5703. n = s.heap[h];
  5704. bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
  5705. if (bits > max_length) {
  5706. bits = max_length;
  5707. overflow++;
  5708. }
  5709. tree[n * 2 + 1] = bits;
  5710. // We overwrite tree[n*2+1] which is no longer needed
  5711. if (n > that.max_code)
  5712. continue; // not a leaf node
  5713. s.bl_count[bits]++;
  5714. xbits = 0;
  5715. if (n >= base)
  5716. xbits = extra[n - base];
  5717. f = tree[n * 2];
  5718. s.opt_len += f * (bits + xbits);
  5719. if (stree)
  5720. s.static_len += f * (stree[n * 2 + 1] + xbits);
  5721. }
  5722. if (overflow === 0)
  5723. return;
  5724. // This happens for example on obj2 and pic of the Calgary corpus
  5725. // Find the first bit length which could increase:
  5726. do {
  5727. bits = max_length - 1;
  5728. while (s.bl_count[bits] === 0)
  5729. bits--;
  5730. s.bl_count[bits]--; // move one leaf down the tree
  5731. s.bl_count[bits + 1] += 2; // move one overflow item as its brother
  5732. s.bl_count[max_length]--;
  5733. // The brother of the overflow item also moves one step up,
  5734. // but this does not affect bl_count[max_length]
  5735. overflow -= 2;
  5736. } while (overflow > 0);
  5737. for (bits = max_length; bits !== 0; bits--) {
  5738. n = s.bl_count[bits];
  5739. while (n !== 0) {
  5740. m = s.heap[--h];
  5741. if (m > that.max_code)
  5742. continue;
  5743. if (tree[m * 2 + 1] != bits) {
  5744. s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2];
  5745. tree[m * 2 + 1] = bits;
  5746. }
  5747. n--;
  5748. }
  5749. }
  5750. }
  5751. // Reverse the first len bits of a code, using straightforward code (a
  5752. // faster
  5753. // method would use a table)
  5754. // IN assertion: 1 <= len <= 15
  5755. function bi_reverse(code, // the value to invert
  5756. len // its bit length
  5757. ) {
  5758. var res = 0;
  5759. do {
  5760. res |= code & 1;
  5761. code >>>= 1;
  5762. res <<= 1;
  5763. } while (--len > 0);
  5764. return res >>> 1;
  5765. }
  5766. // Generate the codes for a given tree and bit counts (which need not be
  5767. // optimal).
  5768. // IN assertion: the array bl_count contains the bit length statistics for
  5769. // the given tree and the field len is set for all tree elements.
  5770. // OUT assertion: the field code is set for all tree elements of non
  5771. // zero code length.
  5772. function gen_codes(tree, // the tree to decorate
  5773. max_code, // largest code with non zero frequency
  5774. bl_count // number of codes at each bit length
  5775. ) {
  5776. var next_code = []; // next code value for each
  5777. // bit length
  5778. var code = 0; // running code value
  5779. var bits; // bit index
  5780. var n; // code index
  5781. var len;
  5782. // The distribution counts are first used to generate the code values
  5783. // without bit reversal.
  5784. for (bits = 1; bits <= MAX_BITS; bits++) {
  5785. next_code[bits] = code = ((code + bl_count[bits - 1]) << 1);
  5786. }
  5787. // Check that the bit counts in bl_count are consistent. The last code
  5788. // must be all ones.
  5789. // Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
  5790. // "inconsistent bit counts");
  5791. // Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
  5792. for (n = 0; n <= max_code; n++) {
  5793. len = tree[n * 2 + 1];
  5794. if (len === 0)
  5795. continue;
  5796. // Now reverse the bits
  5797. tree[n * 2] = bi_reverse(next_code[len]++, len);
  5798. }
  5799. }
  5800. // Construct one Huffman tree and assigns the code bit strings and lengths.
  5801. // Update the total bit length for the current block.
  5802. // IN assertion: the field freq is set for all tree elements.
  5803. // OUT assertions: the fields len and code are set to the optimal bit length
  5804. // and corresponding code. The length opt_len is updated; static_len is
  5805. // also updated if stree is not null. The field max_code is set.
  5806. that.build_tree = function(s) {
  5807. var tree = that.dyn_tree;
  5808. var stree = that.stat_desc.static_tree;
  5809. var elems = that.stat_desc.elems;
  5810. var n, m; // iterate over heap elements
  5811. var max_code = -1; // largest code with non zero frequency
  5812. var node; // new node being created
  5813. // Construct the initial heap, with least frequent element in
  5814. // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
  5815. // heap[0] is not used.
  5816. s.heap_len = 0;
  5817. s.heap_max = HEAP_SIZE;
  5818. for (n = 0; n < elems; n++) {
  5819. if (tree[n * 2] !== 0) {
  5820. s.heap[++s.heap_len] = max_code = n;
  5821. s.depth[n] = 0;
  5822. } else {
  5823. tree[n * 2 + 1] = 0;
  5824. }
  5825. }
  5826. // The pkzip format requires that at least one distance code exists,
  5827. // and that at least one bit should be sent even if there is only one
  5828. // possible code. So to avoid special checks later on we force at least
  5829. // two codes of non zero frequency.
  5830. while (s.heap_len < 2) {
  5831. node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0;
  5832. tree[node * 2] = 1;
  5833. s.depth[node] = 0;
  5834. s.opt_len--;
  5835. if (stree)
  5836. s.static_len -= stree[node * 2 + 1];
  5837. // node is 0 or 1 so it does not have extra bits
  5838. }
  5839. that.max_code = max_code;
  5840. // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
  5841. // establish sub-heaps of increasing lengths:
  5842. for (n = Math.floor(s.heap_len / 2); n >= 1; n--)
  5843. s.pqdownheap(tree, n);
  5844. // Construct the Huffman tree by repeatedly combining the least two
  5845. // frequent nodes.
  5846. node = elems; // next internal node of the tree
  5847. do {
  5848. // n = node of least frequency
  5849. n = s.heap[1];
  5850. s.heap[1] = s.heap[s.heap_len--];
  5851. s.pqdownheap(tree, 1);
  5852. m = s.heap[1]; // m = node of next least frequency
  5853. s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
  5854. s.heap[--s.heap_max] = m;
  5855. // Create a new node father of n and m
  5856. tree[node * 2] = (tree[n * 2] + tree[m * 2]);
  5857. s.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1;
  5858. tree[n * 2 + 1] = tree[m * 2 + 1] = node;
  5859. // and insert the new node in the heap
  5860. s.heap[1] = node++;
  5861. s.pqdownheap(tree, 1);
  5862. } while (s.heap_len >= 2);
  5863. s.heap[--s.heap_max] = s.heap[1];
  5864. // At this point, the fields freq and dad are set. We can now
  5865. // generate the bit lengths.
  5866. gen_bitlen(s);
  5867. // The field len is now set, we can generate the bit codes
  5868. gen_codes(tree, that.max_code, s.bl_count);
  5869. };
  5870. }
  5871. 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,
  5872. 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,
  5873. 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,
  5874. 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,
  5875. 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,
  5876. 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,
  5877. 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 ];
  5878. 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 ];
  5879. 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,
  5880. 24576 ];
  5881. // Mapping from a distance to a distance code. dist is the distance - 1 and
  5882. // must not have side effects. _dist_code[256] and _dist_code[257] are never
  5883. // used.
  5884. Tree.d_code = function(dist) {
  5885. return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >>> 7)]);
  5886. };
  5887. // extra bits for each length code
  5888. 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 ];
  5889. // extra bits for each distance code
  5890. 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 ];
  5891. // extra bits for each bit length code
  5892. Tree.extra_blbits = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 ];
  5893. Tree.bl_order = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
  5894. // StaticTree
  5895. function StaticTree(static_tree, extra_bits, extra_base, elems, max_length) {
  5896. var that = this;
  5897. that.static_tree = static_tree;
  5898. that.extra_bits = extra_bits;
  5899. that.extra_base = extra_base;
  5900. that.elems = elems;
  5901. that.max_length = max_length;
  5902. }
  5903. 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,
  5904. 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,
  5905. 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,
  5906. 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,
  5907. 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,
  5908. 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,
  5909. 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,
  5910. 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,
  5911. 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,
  5912. 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,
  5913. 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,
  5914. 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,
  5915. 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,
  5916. 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,
  5917. 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,
  5918. 99, 8, 227, 8 ];
  5919. 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,
  5920. 25, 5, 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5 ];
  5921. StaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
  5922. StaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS);
  5923. StaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
  5924. // Deflate
  5925. var MAX_MEM_LEVEL = 9;
  5926. var DEF_MEM_LEVEL = 8;
  5927. function Config(good_length, max_lazy, nice_length, max_chain, func) {
  5928. var that = this;
  5929. that.good_length = good_length;
  5930. that.max_lazy = max_lazy;
  5931. that.nice_length = nice_length;
  5932. that.max_chain = max_chain;
  5933. that.func = func;
  5934. }
  5935. var STORED = 0;
  5936. var FAST = 1;
  5937. var SLOW = 2;
  5938. 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),
  5939. 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),
  5940. new Config(32, 128, 258, 1024, SLOW), new Config(32, 258, 258, 4096, SLOW) ];
  5941. var z_errmsg = [ "need dictionary", // Z_NEED_DICT
  5942. // 2
  5943. "stream end", // Z_STREAM_END 1
  5944. "", // Z_OK 0
  5945. "", // Z_ERRNO (-1)
  5946. "stream error", // Z_STREAM_ERROR (-2)
  5947. "data error", // Z_DATA_ERROR (-3)
  5948. "", // Z_MEM_ERROR (-4)
  5949. "buffer error", // Z_BUF_ERROR (-5)
  5950. "",// Z_VERSION_ERROR (-6)
  5951. "" ];
  5952. // block not completed, need more input or more output
  5953. var NeedMore = 0;
  5954. // block flush performed
  5955. var BlockDone = 1;
  5956. // finish started, need only more output at next deflate
  5957. var FinishStarted = 2;
  5958. // finish done, accept no more input or output
  5959. var FinishDone = 3;
  5960. // preset dictionary flag in zlib header
  5961. var PRESET_DICT = 0x20;
  5962. var INIT_STATE = 42;
  5963. var BUSY_STATE = 113;
  5964. var FINISH_STATE = 666;
  5965. // The deflate compression method
  5966. var Z_DEFLATED = 8;
  5967. var STORED_BLOCK = 0;
  5968. var STATIC_TREES = 1;
  5969. var DYN_TREES = 2;
  5970. var MIN_MATCH = 3;
  5971. var MAX_MATCH = 258;
  5972. var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
  5973. function smaller(tree, n, m, depth) {
  5974. var tn2 = tree[n * 2];
  5975. var tm2 = tree[m * 2];
  5976. return (tn2 < tm2 || (tn2 == tm2 && depth[n] <= depth[m]));
  5977. }
  5978. function Deflate() {
  5979. var that = this;
  5980. var strm; // pointer back to this zlib stream
  5981. var status; // as the name implies
  5982. // pending_buf; // output still pending
  5983. var pending_buf_size; // size of pending_buf
  5984. // pending_out; // next pending byte to output to the stream
  5985. // pending; // nb of bytes in the pending buffer
  5986. var method; // STORED (for zip only) or DEFLATED
  5987. var last_flush; // value of flush param for previous deflate call
  5988. var w_size; // LZ77 window size (32K by default)
  5989. var w_bits; // log2(w_size) (8..16)
  5990. var w_mask; // w_size - 1
  5991. var window;
  5992. // Sliding window. Input bytes are read into the second half of the window,
  5993. // and move to the first half later to keep a dictionary of at least wSize
  5994. // bytes. With this organization, matches are limited to a distance of
  5995. // wSize-MAX_MATCH bytes, but this ensures that IO is always
  5996. // performed with a length multiple of the block size. Also, it limits
  5997. // the window size to 64K, which is quite useful on MSDOS.
  5998. // To do: use the user input buffer as sliding window.
  5999. var window_size;
  6000. // Actual size of window: 2*wSize, except when the user input buffer
  6001. // is directly used as sliding window.
  6002. var prev;
  6003. // Link to older string with same hash index. To limit the size of this
  6004. // array to 64K, this link is maintained only for the last 32K strings.
  6005. // An index in this array is thus a window index modulo 32K.
  6006. var head; // Heads of the hash chains or NIL.
  6007. var ins_h; // hash index of string to be inserted
  6008. var hash_size; // number of elements in hash table
  6009. var hash_bits; // log2(hash_size)
  6010. var hash_mask; // hash_size-1
  6011. // Number of bits by which ins_h must be shifted at each input
  6012. // step. It must be such that after MIN_MATCH steps, the oldest
  6013. // byte no longer takes part in the hash key, that is:
  6014. // hash_shift * MIN_MATCH >= hash_bits
  6015. var hash_shift;
  6016. // Window position at the beginning of the current output block. Gets
  6017. // negative when the window is moved backwards.
  6018. var block_start;
  6019. var match_length; // length of best match
  6020. var prev_match; // previous match
  6021. var match_available; // set if previous match exists
  6022. var strstart; // start of string to insert
  6023. var match_start; // start of matching string
  6024. var lookahead; // number of valid bytes ahead in window
  6025. // Length of the best match at previous step. Matches not greater than this
  6026. // are discarded. This is used in the lazy match evaluation.
  6027. var prev_length;
  6028. // To speed up deflation, hash chains are never searched beyond this
  6029. // length. A higher limit improves compression ratio but degrades the speed.
  6030. var max_chain_length;
  6031. // Attempt to find a better match only when the current match is strictly
  6032. // smaller than this value. This mechanism is used only for compression
  6033. // levels >= 4.
  6034. var max_lazy_match;
  6035. // Insert new strings in the hash table only if the match length is not
  6036. // greater than this length. This saves time but degrades compression.
  6037. // max_insert_length is used only for compression levels <= 3.
  6038. var level; // compression level (1..9)
  6039. var strategy; // favor or force Huffman coding
  6040. // Use a faster search when the previous match is longer than this
  6041. var good_match;
  6042. // Stop searching when current match exceeds this
  6043. var nice_match;
  6044. var dyn_ltree; // literal and length tree
  6045. var dyn_dtree; // distance tree
  6046. var bl_tree; // Huffman tree for bit lengths
  6047. var l_desc = new Tree(); // desc for literal tree
  6048. var d_desc = new Tree(); // desc for distance tree
  6049. var bl_desc = new Tree(); // desc for bit length tree
  6050. // that.heap_len; // number of elements in the heap
  6051. // that.heap_max; // element of largest frequency
  6052. // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
  6053. // The same heap array is used to build all trees.
  6054. // Depth of each subtree used as tie breaker for trees of equal frequency
  6055. that.depth = [];
  6056. var l_buf; // index for literals or lengths */
  6057. // Size of match buffer for literals/lengths. There are 4 reasons for
  6058. // limiting lit_bufsize to 64K:
  6059. // - frequencies can be kept in 16 bit counters
  6060. // - if compression is not successful for the first block, all input
  6061. // data is still in the window so we can still emit a stored block even
  6062. // when input comes from standard input. (This can also be done for
  6063. // all blocks if lit_bufsize is not greater than 32K.)
  6064. // - if compression is not successful for a file smaller than 64K, we can
  6065. // even emit a stored file instead of a stored block (saving 5 bytes).
  6066. // This is applicable only for zip (not gzip or zlib).
  6067. // - creating new Huffman trees less frequently may not provide fast
  6068. // adaptation to changes in the input data statistics. (Take for
  6069. // example a binary file with poorly compressible code followed by
  6070. // a highly compressible string table.) Smaller buffer sizes give
  6071. // fast adaptation but have of course the overhead of transmitting
  6072. // trees more frequently.
  6073. // - I can't count above 4
  6074. var lit_bufsize;
  6075. var last_lit; // running index in l_buf
  6076. // Buffer for distances. To simplify the code, d_buf and l_buf have
  6077. // the same number of elements. To use different lengths, an extra flag
  6078. // array would be necessary.
  6079. var d_buf; // index of pendig_buf
  6080. // that.opt_len; // bit length of current block with optimal trees
  6081. // that.static_len; // bit length of current block with static trees
  6082. var matches; // number of string matches in current block
  6083. var last_eob_len; // bit length of EOB code for last block
  6084. // Output buffer. bits are inserted starting at the bottom (least
  6085. // significant bits).
  6086. var bi_buf;
  6087. // Number of valid bits in bi_buf. All bits above the last valid bit
  6088. // are always zero.
  6089. var bi_valid;
  6090. // number of codes at each bit length for an optimal tree
  6091. that.bl_count = [];
  6092. // heap used to build the Huffman trees
  6093. that.heap = [];
  6094. dyn_ltree = [];
  6095. dyn_dtree = [];
  6096. bl_tree = [];
  6097. function lm_init() {
  6098. var i;
  6099. window_size = 2 * w_size;
  6100. head[hash_size - 1] = 0;
  6101. for (i = 0; i < hash_size - 1; i++) {
  6102. head[i] = 0;
  6103. }
  6104. // Set the default configuration parameters:
  6105. max_lazy_match = config_table[level].max_lazy;
  6106. good_match = config_table[level].good_length;
  6107. nice_match = config_table[level].nice_length;
  6108. max_chain_length = config_table[level].max_chain;
  6109. strstart = 0;
  6110. block_start = 0;
  6111. lookahead = 0;
  6112. match_length = prev_length = MIN_MATCH - 1;
  6113. match_available = 0;
  6114. ins_h = 0;
  6115. }
  6116. function init_block() {
  6117. var i;
  6118. // Initialize the trees.
  6119. for (i = 0; i < L_CODES; i++)
  6120. dyn_ltree[i * 2] = 0;
  6121. for (i = 0; i < D_CODES; i++)
  6122. dyn_dtree[i * 2] = 0;
  6123. for (i = 0; i < BL_CODES; i++)
  6124. bl_tree[i * 2] = 0;
  6125. dyn_ltree[END_BLOCK * 2] = 1;
  6126. that.opt_len = that.static_len = 0;
  6127. last_lit = matches = 0;
  6128. }
  6129. // Initialize the tree data structures for a new zlib stream.
  6130. function tr_init() {
  6131. l_desc.dyn_tree = dyn_ltree;
  6132. l_desc.stat_desc = StaticTree.static_l_desc;
  6133. d_desc.dyn_tree = dyn_dtree;
  6134. d_desc.stat_desc = StaticTree.static_d_desc;
  6135. bl_desc.dyn_tree = bl_tree;
  6136. bl_desc.stat_desc = StaticTree.static_bl_desc;
  6137. bi_buf = 0;
  6138. bi_valid = 0;
  6139. last_eob_len = 8; // enough lookahead for inflate
  6140. // Initialize the first block of the first file:
  6141. init_block();
  6142. }
  6143. // Restore the heap property by moving down the tree starting at node k,
  6144. // exchanging a node with the smallest of its two sons if necessary,
  6145. // stopping
  6146. // when the heap property is re-established (each father smaller than its
  6147. // two sons).
  6148. that.pqdownheap = function(tree, // the tree to restore
  6149. k // node to move down
  6150. ) {
  6151. var heap = that.heap;
  6152. var v = heap[k];
  6153. var j = k << 1; // left son of k
  6154. while (j <= that.heap_len) {
  6155. // Set j to the smallest of the two sons:
  6156. if (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) {
  6157. j++;
  6158. }
  6159. // Exit if v is smaller than both sons
  6160. if (smaller(tree, v, heap[j], that.depth))
  6161. break;
  6162. // Exchange v with the smallest son
  6163. heap[k] = heap[j];
  6164. k = j;
  6165. // And continue down the tree, setting j to the left son of k
  6166. j <<= 1;
  6167. }
  6168. heap[k] = v;
  6169. };
  6170. // Scan a literal or distance tree to determine the frequencies of the codes
  6171. // in the bit length tree.
  6172. function scan_tree(tree,// the tree to be scanned
  6173. max_code // and its largest code of non zero frequency
  6174. ) {
  6175. var n; // iterates over all tree elements
  6176. var prevlen = -1; // last emitted length
  6177. var curlen; // length of current code
  6178. var nextlen = tree[0 * 2 + 1]; // length of next code
  6179. var count = 0; // repeat count of the current code
  6180. var max_count = 7; // max repeat count
  6181. var min_count = 4; // min repeat count
  6182. if (nextlen === 0) {
  6183. max_count = 138;
  6184. min_count = 3;
  6185. }
  6186. tree[(max_code + 1) * 2 + 1] = 0xffff; // guard
  6187. for (n = 0; n <= max_code; n++) {
  6188. curlen = nextlen;
  6189. nextlen = tree[(n + 1) * 2 + 1];
  6190. if (++count < max_count && curlen == nextlen) {
  6191. continue;
  6192. } else if (count < min_count) {
  6193. bl_tree[curlen * 2] += count;
  6194. } else if (curlen !== 0) {
  6195. if (curlen != prevlen)
  6196. bl_tree[curlen * 2]++;
  6197. bl_tree[REP_3_6 * 2]++;
  6198. } else if (count <= 10) {
  6199. bl_tree[REPZ_3_10 * 2]++;
  6200. } else {
  6201. bl_tree[REPZ_11_138 * 2]++;
  6202. }
  6203. count = 0;
  6204. prevlen = curlen;
  6205. if (nextlen === 0) {
  6206. max_count = 138;
  6207. min_count = 3;
  6208. } else if (curlen == nextlen) {
  6209. max_count = 6;
  6210. min_count = 3;
  6211. } else {
  6212. max_count = 7;
  6213. min_count = 4;
  6214. }
  6215. }
  6216. }
  6217. // Construct the Huffman tree for the bit lengths and return the index in
  6218. // bl_order of the last bit length code to send.
  6219. function build_bl_tree() {
  6220. var max_blindex; // index of last bit length code of non zero freq
  6221. // Determine the bit length frequencies for literal and distance trees
  6222. scan_tree(dyn_ltree, l_desc.max_code);
  6223. scan_tree(dyn_dtree, d_desc.max_code);
  6224. // Build the bit length tree:
  6225. bl_desc.build_tree(that);
  6226. // opt_len now includes the length of the tree representations, except
  6227. // the lengths of the bit lengths codes and the 5+5+4 bits for the
  6228. // counts.
  6229. // Determine the number of bit length codes to send. The pkzip format
  6230. // requires that at least 4 bit length codes be sent. (appnote.txt says
  6231. // 3 but the actual value used is 4.)
  6232. for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
  6233. if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0)
  6234. break;
  6235. }
  6236. // Update opt_len to include the bit length tree and counts
  6237. that.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
  6238. return max_blindex;
  6239. }
  6240. // Output a byte on the stream.
  6241. // IN assertion: there is enough room in pending_buf.
  6242. function put_byte(p) {
  6243. that.pending_buf[that.pending++] = p;
  6244. }
  6245. function put_short(w) {
  6246. put_byte(w & 0xff);
  6247. put_byte((w >>> 8) & 0xff);
  6248. }
  6249. function putShortMSB(b) {
  6250. put_byte((b >> 8) & 0xff);
  6251. put_byte((b & 0xff) & 0xff);
  6252. }
  6253. function send_bits(value, length) {
  6254. var val, len = length;
  6255. if (bi_valid > Buf_size - len) {
  6256. val = value;
  6257. // bi_buf |= (val << bi_valid);
  6258. bi_buf |= ((val << bi_valid) & 0xffff);
  6259. put_short(bi_buf);
  6260. bi_buf = val >>> (Buf_size - bi_valid);
  6261. bi_valid += len - Buf_size;
  6262. } else {
  6263. // bi_buf |= (value) << bi_valid;
  6264. bi_buf |= (((value) << bi_valid) & 0xffff);
  6265. bi_valid += len;
  6266. }
  6267. }
  6268. function send_code(c, tree) {
  6269. var c2 = c * 2;
  6270. send_bits(tree[c2] & 0xffff, tree[c2 + 1] & 0xffff);
  6271. }
  6272. // Send a literal or distance tree in compressed form, using the codes in
  6273. // bl_tree.
  6274. function send_tree(tree,// the tree to be sent
  6275. max_code // and its largest code of non zero frequency
  6276. ) {
  6277. var n; // iterates over all tree elements
  6278. var prevlen = -1; // last emitted length
  6279. var curlen; // length of current code
  6280. var nextlen = tree[0 * 2 + 1]; // length of next code
  6281. var count = 0; // repeat count of the current code
  6282. var max_count = 7; // max repeat count
  6283. var min_count = 4; // min repeat count
  6284. if (nextlen === 0) {
  6285. max_count = 138;
  6286. min_count = 3;
  6287. }
  6288. for (n = 0; n <= max_code; n++) {
  6289. curlen = nextlen;
  6290. nextlen = tree[(n + 1) * 2 + 1];
  6291. if (++count < max_count && curlen == nextlen) {
  6292. continue;
  6293. } else if (count < min_count) {
  6294. do {
  6295. send_code(curlen, bl_tree);
  6296. } while (--count !== 0);
  6297. } else if (curlen !== 0) {
  6298. if (curlen != prevlen) {
  6299. send_code(curlen, bl_tree);
  6300. count--;
  6301. }
  6302. send_code(REP_3_6, bl_tree);
  6303. send_bits(count - 3, 2);
  6304. } else if (count <= 10) {
  6305. send_code(REPZ_3_10, bl_tree);
  6306. send_bits(count - 3, 3);
  6307. } else {
  6308. send_code(REPZ_11_138, bl_tree);
  6309. send_bits(count - 11, 7);
  6310. }
  6311. count = 0;
  6312. prevlen = curlen;
  6313. if (nextlen === 0) {
  6314. max_count = 138;
  6315. min_count = 3;
  6316. } else if (curlen == nextlen) {
  6317. max_count = 6;
  6318. min_count = 3;
  6319. } else {
  6320. max_count = 7;
  6321. min_count = 4;
  6322. }
  6323. }
  6324. }
  6325. // Send the header for a block using dynamic Huffman trees: the counts, the
  6326. // lengths of the bit length codes, the literal tree and the distance tree.
  6327. // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
  6328. function send_all_trees(lcodes, dcodes, blcodes) {
  6329. var rank; // index in bl_order
  6330. send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
  6331. send_bits(dcodes - 1, 5);
  6332. send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
  6333. for (rank = 0; rank < blcodes; rank++) {
  6334. send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3);
  6335. }
  6336. send_tree(dyn_ltree, lcodes - 1); // literal tree
  6337. send_tree(dyn_dtree, dcodes - 1); // distance tree
  6338. }
  6339. // Flush the bit buffer, keeping at most 7 bits in it.
  6340. function bi_flush() {
  6341. if (bi_valid == 16) {
  6342. put_short(bi_buf);
  6343. bi_buf = 0;
  6344. bi_valid = 0;
  6345. } else if (bi_valid >= 8) {
  6346. put_byte(bi_buf & 0xff);
  6347. bi_buf >>>= 8;
  6348. bi_valid -= 8;
  6349. }
  6350. }
  6351. // Send one empty static block to give enough lookahead for inflate.
  6352. // This takes 10 bits, of which 7 may remain in the bit buffer.
  6353. // The current inflate code requires 9 bits of lookahead. If the
  6354. // last two codes for the previous block (real code plus EOB) were coded
  6355. // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
  6356. // the last real code. In this case we send two empty static blocks instead
  6357. // of one. (There are no problems if the previous block is stored or fixed.)
  6358. // To simplify the code, we assume the worst case of last real code encoded
  6359. // on one bit only.
  6360. function _tr_align() {
  6361. send_bits(STATIC_TREES << 1, 3);
  6362. send_code(END_BLOCK, StaticTree.static_ltree);
  6363. bi_flush();
  6364. // Of the 10 bits for the empty block, we have already sent
  6365. // (10 - bi_valid) bits. The lookahead for the last real code (before
  6366. // the EOB of the previous block) was thus at least one plus the length
  6367. // of the EOB plus what we have just sent of the empty static block.
  6368. if (1 + last_eob_len + 10 - bi_valid < 9) {
  6369. send_bits(STATIC_TREES << 1, 3);
  6370. send_code(END_BLOCK, StaticTree.static_ltree);
  6371. bi_flush();
  6372. }
  6373. last_eob_len = 7;
  6374. }
  6375. // Save the match info and tally the frequency counts. Return true if
  6376. // the current block must be flushed.
  6377. function _tr_tally(dist, // distance of matched string
  6378. lc // match length-MIN_MATCH or unmatched char (if dist==0)
  6379. ) {
  6380. var out_length, in_length, dcode;
  6381. that.pending_buf[d_buf + last_lit * 2] = (dist >>> 8) & 0xff;
  6382. that.pending_buf[d_buf + last_lit * 2 + 1] = dist & 0xff;
  6383. that.pending_buf[l_buf + last_lit] = lc & 0xff;
  6384. last_lit++;
  6385. if (dist === 0) {
  6386. // lc is the unmatched char
  6387. dyn_ltree[lc * 2]++;
  6388. } else {
  6389. matches++;
  6390. // Here, lc is the match length - MIN_MATCH
  6391. dist--; // dist = match distance - 1
  6392. dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++;
  6393. dyn_dtree[Tree.d_code(dist) * 2]++;
  6394. }
  6395. if ((last_lit & 0x1fff) === 0 && level > 2) {
  6396. // Compute an upper bound for the compressed length
  6397. out_length = last_lit * 8;
  6398. in_length = strstart - block_start;
  6399. for (dcode = 0; dcode < D_CODES; dcode++) {
  6400. out_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]);
  6401. }
  6402. out_length >>>= 3;
  6403. if ((matches < Math.floor(last_lit / 2)) && out_length < Math.floor(in_length / 2))
  6404. return true;
  6405. }
  6406. return (last_lit == lit_bufsize - 1);
  6407. // We avoid equality with lit_bufsize because of wraparound at 64K
  6408. // on 16 bit machines and because stored blocks are restricted to
  6409. // 64K-1 bytes.
  6410. }
  6411. // Send the block data compressed using the given Huffman trees
  6412. function compress_block(ltree, dtree) {
  6413. var dist; // distance of matched string
  6414. var lc; // match length or unmatched char (if dist === 0)
  6415. var lx = 0; // running index in l_buf
  6416. var code; // the code to send
  6417. var extra; // number of extra bits to send
  6418. if (last_lit !== 0) {
  6419. do {
  6420. dist = ((that.pending_buf[d_buf + lx * 2] << 8) & 0xff00) | (that.pending_buf[d_buf + lx * 2 + 1] & 0xff);
  6421. lc = (that.pending_buf[l_buf + lx]) & 0xff;
  6422. lx++;
  6423. if (dist === 0) {
  6424. send_code(lc, ltree); // send a literal byte
  6425. } else {
  6426. // Here, lc is the match length - MIN_MATCH
  6427. code = Tree._length_code[lc];
  6428. send_code(code + LITERALS + 1, ltree); // send the length
  6429. // code
  6430. extra = Tree.extra_lbits[code];
  6431. if (extra !== 0) {
  6432. lc -= Tree.base_length[code];
  6433. send_bits(lc, extra); // send the extra length bits
  6434. }
  6435. dist--; // dist is now the match distance - 1
  6436. code = Tree.d_code(dist);
  6437. send_code(code, dtree); // send the distance code
  6438. extra = Tree.extra_dbits[code];
  6439. if (extra !== 0) {
  6440. dist -= Tree.base_dist[code];
  6441. send_bits(dist, extra); // send the extra distance bits
  6442. }
  6443. } // literal or match pair ?
  6444. // Check that the overlay between pending_buf and d_buf+l_buf is
  6445. // ok:
  6446. } while (lx < last_lit);
  6447. }
  6448. send_code(END_BLOCK, ltree);
  6449. last_eob_len = ltree[END_BLOCK * 2 + 1];
  6450. }
  6451. // Flush the bit buffer and align the output on a byte boundary
  6452. function bi_windup() {
  6453. if (bi_valid > 8) {
  6454. put_short(bi_buf);
  6455. } else if (bi_valid > 0) {
  6456. put_byte(bi_buf & 0xff);
  6457. }
  6458. bi_buf = 0;
  6459. bi_valid = 0;
  6460. }
  6461. // Copy a stored block, storing first the length and its
  6462. // one's complement if requested.
  6463. function copy_block(buf, // the input data
  6464. len, // its length
  6465. header // true if block header must be written
  6466. ) {
  6467. bi_windup(); // align on byte boundary
  6468. last_eob_len = 8; // enough lookahead for inflate
  6469. if (header) {
  6470. put_short(len);
  6471. put_short(~len);
  6472. }
  6473. that.pending_buf.set(window.subarray(buf, buf + len), that.pending);
  6474. that.pending += len;
  6475. }
  6476. // Send a stored block
  6477. function _tr_stored_block(buf, // input block
  6478. stored_len, // length of input block
  6479. eof // true if this is the last block for a file
  6480. ) {
  6481. send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
  6482. copy_block(buf, stored_len, true); // with header
  6483. }
  6484. // Determine the best encoding for the current block: dynamic trees, static
  6485. // trees or store, and output the encoded block to the zip file.
  6486. function _tr_flush_block(buf, // input block, or NULL if too old
  6487. stored_len, // length of input block
  6488. eof // true if this is the last block for a file
  6489. ) {
  6490. var opt_lenb, static_lenb;// opt_len and static_len in bytes
  6491. var max_blindex = 0; // index of last bit length code of non zero freq
  6492. // Build the Huffman trees unless a stored block is forced
  6493. if (level > 0) {
  6494. // Construct the literal and distance trees
  6495. l_desc.build_tree(that);
  6496. d_desc.build_tree(that);
  6497. // At this point, opt_len and static_len are the total bit lengths
  6498. // of
  6499. // the compressed block data, excluding the tree representations.
  6500. // Build the bit length tree for the above two trees, and get the
  6501. // index
  6502. // in bl_order of the last bit length code to send.
  6503. max_blindex = build_bl_tree();
  6504. // Determine the best encoding. Compute first the block length in
  6505. // bytes
  6506. opt_lenb = (that.opt_len + 3 + 7) >>> 3;
  6507. static_lenb = (that.static_len + 3 + 7) >>> 3;
  6508. if (static_lenb <= opt_lenb)
  6509. opt_lenb = static_lenb;
  6510. } else {
  6511. opt_lenb = static_lenb = stored_len + 5; // force a stored block
  6512. }
  6513. if ((stored_len + 4 <= opt_lenb) && buf != -1) {
  6514. // 4: two words for the lengths
  6515. // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
  6516. // Otherwise we can't have processed more than WSIZE input bytes
  6517. // since
  6518. // the last block flush, because compression would have been
  6519. // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
  6520. // transform a block into a stored block.
  6521. _tr_stored_block(buf, stored_len, eof);
  6522. } else if (static_lenb == opt_lenb) {
  6523. send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
  6524. compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
  6525. } else {
  6526. send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
  6527. send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1);
  6528. compress_block(dyn_ltree, dyn_dtree);
  6529. }
  6530. // The above check is made mod 2^32, for files larger than 512 MB
  6531. // and uLong implemented on 32 bits.
  6532. init_block();
  6533. if (eof) {
  6534. bi_windup();
  6535. }
  6536. }
  6537. function flush_block_only(eof) {
  6538. _tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof);
  6539. block_start = strstart;
  6540. strm.flush_pending();
  6541. }
  6542. // Fill the window when the lookahead becomes insufficient.
  6543. // Updates strstart and lookahead.
  6544. //
  6545. // IN assertion: lookahead < MIN_LOOKAHEAD
  6546. // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
  6547. // At least one byte has been read, or avail_in === 0; reads are
  6548. // performed for at least two bytes (required for the zip translate_eol
  6549. // option -- not supported here).
  6550. function fill_window() {
  6551. var n, m;
  6552. var p;
  6553. var more; // Amount of free space at the end of the window.
  6554. do {
  6555. more = (window_size - lookahead - strstart);
  6556. // Deal with !@#$% 64K limit:
  6557. if (more === 0 && strstart === 0 && lookahead === 0) {
  6558. more = w_size;
  6559. } else if (more == -1) {
  6560. // Very unlikely, but possible on 16 bit machine if strstart ==
  6561. // 0
  6562. // and lookahead == 1 (input done one byte at time)
  6563. more--;
  6564. // If the window is almost full and there is insufficient
  6565. // lookahead,
  6566. // move the upper half to the lower one to make room in the
  6567. // upper half.
  6568. } else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) {
  6569. window.set(window.subarray(w_size, w_size + w_size), 0);
  6570. match_start -= w_size;
  6571. strstart -= w_size; // we now have strstart >= MAX_DIST
  6572. block_start -= w_size;
  6573. // Slide the hash table (could be avoided with 32 bit values
  6574. // at the expense of memory usage). We slide even when level ==
  6575. // 0
  6576. // to keep the hash table consistent if we switch back to level
  6577. // > 0
  6578. // later. (Using level 0 permanently is not an optimal usage of
  6579. // zlib, so we don't care about this pathological case.)
  6580. n = hash_size;
  6581. p = n;
  6582. do {
  6583. m = (head[--p] & 0xffff);
  6584. head[p] = (m >= w_size ? m - w_size : 0);
  6585. } while (--n !== 0);
  6586. n = w_size;
  6587. p = n;
  6588. do {
  6589. m = (prev[--p] & 0xffff);
  6590. prev[p] = (m >= w_size ? m - w_size : 0);
  6591. // If n is not on any hash chain, prev[n] is garbage but
  6592. // its value will never be used.
  6593. } while (--n !== 0);
  6594. more += w_size;
  6595. }
  6596. if (strm.avail_in === 0)
  6597. return;
  6598. // If there was no sliding:
  6599. // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
  6600. // more == window_size - lookahead - strstart
  6601. // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
  6602. // => more >= window_size - 2*WSIZE + 2
  6603. // In the BIG_MEM or MMAP case (not yet supported),
  6604. // window_size == input_size + MIN_LOOKAHEAD &&
  6605. // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
  6606. // Otherwise, window_size == 2*WSIZE so more >= 2.
  6607. // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
  6608. n = strm.read_buf(window, strstart + lookahead, more);
  6609. lookahead += n;
  6610. // Initialize the hash value now that we have some input:
  6611. if (lookahead >= MIN_MATCH) {
  6612. ins_h = window[strstart] & 0xff;
  6613. ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
  6614. }
  6615. // If the whole input has less than MIN_MATCH bytes, ins_h is
  6616. // garbage,
  6617. // but this is not important since only literal bytes will be
  6618. // emitted.
  6619. } while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0);
  6620. }
  6621. // Copy without compression as much as possible from the input stream,
  6622. // return
  6623. // the current block state.
  6624. // This function does not insert new strings in the dictionary since
  6625. // uncompressible data is probably not useful. This function is used
  6626. // only for the level=0 compression option.
  6627. // NOTE: this function should be optimized to avoid extra copying from
  6628. // window to pending_buf.
  6629. function deflate_stored(flush) {
  6630. // Stored blocks are limited to 0xffff bytes, pending_buf is limited
  6631. // to pending_buf_size, and each stored block has a 5 byte header:
  6632. var max_block_size = 0xffff;
  6633. var max_start;
  6634. if (max_block_size > pending_buf_size - 5) {
  6635. max_block_size = pending_buf_size - 5;
  6636. }
  6637. // Copy as much as possible from input to output:
  6638. while (true) {
  6639. // Fill the window as much as possible:
  6640. if (lookahead <= 1) {
  6641. fill_window();
  6642. if (lookahead === 0 && flush == Z_NO_FLUSH)
  6643. return NeedMore;
  6644. if (lookahead === 0)
  6645. break; // flush the current block
  6646. }
  6647. strstart += lookahead;
  6648. lookahead = 0;
  6649. // Emit a stored block if pending_buf will be full:
  6650. max_start = block_start + max_block_size;
  6651. if (strstart === 0 || strstart >= max_start) {
  6652. // strstart === 0 is possible when wraparound on 16-bit machine
  6653. lookahead = (strstart - max_start);
  6654. strstart = max_start;
  6655. flush_block_only(false);
  6656. if (strm.avail_out === 0)
  6657. return NeedMore;
  6658. }
  6659. // Flush if we may have to slide, otherwise block_start may become
  6660. // negative and the data will be gone:
  6661. if (strstart - block_start >= w_size - MIN_LOOKAHEAD) {
  6662. flush_block_only(false);
  6663. if (strm.avail_out === 0)
  6664. return NeedMore;
  6665. }
  6666. }
  6667. flush_block_only(flush == Z_FINISH);
  6668. if (strm.avail_out === 0)
  6669. return (flush == Z_FINISH) ? FinishStarted : NeedMore;
  6670. return flush == Z_FINISH ? FinishDone : BlockDone;
  6671. }
  6672. function longest_match(cur_match) {
  6673. var chain_length = max_chain_length; // max hash chain length
  6674. var scan = strstart; // current string
  6675. var match; // matched string
  6676. var len; // length of current match
  6677. var best_len = prev_length; // best match length so far
  6678. var limit = strstart > (w_size - MIN_LOOKAHEAD) ? strstart - (w_size - MIN_LOOKAHEAD) : 0;
  6679. var _nice_match = nice_match;
  6680. // Stop when cur_match becomes <= limit. To simplify the code,
  6681. // we prevent matches with the string of window index 0.
  6682. var wmask = w_mask;
  6683. var strend = strstart + MAX_MATCH;
  6684. var scan_end1 = window[scan + best_len - 1];
  6685. var scan_end = window[scan + best_len];
  6686. // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of
  6687. // 16.
  6688. // It is easy to get rid of this optimization if necessary.
  6689. // Do not waste too much time if we already have a good match:
  6690. if (prev_length >= good_match) {
  6691. chain_length >>= 2;
  6692. }
  6693. // Do not look for matches beyond the end of the input. This is
  6694. // necessary
  6695. // to make deflate deterministic.
  6696. if (_nice_match > lookahead)
  6697. _nice_match = lookahead;
  6698. do {
  6699. match = cur_match;
  6700. // Skip to next match if the match length cannot increase
  6701. // or if the match length is less than 2:
  6702. if (window[match + best_len] != scan_end || window[match + best_len - 1] != scan_end1 || window[match] != window[scan]
  6703. || window[++match] != window[scan + 1])
  6704. continue;
  6705. // The check at best_len-1 can be removed because it will be made
  6706. // again later. (This heuristic is not always a win.)
  6707. // It is not necessary to compare scan[2] and match[2] since they
  6708. // are always equal when the other bytes match, given that
  6709. // the hash keys are equal and that HASH_BITS >= 8.
  6710. scan += 2;
  6711. match++;
  6712. // We check for insufficient lookahead only every 8th comparison;
  6713. // the 256th check will be made at strstart+258.
  6714. do {
  6715. } while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]
  6716. && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]
  6717. && window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend);
  6718. len = MAX_MATCH - (strend - scan);
  6719. scan = strend - MAX_MATCH;
  6720. if (len > best_len) {
  6721. match_start = cur_match;
  6722. best_len = len;
  6723. if (len >= _nice_match)
  6724. break;
  6725. scan_end1 = window[scan + best_len - 1];
  6726. scan_end = window[scan + best_len];
  6727. }
  6728. } while ((cur_match = (prev[cur_match & wmask] & 0xffff)) > limit && --chain_length !== 0);
  6729. if (best_len <= lookahead)
  6730. return best_len;
  6731. return lookahead;
  6732. }
  6733. // Compress as much as possible from the input stream, return the current
  6734. // block state.
  6735. // This function does not perform lazy evaluation of matches and inserts
  6736. // new strings in the dictionary only for unmatched strings or for short
  6737. // matches. It is used only for the fast compression options.
  6738. function deflate_fast(flush) {
  6739. // short hash_head = 0; // head of the hash chain
  6740. var hash_head = 0; // head of the hash chain
  6741. var bflush; // set if current block must be flushed
  6742. while (true) {
  6743. // Make sure that we always have enough lookahead, except
  6744. // at the end of the input file. We need MAX_MATCH bytes
  6745. // for the next match, plus MIN_MATCH bytes to insert the
  6746. // string following the next match.
  6747. if (lookahead < MIN_LOOKAHEAD) {
  6748. fill_window();
  6749. if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
  6750. return NeedMore;
  6751. }
  6752. if (lookahead === 0)
  6753. break; // flush the current block
  6754. }
  6755. // Insert the string window[strstart .. strstart+2] in the
  6756. // dictionary, and set hash_head to the head of the hash chain:
  6757. if (lookahead >= MIN_MATCH) {
  6758. ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
  6759. // prev[strstart&w_mask]=hash_head=head[ins_h];
  6760. hash_head = (head[ins_h] & 0xffff);
  6761. prev[strstart & w_mask] = head[ins_h];
  6762. head[ins_h] = strstart;
  6763. }
  6764. // Find the longest match, discarding those <= prev_length.
  6765. // At this point we have always match_length < MIN_MATCH
  6766. if (hash_head !== 0 && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {
  6767. // To simplify the code, we prevent matches with the string
  6768. // of window index 0 (in particular we have to avoid a match
  6769. // of the string with itself at the start of the input file).
  6770. if (strategy != Z_HUFFMAN_ONLY) {
  6771. match_length = longest_match(hash_head);
  6772. }
  6773. // longest_match() sets match_start
  6774. }
  6775. if (match_length >= MIN_MATCH) {
  6776. // check_match(strstart, match_start, match_length);
  6777. bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);
  6778. lookahead -= match_length;
  6779. // Insert new strings in the hash table only if the match length
  6780. // is not too large. This saves time but degrades compression.
  6781. if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) {
  6782. match_length--; // string at strstart already in hash table
  6783. do {
  6784. strstart++;
  6785. ins_h = ((ins_h << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
  6786. // prev[strstart&w_mask]=hash_head=head[ins_h];
  6787. hash_head = (head[ins_h] & 0xffff);
  6788. prev[strstart & w_mask] = head[ins_h];
  6789. head[ins_h] = strstart;
  6790. // strstart never exceeds WSIZE-MAX_MATCH, so there are
  6791. // always MIN_MATCH bytes ahead.
  6792. } while (--match_length !== 0);
  6793. strstart++;
  6794. } else {
  6795. strstart += match_length;
  6796. match_length = 0;
  6797. ins_h = window[strstart] & 0xff;
  6798. ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
  6799. // If lookahead < MIN_MATCH, ins_h is garbage, but it does
  6800. // not
  6801. // matter since it will be recomputed at next deflate call.
  6802. }
  6803. } else {
  6804. // No match, output a literal byte
  6805. bflush = _tr_tally(0, window[strstart] & 0xff);
  6806. lookahead--;
  6807. strstart++;
  6808. }
  6809. if (bflush) {
  6810. flush_block_only(false);
  6811. if (strm.avail_out === 0)
  6812. return NeedMore;
  6813. }
  6814. }
  6815. flush_block_only(flush == Z_FINISH);
  6816. if (strm.avail_out === 0) {
  6817. if (flush == Z_FINISH)
  6818. return FinishStarted;
  6819. else
  6820. return NeedMore;
  6821. }
  6822. return flush == Z_FINISH ? FinishDone : BlockDone;
  6823. }
  6824. // Same as above, but achieves better compression. We use a lazy
  6825. // evaluation for matches: a match is finally adopted only if there is
  6826. // no better match at the next window position.
  6827. function deflate_slow(flush) {
  6828. // short hash_head = 0; // head of hash chain
  6829. var hash_head = 0; // head of hash chain
  6830. var bflush; // set if current block must be flushed
  6831. var max_insert;
  6832. // Process the input block.
  6833. while (true) {
  6834. // Make sure that we always have enough lookahead, except
  6835. // at the end of the input file. We need MAX_MATCH bytes
  6836. // for the next match, plus MIN_MATCH bytes to insert the
  6837. // string following the next match.
  6838. if (lookahead < MIN_LOOKAHEAD) {
  6839. fill_window();
  6840. if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
  6841. return NeedMore;
  6842. }
  6843. if (lookahead === 0)
  6844. break; // flush the current block
  6845. }
  6846. // Insert the string window[strstart .. strstart+2] in the
  6847. // dictionary, and set hash_head to the head of the hash chain:
  6848. if (lookahead >= MIN_MATCH) {
  6849. ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
  6850. // prev[strstart&w_mask]=hash_head=head[ins_h];
  6851. hash_head = (head[ins_h] & 0xffff);
  6852. prev[strstart & w_mask] = head[ins_h];
  6853. head[ins_h] = strstart;
  6854. }
  6855. // Find the longest match, discarding those <= prev_length.
  6856. prev_length = match_length;
  6857. prev_match = match_start;
  6858. match_length = MIN_MATCH - 1;
  6859. if (hash_head !== 0 && prev_length < max_lazy_match && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {
  6860. // To simplify the code, we prevent matches with the string
  6861. // of window index 0 (in particular we have to avoid a match
  6862. // of the string with itself at the start of the input file).
  6863. if (strategy != Z_HUFFMAN_ONLY) {
  6864. match_length = longest_match(hash_head);
  6865. }
  6866. // longest_match() sets match_start
  6867. if (match_length <= 5 && (strategy == Z_FILTERED || (match_length == MIN_MATCH && strstart - match_start > 4096))) {
  6868. // If prev_match is also MIN_MATCH, match_start is garbage
  6869. // but we will ignore the current match anyway.
  6870. match_length = MIN_MATCH - 1;
  6871. }
  6872. }
  6873. // If there was a match at the previous step and the current
  6874. // match is not better, output the previous match:
  6875. if (prev_length >= MIN_MATCH && match_length <= prev_length) {
  6876. max_insert = strstart + lookahead - MIN_MATCH;
  6877. // Do not insert strings in hash table beyond this.
  6878. // check_match(strstart-1, prev_match, prev_length);
  6879. bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
  6880. // Insert in hash table all strings up to the end of the match.
  6881. // strstart-1 and strstart are already inserted. If there is not
  6882. // enough lookahead, the last two strings are not inserted in
  6883. // the hash table.
  6884. lookahead -= prev_length - 1;
  6885. prev_length -= 2;
  6886. do {
  6887. if (++strstart <= max_insert) {
  6888. ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
  6889. // prev[strstart&w_mask]=hash_head=head[ins_h];
  6890. hash_head = (head[ins_h] & 0xffff);
  6891. prev[strstart & w_mask] = head[ins_h];
  6892. head[ins_h] = strstart;
  6893. }
  6894. } while (--prev_length !== 0);
  6895. match_available = 0;
  6896. match_length = MIN_MATCH - 1;
  6897. strstart++;
  6898. if (bflush) {
  6899. flush_block_only(false);
  6900. if (strm.avail_out === 0)
  6901. return NeedMore;
  6902. }
  6903. } else if (match_available !== 0) {
  6904. // If there was no match at the previous position, output a
  6905. // single literal. If there was a match but the current match
  6906. // is longer, truncate the previous match to a single literal.
  6907. bflush = _tr_tally(0, window[strstart - 1] & 0xff);
  6908. if (bflush) {
  6909. flush_block_only(false);
  6910. }
  6911. strstart++;
  6912. lookahead--;
  6913. if (strm.avail_out === 0)
  6914. return NeedMore;
  6915. } else {
  6916. // There is no previous match to compare with, wait for
  6917. // the next step to decide.
  6918. match_available = 1;
  6919. strstart++;
  6920. lookahead--;
  6921. }
  6922. }
  6923. if (match_available !== 0) {
  6924. bflush = _tr_tally(0, window[strstart - 1] & 0xff);
  6925. match_available = 0;
  6926. }
  6927. flush_block_only(flush == Z_FINISH);
  6928. if (strm.avail_out === 0) {
  6929. if (flush == Z_FINISH)
  6930. return FinishStarted;
  6931. else
  6932. return NeedMore;
  6933. }
  6934. return flush == Z_FINISH ? FinishDone : BlockDone;
  6935. }
  6936. function deflateReset(strm) {
  6937. strm.total_in = strm.total_out = 0;
  6938. strm.msg = null; //
  6939. that.pending = 0;
  6940. that.pending_out = 0;
  6941. status = BUSY_STATE;
  6942. last_flush = Z_NO_FLUSH;
  6943. tr_init();
  6944. lm_init();
  6945. return Z_OK;
  6946. }
  6947. that.deflateInit = function(strm, _level, bits, _method, memLevel, _strategy) {
  6948. if (!_method)
  6949. _method = Z_DEFLATED;
  6950. if (!memLevel)
  6951. memLevel = DEF_MEM_LEVEL;
  6952. if (!_strategy)
  6953. _strategy = Z_DEFAULT_STRATEGY;
  6954. // byte[] my_version=ZLIB_VERSION;
  6955. //
  6956. // if (!version || version[0] != my_version[0]
  6957. // || stream_size != sizeof(z_stream)) {
  6958. // return Z_VERSION_ERROR;
  6959. // }
  6960. strm.msg = null;
  6961. if (_level == Z_DEFAULT_COMPRESSION)
  6962. _level = 6;
  6963. if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0
  6964. || _strategy > Z_HUFFMAN_ONLY) {
  6965. return Z_STREAM_ERROR;
  6966. }
  6967. strm.dstate = that;
  6968. w_bits = bits;
  6969. w_size = 1 << w_bits;
  6970. w_mask = w_size - 1;
  6971. hash_bits = memLevel + 7;
  6972. hash_size = 1 << hash_bits;
  6973. hash_mask = hash_size - 1;
  6974. hash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH);
  6975. window = new Uint8Array(w_size * 2);
  6976. prev = [];
  6977. head = [];
  6978. lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
  6979. // We overlay pending_buf and d_buf+l_buf. This works since the average
  6980. // output size for (length,distance) codes is <= 24 bits.
  6981. that.pending_buf = new Uint8Array(lit_bufsize * 4);
  6982. pending_buf_size = lit_bufsize * 4;
  6983. d_buf = Math.floor(lit_bufsize / 2);
  6984. l_buf = (1 + 2) * lit_bufsize;
  6985. level = _level;
  6986. strategy = _strategy;
  6987. method = _method & 0xff;
  6988. return deflateReset(strm);
  6989. };
  6990. that.deflateEnd = function() {
  6991. if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) {
  6992. return Z_STREAM_ERROR;
  6993. }
  6994. // Deallocate in reverse order of allocations:
  6995. that.pending_buf = null;
  6996. head = null;
  6997. prev = null;
  6998. window = null;
  6999. // free
  7000. that.dstate = null;
  7001. return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
  7002. };
  7003. that.deflateParams = function(strm, _level, _strategy) {
  7004. var err = Z_OK;
  7005. if (_level == Z_DEFAULT_COMPRESSION) {
  7006. _level = 6;
  7007. }
  7008. if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
  7009. return Z_STREAM_ERROR;
  7010. }
  7011. if (config_table[level].func != config_table[_level].func && strm.total_in !== 0) {
  7012. // Flush the last buffer:
  7013. err = strm.deflate(Z_PARTIAL_FLUSH);
  7014. }
  7015. if (level != _level) {
  7016. level = _level;
  7017. max_lazy_match = config_table[level].max_lazy;
  7018. good_match = config_table[level].good_length;
  7019. nice_match = config_table[level].nice_length;
  7020. max_chain_length = config_table[level].max_chain;
  7021. }
  7022. strategy = _strategy;
  7023. return err;
  7024. };
  7025. that.deflateSetDictionary = function(strm, dictionary, dictLength) {
  7026. var length = dictLength;
  7027. var n, index = 0;
  7028. if (!dictionary || status != INIT_STATE)
  7029. return Z_STREAM_ERROR;
  7030. if (length < MIN_MATCH)
  7031. return Z_OK;
  7032. if (length > w_size - MIN_LOOKAHEAD) {
  7033. length = w_size - MIN_LOOKAHEAD;
  7034. index = dictLength - length; // use the tail of the dictionary
  7035. }
  7036. window.set(dictionary.subarray(index, index + length), 0);
  7037. strstart = length;
  7038. block_start = length;
  7039. // Insert all strings in the hash table (except for the last two bytes).
  7040. // s->lookahead stays null, so s->ins_h will be recomputed at the next
  7041. // call of fill_window.
  7042. ins_h = window[0] & 0xff;
  7043. ins_h = (((ins_h) << hash_shift) ^ (window[1] & 0xff)) & hash_mask;
  7044. for (n = 0; n <= length - MIN_MATCH; n++) {
  7045. ins_h = (((ins_h) << hash_shift) ^ (window[(n) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
  7046. prev[n & w_mask] = head[ins_h];
  7047. head[ins_h] = n;
  7048. }
  7049. return Z_OK;
  7050. };
  7051. that.deflate = function(_strm, flush) {
  7052. var i, header, level_flags, old_flush, bstate;
  7053. if (flush > Z_FINISH || flush < 0) {
  7054. return Z_STREAM_ERROR;
  7055. }
  7056. if (!_strm.next_out || (!_strm.next_in && _strm.avail_in !== 0) || (status == FINISH_STATE && flush != Z_FINISH)) {
  7057. _strm.msg = z_errmsg[Z_NEED_DICT - (Z_STREAM_ERROR)];
  7058. return Z_STREAM_ERROR;
  7059. }
  7060. if (_strm.avail_out === 0) {
  7061. _strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
  7062. return Z_BUF_ERROR;
  7063. }
  7064. strm = _strm; // just in case
  7065. old_flush = last_flush;
  7066. last_flush = flush;
  7067. // Write the zlib header
  7068. if (status == INIT_STATE) {
  7069. header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8;
  7070. level_flags = ((level - 1) & 0xff) >> 1;
  7071. if (level_flags > 3)
  7072. level_flags = 3;
  7073. header |= (level_flags << 6);
  7074. if (strstart !== 0)
  7075. header |= PRESET_DICT;
  7076. header += 31 - (header % 31);
  7077. status = BUSY_STATE;
  7078. putShortMSB(header);
  7079. }
  7080. // Flush as much pending output as possible
  7081. if (that.pending !== 0) {
  7082. strm.flush_pending();
  7083. if (strm.avail_out === 0) {
  7084. // console.log(" avail_out==0");
  7085. // Since avail_out is 0, deflate will be called again with
  7086. // more output space, but possibly with both pending and
  7087. // avail_in equal to zero. There won't be anything to do,
  7088. // but this is not an error situation so make sure we
  7089. // return OK instead of BUF_ERROR at next call of deflate:
  7090. last_flush = -1;
  7091. return Z_OK;
  7092. }
  7093. // Make sure there is something to do and avoid duplicate
  7094. // consecutive
  7095. // flushes. For repeated and useless calls with Z_FINISH, we keep
  7096. // returning Z_STREAM_END instead of Z_BUFF_ERROR.
  7097. } else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) {
  7098. strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
  7099. return Z_BUF_ERROR;
  7100. }
  7101. // User must not provide more input after the first FINISH:
  7102. if (status == FINISH_STATE && strm.avail_in !== 0) {
  7103. _strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
  7104. return Z_BUF_ERROR;
  7105. }
  7106. // Start a new block or continue the current one.
  7107. if (strm.avail_in !== 0 || lookahead !== 0 || (flush != Z_NO_FLUSH && status != FINISH_STATE)) {
  7108. bstate = -1;
  7109. switch (config_table[level].func) {
  7110. case STORED:
  7111. bstate = deflate_stored(flush);
  7112. break;
  7113. case FAST:
  7114. bstate = deflate_fast(flush);
  7115. break;
  7116. case SLOW:
  7117. bstate = deflate_slow(flush);
  7118. break;
  7119. default:
  7120. }
  7121. if (bstate == FinishStarted || bstate == FinishDone) {
  7122. status = FINISH_STATE;
  7123. }
  7124. if (bstate == NeedMore || bstate == FinishStarted) {
  7125. if (strm.avail_out === 0) {
  7126. last_flush = -1; // avoid BUF_ERROR next call, see above
  7127. }
  7128. return Z_OK;
  7129. // If flush != Z_NO_FLUSH && avail_out === 0, the next call
  7130. // of deflate should use the same flush parameter to make sure
  7131. // that the flush is complete. So we don't have to output an
  7132. // empty block here, this will be done at next call. This also
  7133. // ensures that for a very small output buffer, we emit at most
  7134. // one empty block.
  7135. }
  7136. if (bstate == BlockDone) {
  7137. if (flush == Z_PARTIAL_FLUSH) {
  7138. _tr_align();
  7139. } else { // FULL_FLUSH or SYNC_FLUSH
  7140. _tr_stored_block(0, 0, false);
  7141. // For a full flush, this empty block will be recognized
  7142. // as a special marker by inflate_sync().
  7143. if (flush == Z_FULL_FLUSH) {
  7144. // state.head[s.hash_size-1]=0;
  7145. for (i = 0; i < hash_size/*-1*/; i++)
  7146. // forget history
  7147. head[i] = 0;
  7148. }
  7149. }
  7150. strm.flush_pending();
  7151. if (strm.avail_out === 0) {
  7152. last_flush = -1; // avoid BUF_ERROR at next call, see above
  7153. return Z_OK;
  7154. }
  7155. }
  7156. }
  7157. if (flush != Z_FINISH)
  7158. return Z_OK;
  7159. return Z_STREAM_END;
  7160. };
  7161. }
  7162. // ZStream
  7163. function ZStream() {
  7164. var that = this;
  7165. that.next_in_index = 0;
  7166. that.next_out_index = 0;
  7167. // that.next_in; // next input byte
  7168. that.avail_in = 0; // number of bytes available at next_in
  7169. that.total_in = 0; // total nb of input bytes read so far
  7170. // that.next_out; // next output byte should be put there
  7171. that.avail_out = 0; // remaining free space at next_out
  7172. that.total_out = 0; // total nb of bytes output so far
  7173. // that.msg;
  7174. // that.dstate;
  7175. }
  7176. ZStream.prototype = {
  7177. deflateInit : function(level, bits) {
  7178. var that = this;
  7179. that.dstate = new Deflate();
  7180. if (!bits)
  7181. bits = MAX_BITS;
  7182. return that.dstate.deflateInit(that, level, bits);
  7183. },
  7184. deflate : function(flush) {
  7185. var that = this;
  7186. if (!that.dstate) {
  7187. return Z_STREAM_ERROR;
  7188. }
  7189. return that.dstate.deflate(that, flush);
  7190. },
  7191. deflateEnd : function() {
  7192. var that = this;
  7193. if (!that.dstate)
  7194. return Z_STREAM_ERROR;
  7195. var ret = that.dstate.deflateEnd();
  7196. that.dstate = null;
  7197. return ret;
  7198. },
  7199. deflateParams : function(level, strategy) {
  7200. var that = this;
  7201. if (!that.dstate)
  7202. return Z_STREAM_ERROR;
  7203. return that.dstate.deflateParams(that, level, strategy);
  7204. },
  7205. deflateSetDictionary : function(dictionary, dictLength) {
  7206. var that = this;
  7207. if (!that.dstate)
  7208. return Z_STREAM_ERROR;
  7209. return that.dstate.deflateSetDictionary(that, dictionary, dictLength);
  7210. },
  7211. // Read a new buffer from the current input stream, update the
  7212. // total number of bytes read. All deflate() input goes through
  7213. // this function so some applications may wish to modify it to avoid
  7214. // allocating a large strm->next_in buffer and copying from it.
  7215. // (See also flush_pending()).
  7216. read_buf : function(buf, start, size) {
  7217. var that = this;
  7218. var len = that.avail_in;
  7219. if (len > size)
  7220. len = size;
  7221. if (len === 0)
  7222. return 0;
  7223. that.avail_in -= len;
  7224. buf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start);
  7225. that.next_in_index += len;
  7226. that.total_in += len;
  7227. return len;
  7228. },
  7229. // Flush as much pending output as possible. All deflate() output goes
  7230. // through this function so some applications may wish to modify it
  7231. // to avoid allocating a large strm->next_out buffer and copying into it.
  7232. // (See also read_buf()).
  7233. flush_pending : function() {
  7234. var that = this;
  7235. var len = that.dstate.pending;
  7236. if (len > that.avail_out)
  7237. len = that.avail_out;
  7238. if (len === 0)
  7239. return;
  7240. // if (that.dstate.pending_buf.length <= that.dstate.pending_out || that.next_out.length <= that.next_out_index
  7241. // || that.dstate.pending_buf.length < (that.dstate.pending_out + len) || that.next_out.length < (that.next_out_index +
  7242. // len)) {
  7243. // console.log(that.dstate.pending_buf.length + ", " + that.dstate.pending_out + ", " + that.next_out.length + ", " +
  7244. // that.next_out_index + ", " + len);
  7245. // console.log("avail_out=" + that.avail_out);
  7246. // }
  7247. that.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index);
  7248. that.next_out_index += len;
  7249. that.dstate.pending_out += len;
  7250. that.total_out += len;
  7251. that.avail_out -= len;
  7252. that.dstate.pending -= len;
  7253. if (that.dstate.pending === 0) {
  7254. that.dstate.pending_out = 0;
  7255. }
  7256. }
  7257. };
  7258. // Deflater
  7259. return function Deflater(level) {
  7260. var that = this;
  7261. var z = new ZStream();
  7262. var bufsize = 512;
  7263. var flush = Z_NO_FLUSH;
  7264. var buf = new Uint8Array(bufsize);
  7265. if (typeof level == "undefined")
  7266. level = Z_DEFAULT_COMPRESSION;
  7267. z.deflateInit(level);
  7268. z.next_out = buf;
  7269. that.append = function(data, onprogress) {
  7270. var err, buffers = [], lastIndex = 0, bufferIndex = 0, bufferSize = 0, array;
  7271. if (!data.length)
  7272. return;
  7273. z.next_in_index = 0;
  7274. z.next_in = data;
  7275. z.avail_in = data.length;
  7276. do {
  7277. z.next_out_index = 0;
  7278. z.avail_out = bufsize;
  7279. err = z.deflate(flush);
  7280. if (err != Z_OK)
  7281. throw "deflating: " + z.msg;
  7282. if (z.next_out_index)
  7283. if (z.next_out_index == bufsize)
  7284. buffers.push(new Uint8Array(buf));
  7285. else
  7286. buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
  7287. bufferSize += z.next_out_index;
  7288. if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
  7289. onprogress(z.next_in_index);
  7290. lastIndex = z.next_in_index;
  7291. }
  7292. } while (z.avail_in > 0 || z.avail_out === 0);
  7293. array = new Uint8Array(bufferSize);
  7294. buffers.forEach(function(chunk) {
  7295. array.set(chunk, bufferIndex);
  7296. bufferIndex += chunk.length;
  7297. });
  7298. return array;
  7299. };
  7300. that.flush = function() {
  7301. var err, buffers = [], bufferIndex = 0, bufferSize = 0, array;
  7302. do {
  7303. z.next_out_index = 0;
  7304. z.avail_out = bufsize;
  7305. err = z.deflate(Z_FINISH);
  7306. if (err != Z_STREAM_END && err != Z_OK)
  7307. throw "deflating: " + z.msg;
  7308. if (bufsize - z.avail_out > 0)
  7309. buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
  7310. bufferSize += z.next_out_index;
  7311. } while (z.avail_in > 0 || z.avail_out === 0);
  7312. z.deflateEnd();
  7313. array = new Uint8Array(bufferSize);
  7314. buffers.forEach(function(chunk) {
  7315. array.set(chunk, bufferIndex);
  7316. bufferIndex += chunk.length;
  7317. });
  7318. return array;
  7319. };
  7320. };
  7321. })(this);
  7322. // Generated by CoffeeScript 1.4.0
  7323. /*
  7324. # PNG.js
  7325. # Copyright (c) 2011 Devon Govett
  7326. # MIT LICENSE
  7327. #
  7328. # Permission is hereby granted, free of charge, to any person obtaining a copy of this
  7329. # software and associated documentation files (the "Software"), to deal in the Software
  7330. # without restriction, including without limitation the rights to use, copy, modify, merge,
  7331. # publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  7332. # to whom the Software is furnished to do so, subject to the following conditions:
  7333. #
  7334. # The above copyright notice and this permission notice shall be included in all copies or
  7335. # substantial portions of the Software.
  7336. #
  7337. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
  7338. # BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  7339. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  7340. # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  7341. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  7342. */
  7343. (function(global) {
  7344. var PNG;
  7345. PNG = (function() {
  7346. var APNG_BLEND_OP_OVER, APNG_BLEND_OP_SOURCE, APNG_DISPOSE_OP_BACKGROUND, APNG_DISPOSE_OP_NONE, APNG_DISPOSE_OP_PREVIOUS, makeImage, scratchCanvas, scratchCtx;
  7347. PNG.load = function(url, canvas, callback) {
  7348. var xhr,
  7349. _this = this;
  7350. if (typeof canvas === 'function') {
  7351. callback = canvas;
  7352. }
  7353. xhr = new XMLHttpRequest;
  7354. xhr.open("GET", url, true);
  7355. xhr.responseType = "arraybuffer";
  7356. xhr.onload = function() {
  7357. var data, png;
  7358. data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
  7359. png = new PNG(data);
  7360. if (typeof (canvas != null ? canvas.getContext : void 0) === 'function') {
  7361. png.render(canvas);
  7362. }
  7363. return typeof callback === "function" ? callback(png) : void 0;
  7364. };
  7365. return xhr.send(null);
  7366. };
  7367. APNG_DISPOSE_OP_NONE = 0;
  7368. APNG_DISPOSE_OP_BACKGROUND = 1;
  7369. APNG_DISPOSE_OP_PREVIOUS = 2;
  7370. APNG_BLEND_OP_SOURCE = 0;
  7371. APNG_BLEND_OP_OVER = 1;
  7372. function PNG(data) {
  7373. var chunkSize, colors, palLen, delayDen, delayNum, frame, i, index, key, section, palShort, text, _i, _j, _ref;
  7374. this.data = data;
  7375. this.pos = 8;
  7376. this.palette = [];
  7377. this.imgData = [];
  7378. this.transparency = {};
  7379. this.animation = null;
  7380. this.text = {};
  7381. frame = null;
  7382. while (true) {
  7383. chunkSize = this.readUInt32();
  7384. section = ((function() {
  7385. var _i, _results;
  7386. _results = [];
  7387. for (i = _i = 0; _i < 4; i = ++_i) {
  7388. _results.push(String.fromCharCode(this.data[this.pos++]));
  7389. }
  7390. return _results;
  7391. }).call(this)).join('');
  7392. switch (section) {
  7393. case 'IHDR':
  7394. this.width = this.readUInt32();
  7395. this.height = this.readUInt32();
  7396. this.bits = this.data[this.pos++];
  7397. this.colorType = this.data[this.pos++];
  7398. this.compressionMethod = this.data[this.pos++];
  7399. this.filterMethod = this.data[this.pos++];
  7400. this.interlaceMethod = this.data[this.pos++];
  7401. break;
  7402. case 'acTL':
  7403. this.animation = {
  7404. numFrames: this.readUInt32(),
  7405. numPlays: this.readUInt32() || Infinity,
  7406. frames: []
  7407. };
  7408. break;
  7409. case 'PLTE':
  7410. this.palette = this.read(chunkSize);
  7411. break;
  7412. case 'fcTL':
  7413. if (frame) {
  7414. this.animation.frames.push(frame);
  7415. }
  7416. this.pos += 4;
  7417. frame = {
  7418. width: this.readUInt32(),
  7419. height: this.readUInt32(),
  7420. xOffset: this.readUInt32(),
  7421. yOffset: this.readUInt32()
  7422. };
  7423. delayNum = this.readUInt16();
  7424. delayDen = this.readUInt16() || 100;
  7425. frame.delay = 1000 * delayNum / delayDen;
  7426. frame.disposeOp = this.data[this.pos++];
  7427. frame.blendOp = this.data[this.pos++];
  7428. frame.data = [];
  7429. break;
  7430. case 'IDAT':
  7431. case 'fdAT':
  7432. if (section === 'fdAT') {
  7433. this.pos += 4;
  7434. chunkSize -= 4;
  7435. }
  7436. data = (frame != null ? frame.data : void 0) || this.imgData;
  7437. for (i = _i = 0; 0 <= chunkSize ? _i < chunkSize : _i > chunkSize; i = 0 <= chunkSize ? ++_i : --_i) {
  7438. data.push(this.data[this.pos++]);
  7439. }
  7440. break;
  7441. case 'tRNS':
  7442. this.transparency = {};
  7443. switch (this.colorType) {
  7444. case 3:
  7445. palLen = this.palette.length/3;
  7446. this.transparency.indexed = this.read(chunkSize);
  7447. if(this.transparency.indexed.length > palLen)
  7448. throw new Error('More transparent colors than palette size');
  7449. /*
  7450. * According to the PNG spec trns should be increased to the same size as palette if shorter
  7451. */
  7452. //palShort = 255 - this.transparency.indexed.length;
  7453. palShort = palLen - this.transparency.indexed.length;
  7454. if (palShort > 0) {
  7455. for (i = _j = 0; 0 <= palShort ? _j < palShort : _j > palShort; i = 0 <= palShort ? ++_j : --_j) {
  7456. this.transparency.indexed.push(255);
  7457. }
  7458. }
  7459. break;
  7460. case 0:
  7461. this.transparency.grayscale = this.read(chunkSize)[0];
  7462. break;
  7463. case 2:
  7464. this.transparency.rgb = this.read(chunkSize);
  7465. }
  7466. break;
  7467. case 'tEXt':
  7468. text = this.read(chunkSize);
  7469. index = text.indexOf(0);
  7470. key = String.fromCharCode.apply(String, text.slice(0, index));
  7471. this.text[key] = String.fromCharCode.apply(String, text.slice(index + 1));
  7472. break;
  7473. case 'IEND':
  7474. if (frame) {
  7475. this.animation.frames.push(frame);
  7476. }
  7477. this.colors = (function() {
  7478. switch (this.colorType) {
  7479. case 0:
  7480. case 3:
  7481. case 4:
  7482. return 1;
  7483. case 2:
  7484. case 6:
  7485. return 3;
  7486. }
  7487. }).call(this);
  7488. this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6;
  7489. colors = this.colors + (this.hasAlphaChannel ? 1 : 0);
  7490. this.pixelBitlength = this.bits * colors;
  7491. this.colorSpace = (function() {
  7492. switch (this.colors) {
  7493. case 1:
  7494. return 'DeviceGray';
  7495. case 3:
  7496. return 'DeviceRGB';
  7497. }
  7498. }).call(this);
  7499. this.imgData = new Uint8Array(this.imgData);
  7500. return;
  7501. default:
  7502. this.pos += chunkSize;
  7503. }
  7504. this.pos += 4;
  7505. if (this.pos > this.data.length) {
  7506. throw new Error("Incomplete or corrupt PNG file");
  7507. }
  7508. }
  7509. return;
  7510. }
  7511. PNG.prototype.read = function(bytes) {
  7512. var i, _i, _results;
  7513. _results = [];
  7514. for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) {
  7515. _results.push(this.data[this.pos++]);
  7516. }
  7517. return _results;
  7518. };
  7519. PNG.prototype.readUInt32 = function() {
  7520. var b1, b2, b3, b4;
  7521. b1 = this.data[this.pos++] << 24;
  7522. b2 = this.data[this.pos++] << 16;
  7523. b3 = this.data[this.pos++] << 8;
  7524. b4 = this.data[this.pos++];
  7525. return b1 | b2 | b3 | b4;
  7526. };
  7527. PNG.prototype.readUInt16 = function() {
  7528. var b1, b2;
  7529. b1 = this.data[this.pos++] << 8;
  7530. b2 = this.data[this.pos++];
  7531. return b1 | b2;
  7532. };
  7533. PNG.prototype.decodePixels = function(data) {
  7534. var abyte, c, col, i, left, length, p, pa, paeth, pb, pc, pixelBytes, pixels, pos, row, scanlineLength, upper, upperLeft, _i, _j, _k, _l, _m;
  7535. if (data == null) {
  7536. data = this.imgData;
  7537. }
  7538. if (data.length === 0) {
  7539. return new Uint8Array(0);
  7540. }
  7541. data = new FlateStream(data);
  7542. data = data.getBytes();
  7543. pixelBytes = this.pixelBitlength / 8;
  7544. scanlineLength = pixelBytes * this.width;
  7545. pixels = new Uint8Array(scanlineLength * this.height);
  7546. length = data.length;
  7547. row = 0;
  7548. pos = 0;
  7549. c = 0;
  7550. while (pos < length) {
  7551. switch (data[pos++]) {
  7552. case 0:
  7553. for (i = _i = 0; _i < scanlineLength; i = _i += 1) {
  7554. pixels[c++] = data[pos++];
  7555. }
  7556. break;
  7557. case 1:
  7558. for (i = _j = 0; _j < scanlineLength; i = _j += 1) {
  7559. abyte = data[pos++];
  7560. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  7561. pixels[c++] = (abyte + left) % 256;
  7562. }
  7563. break;
  7564. case 2:
  7565. for (i = _k = 0; _k < scanlineLength; i = _k += 1) {
  7566. abyte = data[pos++];
  7567. col = (i - (i % pixelBytes)) / pixelBytes;
  7568. upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
  7569. pixels[c++] = (upper + abyte) % 256;
  7570. }
  7571. break;
  7572. case 3:
  7573. for (i = _l = 0; _l < scanlineLength; i = _l += 1) {
  7574. abyte = data[pos++];
  7575. col = (i - (i % pixelBytes)) / pixelBytes;
  7576. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  7577. upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
  7578. pixels[c++] = (abyte + Math.floor((left + upper) / 2)) % 256;
  7579. }
  7580. break;
  7581. case 4:
  7582. for (i = _m = 0; _m < scanlineLength; i = _m += 1) {
  7583. abyte = data[pos++];
  7584. col = (i - (i % pixelBytes)) / pixelBytes;
  7585. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  7586. if (row === 0) {
  7587. upper = upperLeft = 0;
  7588. } else {
  7589. upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
  7590. upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + (i % pixelBytes)];
  7591. }
  7592. p = left + upper - upperLeft;
  7593. pa = Math.abs(p - left);
  7594. pb = Math.abs(p - upper);
  7595. pc = Math.abs(p - upperLeft);
  7596. if (pa <= pb && pa <= pc) {
  7597. paeth = left;
  7598. } else if (pb <= pc) {
  7599. paeth = upper;
  7600. } else {
  7601. paeth = upperLeft;
  7602. }
  7603. pixels[c++] = (abyte + paeth) % 256;
  7604. }
  7605. break;
  7606. default:
  7607. throw new Error("Invalid filter algorithm: " + data[pos - 1]);
  7608. }
  7609. row++;
  7610. }
  7611. return pixels;
  7612. };
  7613. PNG.prototype.decodePalette = function() {
  7614. var c, i, length, palette, pos, ret, transparency, _i, _ref, _ref1;
  7615. palette = this.palette;
  7616. transparency = this.transparency.indexed || [];
  7617. ret = new Uint8Array((transparency.length || 0) + palette.length);
  7618. pos = 0;
  7619. length = palette.length;
  7620. c = 0;
  7621. for (i = _i = 0, _ref = palette.length; _i < _ref; i = _i += 3) {
  7622. ret[pos++] = palette[i];
  7623. ret[pos++] = palette[i + 1];
  7624. ret[pos++] = palette[i + 2];
  7625. ret[pos++] = (_ref1 = transparency[c++]) != null ? _ref1 : 255;
  7626. }
  7627. return ret;
  7628. };
  7629. PNG.prototype.copyToImageData = function(imageData, pixels) {
  7630. var alpha, colors, data, i, input, j, k, length, palette, v, _ref;
  7631. colors = this.colors;
  7632. palette = null;
  7633. alpha = this.hasAlphaChannel;
  7634. if (this.palette.length) {
  7635. palette = (_ref = this._decodedPalette) != null ? _ref : this._decodedPalette = this.decodePalette();
  7636. colors = 4;
  7637. alpha = true;
  7638. }
  7639. data = imageData.data || imageData;
  7640. length = data.length;
  7641. input = palette || pixels;
  7642. i = j = 0;
  7643. if (colors === 1) {
  7644. while (i < length) {
  7645. k = palette ? pixels[i / 4] * 4 : j;
  7646. v = input[k++];
  7647. data[i++] = v;
  7648. data[i++] = v;
  7649. data[i++] = v;
  7650. data[i++] = alpha ? input[k++] : 255;
  7651. j = k;
  7652. }
  7653. } else {
  7654. while (i < length) {
  7655. k = palette ? pixels[i / 4] * 4 : j;
  7656. data[i++] = input[k++];
  7657. data[i++] = input[k++];
  7658. data[i++] = input[k++];
  7659. data[i++] = alpha ? input[k++] : 255;
  7660. j = k;
  7661. }
  7662. }
  7663. };
  7664. PNG.prototype.decode = function() {
  7665. var ret;
  7666. ret = new Uint8Array(this.width * this.height * 4);
  7667. this.copyToImageData(ret, this.decodePixels());
  7668. return ret;
  7669. };
  7670. try {
  7671. scratchCanvas = global.document.createElement('canvas');
  7672. scratchCtx = scratchCanvas.getContext('2d');
  7673. } catch(e) {
  7674. return -1;
  7675. }
  7676. makeImage = function(imageData) {
  7677. var img;
  7678. scratchCtx.width = imageData.width;
  7679. scratchCtx.height = imageData.height;
  7680. scratchCtx.clearRect(0, 0, imageData.width, imageData.height);
  7681. scratchCtx.putImageData(imageData, 0, 0);
  7682. img = new Image;
  7683. img.src = scratchCanvas.toDataURL();
  7684. return img;
  7685. };
  7686. PNG.prototype.decodeFrames = function(ctx) {
  7687. var frame, i, imageData, pixels, _i, _len, _ref, _results;
  7688. if (!this.animation) {
  7689. return;
  7690. }
  7691. _ref = this.animation.frames;
  7692. _results = [];
  7693. for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
  7694. frame = _ref[i];
  7695. imageData = ctx.createImageData(frame.width, frame.height);
  7696. pixels = this.decodePixels(new Uint8Array(frame.data));
  7697. this.copyToImageData(imageData, pixels);
  7698. frame.imageData = imageData;
  7699. _results.push(frame.image = makeImage(imageData));
  7700. }
  7701. return _results;
  7702. };
  7703. PNG.prototype.renderFrame = function(ctx, number) {
  7704. var frame, frames, prev;
  7705. frames = this.animation.frames;
  7706. frame = frames[number];
  7707. prev = frames[number - 1];
  7708. if (number === 0) {
  7709. ctx.clearRect(0, 0, this.width, this.height);
  7710. }
  7711. if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_BACKGROUND) {
  7712. ctx.clearRect(prev.xOffset, prev.yOffset, prev.width, prev.height);
  7713. } else if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_PREVIOUS) {
  7714. ctx.putImageData(prev.imageData, prev.xOffset, prev.yOffset);
  7715. }
  7716. if (frame.blendOp === APNG_BLEND_OP_SOURCE) {
  7717. ctx.clearRect(frame.xOffset, frame.yOffset, frame.width, frame.height);
  7718. }
  7719. return ctx.drawImage(frame.image, frame.xOffset, frame.yOffset);
  7720. };
  7721. PNG.prototype.animate = function(ctx) {
  7722. var doFrame, frameNumber, frames, numFrames, numPlays, _ref,
  7723. _this = this;
  7724. frameNumber = 0;
  7725. _ref = this.animation, numFrames = _ref.numFrames, frames = _ref.frames, numPlays = _ref.numPlays;
  7726. return (doFrame = function() {
  7727. var f, frame;
  7728. f = frameNumber++ % numFrames;
  7729. frame = frames[f];
  7730. _this.renderFrame(ctx, f);
  7731. if (numFrames > 1 && frameNumber / numFrames < numPlays) {
  7732. return _this.animation._timeout = setTimeout(doFrame, frame.delay);
  7733. }
  7734. })();
  7735. };
  7736. PNG.prototype.stopAnimation = function() {
  7737. var _ref;
  7738. return clearTimeout((_ref = this.animation) != null ? _ref._timeout : void 0);
  7739. };
  7740. PNG.prototype.render = function(canvas) {
  7741. var ctx, data;
  7742. if (canvas._png) {
  7743. canvas._png.stopAnimation();
  7744. }
  7745. canvas._png = this;
  7746. canvas.width = this.width;
  7747. canvas.height = this.height;
  7748. ctx = canvas.getContext("2d");
  7749. if (this.animation) {
  7750. this.decodeFrames(ctx);
  7751. return this.animate(ctx);
  7752. } else {
  7753. data = ctx.createImageData(this.width, this.height);
  7754. this.copyToImageData(data, this.decodePixels());
  7755. return ctx.putImageData(data, 0, 0);
  7756. }
  7757. };
  7758. return PNG;
  7759. })();
  7760. global.PNG = PNG;
  7761. })(typeof window !== "undefined" && window || this);
  7762. /*
  7763. * Extracted from pdf.js
  7764. * https://github.com/andreasgal/pdf.js
  7765. *
  7766. * Copyright (c) 2011 Mozilla Foundation
  7767. *
  7768. * Contributors: Andreas Gal <gal@mozilla.com>
  7769. * Chris G Jones <cjones@mozilla.com>
  7770. * Shaon Barman <shaon.barman@gmail.com>
  7771. * Vivien Nicolas <21@vingtetun.org>
  7772. * Justin D'Arcangelo <justindarc@gmail.com>
  7773. * Yury Delendik
  7774. *
  7775. * Permission is hereby granted, free of charge, to any person obtaining a
  7776. * copy of this software and associated documentation files (the "Software"),
  7777. * to deal in the Software without restriction, including without limitation
  7778. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  7779. * and/or sell copies of the Software, and to permit persons to whom the
  7780. * Software is furnished to do so, subject to the following conditions:
  7781. *
  7782. * The above copyright notice and this permission notice shall be included in
  7783. * all copies or substantial portions of the Software.
  7784. *
  7785. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  7786. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  7787. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  7788. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  7789. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  7790. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  7791. * DEALINGS IN THE SOFTWARE.
  7792. */
  7793. var DecodeStream = (function() {
  7794. function constructor() {
  7795. this.pos = 0;
  7796. this.bufferLength = 0;
  7797. this.eof = false;
  7798. this.buffer = null;
  7799. }
  7800. constructor.prototype = {
  7801. ensureBuffer: function decodestream_ensureBuffer(requested) {
  7802. var buffer = this.buffer;
  7803. var current = buffer ? buffer.byteLength : 0;
  7804. if (requested < current)
  7805. return buffer;
  7806. var size = 512;
  7807. while (size < requested)
  7808. size <<= 1;
  7809. var buffer2 = new Uint8Array(size);
  7810. for (var i = 0; i < current; ++i)
  7811. buffer2[i] = buffer[i];
  7812. return this.buffer = buffer2;
  7813. },
  7814. getByte: function decodestream_getByte() {
  7815. var pos = this.pos;
  7816. while (this.bufferLength <= pos) {
  7817. if (this.eof)
  7818. return null;
  7819. this.readBlock();
  7820. }
  7821. return this.buffer[this.pos++];
  7822. },
  7823. getBytes: function decodestream_getBytes(length) {
  7824. var pos = this.pos;
  7825. if (length) {
  7826. this.ensureBuffer(pos + length);
  7827. var end = pos + length;
  7828. while (!this.eof && this.bufferLength < end)
  7829. this.readBlock();
  7830. var bufEnd = this.bufferLength;
  7831. if (end > bufEnd)
  7832. end = bufEnd;
  7833. } else {
  7834. while (!this.eof)
  7835. this.readBlock();
  7836. var end = this.bufferLength;
  7837. }
  7838. this.pos = end;
  7839. return this.buffer.subarray(pos, end);
  7840. },
  7841. lookChar: function decodestream_lookChar() {
  7842. var pos = this.pos;
  7843. while (this.bufferLength <= pos) {
  7844. if (this.eof)
  7845. return null;
  7846. this.readBlock();
  7847. }
  7848. return String.fromCharCode(this.buffer[this.pos]);
  7849. },
  7850. getChar: function decodestream_getChar() {
  7851. var pos = this.pos;
  7852. while (this.bufferLength <= pos) {
  7853. if (this.eof)
  7854. return null;
  7855. this.readBlock();
  7856. }
  7857. return String.fromCharCode(this.buffer[this.pos++]);
  7858. },
  7859. makeSubStream: function decodestream_makeSubstream(start, length, dict) {
  7860. var end = start + length;
  7861. while (this.bufferLength <= end && !this.eof)
  7862. this.readBlock();
  7863. return new Stream(this.buffer, start, length, dict);
  7864. },
  7865. skip: function decodestream_skip(n) {
  7866. if (!n)
  7867. n = 1;
  7868. this.pos += n;
  7869. },
  7870. reset: function decodestream_reset() {
  7871. this.pos = 0;
  7872. }
  7873. };
  7874. return constructor;
  7875. })();
  7876. var FlateStream = (function() {
  7877. if (typeof Uint32Array === 'undefined') {
  7878. return undefined;
  7879. }
  7880. var codeLenCodeMap = new Uint32Array([
  7881. 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
  7882. ]);
  7883. var lengthDecode = new Uint32Array([
  7884. 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a,
  7885. 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f,
  7886. 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073,
  7887. 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102
  7888. ]);
  7889. var distDecode = new Uint32Array([
  7890. 0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d,
  7891. 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1,
  7892. 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01,
  7893. 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001
  7894. ]);
  7895. var fixedLitCodeTab = [new Uint32Array([
  7896. 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0,
  7897. 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0,
  7898. 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0,
  7899. 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0,
  7900. 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8,
  7901. 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8,
  7902. 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8,
  7903. 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8,
  7904. 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4,
  7905. 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4,
  7906. 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4,
  7907. 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4,
  7908. 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc,
  7909. 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec,
  7910. 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc,
  7911. 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc,
  7912. 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2,
  7913. 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2,
  7914. 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2,
  7915. 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2,
  7916. 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca,
  7917. 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea,
  7918. 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da,
  7919. 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa,
  7920. 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6,
  7921. 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6,
  7922. 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6,
  7923. 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6,
  7924. 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce,
  7925. 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee,
  7926. 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de,
  7927. 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe,
  7928. 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1,
  7929. 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1,
  7930. 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1,
  7931. 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1,
  7932. 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9,
  7933. 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9,
  7934. 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9,
  7935. 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9,
  7936. 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5,
  7937. 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5,
  7938. 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5,
  7939. 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5,
  7940. 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd,
  7941. 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed,
  7942. 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd,
  7943. 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd,
  7944. 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3,
  7945. 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3,
  7946. 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3,
  7947. 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3,
  7948. 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb,
  7949. 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb,
  7950. 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db,
  7951. 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb,
  7952. 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7,
  7953. 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7,
  7954. 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7,
  7955. 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7,
  7956. 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf,
  7957. 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef,
  7958. 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df,
  7959. 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff
  7960. ]), 9];
  7961. var fixedDistCodeTab = [new Uint32Array([
  7962. 0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c,
  7963. 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000,
  7964. 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d,
  7965. 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000
  7966. ]), 5];
  7967. function error(e) {
  7968. throw new Error(e)
  7969. }
  7970. function constructor(bytes) {
  7971. //var bytes = stream.getBytes();
  7972. var bytesPos = 0;
  7973. var cmf = bytes[bytesPos++];
  7974. var flg = bytes[bytesPos++];
  7975. if (cmf == -1 || flg == -1)
  7976. error('Invalid header in flate stream');
  7977. if ((cmf & 0x0f) != 0x08)
  7978. error('Unknown compression method in flate stream');
  7979. if ((((cmf << 8) + flg) % 31) != 0)
  7980. error('Bad FCHECK in flate stream');
  7981. if (flg & 0x20)
  7982. error('FDICT bit set in flate stream');
  7983. this.bytes = bytes;
  7984. this.bytesPos = bytesPos;
  7985. this.codeSize = 0;
  7986. this.codeBuf = 0;
  7987. DecodeStream.call(this);
  7988. }
  7989. constructor.prototype = Object.create(DecodeStream.prototype);
  7990. constructor.prototype.getBits = function(bits) {
  7991. var codeSize = this.codeSize;
  7992. var codeBuf = this.codeBuf;
  7993. var bytes = this.bytes;
  7994. var bytesPos = this.bytesPos;
  7995. var b;
  7996. while (codeSize < bits) {
  7997. if (typeof (b = bytes[bytesPos++]) == 'undefined')
  7998. error('Bad encoding in flate stream');
  7999. codeBuf |= b << codeSize;
  8000. codeSize += 8;
  8001. }
  8002. b = codeBuf & ((1 << bits) - 1);
  8003. this.codeBuf = codeBuf >> bits;
  8004. this.codeSize = codeSize -= bits;
  8005. this.bytesPos = bytesPos;
  8006. return b;
  8007. };
  8008. constructor.prototype.getCode = function(table) {
  8009. var codes = table[0];
  8010. var maxLen = table[1];
  8011. var codeSize = this.codeSize;
  8012. var codeBuf = this.codeBuf;
  8013. var bytes = this.bytes;
  8014. var bytesPos = this.bytesPos;
  8015. while (codeSize < maxLen) {
  8016. var b;
  8017. if (typeof (b = bytes[bytesPos++]) == 'undefined')
  8018. error('Bad encoding in flate stream');
  8019. codeBuf |= (b << codeSize);
  8020. codeSize += 8;
  8021. }
  8022. var code = codes[codeBuf & ((1 << maxLen) - 1)];
  8023. var codeLen = code >> 16;
  8024. var codeVal = code & 0xffff;
  8025. if (codeSize == 0 || codeSize < codeLen || codeLen == 0)
  8026. error('Bad encoding in flate stream');
  8027. this.codeBuf = (codeBuf >> codeLen);
  8028. this.codeSize = (codeSize - codeLen);
  8029. this.bytesPos = bytesPos;
  8030. return codeVal;
  8031. };
  8032. constructor.prototype.generateHuffmanTable = function(lengths) {
  8033. var n = lengths.length;
  8034. // find max code length
  8035. var maxLen = 0;
  8036. for (var i = 0; i < n; ++i) {
  8037. if (lengths[i] > maxLen)
  8038. maxLen = lengths[i];
  8039. }
  8040. // build the table
  8041. var size = 1 << maxLen;
  8042. var codes = new Uint32Array(size);
  8043. for (var len = 1, code = 0, skip = 2;
  8044. len <= maxLen;
  8045. ++len, code <<= 1, skip <<= 1) {
  8046. for (var val = 0; val < n; ++val) {
  8047. if (lengths[val] == len) {
  8048. // bit-reverse the code
  8049. var code2 = 0;
  8050. var t = code;
  8051. for (var i = 0; i < len; ++i) {
  8052. code2 = (code2 << 1) | (t & 1);
  8053. t >>= 1;
  8054. }
  8055. // fill the table entries
  8056. for (var i = code2; i < size; i += skip)
  8057. codes[i] = (len << 16) | val;
  8058. ++code;
  8059. }
  8060. }
  8061. }
  8062. return [codes, maxLen];
  8063. };
  8064. constructor.prototype.readBlock = function() {
  8065. function repeat(stream, array, len, offset, what) {
  8066. var repeat = stream.getBits(len) + offset;
  8067. while (repeat-- > 0)
  8068. array[i++] = what;
  8069. }
  8070. // read block header
  8071. var hdr = this.getBits(3);
  8072. if (hdr & 1)
  8073. this.eof = true;
  8074. hdr >>= 1;
  8075. if (hdr == 0) { // uncompressed block
  8076. var bytes = this.bytes;
  8077. var bytesPos = this.bytesPos;
  8078. var b;
  8079. if (typeof (b = bytes[bytesPos++]) == 'undefined')
  8080. error('Bad block header in flate stream');
  8081. var blockLen = b;
  8082. if (typeof (b = bytes[bytesPos++]) == 'undefined')
  8083. error('Bad block header in flate stream');
  8084. blockLen |= (b << 8);
  8085. if (typeof (b = bytes[bytesPos++]) == 'undefined')
  8086. error('Bad block header in flate stream');
  8087. var check = b;
  8088. if (typeof (b = bytes[bytesPos++]) == 'undefined')
  8089. error('Bad block header in flate stream');
  8090. check |= (b << 8);
  8091. if (check != (~blockLen & 0xffff))
  8092. error('Bad uncompressed block length in flate stream');
  8093. this.codeBuf = 0;
  8094. this.codeSize = 0;
  8095. var bufferLength = this.bufferLength;
  8096. var buffer = this.ensureBuffer(bufferLength + blockLen);
  8097. var end = bufferLength + blockLen;
  8098. this.bufferLength = end;
  8099. for (var n = bufferLength; n < end; ++n) {
  8100. if (typeof (b = bytes[bytesPos++]) == 'undefined') {
  8101. this.eof = true;
  8102. break;
  8103. }
  8104. buffer[n] = b;
  8105. }
  8106. this.bytesPos = bytesPos;
  8107. return;
  8108. }
  8109. var litCodeTable;
  8110. var distCodeTable;
  8111. if (hdr == 1) { // compressed block, fixed codes
  8112. litCodeTable = fixedLitCodeTab;
  8113. distCodeTable = fixedDistCodeTab;
  8114. } else if (hdr == 2) { // compressed block, dynamic codes
  8115. var numLitCodes = this.getBits(5) + 257;
  8116. var numDistCodes = this.getBits(5) + 1;
  8117. var numCodeLenCodes = this.getBits(4) + 4;
  8118. // build the code lengths code table
  8119. var codeLenCodeLengths = Array(codeLenCodeMap.length);
  8120. var i = 0;
  8121. while (i < numCodeLenCodes)
  8122. codeLenCodeLengths[codeLenCodeMap[i++]] = this.getBits(3);
  8123. var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths);
  8124. // build the literal and distance code tables
  8125. var len = 0;
  8126. var i = 0;
  8127. var codes = numLitCodes + numDistCodes;
  8128. var codeLengths = new Array(codes);
  8129. while (i < codes) {
  8130. var code = this.getCode(codeLenCodeTab);
  8131. if (code == 16) {
  8132. repeat(this, codeLengths, 2, 3, len);
  8133. } else if (code == 17) {
  8134. repeat(this, codeLengths, 3, 3, len = 0);
  8135. } else if (code == 18) {
  8136. repeat(this, codeLengths, 7, 11, len = 0);
  8137. } else {
  8138. codeLengths[i++] = len = code;
  8139. }
  8140. }
  8141. litCodeTable =
  8142. this.generateHuffmanTable(codeLengths.slice(0, numLitCodes));
  8143. distCodeTable =
  8144. this.generateHuffmanTable(codeLengths.slice(numLitCodes, codes));
  8145. } else {
  8146. error('Unknown block type in flate stream');
  8147. }
  8148. var buffer = this.buffer;
  8149. var limit = buffer ? buffer.length : 0;
  8150. var pos = this.bufferLength;
  8151. while (true) {
  8152. var code1 = this.getCode(litCodeTable);
  8153. if (code1 < 256) {
  8154. if (pos + 1 >= limit) {
  8155. buffer = this.ensureBuffer(pos + 1);
  8156. limit = buffer.length;
  8157. }
  8158. buffer[pos++] = code1;
  8159. continue;
  8160. }
  8161. if (code1 == 256) {
  8162. this.bufferLength = pos;
  8163. return;
  8164. }
  8165. code1 -= 257;
  8166. code1 = lengthDecode[code1];
  8167. var code2 = code1 >> 16;
  8168. if (code2 > 0)
  8169. code2 = this.getBits(code2);
  8170. var len = (code1 & 0xffff) + code2;
  8171. code1 = this.getCode(distCodeTable);
  8172. code1 = distDecode[code1];
  8173. code2 = code1 >> 16;
  8174. if (code2 > 0)
  8175. code2 = this.getBits(code2);
  8176. var dist = (code1 & 0xffff) + code2;
  8177. if (pos + len >= limit) {
  8178. buffer = this.ensureBuffer(pos + len);
  8179. limit = buffer.length;
  8180. }
  8181. for (var k = 0; k < len; ++k, ++pos)
  8182. buffer[pos] = buffer[pos - dist];
  8183. }
  8184. };
  8185. return constructor;
  8186. })();/**
  8187. * JavaScript Polyfill functions for jsPDF
  8188. * Collected from public resources by
  8189. * https://github.com/diegocr
  8190. */
  8191. (function (global) {
  8192. var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  8193. if (typeof global.btoa === 'undefined') {
  8194. global.btoa = function(data) {
  8195. // discuss at: http://phpjs.org/functions/base64_encode/
  8196. // original by: Tyler Akins (http://rumkin.com)
  8197. // improved by: Bayron Guevara
  8198. // improved by: Thunder.m
  8199. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  8200. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  8201. // improved by: Rafal Kukawski (http://kukawski.pl)
  8202. // bugfixed by: Pellentesque Malesuada
  8203. // example 1: base64_encode('Kevin van Zonneveld');
  8204. // returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
  8205. var o1,o2,o3,h1,h2,h3,h4,bits,i = 0,ac = 0,enc = '',tmp_arr = [];
  8206. if (!data) {
  8207. return data;
  8208. }
  8209. do { // pack three octets into four hexets
  8210. o1 = data.charCodeAt(i++);
  8211. o2 = data.charCodeAt(i++);
  8212. o3 = data.charCodeAt(i++);
  8213. bits = o1 << 16 | o2 << 8 | o3;
  8214. h1 = bits >> 18 & 0x3f;
  8215. h2 = bits >> 12 & 0x3f;
  8216. h3 = bits >> 6 & 0x3f;
  8217. h4 = bits & 0x3f;
  8218. // use hexets to index into b64, and append result to encoded string
  8219. tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
  8220. } while (i < data.length);
  8221. enc = tmp_arr.join('');
  8222. var r = data.length % 3;
  8223. return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
  8224. };
  8225. }
  8226. if (typeof global.atob === 'undefined') {
  8227. global.atob = function(data) {
  8228. // discuss at: http://phpjs.org/functions/base64_decode/
  8229. // original by: Tyler Akins (http://rumkin.com)
  8230. // improved by: Thunder.m
  8231. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  8232. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  8233. // input by: Aman Gupta
  8234. // input by: Brett Zamir (http://brett-zamir.me)
  8235. // bugfixed by: Onno Marsman
  8236. // bugfixed by: Pellentesque Malesuada
  8237. // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  8238. // example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
  8239. // returns 1: 'Kevin van Zonneveld'
  8240. var o1,o2,o3,h1,h2,h3,h4,bits,i = 0,ac = 0,dec = '',tmp_arr = [];
  8241. if (!data) {
  8242. return data;
  8243. }
  8244. data += '';
  8245. do { // unpack four hexets into three octets using index points in b64
  8246. h1 = b64.indexOf(data.charAt(i++));
  8247. h2 = b64.indexOf(data.charAt(i++));
  8248. h3 = b64.indexOf(data.charAt(i++));
  8249. h4 = b64.indexOf(data.charAt(i++));
  8250. bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
  8251. o1 = bits >> 16 & 0xff;
  8252. o2 = bits >> 8 & 0xff;
  8253. o3 = bits & 0xff;
  8254. if (h3 == 64) {
  8255. tmp_arr[ac++] = String.fromCharCode(o1);
  8256. } else if (h4 == 64) {
  8257. tmp_arr[ac++] = String.fromCharCode(o1, o2);
  8258. } else {
  8259. tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
  8260. }
  8261. } while (i < data.length);
  8262. dec = tmp_arr.join('');
  8263. return dec;
  8264. };
  8265. }
  8266. if (!Array.prototype.map) {
  8267. Array.prototype.map = function(fun /*, thisArg */) {
  8268. if (this === void 0 || this === null || typeof fun !== "function")
  8269. throw new TypeError();
  8270. var t = Object(this), len = t.length >>> 0, res = new Array(len);
  8271. var thisArg = arguments.length > 1 ? arguments[1] : void 0;
  8272. for (var i = 0; i < len; i++) {
  8273. // NOTE: Absolute correctness would demand Object.defineProperty
  8274. // be used. But this method is fairly new, and failure is
  8275. // possible only if Object.prototype or Array.prototype
  8276. // has a property |i| (very unlikely), so use a less-correct
  8277. // but more portable alternative.
  8278. if (i in t)
  8279. res[i] = fun.call(thisArg, t[i], i, t);
  8280. }
  8281. return res;
  8282. };
  8283. }
  8284. if(!Array.isArray) {
  8285. Array.isArray = function(arg) {
  8286. return Object.prototype.toString.call(arg) === '[object Array]';
  8287. };
  8288. }
  8289. if (!Array.prototype.forEach) {
  8290. Array.prototype.forEach = function(fun, thisArg) {
  8291. "use strict";
  8292. if (this === void 0 || this === null || typeof fun !== "function")
  8293. throw new TypeError();
  8294. var t = Object(this), len = t.length >>> 0;
  8295. for (var i = 0; i < len; i++) {
  8296. if (i in t)
  8297. fun.call(thisArg, t[i], i, t);
  8298. }
  8299. };
  8300. }
  8301. if (!Object.keys) {
  8302. Object.keys = (function () {
  8303. 'use strict';
  8304. var hasOwnProperty = Object.prototype.hasOwnProperty,
  8305. hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
  8306. dontEnums = ['toString','toLocaleString','valueOf','hasOwnProperty',
  8307. 'isPrototypeOf','propertyIsEnumerable','constructor'],
  8308. dontEnumsLength = dontEnums.length;
  8309. return function (obj) {
  8310. if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
  8311. throw new TypeError();
  8312. }
  8313. var result = [], prop, i;
  8314. for (prop in obj) {
  8315. if (hasOwnProperty.call(obj, prop)) {
  8316. result.push(prop);
  8317. }
  8318. }
  8319. if (hasDontEnumBug) {
  8320. for (i = 0; i < dontEnumsLength; i++) {
  8321. if (hasOwnProperty.call(obj, dontEnums[i])) {
  8322. result.push(dontEnums[i]);
  8323. }
  8324. }
  8325. }
  8326. return result;
  8327. };
  8328. }());
  8329. }
  8330. if (!String.prototype.trim) {
  8331. String.prototype.trim = function () {
  8332. return this.replace(/^\s+|\s+$/g, '');
  8333. };
  8334. }
  8335. if (!String.prototype.trimLeft) {
  8336. String.prototype.trimLeft = function() {
  8337. return this.replace(/^\s+/g, "");
  8338. };
  8339. }
  8340. if (!String.prototype.trimRight) {
  8341. String.prototype.trimRight = function() {
  8342. return this.replace(/\s+$/g, "");
  8343. };
  8344. }
  8345. })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this);