Subversion-Projekte lars-tiefland.cienc

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
9 lars 1
/** @preserve jsPDF 0.9.0rc1 ( 2013-04-07T16:52 commit ID d95d8f69915bb999f6704e8021108e2e755bd868 )
2
Copyright (c) 2010-2012 James Hall, james@snapshotmedia.co.uk, https://github.com/MrRio/jsPDF
3
Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
4
MIT license.
5
*/
6
 
7
/*
8
 * Permission is hereby granted, free of charge, to any person obtaining
9
 * a copy of this software and associated documentation files (the
10
 * "Software"), to deal in the Software without restriction, including
11
 * without limitation the rights to use, copy, modify, merge, publish,
12
 * distribute, sublicense, and/or sell copies of the Software, and to
13
 * permit persons to whom the Software is furnished to do so, subject to
14
 * the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be
17
 * included in all copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
 * ====================================================================
27
 */
28
 
29
 
30
/**
31
Creates new jsPDF document object instance
32
@class
33
@param orientation One of "portrait" or "landscape" (or shortcuts "p" (Default), "l")
34
@param unit Measurement unit to be used when coordinates are specified. One of "pt" (points), "mm" (Default), "cm", "in"
35
@param format One of 'a3', 'a4' (Default),'a5' ,'letter' ,'legal'
36
@returns {jsPDF}
37
@name jsPDF
38
*/
39
var jsPDF = (function () {
40
    'use strict';
41
    /*jslint browser:true, plusplus: true, bitwise: true, nomen: true */
42
    /*global document: false, btoa, atob, zpipe, Uint8Array, ArrayBuffer, Blob, saveAs, adler32cs, Deflater */
43
 
44
// this will run on <=IE9, possibly some niche browsers
45
// new webkit-based, FireFox, IE10 already have native version of this.
46
    if (typeof btoa === 'undefined') {
47
        window.btoa = function (data) {
48
        // DO NOT ADD UTF8 ENCODING CODE HERE!!!!
49
 
50
        // UTF8 encoding encodes bytes over char code 128
51
        // and, essentially, turns an 8-bit binary streams
52
        // (that base64 can deal with) into 7-bit binary streams.
53
        // (by default server does not know that and does not recode the data back to 8bit)
54
        // You destroy your data.
55
 
56
        // binary streams like jpeg image data etc, while stored in JavaScript strings,
57
        // (which are 16bit arrays) are in 8bit format already.
58
        // You do NOT need to char-encode that before base64 encoding.
59
 
60
        // if you, by act of fate
61
        // have string which has individual characters with code
62
        // above 255 (pure unicode chars), encode that BEFORE you base64 here.
63
        // you can use absolutely any approch there, as long as in the end,
64
        // base64 gets an 8bit (char codes 0 - 255) stream.
65
        // when you get it on the server after un-base64, you must
66
        // UNencode it too, to get back to 16, 32bit or whatever original bin stream.
67
 
68
        // Note, Yes, JavaScript strings are, in most cases UCS-2 -
69
        // 16-bit character arrays. This does not mean, however,
70
        // that you always have to UTF8 it before base64.
71
        // it means that if you have actual characters anywhere in
72
        // that string that have char code above 255, you need to
73
        // recode *entire* string from 16-bit (or 32bit) to 8-bit array.
74
        // You can do binary split to UTF16 (BE or LE)
75
        // you can do utf8, you can split the thing by hand and prepend BOM to it,
76
        // but whatever you do, make sure you mirror the opposite on
77
        // the server. If server does not expect to post-process un-base64
78
        // 8-bit binary stream, think very very hard about messing around with encoding.
79
 
80
        // so, long story short:
81
        // DO NOT ADD UTF8 ENCODING CODE HERE!!!!
82
 
83
        /* @preserve
84
        ====================================================================
85
        base64 encoder
86
        MIT, GPL
87
 
88
        version: 1109.2015
89
        discuss at: http://phpjs.org/functions/base64_encode
90
        +   original by: Tyler Akins (http://rumkin.com)
91
        +   improved by: Bayron Guevara
92
        +   improved by: Thunder.m
93
        +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
94
        +   bugfixed by: Pellentesque Malesuada
95
        +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
96
        +   improved by: Rafal Kukawski (http://kukawski.pl)
97
        +                Daniel Dotsenko, Willow Systems Corp, willow-systems.com
98
        ====================================================================
99
        */
100
 
101
            var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
102
                b64a = b64.split(''),
103
                o1,
104
                o2,
105
                o3,
106
                h1,
107
                h2,
108
                h3,
109
                h4,
110
                bits,
111
                i = 0,
112
                ac = 0,
113
                enc = "",
114
                tmp_arr = [],
115
                r;
116
 
117
            do { // pack three octets into four hexets
118
                o1 = data.charCodeAt(i++);
119
                o2 = data.charCodeAt(i++);
120
                o3 = data.charCodeAt(i++);
121
 
122
                bits = o1 << 16 | o2 << 8 | o3;
123
 
124
                h1 = bits >> 18 & 0x3f;
125
                h2 = bits >> 12 & 0x3f;
126
                h3 = bits >> 6 & 0x3f;
127
                h4 = bits & 0x3f;
128
 
129
                // use hexets to index into b64, and append result to encoded string
130
                tmp_arr[ac++] = b64a[h1] + b64a[h2] + b64a[h3] + b64a[h4];
131
            } while (i < data.length);
132
 
133
            enc = tmp_arr.join('');
134
            r = data.length % 3;
135
            return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
136
            // end of base64 encoder MIT, GPL
137
        };
138
    }
139
 
140
    if (typeof atob === 'undefined') {
141
        window.atob = function (data) {
142
        // http://kevin.vanzonneveld.net
143
        // +   original by: Tyler Akins (http://rumkin.com)
144
        // +   improved by: Thunder.m
145
        // +      input by: Aman Gupta
146
        // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
147
        // +   bugfixed by: Onno Marsman
148
        // +   bugfixed by: Pellentesque Malesuada
149
        // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
150
        // +      input by: Brett Zamir (http://brett-zamir.me)
151
        // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
152
        // *     example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
153
        // *     returns 1: 'Kevin van Zonneveld'
154
        // mozilla has this native
155
        // - but breaks in 2.0.0.12!
156
        //if (typeof this.window['atob'] == 'function') {
157
        //    return atob(data);
158
        //}
159
            var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
160
                o1,
161
                o2,
162
                o3,
163
                h1,
164
                h2,
165
                h3,
166
                h4,
167
                bits,
168
                i = 0,
169
                ac = 0,
170
                dec = "",
171
                tmp_arr = [];
172
 
173
            if (!data) {
174
                return data;
175
            }
176
 
177
            data += '';
178
 
179
            do { // unpack four hexets into three octets using index points in b64
180
                h1 = b64.indexOf(data.charAt(i++));
181
                h2 = b64.indexOf(data.charAt(i++));
182
                h3 = b64.indexOf(data.charAt(i++));
183
                h4 = b64.indexOf(data.charAt(i++));
184
 
185
                bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
186
 
187
                o1 = bits >> 16 & 0xff;
188
                o2 = bits >> 8 & 0xff;
189
                o3 = bits & 0xff;
190
 
191
                if (h3 === 64) {
192
                    tmp_arr[ac++] = String.fromCharCode(o1);
193
                } else if (h4 === 64) {
194
                    tmp_arr[ac++] = String.fromCharCode(o1, o2);
195
                } else {
196
                    tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
197
                }
198
            } while (i < data.length);
199
            dec = tmp_arr.join('');
200
            return dec;
201
        };
202
    }
203
 
204
    var getObjectLength = typeof Object.keys === 'function' ?
205
                function (object) {
206
                    return Object.keys(object).length;
207
                } :
208
                function (object) {
209
                    var i = 0, e;
210
                    for (e in object) {
211
                        if (object.hasOwnProperty(e)) {
212
                            i++;
213
                        }
214
                    }
215
                    return i;
216
                },
217
 
218
/**
219
PubSub implementation
220
 
221
@class
222
@name PubSub
223
*/
224
        PubSub = function (context) {
225
            /**  @preserve
226
            -----------------------------------------------------------------------------------------------
227
            JavaScript PubSub library
228
            2012 (c) ddotsenko@willowsystems.com
229
            based on Peter Higgins (dante@dojotoolkit.org)
230
            Loosely based on Dojo publish/subscribe API, limited in scope. Rewritten blindly.
231
            Original is (c) Dojo Foundation 2004-2010. Released under either AFL or new BSD, see:
232
            http://dojofoundation.org/license for more information.
233
            -----------------------------------------------------------------------------------------------
234
            */
235
            /**
236
            @private
237
            @fieldOf PubSub
238
            */
239
            this.topics = {};
240
            /**
241
            Stores what will be `this` within the callback functions.
242
 
243
            @private
244
            @fieldOf PubSub#
245
            */
246
            this.context = context;
247
            /**
248
            Allows caller to emit an event and pass arguments to event listeners.
249
            @public
250
            @function
251
            @param topic {String} Name of the channel on which to voice this event
252
            @param args Any number of arguments you want to pass to the listeners of this event.
253
            @methodOf PubSub#
254
            @name publish
255
            */
256
            this.publish = function (topic, args) {
257
                if (this.topics[topic]) {
258
                    var currentTopic = this.topics[topic],
259
                        toremove = [],
260
                        fn,
261
                        i,
262
                        l,
263
                        pair,
264
                        emptyFunc = function () {};
265
                    args = Array.prototype.slice.call(arguments, 1);
266
                    for (i = 0, l = currentTopic.length; i < l; i++) {
267
                        pair = currentTopic[i]; // this is a [function, once_flag] array
268
                        fn = pair[0];
269
                        if (pair[1]) { /* 'run once' flag set */
270
                            pair[0] = emptyFunc;
271
                            toremove.push(i);
272
                        }
273
                        fn.apply(this.context, args);
274
                    }
275
                    for (i = 0, l = toremove.length; i < l; i++) {
276
                        currentTopic.splice(toremove[i], 1);
277
                    }
278
                }
279
            };
280
            /**
281
            Allows listener code to subscribe to channel and be called when data is available
282
            @public
283
            @function
284
            @param topic {String} Name of the channel on which to voice this event
285
            @param callback {Function} Executable (function pointer) that will be ran when event is voiced on this channel.
286
            @param once {Boolean} (optional. False by default) Flag indicating if the function is to be triggered only once.
287
            @returns {Object} A token object that cen be used for unsubscribing.
288
            @methodOf PubSub#
289
            @name subscribe
290
            */
291
            this.subscribe = function (topic, callback, once) {
292
                if (!this.topics[topic]) {
293
                    this.topics[topic] = [[callback, once]];
294
                } else {
295
                    this.topics[topic].push([callback, once]);
296
                }
297
                return {
298
                    "topic": topic,
299
                    "callback": callback
300
                };
301
            };
302
            /**
303
            Allows listener code to unsubscribe from a channel
304
            @public
305
            @function
306
            @param token {Object} A token object that was returned by `subscribe` method
307
            @methodOf PubSub#
308
            @name unsubscribe
309
            */
310
            this.unsubscribe = function (token) {
311
                if (this.topics[token.topic]) {
312
                    var currentTopic = this.topics[token.topic], i, l;
313
 
314
                    for (i = 0, l = currentTopic.length; i < l; i++) {
315
                        if (currentTopic[i][0] === token.callback) {
316
                            currentTopic.splice(i, 1);
317
                        }
318
                    }
319
                }
320
            };
321
        };
322
 
323
 
324
/**
325
@constructor
326
@private
327
*/
328
    function jsPDF(orientation, unit, format, compressPdf) { /** String orientation, String unit, String format, Boolean compressed */
329
 
330
        // Default parameter values
331
        if (typeof orientation === 'undefined') {
332
            orientation = 'p';
333
        } else {
334
            orientation = orientation.toString().toLowerCase();
335
        }
336
        if (typeof unit === 'undefined') { unit = 'mm'; }
337
        if (typeof format === 'undefined') { format = 'a4'; }
338
        if (typeof compressPdf === 'undefined' && typeof zpipe === 'undefined') { compressPdf = false; }
339
 
340
        var format_as_string = format.toString().toLowerCase(),
341
            version = '20120619',
342
            content = [],
343
            content_length = 0,
344
            compress = compressPdf,
345
            pdfVersion = '1.3', // PDF Version
346
            pageFormats = { // Size in pt of various paper formats
347
                'a3': [841.89, 1190.55],
348
                'a4': [595.28, 841.89],
349
                'a5': [420.94, 595.28],
350
                'letter': [612, 792],
351
                'legal': [612, 1008]
352
            },
353
            textColor = '0 g',
354
            drawColor = '0 G',
355
            page = 0,
356
            pages = [],
357
            objectNumber = 2, // 'n' Current object number
358
            outToPages = false, // switches where out() prints. outToPages true = push to pages obj. outToPages false = doc builder content
359
            offsets = [], // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes.
360
            fonts = {}, // collection of font objects, where key is fontKey - a dynamically created label for a given font.
361
            fontmap = {}, // mapping structure fontName > fontStyle > font key - performance layer. See addFont()
362
            activeFontSize = 16,
363
            activeFontKey, // will be string representing the KEY of the font as combination of fontName + fontStyle
364
            lineWidth = 0.200025, // 2mm
365
            pageHeight,
366
            pageWidth,
367
            k, // Scale factor
368
            documentProperties = {'title': '', 'subject': '', 'author': '', 'keywords': '', 'creator': ''},
369
            lineCapID = 0,
370
            lineJoinID = 0,
371
            API = {},
372
            events = new PubSub(API),
373
            tmp,
374
            plugin,
375
            /////////////////////
376
            // Private functions
377
            /////////////////////
378
            // simplified (speedier) replacement for sprintf's %.2f conversion
379
            f2 = function (number) {
380
                return number.toFixed(2);
381
            },
382
            // simplified (speedier) replacement for sprintf's %.3f conversion
383
            f3 = function (number) {
384
                return number.toFixed(3);
385
            },
386
            // simplified (speedier) replacement for sprintf's %02d
387
            padd2 = function (number) {
388
                var n = (number).toFixed(0);
389
                if (number < 10) {
390
                    return '0' + n;
391
                } else {
392
                    return n;
393
                }
394
            },
395
            // simplified (speedier) replacement for sprintf's %02d
396
            padd10 = function (number) {
397
                var n = (number).toFixed(0);
398
                if (n.length < 10) {
399
                    return new Array( 11 - n.length ).join('0') + n;
400
                } else {
401
                    return n;
402
                }
403
            },
404
            out = function (string) {
405
                if (outToPages) { /* set by beginPage */
406
                    pages[page].push(string);
407
                } else {
408
                    content.push(string);
409
                    content_length += string.length + 1; // +1 is for '\n' that will be used to join contents of content
410
                }
411
            },
412
            newObject = function () {
413
                // Begin a new object
414
                objectNumber++;
415
                offsets[objectNumber] = content_length;
416
                out(objectNumber + ' 0 obj');
417
                return objectNumber;
418
            },
419
            putStream = function (str) {
420
                out('stream');
421
                out(str);
422
                out('endstream');
423
            },
424
            wPt,
425
            hPt,
426
            kids,
427
            i,
428
            putPages = function () {
429
                wPt = pageWidth * k;
430
                hPt = pageHeight * k;
431
 
432
                // outToPages = false as set in endDocument(). out() writes to content.
433
 
434
                var n, p, arr, uint, i, deflater, adler32;
435
                for (n = 1; n <= page; n++) {
436
                    newObject();
437
                    out('<</Type /Page');
438
                    out('/Parent 1 0 R');
439
                    out('/Resources 2 0 R');
440
                    out('/Contents ' + (objectNumber + 1) + ' 0 R>>');
441
                    out('endobj');
442
 
443
                    // Page content
444
                    p = pages[n].join('\n');
445
                    newObject();
446
                    if (compress) {
447
                        arr = [];
448
                        for (i = 0; i < p.length; ++i) {
449
                            arr[i] = p.charCodeAt(i);
450
                        }
451
                        adler32 = adler32cs.from(p);
452
                        deflater = new Deflater(6);
453
                        deflater.append(new Uint8Array(arr));
454
                        p = deflater.flush();
455
                        arr = [new Uint8Array([120, 156]), new Uint8Array(p),
456
                               new Uint8Array([adler32 & 0xFF, (adler32 >> 8) & 0xFF, (adler32 >> 16) & 0xFF, (adler32 >> 24) & 0xFF])];
457
                        p = '';
458
                        for (i in arr) {
459
                            if (arr.hasOwnProperty(i)) {
460
                                p += String.fromCharCode.apply(null, arr[i]);
461
                            }
462
                        }
463
                        out('<</Length ' + p.length  + ' /Filter [/FlateDecode]>>');
464
                    } else {
465
                        out('<</Length ' + p.length  + '>>');
466
                    }
467
                    putStream(p);
468
                    out('endobj');
469
                }
470
                offsets[1] = content_length;
471
                out('1 0 obj');
472
                out('<</Type /Pages');
473
                kids = '/Kids [';
474
                for (i = 0; i < page; i++) {
475
                    kids += (3 + 2 * i) + ' 0 R ';
476
                }
477
                out(kids + ']');
478
                out('/Count ' + page);
479
                out('/MediaBox [0 0 ' + f2(wPt) + ' ' + f2(hPt) + ']');
480
                out('>>');
481
                out('endobj');
482
            },
483
            putFont = function (font) {
484
                font.objectNumber = newObject();
485
                out('<</BaseFont/' + font.PostScriptName + '/Type/Font');
486
                if (typeof font.encoding === 'string') {
487
                    out('/Encoding/' + font.encoding);
488
                }
489
                out('/Subtype/Type1>>');
490
                out('endobj');
491
            },
492
            putFonts = function () {
493
                var fontKey;
494
                for (fontKey in fonts) {
495
                    if (fonts.hasOwnProperty(fontKey)) {
496
                        putFont(fonts[fontKey]);
497
                    }
498
                }
499
            },
500
            putXobjectDict = function () {
501
                // Loop through images, or other data objects
502
                events.publish('putXobjectDict');
503
            },
504
            putResourceDictionary = function () {
505
                out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
506
                out('/Font <<');
507
                // Do this for each font, the '1' bit is the index of the font
508
                var fontKey;
509
                for (fontKey in fonts) {
510
                    if (fonts.hasOwnProperty(fontKey)) {
511
                        out('/' + fontKey + ' ' + fonts[fontKey].objectNumber + ' 0 R');
512
                    }
513
                }
514
                out('>>');
515
                out('/XObject <<');
516
                putXobjectDict();
517
                out('>>');
518
            },
519
            putResources = function () {
520
                putFonts();
521
                events.publish('putResources');
522
                // Resource dictionary
523
                offsets[2] = content_length;
524
                out('2 0 obj');
525
                out('<<');
526
                putResourceDictionary();
527
                out('>>');
528
                out('endobj');
529
                events.publish('postPutResources');
530
            },
531
            addToFontDictionary = function (fontKey, fontName, fontStyle) {
532
                // this is mapping structure for quick font key lookup.
533
                // returns the KEY of the font (ex: "F1") for a given pair of font name and type (ex: "Arial". "Italic")
534
                var undef;
535
                if (fontmap[fontName] === undef) {
536
                    fontmap[fontName] = {}; // fontStyle is a var interpreted and converted to appropriate string. don't wrap in quotes.
537
                }
538
                fontmap[fontName][fontStyle] = fontKey;
539
            },
540
            /**
541
            FontObject describes a particular font as member of an instnace of jsPDF
542
 
543
            It's a collection of properties like 'id' (to be used in PDF stream),
544
            'fontName' (font's family name), 'fontStyle' (font's style variant label)
545
 
546
            @class
547
            @public
548
            @property id {String} PDF-document-instance-specific label assinged to the font.
549
            @property PostScriptName {String} PDF specification full name for the font
550
            @property encoding {Object} Encoding_name-to-Font_metrics_object mapping.
551
            @name FontObject
552
            */
553
            FontObject = {},
554
            addFont = function (PostScriptName, fontName, fontStyle, encoding) {
555
                var fontKey = 'F' + (getObjectLength(fonts) + 1).toString(10),
556
                    // This is FontObject
557
                    font = fonts[fontKey] = {
558
                        'id': fontKey,
559
                        // , 'objectNumber':   will be set by putFont()
560
                        'PostScriptName': PostScriptName,
561
                        'fontName': fontName,
562
                        'fontStyle': fontStyle,
563
                        'encoding': encoding,
564
                        'metadata': {}
565
                    };
566
 
567
                addToFontDictionary(fontKey, fontName, fontStyle);
568
 
569
                events.publish('addFont', font);
570
 
571
                return fontKey;
572
            },
573
            addFonts = function () {
574
 
575
                var HELVETICA = "helvetica",
576
                    TIMES = "times",
577
                    COURIER = "courier",
578
                    NORMAL = "normal",
579
                    BOLD = "bold",
580
                    ITALIC = "italic",
581
                    BOLD_ITALIC = "bolditalic",
582
                    encoding = 'StandardEncoding',
583
                    standardFonts = [
584
                        ['Helvetica', HELVETICA, NORMAL],
585
                        ['Helvetica-Bold', HELVETICA, BOLD],
586
                        ['Helvetica-Oblique', HELVETICA, ITALIC],
587
                        ['Helvetica-BoldOblique', HELVETICA, BOLD_ITALIC],
588
                        ['Courier', COURIER, NORMAL],
589
                        ['Courier-Bold', COURIER, BOLD],
590
                        ['Courier-Oblique', COURIER, ITALIC],
591
                        ['Courier-BoldOblique', COURIER, BOLD_ITALIC],
592
                        ['Times-Roman', TIMES, NORMAL],
593
                        ['Times-Bold', TIMES, BOLD],
594
                        ['Times-Italic', TIMES, ITALIC],
595
                        ['Times-BoldItalic', TIMES, BOLD_ITALIC]
596
                    ],
597
                    i,
598
                    l,
599
                    fontKey,
600
                    parts;
601
                for (i = 0, l = standardFonts.length; i < l; i++) {
602
                    fontKey = addFont(
603
                        standardFonts[i][0],
604
                        standardFonts[i][1],
605
                        standardFonts[i][2],
606
                        encoding
607
                    );
608
 
609
                    // adding aliases for standard fonts, this time matching the capitalization
610
                    parts = standardFonts[i][0].split('-');
611
                    addToFontDictionary(fontKey, parts[0], parts[1] || '');
612
                }
613
 
614
                events.publish('addFonts', {'fonts': fonts, 'dictionary': fontmap});
615
            },
616
            /**
617
 
618
            @public
619
            @function
620
            @param text {String}
621
            @param flags {Object} Encoding flags.
622
            @returns {String} Encoded string
623
            */
624
            to8bitStream = function (text, flags) {
625
                /* PDF 1.3 spec:
626
                "For text strings encoded in Unicode, the first two bytes must be 254 followed by
627
                255, representing the Unicode byte order marker, U+FEFF. (This sequence conflicts
628
                with the PDFDocEncoding character sequence thorn ydieresis, which is unlikely
629
                to be a meaningful beginning of a word or phrase.) The remainder of the
630
                string consists of Unicode character codes, according to the UTF-16 encoding
631
                specified in the Unicode standard, version 2.0. Commonly used Unicode values
632
                are represented as 2 bytes per character, with the high-order byte appearing first
633
                in the string."
634
 
635
                In other words, if there are chars in a string with char code above 255, we
636
                recode the string to UCS2 BE - string doubles in length and BOM is prepended.
637
 
638
                HOWEVER!
639
                Actual *content* (body) text (as opposed to strings used in document properties etc)
640
                does NOT expect BOM. There, it is treated as a literal GID (Glyph ID)
641
 
642
                Because of Adobe's focus on "you subset your fonts!" you are not supposed to have
643
                a font that maps directly Unicode (UCS2 / UTF16BE) code to font GID, but you could
644
                fudge it with "Identity-H" encoding and custom CIDtoGID map that mimics Unicode
645
                code page. There, however, all characters in the stream are treated as GIDs,
646
                including BOM, which is the reason we need to skip BOM in content text (i.e. that
647
                that is tied to a font).
648
 
649
                To signal this "special" PDFEscape / to8bitStream handling mode,
650
                API.text() function sets (unless you overwrite it with manual values
651
                given to API.text(.., flags) )
652
                    flags.autoencode = true
653
                    flags.noBOM = true
654
 
655
                */
656
 
657
                /*
658
                `flags` properties relied upon:
659
                .sourceEncoding = string with encoding label.
660
                    "Unicode" by default. = encoding of the incoming text.
661
                    pass some non-existing encoding name
662
                    (ex: 'Do not touch my strings! I know what I am doing.')
663
                    to make encoding code skip the encoding step.
664
                .outputEncoding = Either valid PDF encoding name
665
                    (must be supported by jsPDF font metrics, otherwise no encoding)
666
                    or a JS object, where key = sourceCharCode, value = outputCharCode
667
                    missing keys will be treated as: sourceCharCode === outputCharCode
668
                .noBOM
669
                    See comment higher above for explanation for why this is important
670
                .autoencode
671
                    See comment higher above for explanation for why this is important
672
                */
673
 
674
                var i, l, undef, sourceEncoding, encodingBlock, outputEncoding, newtext, isUnicode, ch, bch;
675
 
676
                if (flags === undef) {
677
                    flags = {};
678
                }
679
 
680
                sourceEncoding = flags.sourceEncoding ? sourceEncoding : 'Unicode';
681
 
682
                outputEncoding = flags.outputEncoding;
683
 
684
                // This 'encoding' section relies on font metrics format
685
                // attached to font objects by, among others,
686
                // "Willow Systems' standard_font_metrics plugin"
687
                // see jspdf.plugin.standard_font_metrics.js for format
688
                // of the font.metadata.encoding Object.
689
                // It should be something like
690
                //   .encoding = {'codePages':['WinANSI....'], 'WinANSI...':{code:code, ...}}
691
                //   .widths = {0:width, code:width, ..., 'fof':divisor}
692
                //   .kerning = {code:{previous_char_code:shift, ..., 'fof':-divisor},...}
693
                if ((flags.autoencode || outputEncoding) &&
694
                        fonts[activeFontKey].metadata &&
695
                        fonts[activeFontKey].metadata[sourceEncoding] &&
696
                        fonts[activeFontKey].metadata[sourceEncoding].encoding
697
                        ) {
698
                    encodingBlock = fonts[activeFontKey].metadata[sourceEncoding].encoding;
699
 
700
                    // each font has default encoding. Some have it clearly defined.
701
                    if (!outputEncoding && fonts[activeFontKey].encoding) {
702
                        outputEncoding = fonts[activeFontKey].encoding;
703
                    }
704
 
705
                    // Hmmm, the above did not work? Let's try again, in different place.
706
                    if (!outputEncoding && encodingBlock.codePages) {
707
                        outputEncoding = encodingBlock.codePages[0]; // let's say, first one is the default
708
                    }
709
 
710
                    if (typeof outputEncoding === 'string') {
711
                        outputEncoding = encodingBlock[outputEncoding];
712
                    }
713
                    // we want output encoding to be a JS Object, where
714
                    // key = sourceEncoding's character code and
715
                    // value = outputEncoding's character code.
716
                    if (outputEncoding) {
717
                        isUnicode = false;
718
                        newtext = [];
719
                        for (i = 0, l = text.length; i < l; i++) {
720
                            ch = outputEncoding[text.charCodeAt(i)];
721
                            if (ch) {
722
                                newtext.push(
723
                                    String.fromCharCode(ch)
724
                                );
725
                            } else {
726
                                newtext.push(
727
                                    text[i]
728
                                );
729
                            }
730
 
731
                            // since we are looping over chars anyway, might as well
732
                            // check for residual unicodeness
733
                            if (newtext[i].charCodeAt(0) >> 8) { /* more than 255 */
734
                                isUnicode = true;
735
                            }
736
                        }
737
                        text = newtext.join('');
738
                    }
739
                }
740
 
741
                i = text.length;
742
                // isUnicode may be set to false above. Hence the triple-equal to undefined
743
                while (isUnicode === undef && i !== 0) {
744
                    if (text.charCodeAt(i - 1) >> 8) { /* more than 255 */
745
                        isUnicode = true;
746
                    }
747
                    i--;
748
                }
749
                if (!isUnicode) {
750
                    return text;
751
                } else {
752
                    newtext = flags.noBOM ? [] : [254, 255];
753
                    for (i = 0, l = text.length; i < l; i++) {
754
                        ch = text.charCodeAt(i);
755
                        bch = ch >> 8; // divide by 256
756
                        if (bch >> 8) { /* something left after dividing by 256 second time */
757
                            throw new Error("Character at position " + i.toString(10) + " of string '" + text + "' exceeds 16bits. Cannot be encoded into UCS-2 BE");
758
                        }
759
                        newtext.push(bch);
760
                        newtext.push(ch - (bch << 8));
761
                    }
762
                    return String.fromCharCode.apply(undef, newtext);
763
                }
764
            },
765
            // Replace '/', '(', and ')' with pdf-safe versions
766
            pdfEscape = function (text, flags) {
767
                // doing to8bitStream does NOT make this PDF display unicode text. For that
768
                // we also need to reference a unicode font and embed it - royal pain in the rear.
769
 
770
                // There is still a benefit to to8bitStream - PDF simply cannot handle 16bit chars,
771
                // which JavaScript Strings are happy to provide. So, while we still cannot display
772
                // 2-byte characters property, at least CONDITIONALLY converting (entire string containing)
773
                // 16bit chars to (USC-2-BE) 2-bytes per char + BOM streams we ensure that entire PDF
774
                // is still parseable.
775
                // This will allow immediate support for unicode in document properties strings.
776
                return to8bitStream(text, flags).replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
777
            },
778
            putInfo = function () {
779
                out('/Producer (jsPDF ' + version + ')');
780
                if (documentProperties.title) {
781
                    out('/Title (' + pdfEscape(documentProperties.title) + ')');
782
                }
783
                if (documentProperties.subject) {
784
                    out('/Subject (' + pdfEscape(documentProperties.subject) + ')');
785
                }
786
                if (documentProperties.author) {
787
                    out('/Author (' + pdfEscape(documentProperties.author) + ')');
788
                }
789
                if (documentProperties.keywords) {
790
                    out('/Keywords (' + pdfEscape(documentProperties.keywords) + ')');
791
                }
792
                if (documentProperties.creator) {
793
                    out('/Creator (' + pdfEscape(documentProperties.creator) + ')');
794
                }
795
                var created = new Date();
796
                out('/CreationDate (D:' +
797
                    [
798
                        created.getFullYear(),
799
                        padd2(created.getMonth() + 1),
800
                        padd2(created.getDate()),
801
                        padd2(created.getHours()),
802
                        padd2(created.getMinutes()),
803
                        padd2(created.getSeconds())
804
                    ].join('') +
805
                    ')'
806
                    );
807
            },
808
            putCatalog = function () {
809
                out('/Type /Catalog');
810
                out('/Pages 1 0 R');
811
                // @TODO: Add zoom and layout modes
812
                out('/OpenAction [3 0 R /FitH null]');
813
                out('/PageLayout /OneColumn');
814
                events.publish('putCatalog');
815
            },
816
            putTrailer = function () {
817
                out('/Size ' + (objectNumber + 1));
818
                out('/Root ' + objectNumber + ' 0 R');
819
                out('/Info ' + (objectNumber - 1) + ' 0 R');
820
            },
821
            beginPage = function () {
822
                page++;
823
                // Do dimension stuff
824
                outToPages = true;
825
                pages[page] = [];
826
            },
827
            _addPage = function () {
828
                beginPage();
829
                // Set line width
830
                out(f2(lineWidth * k) + ' w');
831
                // Set draw color
832
                out(drawColor);
833
                // resurrecting non-default line caps, joins
834
                if (lineCapID !== 0) {
835
                    out(lineCapID.toString(10) + ' J');
836
                }
837
                if (lineJoinID !== 0) {
838
                    out(lineJoinID.toString(10) + ' j');
839
                }
840
                events.publish('addPage', {'pageNumber': page});
841
            },
842
            /**
843
            Returns a document-specific font key - a label assigned to a
844
            font name + font type combination at the time the font was added
845
            to the font inventory.
846
 
847
            Font key is used as label for the desired font for a block of text
848
            to be added to the PDF document stream.
849
            @private
850
            @function
851
            @param fontName {String} can be undefined on "falthy" to indicate "use current"
852
            @param fontStyle {String} can be undefined on "falthy" to indicate "use current"
853
            @returns {String} Font key.
854
            */
855
            getFont = function (fontName, fontStyle) {
856
                var key, undef;
857
 
858
                if (fontName === undef) {
859
                    fontName = fonts[activeFontKey].fontName;
860
                }
861
                if (fontStyle === undef) {
862
                    fontStyle = fonts[activeFontKey].fontStyle;
863
                }
864
 
865
                try {
866
                    key = fontmap[fontName][fontStyle]; // returns a string like 'F3' - the KEY corresponding tot he font + type combination.
867
                } catch (e) {
868
                    key = undef;
869
                }
870
                if (!key) {
871
                    throw new Error("Unable to look up font label for font '" + fontName + "', '" + fontStyle + "'. Refer to getFontList() for available fonts.");
872
                }
873
 
874
                return key;
875
            },
876
            buildDocument = function () {
877
 
878
                outToPages = false; // switches out() to content
879
                content = [];
880
                offsets = [];
881
 
882
                // putHeader()
883
                out('%PDF-' + pdfVersion);
884
 
885
                putPages();
886
 
887
                putResources();
888
 
889
                // Info
890
                newObject();
891
                out('<<');
892
                putInfo();
893
                out('>>');
894
                out('endobj');
895
 
896
                // Catalog
897
                newObject();
898
                out('<<');
899
                putCatalog();
900
                out('>>');
901
                out('endobj');
902
 
903
                // Cross-ref
904
                var o = content_length, i;
905
                out('xref');
906
                out('0 ' + (objectNumber + 1));
907
                out('0000000000 65535 f ');
908
                for (i = 1; i <= objectNumber; i++) {
909
                    out(padd10(offsets[i]) + ' 00000 n ');
910
                }
911
                // Trailer
912
                out('trailer');
913
                out('<<');
914
                putTrailer();
915
                out('>>');
916
                out('startxref');
917
                out(o);
918
                out('%%EOF');
919
 
920
                outToPages = true;
921
 
922
                return content.join('\n');
923
            },
924
            getStyle = function (style) {
925
                // see Path-Painting Operators of PDF spec
926
                var op = 'S'; // stroke
927
                if (style === 'F') {
928
                    op = 'f'; // fill
929
                } else if (style === 'FD' || style === 'DF') {
930
                    op = 'B'; // both
931
                }
932
                return op;
933
            },
934
 
935
            /**
936
            Generates the PDF document.
937
            Possible values:
938
                datauristring (alias dataurlstring) - Data-Url-formatted data returned as string.
939
                datauri (alias datauri) - Data-Url-formatted data pushed into current window's location (effectively reloading the window with contents of the PDF).
940
 
941
            If `type` argument is undefined, output is raw body of resulting PDF returned as a string.
942
 
943
            @param {String} type A string identifying one of the possible output types.
944
            @param {Object} options An object providing some additional signalling to PDF generator.
945
            @function
946
            @returns {jsPDF}
947
            @methodOf jsPDF#
948
            @name output
949
            */
950
            output = function (type, options) {
951
                var undef, data, length, array, i, blob;
952
                switch (type) {
953
                case undef:
954
                    return buildDocument();
955
                case 'save':
956
                    if (navigator.getUserMedia) {
957
                        if (window.URL === undefined) {
958
                            return API.output('dataurlnewwindow');
959
                        } else if (window.URL.createObjectURL === undefined) {
960
                            return API.output('dataurlnewwindow');
961
                        }
962
                    }
963
                    data = buildDocument();
964
 
965
                    // Need to add the file to BlobBuilder as a Uint8Array
966
                    length = data.length;
967
                    array = new Uint8Array(new ArrayBuffer(length));
968
 
969
                    for (i = 0; i < length; i++) {
970
                        array[i] = data.charCodeAt(i);
971
                    }
972
 
973
                    blob = new Blob([array], {type: "application/pdf"});
974
 
975
                    saveAs(blob, options);
976
                    break;
977
                case 'datauristring':
978
                case 'dataurlstring':
979
                    return 'data:application/pdf;base64,' + btoa(buildDocument());
980
                case 'datauri':
981
                case 'dataurl':
982
                    document.location.href = 'data:application/pdf;base64,' + btoa(buildDocument());
983
                    break;
984
                case 'dataurlnewwindow':
985
                    window.open('data:application/pdf;base64,' + btoa(buildDocument()));
986
                    break;
987
                default:
988
                    throw new Error('Output type "' + type + '" is not supported.');
989
                }
990
                // @TODO: Add different output options
991
            };
992
 
993
        if (unit === 'pt') {
994
            k = 1;
995
        } else if (unit === 'mm') {
996
            k = 72 / 25.4;
997
        } else if (unit === 'cm') {
998
            k = 72 / 2.54;
999
        } else if (unit === 'in') {
1000
            k = 72;
1001
        } else {
1002
            throw ('Invalid unit: ' + unit);
1003
        }
1004
 
1005
        // Dimensions are stored as user units and converted to points on output
1006
        if (pageFormats.hasOwnProperty(format_as_string)) {
1007
            pageHeight = pageFormats[format_as_string][1] / k;
1008
            pageWidth = pageFormats[format_as_string][0] / k;
1009
        } else {
1010
            try {
1011
                pageHeight = format[1];
1012
                pageWidth = format[0];
1013
            } catch (err) {
1014
                throw ('Invalid format: ' + format);
1015
            }
1016
        }
1017
 
1018
        if (orientation === 'p' || orientation === 'portrait') {
1019
            orientation = 'p';
1020
            if (pageWidth > pageHeight) {
1021
                tmp = pageWidth;
1022
                pageWidth = pageHeight;
1023
                pageHeight = tmp;
1024
            }
1025
        } else if (orientation === 'l' || orientation === 'landscape') {
1026
            orientation = 'l';
1027
            if (pageHeight > pageWidth) {
1028
                tmp = pageWidth;
1029
                pageWidth = pageHeight;
1030
                pageHeight = tmp;
1031
            }
1032
        } else {
1033
            throw ('Invalid orientation: ' + orientation);
1034
        }
1035
 
1036
 
1037
 
1038
        //---------------------------------------
1039
        // Public API
1040
 
1041
        /*
1042
        Object exposing internal API to plugins
1043
        @public
1044
        */
1045
        API.internal = {
1046
            'pdfEscape': pdfEscape,
1047
            'getStyle': getStyle,
1048
            /**
1049
            Returns {FontObject} describing a particular font.
1050
            @public
1051
            @function
1052
            @param fontName {String} (Optional) Font's family name
1053
            @param fontStyle {String} (Optional) Font's style variation name (Example:"Italic")
1054
            @returns {FontObject}
1055
            */
1056
            'getFont': function () { return fonts[getFont.apply(API, arguments)]; },
1057
            'getFontSize': function () { return activeFontSize;    },
1058
            'btoa': btoa,
1059
            'write': function (string1, string2, string3, etc) {
1060
                out(
1061
                    arguments.length === 1 ? string1 : Array.prototype.join.call(arguments, ' ')
1062
                );
1063
            },
1064
            'getCoordinateString': function (value) {
1065
                return f2(value * k);
1066
            },
1067
            'getVerticalCoordinateString': function (value) {
1068
                return f2((pageHeight - value) * k);
1069
            },
1070
            'collections': {},
1071
            'newObject': newObject,
1072
            'putStream': putStream,
1073
            'events': events,
1074
            // ratio that you use in multiplication of a given "size" number to arrive to 'point'
1075
            // units of measurement.
1076
            // scaleFactor is set at initialization of the document and calculated against the stated
1077
            // default measurement units for the document.
1078
            // If default is "mm", k is the number that will turn number in 'mm' into 'points' number.
1079
            // through multiplication.
1080
            'scaleFactor': k,
1081
            'pageSize': {'width': pageWidth, 'height': pageHeight},
1082
            'output': function (type, options) {
1083
                return output(type, options);
1084
            }
1085
        };
1086
 
1087
        /**
1088
        Adds (and transfers the focus to) new page to the PDF document.
1089
        @function
1090
        @returns {jsPDF}
1091
 
1092
        @methodOf jsPDF#
1093
        @name addPage
1094
         */
1095
        API.addPage = function () {
1096
            _addPage();
1097
            return this;
1098
        };
1099
 
1100
        /**
1101
        Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings.
1102
        @function
1103
        @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.
1104
        @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
1105
        @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
1106
        @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.
1107
        @returns {jsPDF}
1108
        @methodOf jsPDF#
1109
        @name text
1110
         */
1111
        API.text = function (text, x, y, flags) {
1112
            /**
1113
             * Inserts something like this into PDF
1114
                BT
1115
                /F1 16 Tf  % Font name + size
1116
                16 TL % How many units down for next line in multiline text
1117
 
1118
                28.35 813.54 Td % position
1119
                (line one) Tj
1120
                T* (line two) Tj
1121
                T* (line three) Tj
1122
                ET
1123
            */
1124
 
1125
            var undef, _first, _second, _third, newtext, str, i;
1126
            // Pre-August-2012 the order of arguments was function(x, y, text, flags)
1127
            // in effort to make all calls have similar signature like
1128
            //   function(data, coordinates... , miscellaneous)
1129
            // this method had its args flipped.
1130
            // code below allows backward compatibility with old arg order.
1131
            if (typeof text === 'number') {
1132
                _first = y;
1133
                _second = text;
1134
                _third = x;
1135
 
1136
                text = _first;
1137
                x = _second;
1138
                y = _third;
1139
            }
1140
 
1141
            // If there are any newlines in text, we assume
1142
            // the user wanted to print multiple lines, so break the
1143
            // text up into an array.  If the text is already an array,
1144
            // we assume the user knows what they are doing.
1145
            if (typeof text === 'string' && text.match(/[\n\r]/)) {
1146
                text = text.split(/\r\n|\r|\n/g);
1147
            }
1148
 
1149
            if (typeof flags === 'undefined') {
1150
                flags = {'noBOM': true, 'autoencode': true};
1151
            } else {
1152
 
1153
                if (flags.noBOM === undef) {
1154
                    flags.noBOM = true;
1155
                }
1156
 
1157
                if (flags.autoencode === undef) {
1158
                    flags.autoencode = true;
1159
                }
1160
 
1161
            }
1162
 
1163
            if (typeof text === 'string') {
1164
                str = pdfEscape(text, flags);
1165
            } else if (text instanceof Array) {  /* Array */
1166
                // we don't want to destroy  original text array, so cloning it
1167
                newtext = text.concat();
1168
                // we do array.join('text that must not be PDFescaped")
1169
                // thus, pdfEscape each component separately
1170
                for (i = newtext.length - 1; i !== -1; i--) {
1171
                    newtext[i] = pdfEscape(newtext[i], flags);
1172
                }
1173
                str = newtext.join(") Tj\nT* (");
1174
            } else {
1175
                throw new Error('Type of text must be string or Array. "' + text + '" is not recognized.');
1176
            }
1177
            // Using "'" ("go next line and render text" mark) would save space but would complicate our rendering code, templates
1178
 
1179
            // BT .. ET does NOT have default settings for Tf. You must state that explicitely every time for BT .. ET
1180
            // if you want text transformation matrix (+ multiline) to work reliably (which reads sizes of things from font declarations)
1181
            // Thus, there is NO useful, *reliable* concept of "default" font for a page.
1182
            // The fact that "default" (reuse font used before) font worked before in basic cases is an accident
1183
            // - readers dealing smartly with brokenness of jsPDF's markup.
1184
            out(
1185
                'BT\n/' +
1186
                    activeFontKey + ' ' + activeFontSize + ' Tf\n' + // font face, style, size
1187
                    activeFontSize + ' TL\n' + // line spacing
1188
                    textColor +
1189
                    '\n' + f2(x * k) + ' ' + f2((pageHeight - y) * k) + ' Td\n(' +
1190
                    str +
1191
                    ') Tj\nET'
1192
            );
1193
            return this;
1194
        };
1195
 
1196
        API.line = function (x1, y1, x2, y2) {
1197
            out(
1198
                f2(x1 * k) + ' ' + f2((pageHeight - y1) * k) + ' m ' +
1199
                    f2(x2 * k) + ' ' + f2((pageHeight - y2) * k) + ' l S'
1200
            );
1201
            return this;
1202
        };
1203
 
1204
        /**
1205
        Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates.
1206
        All data points in `lines` are relative to last line origin.
1207
        `x`, `y` become x1,y1 for first line / curve in the set.
1208
        For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point.
1209
        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.
1210
 
1211
        @example .lines([[2,2],[-2,2],[1,1,2,2,3,3],[2,1]], 212,110, 10) // line, line, bezier curve, line
1212
        @param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves).
1213
        @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
1214
        @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
1215
        @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.
1216
        @function
1217
        @returns {jsPDF}
1218
        @methodOf jsPDF#
1219
        @name lines
1220
         */
1221
        API.lines = function (lines, x, y, scale, style) {
1222
            var undef, _first, _second, _third, scalex, scaley, i, l, leg, x2, y2, x3, y3, x4, y4;
1223
 
1224
            // Pre-August-2012 the order of arguments was function(x, y, lines, scale, style)
1225
            // in effort to make all calls have similar signature like
1226
            //   function(content, coordinateX, coordinateY , miscellaneous)
1227
            // this method had its args flipped.
1228
            // code below allows backward compatibility with old arg order.
1229
            if (typeof lines === 'number') {
1230
                _first = y;
1231
                _second = lines;
1232
                _third = x;
1233
 
1234
                lines = _first;
1235
                x = _second;
1236
                y = _third;
1237
            }
1238
 
1239
            style = getStyle(style);
1240
            scale = scale === undef ? [1, 1] : scale;
1241
 
1242
            // starting point
1243
            out(f3(x * k) + ' ' + f3((pageHeight - y) * k) + ' m ');
1244
 
1245
            scalex = scale[0];
1246
            scaley = scale[1];
1247
            l = lines.length;
1248
            //, x2, y2 // bezier only. In page default measurement "units", *after* scaling
1249
            //, x3, y3 // bezier only. In page default measurement "units", *after* scaling
1250
            // ending point for all, lines and bezier. . In page default measurement "units", *after* scaling
1251
            x4 = x; // last / ending point = starting point for first item.
1252
            y4 = y; // last / ending point = starting point for first item.
1253
 
1254
            for (i = 0; i < l; i++) {
1255
                leg = lines[i];
1256
                if (leg.length === 2) {
1257
                    // simple line
1258
                    x4 = leg[0] * scalex + x4; // here last x4 was prior ending point
1259
                    y4 = leg[1] * scaley + y4; // here last y4 was prior ending point
1260
                    out(f3(x4 * k) + ' ' + f3((pageHeight - y4) * k) + ' l');
1261
                } else {
1262
                    // bezier curve
1263
                    x2 = leg[0] * scalex + x4; // here last x4 is prior ending point
1264
                    y2 = leg[1] * scaley + y4; // here last y4 is prior ending point
1265
                    x3 = leg[2] * scalex + x4; // here last x4 is prior ending point
1266
                    y3 = leg[3] * scaley + y4; // here last y4 is prior ending point
1267
                    x4 = leg[4] * scalex + x4; // here last x4 was prior ending point
1268
                    y4 = leg[5] * scaley + y4; // here last y4 was prior ending point
1269
                    out(
1270
                        f3(x2 * k) + ' ' +
1271
                            f3((pageHeight - y2) * k) + ' ' +
1272
                            f3(x3 * k) + ' ' +
1273
                            f3((pageHeight - y3) * k) + ' ' +
1274
                            f3(x4 * k) + ' ' +
1275
                            f3((pageHeight - y4) * k) + ' c'
1276
                    );
1277
                }
1278
            }
1279
            // stroking / filling / both the path
1280
            out(style);
1281
            return this;
1282
        };
1283
 
1284
        /**
1285
        Adds a rectangle to PDF
1286
 
1287
        @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
1288
        @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
1289
        @param {Number} w Width (in units declared at inception of PDF document)
1290
        @param {Number} h Height (in units declared at inception of PDF document)
1291
        @param {String} style (Defaults to active fill/stroke style) A string signalling if stroke, fill or both are to be applied.
1292
        @function
1293
        @returns {jsPDF}
1294
        @methodOf jsPDF#
1295
        @name rect
1296
         */
1297
        API.rect = function (x, y, w, h, style) {
1298
            var op = getStyle(style);
1299
            out([
1300
                f2(x * k),
1301
                f2((pageHeight - y) * k),
1302
                f2(w * k),
1303
                f2(-h * k),
1304
                're',
1305
                op
1306
            ].join(' '));
1307
            return this;
1308
        };
1309
 
1310
        /**
1311
        Adds a triangle to PDF
1312
 
1313
        @param {Number} x1 Coordinate (in units declared at inception of PDF document) against left edge of the page
1314
        @param {Number} y1 Coordinate (in units declared at inception of PDF document) against upper edge of the page
1315
        @param {Number} x2 Coordinate (in units declared at inception of PDF document) against left edge of the page
1316
        @param {Number} y2 Coordinate (in units declared at inception of PDF document) against upper edge of the page
1317
        @param {Number} x3 Coordinate (in units declared at inception of PDF document) against left edge of the page
1318
        @param {Number} y3 Coordinate (in units declared at inception of PDF document) against upper edge of the page
1319
        @param {String} style (Defaults to active fill/stroke style) A string signalling if stroke, fill or both are to be applied.
1320
        @function
1321
        @returns {jsPDF}
1322
        @methodOf jsPDF#
1323
        @name triangle
1324
         */
1325
        API.triangle = function (x1, y1, x2, y2, x3, y3, style) {
1326
            this.lines(
1327
                [
1328
                    [ x2 - x1, y2 - y1 ], // vector to point 2
1329
                    [ x3 - x2, y3 - y2 ], // vector to point 3
1330
                    [ x1 - x3, y1 - y3 ] // closing vector back to point 1
1331
                ],
1332
                x1,
1333
                y1, // start of path
1334
                [1, 1],
1335
                style
1336
            );
1337
            return this;
1338
        };
1339
 
1340
        /**
1341
        Adds a rectangle with rounded corners to PDF
1342
 
1343
        @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
1344
        @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
1345
        @param {Number} w Width (in units declared at inception of PDF document)
1346
        @param {Number} h Height (in units declared at inception of PDF document)
1347
        @param {Number} rx Radius along x axis (in units declared at inception of PDF document)
1348
        @param {Number} rx Radius along y axis (in units declared at inception of PDF document)
1349
        @param {String} style (Defaults to active fill/stroke style) A string signalling if stroke, fill or both are to be applied.
1350
        @function
1351
        @returns {jsPDF}
1352
        @methodOf jsPDF#
1353
        @name roundedRect
1354
        */
1355
        API.roundedRect = function (x, y, w, h, rx, ry, style) {
1356
            var MyArc = 4 / 3 * (Math.SQRT2 - 1);
1357
            this.lines(
1358
                [
1359
                    [ (w - 2 * rx), 0 ],
1360
                    [ (rx * MyArc), 0, rx, ry - (ry * MyArc), rx, ry ],
1361
                    [ 0, (h - 2 * ry) ],
1362
                    [ 0, (ry * MyArc), -(rx * MyArc), ry, -rx, ry],
1363
                    [ (-w + 2 * rx), 0],
1364
                    [ -(rx * MyArc), 0, -rx, -(ry * MyArc), -rx, -ry],
1365
                    [ 0, (-h + 2 * ry)],
1366
                    [ 0, -(ry * MyArc), (rx * MyArc), -ry, rx, -ry]
1367
                ],
1368
                x + rx,
1369
                y, // start of path
1370
                [1, 1],
1371
                style
1372
            );
1373
            return this;
1374
        };
1375
 
1376
        /**
1377
        Adds an ellipse to PDF
1378
 
1379
        @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
1380
        @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
1381
        @param {Number} rx Radius along x axis (in units declared at inception of PDF document)
1382
        @param {Number} rx Radius along y axis (in units declared at inception of PDF document)
1383
        @param {String} style (Defaults to active fill/stroke style) A string signalling if stroke, fill or both are to be applied.
1384
        @function
1385
        @returns {jsPDF}
1386
        @methodOf jsPDF#
1387
        @name ellipse
1388
         */
1389
        API.ellipse = function (x, y, rx, ry, style) {
1390
            var op = getStyle(style),
1391
                lx = 4 / 3 * (Math.SQRT2 - 1) * rx,
1392
                ly = 4 / 3 * (Math.SQRT2 - 1) * ry;
1393
 
1394
            out([
1395
                f2((x + rx) * k),
1396
                f2((pageHeight - y) * k),
1397
                'm',
1398
                f2((x + rx) * k),
1399
                f2((pageHeight - (y - ly)) * k),
1400
                f2((x + lx) * k),
1401
                f2((pageHeight - (y - ry)) * k),
1402
                f2(x * k),
1403
                f2((pageHeight - (y - ry)) * k),
1404
                'c'
1405
            ].join(' '));
1406
            out([
1407
                f2((x - lx) * k),
1408
                f2((pageHeight - (y - ry)) * k),
1409
                f2((x - rx) * k),
1410
                f2((pageHeight - (y - ly)) * k),
1411
                f2((x - rx) * k),
1412
                f2((pageHeight - y) * k),
1413
                'c'
1414
            ].join(' '));
1415
            out([
1416
                f2((x - rx) * k),
1417
                f2((pageHeight - (y + ly)) * k),
1418
                f2((x - lx) * k),
1419
                f2((pageHeight - (y + ry)) * k),
1420
                f2(x * k),
1421
                f2((pageHeight - (y + ry)) * k),
1422
                'c'
1423
            ].join(' '));
1424
            out([
1425
                f2((x + lx) * k),
1426
                f2((pageHeight - (y + ry)) * k),
1427
                f2((x + rx) * k),
1428
                f2((pageHeight - (y + ly)) * k),
1429
                f2((x + rx) * k),
1430
                f2((pageHeight - y) * k),
1431
                'c',
1432
                op
1433
            ].join(' '));
1434
            return this;
1435
        };
1436
 
1437
        /**
1438
        Adds an circle to PDF
1439
 
1440
        @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
1441
        @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
1442
        @param {Number} r Radius (in units declared at inception of PDF document)
1443
        @param {String} style (Defaults to active fill/stroke style) A string signalling if stroke, fill or both are to be applied.
1444
        @function
1445
        @returns {jsPDF}
1446
        @methodOf jsPDF#
1447
        @name circle
1448
         */
1449
        API.circle = function (x, y, r, style) {
1450
            return this.ellipse(x, y, r, r, style);
1451
        };
1452
 
1453
        /**
1454
        Adds a properties to the PDF document
1455
 
1456
        @param {Object} A property_name-to-property_value object structure.
1457
        @function
1458
        @returns {jsPDF}
1459
        @methodOf jsPDF#
1460
        @name setProperties
1461
         */
1462
        API.setProperties = function (properties) {
1463
            // copying only those properties we can render.
1464
            var property;
1465
            for (property in documentProperties) {
1466
                if (documentProperties.hasOwnProperty(property) && properties[property]) {
1467
                    documentProperties[property] = properties[property];
1468
                }
1469
            }
1470
            return this;
1471
        };
1472
 
1473
        /**
1474
        Sets font size for upcoming text elements.
1475
 
1476
        @param {Number} size Font size in points.
1477
        @function
1478
        @returns {jsPDF}
1479
        @methodOf jsPDF#
1480
        @name setFontSize
1481
         */
1482
        API.setFontSize = function (size) {
1483
            activeFontSize = size;
1484
            return this;
1485
        };
1486
 
1487
        /**
1488
        Sets text font face, variant for upcoming text elements.
1489
        See output of jsPDF.getFontList() for possible font names, styles.
1490
 
1491
        @param {String} fontName Font name or family. Example: "times"
1492
        @param {String} fontStyle Font style or variant. Example: "italic"
1493
        @function
1494
        @returns {jsPDF}
1495
        @methodOf jsPDF#
1496
        @name setFont
1497
         */
1498
        API.setFont = function (fontName, fontStyle) {
1499
            activeFontKey = getFont(fontName, fontStyle);
1500
            // if font is not found, the above line blows up and we never go further
1501
            return this;
1502
        };
1503
 
1504
        /**
1505
        Switches font style or variant for upcoming text elements,
1506
        while keeping the font face or family same.
1507
        See output of jsPDF.getFontList() for possible font names, styles.
1508
 
1509
        @param {String} style Font style or variant. Example: "italic"
1510
        @function
1511
        @returns {jsPDF}
1512
        @methodOf jsPDF#
1513
        @name setFontStyle
1514
         */
1515
        API.setFontStyle = API.setFontType = function (style) {
1516
            var undef;
1517
            activeFontKey = getFont(undef, style);
1518
            // if font is not found, the above line blows up and we never go further
1519
            return this;
1520
        };
1521
 
1522
        /**
1523
        Returns an object - a tree of fontName to fontStyle relationships available to
1524
        active PDF document.
1525
 
1526
        @public
1527
        @function
1528
        @returns {Object} Like {'times':['normal', 'italic', ... ], 'arial':['normal', 'bold', ... ], ... }
1529
        @methodOf jsPDF#
1530
        @name getFontList
1531
        */
1532
        API.getFontList = function () {
1533
            // TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added.
1534
            var list = {},
1535
                fontName,
1536
                fontStyle,
1537
                tmp;
1538
 
1539
            for (fontName in fontmap) {
1540
                if (fontmap.hasOwnProperty(fontName)) {
1541
                    list[fontName] = tmp = [];
1542
                    for (fontStyle in fontmap[fontName]) {
1543
                        if (fontmap[fontName].hasOwnProperty(fontStyle)) {
1544
                            tmp.push(fontStyle);
1545
                        }
1546
                    }
1547
                }
1548
            }
1549
 
1550
            return list;
1551
        };
1552
 
1553
        /**
1554
        Sets line width for upcoming lines.
1555
 
1556
        @param {Number} width Line width (in units declared at inception of PDF document)
1557
        @function
1558
        @returns {jsPDF}
1559
        @methodOf jsPDF#
1560
        @name setLineWidth
1561
         */
1562
        API.setLineWidth = function (width) {
1563
            out((width * k).toFixed(2) + ' w');
1564
            return this;
1565
        };
1566
 
1567
        /**
1568
        Sets the stroke color for upcoming elements.
1569
 
1570
        Depending on the number of arguments given, Gray, RGB, or CMYK
1571
        color space is implied.
1572
 
1573
        When only ch1 is given, "Gray" color space is implied and it
1574
        must be a value in the range from 0.00 (solid black) to to 1.00 (white)
1575
        if values are communicated as String types, or in range from 0 (black)
1576
        to 255 (white) if communicated as Number type.
1577
        The RGB-like 0-255 range is provided for backward compatibility.
1578
 
1579
        When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
1580
        value must be in the range from 0.00 (minimum intensity) to to 1.00
1581
        (max intensity) if values are communicated as String types, or
1582
        from 0 (min intensity) to to 255 (max intensity) if values are communicated
1583
        as Number types.
1584
        The RGB-like 0-255 range is provided for backward compatibility.
1585
 
1586
        When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
1587
        value must be a in the range from 0.00 (0% concentration) to to
1588
        1.00 (100% concentration)
1589
 
1590
        Because JavaScript treats fixed point numbers badly (rounds to
1591
        floating point nearest to binary representation) it is highly advised to
1592
        communicate the fractional numbers as String types, not JavaScript Number type.
1593
 
1594
        @param {Number|String} ch1 Color channel value
1595
        @param {Number|String} ch2 Color channel value
1596
        @param {Number|String} ch3 Color channel value
1597
        @param {Number|String} ch4 Color channel value
1598
 
1599
        @function
1600
        @returns {jsPDF}
1601
        @methodOf jsPDF#
1602
        @name setDrawColor
1603
         */
1604
        API.setDrawColor = function (ch1, ch2, ch3, ch4) {
1605
            var color;
1606
            if (ch2 === undefined || (ch4 === undefined && ch1 === ch2 === ch3)) {
1607
                // Gray color space.
1608
                if (typeof ch1 === 'string') {
1609
                    color = ch1 + ' G';
1610
                } else {
1611
                    color = f2(ch1 / 255) + ' G';
1612
                }
1613
            } else if (ch4 === undefined) {
1614
                // RGB
1615
                if (typeof ch1 === 'string') {
1616
                    color = [ch1, ch2, ch3, 'RG'].join(' ');
1617
                } else {
1618
                    color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), 'RG'].join(' ');
1619
                }
1620
            } else {
1621
                // CMYK
1622
                if (typeof ch1 === 'string') {
1623
                    color = [ch1, ch2, ch3, ch4, 'K'].join(' ');
1624
                } else {
1625
                    color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), 'K'].join(' ');
1626
                }
1627
            }
1628
 
1629
            out(color);
1630
            return this;
1631
        };
1632
 
1633
        /**
1634
        Sets the fill color for upcoming elements.
1635
 
1636
        Depending on the number of arguments given, Gray, RGB, or CMYK
1637
        color space is implied.
1638
 
1639
        When only ch1 is given, "Gray" color space is implied and it
1640
        must be a value in the range from 0.00 (solid black) to to 1.00 (white)
1641
        if values are communicated as String types, or in range from 0 (black)
1642
        to 255 (white) if communicated as Number type.
1643
        The RGB-like 0-255 range is provided for backward compatibility.
1644
 
1645
        When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
1646
        value must be in the range from 0.00 (minimum intensity) to to 1.00
1647
        (max intensity) if values are communicated as String types, or
1648
        from 0 (min intensity) to to 255 (max intensity) if values are communicated
1649
        as Number types.
1650
        The RGB-like 0-255 range is provided for backward compatibility.
1651
 
1652
        When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
1653
        value must be a in the range from 0.00 (0% concentration) to to
1654
        1.00 (100% concentration)
1655
 
1656
        Because JavaScript treats fixed point numbers badly (rounds to
1657
        floating point nearest to binary representation) it is highly advised to
1658
        communicate the fractional numbers as String types, not JavaScript Number type.
1659
 
1660
        @param {Number|String} ch1 Color channel value
1661
        @param {Number|String} ch2 Color channel value
1662
        @param {Number|String} ch3 Color channel value
1663
        @param {Number|String} ch4 Color channel value
1664
 
1665
        @function
1666
        @returns {jsPDF}
1667
        @methodOf jsPDF#
1668
        @name setFillColor
1669
         */
1670
        API.setFillColor = function (ch1, ch2, ch3, ch4) {
1671
            var color;
1672
 
1673
            if (ch2 === undefined || (ch4 === undefined && ch1 === ch2 === ch3)) {
1674
                // Gray color space.
1675
                if (typeof ch1 === 'string') {
1676
                    color = ch1 + ' g';
1677
                } else {
1678
                    color = f2(ch1 / 255) + ' g';
1679
                }
1680
            } else if (ch4 === undefined) {
1681
                // RGB
1682
                if (typeof ch1 === 'string') {
1683
                    color = [ch1, ch2, ch3, 'rg'].join(' ');
1684
                } else {
1685
                    color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), 'rg'].join(' ');
1686
                }
1687
            } else {
1688
                // CMYK
1689
                if (typeof ch1 === 'string') {
1690
                    color = [ch1, ch2, ch3, ch4, 'k'].join(' ');
1691
                } else {
1692
                    color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), 'k'].join(' ');
1693
                }
1694
            }
1695
 
1696
            out(color);
1697
            return this;
1698
        };
1699
 
1700
        /**
1701
        Sets the text color for upcoming elements.
1702
        If only one, first argument is given,
1703
        treats the value as gray-scale color value.
1704
 
1705
        @param {Number} r Red channel color value in range 0-255
1706
        @param {Number} g Green channel color value in range 0-255
1707
        @param {Number} b Blue channel color value in range 0-255
1708
        @function
1709
        @returns {jsPDF}
1710
        @methodOf jsPDF#
1711
        @name setTextColor
1712
        */
1713
        API.setTextColor = function (r, g, b) {
1714
            if ((r === 0 && g === 0 && b === 0) || (typeof g === 'undefined')) {
1715
                textColor = f3(r / 255) + ' g';
1716
            } else {
1717
                textColor = [f3(r / 255), f3(g / 255), f3(b / 255), 'rg'].join(' ');
1718
            }
1719
            return this;
1720
        };
1721
 
1722
        /**
1723
        Is an Object providing a mapping from human-readable to
1724
        integer flag values designating the varieties of line cap
1725
        and join styles.
1726
 
1727
        @returns {Object}
1728
        @fieldOf jsPDF#
1729
        @name CapJoinStyles
1730
        */
1731
        API.CapJoinStyles = {
1732
            0: 0,
1733
            'butt': 0,
1734
            'but': 0,
1735
            'bevel': 0,
1736
            1: 1,
1737
            'round': 1,
1738
            'rounded': 1,
1739
            'circle': 1,
1740
            2: 2,
1741
            'projecting': 2,
1742
            'project': 2,
1743
            'square': 2,
1744
            'milter': 2
1745
        };
1746
 
1747
        /**
1748
        Sets the line cap styles
1749
        See {jsPDF.CapJoinStyles} for variants
1750
 
1751
        @param {String|Number} style A string or number identifying the type of line cap
1752
        @function
1753
        @returns {jsPDF}
1754
        @methodOf jsPDF#
1755
        @name setLineCap
1756
        */
1757
        API.setLineCap = function (style) {
1758
            var id = this.CapJoinStyles[style];
1759
            if (id === undefined) {
1760
                throw new Error("Line cap style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
1761
            }
1762
            lineCapID = id;
1763
            out(id.toString(10) + ' J');
1764
 
1765
            return this;
1766
        };
1767
 
1768
        /**
1769
        Sets the line join styles
1770
        See {jsPDF.CapJoinStyles} for variants
1771
 
1772
        @param {String|Number} style A string or number identifying the type of line join
1773
        @function
1774
        @returns {jsPDF}
1775
        @methodOf jsPDF#
1776
        @name setLineJoin
1777
        */
1778
        API.setLineJoin = function (style) {
1779
            var id = this.CapJoinStyles[style];
1780
            if (id === undefined) {
1781
                throw new Error("Line join style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
1782
            }
1783
            lineJoinID = id;
1784
            out(id.toString(10) + ' j');
1785
 
1786
            return this;
1787
        };
1788
 
1789
        // Output is both an internal (for plugins) and external function
1790
        API.output = output;
1791
 
1792
        /**
1793
         * Saves as PDF document. An alias of jsPDF.output('save', 'filename.pdf')
1794
         * @param  {String} filename The filename including extension.
1795
         *
1796
         * @function
1797
         * @returns {jsPDF}
1798
         * @methodOf jsPDF#
1799
         * @name save
1800
         */
1801
        API.save = function (filename) {
1802
            API.output('save', filename);
1803
        };
1804
 
1805
        // applying plugins (more methods) ON TOP of built-in API.
1806
        // this is intentional as we allow plugins to override
1807
        // built-ins
1808
        for (plugin in jsPDF.API) {
1809
            if (jsPDF.API.hasOwnProperty(plugin)) {
1810
                if (plugin === 'events' && jsPDF.API.events.length) {
1811
                    (function (events, newEvents) {
1812
 
1813
                        // jsPDF.API.events is a JS Array of Arrays
1814
                        // where each Array is a pair of event name, handler
1815
                        // Events were added by plugins to the jsPDF instantiator.
1816
                        // These are always added to the new instance and some ran
1817
                        // during instantiation.
1818
 
1819
                        var eventname, handler_and_args, i;
1820
 
1821
                        for (i = newEvents.length - 1; i !== -1; i--) {
1822
                            // subscribe takes 3 args: 'topic', function, runonce_flag
1823
                            // if undefined, runonce is false.
1824
                            // users can attach callback directly,
1825
                            // or they can attach an array with [callback, runonce_flag]
1826
                            // that's what the "apply" magic is for below.
1827
                            eventname = newEvents[i][0];
1828
                            handler_and_args = newEvents[i][1];
1829
                            events.subscribe.apply(
1830
                                events,
1831
                                [eventname].concat(
1832
                                    typeof handler_and_args === 'function' ?
1833
                                            [ handler_and_args ] :
1834
                                            handler_and_args
1835
                                )
1836
                            );
1837
                        }
1838
                    }(events, jsPDF.API.events));
1839
                } else {
1840
                    API[plugin] = jsPDF.API[plugin];
1841
                }
1842
            }
1843
        }
1844
 
1845
        /////////////////////////////////////////
1846
        // continuing initilisation of jsPDF Document object
1847
        /////////////////////////////////////////
1848
 
1849
 
1850
        // Add the first page automatically
1851
        addFonts();
1852
        activeFontKey = 'F1';
1853
        _addPage();
1854
 
1855
        events.publish('initialized');
1856
 
1857
        return API;
1858
    }
1859
 
1860
/**
1861
jsPDF.API is a STATIC property of jsPDF class.
1862
jsPDF.API is an object you can add methods and properties to.
1863
The methods / properties you add will show up in new jsPDF objects.
1864
 
1865
One property is prepopulated. It is the 'events' Object. Plugin authors can add topics, callbacks to this object. These will be reassigned to all new instances of jsPDF.
1866
Examples:
1867
    jsPDF.API.events['initialized'] = function(){ 'this' is API object }
1868
    jsPDF.API.events['addFont'] = function(added_font_object){ 'this' is API object }
1869
 
1870
@static
1871
@public
1872
@memberOf jsPDF
1873
@name API
1874
 
1875
@example
1876
    jsPDF.API.mymethod = function(){
1877
        // 'this' will be ref to internal API object. see jsPDF source
1878
        // , so you can refer to built-in methods like so:
1879
        //     this.line(....)
1880
        //     this.text(....)
1881
    }
1882
    var pdfdoc = new jsPDF()
1883
    pdfdoc.mymethod() // <- !!!!!!
1884
*/
1885
    jsPDF.API = {'events': []};
1886
 
1887
    return jsPDF;
1888
}());
1889
/** @preserve
1890
jsPDF addImage plugin (JPEG only at this time)
1891
Copyright (c) 2012 https://github.com/siefkenj/
1892
*/
1893
 
1894
/**
1895
 * Permission is hereby granted, free of charge, to any person obtaining
1896
 * a copy of this software and associated documentation files (the
1897
 * "Software"), to deal in the Software without restriction, including
1898
 * without limitation the rights to use, copy, modify, merge, publish,
1899
 * distribute, sublicense, and/or sell copies of the Software, and to
1900
 * permit persons to whom the Software is furnished to do so, subject to
1901
 * the following conditions:
1902
 *
1903
 * The above copyright notice and this permission notice shall be
1904
 * included in all copies or substantial portions of the Software.
1905
 *
1906
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1907
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1908
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1909
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
1910
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1911
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1912
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1913
 * ====================================================================
1914
 */
1915
 
1916
;(function(jsPDFAPI) {
1917
'use strict'
1918
 
1919
var namespace = 'addImage_'
1920
 
1921
// takes a string imgData containing the raw bytes of
1922
// a jpeg image and returns [width, height]
1923
// Algorithm from: http://www.64lines.com/jpeg-width-height
1924
var getJpegSize = function(imgData) {
1925
	'use strict'
1926
	var width, height;
1927
	// Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00
1928
	if (!imgData.charCodeAt(0) === 0xff ||
1929
		!imgData.charCodeAt(1) === 0xd8 ||
1930
		!imgData.charCodeAt(2) === 0xff ||
1931
		!imgData.charCodeAt(3) === 0xe0 ||
1932
		!imgData.charCodeAt(6) === 'J'.charCodeAt(0) ||
1933
		!imgData.charCodeAt(7) === 'F'.charCodeAt(0) ||
1934
		!imgData.charCodeAt(8) === 'I'.charCodeAt(0) ||
1935
		!imgData.charCodeAt(9) === 'F'.charCodeAt(0) ||
1936
		!imgData.charCodeAt(10) === 0x00) {
1937
			throw new Error('getJpegSize requires a binary jpeg file')
1938
	}
1939
	var blockLength = imgData.charCodeAt(4)*256 + imgData.charCodeAt(5);
1940
	var i = 4, len = imgData.length;
1941
	while ( i < len ) {
1942
		i += blockLength;
1943
		if (imgData.charCodeAt(i) !== 0xff) {
1944
			throw new Error('getJpegSize could not find the size of the image');
1945
		}
1946
		if (imgData.charCodeAt(i+1) === 0xc0) {
1947
			height = imgData.charCodeAt(i+5)*256 + imgData.charCodeAt(i+6);
1948
			width = imgData.charCodeAt(i+7)*256 + imgData.charCodeAt(i+8);
1949
			return [width, height];
1950
		} else {
1951
			i += 2;
1952
			blockLength = imgData.charCodeAt(i)*256 + imgData.charCodeAt(i+1)
1953
		}
1954
	}
1955
}
1956
// Image functionality ported from pdf.js
1957
, putImage = function(img) {
1958
	var objectNumber = this.internal.newObject()
1959
	, out = this.internal.write
1960
	, putStream = this.internal.putStream
1961
 
1962
	img['n'] = objectNumber
1963
 
1964
	out('<</Type /XObject')
1965
	out('/Subtype /Image')
1966
	out('/Width ' + img['w'])
1967
	out('/Height ' + img['h'])
1968
	if (img['cs'] === 'Indexed') {
1969
		out('/ColorSpace [/Indexed /DeviceRGB '
1970
				+ (img['pal'].length / 3 - 1) + ' ' + (objectNumber + 1)
1971
				+ ' 0 R]');
1972
	} else {
1973
		out('/ColorSpace /' + img['cs']);
1974
		if (img['cs'] === 'DeviceCMYK') {
1975
			out('/Decode [1 0 1 0 1 0 1 0]');
1976
		}
1977
	}
1978
	out('/BitsPerComponent ' + img['bpc']);
1979
	if ('f' in img) {
1980
		out('/Filter /' + img['f']);
1981
	}
1982
	if ('dp' in img) {
1983
		out('/DecodeParms <<' + img['dp'] + '>>');
1984
	}
1985
	if ('trns' in img && img['trns'].constructor == Array) {
1986
		var trns = '';
1987
		for ( var i = 0; i < img['trns'].length; i++) {
1988
			trns += (img[trns][i] + ' ' + img['trns'][i] + ' ');
1989
			out('/Mask [' + trns + ']');
1990
		}
1991
	}
1992
	if ('smask' in img) {
1993
		out('/SMask ' + (objectNumber + 1) + ' 0 R');
1994
	}
1995
	out('/Length ' + img['data'].length + '>>');
1996
 
1997
	putStream(img['data']);
1998
 
1999
	out('endobj');
2000
}
2001
, putResourcesCallback = function() {
2002
	var images = this.internal.collections[namespace + 'images']
2003
	for ( var i in images ) {
2004
		putImage.call(this, images[i])
2005
	}
2006
}
2007
, putXObjectsDictCallback = function(){
2008
	var images = this.internal.collections[namespace + 'images']
2009
	, out = this.internal.write
2010
	, image
2011
	for (var i in images) {
2012
		image = images[i]
2013
		out(
2014
			'/I' + image['i']
2015
			, image['n']
2016
			, '0'
2017
			, 'R'
2018
		)
2019
	}
2020
}
2021
 
2022
jsPDFAPI.addImage = function(imageData, format, x, y, w, h) {
2023
	'use strict'
2024
	if (typeof imageData === 'object' && imageData.nodeType === 1) {
2025
        var canvas = document.createElement('canvas');
2026
        canvas.width = imageData.clientWidth;
2027
	    canvas.height = imageData.clientHeight;
2028
 
2029
        var ctx = canvas.getContext('2d');
2030
        if (!ctx) {
2031
            throw ('addImage requires canvas to be supported by browser.');
2032
        }
2033
        ctx.drawImage(imageData, 0, 0, canvas.width, canvas.height);
2034
        imageData = canvas.toDataURL('image/jpeg');
2035
	    format = "JPEG";
2036
	}
2037
	if (format.toUpperCase() !== 'JPEG') {
2038
		throw new Error('addImage currently only supports format \'JPEG\', not \''+format+'\'');
2039
	}
2040
 
2041
	var imageIndex
2042
	, images = this.internal.collections[namespace + 'images']
2043
	, coord = this.internal.getCoordinateString
2044
	, vcoord = this.internal.getVerticalCoordinateString;
2045
 
2046
	// Detect if the imageData is raw binary or Data URL
2047
	if (imageData.substring(0, 23) === 'data:image/jpeg;base64,') {
2048
		imageData = atob(imageData.replace('data:image/jpeg;base64,', ''));
2049
	}
2050
 
2051
	if (images){
2052
		// this is NOT the first time this method is ran on this instance of jsPDF object.
2053
		imageIndex = Object.keys ?
2054
		Object.keys(images).length :
2055
		(function(o){
2056
			var i = 0
2057
			for (var e in o){if(o.hasOwnProperty(e)){ i++ }}
2058
			return i
2059
		})(images)
2060
	} else {
2061
		// this is the first time this method is ran on this instance of jsPDF object.
2062
		imageIndex = 0
2063
		this.internal.collections[namespace + 'images'] = images = {}
2064
		this.internal.events.subscribe('putResources', putResourcesCallback)
2065
		this.internal.events.subscribe('putXobjectDict', putXObjectsDictCallback)
2066
	}
2067
 
2068
	var dims = getJpegSize(imageData);
2069
	var info = {
2070
		w : dims[0],
2071
		h : dims[1],
2072
		cs : 'DeviceRGB',
2073
		bpc : 8,
2074
		f : 'DCTDecode',
2075
		i : imageIndex,
2076
		data : imageData
2077
		// n: objectNumber will be added by putImage code
2078
 
2079
	};
2080
	images[imageIndex] = info
2081
	if (!w && !h) {
2082
		w = -96;
2083
		h = -96;
2084
	}
2085
	if (w < 0) {
2086
		w = (-1) * info['w'] * 72 / w / this.internal.scaleFactor;
2087
	}
2088
	if (h < 0) {
2089
		h = (-1) * info['h'] * 72 / h / this.internal.scaleFactor;
2090
	}
2091
	if (w === 0) {
2092
		w = h * info['w'] / info['h'];
2093
	}
2094
	if (h === 0) {
2095
		h = w * info['h'] / info['w'];
2096
	}
2097
 
2098
	this.internal.write(
2099
		'q'
2100
		, coord(w)
2101
		, '0 0'
2102
		, coord(h) // TODO: check if this should be shifted by vcoord
2103
		, coord(x)
2104
		, vcoord(y + h)
2105
		, 'cm /I'+info['i']
2106
		, 'Do Q'
2107
	)
2108
 
2109
	return this
2110
}
2111
})(jsPDF.API)
2112
/** @preserve
2113
jsPDF fromHTML plugin. BETA stage. API subject to change. Needs browser, jQuery
2114
Copyright (c) 2012 2012 Willow Systems Corporation, willow-systems.com
2115
*/
2116
/*
2117
 * Permission is hereby granted, free of charge, to any person obtaining
2118
 * a copy of this software and associated documentation files (the
2119
 * "Software"), to deal in the Software without restriction, including
2120
 * without limitation the rights to use, copy, modify, merge, publish,
2121
 * distribute, sublicense, and/or sell copies of the Software, and to
2122
 * permit persons to whom the Software is furnished to do so, subject to
2123
 * the following conditions:
2124
 *
2125
 * The above copyright notice and this permission notice shall be
2126
 * included in all copies or substantial portions of the Software.
2127
 *
2128
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2129
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2130
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2131
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
2132
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2133
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2134
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2135
 * ====================================================================
2136
 */
2137
 
2138
;(function(jsPDFAPI) {
2139
'use strict'
2140
 
2141
 
2142
if(!String.prototype.trim) {
2143
  String.prototype.trim = function () {
2144
    return this.replace(/^\s+|\s+$/g,'');
2145
  };
2146
}
2147
if(!String.prototype.trimLeft) {
2148
  String.prototype.trimLeft = function () {
2149
    return this.replace(/^\s+/g,'');
2150
  };
2151
}
2152
if(!String.prototype.trimRight) {
2153
  String.prototype.trimRight = function () {
2154
    return this.replace(/\s+$/g,'');
2155
  };
2156
}
2157
 
2158
function PurgeWhiteSpace(array){
2159
	var i = 0, l = array.length, fragment
2160
	, lTrimmed = false
2161
	, rTrimmed = false
2162
 
2163
	while (!lTrimmed && i !== l) {
2164
		fragment = array[i] = array[i].trimLeft()
2165
		if (fragment) {
2166
			// there is something left there.
2167
			lTrimmed = true
2168
		}
2169
		;i++;
2170
	}
2171
 
2172
	i = l - 1
2173
	while (l && !rTrimmed && i !== -1) {
2174
		fragment = array[i] = array[i].trimRight()
2175
		if (fragment) {
2176
			// there is something left there.
2177
			rTrimmed = true
2178
		}
2179
		;i--;
2180
	}
2181
 
2182
	var r = /\s+$/g
2183
	, trailingSpace = true // it's safe to assume we always trim start of display:block element's text.
2184
 
2185
	for (i = 0; i !== l; i++) {
2186
		fragment = array[i].replace(/\s+/g, ' ')
2187
		// if (l > 1) {
2188
		// 	console.log(i, trailingSpace, fragment)
2189
		// }
2190
		if (trailingSpace) {
2191
			fragment = fragment.trimLeft()
2192
		}
2193
		if (fragment) {
2194
			// meaning, it was not reduced to ""
2195
			// if it was, we don't want to clear trailingSpace flag.
2196
			trailingSpace = r.test(fragment)
2197
		}
2198
		array[i] = fragment
2199
	}
2200
 
2201
	return array
2202
}
2203
 
2204
function Renderer(pdf, x, y, settings) {
2205
	this.pdf = pdf
2206
	this.x = x
2207
	this.y = y
2208
	this.settings = settings
2209
 
2210
	this.init()
2211
 
2212
	return this
2213
}
2214
 
2215
Renderer.prototype.init = function(){
2216
 
2217
	this.paragraph = {
2218
		'text': []
2219
		, 'style': []
2220
	}
2221
 
2222
	this.pdf.internal.write(
2223
		'q'
2224
	)
2225
}
2226
 
2227
Renderer.prototype.dispose = function(){
2228
	this.pdf.internal.write(
2229
		'Q' // closes the 'q' in init()
2230
	)
2231
	return {
2232
		'x':this.x, 'y':this.y // bottom left of last line. = upper left of what comes after us.
2233
		// TODO: we cannot traverse pages yet, but need to figure out how to communicate that when we do.
2234
		// TODO: add more stats: number of lines, paragraphs etc.
2235
	}
2236
}
2237
 
2238
Renderer.prototype.splitFragmentsIntoLines = function(fragments, styles){
2239
	var defaultFontSize = 12 // points
2240
	, k = this.pdf.internal.scaleFactor // when multiplied by this, converts jsPDF instance units into 'points'
2241
 
2242
	// var widths = options.widths ? options.widths : this.internal.getFont().metadata.Unicode.widths
2243
	// , kerning = options.kerning ? options.kerning : this.internal.getFont().metadata.Unicode.kerning
2244
	, fontMetricsCache = {}
2245
	, ff, fs
2246
	, fontMetrics
2247
 
2248
	, fragment // string, element of `fragments`
2249
	, style // object with properties with names similar to CSS. Holds pertinent style info for given fragment
2250
	, fragmentSpecificMetrics // fontMetrics + some indent and sizing properties populated. We reuse it, hence the bother.
2251
	, fragmentLength // fragment's length in jsPDF units
2252
	, fragmentChopped // will be array - fragment split into "lines"
2253
 
2254
	, line = [] // array of pairs of arrays [t,s], where t is text string, and s is style object for that t.
2255
	, lines = [line] // array of arrays of pairs of arrays
2256
	, currentLineLength = 0 // in jsPDF instance units (inches, cm etc)
2257
	, maxLineLength = this.settings.width // need to decide if this is the best way to know width of content.
2258
 
2259
	// this loop sorts text fragments (and associated style)
2260
	// into lines. Some fragments will be chopped into smaller
2261
	// fragments to be spread over multiple lines.
2262
	while (fragments.length) {
2263
 
2264
		fragment = fragments.shift()
2265
		style = styles.shift()
2266
 
2267
		// if not empty string
2268
		if (fragment) {
2269
 
2270
			ff = style['font-family']
2271
			fs = style['font-style']
2272
 
2273
			fontMetrics = fontMetricsCache[ff+fs]
2274
			if (!fontMetrics) {
2275
				fontMetrics = this.pdf.internal.getFont(ff, fs).metadata.Unicode
2276
				fontMetricsCache[ff+fs] = fontMetrics
2277
			}
2278
 
2279
			fragmentSpecificMetrics = {
2280
				'widths': fontMetrics.widths
2281
				, 'kerning': fontMetrics.kerning
2282
 
2283
				// fontSize comes to us from CSS scraper as "proportion of normal" value
2284
				// , hence the multiplication
2285
				, 'fontSize': style['font-size'] * defaultFontSize
2286
 
2287
				// // these should not matter as we provide the metrics manually
2288
				// // if we would not, we would need these:
2289
				// , 'fontName': style.fontName
2290
				// , 'fontStyle': style.fontStyle
2291
 
2292
				// this is setting for "indent first line of paragraph", but we abuse it
2293
				// for continuing inline spans of text. Indent value = space in jsPDF instance units
2294
				// (whatever user passed to 'new jsPDF(orientation, units, size)
2295
				// already consumed on this line. May be zero, of course, for "start of line"
2296
				// it's used only on chopper, ignored in all "sizing" code
2297
				, 'textIndent': currentLineLength
2298
			}
2299
 
2300
			// in user units (inch, cm etc.)
2301
			fragmentLength = this.pdf.getStringUnitWidth(
2302
				fragment
2303
				, fragmentSpecificMetrics
2304
			) * fragmentSpecificMetrics.fontSize / k
2305
 
2306
			if (currentLineLength + fragmentLength > maxLineLength) {
2307
				// whatever is already on the line + this new fragment
2308
				// will be longer than max len for a line.
2309
				// Hence, chopping fragment into lines:
2310
				fragmentChopped = this.pdf.splitTextToSize(
2311
					fragment
2312
					, maxLineLength
2313
					, fragmentSpecificMetrics
2314
				)
2315
 
2316
				line.push([fragmentChopped.shift(), style])
2317
				while (fragmentChopped.length){
2318
					line = [[fragmentChopped.shift(), style]]
2319
					lines.push(line)
2320
				}
2321
 
2322
				currentLineLength = this.pdf.getStringUnitWidth(
2323
					// new line's first (and only) fragment's length is our new line length
2324
					line[0][0]
2325
					, fragmentSpecificMetrics
2326
				) * fragmentSpecificMetrics.fontSize / k
2327
			} else {
2328
				// nice, we can fit this fragment on current line. Less work for us...
2329
				line.push([fragment, style])
2330
				currentLineLength += fragmentLength
2331
			}
2332
		}
2333
	}
2334
 
2335
	return lines
2336
}
2337
 
2338
Renderer.prototype.RenderTextFragment = function(text, style) {
2339
 
2340
	var defaultFontSize = 12
2341
	// , header = "/F1 16 Tf\n16 TL\n0 g"
2342
	, font = this.pdf.internal.getFont(style['font-family'], style['font-style'])
2343
 
2344
	this.pdf.internal.write(
2345
		'/' + font.id // font key
2346
		, (defaultFontSize * style['font-size']).toFixed(2) // font size comes as float = proportion to normal.
2347
		, 'Tf' // font def marker
2348
		, '('+this.pdf.internal.pdfEscape(text)+') Tj'
2349
	)
2350
}
2351
 
2352
Renderer.prototype.renderParagraph = function(){
2353
 
2354
	var fragments = PurgeWhiteSpace( this.paragraph.text )
2355
	, styles = this.paragraph.style
2356
	, blockstyle = this.paragraph.blockstyle
2357
	, priorblockstype = this.paragraph.blockstyle || {}
2358
	this.paragraph = {'text':[], 'style':[], 'blockstyle':{}, 'priorblockstyle':blockstyle}
2359
 
2360
	if (!fragments.join('').trim()) {
2361
		/* if it's empty string */
2362
		return
2363
	} // else there is something to draw
2364
 
2365
	var lines = this.splitFragmentsIntoLines(fragments, styles)
2366
	, line // will be array of array pairs [[t,s],[t,s],[t,s]...] where t = text, s = style object
2367
 
2368
	, maxLineHeight
2369
	, defaultFontSize = 12
2370
	, fontToUnitRatio = defaultFontSize / this.pdf.internal.scaleFactor
2371
 
2372
	// these will be in pdf instance units
2373
	, paragraphspacing_before = (
2374
		// we only use margin-top potion that is larger than margin-bottom of previous elem
2375
		// because CSS margins don't stack, they overlap.
2376
		Math.max( ( blockstyle['margin-top'] || 0 ) - ( priorblockstype['margin-bottom'] || 0 ), 0 ) +
2377
		( blockstyle['padding-top'] || 0 )
2378
	) * fontToUnitRatio
2379
	, paragraphspacing_after = (
2380
		( blockstyle['margin-bottom'] || 0 ) + ( blockstyle['padding-bottom'] || 0 )
2381
	) * fontToUnitRatio
2382
 
2383
	, out = this.pdf.internal.write
2384
 
2385
	, i, l
2386
 
2387
	this.y += paragraphspacing_before
2388
 
2389
	out(
2390
		'q' // canning the scope
2391
		, 'BT' // Begin Text
2392
		// and this moves the text start to desired position.
2393
		, this.pdf.internal.getCoordinateString(this.x)
2394
		, this.pdf.internal.getVerticalCoordinateString(this.y)
2395
		, 'Td'
2396
	)
2397
 
2398
	// looping through lines
2399
	while (lines.length) {
2400
		line = lines.shift()
2401
 
2402
		maxLineHeight = 0
2403
 
2404
		for (i = 0, l = line.length; i !== l; i++) {
2405
			if (line[i][0].trim()) {
2406
				maxLineHeight = Math.max(maxLineHeight, line[i][1]['line-height'], line[i][1]['font-size'])
2407
			}
2408
		}
2409
 
2410
		// current coordinates are "top left" corner of text box. Text must start from "lower left"
2411
		// so, lowering the current coord one line height.
2412
		out(
2413
 
2414
			, (-1 * defaultFontSize * maxLineHeight).toFixed(2) // shifting down a line in native `points' means reducing y coordinate
2415
			, 'Td'
2416
			// , (defaultFontSize * maxLineHeight).toFixed(2) // line height comes as float = proportion to normal.
2417
			// , 'TL' // line height marker. Not sure we need it with "Td", but...
2418
		)
2419
 
2420
		for (i = 0, l = line.length; i !== l; i++) {
2421
			if (line[i][0]) {
2422
				this.RenderTextFragment(line[i][0], line[i][1])
2423
			}
2424
		}
2425
 
2426
		// y is in user units (cm, inch etc)
2427
		// maxLineHeight is ratio of defaultFontSize
2428
		// defaultFontSize is in points always.
2429
		// this.internal.scaleFactor is ratio of user unit to points.
2430
		// Dividing by it converts points to user units.
2431
		// vertical offset will be in user units.
2432
		// this.y is in user units.
2433
		this.y += maxLineHeight * fontToUnitRatio
2434
	}
2435
 
2436
	out(
2437
		'ET' // End Text
2438
		, 'Q' // restore scope
2439
	)
2440
 
2441
	this.y += paragraphspacing_after
2442
}
2443
 
2444
Renderer.prototype.setBlockBoundary = function(){
2445
	this.renderParagraph()
2446
}
2447
 
2448
Renderer.prototype.setBlockStyle = function(css){
2449
	this.paragraph.blockstyle = css
2450
}
2451
 
2452
Renderer.prototype.addText = function(text, css){
2453
	this.paragraph.text.push(text)
2454
	this.paragraph.style.push(css)
2455
}
2456
 
2457
 
2458
//=====================
2459
// these are DrillForContent and friends
2460
 
2461
var FontNameDB = {
2462
	'helvetica':'helvetica'
2463
	, 'sans-serif':'helvetica'
2464
	, 'serif':'times'
2465
	, 'times':'times'
2466
	, 'times new roman':'times'
2467
	, 'monospace':'courier'
2468
	, 'courier':'courier'
2469
}
2470
, FontWeightMap = {"100":'normal',"200":'normal',"300":'normal',"400":'normal',"500":'bold',"600":'bold',"700":'bold',"800":'bold',"900":'bold',"normal":'normal',"bold":'bold',"bolder":'bold',"lighter":'normal'}
2471
, FontStyleMap = {'normal':'normal','italic':'italic','oblique':'italic'}
2472
, UnitedNumberMap = {'normal':1}
2473
 
2474
function ResolveFont(css_font_family_string){
2475
	var name
2476
	, parts = css_font_family_string.split(',') // yes, we don't care about , inside quotes
2477
	, part = parts.shift()
2478
 
2479
	while (!name && part){
2480
		name = FontNameDB[ part.trim().toLowerCase() ]
2481
		part = parts.shift()
2482
	}
2483
	return name
2484
}
2485
 
2486
// return ratio to "normal" font size. in other words, it's fraction of 16 pixels.
2487
function ResolveUnitedNumber(css_line_height_string){
2488
	var undef
2489
	, normal = 16.00
2490
	, value = UnitedNumberMap[css_line_height_string]
2491
	if (value) {
2492
		return value
2493
	}
2494
 
2495
	// not in cache, ok. need to parse it.
2496
 
2497
	// Could it be a named value?
2498
	// we will use Windows 94dpi sizing with CSS2 suggested 1.2 step ratio
2499
	// where "normal" or "medium" is 16px
2500
	// see: http://style.cleverchimp.com/font_size_intervals/altintervals.html
2501
	value = ({
2502
		'xx-small':9
2503
		, 'x-small':11
2504
		, 'small':13
2505
		, 'medium':16
2506
		, 'large':19
2507
		, 'x-large':23
2508
		, 'xx-large':28
2509
		, 'auto':0
2510
	})[css_line_height_string]
2511
	if (value !== undef) {
2512
		// caching, returning
2513
		return UnitedNumberMap[css_line_height_string] = value / normal
2514
	}
2515
 
2516
	// not in cache, ok. need to parse it.
2517
	// is it int?
2518
	if (value = parseFloat(css_line_height_string)) {
2519
		// caching, returning
2520
		return UnitedNumberMap[css_line_height_string] = value / normal
2521
	}
2522
 
2523
	// must be a "united" value ('123em', '134px' etc.)
2524
	// most browsers convert it to px so, only handling the px
2525
	value = css_line_height_string.match( /([\d\.]+)(px)/ )
2526
	if (value.length === 3) {
2527
		// caching, returning
2528
		return UnitedNumberMap[css_line_height_string] = parseFloat( value[1] ) / normal
2529
	}
2530
 
2531
	return UnitedNumberMap[css_line_height_string] = 1
2532
}
2533
 
2534
function GetCSS(element){
2535
	var $e = $(element)
2536
	, css = {}
2537
	, tmp
2538
 
2539
	css['font-family'] = ResolveFont( $e.css('font-family') ) || 'times'
2540
	css['font-style'] = FontStyleMap [ $e.css('font-style') ] || 'normal'
2541
	tmp = FontWeightMap[ $e.css('font-weight') ] || 'normal'
2542
	if (tmp === 'bold') {
2543
		if (css['font-style'] === 'normal') {
2544
			css['font-style'] = tmp
2545
		} else {
2546
			css['font-style'] = tmp + css['font-style'] // jsPDF's default fonts have it as "bolditalic"
2547
		}
2548
	}
2549
 
2550
	css['font-size'] = ResolveUnitedNumber( $e.css('font-size') ) || 1 // ratio to "normal" size
2551
	css['line-height'] = ResolveUnitedNumber( $e.css('line-height') ) || 1 // ratio to "normal" size
2552
 
2553
	css['display'] = $e.css('display') === 'inline' ? 'inline' : 'block'
2554
 
2555
	if (css['display'] === 'block'){
2556
		css['margin-top'] = ResolveUnitedNumber( $e.css('margin-top') ) || 0
2557
		css['margin-bottom'] = ResolveUnitedNumber( $e.css('margin-bottom') ) || 0
2558
		css['padding-top'] = ResolveUnitedNumber( $e.css('padding-top') ) || 0
2559
		css['padding-bottom'] = ResolveUnitedNumber( $e.css('padding-bottom') ) || 0
2560
	}
2561
 
2562
	return css
2563
}
2564
 
2565
function elementHandledElsewhere(element, renderer, elementHandlers){
2566
	var isHandledElsewhere = false
2567
 
2568
	var i, l, t
2569
	, handlers = elementHandlers['#'+element.id]
2570
	if (handlers) {
2571
		if (typeof handlers === 'function') {
2572
			isHandledElsewhere = handlers(element, renderer)
2573
		} else /* array */ {
2574
			i = 0
2575
			l = handlers.length
2576
			while (!isHandledElsewhere && i !== l){
2577
				isHandledElsewhere = handlers[i](element, renderer)
2578
				;i++;
2579
			}
2580
		}
2581
	}
2582
 
2583
	handlers = elementHandlers[element.nodeName]
2584
	if (!isHandledElsewhere && handlers) {
2585
		if (typeof handlers === 'function') {
2586
			isHandledElsewhere = handlers(element, renderer)
2587
		} else /* array */ {
2588
			i = 0
2589
			l = handlers.length
2590
			while (!isHandledElsewhere && i !== l){
2591
				isHandledElsewhere = handlers[i](element, renderer)
2592
				;i++;
2593
			}
2594
		}
2595
	}
2596
 
2597
	return isHandledElsewhere
2598
}
2599
 
2600
function DrillForContent(element, renderer, elementHandlers){
2601
	var cns = element.childNodes
2602
	, cn
2603
	, fragmentCSS = GetCSS(element)
2604
	, isBlock = fragmentCSS.display === 'block'
2605
 
2606
	if (isBlock) {
2607
		renderer.setBlockBoundary()
2608
		renderer.setBlockStyle(fragmentCSS)
2609
	}
2610
 
2611
	for (var i = 0, l = cns.length; i < l ; i++){
2612
		cn = cns[i]
2613
 
2614
		if (typeof cn === 'object') {
2615
			// Don't render the insides of script tags, they contain text nodes which then render
2616
			if (cn.nodeType === 1 && cn.nodeName != 'SCRIPT') {
2617
				if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
2618
					DrillForContent(cn, renderer, elementHandlers)
2619
				}
2620
			} else if (cn.nodeType === 3){
2621
				renderer.addText( cn.nodeValue, fragmentCSS )
2622
			}
2623
		} else if (typeof cn === 'string') {
2624
			renderer.addText( cn, fragmentCSS )
2625
		}
2626
	}
2627
 
2628
	if (isBlock) {
2629
		renderer.setBlockBoundary()
2630
	}
2631
}
2632
 
2633
function process(pdf, element, x, y, settings) {
2634
 
2635
	// we operate on DOM elems. So HTML-formatted strings need to pushed into one
2636
	if (typeof element === 'string') {
2637
		element = (function(element) {
2638
			var framename = "jsPDFhtmlText" + Date.now().toString() + (Math.random() * 1000).toFixed(0)
2639
			, visuallyhidden = 'position: absolute !important;' +
2640
				'clip: rect(1px 1px 1px 1px); /* IE6, IE7 */' +
2641
				'clip: rect(1px, 1px, 1px, 1px);' +
2642
				'padding:0 !important;' +
2643
				'border:0 !important;' +
2644
				'height: 1px !important;' +
2645
				'width: 1px !important; ' +
2646
				'top:auto;' +
2647
				'left:-100px;' +
2648
				'overflow: hidden;'
2649
			// TODO: clean up hidden div
2650
			, $hiddendiv = $(
2651
				'<div style="'+visuallyhidden+'">' +
2652
				'<iframe style="height:1px;width:1px" name="'+framename+'" />' +
2653
				'</div>'
2654
			).appendTo(document.body)
2655
			, $frame = window.frames[framename]
2656
			return $($frame.document.body).html(element)[0]
2657
		})( element )
2658
	}
2659
 
2660
	var r = new Renderer( pdf, x, y, settings )
2661
	, a = DrillForContent( element, r, settings.elementHandlers )
2662
 
2663
	return r.dispose()
2664
 
2665
}
2666
 
2667
 
2668
/**
2669
Converts HTML-formatted text into formatted PDF text.
2670
 
2671
Notes:
2672
2012-07-18
2673
	Plugin relies on having browser, DOM around. The HTML is pushed into dom and traversed.
2674
	Plugin relies on jQuery for CSS extraction.
2675
	Targeting HTML output from Markdown templating, which is a very simple
2676
	markup - div, span, em, strong, p. No br-based paragraph separation supported explicitly (but still may work.)
2677
	Images, tables are NOT supported.
2678
 
2679
@public
2680
@function
2681
@param HTML {String or DOM Element} HTML-formatted text, or pointer to DOM element that is to be rendered into PDF.
2682
@param x {Number} starting X coordinate in jsPDF instance's declared units.
2683
@param y {Number} starting Y coordinate in jsPDF instance's declared units.
2684
@param settings {Object} Additional / optional variables controlling parsing, rendering.
2685
@returns {Object} jsPDF instance
2686
*/
2687
jsPDFAPI.fromHTML = function(HTML, x, y, settings) {
2688
	'use strict'
2689
	// `this` is _jsPDF object returned when jsPDF is inited (new jsPDF())
2690
	// `this.internal` is a collection of useful, specific-to-raw-PDF-stream functions.
2691
	// for example, `this.internal.write` function allowing you to write directly to PDF stream.
2692
	// `this.line`, `this.text` etc are available directly.
2693
	// so if your plugin just wraps complex series of this.line or this.text or other public API calls,
2694
	// you don't need to look into `this.internal`
2695
	// See _jsPDF object in jspdf.js for complete list of what's available to you.
2696
 
2697
	// it is good practice to return ref to jsPDF instance to make
2698
	// the calls chainable.
2699
	// return this
2700
 
2701
	// but in this case it is more usefull to return some stats about what we rendered.
2702
	return process(this, HTML, x, y, settings)
2703
}
2704
 
2705
})(jsPDF.API)
2706
/** @preserve
2707
jsPDF Silly SVG plugin
2708
Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
2709
*/
2710
/**
2711
 * Permission is hereby granted, free of charge, to any person obtaining
2712
 * a copy of this software and associated documentation files (the
2713
 * "Software"), to deal in the Software without restriction, including
2714
 * without limitation the rights to use, copy, modify, merge, publish,
2715
 * distribute, sublicense, and/or sell copies of the Software, and to
2716
 * permit persons to whom the Software is furnished to do so, subject to
2717
 * the following conditions:
2718
 *
2719
 * The above copyright notice and this permission notice shall be
2720
 * included in all copies or substantial portions of the Software.
2721
 *
2722
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2723
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2724
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2725
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
2726
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2727
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2728
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2729
 * ====================================================================
2730
 */
2731
 
2732
;(function(jsPDFAPI) {
2733
'use strict'
2734
 
2735
/**
2736
Parses SVG XML and converts only some of the SVG elements into
2737
PDF elements.
2738
 
2739
Supports:
2740
 paths
2741
 
2742
@public
2743
@function
2744
@param
2745
@returns {Type}
2746
*/
2747
jsPDFAPI.addSVG = function(svgtext, x, y, w, h) {
2748
	// 'this' is _jsPDF object returned when jsPDF is inited (new jsPDF())
2749
 
2750
	var undef
2751
 
2752
	if (x === undef || x === undef) {
2753
		throw new Error("addSVG needs values for 'x' and 'y'")
2754
	}
2755
 
2756
    function InjectCSS(cssbody, document) {
2757
        var styletag = document.createElement('style')
2758
        styletag.type = 'text/css'
2759
        if (styletag.styleSheet) {
2760
        	// ie
2761
            styletag.styleSheet.cssText = cssbody
2762
        } else {
2763
        	// others
2764
            styletag.appendChild(document.createTextNode(cssbody))
2765
        }
2766
        document.getElementsByTagName("head")[0].appendChild(styletag)
2767
    }
2768
 
2769
	function createWorkerNode(document){
2770
 
2771
		var frameID = 'childframe' // Date.now().toString() + '_' + (Math.random() * 100).toString()
2772
		, frame = document.createElement('iframe')
2773
 
2774
		InjectCSS(
2775
			'.jsPDF_sillysvg_iframe {display:none;position:absolute;}'
2776
			, document
2777
		)
2778
 
2779
		frame.name = frameID
2780
		frame.setAttribute("width", 0)
2781
		frame.setAttribute("height", 0)
2782
		frame.setAttribute("frameborder", "0")
2783
		frame.setAttribute("scrolling", "no")
2784
		frame.setAttribute("seamless", "seamless")
2785
		frame.setAttribute("class", "jsPDF_sillysvg_iframe")
2786
 
2787
		document.body.appendChild(frame)
2788
 
2789
		return frame
2790
	}
2791
 
2792
	function attachSVGToWorkerNode(svgtext, frame){
2793
		var framedoc = ( frame.contentWindow || frame.contentDocument ).document
2794
		framedoc.write(svgtext)
2795
		framedoc.close()
2796
		return framedoc.getElementsByTagName('svg')[0]
2797
	}
2798
 
2799
	function convertPathToPDFLinesArgs(path){
2800
		'use strict'
2801
		// we will use 'lines' method call. it needs:
2802
		// - starting coordinate pair
2803
		// - array of arrays of vector shifts (2-len for line, 6 len for bezier)
2804
		// - scale array [horizontal, vertical] ratios
2805
		// - style (stroke, fill, both)
2806
 
2807
		var x = parseFloat(path[1])
2808
		, y = parseFloat(path[2])
2809
		, vectors = []
2810
		, position = 3
2811
		, len = path.length
2812
 
2813
		while (position < len){
2814
			if (path[position] === 'c'){
2815
				vectors.push([
2816
					parseFloat(path[position + 1])
2817
					, parseFloat(path[position + 2])
2818
					, parseFloat(path[position + 3])
2819
					, parseFloat(path[position + 4])
2820
					, parseFloat(path[position + 5])
2821
					, parseFloat(path[position + 6])
2822
				])
2823
				position += 7
2824
			} else if (path[position] === 'l') {
2825
				vectors.push([
2826
					parseFloat(path[position + 1])
2827
					, parseFloat(path[position + 2])
2828
				])
2829
				position += 3
2830
			} else {
2831
				position += 1
2832
			}
2833
		}
2834
		return [x,y,vectors]
2835
	}
2836
 
2837
	var workernode = createWorkerNode(document)
2838
	, svgnode = attachSVGToWorkerNode(svgtext, workernode)
2839
	, scale = [1,1]
2840
	, svgw = parseFloat(svgnode.getAttribute('width'))
2841
	, svgh = parseFloat(svgnode.getAttribute('height'))
2842
 
2843
	if (svgw && svgh) {
2844
		// setting both w and h makes image stretch to size.
2845
		// this may distort the image, but fits your demanded size
2846
		if (w && h) {
2847
			scale = [w / svgw, h / svgh]
2848
		}
2849
		// if only one is set, that value is set as max and SVG
2850
		// is scaled proportionately.
2851
		else if (w) {
2852
			scale = [w / svgw, w / svgw]
2853
		} else if (h) {
2854
			scale = [h / svgh, h / svgh]
2855
		}
2856
	}
2857
 
2858
	var i, l, tmp
2859
	, linesargs
2860
	, items = svgnode.childNodes
2861
	for (i = 0, l = items.length; i < l; i++) {
2862
		tmp = items[i]
2863
		if (tmp.tagName && tmp.tagName.toUpperCase() === 'PATH') {
2864
			linesargs = convertPathToPDFLinesArgs( tmp.getAttribute("d").split(' ') )
2865
			// path start x coordinate
2866
			linesargs[0] = linesargs[0] * scale[0] + x // where x is upper left X of image
2867
			// path start y coordinate
2868
			linesargs[1] = linesargs[1] * scale[1] + y // where y is upper left Y of image
2869
			// the rest of lines are vectors. these will adjust with scale value auto.
2870
			this.lines.call(
2871
				this
2872
				, linesargs[2] // lines
2873
				, linesargs[0] // starting x
2874
				, linesargs[1] // starting y
2875
				, scale
2876
			)
2877
		}
2878
	}
2879
 
2880
	// clean up
2881
	// workernode.parentNode.removeChild(workernode)
2882
 
2883
	return this
2884
}
2885
 
2886
})(jsPDF.API)
2887
/** @preserve
2888
jsPDF split_text_to_size plugin
2889
Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
2890
MIT license.
2891
*/
2892
/**
2893
 * Permission is hereby granted, free of charge, to any person obtaining
2894
 * a copy of this software and associated documentation files (the
2895
 * "Software"), to deal in the Software without restriction, including
2896
 * without limitation the rights to use, copy, modify, merge, publish,
2897
 * distribute, sublicense, and/or sell copies of the Software, and to
2898
 * permit persons to whom the Software is furnished to do so, subject to
2899
 * the following conditions:
2900
 *
2901
 * The above copyright notice and this permission notice shall be
2902
 * included in all copies or substantial portions of the Software.
2903
 *
2904
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2905
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2906
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2907
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
2908
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2909
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2910
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2911
 * ====================================================================
2912
 */
2913
 
2914
;(function(API) {
2915
'use strict'
2916
 
2917
/**
2918
Returns an array of length matching length of the 'word' string, with each
2919
cell ocupied by the width of the char in that position.
2920
 
2921
@function
2922
@param word {String}
2923
@param widths {Object}
2924
@param kerning {Object}
2925
@returns {Array}
2926
*/
2927
var getCharWidthsArray = API.getCharWidthsArray = function(text, options){
2928
 
2929
	if (!options) {
2930
		options = {}
2931
	}
2932
 
2933
	var widths = options.widths ? options.widths : this.internal.getFont().metadata.Unicode.widths
2934
	, widthsFractionOf = widths.fof ? widths.fof : 1
2935
	, kerning = options.kerning ? options.kerning : this.internal.getFont().metadata.Unicode.kerning
2936
	, kerningFractionOf = kerning.fof ? kerning.fof : 1
2937
 
2938
	// console.log("widths, kergnings", widths, kerning)
2939
 
2940
	var i, l
2941
	, char_code
2942
	, char_width
2943
	, prior_char_code = 0 // for kerning
2944
	, default_char_width = widths[0] || widthsFractionOf
2945
	, output = []
2946
 
2947
	for (i = 0, l = text.length; i < l; i++) {
2948
		char_code = text.charCodeAt(i)
2949
		output.push(
2950
			( widths[char_code] || default_char_width ) / widthsFractionOf +
2951
			( kerning[char_code] && kerning[char_code][prior_char_code] || 0 ) / kerningFractionOf
2952
		)
2953
		prior_char_code = char_code
2954
	}
2955
 
2956
	return output
2957
}
2958
var getArraySum = function(array){
2959
	var i = array.length
2960
	, output = 0
2961
	while(i){
2962
		;i--;
2963
		output += array[i]
2964
	}
2965
	return output
2966
}
2967
/**
2968
Returns a widths of string in a given font, if the font size is set as 1 point.
2969
 
2970
In other words, this is "proportional" value. For 1 unit of font size, the length
2971
of the string will be that much.
2972
 
2973
Multiply by font size to get actual width in *points*
2974
Then divide by 72 to get inches or divide by (72/25.6) to get 'mm' etc.
2975
 
2976
@public
2977
@function
2978
@param
2979
@returns {Type}
2980
*/
2981
var getStringUnitWidth = API.getStringUnitWidth = function(text, options) {
2982
	return getArraySum(getCharWidthsArray.call(this, text, options))
2983
}
2984
 
2985
/**
2986
returns array of lines
2987
*/
2988
var splitLongWord = function(word, widths_array, firstLineMaxLen, maxLen){
2989
	var answer = []
2990
 
2991
	// 1st, chop off the piece that can fit on the hanging line.
2992
	var i = 0
2993
	, l = word.length
2994
	, workingLen = 0
2995
	while (i !== l && workingLen + widths_array[i] < firstLineMaxLen){
2996
		workingLen += widths_array[i]
2997
		;i++;
2998
	}
2999
	// this is first line.
3000
	answer.push(word.slice(0, i))
3001
 
3002
	// 2nd. Split the rest into maxLen pieces.
3003
	var startOfLine = i
3004
	workingLen = 0
3005
	while (i !== l){
3006
		if (workingLen + widths_array[i] > maxLen) {
3007
			answer.push(word.slice(startOfLine, i))
3008
			workingLen = 0
3009
			startOfLine = i
3010
		}
3011
		workingLen += widths_array[i]
3012
		;i++;
3013
	}
3014
	if (startOfLine !== i) {
3015
		answer.push(word.slice(startOfLine, i))
3016
	}
3017
 
3018
	return answer
3019
}
3020
 
3021
// Note, all sizing inputs for this function must be in "font measurement units"
3022
// By default, for PDF, it's "point".
3023
var splitParagraphIntoLines = function(text, maxlen, options){
3024
	// at this time works only on Western scripts, ones with space char
3025
	// separating the words. Feel free to expand.
3026
 
3027
	if (!options) {
3028
		options = {}
3029
	}
3030
 
3031
	var spaceCharWidth = getCharWidthsArray(' ', options)[0]
3032
 
3033
	var words = text.split(' ')
3034
 
3035
	var line = []
3036
	, lines = [line]
3037
	, line_length = options.textIndent || 0
3038
	, separator_length = 0
3039
	, current_word_length = 0
3040
	, word
3041
	, widths_array
3042
 
3043
	var i, l, tmp
3044
	for (i = 0, l = words.length; i < l; i++) {
3045
		word = words[i]
3046
		widths_array = getCharWidthsArray(word, options)
3047
		current_word_length = getArraySum(widths_array)
3048
 
3049
		if (line_length + separator_length + current_word_length > maxlen) {
3050
			if (current_word_length > maxlen) {
3051
				// this happens when you have space-less long URLs for example.
3052
				// we just chop these to size. We do NOT insert hiphens
3053
				tmp = splitLongWord(word, widths_array, maxlen - (line_length + separator_length), maxlen)
3054
				// first line we add to existing line object
3055
				line.push(tmp.shift()) // it's ok to have extra space indicator there
3056
				// last line we make into new line object
3057
				line = [tmp.pop()]
3058
				// lines in the middle we apped to lines object as whole lines
3059
				while(tmp.length){
3060
					lines.push([tmp.shift()]) // single fragment occupies whole line
3061
				}
3062
				current_word_length = getArraySum( widths_array.slice(word.length - line[0].length) )
3063
			} else {
3064
				// just put it on a new line
3065
				line = [word]
3066
			}
3067
 
3068
			// now we attach new line to lines
3069
			lines.push(line)
3070
 
3071
			line_length = current_word_length
3072
			separator_length = spaceCharWidth
3073
 
3074
		} else {
3075
			line.push(word)
3076
 
3077
			line_length += separator_length + current_word_length
3078
			separator_length = spaceCharWidth
3079
		}
3080
	}
3081
 
3082
	var output = []
3083
	for (i = 0, l = lines.length; i < l; i++) {
3084
		output.push( lines[i].join(' ') )
3085
	}
3086
	return output
3087
 
3088
}
3089
 
3090
/**
3091
Splits a given string into an array of strings. Uses 'size' value
3092
(in measurement units declared as default for the jsPDF instance)
3093
and the font's "widths" and "Kerning" tables, where availabe, to
3094
determine display length of a given string for a given font.
3095
 
3096
We use character's 100% of unit size (height) as width when Width
3097
table or other default width is not available.
3098
 
3099
@public
3100
@function
3101
@param text {String} Unencoded, regular JavaScript (Unicode, UTF-16 / UCS-2) string.
3102
@param size {Number} Nominal number, measured in units default to this instance of jsPDF.
3103
@param options {Object} Optional flags needed for chopper to do the right thing.
3104
@returns {Array} with strings chopped to size.
3105
*/
3106
API.splitTextToSize = function(text, maxlen, options) {
3107
	'use strict'
3108
 
3109
	if (!options) {
3110
		options = {}
3111
	}
3112
 
3113
	var fsize = options.fontSize || this.internal.getFontSize()
3114
	, newOptions = (function(options){
3115
		var widths = {0:1}
3116
		, kerning = {}
3117
 
3118
		if (!options.widths || !options.kerning) {
3119
			var f = this.internal.getFont(options.fontName, options.fontStyle)
3120
			, encoding = 'Unicode'
3121
			// NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE
3122
			// Actual JavaScript-native String's 16bit char codes used.
3123
			// no multi-byte logic here
3124
 
3125
			if (f.metadata[encoding]) {
3126
				return {
3127
					widths: f.metadata[encoding].widths || widths
3128
					, kerning: f.metadata[encoding].kerning || kerning
3129
				}
3130
			}
3131
		} else {
3132
			return 	{
3133
				widths: options.widths
3134
				, kerning: options.kerning
3135
			}
3136
		}
3137
 
3138
		// then use default values
3139
		return 	{
3140
			widths: widths
3141
			, kerning: kerning
3142
		}
3143
	}).call(this, options)
3144
 
3145
	// first we split on end-of-line chars
3146
	var paragraphs
3147
	if (text.match(/[\n\r]/)) {
3148
		paragraphs = text.split(/\r\n|\r|\n/g)
3149
	} else {
3150
		paragraphs = [text]
3151
	}
3152
 
3153
	// now we convert size (max length of line) into "font size units"
3154
	// at present time, the "font size unit" is always 'point'
3155
	// 'proportional' means, "in proportion to font size"
3156
	var fontUnit_maxLen = 1.0 * this.internal.scaleFactor * maxlen / fsize
3157
	// at this time, fsize is always in "points" regardless of the default measurement unit of the doc.
3158
	// this may change in the future?
3159
	// until then, proportional_maxlen is likely to be in 'points'
3160
 
3161
	// If first line is to be indented (shorter or longer) than maxLen
3162
	// we indicate that by using CSS-style "text-indent" option.
3163
	// here it's in font units too (which is likely 'points')
3164
	// it can be negative (which makes the first line longer than maxLen)
3165
	newOptions.textIndent = options.textIndent ?
3166
		options.textIndent * 1.0 * this.internal.scaleFactor / fsize :
3167
 
3168
 
3169
	var i, l
3170
	, output = []
3171
	for (i = 0, l = paragraphs.length; i < l; i++) {
3172
		output = output.concat(
3173
			splitParagraphIntoLines(
3174
				paragraphs[i]
3175
				, fontUnit_maxLen
3176
				, newOptions
3177
			)
3178
		)
3179
	}
3180
 
3181
	return output
3182
}
3183
 
3184
})(jsPDF.API);
3185
/** @preserve
3186
jsPDF standard_fonts_metrics plugin
3187
Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
3188
MIT license.
3189
*/
3190
/**
3191
 * Permission is hereby granted, free of charge, to any person obtaining
3192
 * a copy of this software and associated documentation files (the
3193
 * "Software"), to deal in the Software without restriction, including
3194
 * without limitation the rights to use, copy, modify, merge, publish,
3195
 * distribute, sublicense, and/or sell copies of the Software, and to
3196
 * permit persons to whom the Software is furnished to do so, subject to
3197
 * the following conditions:
3198
 *
3199
 * The above copyright notice and this permission notice shall be
3200
 * included in all copies or substantial portions of the Software.
3201
 *
3202
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3203
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3204
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
3205
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
3206
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
3207
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
3208
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3209
 * ====================================================================
3210
 */
3211
 
3212
;(function(API) {
3213
'use strict'
3214
 
3215
/*
3216
# reference (Python) versions of 'compress' and 'uncompress'
3217
# only 'uncompress' function is featured lower as JavaScript
3218
# if you want to unit test "roundtrip", just transcribe the reference
3219
# 'compress' function from Python into JavaScript
3220
 
3221
def compress(data):
3222
 
3223
	keys =   '0123456789abcdef'
3224
	values = 'klmnopqrstuvwxyz'
3225
	mapping = dict(zip(keys, values))
3226
	vals = []
3227
	for key in data.keys():
3228
		value = data[key]
3229
		try:
3230
			keystring = hex(key)[2:]
3231
			keystring = keystring[:-1] + mapping[keystring[-1:]]
3232
		except:
3233
			keystring = key.join(["'","'"])
3234
			#print('Keystring is %s' % keystring)
3235
 
3236
		try:
3237
			if value < 0:
3238
				valuestring = hex(value)[3:]
3239
				numberprefix = '-'
3240
			else:
3241
				valuestring = hex(value)[2:]
3242
				numberprefix = ''
3243
			valuestring = numberprefix + valuestring[:-1] + mapping[valuestring[-1:]]
3244
		except:
3245
			if type(value) == dict:
3246
				valuestring = compress(value)
3247
			else:
3248
				raise Exception("Don't know what to do with value type %s" % type(value))
3249
 
3250
		vals.append(keystring+valuestring)
3251
 
3252
	return '{' + ''.join(vals) + '}'
3253
 
3254
def uncompress(data):
3255
 
3256
	decoded = '0123456789abcdef'
3257
	encoded = 'klmnopqrstuvwxyz'
3258
	mapping = dict(zip(encoded, decoded))
3259
 
3260
	sign = +1
3261
	stringmode = False
3262
	stringparts = []
3263
 
3264
	output = {}
3265
 
3266
	activeobject = output
3267
	parentchain = []
3268
 
3269
	keyparts = ''
3270
	valueparts = ''
3271
 
3272
	key = None
3273
 
3274
	ending = set(encoded)
3275
 
3276
	i = 1
3277
	l = len(data) - 1 # stripping starting, ending {}
3278
	while i != l: # stripping {}
3279
		# -, {, }, ' are special.
3280
 
3281
		ch = data[i]
3282
		i += 1
3283
 
3284
		if ch == "'":
3285
			if stringmode:
3286
				# end of string mode
3287
				stringmode = False
3288
				key = ''.join(stringparts)
3289
			else:
3290
				# start of string mode
3291
				stringmode = True
3292
				stringparts = []
3293
		elif stringmode == True:
3294
			#print("Adding %s to stringpart" % ch)
3295
			stringparts.append(ch)
3296
 
3297
		elif ch == '{':
3298
			# start of object
3299
			parentchain.append( [activeobject, key] )
3300
			activeobject = {}
3301
			key = None
3302
			#DEBUG = True
3303
		elif ch == '}':
3304
			# end of object
3305
			parent, key = parentchain.pop()
3306
			parent[key] = activeobject
3307
			key = None
3308
			activeobject = parent
3309
			#DEBUG = False
3310
 
3311
		elif ch == '-':
3312
			sign = -1
3313
		else:
3314
			# must be number
3315
			if key == None:
3316
				#debug("In Key. It is '%s', ch is '%s'" % (keyparts, ch))
3317
				if ch in ending:
3318
					#debug("End of key")
3319
					keyparts += mapping[ch]
3320
					key = int(keyparts, 16) * sign
3321
					sign = +1
3322
					keyparts = ''
3323
				else:
3324
					keyparts += ch
3325
			else:
3326
				#debug("In value. It is '%s', ch is '%s'" % (valueparts, ch))
3327
				if ch in ending:
3328
					#debug("End of value")
3329
					valueparts += mapping[ch]
3330
					activeobject[key] = int(valueparts, 16) * sign
3331
					sign = +1
3332
					key = None
3333
					valueparts = ''
3334
				else:
3335
					valueparts += ch
3336
 
3337
			#debug(activeobject)
3338
 
3339
	return output
3340
 
3341
*/
3342
 
3343
/**
3344
Uncompresses data compressed into custom, base16-like format.
3345
@public
3346
@function
3347
@param
3348
@returns {Type}
3349
*/
3350
var uncompress = function(data){
3351
 
3352
	var decoded = '0123456789abcdef'
3353
	, encoded = 'klmnopqrstuvwxyz'
3354
	, mapping = {}
3355
 
3356
	for (var i = 0; i < encoded.length; i++){
3357
		mapping[encoded[i]] = decoded[i]
3358
	}
3359
 
3360
	var undef
3361
	, output = {}
3362
	, sign = 1
3363
	, stringparts // undef. will be [] in string mode
3364
 
3365
	, activeobject = output
3366
	, parentchain = []
3367
	, parent_key_pair
3368
	, keyparts = ''
3369
	, valueparts = ''
3370
	, key // undef. will be Truthy when Key is resolved.
3371
	, datalen = data.length - 1 // stripping ending }
3372
	, ch
3373
 
3374
	i = 1 // stripping starting {
3375
 
3376
	while (i != datalen){
3377
		// - { } ' are special.
3378
 
3379
		ch = data[i]
3380
		i += 1
3381
 
3382
		if (ch == "'"){
3383
			if (stringparts){
3384
				// end of string mode
3385
				key = stringparts.join('')
3386
				stringparts = undef
3387
			} else {
3388
				// start of string mode
3389
				stringparts = []
3390
			}
3391
		} else if (stringparts){
3392
			stringparts.push(ch)
3393
		} else if (ch == '{'){
3394
			// start of object
3395
			parentchain.push( [activeobject, key] )
3396
			activeobject = {}
3397
			key = undef
3398
		} else if (ch == '}'){
3399
			// end of object
3400
			parent_key_pair = parentchain.pop()
3401
			parent_key_pair[0][parent_key_pair[1]] = activeobject
3402
			key = undef
3403
			activeobject = parent_key_pair[0]
3404
		} else if (ch == '-'){
3405
			sign = -1
3406
		} else {
3407
			// must be number
3408
			if (key === undef) {
3409
				if (mapping.hasOwnProperty(ch)){
3410
					keyparts += mapping[ch]
3411
					key = parseInt(keyparts, 16) * sign
3412
					sign = +1
3413
					keyparts = ''
3414
				} else {
3415
					keyparts += ch
3416
				}
3417
			} else {
3418
				if (mapping.hasOwnProperty(ch)){
3419
					valueparts += mapping[ch]
3420
					activeobject[key] = parseInt(valueparts, 16) * sign
3421
					sign = +1
3422
					key = undef
3423
					valueparts = ''
3424
				} else {
3425
					valueparts += ch
3426
				}
3427
			}
3428
		}
3429
	} // end while
3430
 
3431
	return output
3432
}
3433
 
3434
// encoding = 'Unicode'
3435
// NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE. NO clever BOM behavior
3436
// Actual 16bit char codes used.
3437
// no multi-byte logic here
3438
 
3439
// Unicode characters to WinAnsiEncoding:
3440
// {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}
3441
// as you can see, all Unicode chars are outside of 0-255 range. No char code conflicts.
3442
// this means that you can give Win cp1252 encoded strings to jsPDF for rendering directly
3443
// as well as give strings with some (supported by these fonts) Unicode characters and
3444
// these will be mapped to win cp1252
3445
// for example, you can send char code (cp1252) 0x80 or (unicode) 0x20AC, getting "Euro" glyph displayed in both cases.
3446
 
3447
var encodingBlock = {
3448
	'codePages': ['WinAnsiEncoding']
3449
	, 'WinAnsiEncoding': uncompress("{19m8n201n9q201o9r201s9l201t9m201u8m201w9n201x9o201y8o202k8q202l8r202m9p202q8p20aw8k203k8t203t8v203u9v2cq8s212m9t15m8w15n9w2dw9s16k8u16l9u17s9z17x8y17y9y}")
3450
}
3451
, encodings = {'Unicode':{
3452
	'Courier': encodingBlock
3453
	, 'Courier-Bold': encodingBlock
3454
	, 'Courier-BoldOblique': encodingBlock
3455
	, 'Courier-Oblique': encodingBlock
3456
	, 'Helvetica': encodingBlock
3457
	, 'Helvetica-Bold': encodingBlock
3458
	, 'Helvetica-BoldOblique': encodingBlock
3459
	, 'Helvetica-Oblique': encodingBlock
3460
	, 'Times-Roman': encodingBlock
3461
	, 'Times-Bold': encodingBlock
3462
	, 'Times-BoldItalic': encodingBlock
3463
	, 'Times-Italic': encodingBlock
3464
//	, 'Symbol'
3465
//	, 'ZapfDingbats'
3466
}}
3467
/**
3468
Resources:
3469
Font metrics data is reprocessed derivative of contents of
3470
"Font Metrics for PDF Core 14 Fonts" package, which exhibits the following copyright and license:
3471
 
3472
Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
3473
 
3474
This file and the 14 PostScript(R) AFM files it accompanies may be used,
3475
copied, and distributed for any purpose and without charge, with or without
3476
modification, provided that all copyright notices are retained; that the AFM
3477
files are not distributed without this file; that all modifications to this
3478
file or any of the AFM files are prominently noted in the modified file(s);
3479
and that this paragraph is not modified. Adobe Systems has no responsibility
3480
or obligation to support the use of the AFM files.
3481
 
3482
*/
3483
, fontMetrics = {'Unicode':{
3484
	// all sizing numbers are n/fontMetricsFractionOf = one font size unit
3485
	// this means that if fontMetricsFractionOf = 1000, and letter A's width is 476, it's
3486
	// width is 476/1000 or 47.6% of its height (regardless of font size)
3487
	// At this time this value applies to "widths" and "kerning" numbers.
3488
 
3489
	// char code 0 represents "default" (average) width - use it for chars missing in this table.
3490
	// key 'fof' represents the "fontMetricsFractionOf" value
3491
 
3492
	'Courier-Oblique': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
3493
	, '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}}}")
3494
	, '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}}}")
3495
	, 'Courier': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
3496
	, 'Courier-BoldOblique': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
3497
	, '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}}}")
3498
	//, 'Symbol': uncompress("{'widths'{k3uaw4r19m3m2k1t2l2l202m2y2n3m2p5n202q6o3k3m2s2l2t2l2v3r2w1t3m3m2y1t2z1wbk2sbl3r'fof'6o3n3m3o3m3p3m3q3m3r3m3s3m3t3m3u1w3v1w3w3r3x3r3y3r3z2wbp3t3l3m5v2l5x2l5z3m2q4yfr3r7v3k7w1o7x3k}'kerning'{'fof'-6o}}")
3499
	, '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}}}")
3500
	, '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}}}")
3501
	//, 'ZapfDingbats': uncompress("{'widths'{k4u2k1w'fof'6o}'kerning'{'fof'-6o}}")
3502
	, 'Courier-Bold': uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}")
3503
	, '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}}}")
3504
	, '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}}}")
3505
	, '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}}}")
3506
}};
3507
 
3508
/*
3509
This event handler is fired when a new jsPDF object is initialized
3510
This event handler appends metrics data to standard fonts within
3511
that jsPDF instance. The metrics are mapped over Unicode character
3512
codes, NOT CIDs or other codes matching the StandardEncoding table of the
3513
standard PDF fonts.
3514
Future:
3515
Also included is the encoding maping table, converting Unicode (UCS-2, UTF-16)
3516
char codes to StandardEncoding character codes. The encoding table is to be used
3517
somewhere around "pdfEscape" call.
3518
*/
3519
 
3520
API.events.push([
3521
	'addFonts'
3522
	,function(fontManagementObjects) {
3523
		// fontManagementObjects is {
3524
		//	'fonts':font_ID-keyed hash of font objects
3525
		//	, 'dictionary': lookup object, linking ["FontFamily"]['Style'] to font ID
3526
		//}
3527
		var font
3528
		, fontID
3529
		, metrics
3530
		, unicode_section
3531
		, encoding = 'Unicode'
3532
		, encodingBlock
3533
 
3534
		for (fontID in fontManagementObjects.fonts){
3535
			if (fontManagementObjects.fonts.hasOwnProperty(fontID)) {
3536
				font = fontManagementObjects.fonts[fontID]
3537
 
3538
				// // we only ship 'Unicode' mappings and metrics. No need for loop.
3539
				// // still, leaving this for the future.
3540
 
3541
				// for (encoding in fontMetrics){
3542
				// 	if (fontMetrics.hasOwnProperty(encoding)) {
3543
 
3544
						metrics = fontMetrics[encoding][font.PostScriptName]
3545
						if (metrics) {
3546
							if (font.metadata[encoding]) {
3547
								unicode_section = font.metadata[encoding]
3548
							} else {
3549
								unicode_section = font.metadata[encoding] = {}
3550
							}
3551
 
3552
							unicode_section.widths = metrics.widths
3553
							unicode_section.kerning = metrics.kerning
3554
						}
3555
				// 	}
3556
				// }
3557
				// for (encoding in encodings){
3558
				// 	if (encodings.hasOwnProperty(encoding)) {
3559
						encodingBlock = encodings[encoding][font.PostScriptName]
3560
						if (encodingBlock) {
3561
							if (font.metadata[encoding]) {
3562
								unicode_section = font.metadata[encoding]
3563
							} else {
3564
								unicode_section = font.metadata[encoding] = {}
3565
							}
3566
 
3567
							unicode_section.encoding = encodingBlock
3568
							if (encodingBlock.codePages && encodingBlock.codePages.length) {
3569
								font.encoding = encodingBlock.codePages[0]
3570
							}
3571
						}
3572
				// 	}
3573
				// }
3574
			}
3575
		}
3576
	}
3577
]) // end of adding event handler
3578
 
3579
})(jsPDF.API);
3580
/* BlobBuilder.js
3581
 * A BlobBuilder implementation.
3582
 * 2012-04-21
3583
 *
3584
 * By Eli Grey, http://eligrey.com
3585
 * License: X11/MIT
3586
 *   See LICENSE.md
3587
 */
3588
 
3589
/*global self, unescape */
3590
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
3591
  plusplus: true */
3592
 
3593
/*! @source http://purl.eligrey.com/github/BlobBuilder.js/blob/master/BlobBuilder.js */
3594
 
3595
var BlobBuilder = BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder || (function(view) {
3596
"use strict";
3597
var
3598
	  get_class = function(object) {
3599
		return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
3600
	}
3601
	, FakeBlobBuilder = function(){
3602
		this.data = [];
3603
	}
3604
	, FakeBlob = function(data, type, encoding) {
3605
		this.data = data;
3606
		this.size = data.length;
3607
		this.type = type;
3608
		this.encoding = encoding;
3609
	}
3610
	, FBB_proto = FakeBlobBuilder.prototype
3611
	, FB_proto = FakeBlob.prototype
3612
	, FileReaderSync = view.FileReaderSync
3613
	, FileException = function(type) {
3614
		this.code = this[this.name = type];
3615
	}
3616
	, file_ex_codes = (
3617
		  "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
3618
		+ "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
3619
	).split(" ")
3620
	, file_ex_code = file_ex_codes.length
3621
	, real_URL = view.URL || view.webkitURL || view
3622
	, real_create_object_URL = real_URL.createObjectURL
3623
	, real_revoke_object_URL = real_URL.revokeObjectURL
3624
	, URL = real_URL
3625
	, btoa = view.btoa
3626
	, atob = view.atob
3627
	, can_apply_typed_arrays = false
3628
	, can_apply_typed_arrays_test = function(pass) {
3629
		can_apply_typed_arrays = !pass;
3630
	}
3631
 
3632
	, ArrayBuffer = view.ArrayBuffer
3633
	, Uint8Array = view.Uint8Array
3634
;
3635
FakeBlobBuilder.fake = FB_proto.fake = true;
3636
while (file_ex_code--) {
3637
	FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
3638
}
3639
try {
3640
	if (Uint8Array) {
3641
		can_apply_typed_arrays_test.apply(0, new Uint8Array(1));
3642
	}
3643
} catch (ex) {}
3644
if (!real_URL.createObjectURL) {
3645
	URL = view.URL = {};
3646
}
3647
URL.createObjectURL = function(blob) {
3648
	var
3649
		  type = blob.type
3650
		, data_URI_header
3651
	;
3652
	if (type === null) {
3653
		type = "application/octet-stream";
3654
	}
3655
	if (blob instanceof FakeBlob) {
3656
		data_URI_header = "data:" + type;
3657
		if (blob.encoding === "base64") {
3658
			return data_URI_header + ";base64," + blob.data;
3659
		} else if (blob.encoding === "URI") {
3660
			return data_URI_header + "," + decodeURIComponent(blob.data);
3661
		} if (btoa) {
3662
			return data_URI_header + ";base64," + btoa(blob.data);
3663
		} else {
3664
			return data_URI_header + "," + encodeURIComponent(blob.data);
3665
		}
3666
	} else if (real_create_object_URL) {
3667
		return real_create_object_URL.call(real_URL, blob);
3668
	}
3669
};
3670
URL.revokeObjectURL = function(object_URL) {
3671
	if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
3672
		real_revoke_object_URL.call(real_URL, object_URL);
3673
	}
3674
};
3675
FBB_proto.append = function(data/*, endings*/) {
3676
	var bb = this.data;
3677
	// decode data to a binary string
3678
	if (Uint8Array && data instanceof ArrayBuffer) {
3679
		if (can_apply_typed_arrays) {
3680
			bb.push(String.fromCharCode.apply(String, new Uint8Array(data)));
3681
		} else {
3682
			var
3683
				  str = ""
3684
				, buf = new Uint8Array(data)
3685
				, i = 0
3686
				, buf_len = buf.length
3687
			;
3688
			for (; i < buf_len; i++) {
3689
				str += String.fromCharCode(buf[i]);
3690
			}
3691
		}
3692
	} else if (get_class(data) === "Blob" || get_class(data) === "File") {
3693
		if (FileReaderSync) {
3694
			var fr = new FileReaderSync;
3695
			bb.push(fr.readAsBinaryString(data));
3696
		} else {
3697
			// async FileReader won't work as BlobBuilder is sync
3698
			throw new FileException("NOT_READABLE_ERR");
3699
		}
3700
	} else if (data instanceof FakeBlob) {
3701
		if (data.encoding === "base64" && atob) {
3702
			bb.push(atob(data.data));
3703
		} else if (data.encoding === "URI") {
3704
			bb.push(decodeURIComponent(data.data));
3705
		} else if (data.encoding === "raw") {
3706
			bb.push(data.data);
3707
		}
3708
	} else {
3709
		if (typeof data !== "string") {
3710
			data += ""; // convert unsupported types to strings
3711
		}
3712
		// decode UTF-16 to binary string
3713
		bb.push(unescape(encodeURIComponent(data)));
3714
	}
3715
};
3716
FBB_proto.getBlob = function(type) {
3717
	if (!arguments.length) {
3718
		type = null;
3719
	}
3720
	return new FakeBlob(this.data.join(""), type, "raw");
3721
};
3722
FBB_proto.toString = function() {
3723
	return "[object BlobBuilder]";
3724
};
3725
FB_proto.slice = function(start, end, type) {
3726
	var args = arguments.length;
3727
	if (args < 3) {
3728
		type = null;
3729
	}
3730
	return new FakeBlob(
3731
		  this.data.slice(start, args > 1 ? end : this.data.length)
3732
		, type
3733
		, this.encoding
3734
	);
3735
};
3736
FB_proto.toString = function() {
3737
	return "[object Blob]";
3738
};
3739
return FakeBlobBuilder;
3740
}(self));
3741
/* FileSaver.js
3742
 * A saveAs() FileSaver implementation.
3743
 * 2013-01-23
3744
 *
3745
 * By Eli Grey, http://eligrey.com
3746
 * License: X11/MIT
3747
 *   See LICENSE.md
3748
 */
3749
 
3750
/*global self */
3751
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
3752
  plusplus: true */
3753
 
3754
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
3755
 
3756
var saveAs = saveAs
3757
  || (navigator.msSaveBlob && navigator.msSaveBlob.bind(navigator))
3758
  || (function(view) {
3759
	"use strict";
3760
	var
3761
		  doc = view.document
3762
		  // only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
3763
		, get_URL = function() {
3764
			return view.URL || view.webkitURL || view;
3765
		}
3766
		, URL = view.URL || view.webkitURL || view
3767
		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
3768
		, can_use_save_link = "download" in save_link
3769
		, click = function(node) {
3770
			var event = doc.createEvent("MouseEvents");
3771
			event.initMouseEvent(
3772
				"click", true, false, view, 0, 0, 0, 0, 0
3773
				, false, false, false, false, 0, null
3774
			);
3775
			return node.dispatchEvent(event); // false if event was cancelled
3776
		}
3777
		, webkit_req_fs = view.webkitRequestFileSystem
3778
		, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
3779
		, throw_outside = function (ex) {
3780
			(view.setImmediate || view.setTimeout)(function() {
3781
				throw ex;
3782
			}, 0);
3783
		}
3784
		, force_saveable_type = "application/octet-stream"
3785
		, fs_min_size = 0
3786
		, deletion_queue = []
3787
		, process_deletion_queue = function() {
3788
			var i = deletion_queue.length;
3789
			while (i--) {
3790
				var file = deletion_queue[i];
3791
				if (typeof file === "string") { // file is an object URL
3792
					URL.revokeObjectURL(file);
3793
				} else { // file is a File
3794
					file.remove();
3795
				}
3796
			}
3797
			deletion_queue.length = 0; // clear queue
3798
		}
3799
		, dispatch = function(filesaver, event_types, event) {
3800
			event_types = [].concat(event_types);
3801
			var i = event_types.length;
3802
			while (i--) {
3803
				var listener = filesaver["on" + event_types[i]];
3804
				if (typeof listener === "function") {
3805
					try {
3806
						listener.call(filesaver, event || filesaver);
3807
					} catch (ex) {
3808
						throw_outside(ex);
3809
					}
3810
				}
3811
			}
3812
		}
3813
		, FileSaver = function(blob, name) {
3814
			// First try a.download, then web filesystem, then object URLs
3815
			var
3816
				  filesaver = this
3817
				, type = blob.type
3818
				, blob_changed = false
3819
				, object_url
3820
				, target_view
3821
				, get_object_url = function() {
3822
					var object_url = get_URL().createObjectURL(blob);
3823
					deletion_queue.push(object_url);
3824
					return object_url;
3825
				}
3826
				, dispatch_all = function() {
3827
					dispatch(filesaver, "writestart progress write writeend".split(" "));
3828
				}
3829
				// on any filesys errors revert to saving with object URLs
3830
				, fs_error = function() {
3831
					// don't create more object URLs than needed
3832
					if (blob_changed || !object_url) {
3833
						object_url = get_object_url(blob);
3834
					}
3835
					if (target_view) {
3836
						target_view.location.href = object_url;
3837
					}
3838
					filesaver.readyState = filesaver.DONE;
3839
					dispatch_all();
3840
				}
3841
				, abortable = function(func) {
3842
					return function() {
3843
						if (filesaver.readyState !== filesaver.DONE) {
3844
							return func.apply(this, arguments);
3845
						}
3846
					};
3847
				}
3848
				, create_if_not_found = {create: true, exclusive: false}
3849
				, slice
3850
			;
3851
			filesaver.readyState = filesaver.INIT;
3852
			if (!name) {
3853
				name = "download";
3854
			}
3855
			if (can_use_save_link) {
3856
				object_url = get_object_url(blob);
3857
				save_link.href = object_url;
3858
				save_link.download = name;
3859
				if (click(save_link)) {
3860
					filesaver.readyState = filesaver.DONE;
3861
					dispatch_all();
3862
					return;
3863
				}
3864
			}
3865
			// Object and web filesystem URLs have a problem saving in Google Chrome when
3866
			// viewed in a tab, so I force save with application/octet-stream
3867
			// http://code.google.com/p/chromium/issues/detail?id=91158
3868
			if (view.chrome && type && type !== force_saveable_type) {
3869
				slice = blob.slice || blob.webkitSlice;
3870
				blob = slice.call(blob, 0, blob.size, force_saveable_type);
3871
				blob_changed = true;
3872
			}
3873
			// Since I can't be sure that the guessed media type will trigger a download
3874
			// in WebKit, I append .download to the filename.
3875
			// https://bugs.webkit.org/show_bug.cgi?id=65440
3876
			if (webkit_req_fs && name !== "download") {
3877
				name += ".download";
3878
			}
3879
			if (type === force_saveable_type || webkit_req_fs) {
3880
				target_view = view;
3881
			} else {
3882
				target_view = view.open();
3883
			}
3884
			if (!req_fs) {
3885
				fs_error();
3886
				return;
3887
			}
3888
			fs_min_size += blob.size;
3889
			req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
3890
				fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
3891
					var save = function() {
3892
						dir.getFile(name, create_if_not_found, abortable(function(file) {
3893
							file.createWriter(abortable(function(writer) {
3894
								writer.onwriteend = function(event) {
3895
									target_view.location.href = file.toURL();
3896
									deletion_queue.push(file);
3897
									filesaver.readyState = filesaver.DONE;
3898
									dispatch(filesaver, "writeend", event);
3899
								};
3900
								writer.onerror = function() {
3901
									var error = writer.error;
3902
									if (error.code !== error.ABORT_ERR) {
3903
										fs_error();
3904
									}
3905
								};
3906
								"writestart progress write abort".split(" ").forEach(function(event) {
3907
									writer["on" + event] = filesaver["on" + event];
3908
								});
3909
								writer.write(blob);
3910
								filesaver.abort = function() {
3911
									writer.abort();
3912
									filesaver.readyState = filesaver.DONE;
3913
								};
3914
								filesaver.readyState = filesaver.WRITING;
3915
							}), fs_error);
3916
						}), fs_error);
3917
					};
3918
					dir.getFile(name, {create: false}, abortable(function(file) {
3919
						// delete file if it already exists
3920
						file.remove();
3921
						save();
3922
					}), abortable(function(ex) {
3923
						if (ex.code === ex.NOT_FOUND_ERR) {
3924
							save();
3925
						} else {
3926
							fs_error();
3927
						}
3928
					}));
3929
				}), fs_error);
3930
			}), fs_error);
3931
		}
3932
		, FS_proto = FileSaver.prototype
3933
		, saveAs = function(blob, name) {
3934
			return new FileSaver(blob, name);
3935
		}
3936
	;
3937
	FS_proto.abort = function() {
3938
		var filesaver = this;
3939
		filesaver.readyState = filesaver.DONE;
3940
		dispatch(filesaver, "abort");
3941
	};
3942
	FS_proto.readyState = FS_proto.INIT = 0;
3943
	FS_proto.WRITING = 1;
3944
	FS_proto.DONE = 2;
3945
 
3946
	FS_proto.error =
3947
	FS_proto.onwritestart =
3948
	FS_proto.onprogress =
3949
	FS_proto.onwrite =
3950
	FS_proto.onabort =
3951
	FS_proto.onerror =
3952
	FS_proto.onwriteend =
3953
		null;
3954
 
3955
	view.addEventListener("unload", process_deletion_queue, false);
3956
	return saveAs;
3957
}(self));
3958
/*
3959
 Copyright (c) 2013 Gildas Lormeau. All rights reserved.
3960
 
3961
 Redistribution and use in source and binary forms, with or without
3962
 modification, are permitted provided that the following conditions are met:
3963
 
3964
 1. Redistributions of source code must retain the above copyright notice,
3965
 this list of conditions and the following disclaimer.
3966
 
3967
 2. Redistributions in binary form must reproduce the above copyright
3968
 notice, this list of conditions and the following disclaimer in
3969
 the documentation and/or other materials provided with the distribution.
3970
 
3971
 3. The names of the authors may not be used to endorse or promote products
3972
 derived from this software without specific prior written permission.
3973
 
3974
 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
3975
 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
3976
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
3977
 INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
3978
 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3979
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
3980
 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3981
 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3982
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
3983
 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3984
 */
3985
 
3986
/*
3987
 * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.
3988
 * JZlib is based on zlib-1.1.3, so all credit should go authors
3989
 * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
3990
 * and contributors of zlib.
3991
 */
3992
 
3993
// Global
3994
 
3995
var MAX_BITS = 15;
3996
var D_CODES = 30;
3997
var BL_CODES = 19;
3998
 
3999
var LENGTH_CODES = 29;
4000
var LITERALS = 256;
4001
var L_CODES = (LITERALS + 1 + LENGTH_CODES);
4002
var HEAP_SIZE = (2 * L_CODES + 1);
4003
 
4004
var END_BLOCK = 256;
4005
 
4006
// Bit length codes must not exceed MAX_BL_BITS bits
4007
var MAX_BL_BITS = 7;
4008
 
4009
// repeat previous bit length 3-6 times (2 bits of repeat count)
4010
var REP_3_6 = 16;
4011
 
4012
// repeat a zero length 3-10 times (3 bits of repeat count)
4013
var REPZ_3_10 = 17;
4014
 
4015
// repeat a zero length 11-138 times (7 bits of repeat count)
4016
var REPZ_11_138 = 18;
4017
 
4018
// The lengths of the bit length codes are sent in order of decreasing
4019
// probability, to avoid transmitting the lengths for unused bit
4020
// length codes.
4021
 
4022
var Buf_size = 8 * 2;
4023
 
4024
// JZlib version : "1.0.2"
4025
var Z_DEFAULT_COMPRESSION = -1;
4026
 
4027
// compression strategy
4028
var Z_FILTERED = 1;
4029
var Z_HUFFMAN_ONLY = 2;
4030
var Z_DEFAULT_STRATEGY = 0;
4031
 
4032
var Z_NO_FLUSH = 0;
4033
var Z_PARTIAL_FLUSH = 1;
4034
var Z_FULL_FLUSH = 3;
4035
var Z_FINISH = 4;
4036
 
4037
var Z_OK = 0;
4038
var Z_STREAM_END = 1;
4039
var Z_NEED_DICT = 2;
4040
var Z_STREAM_ERROR = -2;
4041
var Z_DATA_ERROR = -3;
4042
var Z_BUF_ERROR = -5;
4043
 
4044
// Tree
4045
 
4046
// see definition of array dist_code below
4047
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,
4048
        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,
4049
        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,
4050
        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,
4051
        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,
4052
        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,
4053
        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,
4054
        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,
4055
        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,
4056
        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,
4057
        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,
4058
        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,
4059
        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,
4060
        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 ];
4061
 
4062
function Tree() {
4063
    'use strict';
4064
    var that = this;
4065
 
4066
    // dyn_tree; // the dynamic tree
4067
    // max_code; // largest code with non zero frequency
4068
    // stat_desc; // the corresponding static tree
4069
 
4070
    // Compute the optimal bit lengths for a tree and update the total bit
4071
    // length
4072
    // for the current block.
4073
    // IN assertion: the fields freq and dad are set, heap[heap_max] and
4074
    // above are the tree nodes sorted by increasing frequency.
4075
    // OUT assertions: the field len is set to the optimal bit length, the
4076
    // array bl_count contains the frequencies for each bit length.
4077
    // The length opt_len is updated; static_len is also updated if stree is
4078
    // not null.
4079
    function gen_bitlen(s) {
4080
        var tree = that.dyn_tree;
4081
        var stree = that.stat_desc.static_tree;
4082
        var extra = that.stat_desc.extra_bits;
4083
        var base = that.stat_desc.extra_base;
4084
        var max_length = that.stat_desc.max_length;
4085
        var h; // heap index
4086
        var n, m; // iterate over the tree elements
4087
        var bits; // bit length
4088
        var xbits; // extra bits
4089
        var f; // frequency
4090
        var overflow = 0; // number of elements with bit length too large
4091
 
4092
        for (bits = 0; bits <= MAX_BITS; bits++)
4093
            s.bl_count[bits] = 0;
4094
 
4095
        // In a first pass, compute the optimal bit lengths (which may
4096
        // overflow in the case of the bit length tree).
4097
        tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
4098
 
4099
        for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
4100
            n = s.heap[h];
4101
            bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
4102
            if (bits > max_length) {
4103
                bits = max_length;
4104
                overflow++;
4105
            }
4106
            tree[n * 2 + 1] = bits;
4107
            // We overwrite tree[n*2+1] which is no longer needed
4108
 
4109
            if (n > that.max_code)
4110
                continue; // not a leaf node
4111
 
4112
            s.bl_count[bits]++;
4113
            xbits = 0;
4114
            if (n >= base)
4115
                xbits = extra[n - base];
4116
            f = tree[n * 2];
4117
            s.opt_len += f * (bits + xbits);
4118
            if (stree)
4119
                s.static_len += f * (stree[n * 2 + 1] + xbits);
4120
        }
4121
        if (overflow === 0)
4122
            return;
4123
 
4124
        // This happens for example on obj2 and pic of the Calgary corpus
4125
        // Find the first bit length which could increase:
4126
        do {
4127
            bits = max_length - 1;
4128
            while (s.bl_count[bits] === 0)
4129
                bits--;
4130
            s.bl_count[bits]--; // move one leaf down the tree
4131
            s.bl_count[bits + 1] += 2; // move one overflow item as its brother
4132
            s.bl_count[max_length]--;
4133
            // The brother of the overflow item also moves one step up,
4134
            // but this does not affect bl_count[max_length]
4135
            overflow -= 2;
4136
        } while (overflow > 0);
4137
 
4138
        for (bits = max_length; bits !== 0; bits--) {
4139
            n = s.bl_count[bits];
4140
            while (n !== 0) {
4141
                m = s.heap[--h];
4142
                if (m > that.max_code)
4143
                    continue;
4144
                if (tree[m * 2 + 1] != bits) {
4145
                    s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2];
4146
                    tree[m * 2 + 1] = bits;
4147
                }
4148
                n--;
4149
            }
4150
        }
4151
    }
4152
 
4153
    // Reverse the first len bits of a code, using straightforward code (a
4154
    // faster
4155
    // method would use a table)
4156
    // IN assertion: 1 <= len <= 15
4157
    function bi_reverse(code, // the value to invert
4158
    len // its bit length
4159
    ) {
4160
        var res = 0;
4161
        do {
4162
            res |= code & 1;
4163
            code >>>= 1;
4164
            res <<= 1;
4165
        } while (--len > 0);
4166
        return res >>> 1;
4167
    }
4168
 
4169
    // Generate the codes for a given tree and bit counts (which need not be
4170
    // optimal).
4171
    // IN assertion: the array bl_count contains the bit length statistics for
4172
    // the given tree and the field len is set for all tree elements.
4173
    // OUT assertion: the field code is set for all tree elements of non
4174
    // zero code length.
4175
    function gen_codes(tree, // the tree to decorate
4176
    max_code, // largest code with non zero frequency
4177
    bl_count // number of codes at each bit length
4178
    ) {
4179
        var next_code = []; // next code value for each
4180
        // bit length
4181
        var code = 0; // running code value
4182
        var bits; // bit index
4183
        var n; // code index
4184
        var len;
4185
 
4186
        // The distribution counts are first used to generate the code values
4187
        // without bit reversal.
4188
        for (bits = 1; bits <= MAX_BITS; bits++) {
4189
            next_code[bits] = code = ((code + bl_count[bits - 1]) << 1);
4190
        }
4191
 
4192
        // Check that the bit counts in bl_count are consistent. The last code
4193
        // must be all ones.
4194
        // Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
4195
        // "inconsistent bit counts");
4196
        // Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
4197
 
4198
        for (n = 0; n <= max_code; n++) {
4199
            len = tree[n * 2 + 1];
4200
            if (len === 0)
4201
                continue;
4202
            // Now reverse the bits
4203
            tree[n * 2] = bi_reverse(next_code[len]++, len);
4204
        }
4205
    }
4206
 
4207
    // Construct one Huffman tree and assigns the code bit strings and lengths.
4208
    // Update the total bit length for the current block.
4209
    // IN assertion: the field freq is set for all tree elements.
4210
    // OUT assertions: the fields len and code are set to the optimal bit length
4211
    // and corresponding code. The length opt_len is updated; static_len is
4212
    // also updated if stree is not null. The field max_code is set.
4213
    that.build_tree = function(s) {
4214
        var tree = that.dyn_tree;
4215
        var stree = that.stat_desc.static_tree;
4216
        var elems = that.stat_desc.elems;
4217
        var n, m; // iterate over heap elements
4218
        var max_code = -1; // largest code with non zero frequency
4219
        var node; // new node being created
4220
 
4221
        // Construct the initial heap, with least frequent element in
4222
        // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
4223
        // heap[0] is not used.
4224
        s.heap_len = 0;
4225
        s.heap_max = HEAP_SIZE;
4226
 
4227
        for (n = 0; n < elems; n++) {
4228
            if (tree[n * 2] !== 0) {
4229
                s.heap[++s.heap_len] = max_code = n;
4230
                s.depth[n] = 0;
4231
            } else {
4232
                tree[n * 2 + 1] = 0;
4233
            }
4234
        }
4235
 
4236
        // The pkzip format requires that at least one distance code exists,
4237
        // and that at least one bit should be sent even if there is only one
4238
        // possible code. So to avoid special checks later on we force at least
4239
        // two codes of non zero frequency.
4240
        while (s.heap_len < 2) {
4241
            node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0;
4242
            tree[node * 2] = 1;
4243
            s.depth[node] = 0;
4244
            s.opt_len--;
4245
            if (stree)
4246
                s.static_len -= stree[node * 2 + 1];
4247
            // node is 0 or 1 so it does not have extra bits
4248
        }
4249
        that.max_code = max_code;
4250
 
4251
        // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
4252
        // establish sub-heaps of increasing lengths:
4253
 
4254
        for (n = Math.floor(s.heap_len / 2); n >= 1; n--)
4255
            s.pqdownheap(tree, n);
4256
 
4257
        // Construct the Huffman tree by repeatedly combining the least two
4258
        // frequent nodes.
4259
 
4260
        node = elems; // next internal node of the tree
4261
        do {
4262
            // n = node of least frequency
4263
            n = s.heap[1];
4264
            s.heap[1] = s.heap[s.heap_len--];
4265
            s.pqdownheap(tree, 1);
4266
            m = s.heap[1]; // m = node of next least frequency
4267
 
4268
            s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
4269
            s.heap[--s.heap_max] = m;
4270
 
4271
            // Create a new node father of n and m
4272
            tree[node * 2] = (tree[n * 2] + tree[m * 2]);
4273
            s.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1;
4274
            tree[n * 2 + 1] = tree[m * 2 + 1] = node;
4275
 
4276
            // and insert the new node in the heap
4277
            s.heap[1] = node++;
4278
            s.pqdownheap(tree, 1);
4279
        } while (s.heap_len >= 2);
4280
 
4281
        s.heap[--s.heap_max] = s.heap[1];
4282
 
4283
        // At this point, the fields freq and dad are set. We can now
4284
        // generate the bit lengths.
4285
 
4286
        gen_bitlen(s);
4287
 
4288
        // The field len is now set, we can generate the bit codes
4289
        gen_codes(tree, that.max_code, s.bl_count);
4290
    };
4291
 
4292
}
4293
 
4294
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,
4295
        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,
4296
        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,
4297
        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,
4298
        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,
4299
        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,
4300
        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 ];
4301
 
4302
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 ];
4303
 
4304
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,
4305
        24576 ];
4306
 
4307
// Mapping from a distance to a distance code. dist is the distance - 1 and
4308
// must not have side effects. _dist_code[256] and _dist_code[257] are never
4309
// used.
4310
Tree.d_code = function(dist) {
4311
    return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >>> 7)]);
4312
};
4313
 
4314
// extra bits for each length code
4315
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 ];
4316
 
4317
// extra bits for each distance code
4318
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 ];
4319
 
4320
// extra bits for each bit length code
4321
Tree.extra_blbits = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 ];
4322
 
4323
Tree.bl_order = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
4324
 
4325
// StaticTree
4326
 
4327
function StaticTree(static_tree, extra_bits, extra_base, elems, max_length) {
4328
    var that = this;
4329
    that.static_tree = static_tree;
4330
    that.extra_bits = extra_bits;
4331
    that.extra_base = extra_base;
4332
    that.elems = elems;
4333
    that.max_length = max_length;
4334
}
4335
 
4336
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,
4337
        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,
4338
        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,
4339
        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,
4340
        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,
4341
        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,
4342
        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,
4343
        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,
4344
        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,
4345
        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,
4346
        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,
4347
        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,
4348
        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,
4349
        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,
4350
        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,
4351
        99, 8, 227, 8 ];
4352
 
4353
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,
4354
        25, 5, 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5 ];
4355
 
4356
StaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
4357
 
4358
StaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS);
4359
 
4360
StaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
4361
 
4362
// Deflate
4363
 
4364
var MAX_MEM_LEVEL = 9;
4365
var DEF_MEM_LEVEL = 8;
4366
 
4367
function Config(good_length, max_lazy, nice_length, max_chain, func) {
4368
    var that = this;
4369
    that.good_length = good_length;
4370
    that.max_lazy = max_lazy;
4371
    that.nice_length = nice_length;
4372
    that.max_chain = max_chain;
4373
    that.func = func;
4374
}
4375
 
4376
var STORED = 0;
4377
var FAST = 1;
4378
var SLOW = 2;
4379
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),
4380
        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),
4381
        new Config(32, 128, 258, 1024, SLOW), new Config(32, 258, 258, 4096, SLOW) ];
4382
 
4383
var z_errmsg = [ "need dictionary", // Z_NEED_DICT
4384
// 2
4385
"stream end", // Z_STREAM_END 1
4386
"", // Z_OK 0
4387
"", // Z_ERRNO (-1)
4388
"stream error", // Z_STREAM_ERROR (-2)
4389
"data error", // Z_DATA_ERROR (-3)
4390
"", // Z_MEM_ERROR (-4)
4391
"buffer error", // Z_BUF_ERROR (-5)
4392
"",// Z_VERSION_ERROR (-6)
4393
"" ];
4394
 
4395
// block not completed, need more input or more output
4396
var NeedMore = 0;
4397
 
4398
// block flush performed
4399
var BlockDone = 1;
4400
 
4401
// finish started, need only more output at next deflate
4402
var FinishStarted = 2;
4403
 
4404
// finish done, accept no more input or output
4405
var FinishDone = 3;
4406
 
4407
// preset dictionary flag in zlib header
4408
var PRESET_DICT = 0x20;
4409
 
4410
var INIT_STATE = 42;
4411
var BUSY_STATE = 113;
4412
var FINISH_STATE = 666;
4413
 
4414
// The deflate compression method
4415
var Z_DEFLATED = 8;
4416
 
4417
var STORED_BLOCK = 0;
4418
var STATIC_TREES = 1;
4419
var DYN_TREES = 2;
4420
 
4421
var MIN_MATCH = 3;
4422
var MAX_MATCH = 258;
4423
var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
4424
 
4425
function smaller(tree, n, m, depth) {
4426
    var tn2 = tree[n * 2];
4427
    var tm2 = tree[m * 2];
4428
    return (tn2 < tm2 || (tn2 == tm2 && depth[n] <= depth[m]));
4429
}
4430
 
4431
function Deflate() {
4432
 
4433
    var that = this;
4434
    var strm; // pointer back to this zlib stream
4435
    var status; // as the name implies
4436
    // pending_buf; // output still pending
4437
    var pending_buf_size; // size of pending_buf
4438
    // pending_out; // next pending byte to output to the stream
4439
    // pending; // nb of bytes in the pending buffer
4440
    var method; // STORED (for zip only) or DEFLATED
4441
    var last_flush; // value of flush param for previous deflate call
4442
 
4443
    var w_size; // LZ77 window size (32K by default)
4444
    var w_bits; // log2(w_size) (8..16)
4445
    var w_mask; // w_size - 1
4446
 
4447
    var window;
4448
    // Sliding window. Input bytes are read into the second half of the window,
4449
    // and move to the first half later to keep a dictionary of at least wSize
4450
    // bytes. With this organization, matches are limited to a distance of
4451
    // wSize-MAX_MATCH bytes, but this ensures that IO is always
4452
    // performed with a length multiple of the block size. Also, it limits
4453
    // the window size to 64K, which is quite useful on MSDOS.
4454
    // To do: use the user input buffer as sliding window.
4455
 
4456
    var window_size;
4457
    // Actual size of window: 2*wSize, except when the user input buffer
4458
    // is directly used as sliding window.
4459
 
4460
    var prev;
4461
    // Link to older string with same hash index. To limit the size of this
4462
    // array to 64K, this link is maintained only for the last 32K strings.
4463
    // An index in this array is thus a window index modulo 32K.
4464
 
4465
    var head; // Heads of the hash chains or NIL.
4466
 
4467
    var ins_h; // hash index of string to be inserted
4468
    var hash_size; // number of elements in hash table
4469
    var hash_bits; // log2(hash_size)
4470
    var hash_mask; // hash_size-1
4471
 
4472
    // Number of bits by which ins_h must be shifted at each input
4473
    // step. It must be such that after MIN_MATCH steps, the oldest
4474
    // byte no longer takes part in the hash key, that is:
4475
    // hash_shift * MIN_MATCH >= hash_bits
4476
    var hash_shift;
4477
 
4478
    // Window position at the beginning of the current output block. Gets
4479
    // negative when the window is moved backwards.
4480
 
4481
    var block_start;
4482
 
4483
    var match_length; // length of best match
4484
    var prev_match; // previous match
4485
    var match_available; // set if previous match exists
4486
    var strstart; // start of string to insert
4487
    var match_start; // start of matching string
4488
    var lookahead; // number of valid bytes ahead in window
4489
 
4490
    // Length of the best match at previous step. Matches not greater than this
4491
    // are discarded. This is used in the lazy match evaluation.
4492
    var prev_length;
4493
 
4494
    // To speed up deflation, hash chains are never searched beyond this
4495
    // length. A higher limit improves compression ratio but degrades the speed.
4496
    var max_chain_length;
4497
 
4498
    // Attempt to find a better match only when the current match is strictly
4499
    // smaller than this value. This mechanism is used only for compression
4500
    // levels >= 4.
4501
    var max_lazy_match;
4502
 
4503
    // Insert new strings in the hash table only if the match length is not
4504
    // greater than this length. This saves time but degrades compression.
4505
    // max_insert_length is used only for compression levels <= 3.
4506
 
4507
    var level; // compression level (1..9)
4508
    var strategy; // favor or force Huffman coding
4509
 
4510
    // Use a faster search when the previous match is longer than this
4511
    var good_match;
4512
 
4513
    // Stop searching when current match exceeds this
4514
    var nice_match;
4515
 
4516
    var dyn_ltree; // literal and length tree
4517
    var dyn_dtree; // distance tree
4518
    var bl_tree; // Huffman tree for bit lengths
4519
 
4520
    var l_desc = new Tree(); // desc for literal tree
4521
    var d_desc = new Tree(); // desc for distance tree
4522
    var bl_desc = new Tree(); // desc for bit length tree
4523
 
4524
    // that.heap_len; // number of elements in the heap
4525
    // that.heap_max; // element of largest frequency
4526
    // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
4527
    // The same heap array is used to build all trees.
4528
 
4529
    // Depth of each subtree used as tie breaker for trees of equal frequency
4530
    that.depth = [];
4531
 
4532
    var l_buf; // index for literals or lengths */
4533
 
4534
    // Size of match buffer for literals/lengths. There are 4 reasons for
4535
    // limiting lit_bufsize to 64K:
4536
    // - frequencies can be kept in 16 bit counters
4537
    // - if compression is not successful for the first block, all input
4538
    // data is still in the window so we can still emit a stored block even
4539
    // when input comes from standard input. (This can also be done for
4540
    // all blocks if lit_bufsize is not greater than 32K.)
4541
    // - if compression is not successful for a file smaller than 64K, we can
4542
    // even emit a stored file instead of a stored block (saving 5 bytes).
4543
    // This is applicable only for zip (not gzip or zlib).
4544
    // - creating new Huffman trees less frequently may not provide fast
4545
    // adaptation to changes in the input data statistics. (Take for
4546
    // example a binary file with poorly compressible code followed by
4547
    // a highly compressible string table.) Smaller buffer sizes give
4548
    // fast adaptation but have of course the overhead of transmitting
4549
    // trees more frequently.
4550
    // - I can't count above 4
4551
    var lit_bufsize;
4552
 
4553
    var last_lit; // running index in l_buf
4554
 
4555
    // Buffer for distances. To simplify the code, d_buf and l_buf have
4556
    // the same number of elements. To use different lengths, an extra flag
4557
    // array would be necessary.
4558
 
4559
    var d_buf; // index of pendig_buf
4560
 
4561
    // that.opt_len; // bit length of current block with optimal trees
4562
    // that.static_len; // bit length of current block with static trees
4563
    var matches; // number of string matches in current block
4564
    var last_eob_len; // bit length of EOB code for last block
4565
 
4566
    // Output buffer. bits are inserted starting at the bottom (least
4567
    // significant bits).
4568
    var bi_buf;
4569
 
4570
    // Number of valid bits in bi_buf. All bits above the last valid bit
4571
    // are always zero.
4572
    var bi_valid;
4573
 
4574
    // number of codes at each bit length for an optimal tree
4575
    that.bl_count = [];
4576
 
4577
    // heap used to build the Huffman trees
4578
    that.heap = [];
4579
 
4580
    dyn_ltree = [];
4581
    dyn_dtree = [];
4582
    bl_tree = [];
4583
 
4584
    function lm_init() {
4585
        var i;
4586
        window_size = 2 * w_size;
4587
 
4588
        head[hash_size - 1] = 0;
4589
        for (i = 0; i < hash_size - 1; i++) {
4590
            head[i] = 0;
4591
        }
4592
 
4593
        // Set the default configuration parameters:
4594
        max_lazy_match = config_table[level].max_lazy;
4595
        good_match = config_table[level].good_length;
4596
        nice_match = config_table[level].nice_length;
4597
        max_chain_length = config_table[level].max_chain;
4598
 
4599
        strstart = 0;
4600
        block_start = 0;
4601
        lookahead = 0;
4602
        match_length = prev_length = MIN_MATCH - 1;
4603
        match_available = 0;
4604
        ins_h = 0;
4605
    }
4606
 
4607
    function init_block() {
4608
        var i;
4609
        // Initialize the trees.
4610
        for (i = 0; i < L_CODES; i++)
4611
            dyn_ltree[i * 2] = 0;
4612
        for (i = 0; i < D_CODES; i++)
4613
            dyn_dtree[i * 2] = 0;
4614
        for (i = 0; i < BL_CODES; i++)
4615
            bl_tree[i * 2] = 0;
4616
 
4617
        dyn_ltree[END_BLOCK * 2] = 1;
4618
        that.opt_len = that.static_len = 0;
4619
        last_lit = matches = 0;
4620
    }
4621
 
4622
    // Initialize the tree data structures for a new zlib stream.
4623
    function tr_init() {
4624
 
4625
        l_desc.dyn_tree = dyn_ltree;
4626
        l_desc.stat_desc = StaticTree.static_l_desc;
4627
 
4628
        d_desc.dyn_tree = dyn_dtree;
4629
        d_desc.stat_desc = StaticTree.static_d_desc;
4630
 
4631
        bl_desc.dyn_tree = bl_tree;
4632
        bl_desc.stat_desc = StaticTree.static_bl_desc;
4633
 
4634
        bi_buf = 0;
4635
        bi_valid = 0;
4636
        last_eob_len = 8; // enough lookahead for inflate
4637
 
4638
        // Initialize the first block of the first file:
4639
        init_block();
4640
    }
4641
 
4642
    // Restore the heap property by moving down the tree starting at node k,
4643
    // exchanging a node with the smallest of its two sons if necessary,
4644
    // stopping
4645
    // when the heap property is re-established (each father smaller than its
4646
    // two sons).
4647
    that.pqdownheap = function(tree, // the tree to restore
4648
    k // node to move down
4649
    ) {
4650
        var heap = that.heap;
4651
        var v = heap[k];
4652
        var j = k << 1; // left son of k
4653
        while (j <= that.heap_len) {
4654
            // Set j to the smallest of the two sons:
4655
            if (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) {
4656
                j++;
4657
            }
4658
            // Exit if v is smaller than both sons
4659
            if (smaller(tree, v, heap[j], that.depth))
4660
                break;
4661
 
4662
            // Exchange v with the smallest son
4663
            heap[k] = heap[j];
4664
            k = j;
4665
            // And continue down the tree, setting j to the left son of k
4666
            j <<= 1;
4667
        }
4668
        heap[k] = v;
4669
    };
4670
 
4671
    // Scan a literal or distance tree to determine the frequencies of the codes
4672
    // in the bit length tree.
4673
    function scan_tree(tree,// the tree to be scanned
4674
    max_code // and its largest code of non zero frequency
4675
    ) {
4676
        var n; // iterates over all tree elements
4677
        var prevlen = -1; // last emitted length
4678
        var curlen; // length of current code
4679
        var nextlen = tree[0 * 2 + 1]; // length of next code
4680
        var count = 0; // repeat count of the current code
4681
        var max_count = 7; // max repeat count
4682
        var min_count = 4; // min repeat count
4683
 
4684
        if (nextlen === 0) {
4685
            max_count = 138;
4686
            min_count = 3;
4687
        }
4688
        tree[(max_code + 1) * 2 + 1] = 0xffff; // guard
4689
 
4690
        for (n = 0; n <= max_code; n++) {
4691
            curlen = nextlen;
4692
            nextlen = tree[(n + 1) * 2 + 1];
4693
            if (++count < max_count && curlen == nextlen) {
4694
                continue;
4695
            } else if (count < min_count) {
4696
                bl_tree[curlen * 2] += count;
4697
            } else if (curlen !== 0) {
4698
                if (curlen != prevlen)
4699
                    bl_tree[curlen * 2]++;
4700
                bl_tree[REP_3_6 * 2]++;
4701
            } else if (count <= 10) {
4702
                bl_tree[REPZ_3_10 * 2]++;
4703
            } else {
4704
                bl_tree[REPZ_11_138 * 2]++;
4705
            }
4706
            count = 0;
4707
            prevlen = curlen;
4708
            if (nextlen === 0) {
4709
                max_count = 138;
4710
                min_count = 3;
4711
            } else if (curlen == nextlen) {
4712
                max_count = 6;
4713
                min_count = 3;
4714
            } else {
4715
                max_count = 7;
4716
                min_count = 4;
4717
            }
4718
        }
4719
    }
4720
 
4721
    // Construct the Huffman tree for the bit lengths and return the index in
4722
    // bl_order of the last bit length code to send.
4723
    function build_bl_tree() {
4724
        var max_blindex; // index of last bit length code of non zero freq
4725
 
4726
        // Determine the bit length frequencies for literal and distance trees
4727
        scan_tree(dyn_ltree, l_desc.max_code);
4728
        scan_tree(dyn_dtree, d_desc.max_code);
4729
 
4730
        // Build the bit length tree:
4731
        bl_desc.build_tree(that);
4732
        // opt_len now includes the length of the tree representations, except
4733
        // the lengths of the bit lengths codes and the 5+5+4 bits for the
4734
        // counts.
4735
 
4736
        // Determine the number of bit length codes to send. The pkzip format
4737
        // requires that at least 4 bit length codes be sent. (appnote.txt says
4738
        // 3 but the actual value used is 4.)
4739
        for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
4740
            if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0)
4741
                break;
4742
        }
4743
        // Update opt_len to include the bit length tree and counts
4744
        that.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
4745
 
4746
        return max_blindex;
4747
    }
4748
 
4749
    // Output a byte on the stream.
4750
    // IN assertion: there is enough room in pending_buf.
4751
    function put_byte(p) {
4752
        that.pending_buf[that.pending++] = p;
4753
    }
4754
 
4755
    function put_short(w) {
4756
        put_byte(w & 0xff);
4757
        put_byte((w >>> 8) & 0xff);
4758
    }
4759
 
4760
    function putShortMSB(b) {
4761
        put_byte((b >> 8) & 0xff);
4762
        put_byte((b & 0xff) & 0xff);
4763
    }
4764
 
4765
    function send_bits(value, length) {
4766
        var val, len = length;
4767
        if (bi_valid > Buf_size - len) {
4768
            val = value;
4769
            // bi_buf |= (val << bi_valid);
4770
            bi_buf |= ((val << bi_valid) & 0xffff);
4771
            put_short(bi_buf);
4772
            bi_buf = val >>> (Buf_size - bi_valid);
4773
            bi_valid += len - Buf_size;
4774
        } else {
4775
            // bi_buf |= (value) << bi_valid;
4776
            bi_buf |= (((value) << bi_valid) & 0xffff);
4777
            bi_valid += len;
4778
        }
4779
    }
4780
 
4781
    function send_code(c, tree) {
4782
        var c2 = c * 2;
4783
        send_bits(tree[c2] & 0xffff, tree[c2 + 1] & 0xffff);
4784
    }
4785
 
4786
    // Send a literal or distance tree in compressed form, using the codes in
4787
    // bl_tree.
4788
    function send_tree(tree,// the tree to be sent
4789
    max_code // and its largest code of non zero frequency
4790
    ) {
4791
        var n; // iterates over all tree elements
4792
        var prevlen = -1; // last emitted length
4793
        var curlen; // length of current code
4794
        var nextlen = tree[0 * 2 + 1]; // length of next code
4795
        var count = 0; // repeat count of the current code
4796
        var max_count = 7; // max repeat count
4797
        var min_count = 4; // min repeat count
4798
 
4799
        if (nextlen === 0) {
4800
            max_count = 138;
4801
            min_count = 3;
4802
        }
4803
 
4804
        for (n = 0; n <= max_code; n++) {
4805
            curlen = nextlen;
4806
            nextlen = tree[(n + 1) * 2 + 1];
4807
            if (++count < max_count && curlen == nextlen) {
4808
                continue;
4809
            } else if (count < min_count) {
4810
                do {
4811
                    send_code(curlen, bl_tree);
4812
                } while (--count !== 0);
4813
            } else if (curlen !== 0) {
4814
                if (curlen != prevlen) {
4815
                    send_code(curlen, bl_tree);
4816
                    count--;
4817
                }
4818
                send_code(REP_3_6, bl_tree);
4819
                send_bits(count - 3, 2);
4820
            } else if (count <= 10) {
4821
                send_code(REPZ_3_10, bl_tree);
4822
                send_bits(count - 3, 3);
4823
            } else {
4824
                send_code(REPZ_11_138, bl_tree);
4825
                send_bits(count - 11, 7);
4826
            }
4827
            count = 0;
4828
            prevlen = curlen;
4829
            if (nextlen === 0) {
4830
                max_count = 138;
4831
                min_count = 3;
4832
            } else if (curlen == nextlen) {
4833
                max_count = 6;
4834
                min_count = 3;
4835
            } else {
4836
                max_count = 7;
4837
                min_count = 4;
4838
            }
4839
        }
4840
    }
4841
 
4842
    // Send the header for a block using dynamic Huffman trees: the counts, the
4843
    // lengths of the bit length codes, the literal tree and the distance tree.
4844
    // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
4845
    function send_all_trees(lcodes, dcodes, blcodes) {
4846
        var rank; // index in bl_order
4847
 
4848
        send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
4849
        send_bits(dcodes - 1, 5);
4850
        send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
4851
        for (rank = 0; rank < blcodes; rank++) {
4852
            send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3);
4853
        }
4854
        send_tree(dyn_ltree, lcodes - 1); // literal tree
4855
        send_tree(dyn_dtree, dcodes - 1); // distance tree
4856
    }
4857
 
4858
    // Flush the bit buffer, keeping at most 7 bits in it.
4859
    function bi_flush() {
4860
        if (bi_valid == 16) {
4861
            put_short(bi_buf);
4862
            bi_buf = 0;
4863
            bi_valid = 0;
4864
        } else if (bi_valid >= 8) {
4865
            put_byte(bi_buf & 0xff);
4866
            bi_buf >>>= 8;
4867
            bi_valid -= 8;
4868
        }
4869
    }
4870
 
4871
    // Send one empty static block to give enough lookahead for inflate.
4872
    // This takes 10 bits, of which 7 may remain in the bit buffer.
4873
    // The current inflate code requires 9 bits of lookahead. If the
4874
    // last two codes for the previous block (real code plus EOB) were coded
4875
    // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
4876
    // the last real code. In this case we send two empty static blocks instead
4877
    // of one. (There are no problems if the previous block is stored or fixed.)
4878
    // To simplify the code, we assume the worst case of last real code encoded
4879
    // on one bit only.
4880
    function _tr_align() {
4881
        send_bits(STATIC_TREES << 1, 3);
4882
        send_code(END_BLOCK, StaticTree.static_ltree);
4883
 
4884
        bi_flush();
4885
 
4886
        // Of the 10 bits for the empty block, we have already sent
4887
        // (10 - bi_valid) bits. The lookahead for the last real code (before
4888
        // the EOB of the previous block) was thus at least one plus the length
4889
        // of the EOB plus what we have just sent of the empty static block.
4890
        if (1 + last_eob_len + 10 - bi_valid < 9) {
4891
            send_bits(STATIC_TREES << 1, 3);
4892
            send_code(END_BLOCK, StaticTree.static_ltree);
4893
            bi_flush();
4894
        }
4895
        last_eob_len = 7;
4896
    }
4897
 
4898
    // Save the match info and tally the frequency counts. Return true if
4899
    // the current block must be flushed.
4900
    function _tr_tally(dist, // distance of matched string
4901
    lc // match length-MIN_MATCH or unmatched char (if dist==0)
4902
    ) {
4903
        var out_length, in_length, dcode;
4904
        that.pending_buf[d_buf + last_lit * 2] = (dist >>> 8) & 0xff;
4905
        that.pending_buf[d_buf + last_lit * 2 + 1] = dist & 0xff;
4906
 
4907
        that.pending_buf[l_buf + last_lit] = lc & 0xff;
4908
        last_lit++;
4909
 
4910
        if (dist === 0) {
4911
            // lc is the unmatched char
4912
            dyn_ltree[lc * 2]++;
4913
        } else {
4914
            matches++;
4915
            // Here, lc is the match length - MIN_MATCH
4916
            dist--; // dist = match distance - 1
4917
            dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++;
4918
            dyn_dtree[Tree.d_code(dist) * 2]++;
4919
        }
4920
 
4921
        if ((last_lit & 0x1fff) === 0 && level > 2) {
4922
            // Compute an upper bound for the compressed length
4923
            out_length = last_lit * 8;
4924
            in_length = strstart - block_start;
4925
            for (dcode = 0; dcode < D_CODES; dcode++) {
4926
                out_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]);
4927
            }
4928
            out_length >>>= 3;
4929
            if ((matches < Math.floor(last_lit / 2)) && out_length < Math.floor(in_length / 2))
4930
                return true;
4931
        }
4932
 
4933
        return (last_lit == lit_bufsize - 1);
4934
        // We avoid equality with lit_bufsize because of wraparound at 64K
4935
        // on 16 bit machines and because stored blocks are restricted to
4936
        // 64K-1 bytes.
4937
    }
4938
 
4939
    // Send the block data compressed using the given Huffman trees
4940
    function compress_block(ltree, dtree) {
4941
        var dist; // distance of matched string
4942
        var lc; // match length or unmatched char (if dist === 0)
4943
        var lx = 0; // running index in l_buf
4944
        var code; // the code to send
4945
        var extra; // number of extra bits to send
4946
 
4947
        if (last_lit !== 0) {
4948
            do {
4949
                dist = ((that.pending_buf[d_buf + lx * 2] << 8) & 0xff00) | (that.pending_buf[d_buf + lx * 2 + 1] & 0xff);
4950
                lc = (that.pending_buf[l_buf + lx]) & 0xff;
4951
                lx++;
4952
 
4953
                if (dist === 0) {
4954
                    send_code(lc, ltree); // send a literal byte
4955
                } else {
4956
                    // Here, lc is the match length - MIN_MATCH
4957
                    code = Tree._length_code[lc];
4958
 
4959
                    send_code(code + LITERALS + 1, ltree); // send the length
4960
                    // code
4961
                    extra = Tree.extra_lbits[code];
4962
                    if (extra !== 0) {
4963
                        lc -= Tree.base_length[code];
4964
                        send_bits(lc, extra); // send the extra length bits
4965
                    }
4966
                    dist--; // dist is now the match distance - 1
4967
                    code = Tree.d_code(dist);
4968
 
4969
                    send_code(code, dtree); // send the distance code
4970
                    extra = Tree.extra_dbits[code];
4971
                    if (extra !== 0) {
4972
                        dist -= Tree.base_dist[code];
4973
                        send_bits(dist, extra); // send the extra distance bits
4974
                    }
4975
                } // literal or match pair ?
4976
 
4977
                // Check that the overlay between pending_buf and d_buf+l_buf is
4978
                // ok:
4979
            } while (lx < last_lit);
4980
        }
4981
 
4982
        send_code(END_BLOCK, ltree);
4983
        last_eob_len = ltree[END_BLOCK * 2 + 1];
4984
    }
4985
 
4986
    // Flush the bit buffer and align the output on a byte boundary
4987
    function bi_windup() {
4988
        if (bi_valid > 8) {
4989
            put_short(bi_buf);
4990
        } else if (bi_valid > 0) {
4991
            put_byte(bi_buf & 0xff);
4992
        }
4993
        bi_buf = 0;
4994
        bi_valid = 0;
4995
    }
4996
 
4997
    // Copy a stored block, storing first the length and its
4998
    // one's complement if requested.
4999
    function copy_block(buf, // the input data
5000
    len, // its length
5001
    header // true if block header must be written
5002
    ) {
5003
        bi_windup(); // align on byte boundary
5004
        last_eob_len = 8; // enough lookahead for inflate
5005
 
5006
        if (header) {
5007
            put_short(len);
5008
            put_short(~len);
5009
        }
5010
 
5011
        that.pending_buf.set(window.subarray(buf, buf + len), that.pending);
5012
        that.pending += len;
5013
    }
5014
 
5015
    // Send a stored block
5016
    function _tr_stored_block(buf, // input block
5017
    stored_len, // length of input block
5018
    eof // true if this is the last block for a file
5019
    ) {
5020
        send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
5021
        copy_block(buf, stored_len, true); // with header
5022
    }
5023
 
5024
    // Determine the best encoding for the current block: dynamic trees, static
5025
    // trees or store, and output the encoded block to the zip file.
5026
    function _tr_flush_block(buf, // input block, or NULL if too old
5027
    stored_len, // length of input block
5028
    eof // true if this is the last block for a file
5029
    ) {
5030
        var opt_lenb, static_lenb;// opt_len and static_len in bytes
5031
        var max_blindex = 0; // index of last bit length code of non zero freq
5032
 
5033
        // Build the Huffman trees unless a stored block is forced
5034
        if (level > 0) {
5035
            // Construct the literal and distance trees
5036
            l_desc.build_tree(that);
5037
 
5038
            d_desc.build_tree(that);
5039
 
5040
            // At this point, opt_len and static_len are the total bit lengths
5041
            // of
5042
            // the compressed block data, excluding the tree representations.
5043
 
5044
            // Build the bit length tree for the above two trees, and get the
5045
            // index
5046
            // in bl_order of the last bit length code to send.
5047
            max_blindex = build_bl_tree();
5048
 
5049
            // Determine the best encoding. Compute first the block length in
5050
            // bytes
5051
            opt_lenb = (that.opt_len + 3 + 7) >>> 3;
5052
            static_lenb = (that.static_len + 3 + 7) >>> 3;
5053
 
5054
            if (static_lenb <= opt_lenb)
5055
                opt_lenb = static_lenb;
5056
        } else {
5057
            opt_lenb = static_lenb = stored_len + 5; // force a stored block
5058
        }
5059
 
5060
        if ((stored_len + 4 <= opt_lenb) && buf != -1) {
5061
            // 4: two words for the lengths
5062
            // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
5063
            // Otherwise we can't have processed more than WSIZE input bytes
5064
            // since
5065
            // the last block flush, because compression would have been
5066
            // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
5067
            // transform a block into a stored block.
5068
            _tr_stored_block(buf, stored_len, eof);
5069
        } else if (static_lenb == opt_lenb) {
5070
            send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
5071
            compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
5072
        } else {
5073
            send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
5074
            send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1);
5075
            compress_block(dyn_ltree, dyn_dtree);
5076
        }
5077
 
5078
        // The above check is made mod 2^32, for files larger than 512 MB
5079
        // and uLong implemented on 32 bits.
5080
 
5081
        init_block();
5082
 
5083
        if (eof) {
5084
            bi_windup();
5085
        }
5086
    }
5087
 
5088
    function flush_block_only(eof) {
5089
        _tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof);
5090
        block_start = strstart;
5091
        strm.flush_pending();
5092
    }
5093
 
5094
    // Fill the window when the lookahead becomes insufficient.
5095
    // Updates strstart and lookahead.
5096
    //
5097
    // IN assertion: lookahead < MIN_LOOKAHEAD
5098
    // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
5099
    // At least one byte has been read, or avail_in === 0; reads are
5100
    // performed for at least two bytes (required for the zip translate_eol
5101
    // option -- not supported here).
5102
    function fill_window() {
5103
        var n, m;
5104
        var p;
5105
        var more; // Amount of free space at the end of the window.
5106
 
5107
        do {
5108
            more = (window_size - lookahead - strstart);
5109
 
5110
            // Deal with !@#$% 64K limit:
5111
            if (more === 0 && strstart === 0 && lookahead === 0) {
5112
                more = w_size;
5113
            } else if (more == -1) {
5114
                // Very unlikely, but possible on 16 bit machine if strstart ==
5115
                // 0
5116
                // and lookahead == 1 (input done one byte at time)
5117
                more--;
5118
 
5119
                // If the window is almost full and there is insufficient
5120
                // lookahead,
5121
                // move the upper half to the lower one to make room in the
5122
                // upper half.
5123
            } else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) {
5124
                window.set(window.subarray(w_size, w_size + w_size), 0);
5125
 
5126
                match_start -= w_size;
5127
                strstart -= w_size; // we now have strstart >= MAX_DIST
5128
                block_start -= w_size;
5129
 
5130
                // Slide the hash table (could be avoided with 32 bit values
5131
                // at the expense of memory usage). We slide even when level ==
5132
                // 0
5133
                // to keep the hash table consistent if we switch back to level
5134
                // > 0
5135
                // later. (Using level 0 permanently is not an optimal usage of
5136
                // zlib, so we don't care about this pathological case.)
5137
 
5138
                n = hash_size;
5139
                p = n;
5140
                do {
5141
                    m = (head[--p] & 0xffff);
5142
                    head[p] = (m >= w_size ? m - w_size : 0);
5143
                } while (--n !== 0);
5144
 
5145
                n = w_size;
5146
                p = n;
5147
                do {
5148
                    m = (prev[--p] & 0xffff);
5149
                    prev[p] = (m >= w_size ? m - w_size : 0);
5150
                    // If n is not on any hash chain, prev[n] is garbage but
5151
                    // its value will never be used.
5152
                } while (--n !== 0);
5153
                more += w_size;
5154
            }
5155
 
5156
            if (strm.avail_in === 0)
5157
                return;
5158
 
5159
            // If there was no sliding:
5160
            // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
5161
            // more == window_size - lookahead - strstart
5162
            // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
5163
            // => more >= window_size - 2*WSIZE + 2
5164
            // In the BIG_MEM or MMAP case (not yet supported),
5165
            // window_size == input_size + MIN_LOOKAHEAD &&
5166
            // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
5167
            // Otherwise, window_size == 2*WSIZE so more >= 2.
5168
            // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
5169
 
5170
            n = strm.read_buf(window, strstart + lookahead, more);
5171
            lookahead += n;
5172
 
5173
            // Initialize the hash value now that we have some input:
5174
            if (lookahead >= MIN_MATCH) {
5175
                ins_h = window[strstart] & 0xff;
5176
                ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
5177
            }
5178
            // If the whole input has less than MIN_MATCH bytes, ins_h is
5179
            // garbage,
5180
            // but this is not important since only literal bytes will be
5181
            // emitted.
5182
        } while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0);
5183
    }
5184
 
5185
    // Copy without compression as much as possible from the input stream,
5186
    // return
5187
    // the current block state.
5188
    // This function does not insert new strings in the dictionary since
5189
    // uncompressible data is probably not useful. This function is used
5190
    // only for the level=0 compression option.
5191
    // NOTE: this function should be optimized to avoid extra copying from
5192
    // window to pending_buf.
5193
    function deflate_stored(flush) {
5194
        // Stored blocks are limited to 0xffff bytes, pending_buf is limited
5195
        // to pending_buf_size, and each stored block has a 5 byte header:
5196
 
5197
        var max_block_size = 0xffff;
5198
        var max_start;
5199
 
5200
        if (max_block_size > pending_buf_size - 5) {
5201
            max_block_size = pending_buf_size - 5;
5202
        }
5203
 
5204
        // Copy as much as possible from input to output:
5205
        while (true) {
5206
            // Fill the window as much as possible:
5207
            if (lookahead <= 1) {
5208
                fill_window();
5209
                if (lookahead === 0 && flush == Z_NO_FLUSH)
5210
                    return NeedMore;
5211
                if (lookahead === 0)
5212
                    break; // flush the current block
5213
            }
5214
 
5215
            strstart += lookahead;
5216
            lookahead = 0;
5217
 
5218
            // Emit a stored block if pending_buf will be full:
5219
            max_start = block_start + max_block_size;
5220
            if (strstart === 0 || strstart >= max_start) {
5221
                // strstart === 0 is possible when wraparound on 16-bit machine
5222
                lookahead = (strstart - max_start);
5223
                strstart = max_start;
5224
 
5225
                flush_block_only(false);
5226
                if (strm.avail_out === 0)
5227
                    return NeedMore;
5228
 
5229
            }
5230
 
5231
            // Flush if we may have to slide, otherwise block_start may become
5232
            // negative and the data will be gone:
5233
            if (strstart - block_start >= w_size - MIN_LOOKAHEAD) {
5234
                flush_block_only(false);
5235
                if (strm.avail_out === 0)
5236
                    return NeedMore;
5237
            }
5238
        }
5239
 
5240
        flush_block_only(flush == Z_FINISH);
5241
        if (strm.avail_out === 0)
5242
            return (flush == Z_FINISH) ? FinishStarted : NeedMore;
5243
 
5244
        return flush == Z_FINISH ? FinishDone : BlockDone;
5245
    }
5246
 
5247
    function longest_match(cur_match) {
5248
        var chain_length = max_chain_length; // max hash chain length
5249
        var scan = strstart; // current string
5250
        var match; // matched string
5251
        var len; // length of current match
5252
        var best_len = prev_length; // best match length so far
5253
        var limit = strstart > (w_size - MIN_LOOKAHEAD) ? strstart - (w_size - MIN_LOOKAHEAD) : 0;
5254
        var _nice_match = nice_match;
5255
 
5256
        // Stop when cur_match becomes <= limit. To simplify the code,
5257
        // we prevent matches with the string of window index 0.
5258
 
5259
        var wmask = w_mask;
5260
 
5261
        var strend = strstart + MAX_MATCH;
5262
        var scan_end1 = window[scan + best_len - 1];
5263
        var scan_end = window[scan + best_len];
5264
 
5265
        // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of
5266
        // 16.
5267
        // It is easy to get rid of this optimization if necessary.
5268
 
5269
        // Do not waste too much time if we already have a good match:
5270
        if (prev_length >= good_match) {
5271
            chain_length >>= 2;
5272
        }
5273
 
5274
        // Do not look for matches beyond the end of the input. This is
5275
        // necessary
5276
        // to make deflate deterministic.
5277
        if (_nice_match > lookahead)
5278
            _nice_match = lookahead;
5279
 
5280
        do {
5281
            match = cur_match;
5282
 
5283
            // Skip to next match if the match length cannot increase
5284
            // or if the match length is less than 2:
5285
            if (window[match + best_len] != scan_end || window[match + best_len - 1] != scan_end1 || window[match] != window[scan]
5286
                    || window[++match] != window[scan + 1])
5287
                continue;
5288
 
5289
            // The check at best_len-1 can be removed because it will be made
5290
            // again later. (This heuristic is not always a win.)
5291
            // It is not necessary to compare scan[2] and match[2] since they
5292
            // are always equal when the other bytes match, given that
5293
            // the hash keys are equal and that HASH_BITS >= 8.
5294
            scan += 2;
5295
            match++;
5296
 
5297
            // We check for insufficient lookahead only every 8th comparison;
5298
            // the 256th check will be made at strstart+258.
5299
            do {
5300
            } while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]
5301
                    && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]
5302
                    && window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend);
5303
 
5304
            len = MAX_MATCH - (strend - scan);
5305
            scan = strend - MAX_MATCH;
5306
 
5307
            if (len > best_len) {
5308
                match_start = cur_match;
5309
                best_len = len;
5310
                if (len >= _nice_match)
5311
                    break;
5312
                scan_end1 = window[scan + best_len - 1];
5313
                scan_end = window[scan + best_len];
5314
            }
5315
 
5316
        } while ((cur_match = (prev[cur_match & wmask] & 0xffff)) > limit && --chain_length !== 0);
5317
 
5318
        if (best_len <= lookahead)
5319
            return best_len;
5320
        return lookahead;
5321
    }
5322
 
5323
    // Compress as much as possible from the input stream, return the current
5324
    // block state.
5325
    // This function does not perform lazy evaluation of matches and inserts
5326
    // new strings in the dictionary only for unmatched strings or for short
5327
    // matches. It is used only for the fast compression options.
5328
    function deflate_fast(flush) {
5329
        // short hash_head = 0; // head of the hash chain
5330
        var hash_head = 0; // head of the hash chain
5331
        var bflush; // set if current block must be flushed
5332
 
5333
        while (true) {
5334
            // Make sure that we always have enough lookahead, except
5335
            // at the end of the input file. We need MAX_MATCH bytes
5336
            // for the next match, plus MIN_MATCH bytes to insert the
5337
            // string following the next match.
5338
            if (lookahead < MIN_LOOKAHEAD) {
5339
                fill_window();
5340
                if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
5341
                    return NeedMore;
5342
                }
5343
                if (lookahead === 0)
5344
                    break; // flush the current block
5345
            }
5346
 
5347
            // Insert the string window[strstart .. strstart+2] in the
5348
            // dictionary, and set hash_head to the head of the hash chain:
5349
            if (lookahead >= MIN_MATCH) {
5350
                ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
5351
 
5352
                // prev[strstart&w_mask]=hash_head=head[ins_h];
5353
                hash_head = (head[ins_h] & 0xffff);
5354
                prev[strstart & w_mask] = head[ins_h];
5355
                head[ins_h] = strstart;
5356
            }
5357
 
5358
            // Find the longest match, discarding those <= prev_length.
5359
            // At this point we have always match_length < MIN_MATCH
5360
 
5361
            if (hash_head !== 0 && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {
5362
                // To simplify the code, we prevent matches with the string
5363
                // of window index 0 (in particular we have to avoid a match
5364
                // of the string with itself at the start of the input file).
5365
                if (strategy != Z_HUFFMAN_ONLY) {
5366
                    match_length = longest_match(hash_head);
5367
                }
5368
                // longest_match() sets match_start
5369
            }
5370
            if (match_length >= MIN_MATCH) {
5371
                // check_match(strstart, match_start, match_length);
5372
 
5373
                bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);
5374
 
5375
                lookahead -= match_length;
5376
 
5377
                // Insert new strings in the hash table only if the match length
5378
                // is not too large. This saves time but degrades compression.
5379
                if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) {
5380
                    match_length--; // string at strstart already in hash table
5381
                    do {
5382
                        strstart++;
5383
 
5384
                        ins_h = ((ins_h << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
5385
                        // prev[strstart&w_mask]=hash_head=head[ins_h];
5386
                        hash_head = (head[ins_h] & 0xffff);
5387
                        prev[strstart & w_mask] = head[ins_h];
5388
                        head[ins_h] = strstart;
5389
 
5390
                        // strstart never exceeds WSIZE-MAX_MATCH, so there are
5391
                        // always MIN_MATCH bytes ahead.
5392
                    } while (--match_length !== 0);
5393
                    strstart++;
5394
                } else {
5395
                    strstart += match_length;
5396
                    match_length = 0;
5397
                    ins_h = window[strstart] & 0xff;
5398
 
5399
                    ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
5400
                    // If lookahead < MIN_MATCH, ins_h is garbage, but it does
5401
                    // not
5402
                    // matter since it will be recomputed at next deflate call.
5403
                }
5404
            } else {
5405
                // No match, output a literal byte
5406
 
5407
                bflush = _tr_tally(0, window[strstart] & 0xff);
5408
                lookahead--;
5409
                strstart++;
5410
            }
5411
            if (bflush) {
5412
 
5413
                flush_block_only(false);
5414
                if (strm.avail_out === 0)
5415
                    return NeedMore;
5416
            }
5417
        }
5418
 
5419
        flush_block_only(flush == Z_FINISH);
5420
        if (strm.avail_out === 0) {
5421
            if (flush == Z_FINISH)
5422
                return FinishStarted;
5423
            else
5424
                return NeedMore;
5425
        }
5426
        return flush == Z_FINISH ? FinishDone : BlockDone;
5427
    }
5428
 
5429
    // Same as above, but achieves better compression. We use a lazy
5430
    // evaluation for matches: a match is finally adopted only if there is
5431
    // no better match at the next window position.
5432
    function deflate_slow(flush) {
5433
        // short hash_head = 0; // head of hash chain
5434
        var hash_head = 0; // head of hash chain
5435
        var bflush; // set if current block must be flushed
5436
        var max_insert;
5437
 
5438
        // Process the input block.
5439
        while (true) {
5440
            // Make sure that we always have enough lookahead, except
5441
            // at the end of the input file. We need MAX_MATCH bytes
5442
            // for the next match, plus MIN_MATCH bytes to insert the
5443
            // string following the next match.
5444
 
5445
            if (lookahead < MIN_LOOKAHEAD) {
5446
                fill_window();
5447
                if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
5448
                    return NeedMore;
5449
                }
5450
                if (lookahead === 0)
5451
                    break; // flush the current block
5452
            }
5453
 
5454
            // Insert the string window[strstart .. strstart+2] in the
5455
            // dictionary, and set hash_head to the head of the hash chain:
5456
 
5457
            if (lookahead >= MIN_MATCH) {
5458
                ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
5459
                // prev[strstart&w_mask]=hash_head=head[ins_h];
5460
                hash_head = (head[ins_h] & 0xffff);
5461
                prev[strstart & w_mask] = head[ins_h];
5462
                head[ins_h] = strstart;
5463
            }
5464
 
5465
            // Find the longest match, discarding those <= prev_length.
5466
            prev_length = match_length;
5467
            prev_match = match_start;
5468
            match_length = MIN_MATCH - 1;
5469
 
5470
            if (hash_head !== 0 && prev_length < max_lazy_match && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {
5471
                // To simplify the code, we prevent matches with the string
5472
                // of window index 0 (in particular we have to avoid a match
5473
                // of the string with itself at the start of the input file).
5474
 
5475
                if (strategy != Z_HUFFMAN_ONLY) {
5476
                    match_length = longest_match(hash_head);
5477
                }
5478
                // longest_match() sets match_start
5479
 
5480
                if (match_length <= 5 && (strategy == Z_FILTERED || (match_length == MIN_MATCH && strstart - match_start > 4096))) {
5481
 
5482
                    // If prev_match is also MIN_MATCH, match_start is garbage
5483
                    // but we will ignore the current match anyway.
5484
                    match_length = MIN_MATCH - 1;
5485
                }
5486
            }
5487
 
5488
            // If there was a match at the previous step and the current
5489
            // match is not better, output the previous match:
5490
            if (prev_length >= MIN_MATCH && match_length <= prev_length) {
5491
                max_insert = strstart + lookahead - MIN_MATCH;
5492
                // Do not insert strings in hash table beyond this.
5493
 
5494
                // check_match(strstart-1, prev_match, prev_length);
5495
 
5496
                bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
5497
 
5498
                // Insert in hash table all strings up to the end of the match.
5499
                // strstart-1 and strstart are already inserted. If there is not
5500
                // enough lookahead, the last two strings are not inserted in
5501
                // the hash table.
5502
                lookahead -= prev_length - 1;
5503
                prev_length -= 2;
5504
                do {
5505
                    if (++strstart <= max_insert) {
5506
                        ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
5507
                        // prev[strstart&w_mask]=hash_head=head[ins_h];
5508
                        hash_head = (head[ins_h] & 0xffff);
5509
                        prev[strstart & w_mask] = head[ins_h];
5510
                        head[ins_h] = strstart;
5511
                    }
5512
                } while (--prev_length !== 0);
5513
                match_available = 0;
5514
                match_length = MIN_MATCH - 1;
5515
                strstart++;
5516
 
5517
                if (bflush) {
5518
                    flush_block_only(false);
5519
                    if (strm.avail_out === 0)
5520
                        return NeedMore;
5521
                }
5522
            } else if (match_available !== 0) {
5523
 
5524
                // If there was no match at the previous position, output a
5525
                // single literal. If there was a match but the current match
5526
                // is longer, truncate the previous match to a single literal.
5527
 
5528
                bflush = _tr_tally(0, window[strstart - 1] & 0xff);
5529
 
5530
                if (bflush) {
5531
                    flush_block_only(false);
5532
                }
5533
                strstart++;
5534
                lookahead--;
5535
                if (strm.avail_out === 0)
5536
                    return NeedMore;
5537
            } else {
5538
                // There is no previous match to compare with, wait for
5539
                // the next step to decide.
5540
 
5541
                match_available = 1;
5542
                strstart++;
5543
                lookahead--;
5544
            }
5545
        }
5546
 
5547
        if (match_available !== 0) {
5548
            bflush = _tr_tally(0, window[strstart - 1] & 0xff);
5549
            match_available = 0;
5550
        }
5551
        flush_block_only(flush == Z_FINISH);
5552
 
5553
        if (strm.avail_out === 0) {
5554
            if (flush == Z_FINISH)
5555
                return FinishStarted;
5556
            else
5557
                return NeedMore;
5558
        }
5559
 
5560
        return flush == Z_FINISH ? FinishDone : BlockDone;
5561
    }
5562
 
5563
    function deflateReset(strm) {
5564
        strm.total_in = strm.total_out = 0;
5565
        strm.msg = null; //
5566
 
5567
        that.pending = 0;
5568
        that.pending_out = 0;
5569
 
5570
        status = BUSY_STATE;
5571
 
5572
        last_flush = Z_NO_FLUSH;
5573
 
5574
        tr_init();
5575
        lm_init();
5576
        return Z_OK;
5577
    }
5578
 
5579
    that.deflateInit = function(strm, _level, bits, _method, memLevel, _strategy) {
5580
        if (!_method)
5581
            _method = Z_DEFLATED;
5582
        if (!memLevel)
5583
            memLevel = DEF_MEM_LEVEL;
5584
        if (!_strategy)
5585
            _strategy = Z_DEFAULT_STRATEGY;
5586
 
5587
        // byte[] my_version=ZLIB_VERSION;
5588
 
5589
        //
5590
        // if (!version || version[0] != my_version[0]
5591
        // || stream_size != sizeof(z_stream)) {
5592
        // return Z_VERSION_ERROR;
5593
        // }
5594
 
5595
        strm.msg = null;
5596
 
5597
        if (_level == Z_DEFAULT_COMPRESSION)
5598
            _level = 6;
5599
 
5600
        if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0
5601
                || _strategy > Z_HUFFMAN_ONLY) {
5602
            return Z_STREAM_ERROR;
5603
        }
5604
 
5605
        strm.dstate = that;
5606
 
5607
        w_bits = bits;
5608
        w_size = 1 << w_bits;
5609
        w_mask = w_size - 1;
5610
 
5611
        hash_bits = memLevel + 7;
5612
        hash_size = 1 << hash_bits;
5613
        hash_mask = hash_size - 1;
5614
        hash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH);
5615
 
5616
        window = new Uint8Array(w_size * 2);
5617
        prev = [];
5618
        head = [];
5619
 
5620
        lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
5621
 
5622
        // We overlay pending_buf and d_buf+l_buf. This works since the average
5623
        // output size for (length,distance) codes is <= 24 bits.
5624
        that.pending_buf = new Uint8Array(lit_bufsize * 4);
5625
        pending_buf_size = lit_bufsize * 4;
5626
 
5627
        d_buf = Math.floor(lit_bufsize / 2);
5628
        l_buf = (1 + 2) * lit_bufsize;
5629
 
5630
        level = _level;
5631
 
5632
        strategy = _strategy;
5633
        method = _method & 0xff;
5634
 
5635
        return deflateReset(strm);
5636
    };
5637
 
5638
    that.deflateEnd = function() {
5639
        if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) {
5640
            return Z_STREAM_ERROR;
5641
        }
5642
        // Deallocate in reverse order of allocations:
5643
        that.pending_buf = null;
5644
        head = null;
5645
        prev = null;
5646
        window = null;
5647
        // free
5648
        that.dstate = null;
5649
        return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
5650
    };
5651
 
5652
    that.deflateParams = function(strm, _level, _strategy) {
5653
        var err = Z_OK;
5654
 
5655
        if (_level == Z_DEFAULT_COMPRESSION) {
5656
            _level = 6;
5657
        }
5658
        if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
5659
            return Z_STREAM_ERROR;
5660
        }
5661
 
5662
        if (config_table[level].func != config_table[_level].func && strm.total_in !== 0) {
5663
            // Flush the last buffer:
5664
            err = strm.deflate(Z_PARTIAL_FLUSH);
5665
        }
5666
 
5667
        if (level != _level) {
5668
            level = _level;
5669
            max_lazy_match = config_table[level].max_lazy;
5670
            good_match = config_table[level].good_length;
5671
            nice_match = config_table[level].nice_length;
5672
            max_chain_length = config_table[level].max_chain;
5673
        }
5674
        strategy = _strategy;
5675
        return err;
5676
    };
5677
 
5678
    that.deflateSetDictionary = function(strm, dictionary, dictLength) {
5679
        var length = dictLength;
5680
        var n, index = 0;
5681
 
5682
        if (!dictionary || status != INIT_STATE)
5683
            return Z_STREAM_ERROR;
5684
 
5685
        if (length < MIN_MATCH)
5686
            return Z_OK;
5687
        if (length > w_size - MIN_LOOKAHEAD) {
5688
            length = w_size - MIN_LOOKAHEAD;
5689
            index = dictLength - length; // use the tail of the dictionary
5690
        }
5691
        window.set(dictionary.subarray(index, index + length), 0);
5692
 
5693
        strstart = length;
5694
        block_start = length;
5695
 
5696
        // Insert all strings in the hash table (except for the last two bytes).
5697
        // s->lookahead stays null, so s->ins_h will be recomputed at the next
5698
        // call of fill_window.
5699
 
5700
        ins_h = window[0] & 0xff;
5701
        ins_h = (((ins_h) << hash_shift) ^ (window[1] & 0xff)) & hash_mask;
5702
 
5703
        for (n = 0; n <= length - MIN_MATCH; n++) {
5704
            ins_h = (((ins_h) << hash_shift) ^ (window[(n) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
5705
            prev[n & w_mask] = head[ins_h];
5706
            head[ins_h] = n;
5707
        }
5708
        return Z_OK;
5709
    };
5710
 
5711
    that.deflate = function(_strm, flush) {
5712
        var i, header, level_flags, old_flush, bstate;
5713
 
5714
        if (flush > Z_FINISH || flush < 0) {
5715
            return Z_STREAM_ERROR;
5716
        }
5717
 
5718
        if (!_strm.next_out || (!_strm.next_in && _strm.avail_in !== 0) || (status == FINISH_STATE && flush != Z_FINISH)) {
5719
            _strm.msg = z_errmsg[Z_NEED_DICT - (Z_STREAM_ERROR)];
5720
            return Z_STREAM_ERROR;
5721
        }
5722
        if (_strm.avail_out === 0) {
5723
            _strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
5724
            return Z_BUF_ERROR;
5725
        }
5726
 
5727
        strm = _strm; // just in case
5728
        old_flush = last_flush;
5729
        last_flush = flush;
5730
 
5731
        // Write the zlib header
5732
        if (status == INIT_STATE) {
5733
            header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8;
5734
            level_flags = ((level - 1) & 0xff) >> 1;
5735
 
5736
            if (level_flags > 3)
5737
                level_flags = 3;
5738
            header |= (level_flags << 6);
5739
            if (strstart !== 0)
5740
                header |= PRESET_DICT;
5741
            header += 31 - (header % 31);
5742
 
5743
            status = BUSY_STATE;
5744
            putShortMSB(header);
5745
        }
5746
 
5747
        // Flush as much pending output as possible
5748
        if (that.pending !== 0) {
5749
            strm.flush_pending();
5750
            if (strm.avail_out === 0) {
5751
                // console.log(" avail_out==0");
5752
                // Since avail_out is 0, deflate will be called again with
5753
                // more output space, but possibly with both pending and
5754
                // avail_in equal to zero. There won't be anything to do,
5755
                // but this is not an error situation so make sure we
5756
                // return OK instead of BUF_ERROR at next call of deflate:
5757
                last_flush = -1;
5758
                return Z_OK;
5759
            }
5760
 
5761
            // Make sure there is something to do and avoid duplicate
5762
            // consecutive
5763
            // flushes. For repeated and useless calls with Z_FINISH, we keep
5764
            // returning Z_STREAM_END instead of Z_BUFF_ERROR.
5765
        } else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) {
5766
            strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
5767
            return Z_BUF_ERROR;
5768
        }
5769
 
5770
        // User must not provide more input after the first FINISH:
5771
        if (status == FINISH_STATE && strm.avail_in !== 0) {
5772
            _strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
5773
            return Z_BUF_ERROR;
5774
        }
5775
 
5776
        // Start a new block or continue the current one.
5777
        if (strm.avail_in !== 0 || lookahead !== 0 || (flush != Z_NO_FLUSH && status != FINISH_STATE)) {
5778
            bstate = -1;
5779
            switch (config_table[level].func) {
5780
            case STORED:
5781
                bstate = deflate_stored(flush);
5782
                break;
5783
            case FAST:
5784
                bstate = deflate_fast(flush);
5785
                break;
5786
            case SLOW:
5787
                bstate = deflate_slow(flush);
5788
                break;
5789
            default:
5790
            }
5791
 
5792
            if (bstate == FinishStarted || bstate == FinishDone) {
5793
                status = FINISH_STATE;
5794
            }
5795
            if (bstate == NeedMore || bstate == FinishStarted) {
5796
                if (strm.avail_out === 0) {
5797
                    last_flush = -1; // avoid BUF_ERROR next call, see above
5798
                }
5799
                return Z_OK;
5800
                // If flush != Z_NO_FLUSH && avail_out === 0, the next call
5801
                // of deflate should use the same flush parameter to make sure
5802
                // that the flush is complete. So we don't have to output an
5803
                // empty block here, this will be done at next call. This also
5804
                // ensures that for a very small output buffer, we emit at most
5805
                // one empty block.
5806
            }
5807
 
5808
            if (bstate == BlockDone) {
5809
                if (flush == Z_PARTIAL_FLUSH) {
5810
                    _tr_align();
5811
                } else { // FULL_FLUSH or SYNC_FLUSH
5812
                    _tr_stored_block(0, 0, false);
5813
                    // For a full flush, this empty block will be recognized
5814
                    // as a special marker by inflate_sync().
5815
                    if (flush == Z_FULL_FLUSH) {
5816
                        // state.head[s.hash_size-1]=0;
5817
                        for (i = 0; i < hash_size/*-1*/; i++)
5818
                            // forget history
5819
                            head[i] = 0;
5820
                    }
5821
                }
5822
                strm.flush_pending();
5823
                if (strm.avail_out === 0) {
5824
                    last_flush = -1; // avoid BUF_ERROR at next call, see above
5825
                    return Z_OK;
5826
                }
5827
            }
5828
        }
5829
 
5830
        if (flush != Z_FINISH)
5831
            return Z_OK;
5832
        return Z_STREAM_END;
5833
    };
5834
}
5835
 
5836
// ZStream
5837
 
5838
function ZStream() {
5839
    var that = this;
5840
    that.next_in_index = 0;
5841
    that.next_out_index = 0;
5842
    // that.next_in; // next input byte
5843
    that.avail_in = 0; // number of bytes available at next_in
5844
    that.total_in = 0; // total nb of input bytes read so far
5845
    // that.next_out; // next output byte should be put there
5846
    that.avail_out = 0; // remaining free space at next_out
5847
    that.total_out = 0; // total nb of bytes output so far
5848
    // that.msg;
5849
    // that.dstate;
5850
}
5851
 
5852
ZStream.prototype = {
5853
    deflateInit : function(level, bits) {
5854
        var that = this;
5855
        that.dstate = new Deflate();
5856
        if (!bits)
5857
            bits = MAX_BITS;
5858
        return that.dstate.deflateInit(that, level, bits);
5859
    },
5860
 
5861
    deflate : function(flush) {
5862
        var that = this;
5863
        if (!that.dstate) {
5864
            return Z_STREAM_ERROR;
5865
        }
5866
        return that.dstate.deflate(that, flush);
5867
    },
5868
 
5869
    deflateEnd : function() {
5870
        var that = this;
5871
        if (!that.dstate)
5872
            return Z_STREAM_ERROR;
5873
        var ret = that.dstate.deflateEnd();
5874
        that.dstate = null;
5875
        return ret;
5876
    },
5877
 
5878
    deflateParams : function(level, strategy) {
5879
        var that = this;
5880
        if (!that.dstate)
5881
            return Z_STREAM_ERROR;
5882
        return that.dstate.deflateParams(that, level, strategy);
5883
    },
5884
 
5885
    deflateSetDictionary : function(dictionary, dictLength) {
5886
        var that = this;
5887
        if (!that.dstate)
5888
            return Z_STREAM_ERROR;
5889
        return that.dstate.deflateSetDictionary(that, dictionary, dictLength);
5890
    },
5891
 
5892
    // Read a new buffer from the current input stream, update the
5893
    // total number of bytes read. All deflate() input goes through
5894
    // this function so some applications may wish to modify it to avoid
5895
    // allocating a large strm->next_in buffer and copying from it.
5896
    // (See also flush_pending()).
5897
    read_buf : function(buf, start, size) {
5898
        var that = this;
5899
        var len = that.avail_in;
5900
        if (len > size)
5901
            len = size;
5902
        if (len === 0)
5903
            return 0;
5904
        that.avail_in -= len;
5905
        buf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start);
5906
        that.next_in_index += len;
5907
        that.total_in += len;
5908
        return len;
5909
    },
5910
 
5911
    // Flush as much pending output as possible. All deflate() output goes
5912
    // through this function so some applications may wish to modify it
5913
    // to avoid allocating a large strm->next_out buffer and copying into it.
5914
    // (See also read_buf()).
5915
    flush_pending : function() {
5916
        var that = this;
5917
        var len = that.dstate.pending;
5918
 
5919
        if (len > that.avail_out)
5920
            len = that.avail_out;
5921
        if (len === 0)
5922
            return;
5923
 
5924
        // if (that.dstate.pending_buf.length <= that.dstate.pending_out || that.next_out.length <= that.next_out_index
5925
        // || that.dstate.pending_buf.length < (that.dstate.pending_out + len) || that.next_out.length < (that.next_out_index +
5926
        // len)) {
5927
        // console.log(that.dstate.pending_buf.length + ", " + that.dstate.pending_out + ", " + that.next_out.length + ", " +
5928
        // that.next_out_index + ", " + len);
5929
        // console.log("avail_out=" + that.avail_out);
5930
        // }
5931
 
5932
        that.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index);
5933
 
5934
        that.next_out_index += len;
5935
        that.dstate.pending_out += len;
5936
        that.total_out += len;
5937
        that.avail_out -= len;
5938
        that.dstate.pending -= len;
5939
        if (that.dstate.pending === 0) {
5940
            that.dstate.pending_out = 0;
5941
        }
5942
    }
5943
};
5944
 
5945
// Deflater
5946
 
5947
function Deflater(level) {
5948
    var that = this;
5949
    var z = new ZStream();
5950
    var bufsize = 512;
5951
    var flush = Z_NO_FLUSH;
5952
    var buf = new Uint8Array(bufsize);
5953
 
5954
    if (typeof level == "undefined")
5955
        level = Z_DEFAULT_COMPRESSION;
5956
    z.deflateInit(level);
5957
    z.next_out = buf;
5958
 
5959
    that.append = function(data, onprogress) {
5960
        var err, buffers = [], lastIndex = 0, bufferIndex = 0, bufferSize = 0, array;
5961
        if (!data.length)
5962
            return;
5963
        z.next_in_index = 0;
5964
        z.next_in = data;
5965
        z.avail_in = data.length;
5966
        do {
5967
            z.next_out_index = 0;
5968
            z.avail_out = bufsize;
5969
            err = z.deflate(flush);
5970
            if (err != Z_OK)
5971
                throw "deflating: " + z.msg;
5972
            if (z.next_out_index)
5973
                if (z.next_out_index == bufsize)
5974
                    buffers.push(new Uint8Array(buf));
5975
                else
5976
                    buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
5977
            bufferSize += z.next_out_index;
5978
            if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
5979
                onprogress(z.next_in_index);
5980
                lastIndex = z.next_in_index;
5981
            }
5982
        } while (z.avail_in > 0 || z.avail_out === 0);
5983
        array = new Uint8Array(bufferSize);
5984
        buffers.forEach(function(chunk) {
5985
            array.set(chunk, bufferIndex);
5986
            bufferIndex += chunk.length;
5987
        });
5988
        return array;
5989
    };
5990
    that.flush = function() {
5991
        var err, buffers = [], bufferIndex = 0, bufferSize = 0, array;
5992
        do {
5993
            z.next_out_index = 0;
5994
            z.avail_out = bufsize;
5995
            err = z.deflate(Z_FINISH);
5996
            if (err != Z_STREAM_END && err != Z_OK)
5997
                throw "deflating: " + z.msg;
5998
            if (bufsize - z.avail_out > 0)
5999
                buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
6000
            bufferSize += z.next_out_index;
6001
        } while (z.avail_in > 0 || z.avail_out === 0);
6002
        z.deflateEnd();
6003
        array = new Uint8Array(bufferSize);
6004
        buffers.forEach(function(chunk) {
6005
            array.set(chunk, bufferIndex);
6006
            bufferIndex += chunk.length;
6007
        });
6008
        return array;
6009
    };
6010
}/*
6011
 * Copyright (c) 2012 chick307 <chick307@gmail.com>
6012
 *
6013
 * Licensed under the MIT License.
6014
 * http://opensource.org/licenses/mit-license
6015
 */
6016
 
6017
void function(global, callback) {
6018
	if (typeof module === 'object') {
6019
		module.exports = callback();
6020
	} else if (typeof define === 'function') {
6021
		define(callback);
6022
	} else {
6023
		global.adler32cs = callback();
6024
	}
6025
}(this, function() {
6026
	var _hasArrayBuffer = typeof ArrayBuffer === 'function' &&
6027
		typeof Uint8Array === 'function';
6028
 
6029
	var _Buffer = null, _isBuffer = (function() {
6030
		if (!_hasArrayBuffer)
6031
			return function _isBuffer() { return false };
6032
 
6033
		try {
6034
			var buffer = require('buffer');
6035
			if (typeof buffer.Buffer === 'function')
6036
				_Buffer = buffer.Buffer;
6037
		} catch (error) {}
6038
 
6039
		return function _isBuffer(value) {
6040
			return value instanceof ArrayBuffer ||
6041
				_Buffer !== null && value instanceof _Buffer;
6042
		};
6043
	}());
6044
 
6045
	var _utf8ToBinary = (function() {
6046
		if (_Buffer !== null) {
6047
			return function _utf8ToBinary(utf8String) {
6048
				return new _Buffer(utf8String, 'utf8').toString('binary');
6049
			};
6050
		} else {
6051
			return function _utf8ToBinary(utf8String) {
6052
				return unescape(encodeURIComponent(utf8String));
6053
			};
6054
		}
6055
	}());
6056
 
6057
	var MOD = 65521;
6058
 
6059
	var _update = function _update(checksum, binaryString) {
6060
		var a = checksum & 0xFFFF, b = checksum >>> 16;
6061
		for (var i = 0, length = binaryString.length; i < length; i++) {
6062
			a = (a + (binaryString.charCodeAt(i) & 0xFF)) % MOD;
6063
			b = (b + a) % MOD;
6064
		}
6065
		return (b << 16 | a) >>> 0;
6066
	};
6067
 
6068
	var _updateUint8Array = function _updateUint8Array(checksum, uint8Array) {
6069
		var a = checksum & 0xFFFF, b = checksum >>> 16;
6070
		for (var i = 0, length = uint8Array.length, x; i < length; i++) {
6071
			a = (a + uint8Array[i]) % MOD;
6072
			b = (b + a) % MOD;
6073
		}
6074
		return (b << 16 | a) >>> 0
6075
	};
6076
 
6077
	var exports = {};
6078
 
6079
	var Adler32 = exports.Adler32 = (function() {
6080
		var ctor = function Adler32(checksum) {
6081
			if (!(this instanceof ctor)) {
6082
				throw new TypeError(
6083
					'Constructor cannot called be as a function.');
6084
			}
6085
			if (!isFinite(checksum = checksum == null ? 1 : +checksum)) {
6086
				throw new Error(
6087
					'First arguments needs to be a finite number.');
6088
			}
6089
			this.checksum = checksum >>> 0;
6090
		};
6091
 
6092
		var proto = ctor.prototype = {};
6093
		proto.constructor = ctor;
6094
 
6095
		ctor.from = function(from) {
6096
			from.prototype = proto;
6097
			return from;
6098
		}(function from(binaryString) {
6099
			if (!(this instanceof ctor)) {
6100
				throw new TypeError(
6101
					'Constructor cannot called be as a function.');
6102
			}
6103
			if (binaryString == null)
6104
				throw new Error('First argument needs to be a string.');
6105
			this.checksum = _update(1, binaryString.toString());
6106
		});
6107
 
6108
		ctor.fromUtf8 = function(fromUtf8) {
6109
			fromUtf8.prototype = proto;
6110
			return fromUtf8;
6111
		}(function fromUtf8(utf8String) {
6112
			if (!(this instanceof ctor)) {
6113
				throw new TypeError(
6114
					'Constructor cannot called be as a function.');
6115
			}
6116
			if (utf8String == null)
6117
				throw new Error('First argument needs to be a string.');
6118
			var binaryString = _utf8ToBinary(utf8String.toString());
6119
			this.checksum = _update(1, binaryString);
6120
		});
6121
 
6122
		if (_hasArrayBuffer) {
6123
			ctor.fromBuffer = function(fromBuffer) {
6124
				fromBuffer.prototype = proto;
6125
				return fromBuffer;
6126
			}(function fromBuffer(buffer) {
6127
				if (!(this instanceof ctor)) {
6128
					throw new TypeError(
6129
						'Constructor cannot called be as a function.');
6130
				}
6131
				if (!_isBuffer(buffer))
6132
					throw new Error('First argument needs to be ArrayBuffer.');
6133
				var array = new Uint8Array(buffer);
6134
				return this.checksum = _updateUint8Array(1, array);
6135
			});
6136
		}
6137
 
6138
		proto.update = function update(binaryString) {
6139
			if (binaryString == null)
6140
				throw new Error('First argument needs to be a string.');
6141
			binaryString = binaryString.toString();
6142
			return this.checksum = _update(this.checksum, binaryString);
6143
		};
6144
 
6145
		proto.updateUtf8 = function updateUtf8(utf8String) {
6146
			if (utf8String == null)
6147
				throw new Error('First argument needs to be a string.');
6148
			var binaryString = _utf8ToBinary(utf8String.toString());
6149
			return this.checksum = _update(this.checksum, binaryString);
6150
		};
6151
 
6152
		if (_hasArrayBuffer) {
6153
			proto.updateBuffer = function updateBuffer(buffer) {
6154
				if (!_isBuffer(buffer))
6155
					throw new Error('First argument needs to be ArrayBuffer.');
6156
				var array = new Uint8Array(buffer);
6157
				return this.checksum = _updateUint8Array(this.checksum, array);
6158
			};
6159
		}
6160
 
6161
		proto.clone = function clone() {
6162
			return new Adler32(this.checksum);
6163
		};
6164
 
6165
		return ctor;
6166
	}());
6167
 
6168
	exports.from = function from(binaryString) {
6169
		if (binaryString == null)
6170
			throw new Error('First argument needs to be a string.');
6171
		return _update(1, binaryString.toString());
6172
	};
6173
 
6174
	exports.fromUtf8 = function fromUtf8(utf8String) {
6175
		if (utf8String == null)
6176
			throw new Error('First argument needs to be a string.');
6177
		var binaryString = _utf8ToBinary(utf8String.toString());
6178
		return _update(1, binaryString);
6179
	};
6180
 
6181
	if (_hasArrayBuffer) {
6182
		exports.fromBuffer = function fromBuffer(buffer) {
6183
			if (!_isBuffer(buffer))
6184
				throw new Error('First argument need to be ArrayBuffer.');
6185
			var array = new Uint8Array(buffer);
6186
			return _updateUint8Array(1, array);
6187
		};
6188
	}
6189
 
6190
	return exports;
6191
});