PageSourceSearch

https://kunde.moretrafo.no/assets/pdf.js

js moretrafo.no collected 2026-10-07 23:17:20 UTC 437,915 bytes, 11,653 lines download raw bytes

1/* Copyright 2012 Mozilla Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/* jshint globalstrict: false */
16/* umdutils ignore */
17
18(function (root, factory) {
19  'use strict';
20  if (typeof define === 'function' && define.amd) {
21    define('pdfjs-dist/build/pdf', ['exports'], factory);
22  } else if (typeof exports !== 'undefined') {
23    factory(exports);
24  } else {
25    factory((root.pdfjsDistBuildPdf = {}));
26  }
27})(this, function (exports) {
28  // Use strict in our context only - users might not want it
29  'use strict';
30
31  var pdfjsVersion = '1.6.210';
32  var pdfjsBuild = '4ce2356';
33
34  var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : null;
35
36  var pdfjsLibs = {};
37
38  (function pdfjsWrapper() {
39    (function (root, factory) {
40      {
41        factory((root.pdfjsSharedUtil = {}));
42      }
43    })(this, function (exports) {
44      var globalScope =
45        typeof window !== 'undefined'
46          ? window
47          : typeof global !== 'undefined'
48            ? global
49            : typeof self !== 'undefined'
50              ? self
51              : this;
52
53      var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
54
55      var TextRenderingMode = {
56        FILL: 0,
57        STROKE: 1,
58        FILL_STROKE: 2,
59        INVISIBLE: 3,
60        FILL_ADD_TO_PATH: 4,
61        STROKE_ADD_TO_PATH: 5,
62        FILL_STROKE_ADD_TO_PATH: 6,
63        ADD_TO_PATH: 7,
64        FILL_STROKE_MASK: 3,
65        ADD_TO_PATH_FLAG: 4,
66      };
67
68      var ImageKind = {
69        GRAYSCALE_1BPP: 1,
70        RGB_24BPP: 2,
71        RGBA_32BPP: 3,
72      };
73
74      var AnnotationType = {
75        TEXT: 1,
76        LINK: 2,
77        FREETEXT: 3,
78        LINE: 4,
79        SQUARE: 5,
80        CIRCLE: 6,
81        POLYGON: 7,
82        POLYLINE: 8,
83        HIGHLIGHT: 9,
84        UNDERLINE: 10,
85        SQUIGGLY: 11,
86        STRIKEOUT: 12,
87        STAMP: 13,
88        CARET: 14,
89        INK: 15,
90        POPUP: 16,
91        FILEATTACHMENT: 17,
92        SOUND: 18,
93        MOVIE: 19,
94        WIDGET: 20,
95        SCREEN: 21,
96        PRINTERMARK: 22,
97        TRAPNET: 23,
98        WATERMARK: 24,
99        THREED: 25,
100        REDACT: 26,
101      };
102
103      var AnnotationFlag = {
104        INVISIBLE: 0x01,
105        HIDDEN: 0x02,
106        PRINT: 0x04,
107        NOZOOM: 0x08,
108        NOROTATE: 0x10,
109        NOVIEW: 0x20,
110        READONLY: 0x40,
111        LOCKED: 0x80,
112        TOGGLENOVIEW: 0x100,
113        LOCKEDCONTENTS: 0x200,
114      };
115
116      var AnnotationFieldFlag = {
117        READONLY: 0x0000001,
118        REQUIRED: 0x0000002,
119        NOEXPORT: 0x0000004,
120        MULTILINE: 0x0001000,
121        PASSWORD: 0x0002000,
122        NOTOGGLETOOFF: 0x0004000,
123        RADIO: 0x0008000,
124        PUSHBUTTON: 0x0010000,
125        COMBO: 0x0020000,
126        EDIT: 0x0040000,
127        SORT: 0x0080000,
128        FILESELECT: 0x0100000,
129        MULTISELECT: 0x0200000,
130        DONOTSPELLCHECK: 0x0400000,
131        DONOTSCROLL: 0x0800000,
132        COMB: 0x1000000,
133        RICHTEXT: 0x2000000,
134        RADIOSINUNISON: 0x2000000,
135        COMMITONSELCHANGE: 0x4000000,
136      };
137
138      var AnnotationBorderStyleType = {
139        SOLID: 1,
140        DASHED: 2,
141        BEVELED: 3,
142        INSET: 4,
143        UNDERLINE: 5,
144      };
145
146      var StreamType = {
147        UNKNOWN: 0,
148        FLATE: 1,
149        LZW: 2,
150        DCT: 3,
151        JPX: 4,
152        JBIG: 5,
153        A85: 6,
154        AHX: 7,
155        CCF: 8,
156        RL: 9,
157      };
158
159      var FontType = {
160        UNKNOWN: 0,
161        TYPE1: 1,
162        TYPE1C: 2,
163        CIDFONTTYPE0: 3,
164        CIDFONTTYPE0C: 4,
165        TRUETYPE: 5,
166        CIDFONTTYPE2: 6,
167        TYPE3: 7,
168        OPENTYPE: 8,
169        TYPE0: 9,
170        MMTYPE1: 10,
171      };
172
173      var VERBOSITY_LEVELS = {
174        errors: 0,
175        warnings: 1,
176        infos: 5,
177      };
178
179      // All the possible operations for an operator list.
180      var OPS = {
181        // Intentionally start from 1 so it is easy to spot bad operators that will be
182        // 0's.
183        dependency: 1,
184        setLineWidth: 2,
185        setLineCap: 3,
186        setLineJoin: 4,
187        setMiterLimit: 5,
188        setDash: 6,
189        setRenderingIntent: 7,
190        setFlatness: 8,
191        setGState: 9,
192        save: 10,
193        restore: 11,
194        transform: 12,
195        moveTo: 13,
196        lineTo: 14,
197        curveTo: 15,
198        curveTo2: 16,
199        curveTo3: 17,
200        closePath: 18,
201        rectangle: 19,
202        stroke: 20,
203        closeStroke: 21,
204        fill: 22,
205        eoFill: 23,
206        fillStroke: 24,
207        eoFillStroke: 25,
208        closeFillStroke: 26,
209        closeEOFillStroke: 27,
210        endPath: 28,
211        clip: 29,
212        eoClip: 30,
213        beginText: 31,
214        endText: 32,
215        setCharSpacing: 33,
216        setWordSpacing: 34,
217        setHScale: 35,
218        setLeading: 36,
219        setFont: 37,
220        setTextRenderingMode: 38,
221        setTextRise: 39,
222        moveText: 40,
223        setLeadingMoveText: 41,
224        setTextMatrix: 42,
225        nextLine: 43,
226        showText: 44,
227        showSpacedText: 45,
228        nextLineShowText: 46,
229        nextLineSetSpacingShowText: 47,
230        setCharWidth: 48,
231        setCharWidthAndBounds: 49,
232        setStrokeColorSpace: 50,
233        setFillColorSpace: 51,
234        setStrokeColor: 52,
235        setStrokeColorN: 53,
236        setFillColor: 54,
237        setFillColorN: 55,
238        setStrokeGray: 56,
239        setFillGray: 57,
240        setStrokeRGBColor: 58,
241        setFillRGBColor: 59,
242        setStrokeCMYKColor: 60,
243        setFillCMYKColor: 61,
244        shadingFill: 62,
245        beginInlineImage: 63,
246        beginImageData: 64,
247        endInlineImage: 65,
248        paintXObject: 66,
249        markPoint: 67,
250        markPointProps: 68,
251        beginMarkedContent: 69,
252        beginMarkedContentProps: 70,
253        endMarkedContent: 71,
254        beginCompat: 72,
255        endCompat: 73,
256        paintFormXObjectBegin: 74,
257        paintFormXObjectEnd: 75,
258        beginGroup: 76,
259        endGroup: 77,
260        beginAnnotations: 78,
261        endAnnotations: 79,
262        beginAnnotation: 80,
263        endAnnotation: 81,
264        paintJpegXObject: 82,
265        paintImageMaskXObject: 83,
266        paintImageMaskXObjectGroup: 84,
267        paintImageXObject: 85,
268        paintInlineImageXObject: 86,
269        paintInlineImageXObjectGroup: 87,
270        paintImageXObjectRepeat: 88,
271        paintImageMaskXObjectRepeat: 89,
272        paintSolidColorImageMask: 90,
273        constructPath: 91,
274      };
275
276      var verbosity = VERBOSITY_LEVELS.warnings;
277
278      function setVerbosityLevel(level) {
279        verbosity = level;
280      }
281
282      function getVerbosityLevel() {
283        return verbosity;
284      }
285
286      // A notice for devs. These are good for things that are helpful to devs, such
287      // as warning that Workers were disabled, which is important to devs but not
288      // end users.
289      function info(msg) {
290        if (verbosity >= VERBOSITY_LEVELS.infos) {
291          console.log('Info: ' + msg);
292        }
293      }
294
295      // Non-fatal warnings.
296      function warn(msg) {
297        if (verbosity >= VERBOSITY_LEVELS.warnings) {
298          console.log('Warning: ' + msg);
299        }
300      }
301
302      // Deprecated API function -- display regardless of the PDFJS.verbosity setting.
303      function deprecated(details) {
304        console.log('Deprecated API usage: ' + details);
305      }
306
307      // Fatal errors that should trigger the fallback UI and halt execution by
308      // throwing an exception.
309      function error(msg) {
310        if (verbosity >= VERBOSITY_LEVELS.errors) {
311          console.log('Error: ' + msg);
312          console.log(backtrace());
313        }
314        throw new Error(msg);
315      }
316
317      function backtrace() {
318        try {
319          throw new Error();
320        } catch (e) {
321          return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
322        }
323      }
324
325      function assert(cond, msg) {
326        if (!cond) {
327          error(msg);
328        }
329      }
330
331      var UNSUPPORTED_FEATURES = {
332        unknown: 'unknown',
333        forms: 'forms',
334        javaScript: 'javaScript',
335        smask: 'smask',
336        shadingPattern: 'shadingPattern',
337        font: 'font',
338      };
339
340      // Checks if URLs have the same origin. For non-HTTP based URLs, returns false.
341      function isSameOrigin(baseUrl, otherUrl) {
342        try {
343          var base = new URL(baseUrl);
344          if (!base.origin || base.origin === 'null') {
345            return false; // non-HTTP url
346          }
347        } catch (e) {
348          return false;
349        }
350
351        var other = new URL(otherUrl, base);
352        return base.origin === other.origin;
353      }
354
355      // Validates if URL is safe and allowed, e.g. to avoid XSS.
356      function isValidUrl(url, allowRelative) {
357        if (!url || typeof url !== 'string') {
358          return false;
359        }
360        // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1)
361        // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
362        var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url);
363        if (!protocol) {
364          return allowRelative;
365        }
366        protocol = protocol[0].toLowerCase();
367        switch (protocol) {
368          case 'http':
369          case 'https':
370          case 'ftp':
371          case 'mailto':
372          case 'tel':
373            return true;
374          default:
375            return false;
376        }
377      }
378
379      function shadow(obj, prop, value) {
380        Object.defineProperty(obj, prop, {
381          value: value,
382          enumerable: true,
383          configurable: true,
384          writable: false,
385        });
386        return value;
387      }
388
389      function getLookupTableFactory(initializer) {
390        var lookup;
391        return function () {
392          if (initializer) {
393            lookup = Object.create(null);
394            initializer(lookup);
395            initializer = null;
396          }
397          return lookup;
398        };
399      }
400
401      var PasswordResponses = {
402        NEED_PASSWORD: 1,
403        INCORRECT_PASSWORD: 2,
404      };
405
406      var PasswordException = (function PasswordExceptionClosure() {
407        function PasswordException(msg, code) {
408          this.name = 'PasswordException';
409          this.message = msg;
410          this.code = code;
411        }
412
413        PasswordException.prototype = new Error();
414        PasswordException.constructor = PasswordException;
415
416        return PasswordException;
417      })();
418
419      var UnknownErrorException = (function UnknownErrorExceptionClosure() {
420        function UnknownErrorException(msg, details) {
421          this.name = 'UnknownErrorException';
422          this.message = msg;
423          this.details = details;
424        }
425
426        UnknownErrorException.prototype = new Error();
427        UnknownErrorException.constructor = UnknownErrorException;
428
429        return UnknownErrorException;
430      })();
431
432      var InvalidPDFException = (function InvalidPDFExceptionClosure() {
433        function InvalidPDFException(msg) {
434          this.name = 'InvalidPDFException';
435          this.message = msg;
436        }
437
438        InvalidPDFException.prototype = new Error();
439        InvalidPDFException.constructor = InvalidPDFException;
440
441        return InvalidPDFException;
442      })();
443
444      var MissingPDFException = (function MissingPDFExceptionClosure() {
445        function MissingPDFException(msg) {
446          this.name = 'MissingPDFException';
447          this.message = msg;
448        }
449
450        MissingPDFException.prototype = new Error();
451        MissingPDFException.constructor = MissingPDFException;
452
453        return MissingPDFException;
454      })();
455
456      var UnexpectedResponseException = (function UnexpectedResponseExceptionClosure() {
457        function UnexpectedResponseException(msg, status) {
458          this.name = 'UnexpectedResponseException';
459          this.message = msg;
460          this.status = status;
461        }
462
463        UnexpectedResponseException.prototype = new Error();
464        UnexpectedResponseException.constructor = UnexpectedResponseException;
465
466        return UnexpectedResponseException;
467      })();
468
469      var NotImplementedException = (function NotImplementedExceptionClosure() {
470        function NotImplementedException(msg) {
471          this.message = msg;
472        }
473
474        NotImplementedException.prototype = new Error();
475        NotImplementedException.prototype.name = 'NotImplementedException';
476        NotImplementedException.constructor = NotImplementedException;
477
478        return NotImplementedException;
479      })();
480
481      var MissingDataException = (function MissingDataExceptionClosure() {
482        function MissingDataException(begin, end) {
483          this.begin = begin;
484          this.end = end;
485          this.message = 'Missing data [' + begin + ', ' + end + ')';
486        }
487
488        MissingDataException.prototype = new Error();
489        MissingDataException.prototype.name = 'MissingDataException';
490        MissingDataException.constructor = MissingDataException;
491
492        return MissingDataException;
493      })();
494
495      var XRefParseException = (function XRefParseExceptionClosure() {
496        function XRefParseException(msg) {
497          this.message = msg;
498        }
499
500        XRefParseException.prototype = new Error();
501        XRefParseException.prototype.name = 'XRefParseException';
502        XRefParseException.constructor = XRefParseException;
503
504        return XRefParseException;
505      })();
506
507      var NullCharactersRegExp = /\x00/g;
508
509      function removeNullCharacters(str) {
510        if (typeof str !== 'string') {
511          warn('The argument for removeNullCharacters must be a string.');
512          return str;
513        }
514        return str.replace(NullCharactersRegExp, '');
515      }
516
517      function bytesToString(bytes) {
518        assert(
519          bytes !== null && typeof bytes === 'object' && bytes.length !== undefined,
520          'Invalid argument for bytesToString'
521        );
522        var length = bytes.length;
523        var MAX_ARGUMENT_COUNT = 8192;
524        if (length < MAX_ARGUMENT_COUNT) {
525          return String.fromCharCode.apply(null, bytes);
526        }
527        var strBuf = [];
528        for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
529          var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
530          var chunk = bytes.subarray(i, chunkEnd);
531          strBuf.push(String.fromCharCode.apply(null, chunk));
532        }
533        return strBuf.join('');
534      }
535
536      function stringToBytes(str) {
537        assert(typeof str === 'string', 'Invalid argument for stringToBytes');
538        var length = str.length;
539        var bytes = new Uint8Array(length);
540        for (var i = 0; i < length; ++i) {
541          bytes[i] = str.charCodeAt(i) & 0xff;
542        }
543        return bytes;
544      }
545
546      /**
547       * Gets length of the array (Array, Uint8Array, or string) in bytes.
548       * @param {Array|Uint8Array|string} arr
549       * @returns {number}
550       */
551      function arrayByteLength(arr) {
552        if (arr.length !== undefined) {
553          return arr.length;
554        }
555        assert(arr.byteLength !== undefined);
556        return arr.byteLength;
557      }
558
559      /**
560       * Combines array items (arrays) into single Uint8Array object.
561       * @param {Array} arr - the array of the arrays (Array, Uint8Array, or string).
562       * @returns {Uint8Array}
563       */
564      function arraysToBytes(arr) {
565        // Shortcut: if first and only item is Uint8Array, return it.
566        if (arr.length === 1 && arr[0] instanceof Uint8Array) {
567          return arr[0];
568        }
569        var resultLength = 0;
570        var i,
571          ii = arr.length;
572        var item, itemLength;
573        for (i = 0; i < ii; i++) {
574          item = arr[i];
575          itemLength = arrayByteLength(item);
576          resultLength += itemLength;
577        }
578        var pos = 0;
579        var data = new Uint8Array(resultLength);
580        for (i = 0; i < ii; i++) {
581          item = arr[i];
582          if (!(item instanceof Uint8Array)) {
583            if (typeof item === 'string') {
584              item = stringToBytes(item);
585            } else {
586              item = new Uint8Array(item);
587            }
588          }
589          itemLength = item.byteLength;
590          data.set(item, pos);
591          pos += itemLength;
592        }
593        return data;
594      }
595
596      function string32(value) {
597        return String.fromCharCode((value >> 24) & 0xff, (value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff);
598      }
599
600      function log2(x) {
601        var n = 1,
602          i = 0;
603        while (x > n) {
604          n <<= 1;
605          i++;
606        }
607        return i;
608      }
609
610      function readInt8(data, start) {
611        return (data[start] << 24) >> 24;
612      }
613
614      function readUint16(data, offset) {
615        return (data[offset] << 8) | data[offset + 1];
616      }
617
618      function readUint32(data, offset) {
619        return ((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]) >>> 0;
620      }
621
622      // Lazy test the endianness of the platform
623      // NOTE: This will be 'true' for simulated TypedArrays
624      function isLittleEndian() {
625        var buffer8 = new Uint8Array(2);
626        buffer8[0] = 1;
627        var buffer16 = new Uint16Array(buffer8.buffer);
628        return buffer16[0] === 1;
629      }
630
631      // Checks if it's possible to eval JS expressions.
632      function isEvalSupported() {
633        try {
634          /* jshint evil: true */
635          new Function('');
636          return true;
637        } catch (e) {
638          return false;
639        }
640      }
641
642      var Uint32ArrayView = (function Uint32ArrayViewClosure() {
643        function Uint32ArrayView(buffer, length) {
644          this.buffer = buffer;
645          this.byteLength = buffer.length;
646          this.length = length === undefined ? this.byteLength >> 2 : length;
647          ensureUint32ArrayViewProps(this.length);
648        }
649
650        Uint32ArrayView.prototype = Object.create(null);
651
652        var uint32ArrayViewSetters = 0;
653
654        function createUint32ArrayProp(index) {
655          return {
656            get: function () {
657              var buffer = this.buffer,
658                offset = index << 2;
659              return (
660                (buffer[offset] |
661                  (buffer[offset + 1] << 8) |
662                  (buffer[offset + 2] << 16) |
663                  (buffer[offset + 3] << 24)) >>>
664                0
665              );
666            },
667            set: function (value) {
668              var buffer = this.buffer,
669                offset = index << 2;
670              buffer[offset] = value & 255;
671              buffer[offset + 1] = (value >> 8) & 255;
672              buffer[offset + 2] = (value >> 16) & 255;
673              buffer[offset + 3] = (value >>> 24) & 255;
674            },
675          };
676        }
677
678        function ensureUint32ArrayViewProps(length) {
679          while (uint32ArrayViewSetters < length) {
680            Object.defineProperty(
681              Uint32ArrayView.prototype,
682              uint32ArrayViewSetters,
683              createUint32ArrayProp(uint32ArrayViewSetters)
684            );
685            uint32ArrayViewSetters++;
686          }
687        }
688
689        return Uint32ArrayView;
690      })();
691
692      exports.Uint32ArrayView = Uint32ArrayView;
693
694      var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
695
696      var Util = (function UtilClosure() {
697        function Util() {}
698
699        var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')'];
700
vendor: 4,308 bytes, lines 701-804
701        // makeCssRgb() can be called thousands of times. Using |rgbBuf| avoids
702        // creating many intermediate strings.
703        Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
704          rgbBuf[1] = r;
705          rgbBuf[3] = g;
706          rgbBuf[5] = b;
707          return rgbBuf.join('');
708        };
709
710        // Concatenates two transformation matrices together and returns the result.
711        Util.transform = function Util_transform(m1, m2) {
712          return [
713            m1[0] * m2[0] + m1[2] * m2[1],
714            m1[1] * m2[0] + m1[3] * m2[1],
715            m1[0] * m2[2] + m1[2] * m2[3],
716            m1[1] * m2[2] + m1[3] * m2[3],
717            m1[0] * m2[4] + m1[2] * m2[5] + m1[4],
718            m1[1] * m2[4] + m1[3] * m2[5] + m1[5],
719          ];
720        };
721
722        // For 2d affine transforms
723        Util.applyTransform = function Util_applyTransform(p, m) {
724          var xt = p[0] * m[0] + p[1] * m[2] + m[4];
725          var yt = p[0] * m[1] + p[1] * m[3] + m[5];
726          return [xt, yt];
727        };
728
729        Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
730          var d = m[0] * m[3] - m[1] * m[2];
731          var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
732          var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
733          return [xt, yt];
734        };
735
736        // Applies the transform to the rectangle and finds the minimum axially
737        // aligned bounding box.
738        Util.getAxialAlignedBoundingBox = function Util_getAxialAlignedBoundingBox(r, m) {
739          var p1 = Util.applyTransform(r, m);
740          var p2 = Util.applyTransform(r.slice(2, 4), m);
741          var p3 = Util.applyTransform([r[0], r[3]], m);
742          var p4 = Util.applyTransform([r[2], r[1]], m);
743          return [
744            Math.min(p1[0], p2[0], p3[0], p4[0]),
745            Math.min(p1[1], p2[1], p3[1], p4[1]),
746            Math.max(p1[0], p2[0], p3[0], p4[0]),
747            Math.max(p1[1], p2[1], p3[1], p4[1]),
748          ];
749        };
750
751        Util.inverseTransform = function Util_inverseTransform(m) {
752          var d = m[0] * m[3] - m[1] * m[2];
753          return [
754            m[3] / d,
755            -m[1] / d,
756            -m[2] / d,
757            m[0] / d,
758            (m[2] * m[5] - m[4] * m[3]) / d,
759            (m[4] * m[1] - m[5] * m[0]) / d,
760          ];
761        };
762
763        // Apply a generic 3d matrix M on a 3-vector v:
764        //   | a b c |   | X |
765        //   | d e f | x | Y |
766        //   | g h i |   | Z |
767        // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
768        // with v as [X,Y,Z]
769        Util.apply3dTransform = function Util_apply3dTransform(m, v) {
770          return [
771            m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
772            m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
773            m[6] * v[0] + m[7] * v[1] + m[8] * v[2],
774          ];
775        };
776
777        // This calculation uses Singular Value Decomposition.
778        // The SVD can be represented with formula A = USV. We are interested in the
779        // matrix S here because it represents the scale values.
780        Util.singularValueDecompose2dScale = function Util_singularValueDecompose2dScale(m) {
781          var transpose = [m[0], m[2], m[1], m[3]];
782
783          // Multiply matrix m with its transpose.
784          var a = m[0] * transpose[0] + m[1] * transpose[2];
785          var b = m[0] * transpose[1] + m[1] * transpose[3];
786          var c = m[2] * transpose[0] + m[3] * transpose[2];
787          var d = m[2] * transpose[1] + m[3] * transpose[3];
788
789          // Solve the second degree polynomial to get roots.
790          var first = (a + d) / 2;
791          var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
792          var sx = first + second || 1;
793          var sy = first - second || 1;
794
795          // Scale values are the square roots of the eigenvalues.
796          return [Math.sqrt(sx), Math.sqrt(sy)];
797        };
798
799        // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
800        // For coordinate systems whose origin lies in the bottom-left, this
801        // means normalization to (BL,TR) ordering. For systems with origin in the
802        // top-left, this means (TL,BR) ordering.
803        Util.normalizeRect = function Util_normalizeRect(rect) {
804          var r = rect.slice(0); // clone rect
805          if (rect[0] > rect[2]) {
806            r[0] = rect[2];
807            r[2] = rect[0];
808          }
809          if (rect[1] > rect[3]) {
810            r[1] = rect[3];
811            r[3] = rect[1];
812          }
813          return r;
814        };
815
816        // Returns a rectangle [x1, y1, x2, y2] corresponding to the
817        // intersection of rect1 and rect2. If no intersection, returns 'false'
818        // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
819        Util.intersect = function Util_intersect(rect1, rect2) {
820          function compare(a, b) {
821            return a - b;
822          }
823
824          // Order points along the axes
825          var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
826            orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
827            result = [];
828
829          rect1 = Util.normalizeRect(rect1);
830          rect2 = Util.normalizeRect(rect2);
831
832          // X: first and second points belong to different rectangles?
833          if (
834            (orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) ||
835            (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])
836          ) {
837            // Intersection must be between second and third points
838            result[0] = orderedX[1];
839            result[2] = orderedX[2];
840          } else {
841            return false;
842          }
843
844          // Y: first and second points belong to different rectangles?
845          if (
846            (orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) ||
847            (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])
848          ) {
849            // Intersection must be between second and third points
850            result[1] = orderedY[1];
851            result[3] = orderedY[2];
852          } else {
853            return false;
854          }
855
856          return result;
857        };
858
859        Util.sign = function Util_sign(num) {
860          return num < 0 ? -1 : 1;
861        };
862
863        var ROMAN_NUMBER_MAP = [
864          '',
865          'C',
866          'CC',
867          'CCC',
868          'CD',
869          'D',
870          'DC',
871          'DCC',
872          'DCCC',
873          'CM',
874          '',
875          'X',
876          'XX',
877          'XXX',
878          'XL',
879          'L',
880          'LX',
881          'LXX',
882          'LXXX',
883          'XC',
884          '',
885          'I',
886          'II',
887          'III',
888          'IV',
889          'V',
890          'VI',
891          'VII',
892          'VIII',
893          'IX',
894        ];
895        /**
896         * Converts positive integers to (upper case) Roman numerals.
897         * @param {integer} number - The number that should be converted.
898         * @param {boolean} lowerCase - Indicates if the result should be converted
899         *   to lower case letters. The default is false.
900         * @return {string} The resulting Roman number.
901         */
902        Util.toRoman = function Util_toRoman(number, lowerCase) {
903          assert(isInt(number) && number > 0, 'The number should be a positive integer.');
904          var pos,
905            romanBuf = [];
906          // Thousands
907          while (number >= 1000) {
908            number -= 1000;
909            romanBuf.push('M');
910          }
911          // Hundreds
912          pos = (number / 100) | 0;
913          number %= 100;
914          romanBuf.push(ROMAN_NUMBER_MAP[pos]);
915          // Tens
916          pos = (number / 10) | 0;
917          number %= 10;
918          romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
919          // Ones
920          romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
921
922          var romanStr = romanBuf.join('');
923          return lowerCase ? romanStr.toLowerCase() : romanStr;
924        };
925
926        Util.appendToArray = function Util_appendToArray(arr1, arr2) {
927          Array.prototype.push.apply(arr1, arr2);
928        };
929
930        Util.prependToArray = function Util_prependToArray(arr1, arr2) {
931          Array.prototype.unshift.apply(arr1, arr2);
932        };
933
934        Util.extendObj = function extendObj(obj1, obj2) {
935          for (var key in obj2) {
936            obj1[key] = obj2[key];
937          }
938        };
939
940        Util.getInheritableProperty = function Util_getInheritableProperty(dict, name) {
941          while (dict && !dict.has(name)) {
942            dict = dict.get('Parent');
943          }
944          if (!dict) {
945            return null;
946          }
947          return dict.get(name);
948        };
949
950        Util.inherit = function Util_inherit(sub, base, prototype) {
951          sub.prototype = Object.create(base.prototype);
952          sub.prototype.constructor = sub;
953          for (var prop in prototype) {
954            sub.prototype[prop] = prototype[prop];
955          }
956        };
957
958        Util.loadScript = function Util_loadScript(src, callback) {
959          var script = document.createElement('script');
960          var loaded = false;
vendor: 4,632 bytes, lines 961-1084
961          script.setAttribute('src', src);
962          if (callback) {
963            script.onload = function () {
964              if (!loaded) {
965                callback();
966              }
967              loaded = true;
968            };
969          }
970          document.getElementsByTagName('head')[0].appendChild(script);
971        };
972
973        return Util;
974      })();
975
976      /**
977       * PDF page viewport created based on scale, rotation and offset.
978       * @class
979       * @alias PageViewport
980       */
981      var PageViewport = (function PageViewportClosure() {
982        /**
983         * @constructor
984         * @private
985         * @param viewBox {Array} xMin, yMin, xMax and yMax coordinates.
986         * @param scale {number} scale of the viewport.
987         * @param rotation {number} rotations of the viewport in degrees.
988         * @param offsetX {number} offset X
989         * @param offsetY {number} offset Y
990         * @param dontFlip {boolean} if true, axis Y will not be flipped.
991         */
992        function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) {
993          this.viewBox = viewBox;
994          this.scale = scale;
995          this.rotation = rotation;
996          this.offsetX = offsetX;
997          this.offsetY = offsetY;
998
999          // creating transform to convert pdf coordinate system to the normal
1000          // canvas like coordinates taking in account scale and rotation
1001          var centerX = (viewBox[2] + viewBox[0]) / 2;
1002          var centerY = (viewBox[3] + viewBox[1]) / 2;
1003          var rotateA, rotateB, rotateC, rotateD;
1004          rotation = rotation % 360;
1005          rotation = rotation < 0 ? rotation + 360 : rotation;
1006          switch (rotation) {
1007            case 180:
1008              rotateA = -1;
1009              rotateB = 0;
1010              rotateC = 0;
1011              rotateD = 1;
1012              break;
1013            case 90:
1014              rotateA = 0;
1015              rotateB = 1;
1016              rotateC = 1;
1017              rotateD = 0;
1018              break;
1019            case 270:
1020              rotateA = 0;
1021              rotateB = -1;
1022              rotateC = -1;
1023              rotateD = 0;
1024              break;
1025            //case 0:
1026            default:
1027              rotateA = 1;
1028              rotateB = 0;
1029              rotateC = 0;
1030              rotateD = -1;
1031              break;
1032          }
1033
1034          if (dontFlip) {
1035            rotateC = -rotateC;
1036            rotateD = -rotateD;
1037          }
1038
1039          var offsetCanvasX, offsetCanvasY;
1040          var width, height;
1041          if (rotateA === 0) {
1042            offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
1043            offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
1044            width = Math.abs(viewBox[3] - viewBox[1]) * scale;
1045            height = Math.abs(viewBox[2] - viewBox[0]) * scale;
1046          } else {
1047            offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
1048            offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
1049            width = Math.abs(viewBox[2] - viewBox[0]) * scale;
1050            height = Math.abs(viewBox[3] - viewBox[1]) * scale;
1051          }
1052          // creating transform for the following operations:
1053          // translate(-centerX, -centerY), rotate and flip vertically,
1054          // scale, and translate(offsetCanvasX, offsetCanvasY)
1055          this.transform = [
1056            rotateA * scale,
1057            rotateB * scale,
1058            rotateC * scale,
1059            rotateD * scale,
1060            offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
1061            offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY,
1062          ];
1063
1064          this.width = width;
1065          this.height = height;
1066          this.fontScale = scale;
1067        }
1068
1069        PageViewport.prototype = /** @lends PageViewport.prototype */ {
1070          /**
1071           * Clones viewport with additional properties.
1072           * @param args {Object} (optional) If specified, may contain the 'scale' or
1073           * 'rotation' properties to override the corresponding properties in
1074           * the cloned viewport.
1075           * @returns {PageViewport} Cloned viewport.
1076           */
1077          clone: function PageViewPort_clone(args) {
1078            args = args || {};
1079            var scale = 'scale' in args ? args.scale : this.scale;
1080            var rotation = 'rotation' in args ? args.rotation : this.rotation;
1081            return new PageViewport(this.viewBox.slice(), scale, rotation, this.offsetX, this.offsetY, args.dontFlip);
1082          },
1083          /**
1084           * Converts PDF point to the viewport coordinates. For examples, useful for
1085           * converting PDF location into canvas pixel coordinates.
1086           * @param x {number} X coordinate.
1087           * @param y {number} Y coordinate.
1088           * @returns {Object} Object that contains 'x' and 'y' properties of the
1089           * point in the viewport coordinate space.
1090           * @see {@link convertToPdfPoint}
1091           * @see {@link convertToViewportRectangle}
1092           */
1093          convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
1094            return Util.applyTransform([x, y], this.transform);
1095          },
1096          /**
1097           * Converts PDF rectangle to the viewport coordinates.
1098           * @param rect {Array} xMin, yMin, xMax and yMax coordinates.
1099           * @returns {Array} Contains corresponding coordinates of the rectangle
1100           * in the viewport coordinate space.
1101           * @see {@link convertToViewportPoint}
1102           */
1103          convertToViewportRectangle: function PageViewport_convertToViewportRectangle(rect) {
1104            var tl = Util.applyTransform([rect[0], rect[1]], this.transform);
1105            var br = Util.applyTransform([rect[2], rect[3]], this.transform);
1106            return [tl[0], tl[1], br[0], br[1]];
1107          },
1108          /**
1109           * Converts viewport coordinates to the PDF location. For examples, useful
1110           * for converting canvas pixel location into PDF one.
1111           * @param x {number} X coordinate.
1112           * @param y {number} Y coordinate.
1113           * @returns {Object} Object that contains 'x' and 'y' properties of the
1114           * point in the PDF coordinate space.
1115           * @see {@link convertToViewportPoint}
1116           */
1117          convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
1118            return Util.applyInverseTransform([x, y], this.transform);
1119          },
1120        };
1121        return PageViewport;
1122      })();
1123
1124      var PDFStringTranslateTable = [
1125        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd,
1126        0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1127        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1128        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021,
1129        0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019,
1130        0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac,
1131      ];
1132
1133      function stringToPDFString(str) {
1134        var i,
1135          n = str.length,
1136          strBuf = [];
1137        if (str[0] === '\xFE' && str[1] === '\xFF') {
1138          // UTF16BE BOM
1139          for (i = 2; i < n; i += 2) {
1140            strBuf.push(String.fromCharCode((str.charCodeAt(i) << 8) | str.charCodeAt(i + 1)));
1141          }
1142        } else {
1143          for (i = 0; i < n; ++i) {
1144            var code = PDFStringTranslateTable[str.charCodeAt(i)];
1145            strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
1146          }
1147        }
1148        return strBuf.join('');
1149      }
1150
1151      function stringToUTF8String(str) {
1152        return decodeURIComponent(escape(str));
1153      }
1154
1155      function utf8StringToString(str) {
1156        return unescape(encodeURIComponent(str));
1157      }
1158
1159      function isEmptyObj(obj) {
1160        for (var key in obj) {
1161          return false;
1162        }
1163        return true;
1164      }
1165
1166      function isBool(v) {
1167        return typeof v === 'boolean';
1168      }
1169
1170      function isInt(v) {
1171        return typeof v === 'number' && (v | 0) === v;
1172      }
1173
1174      function isNum(v) {
1175        return typeof v === 'number';
1176      }
1177
1178      function isString(v) {
1179        return typeof v === 'string';
1180      }
1181
1182      function isArray(v) {
1183        return v instanceof Array;
1184      }
1185
1186      function isArrayBuffer(v) {
1187        return typeof v === 'object' && v !== null && v.byteLength !== undefined;
1188      }
1189
1190      // Checks if ch is one of the following characters: SPACE, TAB, CR or LF.
1191      function isSpace(ch) {
1192        return ch === 0x20 || ch === 0x09 || ch === 0x0d || ch === 0x0a;
1193      }
1194
1195      /**
1196       * Promise Capability object.
1197       *
1198       * @typedef {Object} PromiseCapability
1199       * @property {Promise} promise - A promise object.
1200       * @property {function} resolve - Fulfills the promise.
1201       * @property {function} reject - Rejects the promise.
1202       */
1203
1204      /**
1205       * Creates a promise capability object.
1206       * @alias createPromiseCapability
1207       *
1208       * @return {PromiseCapability}
vendor: 11,259 bytes, lines 1208-1542
1208 A capability object contains:
1209       * - a Promise, resolve and reject methods.
1210       */
1211      function createPromiseCapability() {
1212        var capability = {};
1213        capability.promise = new Promise(function (resolve, reject) {
1214          capability.resolve = resolve;
1215          capability.reject = reject;
1216        });
1217        return capability;
1218      }
1219
1220      /**
1221       * Polyfill for Promises:
1222       * The following promise implementation tries to generally implement the
1223       * Promise/A+ spec. Some notable differences from other promise libraries are:
1224       * - There currently isn't a separate deferred and promise object.
1225       * - Unhandled rejections eventually show an error if they aren't handled.
1226       *
1227       * Based off of the work in:
1228       * https://bugzilla.mozilla.org/show_bug.cgi?id=810490
1229       */
1230      (function PromiseClosure() {
1231        if (globalScope.Promise) {
1232          // Promises existing in the DOM/Worker, checking presence of all/resolve
1233          if (typeof globalScope.Promise.all !== 'function') {
1234            globalScope.Promise.all = function (iterable) {
1235              var count = 0,
1236                results = [],
1237                resolve,
1238                reject;
1239              var promise = new globalScope.Promise(function (resolve_, reject_) {
1240                resolve = resolve_;
1241                reject = reject_;
1242              });
1243              iterable.forEach(function (p, i) {
1244                count++;
1245                p.then(function (result) {
1246                  results[i] = result;
1247                  count--;
1248                  if (count === 0) {
1249                    resolve(results);
1250                  }
1251                }, reject);
1252              });
1253              if (count === 0) {
1254                resolve(results);
1255              }
1256              return promise;
1257            };
1258          }
1259          if (typeof globalScope.Promise.resolve !== 'function') {
1260            globalScope.Promise.resolve = function (value) {
1261              return new globalScope.Promise(function (resolve) {
1262                resolve(value);
1263              });
1264            };
1265          }
1266          if (typeof globalScope.Promise.reject !== 'function') {
1267            globalScope.Promise.reject = function (reason) {
1268              return new globalScope.Promise(function (resolve, reject) {
1269                reject(reason);
1270              });
1271            };
1272          }
1273          if (typeof globalScope.Promise.prototype.catch !== 'function') {
1274            globalScope.Promise.prototype.catch = function (onReject) {
1275              return globalScope.Promise.prototype.then(undefined, onReject);
1276            };
1277          }
1278          return;
1279        }
1280        var STATUS_PENDING = 0;
1281        var STATUS_RESOLVED = 1;
1282        var STATUS_REJECTED = 2;
1283
1284        // In an attempt to avoid silent exceptions, unhandled rejections are
1285        // tracked and if they aren't handled in a certain amount of time an
1286        // error is logged.
1287        var REJECTION_TIMEOUT = 500;
1288
1289        var HandlerManager = {
1290          handlers: [],
1291          running: false,
1292          unhandledRejections: [],
1293          pendingRejectionCheck: false,
1294
1295          scheduleHandlers: function scheduleHandlers(promise) {
1296            if (promise._status === STATUS_PENDING) {
1297              return;
1298            }
1299
1300            this.handlers = this.handlers.concat(promise._handlers);
1301            promise._handlers = [];
1302
1303            if (this.running) {
1304              return;
1305            }
1306            this.running = true;
1307
1308            setTimeout(this.runHandlers.bind(this), 0);
1309          },
1310
1311          runHandlers: function runHandlers() {
1312            var RUN_TIMEOUT = 1; // ms
1313            var timeoutAt = Date.now() + RUN_TIMEOUT;
1314            while (this.handlers.length > 0) {
1315              var handler = this.handlers.shift();
1316
1317              var nextStatus = handler.thisPromise._status;
1318              var nextValue = handler.thisPromise._value;
1319
1320              try {
1321                if (nextStatus === STATUS_RESOLVED) {
1322                  if (typeof handler.onResolve === 'function') {
1323                    nextValue = handler.onResolve(nextValue);
1324                  }
1325                } else if (typeof handler.onReject === 'function') {
1326                  nextValue = handler.onReject(nextValue);
1327                  nextStatus = STATUS_RESOLVED;
1328
1329                  if (handler.thisPromise._unhandledRejection) {
1330                    this.removeUnhandeledRejection(handler.thisPromise);
1331                  }
1332                }
1333              } catch (ex) {
1334                nextStatus = STATUS_REJECTED;
1335                nextValue = ex;
1336              }
1337
1338              handler.nextPromise._updateStatus(nextStatus, nextValue);
1339              if (Date.now() >= timeoutAt) {
1340                break;
1341              }
1342            }
1343
1344            if (this.handlers.length > 0) {
1345              setTimeout(this.runHandlers.bind(this), 0);
1346              return;
1347            }
1348
1349            this.running = false;
1350          },
1351
1352          addUnhandledRejection: function addUnhandledRejection(promise) {
1353            this.unhandledRejections.push({
1354              promise: promise,
1355              time: Date.now(),
1356            });
1357            this.scheduleRejectionCheck();
1358          },
1359
1360          removeUnhandeledRejection: function removeUnhandeledRejection(promise) {
1361            promise._unhandledRejection = false;
1362            for (var i = 0; i < this.unhandledRejections.length; i++) {
1363              if (this.unhandledRejections[i].promise === promise) {
1364                this.unhandledRejections.splice(i);
1365                i--;
1366              }
1367            }
1368          },
1369
1370          scheduleRejectionCheck: function scheduleRejectionCheck() {
1371            if (this.pendingRejectionCheck) {
1372              return;
1373            }
1374            this.pendingRejectionCheck = true;
1375            setTimeout(
1376              function rejectionCheck() {
1377                this.pendingRejectionCheck = false;
1378                var now = Date.now();
1379                for (var i = 0; i < this.unhandledRejections.length; i++) {
1380                  if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) {
1381                    var unhandled = this.unhandledRejections[i].promise._value;
1382                    var msg = 'Unhandled rejection: ' + unhandled;
1383                    if (unhandled.stack) {
1384                      msg += '\n' + unhandled.stack;
1385                    }
1386                    warn(msg);
1387                    this.unhandledRejections.splice(i);
1388                    i--;
1389                  }
1390                }
1391                if (this.unhandledRejections.length) {
1392                  this.scheduleRejectionCheck();
1393                }
1394              }.bind(this),
1395              REJECTION_TIMEOUT
1396            );
1397          },
1398        };
1399
1400        function Promise(resolver) {
1401          this._status = STATUS_PENDING;
1402          this._handlers = [];
1403          try {
1404            resolver.call(this, this._resolve.bind(this), this._reject.bind(this));
1405          } catch (e) {
1406            this._reject(e);
1407          }
1408        }
1409
1410        /**
1411         * Builds a promise that is resolved when all the passed in promises are
1412         * resolved.
1413         * @param {array} promises array of data and/or promises to wait for.
1414         * @return {Promise} New dependent promise.
1415         */
1416        Promise.all = function Promise_all(promises) {
1417          var resolveAll, rejectAll;
1418          var deferred = new Promise(function (resolve, reject) {
1419            resolveAll = resolve;
1420            rejectAll = reject;
1421          });
1422          var unresolved = promises.length;
1423          var results = [];
1424          if (unresolved === 0) {
1425            resolveAll(results);
1426            return deferred;
1427          }
1428
1429          function reject(reason) {
1430            if (deferred._status === STATUS_REJECTED) {
1431              return;
1432            }
1433            results = [];
1434            rejectAll(reason);
1435          }
1436
1437          for (var i = 0, ii = promises.length; i < ii; ++i) {
1438            var promise = promises[i];
1439            var resolve = (function (i) {
1440              return function (value) {
1441                if (deferred._status === STATUS_REJECTED) {
1442                  return;
1443                }
1444                results[i] = value;
1445                unresolved--;
1446                if (unresolved === 0) {
1447                  resolveAll(results);
1448                }
1449              };
1450            })(i);
1451            if (Promise.isPromise(promise)) {
1452              promise.then(resolve, reject);
1453            } else {
1454              resolve(promise);
1455            }
1456          }
1457          return deferred;
1458        };
1459
1460        /**
1461         * Checks if the value is likely a promise (has a 'then' function).
1462         * @return {boolean} true if value is thenable
1463         */
1464        Promise.isPromise = function Promise_isPromise(value) {
1465          return value && typeof value.then === 'function';
1466        };
1467
1468        /**
1469         * Creates resolved promise
1470         * @param value resolve value
1471         * @returns {Promise}
1472         */
1473        Promise.resolve = function Promise_resolve(value) {
1474          return new Promise(function (resolve) {
1475            resolve(value);
1476          });
1477        };
1478
1479        /**
1480         * Creates rejected promise
1481         * @param reason rejection value
1482         * @returns {Promise}
1483         */
1484        Promise.reject = function Promise_reject(reason) {
1485          return new Promise(function (resolve, reject) {
1486            reject(reason);
1487          });
1488        };
1489
1490        Promise.prototype = {
1491          _status: null,
1492          _value: null,
1493          _handlers: null,
1494          _unhandledRejection: null,
1495
1496          _updateStatus: function Promise__updateStatus(status, value) {
1497            if (this._status === STATUS_RESOLVED || this._status === STATUS_REJECTED) {
1498              return;
1499            }
1500
1501            if (status === STATUS_RESOLVED && Promise.isPromise(value)) {
1502              value.then(
1503                this._updateStatus.bind(this, STATUS_RESOLVED),
1504                this._updateStatus.bind(this, STATUS_REJECTED)
1505              );
1506              return;
1507            }
1508
1509            this._status = status;
1510            this._value = value;
1511
1512            if (status === STATUS_REJECTED && this._handlers.length === 0) {
1513              this._unhandledRejection = true;
1514              HandlerManager.addUnhandledRejection(this);
1515            }
1516
1517            HandlerManager.scheduleHandlers(this);
1518          },
1519
1520          _resolve: function Promise_resolve(value) {
1521            this._updateStatus(STATUS_RESOLVED, value);
1522          },
1523
1524          _reject: function Promise_reject(reason) {
1525            this._updateStatus(STATUS_REJECTED, reason);
1526          },
1527
1528          then: function Promise_then(onResolve, onReject) {
1529            var nextPromise = new Promise(function (resolve, reject) {
1530              this.resolve = resolve;
1531              this.reject = reject;
1532            });
1533            this._handlers.push({
1534              thisPromise: this,
1535              onResolve: onResolve,
1536              onReject: onReject,
1537              nextPromise: nextPromise,
1538            });
1539            HandlerManager.scheduleHandlers(this);
1540            return nextPromise;
1541          },
1542
1543          catch: function Promise_catch(onReject) {
1544            return this.then(undefined, onReject);
1545          },
1546        };
1547
1548        globalScope.Promise = Promise;
1549      })();
1550
1551      (function WeakMapClosure() {
1552        if (globalScope.WeakMap) {
1553          return;
1554        }
1555
1556        var id = 0;
1557
1558        function WeakMap() {
1559          this.id = '$weakmap' + id++;
1560        }
1561
1562        WeakMap.prototype = {
1563          has: function (obj) {
1564            return !!Object.getOwnPropertyDescriptor(obj, this.id);
1565          },
1566          get: function (obj, defaultValue) {
1567            return this.has(obj) ? obj[this.id] : defaultValue;
1568          },
1569          set: function (obj, value) {
1570            Object.defineProperty(obj, this.id, {
1571              value: value,
1572              enumerable: false,
1573              configurable: true,
1574            });
1575          },
1576          delete: function (obj) {
1577            delete obj[this.id];
1578          },
1579        };
1580
1581        globalScope.WeakMap = WeakMap;
1582      })();
1583
1584      var StatTimer = (function StatTimerClosure() {
1585        function rpad(str, pad, length) {
1586          while (str.length < length) {
1587            str += pad;
1588          }
1589          return str;
1590        }
1591
1592        function StatTimer() {
1593          this.started = Object.create(null);
1594          this.times = [];
1595          this.enabled = true;
1596        }
1597
1598        StatTimer.prototype = {
1599          time: function StatTimer_time(name) {
1600            if (!this.enabled) {
1601              return;
1602            }
1603            if (name in this.started) {
1604              warn('Timer is already running for ' + name);
1605            }
1606            this.started[name] = Date.now();
1607          },
1608          timeEnd: function StatTimer_timeEnd(name) {
1609            if (!this.enabled) {
1610              return;
1611            }
1612            if (!(name in this.started)) {
1613              warn('Timer has not been started for ' + name);
1614            }
1615            this.times.push({
1616              name: name,
1617              start: this.started[name],
1618              end: Date.now(),
1619            });
1620            // Remove timer from started so it can be called again.
1621            delete this.started[name];
1622          },
1623          toString: function StatTimer_toString() {
1624            var i, ii;
1625            var times = this.times;
1626            var out = '';
1627            // Find the longest name for padding purposes.
1628            var longest = 0;
1629            for (i = 0, ii = times.length; i < ii; ++i) {
1630              var name = times[i]['name'];
1631              if (name.length > longest) {
1632                longest = name.length;
1633              }
1634            }
1635            for (i = 0, ii = times.length; i < ii; ++i) {
1636              var span = times[i];
1637              var duration = span.end - span.start;
1638              out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
1639            }
1640            return out;
1641          },
1642        };
1643        return StatTimer;
1644      })();
1645
1646      var createBlob = function createBlob(data, contentType) {
1647        if (typeof Blob !== 'undefined') {
1648          return new Blob([data], { type: contentType });
1649        }
1650        warn('The "Blob" constructor is not supported.');
1651      };
1652
1653      var createObjectURL = (function createObjectURLClosure() {
1654        // Blob/createObjectURL is not available, falling back to data schema.
1655        var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
1656
1657        return function createObjectURL(data, contentType, forceDataSchema) {
1658          if (!forceDataSchema && typeof URL !== 'undefined' && URL.createObjectURL) {
1659            var blob = createBlob(data, contentType);
1660            return URL.createObjectURL(blob);
1661          }
1662
1663          var buffer = 'data:' + contentType + ';base64,';
1664          for (var i = 0, ii = data.length; i < ii; i += 3) {
1665            var b1 = data[i] & 0xff;
1666            var b2 = data[i + 1] & 0xff;
1667            var b3 = data[i + 2] & 0xff;
1668            var d1 = b1 >> 2,
1669              d2 = ((b1 & 3) << 4) | (b2 >> 4);
1670            var d3 = i + 1 < ii ? ((b2 & 0xf) << 2) | (b3 >> 6) : 64;
1671            var d4 = i + 2 < ii ? b3 & 0x3f : 64;
1672            buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
1673          }
1674          return buffer;
1675        };
1676      })();
1677
1678      function MessageHandler(sourceName, targetName, comObj) {
1679        this.sourceName = sourceName;
1680        this.targetName = targetName;
1681        this.comObj = comObj;
1682        this.callbackIndex = 1;
1683        this.postMessageTransfers = true;
1684        var callbacksCapabilities = (this.callbacksCapabilities = Object.create(null));
1685        var ah = (this.actionHandler = Object.create(null));
1686
1687        this._onComObjOnMessage = function messageHandlerComObjOnMessage(event) {
1688          var data = event.data;
1689          if (data.targetName !== this.sourceName) {
1690            return;
1691          }
1692          if (data.isReply) {
1693            var callbackId = data.callbackId;
1694            if (data.callbackId in callbacksCapabilities) {
1695              var callback = callbacksCapabilities[callbackId];
1696              delete callbacksCapabilities[callbackId];
1697              if ('error' in data) {
1698                callback.reject(data.error);
1699              } else {
1700                callback.resolve(data.data);
1701              }
1702            } else {
1703              error('Cannot resolve callback ' + callbackId);
1704            }
1705          } else if (data.action in ah) {
1706            var action = ah[data.action];
1707            if (data.callbackId) {
1708              var sourceName = this.sourceName;
1709              var targetName = data.sourceName;
1710              Promise.resolve()
1711                .then(function () {
1712                  return action[0].call(action[1], data.data);
1713                })
1714                .then(
1715                  function (result) {
1716                    comObj.postMessage({
1717                      sourceName: sourceName,
1718                      targetName: targetName,
1719                      isReply: true,
1720                      callbackId: data.callbackId,
1721                      data: result,
1722                    });
1723                  },
1724                  function (reason) {
1725                    if (reason instanceof Error) {
1726                      // Serialize error to avoid "DataCloneError"
1727                      reason = reason + '';
1728                    }
1729                    comObj.postMessage({
1730                      sourceName: sourceName,
1731                      targetName: targetName,
1732                      isReply: true,
1733                      callbackId: data.callbackId,
1734                      error: reason,
1735                    });
1736                  }
1737                );
1738            } else {
1739              action[0].call(action[1], data.data);
1740            }
1741          } else {
1742            error('Unknown action from worker: ' + data.action);
1743          }
1744        }.bind(this);
1745        comObj.addEventListener('message', this._onComObjOnMessage);
1746      }
1747
1748      MessageHandler.prototype = {
1749        on: function messageHandlerOn(actionName, handler, scope) {
1750          var ah = this.actionHandler;
1751          if (ah[actionName]) {
1752            error('There is already an actionName called "' + actionName + '"');
1753          }
1754          ah[actionName] = [handler, scope];
1755        },
1756        /**
1757         * Sends a message to the comObj to invoke the action with the supplied data.
1758         * @param {String} actionName Action to call.
1759         * @param {JSON} data JSON data to send.
1760         * @param {Array} [transfers] Optional list of transfers/ArrayBuffers
1761         */
1762        send: function messageHandlerSend(actionName, data, transfers) {
1763          var message = {
1764            sourceName: this.sourceName,
1765            targetName: this.targetName,
1766            action: actionName,
1767            data: data,
1768          };
1769          this.postMessage(message, transfers);
1770        },
1771        /**
1772         * Sends a message to the comObj to invoke the action with the supplied data.
1773         * Expects that other side will callback with the response.
1774         * @param {String} actionName Action to call.
1775         * @param {JSON} data JSON data to send.
1776         * @param {Array} [transfers] Optional list of transfers/ArrayBuffers.
1777         * @returns {Promise} Promise to be resolved with response data.
1778         */
1779        sendWithPromise: function messageHandlerSendWithPromise(actionName, data, transfers) {
1780          var callbackId = this.callbackIndex++;
1781          var message = {
1782            sourceName: this.sourceName,
1783            targetName: this.targetName,
1784            action: actionName,
1785            data: data,
1786            callbackId: callbackId,
1787          };
1788          var capability = createPromiseCapability();
1789          this.callbacksCapabilities[callbackId] = capability;
1790          try {
1791            this.postMessage(message, transfers);
1792          } catch (e) {
1793            capability.reject(e);
1794          }
1795          return capability.promise;
1796        },
1797        /**
1798         * Sends raw message to the comObj.
1799         * @private
1800         * @param message {Object} Raw message.
1801         * @param transfers List of transfers/ArrayBuffers, or undefined.
1802         */
1803        postMessage: function (message, transfers) {
1804          if (transfers && this.postMessageTransfers) {
1805            this.comObj.postMessage(message, transfers);
1806          } else {
1807            this.comObj.postMessage(message);
1808          }
1809        },
1810
1811        destroy: function () {
1812          this.comObj.removeEventListener('message', this._onComObjOnMessage);
1813        },
1814      };
1815
1816      function loadJpegStream(id, imageUrl, objs) {
1817        var img = new Image();
1818        img.onload = function loadJpegStream_onloadClosure() {
1819          objs.resolve(id, img);
1820        };
1821        img.onerror = function loadJpegStream_onerrorClosure() {
1822          objs.resolve(id, null);
1823          warn('Error during JPEG image loading');
1824        };
1825        img.src = imageUrl;
1826      }
1827
1828      // Polyfill from https://github.com/Polymer/URL
1829      /* Any copyright is dedicated to the Public Domain.
1830       * http://creativecommons.org/publicdomain/zero/1.0/ */
1831      (function checkURLConstructor(scope) {
1832        // feature detect for URL constructor
1833        var hasWorkingUrl = false;
1834        try {
1835          if (typeof URL === 'function' && typeof URL.prototype === 'object' && 'origin' in URL.prototype) {
1836            var u = new URL('b', 'http://a');
1837            u.pathname = 'c%20d';
1838            hasWorkingUrl = u.href === 'http://a/c%20d';
1839          }
1840        } catch (e) {}
1841
1842        if (hasWorkingUrl) {
1843          return;
1844        }
1845
1846        var relative = Object.create(null);
1847        relative['ftp'] = 21;
1848        relative['file'] = 0;
1849        relative['gopher'] = 70;
1850        relative['http'] = 80;
1851        relative['https'] = 443;
1852        relative['ws'] = 80;
1853        relative['wss'] = 443;
1854
1855        var relativePathDotMapping = Object.create(null);
1856        relativePathDotMapping['%2e'] = '.';
1857        relativePathDotMapping['.%2e'] = '..';
1858        relativePathDotMapping['%2e.'] = '..';
1859        relativePathDotMapping['%2e%2e'] = '..';
1860
1861        function isRelativeScheme(scheme) {
1862          return relative[scheme] !== undefined;
1863        }
1864
1865        function invalid() {
1866          clear.call(this);
1867          this._isInvalid = true;
1868        }
1869
1870        function IDNAToASCII(h) {
1871          if ('' === h) {
1872            invalid.call(this);
1873          }
1874          // XXX
1875          return h.toLowerCase();
1876        }
1877
1878        function percentEscape(c) {
1879          var unicode = c.charCodeAt(0);
1880          if (
1881            unicode > 0x20 &&
1882            unicode < 0x7f &&
1883            // " # < > ? `
1884            [0x22, 0x23, 0x3c, 0x3e, 0x3f, 0x60].indexOf(unicode) === -1
1885          ) {
1886            return c;
1887          }
1888          return encodeURIComponent(c);
1889        }
1890
1891        function percentEscapeQuery(c) {
1892          // XXX This actually needs to encode c using encoding and then
1893          // convert the bytes one-by-one.
1894
1895          var unicode = c.charCodeAt(0);
1896          if (
1897            unicode > 0x20 &&
1898            unicode < 0x7f &&
1899            // " # < > ` (do not escape '?')
1900            [0x22, 0x23, 0x3c, 0x3e, 0x60].indexOf(unicode) === -1
1901          ) {
1902            return c;
1903          }
1904          return encodeURIComponent(c);
1905        }
1906
1907        var EOF,
1908          ALPHA = /[a-zA-Z]/,
1909          ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
1910
1911        function parse(input, stateOverride, base) {
1912          function err(message) {
1913            errors.push(message);
1914          }
1915
1916          var state = stateOverride || 'scheme start',
1917            cursor = 0,
1918            buffer = '',
1919            seenAt = false,
1920            seenBracket = false,
1921            errors = [];
1922
1923          loop: while ((input[cursor - 1] !== EOF || cursor === 0) && !this._isInvalid) {
1924            var c = input[cursor];
1925            switch (state) {
1926              case 'scheme start':
1927                if (c && ALPHA.test(c)) {
1928                  buffer += c.toLowerCase(); // ASCII-safe
1929                  state = 'scheme';
1930                } else if (!stateOverride) {
1931                  buffer = '';
1932                  state = 'no scheme';
1933                  continue;
1934                } else {
1935                  err('Invalid scheme.');
1936                  break loop;
1937                }
1938                break;
1939
1940              case 'scheme':
1941                if (c && ALPHANUMERIC.test(c)) {
1942                  buffer += c.toLowerCase(); // ASCII-safe
1943                } else if (':' === c) {
1944                  this._scheme = buffer;
1945                  buffer = '';
1946                  if (stateOverride) {
1947                    break loop;
1948                  }
1949                  if (isRelativeScheme(this._scheme)) {
1950                    this._isRelative = true;
1951                  }
1952                  if ('file' === this._scheme) {
1953                    state = 'relative';
1954                  } else if (this._isRelative && base && base._scheme === this._scheme) {
1955                    state = 'relative or authority';
1956                  } else if (this._isRelative) {
1957                    state = 'authority first slash';
1958                  } else {
1959                    state = 'scheme data';
1960                  }
1961                } else if (!stateOverride) {
1962                  buffer = '';
1963                  cursor = 0;
1964                  state = 'no scheme';
1965                  continue;
1966                } else if (EOF === c) {
1967                  break loop;
1968                } else {
1969                  err('Code point not allowed in scheme: ' + c);
1970                  break loop;
1971                }
1972                break;
1973
1974              case 'scheme data':
1975                if ('?' === c) {
1976                  this._query = '?';
1977                  state = 'query';
1978                } else if ('#' === c) {
1979                  this._fragment = '#';
1980                  state = 'fragment';
1981                } else {
1982                  // XXX error handling
1983                  if (EOF !== c && '\t' !== c && '\n' !== c && '\r' !== c) {
1984                    this._schemeData += percentEscape(c);
1985                  }
1986                }
1987                break;
1988
1989              case 'no scheme':
1990                if (!base || !isRelativeScheme(base._scheme)) {
1991                  err('Missing scheme.');
1992                  invalid.call(this);
1993                } else {
1994                  state = 'relative';
1995                  continue;
1996                }
1997                break;
1998
1999              case 'relative or authority':
2000                if ('/' === c && '/' === input[cursor + 1]) {
2001                  state = 'authority ignore slashes';
2002                } else {
2003                  err('Expected /, got: ' + c);
2004                  state = 'relative';
2005                  continue;
2006                }
2007                break;
2008
2009              case 'relative':
2010                this._isRelative = true;
2011                if ('file' !== this._scheme) {
2012                  this._scheme = base._scheme;
2013                }
2014                if (EOF === c) {
2015                  this._host = base._host;
2016                  this._port = base._port;
2017                  this._path = base._path.slice();
2018                  this._query = base._query;
2019                  this._username = base._username;
2020                  this._password = base._password;
2021                  break loop;
2022                } else if ('/' === c || '\\' === c) {
2023                  if ('\\' === c) {
2024                    err('\\ is an invalid code point.');
2025                  }
2026                  state = 'relative slash';
2027                } else if ('?' === c) {
2028                  this._host = base._host;
2029                  this._port = base._port;
2030                  this._path = base._path.slice();
2031                  this._query = '?';
2032                  this._username = base._username;
2033                  this._password = base._password;
2034                  state = 'query';
2035                } else if ('#' === c) {
2036                  this._host = base._host;
2037                  this._port = base._port;
2038                  this._path = base._path.slice();
2039                  this._query = base._query;
2040                  this._fragment = '#';
2041                  this._username = base._username;
2042                  this._password = base._password;
2043                  state = 'fragment';
2044                } else {
2045                  var nextC = input[cursor + 1];
2046                  var nextNextC = input[cursor + 2];
2047                  if (
2048                    'file' !== this._scheme ||
2049                    !ALPHA.test(c) ||
2050                    (nextC !== ':' && nextC !== '|') ||
2051                    (EOF !== nextNextC &&
2052                      '/' !== nextNextC &&
2053                      '\\' !== nextNextC &&
2054                      '?' !== nextNextC &&
2055                      '#' !== nextNextC)
2056                  ) {
2057                    this._host = base._host;
2058                    this._port = base._port;
2059                    this._username = base._username;
2060                    this._password = base._password;
2061                    this._path = base._path.slice();
2062                    this._path.pop();
2063                  }
2064                  state = 'relative path';
2065                  continue;
2066                }
2067                break;
2068
2069              case 'relative slash':
2070                if ('/' === c || '\\' === c) {
2071                  if ('\\' === c) {
2072                    err('\\ is an invalid code point.');
2073                  }
2074                  if ('file' === this._scheme) {
2075                    state = 'file host';
2076                  } else {
2077                    state = 'authority ignore slashes';
2078                  }
2079                } else {
2080                  if ('file' !== this._scheme) {
2081                    this._host = base._host;
2082                    this._port = base._port;
2083                    this._username = base._username;
2084                    this._password = base._password;
2085                  }
2086                  state = 'relative path';
2087                  continue;
2088                }
2089                break;
2090
2091              case 'authority first slash':
2092                if ('/' === c) {
2093                  state = 'authority second slash';
2094                } else {
2095                  err("Expected '/', got: " + c);
2096                  state = 'authority ignore slashes';
2097                  continue;
2098                }
2099                break;
2100
2101              case 'authority second slash':
2102                state = 'authority ignore slashes';
2103                if ('/' !== c) {
2104                  err("Expected '/', got: " + c);
2105                  continue;
2106                }
2107                break;
2108
2109              case 'authority ignore slashes':
2110                if ('/' !== c && '\\' !== c) {
2111                  state = 'authority';
2112                  continue;
2113                } else {
2114                  err('Expected authority, got: ' + c);
2115                }
2116                break;
2117
2118              case 'authority':
2119                if ('@' === c) {
2120                  if (seenAt) {
2121                    err('@ already seen.');
2122                    buffer += '%40';
2123                  }
2124                  seenAt = true;
2125                  for (var i = 0; i < buffer.length; i++) {
2126                    var cp = buffer[i];
2127                    if ('\t' === cp || '\n' === cp || '\r' === cp) {
2128                      err('Invalid whitespace in authority.');
2129                      continue;
2130                    }
2131                    // XXX check URL code points
2132                    if (':' === cp && null === this._password) {
2133                      this._password = '';
2134                      continue;
2135                    }
2136                    var tempC = percentEscape(cp);
2137                    if (null !== this._password) {
2138                      this._password += tempC;
2139                    } else {
2140                      this._username += tempC;
2141                    }
2142                  }
2143                  buffer = '';
2144                } else if (EOF === c || '/' === c || '\\' === c || '?' === c || '#' === c) {
2145                  cursor -= buffer.length;
2146                  buffer = '';
2147                  state = 'host';
2148                  continue;
2149                } else {
2150                  buffer += c;
2151                }
2152                break;
2153
2154              case 'file host':
2155                if (EOF === c || '/' === c || '\\' === c || '?' === c || '#' === c) {
2156                  if (buffer.length === 2 && ALPHA.test(buffer[0]) && (buffer[1] === ':' || buffer[1] === '|')) {
2157                    state = 'relative path';
2158                  } else if (buffer.length === 0) {
2159                    state = 'relative path start';
2160                  } else {
2161                    this._host = IDNAToASCII.call(this, buffer);
2162                    buffer = '';
2163                    state = 'relative path start';
2164                  }
2165                  continue;
2166                } else if ('\t' === c || '\n' === c || '\r' === c) {
2167                  err('Invalid whitespace in file host.');
2168                } else {
2169                  buffer += c;
2170                }
2171                break;
2172
2173              case 'host':
2174              case 'hostname':
2175                if (':' === c && !seenBracket) {
2176                  // XXX host parsing
2177                  this._host = IDNAToASCII.call(this, buffer);
2178                  buffer = '';
2179                  state = 'port';
2180                  if ('hostname' === stateOverride) {
2181                    break loop;
2182                  }
2183                } else if (EOF === c || '/' === c || '\\' === c || '?' === c || '#' === c) {
2184                  this._host = IDNAToASCII.call(this, buffer);
2185                  buffer = '';
2186                  state = 'relative path start';
2187                  if (stateOverride) {
2188                    break loop;
2189                  }
2190                  continue;
2191                } else if ('\t' !== c && '\n' !== c && '\r' !== c) {
2192                  if ('[' === c) {
2193                    seenBracket = true;
2194                  } else if (']' === c) {
2195                    seenBracket = false;
2196                  }
2197                  buffer += c;
2198                } else {
2199                  err('Invalid code point in host/hostname: ' + c);
2200                }
2201                break;
2202
2203              case 'port':
2204                if (/[0-9]/.test(c)) {
2205                  buffer += c;
2206                } else if (EOF === c || '/' === c || '\\' === c || '?' === c || '#' === c || stateOverride) {
2207                  if ('' !== buffer) {
2208                    var temp = parseInt(buffer, 10);
2209                    if (temp !== relative[this._scheme]) {
2210                      this._port = temp + '';
2211                    }
2212                    buffer = '';
2213                  }
2214                  if (stateOverride) {
2215                    break loop;
2216                  }
2217                  state = 'relative path start';
2218                  continue;
2219                } else if ('\t' === c || '\n' === c || '\r' === c) {
2220                  err('Invalid code point in port: ' + c);
2221                } else {
2222                  invalid.call(this);
2223                }
2224                break;
2225
2226              case 'relative path start':
2227                if ('\\' === c) {
2228                  err("'\\' not allowed in path.");
2229                }
2230                state = 'relative path';
2231                if ('/' !== c && '\\' !== c) {
2232                  continue;
2233                }
2234                break;
2235
2236              case 'relative path':
2237                if (EOF === c || '/' === c || '\\' === c || (!stateOverride && ('?' === c || '#' === c))) {
2238                  if ('\\' === c) {
2239                    err('\\ not allowed in relative path.');
2240                  }
2241                  var tmp;
2242                  if ((tmp = relativePathDotMapping[buffer.toLowerCase()])) {
2243                    buffer = tmp;
2244                  }
2245                  if ('..' === buffer) {
2246                    this._path.pop();
2247                    if ('/' !== c && '\\' !== c) {
2248                      this._path.push('');
2249                    }
2250                  } else if ('.' === buffer && '/' !== c && '\\' !== c) {
2251                    this._path.push('');
2252                  } else if ('.' !== buffer) {
2253                    if (
2254                      'file' === this._scheme &&
2255                      this._path.length === 0 &&
2256                      buffer.length === 2 &&
2257                      ALPHA.test(buffer[0]) &&
2258                      buffer[1] === '|'
2259                    ) {
2260                      buffer = buffer[0] + ':';
2261                    }
2262                    this._path.push(buffer);
2263                  }
2264                  buffer = '';
2265                  if ('?' === c) {
2266                    this._query = '?';
2267                    state = 'query';
2268                  } else if ('#' === c) {
2269                    this._fragment = '#';
2270                    state = 'fragment';
2271                  }
2272                } else if ('\t' !== c && '\n' !== c && '\r' !== c) {
2273                  buffer += percentEscape(c);
2274                }
2275                break;
2276
2277              case 'query':
2278                if (!stateOverride && '#' === c) {
2279                  this._fragment = '#';
2280                  state = 'fragment';
2281                }
2281 else if (EOF !== c && '\t' !== c && '\n' !== c && '\r' !== c) {
2282                  this._query += percentEscapeQuery(c);
2283                }
2284                break;
2285
2286              case 'fragment':
2287                if (EOF !== c && '\t' !== c && '\n' !== c && '\r' !== c) {
2288                  this._fragment += c;
2289                }
2290                break;
2291            }
2292
2293            cursor++;
2294          }
2295        }
2296
2297        function clear() {
2298          this._scheme = '';
2299          this._schemeData = '';
2300          this._username = '';
2301          this._password = null;
2302          this._host = '';
2303          this._port = '';
2304          this._path = [];
2305          this._query = '';
2306          this._fragment = '';
2307          this._isInvalid = false;
2308          this._isRelative = false;
2309        }
2310
2311        // Does not process domain names or IP addresses.
2312        // Does not handle encoding for the query parameter.
2313        function JURL(url, base /* , encoding */) {
2314          if (base !== undefined && !(base instanceof JURL)) {
2315            base = new JURL(String(base));
2316          }
2317
2318          this._url = url;
2319          clear.call(this);
2320
2321          var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, '');
2322          // encoding = encoding || 'utf-8'
2323
2324          parse.call(this, input, null, base);
2325        }
2326
2327        JURL.prototype = {
2328          toString: function () {
2329            return this.href;
2330          },
2331          get href() {
2332            if (this._isInvalid) {
2333              return this._url;
2334            }
2335            var authority = '';
2336            if ('' !== this._username || null !== this._password) {
2337              authority = this._username + (null !== this._password ? ':' + this._password : '') + '@';
2338            }
2339
2340            return (
2341              this.protocol +
2342              (this._isRelative ? '//' + authority + this.host : '') +
2343              this.pathname +
2344              this._query +
2345              this._fragment
2346            );
2347          },
2348          set href(href) {
2349            clear.call(this);
2350            parse.call(this, href);
2351          },
2352
2353          get protocol() {
2354            return this._scheme + ':';
2355          },
2356          set protocol(protocol) {
2357            if (this._isInvalid) {
2358              return;
2359            }
2360            parse.call(this, protocol + ':', 'scheme start');
2361          },
2362
2363          get host() {
2364            return this._isInvalid ? '' : this._port ? this._host + ':' + this._port : this._host;
2365          },
2366          set host(host) {
2367            if (this._isInvalid || !this._isRelative) {
2368              return;
2369            }
2370            parse.call(this, host, 'host');
2371          },
2372
2373          get hostname() {
2374            return this._host;
2375          },
2376          set hostname(hostname) {
2377            if (this._isInvalid || !this._isRelative) {
2378              return;
2379            }
2380            parse.call(this, hostname, 'hostname');
2381          },
2382
2383          get port() {
2384            return this._port;
2385          },
2386          set port(port) {
2387            if (this._isInvalid || !this._isRelative) {
2388              return;
2389            }
2390            parse.call(this, port, 'port');
2391          },
2392
2393          get pathname() {
2394            return this._isInvalid ? '' : this._isRelative ? '/' + this._path.join('/') : this._schemeData;
2395          },
2396          set pathname(pathname) {
2397            if (this._isInvalid || !this._isRelative) {
2398              return;
2399            }
2400            this._path = [];
2401            parse.call(this, pathname, 'relative path start');
2402          },
2403
2404          get search() {
2405            return this._isInvalid || !this._query || '?' === this._query ? '' : this._query;
2406          },
2407          set search(search) {
2408            if (this._isInvalid || !this._isRelative) {
2409              return;
2410            }
2411            this._query = '?';
2412            if ('?' === search[0]) {
2413              search = search.slice(1);
2414            }
2415            parse.call(this, search, 'query');
2416          },
2417
2418          get hash() {
2419            return this._isInvalid || !this._fragment || '#' === this._fragment ? '' : this._fragment;
2420          },
2421          set hash(hash) {
2422            if (this._isInvalid) {
2423              return;
2424            }
2425            this._fragment = '#';
2426            if ('#' === hash[0]) {
2427              hash = hash.slice(1);
2428            }
2429            parse.call(this, hash, 'fragment');
2430          },
2431
2432          get origin() {
2433            var host;
2434            if (this._isInvalid || !this._scheme) {
2435              return '';
2436            }
2437            // javascript: Gecko returns String(""), WebKit/Blink String("null")
2438            // Gecko throws error for "data://"
2439            // data: Gecko returns "", Blink returns "data://", WebKit returns "null"
2440            // Gecko returns String("") for file: mailto:
2441            // WebKit/Blink returns String("SCHEME://") for file: mailto:
2442            switch (this._scheme) {
2443              case 'data':
2444              case 'file':
2445              case 'javascript':
2446              case 'mailto':
2447                return 'null';
2448            }
2449            host = this.host;
2450            if (!host) {
2451              return '';
2452            }
2453            return this._scheme + '://' + host;
2454          },
2455        };
2456
2457        // Copy over the static methods
2458        var OriginalURL = scope.URL;
2459        if (OriginalURL) {
2460          JURL.createObjectURL = function (blob) {
2461            // IE extension allows a second optional options argument.
2462            // http://msdn.microsoft.com/en-us/library/ie/hh772302(v=vs.85).aspx
2463            return OriginalURL.createObjectURL.apply(OriginalURL, arguments);
2464          };
2465          JURL.revokeObjectURL = function (url) {
2466            OriginalURL.revokeObjectURL(url);
2467          };
2468        }
2469
2470        scope.URL = JURL;
2471      })(globalScope);
2472
2473      exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX;
2474      exports.IDENTITY_MATRIX = IDENTITY_MATRIX;
2475      exports.OPS = OPS;
2476      exports.VERBOSITY_LEVELS = VERBOSITY_LEVELS;
2477      exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES;
2478      exports.AnnotationBorderStyleType = AnnotationBorderStyleType;
2479      exports.AnnotationFieldFlag = AnnotationFieldFlag;
2480      exports.AnnotationFlag = AnnotationFlag;
2481      exports.AnnotationType = AnnotationType;
2482      exports.FontType = FontType;
2483      exports.ImageKind = ImageKind;
2484      exports.InvalidPDFException = InvalidPDFException;
2485      exports.MessageHandler = MessageHandler;
2486      exports.MissingDataException = MissingDataException;
2487      exports.MissingPDFException = MissingPDFException;
2488      exports.NotImplementedException = NotImplementedException;
2489      exports.PageViewport = PageViewport;
2490      exports.PasswordException = PasswordException;
2491      exports.PasswordResponses = PasswordResponses;
2492      exports.StatTimer = StatTimer;
2493      exports.StreamType = StreamType;
2494      exports.TextRenderingMode = TextRenderingMode;
2495      exports.UnexpectedResponseException = UnexpectedResponseException;
2496      exports.UnknownErrorException = UnknownErrorException;
2497      exports.Util = Util;
2498      exports.XRefParseException = XRefParseException;
2499      exports.arrayByteLength = arrayByteLength;
2500      exports.arraysToBytes = arraysToBytes;
2501      exports.assert = assert;
2502      exports.bytesToString = bytesToString;
2503      exports.createBlob = createBlob;
2504      exports.createPromiseCapability = createPromiseCapability;
2505      exports.createObjectURL = createObjectURL;
2506      exports.deprecated = deprecated;
2507      exports.error = error;
2508      exports.getLookupTableFactory = getLookupTableFactory;
2509      exports.getVerbosityLevel = getVerbosityLevel;
2510      exports.globalScope = globalScope;
2511      exports.info = info;
2512      exports.isArray = isArray;
2513      exports.isArrayBuffer = isArrayBuffer;
2514      exports.isBool = isBool;
2515      exports.isEmptyObj = isEmptyObj;
2516      exports.isInt = isInt;
2517      exports.isNum = isNum;
2518      exports.isString = isString;
2519      exports.isSpace = isSpace;
2520      exports.isSameOrigin = isSameOrigin;
2521      exports.isValidUrl = isValidUrl;
2522      exports.isLittleEndian = isLittleEndian;
2523      exports.isEvalSupported = isEvalSupported;
2524      exports.loadJpegStream = loadJpegStream;
2525      exports.log2 = log2;
2526      exports.readInt8 = readInt8;
2527      exports.readUint16 = readUint16;
2528      exports.readUint32 = readUint32;
2529      exports.removeNullCharacters = removeNullCharacters;
2530      exports.setVerbosityLevel = setVerbosityLevel;
2531      exports.shadow = shadow;
2532      exports.string32 = string32;
2533      exports.stringToBytes = stringToBytes;
2534      exports.stringToPDFString = stringToPDFString;
2535      exports.stringToUTF8String = stringToUTF8String;
2536      exports.utf8StringToString = utf8StringToString;
2537      exports.warn = warn;
2538    });
2539
2540    (function (root, factory) {
2541      {
2542        factory((root.pdfjsDisplayDOMUtils = {}), root.pdfjsSharedUtil);
2543      }
2544    })(this, function (exports, sharedUtil) {
2545      var removeNullCharacters = sharedUtil.removeNullCharacters;
2546      var warn = sharedUtil.warn;
2547
2548      /**
2549       * Optimised CSS custom property getter/setter.
2550       * @class
2551       */
2552      var CustomStyle = (function CustomStyleClosure() {
2553        // As noted on: http://www.zachstronaut.com/posts/2009/02/17/
2554        //              animate-css-transforms-firefox-webkit.html
2555        // in some versions of IE9 it is critical that ms appear in this list
2556        // before Moz
2557        var prefixes = ['ms', 'Moz', 'Webkit', 'O'];
2558        var _cache = Object.create(null);
2559
2560        function CustomStyle() {}
2561
2562        CustomStyle.getProp = function get(propName, element) {
2563          // check cache only when no element is given
2564          if (arguments.length === 1 && typeof _cache[propName] === 'string') {
2565            return _cache[propName];
2566          }
2567
2568          element = element || document.documentElement;
2569          var style = element.style,
2570            prefixed,
2571            uPropName;
2572
2573          // test standard property first
2574          if (typeof style[propName] === 'string') {
2575            return (_cache[propName] = propName);
2576          }
2577
2578          // capitalize
2579          uPropName = propName.charAt(0).toUpperCase() + propName.slice(1);
2580
2581          // test vendor specific properties
2582          for (var i = 0, l = prefixes.length; i < l; i++) {
2583            prefixed = prefixes[i] + uPropName;
2584            if (typeof style[prefixed] === 'string') {
2585              return (_cache[propName] = prefixed);
2586            }
2587          }
2588
2589          //if all fails then set to undefined
2590          return (_cache[propName] = 'undefined');
2591        };
2592
2593        CustomStyle.setProp = function set(propName, element, str) {
2594          var prop = this.getProp(propName);
2595          if (prop !== 'undefined') {
2596            element.style[prop] = str;
2597          }
2598        };
2599
2600        return CustomStyle;
2601      })();
2602
2603      function hasCanvasTypedArrays() {
2604        var canvas = document.createElement('canvas');
2605        canvas.width = canvas.height = 1;
2606        var ctx = canvas.getContext('2d');
2607        var imageData = ctx.createImageData(1, 1);
2608        return typeof imageData.data.buffer !== 'undefined';
2609      }
2610
2611      var LinkTarget = {
2612        NONE: 0, // Default value.
2613        SELF: 1,
2614        BLANK: 2,
2615        PARENT: 3,
2616        TOP: 4,
2617      };
2618
2619      var LinkTargetStringMap = ['', '_self', '_blank', '_parent', '_top'];
2620
2621      /**
2622       * @typedef ExternalLinkParameters
2623       * @typedef {Object} ExternalLinkParameters
2624       * @property {string} url - An absolute URL.
2625       * @property {LinkTarget} target - The link target.
2626       * @property {string} rel - The link relationship.
2627       */
2628
2629      /**
2630       * Adds various attributes (href, title, target, rel) to hyperlinks.
2631       * @param {HTMLLinkElement} link - The link element.
2632       * @param {ExternalLinkParameters} params
2633       */
2634      function addLinkAttributes(link, params) {
2635        var url = params && params.url;
2636        link.href = link.title = url ? removeNullCharacters(url) : '';
2637
2638        if (url) {
2639          var target = params.target;
2640          if (typeof target === 'undefined') {
2641            target = getDefaultSetting('externalLinkTarget');
2642          }
2643          link.target = LinkTargetStringMap[target];
2644
2645          var rel = params.rel;
2646          if (typeof rel === 'undefined') {
2647            rel = getDefaultSetting('externalLinkRel');
2648          }
2649          link.rel = rel;
2650        }
2651      }
2652
2653      // Gets the file name from a given URL.
2654      function getFilenameFromUrl(url) {
2655        var anchor = url.indexOf('#');
2656        var query = url.indexOf('?');
2657        var end = Math.min(anchor > 0 ? anchor : url.length, query > 0 ? query : url.length);
2658        return url.substring(url.lastIndexOf('/', end) + 1, end);
2659      }
2660
2661      function getDefaultSetting(id) {
2662        // The list of the settings and their default is maintained for backward
2663        // compatibility and shall not be extended or modified. See also global.js.
2664        var globalSettings = sharedUtil.globalScope.PDFJS;
2665        switch (id) {
2666          case 'pdfBug':
2667            return globalSettings ? globalSettings.pdfBug : false;
2668          case 'disableAutoFetch':
2669            return globalSettings ? globalSettings.disableAutoFetch : false;
2670          case 'disableStream':
2671            return globalSettings ? globalSettings.disableStream : false;
2672          case 'disableRange':
2673            return globalSettings ? globalSettings.disableRange : false;
2674          case 'disableFontFace':
2675            return globalSettings ? globalSettings.disableFontFace : false;
2676          case 'disableCreateObjectURL':
2677            return globalSettings ? globalSettings.disableCreateObjectURL : false;
2678          case 'disableWebGL':
2679            return globalSettings ? globalSettings.disableWebGL : true;
2680          case 'cMapUrl':
2681            return globalSettings ? globalSettings.cMapUrl : null;
2682          case 'cMapPacked':
2683            return globalSettings ? globalSettings.cMapPacked : false;
2684          case 'postMessageTransfers':
2685            return globalSettings ? globalSettings.postMessageTransfers : true;
2686          case 'workerSrc':
2687            return globalSettings ? globalSettings.workerSrc : null;
2688          case 'disableWorker':
2689            return globalSettings ? globalSettings.disableWorker : false;
2690          case 'maxImageSize':
2691            return globalSettings ? globalSettings.maxImageSize : -1;
2692          case 'imageResourcesPath':
2693            return globalSettings ? globalSettings.imageResourcesPath : '';
2694          case 'isEvalSupported':
2695            return globalSettings ? globalSettings.isEvalSupported : true;
2696          case 'externalLinkTarget':
2697            if (!globalSettings) {
2698              return LinkTarget.NONE;
2699            }
2700            switch (globalSettings.externalLinkTarget) {
2701              case LinkTarget.NONE:
2702              case LinkTarget.SELF:
2703              case LinkTarget.BLANK:
2704              case LinkTarget.PARENT:
2705              case LinkTarget.TOP:
2706                return globalSettings.externalLinkTarget;
2707            }
2708            warn('PDFJS.externalLinkTarget is invalid: ' + globalSettings.externalLinkTarget);
2709            // Reset the external link target, to suppress further warnings.
2710            globalSettings.externalLinkTarget = LinkTarget.NONE;
2711            return LinkTarget.NONE;
2712          case 'externalLinkRel':
2713            return globalSettings ? globalSettings.externalLinkRel : 'noreferrer';
2714          case 'enableStats':
2715            return !!(globalSettings && globalSettings.enableStats);
2716          default:
2717            throw new Error('Unknown default setting: ' + id);
2718        }
2719      }
2720
2721      function isExternalLinkTargetSet() {
2722        var externalLinkTarget = getDefaultSetting('externalLinkTarget');
2723        switch (externalLinkTarget) {
2724          case LinkTarget.NONE:
2725            return false;
2726          case LinkTarget.SELF:
2727          case LinkTarget.BLANK:
2728          case LinkTarget.PARENT:
2729          case LinkTarget.TOP:
2730            return true;
2731        }
2732      }
2733
2734      exports.CustomStyle = CustomStyle;
2735      exports.addLinkAttributes = addLinkAttributes;
2736      exports.isExternalLinkTargetSet = isExternalLinkTargetSet;
2737      exports.getFilenameFromUrl = getFilenameFromUrl;
2738      exports.LinkTarget = LinkTarget;
2739      exports.hasCanvasTypedArrays = hasCanvasTypedArrays;
2740      exports.getDefaultSetting = getDefaultSetting;
2741    });
2742
2743    (function (root, factory) {
2744      {
2745        factory((root.pdfjsDisplayFontLoader = {}), root.pdfjsSharedUtil);
2746      }
2747    })(this, function (exports, sharedUtil) {
2748      var assert = sharedUtil.assert;
2749      var bytesToString = sharedUtil.bytesToString;
2750      var string32 = sharedUtil.string32;
2751      var shadow = sharedUtil.shadow;
2752      var warn = sharedUtil.warn;
2753
2754      function FontLoader(docId) {
2755        this.docId = docId;
2756        this.styleElement = null;
2757        this.nativeFontFaces = [];
2758        this.loadTestFontId = 0;
2759        this.loadingContext = {
2760          requests: [],
2761          nextRequestId: 0,
2762        };
2763      }
2764
2765      FontLoader.prototype = {
2766        insertRule: function fontLoaderInsertRule(rule) {
2767          var styleElement = this.styleElement;
2768          if (!styleElement) {
2769            styleElement = this.styleElement = document.createElement('style');
2770            styleElement.id = 'PDFJS_FONT_STYLE_TAG_' + this.docId;
2771            document.documentElement.getElementsByTagName('head')[0].appendChild(styleElement);
2772          }
2773
2774          var styleSheet = styleElement.sheet;
2775          styleSheet.insertRule(rule, styleSheet.cssRules.length);
2776        },
2777
2778        clear: function fontLoaderClear() {
2779          var styleElement = this.styleElement;
2780          if (styleElement) {
2781            styleElement.parentNode.removeChild(styleElement);
2782            styleElement = this.styleElement = null;
2783          }
2784          this.nativeFontFaces.forEach(function (nativeFontFace) {
2785            document.fonts.delete(nativeFontFace);
2786          });
2787          this.nativeFontFaces.length = 0;
2788        },
2789        get loadTestFont() {
2790          // This is a CFF font with 1 glyph for '.' that fills its entire width and
2791          // height.
2792          return shadow(
2793            this,
2794            'loadTestFont',
2795            atob(
2796              'T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQ' +
2797                'AABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwA' +
2798                'AAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbm' +
2799                'FtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAA' +
2800                'AADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6A' +
2801                'ABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAA' +
2802                'MQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAA' +
2803                'AAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAA' +
2804                'AAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQ' +
2805                'AAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMA' +
2806                'AQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAA' +
2807                'EAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAA' +
2808                'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAA' +
2809                'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
2810                'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
2811                'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
2812                'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA' +
2813                'AAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgc' +
2814                'A/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF' +
2815                'hYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQA' +
2816                'AAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAg' +
2817                'ABAAAAAAAAAAAD6AAAAAAAAA=='
2818            )
2819          );
2820        },
2821
2822        addNativeFontFace: function fontLoader_addNativeFontFace(nativeFontFace) {
2823          this.nativeFontFaces.push(nativeFontFace);
2824          document.fonts.add(nativeFontFace);
2825        },
2826
2827        bind: function fontLoaderBind(fonts, callback) {
2828          var rules = [];
2829          var fontsToLoad = [];
2830          var fontLoadPromises = [];
2831          var getNativeFontPromise = function (nativeFontFace) {
2832            // Return a promise that is always fulfilled, even when the font fails to
2833            // load.
2834            return nativeFontFace.loaded.catch(function (e) {
2835              warn('Failed to load font "' + nativeFontFace.family + '": ' + e);
2836            });
2837          };
2838          for (var i = 0, ii = fonts.length; i < ii; i++) {
2839            var font = fonts[i];
2840
2841            // Add the font to the DOM only once or skip if the font
2842            // is already loaded.
2843            if (font.attached || font.loading === false) {
2844              continue;
2845            }
2846            font.attached = true;
2847
2848            if (FontLoader.isFontLoadingAPISupported) {
2849              var nativeFontFace = font.createNativeFontFace();
2850              if (nativeFontFace) {
2851                this.addNativeFontFace(nativeFontFace);
2852                fontLoadPromises.push(getNativeFontPromise(nativeFontFace));
2853              }
2854            } else {
2855              var rule = font.createFontFaceRule();
2856              if (rule) {
2857                this.insertRule(rule);
2858                rules.push(rule);
2859                fontsToLoad.push(font);
2860              }
2861            }
2862          }
2863
2864          var request = this.queueLoadingCallback(callback);
2865          if (FontLoader.isFontLoadingAPISupported) {
2866            Promise.all(fontLoadPromises).then(function () {
2867              request.complete();
2868            });
2869          } else if (rules.length > 0 && !FontLoader.isSyncFontLoadingSupported) {
2870            this.prepareFontLoadEvent(rules, fontsToLoad, request);
2871          } else {
2872            request.complete();
2873          }
2874        },
2875
2876        queueLoadingCallback: function FontLoader_queueLoadingCallback(callback) {
2877          function LoadLoader_completeRequest() {
2878            assert(!request.end, 'completeRequest() cannot be called twice');
2879            request.end = Date.now();
2880
2881            // sending all completed requests in order how they were queued
2882            while (context.requests.length > 0 && context.requests[0].end) {
2883              var otherRequest = context.requests.shift();
2884              setTimeout(otherRequest.callback, 0);
2885            }
2886          }
2887
2888          var context = this.loadingContext;
2889          var requestId = 'pdfjs-font-loading-' + context.nextRequestId++;
2890          var request = {
2891            id: requestId,
2892            complete: LoadLoader_completeRequest,
2893            callback: callback,
2894            started: Date.now(),
2895          };
2896          context.requests.push(request);
2897          return request;
2898        },
2899
2900        prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, fonts, request) {
2901          /** Hack begin */
2902          // There's currently no event when a font has finished downloading so the
2903          // following code is a dirty hack to 'guess' when a font is
2904          // ready. It's assumed fonts are loaded in order, so add a known test
2905          // font after the desired fonts and then test for the loading of that
2906          // test font.
2907
2908          function int32(data, offset) {
2909            return (
2910              (data.charCodeAt(offset) << 24) |
2911              (data.charCodeAt(offset + 1) << 16) |
2912              (data.charCodeAt(offset + 2) << 8) |
2913              (data.charCodeAt(offset + 3) & 0xff)
2914            );
2915          }
2916
2917          function spliceString(s, offset, remove, insert) {
2918            var chunk1 = s.substr(0, offset);
2919            var chunk2 = s.substr(offset + remove);
2920            return chunk1 + insert + chunk2;
2921          }
2922
2923          var i, ii;
2924
2925          var canvas = document.createElement('canvas');
2926          canvas.width = 1;
2927          canvas.height = 1;
2928          var ctx = canvas.getContext('2d');
2929
2930          var called = 0;
2931
2932          function isFontReady(name, callback) {
2933            called++;
2934            // With setTimeout clamping this gives the font ~100ms to load.
2935            if (called > 30) {
2936              warn('Load test font never loaded.');
2937              callback();
2938              return;
2939            }
2940            ctx.font = '30px ' + name;
2941            ctx.fillText('.', 0, 20);
2942            var imageData = ctx.getImageData(0, 0, 1, 1);
2943            if (imageData.data[3] > 0) {
2944              callback();
2945              return;
2946            }
2947            setTimeout(isFontReady.bind(null, name, callback));
2948          }
2949
2950          var loadTestFontId = 'lt' + Date.now() + this.loadTestFontId++;
2951          // Chromium seems to cache fonts based on a hash of the actual font data,
2952          // so the font must be modified for each load test else it will appear to
2953          // be loaded already.
2954          // TODO: This could maybe be made faster by avoiding the btoa of the full
2955          // font by splitting it in chunks before hand and padding the font id.
2956          var data = this.loadTestFont;
2957          var COMMENT_OFFSET = 976; // has to be on 4 byte boundary (for checksum)
2958          data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, loadTestFontId);
2959          // CFF checksum is important for IE, adjusting it
2960          var CFF_CHECKSUM_OFFSET = 16;
2961          var XXXX_VALUE = 0x58585858; // the "comment" filled with 'X'
2962          var checksum = int32(data, CFF_CHECKSUM_OFFSET);
2963          for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) {
2964            checksum = (checksum - XXXX_VALUE + int32(loadTestFontId, i)) | 0;
2965          }
2966          if (i < loadTestFontId.length) {
2967            // align to 4 bytes boundary
2968            checksum = (checksum - XXXX_VALUE + int32(loadTestFontId + 'XXX', i)) | 0;
2969          }
2970          data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum));
2971
2972          var url = 'url(data:font/opentype;base64,' + btoa(data) + ');';
2973          var rule = '@font-face { font-family:"' + loadTestFontId + '";src:' + url + '}';
2974          this.insertRule(rule);
2975
2976          var names = [];
2977          for (i = 0, ii = fonts.length; i < ii; i++) {
2978            names.push(fonts[i].loadedName);
2979          }
2980          names.push(loadTestFontId);
2981
2982          var div = document.createElement('div');
2983          div.setAttribute(
2984            'style',
2985            'visibility: hidden;' + 'width: 10px; height: 10px;' + 'position: absolute; top: 0px; left: 0px;'
2986          );
2987          for (i = 0, ii = names.length; i < ii; ++i) {
2988            var span = document.createElement('span');
2989            span.textContent = 'Hi';
2990            span.style.fontFamily = names[i];
2991            div.appendChild(span);
2992          }
2993          document.body.appendChild(div);
2994
2995          isFontReady(loadTestFontId, function () {
2996            document.body.removeChild(div);
2997            request.complete();
2998          });
2999          /** Hack end */
3000        },
3001      };
3002      FontLoader.isFontLoadingAPISupported = typeof document !== 'undefined' && !!document.fonts;
3003      Object.defineProperty(FontLoader, 'isSyncFontLoadingSupported', {
3004        get: function () {
3005          if (typeof navigator === 'undefined') {
3006            // node.js - we can pretend sync font loading is supported.
3007            return shadow(FontLoader, 'isSyncFontLoadingSupported', true);
3008          }
3009
3010          var supported = false;
3011
3012          // User agent string sniffing is bad, but there is no reliable way to tell
3013          // if font is fully loaded and ready to be used with canvas.
3014          var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);
3015          if (m && m[1] >= 14) {
3016            supported = true;
3017          }
3018          return shadow(FontLoader, 'isSyncFontLoadingSupported', supported);
3019        },
3020        enumerable: true,
3021        configurable: true,
3022      });
3023
3024      var IsEvalSupportedCached = {
3025        get value() {
3026          return shadow(this, 'value', sharedUtil.isEvalSupported());
3027        },
3028      };
3029
3030      var FontFaceObject = (function FontFaceObjectClosure() {
3031        function FontFaceObject(translatedData, options) {
3032          this.compiledGlyphs = Object.create(null);
3033          // importing translated data
3034          for (var i in translatedData) {
3035            this[i] = translatedData[i];
3036          }
3037          this.options = options;
3038        }
3039
3040        FontFaceObject.prototype = {
3041          createNativeFontFace: function FontFaceObject_createNativeFontFace() {
3042            if (!this.data) {
3043              return null;
3044            }
3045
3046            if (this.options.disableFontFace) {
3047              this.disableFontFace = true;
3048              return null;
3049            }
3050
3051            var nativeFontFace = new FontFace(this.loadedName, this.data, {});
3052
3053            if (this.options.fontRegistry) {
3054              this.options.fontRegistry.registerFont(this);
3055            }
3056            return nativeFontFace;
3057          },
3058
3059          createFontFaceRule: function FontFaceObject_createFontFaceRule() {
3060            if (!this.data) {
3061              return null;
3062            }
3063
3064            if (this.options.disableFontFace) {
3065              this.disableFontFace = true;
3066              return null;
3067            }
3068
3069            var data = bytesToString(new Uint8Array(this.data));
3070            var fontName = this.loadedName;
3071
3072            // Add the font-face rule to the document
3073            var url = 'url(data:' + this.mimetype + ';base64,' + btoa(data) + ');';
3074            var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}';
3075
3076            if (this.options.fontRegistry) {
3077              this.options.fontRegistry.registerFont(this, url);
3078            }
3079
3080            return rule;
3081          },
3082
3083          getPathGenerator: function FontFaceObject_getPathGenerator(objs, character) {
3084            if (!(character in this.compiledGlyphs)) {
3085              var cmds = objs.get(this.loadedName + '_path_' + character);
3086              var current, i, len;
3087
3088              // If we can, compile cmds into JS for MAXIMUM SPEED
3089              if (this.options.isEvalSupported && IsEvalSupportedCached.value) {
3090                var args,
3091                  js = '';
3092                for (i = 0, len = cmds.length; i < len; i++) {
3093                  current = cmds[i];
3094
3095                  if (current.args !== undefined) {
3096                    args = current.args.join(',');
3097                  } else {
3098                    args = '';
3099                  }
3100
3101                  js += 'c.' + current.cmd + '(' + args + ');\n';
3102                }
3103                /* jshint -W054 */
3104                this.compiledGlyphs[character] = new Function('c', 'size', js);
3105              } else {
3106                // But fall back on using Function.prototype.apply() if we're
3107                // blocked from using eval() for whatever reason (like CSP policies)
3108                this.compiledGlyphs[character] = function (c, size) {
3109                  for (i = 0, len = cmds.length; i < len; i++) {
3110                    current = cmds[i];
3111
3112                    if (current.cmd === 'scale') {
3113                      current.args = [size, -size];
3114                    }
3115
3116                    c[current.cmd].apply(c, current.args);
3117                  }
3118                };
3119              }
3120            }
3121            return this.compiledGlyphs[character];
3122          },
3123        };
3124        return FontFaceObject;
3125      })();
3126
3127      exports.FontFaceObject = FontFaceObject;
3128      exports.FontLoader = FontLoader;
3129    });
3130
3131    (function (root, factory) {
3132      {
3133        factory((root.pdfjsDisplayMetadata = {}), root.pdfjsSharedUtil);
3134      }
3135    })(this, function (exports, sharedUtil) {
3136      var error = sharedUtil.error;
3137
3138      function fixMetadata(meta) {
3139        return meta.replace(/>\\376\\377([^<]+)/g, function (all, codes) {
3140          var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g, function (code, d1, d2, d3) {
3141            return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
3142          });
3143          var chars = '';
3144          for (var i = 0; i < bytes.length; i += 2) {
3145            var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
3146            chars +=
3147              code >= 32 && code < 127 && code !== 60 && code !== 62 && code !== 38 && false
3148                ? String.fromCharCode(code)
3149                : '&#x' + (0x10000 + code).toString(16).substring(1) + ';';
3150          }
3151          return '>' + chars;
3152        });
3153      }
3154
3155      function Metadata(meta) {
3156        if (typeof meta === 'string') {
3157          // Ghostscript produces invalid metadata
3158          meta = fixMetadata(meta);
3159
3160          var parser = new DOMParser();
3161          meta = parser.parseFromString(meta, 'application/xml');
3162        } else if (!(meta instanceof Document)) {
3163          error('Metadata: Invalid metadata object');
3164        }
3165
3166        this.metaDocument = meta;
3167        this.metadata = Object.create(null);
3168        this.parse();
3169      }
3170
3171      Metadata.prototype = {
3172        parse: function Metadata_parse() {
3173          var doc = this.metaDocument;
3174          var rdf = doc.documentElement;
3175
3176          if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
3177            // Wrapped in <xmpmeta>
3178            rdf = rdf.firstChild;
3179            while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
3180              rdf = rdf.nextSibling;
3181            }
3182          }
3183
3184          var nodeName = rdf ? rdf.nodeName.toLowerCase() : null;
3185          if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes()) {
3186            return;
3187          }
3188
3189          var children = rdf.childNodes,
3190            desc,
3191            entry,
3192            name,
3193            i,
3194            ii,
3195            length,
3196            iLength;
3197          for (i = 0, length = children.length; i < length; i++) {
3198            desc = children[i];
3199            if (desc.nodeName.toLowerCase() !== 'rdf:description') {
3200              continue;
3201            }
3202
3203            for (ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) {
3204              if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text') {
3205                entry = desc.childNodes[ii];
3206                name = entry.nodeName.toLowerCase();
3207                this.metadata[name] = entry.textContent.trim();
3208              }
3209            }
3210          }
3211        },
3212
3213        get: function Metadata_get(name) {
3214          return this.metadata[name] || null;
3215        },
3216
3217        has: function Metadata_has(name) {
3218          return typeof this.metadata[name] !== 'undefined';
3219        },
3220      };
3221
3222      exports.Metadata = Metadata;
3223    });
3224
3225    (function (root, factory) {
3226      {
3227        factory((root.pdfjsDisplaySVG = {}), root.pdfjsSharedUtil);
3228      }
3229    })(this, function (exports, sharedUtil) {
3230      var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX;
3231      var IDENTITY_MATRIX = sharedUtil.IDENTITY_MATRIX;
3232      var ImageKind = sharedUtil.ImageKind;
3233      var OPS = sharedUtil.OPS;
3234      var Util = sharedUtil.Util;
3235      var isNum = sharedUtil.isNum;
3236      var isArray = sharedUtil.isArray;
3237      var warn = sharedUtil.warn;
3238      var createObjectURL = sharedUtil.createObjectURL;
3239
3240      var SVG_DEFAULTS = {
3241        fontStyle: 'normal',
3242        fontWeight: 'normal',
3243        fillColor: '#000000',
3244      };
3245
3246      var convertImgDataToPng = (function convertImgDataToPngClosure() {
3247        var PNG_HEADER = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
3248
3249        var CHUNK_WRAPPER_SIZE = 12;
3250
3251        var crcTable = new Int32Array(256);
3252        for (var i = 0; i < 256; i++) {
3253          var c = i;
3254          for (var h = 0; h < 8; h++) {
3255            if (c & 1) {
3256              c = 0xedb88320 ^ ((c >> 1) & 0x7fffffff);
3257            } else {
3258              c = (c >> 1) & 0x7fffffff;
3259            }
3260          }
3261          crcTable[i] = c;
3262        }
3263
3264        function crc32(data, start, end) {
3265          var crc = -1;
3266          for (var i = start; i < end; i++) {
3267            var a = (crc ^ data[i]) & 0xff;
vendor: 4,290 bytes, lines 3268-3402
3268            var b = crcTable[a];
3269            crc = (crc >>> 8) ^ b;
3270          }
3271          return crc ^ -1;
3272        }
3273
3274        function writePngChunk(type, body, data, offset) {
3275          var p = offset;
3276          var len = body.length;
3277
3278          data[p] = (len >> 24) & 0xff;
3279          data[p + 1] = (len >> 16) & 0xff;
3280          data[p + 2] = (len >> 8) & 0xff;
3281          data[p + 3] = len & 0xff;
3282          p += 4;
3283
3284          data[p] = type.charCodeAt(0) & 0xff;
3285          data[p + 1] = type.charCodeAt(1) & 0xff;
3286          data[p + 2] = type.charCodeAt(2) & 0xff;
3287          data[p + 3] = type.charCodeAt(3) & 0xff;
3288          p += 4;
3289
3290          data.set(body, p);
3291          p += body.length;
3292
3293          var crc = crc32(data, offset + 4, p);
3294
3295          data[p] = (crc >> 24) & 0xff;
3296          data[p + 1] = (crc >> 16) & 0xff;
3297          data[p + 2] = (crc >> 8) & 0xff;
3298          data[p + 3] = crc & 0xff;
3299        }
3300
3301        function adler32(data, start, end) {
3302          var a = 1;
3303          var b = 0;
3304          for (var i = start; i < end; ++i) {
3305            a = (a + (data[i] & 0xff)) % 65521;
3306            b = (b + a) % 65521;
3307          }
3308          return (b << 16) | a;
3309        }
3310
3311        function encode(imgData, kind, forceDataSchema) {
3312          var width = imgData.width;
3313          var height = imgData.height;
3314          var bitDepth, colorType, lineSize;
3315          var bytes = imgData.data;
3316
3317          switch (kind) {
3318            case ImageKind.GRAYSCALE_1BPP:
3319              colorType = 0;
3320              bitDepth = 1;
3321              lineSize = (width + 7) >> 3;
3322              break;
3323            case ImageKind.RGB_24BPP:
3324              colorType = 2;
3325              bitDepth = 8;
3326              lineSize = width * 3;
3327              break;
3328            case ImageKind.RGBA_32BPP:
3329              colorType = 6;
3330              bitDepth = 8;
3331              lineSize = width * 4;
3332              break;
3333            default:
3334              throw new Error('invalid format');
3335          }
3336
3337          // prefix every row with predictor 0
3338          var literals = new Uint8Array((1 + lineSize) * height);
3339          var offsetLiterals = 0,
3340            offsetBytes = 0;
3341          var y, i;
3342          for (y = 0; y < height; ++y) {
3343            literals[offsetLiterals++] = 0; // no prediction
3344            literals.set(bytes.subarray(offsetBytes, offsetBytes + lineSize), offsetLiterals);
3345            offsetBytes += lineSize;
3346            offsetLiterals += lineSize;
3347          }
3348
3349          if (kind === ImageKind.GRAYSCALE_1BPP) {
3350            // inverting for B/W
3351            offsetLiterals = 0;
3352            for (y = 0; y < height; y++) {
3353              offsetLiterals++; // skipping predictor
3354              for (i = 0; i < lineSize; i++) {
3355                literals[offsetLiterals++] ^= 0xff;
3356              }
3357            }
3358          }
3359
3360          var ihdr = new Uint8Array([
3361            (width >> 24) & 0xff,
3362            (width >> 16) & 0xff,
3363            (width >> 8) & 0xff,
3364            width & 0xff,
3365            (height >> 24) & 0xff,
3366            (height >> 16) & 0xff,
3367            (height >> 8) & 0xff,
3368            height & 0xff,
3369            bitDepth, // bit depth
3370            colorType, // color type
3371            0x00, // compression method
3372            0x00, // filter method
3373            0x00, // interlace method
3374          ]);
3375
3376          var len = literals.length;
3377          var maxBlockLength = 0xffff;
3378
3379          var deflateBlocks = Math.ceil(len / maxBlockLength);
3380          var idat = new Uint8Array(2 + len + deflateBlocks * 5 + 4);
3381          var pi = 0;
3382          idat[pi++] = 0x78; // compression method and flags
3383          idat[pi++] = 0x9c; // flags
3384
3385          var pos = 0;
3386          while (len > maxBlockLength) {
3387            // writing non-final DEFLATE blocks type 0 and length of 65535
3388            idat[pi++] = 0x00;
3389            idat[pi++] = 0xff;
3390            idat[pi++] = 0xff;
3391            idat[pi++] = 0x00;
3392            idat[pi++] = 0x00;
3393            idat.set(literals.subarray(pos, pos + maxBlockLength), pi);
3394            pi += maxBlockLength;
3395            pos += maxBlockLength;
3396            len -= maxBlockLength;
3397          }
3398
3399          // writing non-final DEFLATE blocks type 0
3400          idat[pi++] = 0x01;
3401          idat[pi++] = len & 0xff;
3402          idat[pi++] = (len >> 8) & 0xff;
3403          idat[pi++] = ~len & 0xffff & 0xff;
3404          idat[pi++] = ((~len & 0xffff) >> 8) & 0xff;
3405          idat.set(literals.subarray(pos), pi);
3406          pi += literals.length - pos;
3407
3408          var adler = adler32(literals, 0, literals.length); // checksum
3409          idat[pi++] = (adler >> 24) & 0xff;
3410          idat[pi++] = (adler >> 16) & 0xff;
3411          idat[pi++] = (adler >> 8) & 0xff;
3412          idat[pi++] = adler & 0xff;
3413
3414          // PNG will consists: header, IHDR+data, IDAT+data, and IEND.
3415          var pngLength = PNG_HEADER.length + CHUNK_WRAPPER_SIZE * 3 + ihdr.length + idat.length;
3416          var data = new Uint8Array(pngLength);
3417          var offset = 0;
3418          data.set(PNG_HEADER, offset);
3419          offset += PNG_HEADER.length;
3420          writePngChunk('IHDR', ihdr, data, offset);
3421          offset += CHUNK_WRAPPER_SIZE + ihdr.length;
3422          writePngChunk('IDATA', idat, data, offset);
3423          offset += CHUNK_WRAPPER_SIZE + idat.length;
3424          writePngChunk('IEND', new Uint8Array(0), data, offset);
3425
3426          return createObjectURL(data, 'image/png', forceDataSchema);
3427        }
3428
3429        return function convertImgDataToPng(imgData, forceDataSchema) {
3430          var kind = imgData.kind === undefined ? ImageKind.GRAYSCALE_1BPP : imgData.kind;
3431          return encode(imgData, kind, forceDataSchema);
3432        };
3433      })();
3434
3435      var SVGExtraState = (function SVGExtraStateClosure() {
3436        function SVGExtraState() {
3437          this.fontSizeScale = 1;
3438          this.fontWeight = SVG_DEFAULTS.fontWeight;
3439          this.fontSize = 0;
3440
3441          this.textMatrix = IDENTITY_MATRIX;
3442          this.fontMatrix = FONT_IDENTITY_MATRIX;
3443          this.leading = 0;
3444
3445          // Current point (in user coordinates)
3446          this.x = 0;
3447          this.y = 0;
3448
3449          // Start of text line (in text coordinates)
3450          this.lineX = 0;
3451          this.lineY = 0;
3452
3453          // Character and word spacing
3454          this.charSpacing = 0;
3455          this.wordSpacing = 0;
3456          this.textHScale = 1;
3457          this.textRise = 0;
3458
3459          // Default foreground and background colors
3460          this.fillColor = SVG_DEFAULTS.fillColor;
3461          this.strokeColor = '#000000';
3462
3463          this.fillAlpha = 1;
3464          this.strokeAlpha = 1;
3465          this.lineWidth = 1;
3466          this.lineJoin = '';
3467          this.lineCap = '';
3468          this.miterLimit = 0;
3469
3470          this.dashArray = [];
3471          this.dashPhase = 0;
3472
3473          this.dependencies = [];
3474
3475          // Clipping
3476          this.clipId = '';
3477          this.pendingClip = false;
3478
3479          this.maskId = '';
3480        }
3481
3482        SVGExtraState.prototype = {
3483          clone: function SVGExtraState_clone() {
3484            return Object.create(this);
3485          },
3486          setCurrentPoint: function SVGExtraState_setCurrentPoint(x, y) {
3487            this.x = x;
3488            this.y = y;
3489          },
3490        };
3491        return SVGExtraState;
3492      })();
3493
3494      var SVGGraphics = (function SVGGraphicsClosure() {
3495        function createScratchSVG(width, height) {
3496          var NS = 'http://www.w3.org/2000/svg';
3497          var svg = document.createElementNS(NS, 'svg:svg');
3498          svg.setAttributeNS(null, 'version', '1.1');
3499          svg.setAttributeNS(null, 'width', width + 'px');
3500          svg.setAttributeNS(null, 'height', height + 'px');
3501          svg.setAttributeNS(null, 'viewBox', '0 0 ' + width + ' ' + height);
3502          return svg;
3503        }
3504
3505        function opListToTree(opList) {
3506          var opTree = [];
3507          var tmp = [];
3508          var opListLen = opList.length;
3509
3510          for (var x = 0; x < opListLen; x++) {
3511            if (opList[x].fn === 'save') {
3512              opTree.push({ fnId: 92, fn: 'group', items: [] });
3513              tmp.push(opTree);
3514              opTree = opTree[opTree.length - 1].items;
3515              continue;
3516            }
3517
3518            if (opList[x].fn === 'restore') {
3519              opTree = tmp.pop();
3520            } else {
3521              opTree.push(opList[x]);
3522            }
3523          }
3524          return opTree;
3525        }
3526
3527        /**
3528         * Formats float number.
3529         * @param value {number} number to format.
3530         * @returns {string}
3531         */
3532        function pf(value) {
3533          if (value === (value | 0)) {
3534            // integer number
3535            return value.toString();
3536          }
3537          var s = value.toFixed(10);
3538          var i = s.length - 1;
3539          if (s[i] !== '0') {
3540            return s;
3541          }
3542          // removing trailing zeros
3543          do {
3544            i--;
3545          } while (s[i] === '0');
3546          return s.substr(0, s[i] === '.' ? i : i + 1);
3547        }
3548
3549        /**
3550         * Formats transform matrix. The standard rotation, scale and translate
3551         * matrices are replaced by their shorter forms, and for identity matrix
3552         * returns empty string to save the memory.
3553         * @param m {Array} matrix to format.
3554         * @returns {string}
3555         */
3556        function pm(m) {
3557          if (m[4] === 0 && m[5] === 0) {
3558            if (m[1] === 0 && m[2] === 0) {
3559              if (m[0] === 1 && m[3] === 1) {
3560                return '';
3561              }
3562              return 'scale(' + pf(m[0]) + ' ' + pf(m[3]) + ')';
3563            }
3564            if (m[0] === m[3] && m[1] === -m[2]) {
3565              var a = (Math.acos(m[0]) * 180) / Math.PI;
3566              return 'rotate(' + pf(a) + ')';
3567            }
3568          } else {
3569            if (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1) {
3570              return 'translate(' + pf(m[4]) + ' ' + pf(m[5]) + ')';
3571            }
3572          }
3573          return (
3574            'matrix(' +
3575            pf(m[0]) +
3576            ' ' +
3577            pf(m[1]) +
3578            ' ' +
3579            pf(m[2]) +
3580            ' ' +
3581            pf(m[3]) +
3582            ' ' +
3583            pf(m[4]) +
3584            ' ' +
vendor: 31,271 bytes, lines 3585-4368
3585            pf(m[5]) +
3586            ')'
3587          );
3588        }
3589
3590        function SVGGraphics(commonObjs, objs, forceDataSchema) {
3591          this.current = new SVGExtraState();
3592          this.transformMatrix = IDENTITY_MATRIX; // Graphics state matrix
3593          this.transformStack = [];
3594          this.extraStack = [];
3595          this.commonObjs = commonObjs;
3596          this.objs = objs;
3597          this.pendingEOFill = false;
3598
3599          this.embedFonts = false;
3600          this.embeddedFonts = Object.create(null);
3601          this.cssStyle = null;
3602          this.forceDataSchema = !!forceDataSchema;
3603        }
3604
3605        var NS = 'http://www.w3.org/2000/svg';
3606        var XML_NS = 'http://www.w3.org/XML/1998/namespace';
3607        var XLINK_NS = 'http://www.w3.org/1999/xlink';
3608        var LINE_CAP_STYLES = ['butt', 'round', 'square'];
3609        var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
3610        var clipCount = 0;
3611        var maskCount = 0;
3612
3613        SVGGraphics.prototype = {
3614          save: function SVGGraphics_save() {
3615            this.transformStack.push(this.transformMatrix);
3616            var old = this.current;
3617            this.extraStack.push(old);
3618            this.current = old.clone();
3619          },
3620
3621          restore: function SVGGraphics_restore() {
3622            this.transformMatrix = this.transformStack.pop();
3623            this.current = this.extraStack.pop();
3624
3625            this.tgrp = document.createElementNS(NS, 'svg:g');
3626            this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix));
3627            this.pgrp.appendChild(this.tgrp);
3628          },
3629
3630          group: function SVGGraphics_group(items) {
3631            this.save();
3632            this.executeOpTree(items);
3633            this.restore();
3634          },
3635
3636          loadDependencies: function SVGGraphics_loadDependencies(operatorList) {
3637            var fnArray = operatorList.fnArray;
3638            var fnArrayLen = fnArray.length;
3639            var argsArray = operatorList.argsArray;
3640
3641            var self = this;
3642            for (var i = 0; i < fnArrayLen; i++) {
3643              if (OPS.dependency === fnArray[i]) {
3644                var deps = argsArray[i];
3645                for (var n = 0, nn = deps.length; n < nn; n++) {
3646                  var obj = deps[n];
3647                  var common = obj.substring(0, 2) === 'g_';
3648                  var promise;
3649                  if (common) {
3650                    promise = new Promise(function (resolve) {
3651                      self.commonObjs.get(obj, resolve);
3652                    });
3653                  } else {
3654                    promise = new Promise(function (resolve) {
3655                      self.objs.get(obj, resolve);
3656                    });
3657                  }
3658                  this.current.dependencies.push(promise);
3659                }
3660              }
3661            }
3662            return Promise.all(this.current.dependencies);
3663          },
3664
3665          transform: function SVGGraphics_transform(a, b, c, d, e, f) {
3666            var transformMatrix = [a, b, c, d, e, f];
3667            this.transformMatrix = Util.transform(this.transformMatrix, transformMatrix);
3668
3669            this.tgrp = document.createElementNS(NS, 'svg:g');
3670            this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix));
3671          },
3672
3673          getSVG: function SVGGraphics_getSVG(operatorList, viewport) {
3674            this.svg = createScratchSVG(viewport.width, viewport.height);
3675            this.viewport = viewport;
3676
3677            return this.loadDependencies(operatorList).then(
3678              function () {
3679                this.transformMatrix = IDENTITY_MATRIX;
3680                this.pgrp = document.createElementNS(NS, 'svg:g'); // Parent group
3681                this.pgrp.setAttributeNS(null, 'transform', pm(viewport.transform));
3682                this.tgrp = document.createElementNS(NS, 'svg:g'); // Transform group
3683                this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix));
3684                this.defs = document.createElementNS(NS, 'svg:defs');
3685                this.pgrp.appendChild(this.defs);
3686                this.pgrp.appendChild(this.tgrp);
3687                this.svg.appendChild(this.pgrp);
3688                var opTree = this.convertOpList(operatorList);
3689                this.executeOpTree(opTree);
3690                return this.svg;
3691              }.bind(this)
3692            );
3693          },
3694
3695          convertOpList: function SVGGraphics_convertOpList(operatorList) {
3696            var argsArray = operatorList.argsArray;
3697            var fnArray = operatorList.fnArray;
3698            var fnArrayLen = fnArray.length;
3699            var REVOPS = [];
3700            var opList = [];
3701
3702            for (var op in OPS) {
3703              REVOPS[OPS[op]] = op;
3704            }
3705
3706            for (var x = 0; x < fnArrayLen; x++) {
3707              var fnId = fnArray[x];
3708              opList.push({ fnId: fnId, fn: REVOPS[fnId], args: argsArray[x] });
3709            }
3710            return opListToTree(opList);
3711          },
3712
3713          executeOpTree: function SVGGraphics_executeOpTree(opTree) {
3714            var opTreeLen = opTree.length;
3715            for (var x = 0; x < opTreeLen; x++) {
3716              var fn = opTree[x].fn;
3717              var fnId = opTree[x].fnId;
3718              var args = opTree[x].args;
3719
3720              switch (fnId | 0) {
3721                case OPS.beginText:
3722                  this.beginText();
3723                  break;
3724                case OPS.setLeading:
3725                  this.setLeading(args);
3726                  break;
3727                case OPS.setLeadingMoveText:
3728                  this.setLeadingMoveText(args[0], args[1]);
3729                  break;
3730                case OPS.setFont:
3731                  this.setFont(args);
3732                  break;
3733                case OPS.showText:
3734                  this.showText(args[0]);
3735                  break;
3736                case OPS.showSpacedText:
3737                  this.showText(args[0]);
3738                  break;
3739                case OPS.endText:
3740                  this.endText();
3741                  break;
3742                case OPS.moveText:
3743                  this.moveText(args[0], args[1]);
3744                  break;
3745                case OPS.setCharSpacing:
3746                  this.setCharSpacing(args[0]);
3747                  break;
3748                case OPS.setWordSpacing:
3749                  this.setWordSpacing(args[0]);
3750                  break;
3751                case OPS.setHScale:
3752                  this.setHScale(args[0]);
3753                  break;
3754                case OPS.setTextMatrix:
3755                  this.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);
3756                  break;
3757                case OPS.setLineWidth:
3758                  this.setLineWidth(args[0]);
3759                  break;
3760                case OPS.setLineJoin:
3761                  this.setLineJoin(args[0]);
3762                  break;
3763                case OPS.setLineCap:
3764                  this.setLineCap(args[0]);
3765                  break;
3766                case OPS.setMiterLimit:
3767                  this.setMiterLimit(args[0]);
3768                  break;
3769                case OPS.setFillRGBColor:
3770                  this.setFillRGBColor(args[0], args[1], args[2]);
3771                  break;
3772                case OPS.setStrokeRGBColor:
3773                  this.setStrokeRGBColor(args[0], args[1], args[2]);
3774                  break;
3775                case OPS.setDash:
3776                  this.setDash(args[0], args[1]);
3777                  break;
3778                case OPS.setGState:
3779                  this.setGState(args[0]);
3780                  break;
3781                case OPS.fill:
3782                  this.fill();
3783                  break;
3784                case OPS.eoFill:
3785                  this.eoFill();
3786                  break;
3787                case OPS.stroke:
3788                  this.stroke();
3789                  break;
3790                case OPS.fillStroke:
3791                  this.fillStroke();
3792                  break;
3793                case OPS.eoFillStroke:
3794                  this.eoFillStroke();
3795                  break;
3796                case OPS.clip:
3797                  this.clip('nonzero');
3798                  break;
3799                case OPS.eoClip:
3800                  this.clip('evenodd');
3801                  break;
3802                case OPS.paintSolidColorImageMask:
3803                  this.paintSolidColorImageMask();
3804                  break;
3805                case OPS.paintJpegXObject:
3806                  this.paintJpegXObject(args[0], args[1], args[2]);
3807                  break;
3808                case OPS.paintImageXObject:
3809                  this.paintImageXObject(args[0]);
3810                  break;
3811                case OPS.paintInlineImageXObject:
3812                  this.paintInlineImageXObject(args[0]);
3813                  break;
3814                case OPS.paintImageMaskXObject:
3815                  this.paintImageMaskXObject(args[0]);
3816                  break;
3817                case OPS.paintFormXObjectBegin:
3818                  this.paintFormXObjectBegin(args[0], args[1]);
3819                  break;
3820                case OPS.paintFormXObjectEnd:
3821                  this.paintFormXObjectEnd();
3822                  break;
3823                case OPS.closePath:
3824                  this.closePath();
3825                  break;
3826                case OPS.closeStroke:
3827                  this.closeStroke();
3828                  break;
3829                case OPS.closeFillStroke:
3830                  this.closeFillStroke();
3831                  break;
3832                case OPS.nextLine:
3833                  this.nextLine();
3834                  break;
3835                case OPS.transform:
3836                  this.transform(args[0], args[1], args[2], args[3], args[4], args[5]);
3837                  break;
3838                case OPS.constructPath:
3839                  this.constructPath(args[0], args[1]);
3840                  break;
3841                case OPS.endPath:
3842                  this.endPath();
3843                  break;
3844                case 92:
3845                  this.group(opTree[x].items);
3846                  break;
3847                default:
3848                  warn('Unimplemented method ' + fn);
3849                  break;
3850              }
3851            }
3852          },
3853
3854          setWordSpacing: function SVGGraphics_setWordSpacing(wordSpacing) {
3855            this.current.wordSpacing = wordSpacing;
3856          },
3857
3858          setCharSpacing: function SVGGraphics_setCharSpacing(charSpacing) {
3859            this.current.charSpacing = charSpacing;
3860          },
3861
3862          nextLine: function SVGGraphics_nextLine() {
3863            this.moveText(0, this.current.leading);
3864          },
3865
3866          setTextMatrix: function SVGGraphics_setTextMatrix(a, b, c, d, e, f) {
3867            var current = this.current;
3868            this.current.textMatrix = this.current.lineMatrix = [a, b, c, d, e, f];
3869
3870            this.current.x = this.current.lineX = 0;
3871            this.current.y = this.current.lineY = 0;
3872
3873            current.xcoords = [];
3874            current.tspan = document.createElementNS(NS, 'svg:tspan');
3875            current.tspan.setAttributeNS(null, 'font-family', current.fontFamily);
3876            current.tspan.setAttributeNS(null, 'font-size', pf(current.fontSize) + 'px');
3877            current.tspan.setAttributeNS(null, 'y', pf(-current.y));
3878
3879            current.txtElement = document.createElementNS(NS, 'svg:text');
3880            current.txtElement.appendChild(current.tspan);
3881          },
3882
3883          beginText: function SVGGraphics_beginText() {
3884            this.current.x = this.current.lineX = 0;
3885            this.current.y = this.current.lineY = 0;
3886            this.current.textMatrix = IDENTITY_MATRIX;
3887            this.current.lineMatrix = IDENTITY_MATRIX;
3888            this.current.tspan = document.createElementNS(NS, 'svg:tspan');
3889            this.current.txtElement = document.createElementNS(NS, 'svg:text');
3890            this.current.txtgrp = document.createElementNS(NS, 'svg:g');
3891            this.current.xcoords = [];
3892          },
3893
3894          moveText: function SVGGraphics_moveText(x, y) {
3895            var current = this.current;
3896            this.current.x = this.current.lineX += x;
3897            this.current.y = this.current.lineY += y;
3898
3899            current.xcoords = [];
3900            current.tspan = document.createElementNS(NS, 'svg:tspan');
3901            current.tspan.setAttributeNS(null, 'font-family', current.fontFamily);
3902            current.tspan.setAttributeNS(null, 'font-size', pf(current.fontSize) + 'px');
3903            current.tspan.setAttributeNS(null, 'y', pf(-current.y));
3904          },
3905
3906          showText: function SVGGraphics_showText(glyphs) {
3907            var current = this.current;
3908            var font = current.font;
3909            var fontSize = current.fontSize;
3910
3911            if (fontSize === 0) {
3912              return;
3913            }
3914
3915            var charSpacing = current.charSpacing;
3916            var wordSpacing = current.wordSpacing;
3917            var fontDirection = current.fontDirection;
3918            var textHScale = current.textHScale * fontDirection;
3919            var glyphsLength = glyphs.length;
3920            var vertical = font.vertical;
3921            var widthAdvanceScale = fontSize * current.fontMatrix[0];
3922
3923            var x = 0,
3924              i;
3925            for (i = 0; i < glyphsLength; ++i) {
3926              var glyph = glyphs[i];
3927              if (glyph === null) {
3928                // word break
3929                x += fontDirection * wordSpacing;
3930                continue;
3931              } else if (isNum(glyph)) {
3932                x += -glyph * fontSize * 0.001;
3933                continue;
3934              }
3935              current.xcoords.push(current.x + x * textHScale);
3936
3937              var width = glyph.width;
3938              var character = glyph.fontChar;
3939              var charWidth = width * widthAdvanceScale + charSpacing * fontDirection;
3940              x += charWidth;
3941
3942              current.tspan.textContent += character;
3943            }
3944            if (vertical) {
3945              current.y -= x * textHScale;
3946            } else {
3947              current.x += x * textHScale;
3948            }
3949
3950            current.tspan.setAttributeNS(null, 'x', current.xcoords.map(pf).join(' '));
3951            current.tspan.setAttributeNS(null, 'y', pf(-current.y));
3952            current.tspan.setAttributeNS(null, 'font-family', current.fontFamily);
3953            current.tspan.setAttributeNS(null, 'font-size', pf(current.fontSize) + 'px');
3954            if (current.fontStyle !== SVG_DEFAULTS.fontStyle) {
3955              current.tspan.setAttributeNS(null, 'font-style', current.fontStyle);
3956            }
3957            if (current.fontWeight !== SVG_DEFAULTS.fontWeight) {
3958              current.tspan.setAttributeNS(null, 'font-weight', current.fontWeight);
3959            }
3960            if (current.fillColor !== SVG_DEFAULTS.fillColor) {
3961              current.tspan.setAttributeNS(null, 'fill', current.fillColor);
3962            }
3963
3964            current.txtElement.setAttributeNS(null, 'transform', pm(current.textMatrix) + ' scale(1, -1)');
3965            current.txtElement.setAttributeNS(XML_NS, 'xml:space', 'preserve');
3966            current.txtElement.appendChild(current.tspan);
3967            current.txtgrp.appendChild(current.txtElement);
3968
3969            this.tgrp.appendChild(current.txtElement);
3970          },
3971
3972          setLeadingMoveText: function SVGGraphics_setLeadingMoveText(x, y) {
3973            this.setLeading(-y);
3974            this.moveText(x, y);
3975          },
3976
3977          addFontStyle: function SVGGraphics_addFontStyle(fontObj) {
3978            if (!this.cssStyle) {
3979              this.cssStyle = document.createElementNS(NS, 'svg:style');
3980              this.cssStyle.setAttributeNS(null, 'type', 'text/css');
3981              this.defs.appendChild(this.cssStyle);
3982            }
3983
3984            var url = createObjectURL(fontObj.data, fontObj.mimetype, this.forceDataSchema);
3985            this.cssStyle.textContent +=
3986              '@font-face { font-family: "' + fontObj.loadedName + '";' + ' src: url(' + url + '); }\n';
3987          },
3988
3989          setFont: function SVGGraphics_setFont(details) {
3990            var current = this.current;
3991            var fontObj = this.commonObjs.get(details[0]);
3992            var size = details[1];
3993            this.current.font = fontObj;
3994
3995            if (this.embedFonts && fontObj.data && !this.embeddedFonts[fontObj.loadedName]) {
3996              this.addFontStyle(fontObj);
3997              this.embeddedFonts[fontObj.loadedName] = fontObj;
3998            }
3999
4000            current.fontMatrix = fontObj.fontMatrix ? fontObj.fontMatrix : FONT_IDENTITY_MATRIX;
4001
4002            var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') : fontObj.bold ? 'bold' : 'normal';
4003            var italic = fontObj.italic ? 'italic' : 'normal';
4004
4005            if (size < 0) {
4006              size = -size;
4007              current.fontDirection = -1;
4008            } else {
4009              current.fontDirection = 1;
4010            }
4011            current.fontSize = size;
4012            current.fontFamily = fontObj.loadedName;
4013            current.fontWeight = bold;
4014            current.fontStyle = italic;
4015
4016            current.tspan = document.createElementNS(NS, 'svg:tspan');
4017            current.tspan.setAttributeNS(null, 'y', pf(-current.y));
4018            current.xcoords = [];
4019          },
4020
4021          endText: function SVGGraphics_endText() {
4022            if (this.current.pendingClip) {
4023              this.cgrp.appendChild(this.tgrp);
4024              this.pgrp.appendChild(this.cgrp);
4025            } else {
4026              this.pgrp.appendChild(this.tgrp);
4027            }
4028            this.tgrp = document.createElementNS(NS, 'svg:g');
4029            this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix));
4030          },
4031
4032          // Path properties
4033          setLineWidth: function SVGGraphics_setLineWidth(width) {
4034            this.current.lineWidth = width;
4035          },
4036          setLineCap: function SVGGraphics_setLineCap(style) {
4037            this.current.lineCap = LINE_CAP_STYLES[style];
4038          },
4039          setLineJoin: function SVGGraphics_setLineJoin(style) {
4040            this.current.lineJoin = LINE_JOIN_STYLES[style];
4041          },
4042          setMiterLimit: function SVGGraphics_setMiterLimit(limit) {
4043            this.current.miterLimit = limit;
4044          },
4045          setStrokeRGBColor: function SVGGraphics_setStrokeRGBColor(r, g, b) {
4046            var color = Util.makeCssRgb(r, g, b);
4047            this.current.strokeColor = color;
4048          },
4049          setFillRGBColor: function SVGGraphics_setFillRGBColor(r, g, b) {
4050            var color = Util.makeCssRgb(r, g, b);
4051            this.current.fillColor = color;
4052            this.current.tspan = document.createElementNS(NS, 'svg:tspan');
4053            this.current.xcoords = [];
4054          },
4055          setDash: function SVGGraphics_setDash(dashArray, dashPhase) {
4056            this.current.dashArray = dashArray;
4057            this.current.dashPhase = dashPhase;
4058          },
4059
4060          constructPath: function SVGGraphics_constructPath(ops, args) {
4061            var current = this.current;
4062            var x = current.x,
4063              y = current.y;
4064            current.path = document.createElementNS(NS, 'svg:path');
4065            var d = [];
4066            var opLength = ops.length;
4067
4068            for (var i = 0, j = 0; i < opLength; i++) {
4069              switch (ops[i] | 0) {
4070                case OPS.rectangle:
4071                  x = args[j++];
4072                  y = args[j++];
4073                  var width = args[j++];
4074                  var height = args[j++];
4075                  var xw = x + width;
4076                  var yh = y + height;
4077                  d.push('M', pf(x), pf(y), 'L', pf(xw), pf(y), 'L', pf(xw), pf(yh), 'L', pf(x), pf(yh), 'Z');
4078                  break;
4079                case OPS.moveTo:
4080                  x = args[j++];
4081                  y = args[j++];
4082                  d.push('M', pf(x), pf(y));
4083                  break;
4084                case OPS.lineTo:
4085                  x = args[j++];
4086                  y = args[j++];
4087                  d.push('L', pf(x), pf(y));
4088                  break;
4089                case OPS.curveTo:
4090                  x = args[j + 4];
4091                  y = args[j + 5];
4092                  d.push('C', pf(args[j]), pf(args[j + 1]), pf(args[j + 2]), pf(args[j + 3]), pf(x), pf(y));
4093                  j += 6;
4094                  break;
4095                case OPS.curveTo2:
4096                  x = args[j + 2];
4097                  y = args[j + 3];
4098                  d.push('C', pf(x), pf(y), pf(args[j]), pf(args[j + 1]), pf(args[j + 2]), pf(args[j + 3]));
4099                  j += 4;
4100                  break;
4101                case OPS.curveTo3:
4102                  x = args[j + 2];
4103                  y = args[j + 3];
4104                  d.push('C', pf(args[j]), pf(args[j + 1]), pf(x), pf(y), pf(x), pf(y));
4105                  j += 4;
4106                  break;
4107                case OPS.closePath:
4108                  d.push('Z');
4109                  break;
4110              }
4111            }
4112            current.path.setAttributeNS(null, 'd', d.join(' '));
4113            current.path.setAttributeNS(null, 'stroke-miterlimit', pf(current.miterLimit));
4114            current.path.setAttributeNS(null, 'stroke-linecap', current.lineCap);
4115            current.path.setAttributeNS(null, 'stroke-linejoin', current.lineJoin);
4116            current.path.setAttributeNS(null, 'stroke-width', pf(current.lineWidth) + 'px');
4117            current.path.setAttributeNS(null, 'stroke-dasharray', current.dashArray.map(pf).join(' '));
4118            current.path.setAttributeNS(null, 'stroke-dashoffset', pf(current.dashPhase) + 'px');
4119            current.path.setAttributeNS(null, 'fill', 'none');
4120
4121            this.tgrp.appendChild(current.path);
4122            if (current.pendingClip) {
4123              this.cgrp.appendChild(this.tgrp);
4124              this.pgrp.appendChild(this.cgrp);
4125            } else {
4126              this.pgrp.appendChild(this.tgrp);
4127            }
4128            // Saving a reference in current.element so that it can be addressed
4129            // in 'fill' and 'stroke'
4130            current.element = current.path;
4131            current.setCurrentPoint(x, y);
4132          },
4133
4134          endPath: function SVGGraphics_endPath() {
4135            var current = this.current;
4136            if (current.pendingClip) {
4137              this.cgrp.appendChild(this.tgrp);
4138              this.pgrp.appendChild(this.cgrp);
4139            } else {
4140              this.pgrp.appendChild(this.tgrp);
4141            }
4142            this.tgrp = document.createElementNS(NS, 'svg:g');
4143            this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix));
4144          },
4145
4146          clip: function SVGGraphics_clip(type) {
4147            var current = this.current;
4148            // Add current path to clipping path
4149            current.clipId = 'clippath' + clipCount;
4150            clipCount++;
4151            this.clippath = document.createElementNS(NS, 'svg:clipPath');
4152            this.clippath.setAttributeNS(null, 'id', current.clipId);
4153            var clipElement = current.element.cloneNode();
4154            if (type === 'evenodd') {
4155              clipElement.setAttributeNS(null, 'clip-rule', 'evenodd');
4156            } else {
4157              clipElement.setAttributeNS(null, 'clip-rule', 'nonzero');
4158            }
4159            this.clippath.setAttributeNS(null, 'transform', pm(this.transformMatrix));
4160            this.clippath.appendChild(clipElement);
4161            this.defs.appendChild(this.clippath);
4162
4163            // Create a new group with that attribute
4164            current.pendingClip = true;
4165            this.cgrp = document.createElementNS(NS, 'svg:g');
4166            this.cgrp.setAttributeNS(null, 'clip-path', 'url(#' + current.clipId + ')');
4167            this.pgrp.appendChild(this.cgrp);
4168          },
4169
4170          closePath: function SVGGraphics_closePath() {
4171            var current = this.current;
4172            var d = current.path.getAttributeNS(null, 'd');
4173            d += 'Z';
4174            current.path.setAttributeNS(null, 'd', d);
4175          },
4176
4177          setLeading: function SVGGraphics_setLeading(leading) {
4178            this.current.leading = -leading;
4179          },
4180
4181          setTextRise: function SVGGraphics_setTextRise(textRise) {
4182            this.current.textRise = textRise;
4183          },
4184
4185          setHScale: function SVGGraphics_setHScale(scale) {
4186            this.current.textHScale = scale / 100;
4187          },
4188
4189          setGState: function SVGGraphics_setGState(states) {
4190            for (var i = 0, ii = states.length; i < ii; i++) {
4191              var state = states[i];
4192              var key = state[0];
4193              var value = state[1];
4194
4195              switch (key) {
4196                case 'LW':
4197                  this.setLineWidth(value);
4198                  break;
4199                case 'LC':
4200                  this.setLineCap(value);
4201                  break;
4202                case 'LJ':
4203                  this.setLineJoin(value);
4204                  break;
4205                case 'ML':
4206                  this.setMiterLimit(value);
4207                  break;
4208                case 'D':
4209                  this.setDash(value[0], value[1]);
4210                  break;
4211                case 'RI':
4212                  break;
4213                case 'FL':
4214                  break;
4215                case 'Font':
4216                  this.setFont(value);
4217                  break;
4218                case 'CA':
4219                  break;
4220                case 'ca':
4221                  break;
4222                case 'BM':
4223                  break;
4224                case 'SMask':
4225                  break;
4226              }
4227            }
4228          },
4229
4230          fill: function SVGGraphics_fill() {
4231            var current = this.current;
4232            current.element.setAttributeNS(null, 'fill', current.fillColor);
4233          },
4234
4235          stroke: function SVGGraphics_stroke() {
4236            var current = this.current;
4237            current.element.setAttributeNS(null, 'stroke', current.strokeColor);
4238            current.element.setAttributeNS(null, 'fill', 'none');
4239          },
4240
4241          eoFill: function SVGGraphics_eoFill() {
4242            var current = this.current;
4243            current.element.setAttributeNS(null, 'fill', current.fillColor);
4244            current.element.setAttributeNS(null, 'fill-rule', 'evenodd');
4245          },
4246
4247          fillStroke: function SVGGraphics_fillStroke() {
4248            // Order is important since stroke wants fill to be none.
4249            // First stroke, then if fill needed, it will be overwritten.
4250            this.stroke();
4251            this.fill();
4252          },
4253
4254          eoFillStroke: function SVGGraphics_eoFillStroke() {
4255            this.current.element.setAttributeNS(null, 'fill-rule', 'evenodd');
4256            this.fillStroke();
4257          },
4258
4259          closeStroke: function SVGGraphics_closeStroke() {
4260            this.closePath();
4261            this.stroke();
4262          },
4263
4264          closeFillStroke: function SVGGraphics_closeFillStroke() {
4265            this.closePath();
4266            this.fillStroke();
4267          },
4268
4269          paintSolidColorImageMask: function SVGGraphics_paintSolidColorImageMask() {
4270            var current = this.current;
4271            var rect = document.createElementNS(NS, 'svg:rect');
4272            rect.setAttributeNS(null, 'x', '0');
4273            rect.setAttributeNS(null, 'y', '0');
4274            rect.setAttributeNS(null, 'width', '1px');
4275            rect.setAttributeNS(null, 'height', '1px');
4276            rect.setAttributeNS(null, 'fill', current.fillColor);
4277            this.tgrp.appendChild(rect);
4278          },
4279
4280          paintJpegXObject: function SVGGraphics_paintJpegXObject(objId, w, h) {
4281            var current = this.current;
4282            var imgObj = this.objs.get(objId);
4283            var imgEl = document.createElementNS(NS, 'svg:image');
4284            imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgObj.src);
4285            imgEl.setAttributeNS(null, 'width', imgObj.width + 'px');
4286            imgEl.setAttributeNS(null, 'height', imgObj.height + 'px');
4287            imgEl.setAttributeNS(null, 'x', '0');
4288            imgEl.setAttributeNS(null, 'y', pf(-h));
4289            imgEl.setAttributeNS(null, 'transform', 'scale(' + pf(1 / w) + ' ' + pf(-1 / h) + ')');
4290
4291            this.tgrp.appendChild(imgEl);
4292            if (current.pendingClip) {
4293              this.cgrp.appendChild(this.tgrp);
4294              this.pgrp.appendChild(this.cgrp);
4295            } else {
4296              this.pgrp.appendChild(this.tgrp);
4297            }
4298          },
4299
4300          paintImageXObject: function SVGGraphics_paintImageXObject(objId) {
4301            var imgData = this.objs.get(objId);
4302            if (!imgData) {
4303              warn("Dependent image isn't ready yet");
4304              return;
4305            }
4306            this.paintInlineImageXObject(imgData);
4307          },
4308
4309          paintInlineImageXObject: function SVGGraphics_paintInlineImageXObject(imgData, mask) {
4310            var current = this.current;
4311            var width = imgData.width;
4312            var height = imgData.height;
4313
4314            var imgSrc = convertImgDataToPng(imgData, this.forceDataSchema);
4315            var cliprect = document.createElementNS(NS, 'svg:rect');
4316            cliprect.setAttributeNS(null, 'x', '0');
4317            cliprect.setAttributeNS(null, 'y', '0');
4318            cliprect.setAttributeNS(null, 'width', pf(width));
4319            cliprect.setAttributeNS(null, 'height', pf(height));
4320            current.element = cliprect;
4321            this.clip('nonzero');
4322            var imgEl = document.createElementNS(NS, 'svg:image');
4323            imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgSrc);
4324            imgEl.setAttributeNS(null, 'x', '0');
4325            imgEl.setAttributeNS(null, 'y', pf(-height));
4326            imgEl.setAttributeNS(null, 'width', pf(width) + 'px');
4327            imgEl.setAttributeNS(null, 'height', pf(height) + 'px');
4328            imgEl.setAttributeNS(null, 'transform', 'scale(' + pf(1 / width) + ' ' + pf(-1 / height) + ')');
4329            if (mask) {
4330              mask.appendChild(imgEl);
4331            } else {
4332              this.tgrp.appendChild(imgEl);
4333            }
4334            if (current.pendingClip) {
4335              this.cgrp.appendChild(this.tgrp);
4336              this.pgrp.appendChild(this.cgrp);
4337            } else {
4338              this.pgrp.appendChild(this.tgrp);
4339            }
4340          },
4341
4342          paintImageMaskXObject: function SVGGraphics_paintImageMaskXObject(imgData) {
4343            var current = this.current;
4344            var width = imgData.width;
4345            var height = imgData.height;
4346            var fillColor = current.fillColor;
4347
4348            current.maskId = 'mask' + maskCount++;
4349            var mask = document.createElementNS(NS, 'svg:mask');
4350            mask.setAttributeNS(null, 'id', current.maskId);
4351
4352            var rect = document.createElementNS(NS, 'svg:rect');
4353            rect.setAttributeNS(null, 'x', '0');
4354            rect.setAttributeNS(null, 'y', '0');
4355            rect.setAttributeNS(null, 'width', pf(width));
4356            rect.setAttributeNS(null, 'height', pf(height));
4357            rect.setAttributeNS(null, 'fill', fillColor);
4358            rect.setAttributeNS(null, 'mask', 'url(#' + current.maskId + ')');
4359            this.defs.appendChild(mask);
4360            this.tgrp.appendChild(rect);
4361
4362            this.paintInlineImageXObject(imgData, mask);
4363          },
4364
4365          paintFormXObjectBegin: function SVGGraphics_paintFormXObjectBegin(matrix, bbox) {
4366            this.save();
4367
4368            if (isArray(matrix) && matrix.length === 6) {
4369              this.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
4370            }
4371
4372            if (isArray(bbox) && bbox.length === 4) {
4373              var width = bbox[2] - bbox[0];
4374              var height = bbox[3] - bbox[1];
4375
4376              var cliprect = document.createElementNS(NS, 'svg:rect');
4377              cliprect.setAttributeNS(null, 'x', bbox[0]);
4378              cliprect.setAttributeNS(null, 'y', bbox[1]);
4379              cliprect.setAttributeNS(null, 'width', pf(width));
4380              cliprect.setAttributeNS(null, 'height', pf(height));
4381              this.current.element = cliprect;
4382              this.clip('nonzero');
4383              this.endPath();
4384            }
4385          },
4386
4387          paintFormXObjectEnd: function SVGGraphics_paintFormXObjectEnd() {
4388            this.restore();
4389          },
4390        };
4391        return SVGGraphics;
4392      })();
4393
4394      exports.SVGGraphics = SVGGraphics;
4395    });
4396
4397    (function (root, factory) {
4398      {
4399        factory((root.pdfjsDisplayAnnotationLayer = {}), root.pdfjsSharedUtil, root.pdfjsDisplayDOMUtils);
4400      }
4401    })(this, function (exports, sharedUtil, displayDOMUtils) {
4402      var AnnotationBorderStyleType = sharedUtil.AnnotationBorderStyleType;
4403      var AnnotationType = sharedUtil.AnnotationType;
4404      var Util = sharedUtil.Util;
4405      var addLinkAttributes = displayDOMUtils.addLinkAttributes;
4406      var LinkTarget = displayDOMUtils.LinkTarget;
4407      var getFilenameFromUrl = displayDOMUtils.getFilenameFromUrl;
4408      var warn = sharedUtil.warn;
4409      var CustomStyle = displayDOMUtils.CustomStyle;
4410      var getDefaultSetting = displayDOMUtils.getDefaultSetting;
4411
4412      /**
4413       * @typedef {Object} AnnotationElementParameters
4414       * @property {Object} data
4415       * @property {HTMLDivElement} layer
4416       * @property {PDFPage} page
4417       * @property {PageViewport} viewport
4418       * @property {IPDFLinkService} linkService
4419       * @property {DownloadManager} downloadManager
4420       * @property {string} imageResourcesPath
4421       * @property {boolean} renderInteractiveForms
4422       */
4423
4424      /**
4425       * @class
4426       * @alias AnnotationElementFactory
4427       */
4428      function AnnotationElementFactory() {}
4429
4430      AnnotationElementFactory.prototype = /** @lends AnnotationElementFactory.prototype */ {
4431        /**
4432         * @param {AnnotationElementParameters} parameters
4433         * @returns {AnnotationElement}
4434         */
4435        create: function AnnotationElementFactory_create(parameters) {
4436          var subtype = parameters.data.annotationType;
4437
4438          switch (subtype) {
4439            case AnnotationType.LINK:
4440              return new LinkAnnotationElement(parameters);
4441
4442            case AnnotationType.TEXT:
4443              return new TextAnnotationElement(parameters);
4444
4445            case AnnotationType.WIDGET:
4446              var fieldType = parameters.data.fieldType;
4447
4448              switch (fieldType) {
4449                case 'Tx':
4450                  return new TextWidgetAnnotationElement(parameters);
4451              }
4452              return new WidgetAnnotationElement(parameters);
4453
4454            case AnnotationType.POPUP:
4455              return new PopupAnnotationElement(parameters);
4456
4457            case AnnotationType.HIGHLIGHT:
4458              return new HighlightAnnotationElement(parameters);
4459
4460            case AnnotationType.UNDERLINE:
4461              return new UnderlineAnnotationElement(parameters);
4462
4463            case AnnotationType.SQUIGGLY:
4464              return new SquigglyAnnotationElement(parameters);
4465
4466            case AnnotationType.STRIKEOUT:
4467              return new StrikeOutAnnotationElement(parameters);
4468
4469            case AnnotationType.FILEATTACHMENT:
4470              return new FileAttachmentAnnotationElement(parameters);
4471
4472            default:
4473              return new AnnotationElement(parameters);
4474          }
4475        },
4476      };
4477
4478      /**
4479       * @class
4480       * @alias AnnotationElement
4481       */
4482      var AnnotationElement = (function AnnotationElementClosure() {
4483        function AnnotationElement(parameters, isRenderable) {
4484          this.isRenderable = isRenderable || false;
4485          this.data = parameters.data;
4486          this.layer = parameters.layer;
4487          this.page = parameters.page;
4488          this.viewport = parameters.viewport;
4489          this.linkService = parameters.linkService;
4490          this.downloadManager = parameters.downloadManager;
4491          this.imageResourcesPath = parameters.imageResourcesPath;
4492          this.renderInteractiveForms = parameters.renderInteractiveForms;
4493
4494          if (isRenderable) {
4495            this.container = this._createContainer();
4496          }
4497        }
4498
4499        AnnotationElement.prototype = /** @lends AnnotationElement.prototype */ {
4500          /**
4501           * Create an empty container for the annotation's HTML element.
4502           *
4503           * @private
4504           * @memberof AnnotationElement
4505           * @returns {HTMLSectionElement}
4506           */
4507          _createContainer: function AnnotationElement_createContainer() {
4508            var data = this.data,
4509              page = this.page,
4510              viewport = this.viewport;
4511            var container = document.createElement('section');
4512            var width = data.rect[2] - data.rect[0];
4513            var height = data.rect[3] - data.rect[1];
4514
4515            container.setAttribute('data-annotation-id', data.id);
4516
4517            // Do *not* modify `data.rect`, since that will corrupt the annotation
4518            // position on subsequent calls to `_createContainer` (see issue 6804).
4519            var rect = Util.normalizeRect([
4520              data.rect[0],
4521              page.view[3] - data.rect[1] + page.view[1],
4522              data.rect[2],
4523              page.view[3] - data.rect[3] + page.view[1],
4524            ]);
4525
4526            CustomStyle.setProp('transform', container, 'matrix(' + viewport.transform.join(',') + ')');
4527            CustomStyle.setProp('transformOrigin', container, -rect[0] + 'px ' + -rect[1] + 'px');
4528
4529            if (data.borderStyle.width > 0) {
4530              container.style.borderWidth = data.borderStyle.width + 'px';
4531              if (data.borderStyle.style !== AnnotationBorderStyleType.UNDERLINE) {
4532                // Underline styles only have a bottom border, so we do not need
4533                // to adjust for all borders. This yields a similar result as
4534                // Adobe Acrobat/Reader.
4535                width = width - 2 * data.borderStyle.width;
4536                height = height - 2 * data.borderStyle.width;
4537              }
4538
4539              var horizontalRadius = data.borderStyle.horizontalCornerRadius;
4540              var verticalRadius = data.borderStyle.verticalCornerRadius;
4541              if (horizontalRadius > 0 || verticalRadius > 0) {
4542                var radius = horizontalRadius + 'px / ' + verticalRadius + 'px';
4543                CustomStyle.setProp('borderRadius', container, radius);
4544              }
4545
4546              switch (data.borderStyle.style) {
4547                case AnnotationBorderStyleType.SOLID:
4548                  container.style.borderStyle = 'solid';
4549                  break;
4550
4551                case AnnotationBorderStyleType.DASHED:
4552                  container.style.borderStyle = 'dashed';
4553                  break;
4554
4555                case AnnotationBorderStyleType.BEVELED:
4556                  warn('Unimplemented border style: beveled');
4557                  break;
4558
4559                case AnnotationBorderStyleType.INSET:
4560                  warn('Unimplemented border style: inset');
4561                  break;
4562
4563                case AnnotationBorderStyleType.UNDERLINE:
4564                  container.style.borderBottomStyle = 'solid';
4565                  break;
4566
4567                default:
4568                  break;
4569              }
4570
4571              if (data.color) {
4572                container.style.borderColor = Util.makeCssRgb(data.color[0] | 0, data.color[1] | 0, data.color[2] | 0);
4573              } else {
4574                // Transparent (invisible) border, so do not draw it at all.
4575                container.style.borderWidth = 0;
4576              }
4577            }
4578
4579            container.style.left = rect[0] + 'px';
4580            container.style.top = rect[1] + 'px';
4581
4582            container.style.width = width + 'px';
4583            container.style.height = height + 'px';
4584
4585            return container;
4586          },
4587
4588          /**
4589           * Create a popup for the annotation's HTML element. This is used for
4590           * annotations that do not have a Popup entry in the dictionary, but
4591           * are of a type that works with popups (such as Highlight annotations).
4592           *
4593           * @private
4594           * @param {HTMLSectionElement} container
4595           * @param {HTMLDivElement|HTMLImageElement|null} trigger
4596           * @param {Object} data
4597           * @memberof AnnotationElement
4598           */
4599          _createPopup: function AnnotationElement_createPopup(container, trigger, data) {
4600            // If no trigger element is specified, create it.
4601            if (!trigger) {
4602              trigger = document.createElement('div');
4603              trigger.style.height = container.style.height;
4604              trigger.style.width = container.style.width;
4605              container.appendChild(trigger);
4606            }
4607
4608            var popupElement = new PopupElement({
4609              container: container,
4610              trigger: trigger,
4611              color: data.color,
4612              title: data.title,
4613              contents: data.contents,
4614              hideWrapper: true,
4615            });
4616            var popup = popupElement.render();
4617
4618            // Position the popup next to the annotation's container.
4619            popup.style.left = container.style.width;
4620
4621            container.appendChild(popup);
4622          },
4623
4624          /**
4625           * Render the annotation's HTML element in the empty container.
4626           *
4627           * @public
4628           * @memberof AnnotationElement
4629           */
4630          render: function AnnotationElement_render() {
4631            throw new Error('Abstract method AnnotationElement.render called');
4632          },
4633        };
4634
4635        return AnnotationElement;
4636      })();
4637
4638      /**
4639       * @class
4640       * @alias LinkAnnotationElement
4641       */
4642      var LinkAnnotationElement = (function LinkAnnotationElementClosure() {
4643        function LinkAnnotationElement(parameters) {
4644          AnnotationElement.call(this, parameters, true);
4645        }
4646
4647        Util.inherit(LinkAnnotationElement, AnnotationElement, {
4648          /**
4649           * Render the link annotation's HTML element in the empty container.
4650           *
4651           * @public
4652           * @memberof LinkAnnotationElement
4653           * @returns {HTMLSectionElement}
4654           */
4655          render: function LinkAnnotationElement_render() {
4656            this.container.className = 'linkAnnotation';
4657
4658            var link = document.createElement('a');
4659            addLinkAttributes(link, {
4660              url: this.data.url,
4661              target: this.data.newWindow ? LinkTarget.BLANK : undefined,
4662            });
4663
4664            if (!this.data.url) {
4665              if (this.data.action) {
4666                this._bindNamedAction(link, this.data.action);
4667              } else {
4668                this._bindLink(link, this.data.dest || null);
4669              }
4670            }
4671
4672            this.container.appendChild(link);
4673            return this.container;
4674          },
4675
4676          /**
4677           * Bind internal links to the link element.
4678           *
4679           * @private
4680           * @param {Object} link
4681           * @param {Object} destination
4682           * @memberof LinkAnnotationElement
4683           */
4684          _bindLink: function LinkAnnotationElement_bindLink(link, destination) {
4685            var self = this;
4686
4687            link.href = this.linkService.getDestinationHash(destination);
4688            link.onclick = function () {
4689              if (destination) {
4690                self.linkService.navigateTo(destination);
4691              }
4692              return false;
4693            };
4694            if (destination) {
4695              link.className = 'internalLink';
4696            }
4697          },
4698
4699          /**
4700           * Bind named actions to the link element.
4701           *
4702           * @private
4703           * @param {Object} link
4704           * @param {Object} action
4705           * @memberof LinkAnnotationElement
4706           */
4707          _bindNamedAction: function LinkAnnotationElement_bindNamedAction(link, action) {
4708            var self = this;
4709
4710            link.href = this.linkService.getAnchorUrl('');
4711            link.onclick = function () {
4712              self.linkService.executeNamedAction(action);
4713              return false;
4714            };
4715            link.className = 'internalLink';
4716          },
4717        });
4718
4719        return LinkAnnotationElement;
4720      })();
4721
4722      /**
4723       * @class
4724       * @alias TextAnnotationElement
4725       */
4726      var TextAnnotationElement = (function TextAnnotationElementClosure() {
4727        function TextAnnotationElement(parameters) {
4728          var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
4729          AnnotationElement.call(this, parameters, isRenderable);
4730        }
4731
4732        Util.inherit(TextAnnotationElement, AnnotationElement, {
4733          /**
4734           * Render the text annotation's HTML element in the empty container.
4735           *
4736           * @public
4737           * @memberof TextAnnotationElement
4738           * @returns {HTMLSectionElement}
4739           */
4740          render: function TextAnnotationElement_render() {
4741            this.container.className = 'textAnnotation';
4742
4743            var image = document.createElement('img');
4744            image.style.height = this.container.style.height;
4745            image.style.width = this.container.style.width;
4746            image.src = this.imageResourcesPath + 'annotation-' + this.data.name.toLowerCase() + '.svg';
4747            image.alt = '[{{type}} Annotation]';
4748            image.dataset.l10nId = 'text_annotation_type';
4749            image.dataset.l10nArgs = JSON.stringify({ type: this.data.name });
4750
4751            if (!this.data.hasPopup) {
4752              this._createPopup(this.container, image, this.data);
4753            }
4754
4755            this.container.appendChild(image);
4756            return this.container;
4757          },
4758        });
4759
4760        return TextAnnotationElement;
4761      })();
4762
4763      /**
4764       * @class
4765       * @alias WidgetAnnotationElement
4766       */
4767      var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() {
4768        function WidgetAnnotationElement(parameters) {
4769          var isRenderable =
4770            parameters.renderInteractiveForms || (!parameters.data.hasAppearance && !!parameters.data.fieldValue);
4771          AnnotationElement.call(this, parameters, isRenderable);
4772        }
4773
4774        Util.inherit(WidgetAnnotationElement, AnnotationElement, {
4775          /**
4776           * Render the widget annotation's HTML element in the empty container.
4777           *
4778           * @public
4779           * @memberof WidgetAnnotationElement
4780           * @returns {HTMLSectionElement}
4781           */
4782          render: function WidgetAnnotationElement_render() {
4783            // Show only the container for unsupported field types.
4784            return this.container;
4785          },
4786        });
4787
4788        return WidgetAnnotationElement;
4789      })();
4790
4791      /**
4792       * @class
4793       * @alias TextWidgetAnnotationElement
4794       */
4795      var TextWidgetAnnotationElement = (function TextWidgetAnnotationElementClosure() {
4796        var TEXT_ALIGNMENT = ['left', 'center', 'right'];
4797
4798        function TextWidgetAnnotationElement(parameters) {
4799          WidgetAnnotationElement.call(this, parameters);
4800        }
4801
4802        Util.inherit(TextWidgetAnnotationElement, WidgetAnnotationElement, {
4803          /**
4804           * Render the text widget annotation's HTML element in the empty container.
4805           *
4806           * @public
4807           * @memberof TextWidgetAnnotationElement
4808           * @returns {HTMLSectionElement}
4809           */
4810          render: function TextWidgetAnnotationElement_render() {
4811            this.container.className = 'textWidgetAnnotation';
4812
4813            var element = null;
4814            if (this.renderInteractiveForms) {
4815              // NOTE: We cannot set the values using `element.value` below, since it
4816              //       prevents the AnnotationLayer rasterizer in `test/driver.js`
4817              //       from parsing the elements correctly for the reference tests.
4818              if (this.data.multiLine) {
4819                element = document.createElement('textarea');
4820                element.textContent = this.data.fieldValue;
4821              } else {
4822                element = document.createElement('input');
4823                element.type = 'text';
4824                element.setAttribute('value', this.data.fieldValue);
4825              }
4826
4827              element.disabled = this.data.readOnly;
4828
4829              if (this.data.maxLen !== null) {
4830                element.maxLength = this.data.maxLen;
4831              }
4832
4833              if (this.data.comb) {
4834                var fieldWidth = this.data.rect[2] - this.data.rect[0];
4835                var combWidth = fieldWidth / this.data.maxLen;
4836
4837                element.classList.add('comb');
4838                element.style.letterSpacing = 'calc(' + combWidth + 'px - 1ch)';
4839              }
4840            } else {
4841              element = document.createElement('div');
4842              element.textContent = this.data.fieldValue;
4843              element.style.verticalAlign = 'middle';
4844              element.style.display = 'table-cell';
4845
4846              var font = null;
4847              if (this.data.fontRefName) {
4848                font = this.page.commonObjs.getData(this.data.fontRefName);
4849              }
4850              this._setTextStyle(element, font);
4851            }
4852
4853            if (this.data.textAlignment !== null) {
4854              element.style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment];
4855            }
4856
4857            this.container.appendChild(element);
4858            return this.container;
4859          },
4860
4861          /**
4862           * Apply text styles to the text in the element.
4863           *
4864           * @private
4865           * @param {HTMLDivElement} element
4866           * @param {Object} font
4867           * @memberof TextWidgetAnnotationElement
4868           */
4869          _setTextStyle: function TextWidgetAnnotationElement_setTextStyle(element, font) {
4870            // TODO: This duplicates some of the logic in CanvasGraphics.setFont().
4871            var style = element.style;
4872            style.fontSize = this.data.fontSize + 'px';
4873            style.direction = this.data.fontDirection < 0 ? 'rtl' : 'ltr';
4874
4875            if (!font) {
4876              return;
4877            }
4878
4879            style.fontWeight = font.black ? (font.bold ? '900' : 'bold') : font.bold ? 'bold' : 'normal';
4880            style.fontStyle = font.italic ? 'italic' : 'normal';
4881
4882            // Use a reasonable default font if the font doesn't specify a fallback.
4883            var fontFamily = font.loadedName ? '"' + font.loadedName + '", ' : '';
4884            var fallbackName = font.fallbackName || 'Helvetica, sans-serif';
4885            style.fontFamily = fontFamily + fallbackName;
4886          },
4887        });
4888
4889        return TextWidgetAnnotationElement;
4890      })();
4891
4892      /**
4893       * @class
4894       * @alias PopupAnnotationElement
4895       */
4896      var PopupAnnotationElement = (function PopupAnnotationElementClosure() {
4897        function PopupAnnotationElement(parameters) {
4898          var isRenderable = !!(parameters.data.title || parameters.data.contents);
4899          AnnotationElement.call(this, parameters, isRenderable);
4900        }
4901
4902        Util.inherit(PopupAnnotationElement, AnnotationElement, {
4903          /**
4904           * Render the popup annotation's HTML element in the empty container.
4905           *
4906           * @public
4907           * @memberof PopupAnnotationElement
4908           * @returns {HTMLSectionElement}
4909           */
4910          render: function PopupAnnotationElement_render() {
4911            this.container.className = 'popupAnnotation';
4912
4913            var selector = '[data-annotation-id="' + this.data.parentId + '"]';
4914            var parentElement = this.layer.querySelector(selector);
4915            if (!parentElement) {
4916              return this.container;
4917            }
4918
4919            var popup = new PopupElement({
4920              container: this.container,
4921              trigger: parentElement,
4922              color: this.data.color,
4923              title: this.data.title,
4924              contents: this.data.contents,
4925            });
4926
4927            // Position the popup next to the parent annotation's container.
4928            // PDF viewers ignore a popup annotation's rectangle.
4929            var parentLeft = parseFloat(parentElement.style.left);
4930            var parentWidth = parseFloat(parentElement.style.width);
4931            CustomStyle.setProp(
4932              'transformOrigin',
4933              this.container,
4934              -(parentLeft + parentWidth) + 'px -' + parentElement.style.top
4935            );
4936            this.container.style.left = parentLeft + parentWidth + 'px';
4937
4938            this.container.appendChild(popup.render());
4939            return this.container;
4940          },
4941        });
4942
4943        return PopupAnnotationElement;
4944      })();
4945
4946      /**
4947       * @class
4948       * @alias PopupElement
4949       */
4950      var PopupElement = (function PopupElementClosure() {
4951        var BACKGROUND_ENLIGHT = 0.7;
4952
4953        function PopupElement(parameters) {
4954          this.container = parameters.container;
4955          this.trigger = parameters.trigger;
4956          this.color = parameters.color;
4957          this.title = parameters.title;
4958          this.contents = parameters.contents;
4959          this.hideWrapper = parameters.hideWrapper || false;
4960
4961          this.pinned = false;
4962        }
4963
4964        PopupElement.prototype = /** @lends PopupElement.prototype */ {
4965          /**
4966           * Render the popup's HTML element.
4967           *
4968           * @public
4969           * @memberof PopupElement
4970           * @returns {HTMLSectionElement}
4971           */
4972          render: function PopupElement_render() {
4973            var wrapper = document.createElement('div');
4974            wrapper.className = 'popupWrapper';
4975
4976            // For Popup annotations we hide the entire section because it contains
4977            // only the popup. However, for Text annotations without a separate Popup
4978            // annotation, we cannot hide the entire container as the image would
4979            // disappear too. In that special case, hiding the wrapper suffices.
4980            this.hideElement = this.hideWrapper ? wrapper : this.container;
4981            this.hideElement.setAttribute('hidden', true);
4982
4983            var popup = document.createElement('div');
4984            popup.className = 'popup';
4985
4986            var color = this.color;
4987            if (color) {
4988              // Enlighten the color.
4989              var r = BACKGROUND_ENLIGHT * (255 - color[0]) + color[0];
4990              var g = BACKGROUND_ENLIGHT * (255 - color[1]) + color[1];
4991              var b = BACKGROUND_ENLIGHT * (255 - color[2]) + color[2];
4992              popup.style.backgroundColor = Util.makeCssRgb(r | 0, g | 0, b | 0);
4993            }
4994
4995            var contents = this._formatContents(this.contents);
4996            var title = document.createElement('h1');
4997            title.textContent = this.title;
4998
4999            // Attach the event listeners to the trigger element.
5000            this.trigger.addEventListener('click', this._toggle.bind(this));
5001            this.trigger.addEventListener('mouseover', this._show.bind(this, false));
5002            this.trigger.addEventListener('mouseout', this._hide.bind(this, false));
5003            popup.addEventListener('click', this._hide.bind(this, true));
5004
5005            popup.appendChild(title);
5006            popup.appendChild(contents);
5007            wrapper.appendChild(popup);
5008            return wrapper;
5009          },
5010
5011          /**
5012           * Format the contents of the popup by adding newlines where necessary.
5013           *
5014           * @private
5015           * @param {string} contents
5016           * @memberof PopupElement
5017           * @returns {HTMLParagraphElement}
5018           */
5019          _formatContents: function PopupElement_formatContents(contents) {
5020            var p = document.createElement('p');
5021            var lines = contents.split(/(?:\r\n?|\n)/);
5022            for (var i = 0, ii = lines.length; i < ii; ++i) {
5023              var line = lines[i];
5024              p.appendChild(document.createTextNode(line));
5025              if (i < ii - 1) {
5026                p.appendChild(document.createElement('br'));
5027              }
5028            }
5029            return p;
5030          },
5031
5032          /**
5033           * Toggle the visibility of the popup.
5034           *
5035           * @private
5036           * @memberof PopupElement
5037           */
5038          _toggle: function PopupElement_toggle() {
5039            if (this.pinned) {
5040              this._hide(true);
5041            } else {
5042              this._show(true);
5043            }
5044          },
5045
5046          /**
5047           * Show the popup.
5048           *
5049           * @private
5050           * @param {boolean} pin
5051           * @memberof PopupElement
5052           */
5053          _show: function PopupElement_show(pin) {
5054            if (pin) {
5055              this.pinned = true;
5056            }
5057            if (this.hideElement.hasAttribute('hidden')) {
5058              this.hideElement.removeAttribute('hidden');
5059              this.container.style.zIndex += 1;
5060            }
5061          },
5062
5063          /**
5064           * Hide the popup.
5065           *
5066           * @private
5067           * @param {boolean} unpin
5068           * @memberof PopupElement
5069           */
5070          _hide: function PopupElement_hide(unpin) {
5071            if (unpin) {
5072              this.pinned = false;
5073            }
5074            if (!this.hideElement.hasAttribute('hidden') && !this.pinned) {
5075              this.hideElement.setAttribute('hidden', true);
5076              this.container.style.zIndex -= 1;
5077            }
5078          },
5079        };
5080
5081        return PopupElement;
5082      })();
5083
5084      /**
5085       * @class
5086       * @alias HighlightAnnotationElement
5087       */
5088      var HighlightAnnotationElement = (function HighlightAnnotationElementClosure() {
5089        function HighlightAnnotationElement(parameters) {
5090          var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
5091          AnnotationElement.call(this, parameters, isRenderable);
5092        }
5093
5094        Util.inherit(HighlightAnnotationElement, AnnotationElement, {
5095          /**
5096           * Render the highlight annotation's HTML element in the empty container.
5097           *
5098           * @public
5099           * @memberof HighlightAnnotationElement
5100           * @returns {HTMLSectionElement}
5101           */
5102          render: function HighlightAnnotationElement_render() {
5103            this.container.className = 'highlightAnnotation';
5104
5105            if (!this.data.hasPopup) {
5106              this._createPopup(this.container, null, this.data);
5107            }
5108
5109            return this.container;
5110          },
5111        });
5112
5113        return HighlightAnnotationElement;
5114      })();
5115
5116      /**
5117       * @class
5118       * @alias UnderlineAnnotationElement
5119       */
5120      var UnderlineAnnotationElement = (function UnderlineAnnotationElementClosure() {
5121        function UnderlineAnnotationElement(parameters) {
5122          var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
5123          AnnotationElement.call(this, parameters, isRenderable);
5124        }
5125
5126        Util.inherit(UnderlineAnnotationElement, AnnotationElement, {
5127          /**
5128           * Render the underline annotation's HTML element in the empty container.
5129           *
5130           * @public
5131           * @memberof UnderlineAnnotationElement
5132           * @returns {HTMLSectionElement}
5133           */
5134          render: function UnderlineAnnotationElement_render() {
5135            this.container.className = 'underlineAnnotation';
5136
5137            if (!this.data.hasPopup) {
5138              this._createPopup(this.container, null, this.data);
5139            }
5140
5141            return this.container;
5142          },
5143        });
5144
5145        return UnderlineAnnotationElement;
5146      })();
5147
5148      /**
5149       * @class
5150       * @alias SquigglyAnnotationElement
5151       */
5152      var SquigglyAnnotationElement = (function SquigglyAnnotationElementClosure() {
5153        function SquigglyAnnotationElement(parameters) {
5154          var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
5155          AnnotationElement.call(this, parameters, isRenderable);
5156        }
5157
5158        Util.inherit(SquigglyAnnotationElement, AnnotationElement, {
5159          /**
5160           * Render the squiggly annotation's HTML element in the empty container.
5161           *
5162           * @public
5163           * @memberof SquigglyAnnotationElement
5164           * @returns {HTMLSectionElement}
5165           */
5166          render: function SquigglyAnnotationElement_render() {
5167            this.container.className = 'squigglyAnnotation';
5168
5169            if (!this.data.hasPopup) {
5170              this._createPopup(this.container, null, this.data);
5171            }
5172
5173            return this.container;
5174          },
5175        });
5176
5177        return SquigglyAnnotationElement;
5178      })();
5179
5180      /**
5181       * @class
5182       * @alias StrikeOutAnnotationElement
5183       */
5184      var StrikeOutAnnotationElement = (function StrikeOutAnnotationElementClosure() {
5185        function StrikeOutAnnotationElement(parameters) {
5186          var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
5187          AnnotationElement.call(this, parameters, isRenderable);
5188        }
5189
5190        Util.inherit(StrikeOutAnnotationElement, AnnotationElement, {
5191          /**
5192           * Render the strikeout annotation's HTML element in the empty container.
5193           *
5194           * @public
5195           * @memberof StrikeOutAnnotationElement
5196           * @returns {HTMLSectionElement}
5197           */
5198          render: function StrikeOutAnnotationElement_render() {
5199            this.container.className = 'strikeoutAnnotation';
5200
5201            if (!this.data.hasPopup) {
5202              this._createPopup(this.container, null, this.data);
5203            }
5204
5205            return this.container;
5206          },
5207        });
5208
5209        return StrikeOutAnnotationElement;
5210      })();
5211
5212      /**
5213       * @class
5214       * @alias FileAttachmentAnnotationElement
5215       */
5216      var FileAttachmentAnnotationElement = (function FileAttachmentAnnotationElementClosure() {
5217        function FileAttachmentAnnotationElement(parameters) {
5218          AnnotationElement.call(this, parameters, true);
5219
5220          this.filename = getFilenameFromUrl(parameters.data.file.filename);
5221          this.content = parameters.data.file.content;
5222        }
5223
5224        Util.inherit(FileAttachmentAnnotationElement, AnnotationElement, {
5225          /**
5226           * Render the file attachment annotation's HTML element in the empty
5227           * container.
5228           *
5229           * @public
5230           * @memberof FileAttachmentAnnotationElement
5231           * @returns {HTMLSectionElement}
5232           */
5233          render: function FileAttachmentAnnotationElement_render() {
5234            this.container.className = 'fileAttachmentAnnotation';
5235
5236            var trigger = document.createElement('div');
5237            trigger.style.height = this.container.style.height;
5238            trigger.style.width = this.container.style.width;
5239            trigger.addEventListener('dblclick', this._download.bind(this));
5240
5241            if (!this.data.hasPopup && (this.data.title || this.data.contents)) {
5242              this._createPopup(this.container, trigger, this.data);
5243            }
5244
5245            this.container.appendChild(trigger);
5246            return this.container;
5247          },
5248
5249          /**
5250           * Download the file attachment associated with this annotation.
5251           *
5252           * @private
5253           * @memberof FileAttachmentAnnotationElement
5254           */
5255          _download: function FileAttachmentAnnotationElement_download() {
5256            if (!this.downloadManager) {
5257              warn('Download cannot be started due to unavailable download manager');
5258              return;
5259            }
5260            this.downloadManager.downloadData(this.content, this.filename, '');
5261          },
5262        });
5263
5264        return FileAttachmentAnnotationElement;
5265      })();
5266
5267      /**
5268       * @typedef {Object} AnnotationLayerParameters
5269       * @property {PageViewport} viewport
5270       * @property {HTMLDivElement} div
5271       * @property {Array} annotations
5272       * @property {PDFPage} page
5273       * @property {IPDFLinkService} linkService
5274       * @property {string} imageResourcesPath
5275       * @property {boolean} renderInteractiveForms
5276       */
5277
5278      /**
5279       * @class
5280       * @alias AnnotationLayer
5281       */
5282      var AnnotationLayer = (function AnnotationLayerClosure() {
5283        return {
5284          /**
5285           * Render a new annotation layer with all annotation elements.
5286           *
5287           * @public
5288           * @param {AnnotationLayerParameters} parameters
5289           * @memberof AnnotationLayer
5290           */
5291          render: function AnnotationLayer_render(parameters) {
5292            var annotationElementFactory = new AnnotationElementFactory();
5293
5294            for (var i = 0, ii = parameters.annotations.length; i < ii; i++) {
5295              var data = parameters.annotations[i];
5296              if (!data) {
5297                continue;
5298              }
5299
5300              var properties = {
5301                data: data,
5302                layer: parameters.div,
5303                page: parameters.page,
5304                viewport: parameters.viewport,
5305                linkService: parameters.linkService,
5306                downloadManager: parameters.downloadManager,
5307                imageResourcesPath: parameters.imageResourcesPath || getDefaultSetting('imageResourcesPath'),
5308                renderInteractiveForms: parameters.renderInteractiveForms || false,
5309              };
5310              var element = annotationElementFactory.create(properties);
5311              if (element.isRenderable) {
5312                parameters.div.appendChild(element.render());
5313              }
5314            }
5315          },
5316
5317          /**
5318           * Update the annotation elements on existing annotation layer.
5319           *
5320           * @public
5321           * @param {AnnotationLayerParameters} parameters
5322           * @memberof AnnotationLayer
5323           */
5324          update: function AnnotationLayer_update(parameters) {
5325            for (var i = 0, ii = parameters.annotations.length; i < ii; i++) {
5326              var data = parameters.annotations[i];
5327              var element = parameters.div.querySelector('[data-annotation-id="' + data.id + '"]');
5328              if (element) {
5329                CustomStyle.setProp('transform', element, 'matrix(' + parameters.viewport.transform.join(',') + ')');
5330              }
5331            }
5332            parameters.div.removeAttribute('hidden');
5333          },
5334        };
5335      })();
5336
5337      exports.AnnotationLayer = AnnotationLayer;
5338    });
5339
5340    (function (root, factory) {
5341      {
5342        factory((root.pdfjsDisplayTextLayer = {}), root.pdfjsSharedUtil, root.pdfjsDisplayDOMUtils);
5343      }
5344    })(this, function (exports, sharedUtil, displayDOMUtils) {
5345      var Util = sharedUtil.Util;
5346      var createPromiseCapability = sharedUtil.createPromiseCapability;
5347      var CustomStyle = displayDOMUtils.CustomStyle;
5348      var getDefaultSetting = displayDOMUtils.getDefaultSetting;
5349
5350      /**
5351       * Text layer render parameters.
5352       *
5353       * @typedef {Object} TextLayerRenderParameters
5354       * @property {TextContent} textContent - Text content to render (the object is
5355       *   returned by the page's getTextContent() method).
5356       * @property {HTMLElement} container - HTML element that will contain text runs.
5357       * @property {PageViewport} viewport - The target viewport to properly
5358       *   layout the text runs.
5359       * @property {Array} textDivs - (optional) HTML elements that are correspond
5360       *   the text items of the textContent input. This is output and shall be
5361       *   initially be set to empty array.
5362       * @property {number} timeout - (optional) Delay in milliseconds before
5363       *   rendering of the text  runs occurs.
5364       * @property {boolean} enhanceTextSelection - (optional) Whether to turn on the
5365       *   text selection enhancement.
5366       */
5367      var renderTextLayer = (function renderTextLayerClosure() {
5368        var MAX_TEXT_DIVS_TO_RENDER = 100000;
5369
5370        var NonWhitespaceRegexp = /\S/;
5371
5372        function isAllWhitespace(str) {
5373          return !NonWhitespaceRegexp.test(str);
5374        }
5375
5376        // Text layers may contain many thousand div's, and using `styleBuf` avoids
5377        // creating many intermediate strings when building their 'style' properties.
5378        var styleBuf = ['left: ', 0, 'px; top: ', 0, 'px; font-size: ', 0, 'px; font-family: ', '', ';'];
5379
5380        function appendText(task, geom, styles) {
5381          // Initialize all used properties to keep the caches monomorphic.
5382          var textDiv = document.createElement('div');
5383          var textDivProperties = {
5384            style: null,
5385            angle: 0,
5386            canvasWidth: 0,
5387            isWhitespace: false,
5388            originalTransform: null,
5389            paddingBottom: 0,
5390            paddingLeft: 0,
5391            paddingRight: 0,
5392            paddingTop: 0,
5393            scale: 1,
5394          };
5395
5396          task._textDivs.push(textDiv);
5397          if (isAllWhitespace(geom.str)) {
5398            textDivProperties.isWhitespace = true;
5399            task._textDivProperties.set(textDiv, textDivProperties);
5400            return;
5401          }
5402
5403          var tx = Util.transform(task._viewport.transform, geom.transform);
5404          var angle = Math.atan2(tx[1], tx[0]);
5405          var style = styles[geom.fontName];
5406          if (style.vertical) {
5407            angle += Math.PI / 2;
5408          }
5409          var fontHeight = Math.sqrt(tx[2] * tx[2] + tx[3] * tx[3]);
5410          var fontAscent = fontHeight;
5411          if (style.ascent) {
5412            fontAscent = style.ascent * fontAscent;
5413          }
5413 else if (style.descent) {
5414            fontAscent = (1 + style.descent) * fontAscent;
5415          }
5416
5417          var left;
5418          var top;
5419          if (angle === 0) {
5420            left = tx[4];
5421            top = tx[5] - fontAscent;
5422          } else {
5423            left = tx[4] + fontAscent * Math.sin(angle);
5424            top = tx[5] - fontAscent * Math.cos(angle);
5425          }
5426          styleBuf[1] = left;
5427          styleBuf[3] = top;
5428          styleBuf[5] = fontHeight;
5429          styleBuf[7] = style.fontFamily;
5430          textDivProperties.style = styleBuf.join('');
5431          textDiv.setAttribute('style', textDivProperties.style);
5432
5433          textDiv.textContent = geom.str;
5434          // |fontName| is only used by the Font Inspector. This test will succeed
5435          // when e.g. the Font Inspector is off but the Stepper is on, but it's
5436          // not worth the effort to do a more accurate test. We only use `dataset`
5437          // here to make the font name available for the debugger.
5438          if (getDefaultSetting('pdfBug')) {
5439            textDiv.dataset.fontName = geom.fontName;
5440          }
5441          if (angle !== 0) {
5442            textDivProperties.angle = angle * (180 / Math.PI);
5443          }
5444          // We don't bother scaling single-char text divs, because it has very
5445          // little effect on text highlighting. This makes scrolling on docs with
5446          // lots of such divs a lot faster.
5447          if (geom.str.length > 1) {
5448            if (style.vertical) {
5449              textDivProperties.canvasWidth = geom.height * task._viewport.scale;
5450            } else {
5451              textDivProperties.canvasWidth = geom.width * task._viewport.scale;
5452            }
5453          }
5454          task._textDivProperties.set(textDiv, textDivProperties);
5455
5456          if (task._enhanceTextSelection) {
5457            var angleCos = 1,
5458              angleSin = 0;
5459            if (angle !== 0) {
5460              angleCos = Math.cos(angle);
5461              angleSin = Math.sin(angle);
5462            }
5463            var divWidth = (style.vertical ? geom.height : geom.width) * task._viewport.scale;
5464            var divHeight = fontHeight;
5465
5466            var m, b;
5467            if (angle !== 0) {
5468              m = [angleCos, angleSin, -angleSin, angleCos, left, top];
5469              b = Util.getAxialAlignedBoundingBox([0, 0, divWidth, divHeight], m);
5470            } else {
5471              b = [left, top, left + divWidth, top + divHeight];
5472            }
5473
5474            task._bounds.push({
5475              left: b[0],
5476              top: b[1],
5477              right: b[2],
5478              bottom: b[3],
5479              div: textDiv,
5480              size: [divWidth, divHeight],
5481              m: m,
5482            });
5483          }
5484        }
5485
5486        function render(task) {
5487          if (task._canceled) {
5488            return;
5489          }
5490          var textLayerFrag = task._container;
5491          var textDivs = task._textDivs;
5492          var capability = task._capability;
5493          var textDivsLength = textDivs.length;
5494
5495          // No point in rendering many divs as it would make the browser
5496          // unusable even after the divs are rendered.
5497          if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) {
5498            task._renderingDone = true;
5499            capability.resolve();
5500            return;
5501          }
5502
5503          var canvas = document.createElement('canvas');
5504          canvas.mozOpaque = true;
5505          var ctx = canvas.getContext('2d', { alpha: false });
5506
5507          var lastFontSize;
5508          var lastFontFamily;
5509          for (var i = 0; i < textDivsLength; i++) {
5510            var textDiv = textDivs[i];
5511            var textDivProperties = task._textDivProperties.get(textDiv);
5512            if (textDivProperties.isWhitespace) {
5513              continue;
5514            }
5515
5516            var fontSize = textDiv.style.fontSize;
5517            var fontFamily = textDiv.style.fontFamily;
5518
5519            // Only build font string and set to context if different from last.
5520            if (fontSize !== lastFontSize || fontFamily !== lastFontFamily) {
5521              ctx.font = fontSize + ' ' + fontFamily;
5522              lastFontSize = fontSize;
5523              lastFontFamily = fontFamily;
5524            }
5525
5526            var width = ctx.measureText(textDiv.textContent).width;
5527            textLayerFrag.appendChild(textDiv);
5528
5529            var transform = '';
5530            if (textDivProperties.canvasWidth !== 0 && width > 0) {
5531              textDivProperties.scale = textDivProperties.canvasWidth / width;
5532              transform = 'scaleX(' + textDivProperties.scale + ')';
5533            }
5534            if (textDivProperties.angle !== 0) {
5535              transform = 'rotate(' + textDivProperties.angle + 'deg) ' + transform;
5536            }
5537            if (transform !== '') {
5538              textDivProperties.originalTransform = transform;
5539              CustomStyle.setProp('transform', textDiv, transform);
5540            }
5541            task._textDivProperties.set(textDiv, textDivProperties);
5542          }
5543          task._renderingDone = true;
5544          capability.resolve();
5545        }
5546
5547        function expand(task) {
5548          var bounds = task._bounds;
5549          var viewport = task._viewport;
5550
5551          var expanded = expandBounds(viewport.width, viewport.height, bounds);
5552          for (var i = 0; i < expanded.length; i++) {
5553            var div = bounds[i].div;
5554            var divProperties = task._textDivProperties.get(div);
5555            if (divProperties.angle === 0) {
5556              divProperties.paddingLeft = bounds[i].left - expanded[i].left;
5557              divProperties.paddingTop = bounds[i].top - expanded[i].top;
5558              divProperties.paddingRight = expanded[i].right - bounds[i].right;
5559              divProperties.paddingBottom = expanded[i].bottom - bounds[i].bottom;
5560              task._textDivProperties.set(div, divProperties);
5561              continue;
5562            }
5563            // Box is rotated -- trying to find padding so rotated div will not
5564            // exceed its expanded bounds.
5565            var e = expanded[i],
5566              b = bounds[i];
5567            var m = b.m,
5568              c = m[0],
5569              s = m[1];
5570            // Finding intersections with expanded box.
5571            var points = [[0, 0], [0, b.size[1]], [b.size[0], 0], b.size];
5572            var ts = new Float64Array(64);
5573            points.forEach(function (p, i) {
5574              var t = Util.applyTransform(p, m);
5575              ts[i + 0] = c && (e.left - t[0]) / c;
5576              ts[i + 4] = s && (e.top - t[1]) / s;
5577              ts[i + 8] = c && (e.right - t[0]) / c;
5578              ts[i + 12] = s && (e.bottom - t[1]) / s;
5579
5580              ts[i + 16] = s && (e.left - t[0]) / -s;
5581              ts[i + 20] = c && (e.top - t[1]) / c;
5582              ts[i + 24] = s && (e.right - t[0]) / -s;
5583              ts[i + 28] = c && (e.bottom - t[1]) / c;
5584
5585              ts[i + 32] = c && (e.left - t[0]) / -c;
5586              ts[i + 36] = s && (e.top - t[1]) / -s;
5587              ts[i + 40] = c && (e.right - t[0]) / -c;
5588              ts[i + 44] = s && (e.bottom - t[1]) / -s;
5589
5590              ts[i + 48] = s && (e.left - t[0]) / s;
5591              ts[i + 52] = c && (e.top - t[1]) / -c;
5592              ts[i + 56] = s && (e.right - t[0]) / s;
5593              ts[i + 60] = c && (e.bottom - t[1]) / -c;
5594            });
5595            var findPositiveMin = function (ts, offset, count) {
5596              var result = 0;
5597              for (var i = 0; i < count; i++) {
5598                var t = ts[offset++];
5599                if (t > 0) {
5600                  result = result ? Math.min(t, result) : t;
5601                }
5602              }
5603              return result;
5604            };
5605            // Not based on math, but to simplify calculations, using cos and sin
5606            // absolute values to not exceed the box (it can but insignificantly).
5607            var boxScale = 1 + Math.min(Math.abs(c), Math.abs(s));
5608            divProperties.paddingLeft = findPositiveMin(ts, 32, 16) / boxScale;
5609            divProperties.paddingTop = findPositiveMin(ts, 48, 16) / boxScale;
5610            divProperties.paddingRight = findPositiveMin(ts, 0, 16) / boxScale;
5611            divProperties.paddingBottom = findPositiveMin(ts, 16, 16) / boxScale;
5612            task._textDivProperties.set(div, divProperties);
5613          }
5614        }
5615
5616        function expandBounds(width, height, boxes) {
5617          var bounds = boxes.map(function (box, i) {
5618            return {
5619              x1: box.left,
5620              y1: box.top,
5621              x2: box.right,
5622              y2: box.bottom,
5623              index: i,
5624              x1New: undefined,
5625              x2New: undefined,
5626            };
5627          });
5628          expandBoundsLTR(width, bounds);
5629          var expanded = new Array(boxes.length);
5630          bounds.forEach(function (b) {
5631            var i = b.index;
5632            expanded[i] = {
5633              left: b.x1New,
5634              top: 0,
5635              right: b.x2New,
5636              bottom: 0,
5637            };
5638          });
5639
5640          // Rotating on 90 degrees and extending extended boxes. Reusing the bounds
5641          // array and objects.
5642          boxes.map(function (box, i) {
5643            var e = expanded[i],
5644              b = bounds[i];
5645            b.x1 = box.top;
5646            b.y1 = width - e.right;
5647            b.x2 = box.bottom;
5648            b.y2 = width - e.left;
5649            b.index = i;
5650            b.x1New = undefined;
5651            b.x2New = undefined;
5652          });
5653          expandBoundsLTR(height, bounds);
5654
5655          bounds.forEach(function (b) {
5656            var i = b.index;
5657            expanded[i].top = b.x1New;
5658            expanded[i].bottom = b.x2New;
5659          });
5660          return expanded;
5661        }
5662
5663        function expandBoundsLTR(width, bounds) {
5664          // Sorting by x1 coordinate and walk by the bounds in the same order.
5665          bounds.sort(function (a, b) {
5666            return a.x1 - b.x1 || a.index - b.index;
5667          });
5668
5669          // First we see on the horizon is a fake boundary.
5670          var fakeBoundary = {
5671            x1: -Infinity,
5672            y1: -Infinity,
5673            x2: 0,
5674            y2: Infinity,
5675            index: -1,
5676            x1New: 0,
5677            x2New: 0,
5678          };
5679          var horizon = [
5680            {
5681              start: -Infinity,
5682              end: Infinity,
5683              boundary: fakeBoundary,
5684            },
5685          ];
5686
5687          bounds.forEach(function (boundary) {
5688            // Searching for the affected part of horizon.
5689            // TODO red-black tree or simple binary search
5690            var i = 0;
5691            while (i < horizon.length && horizon[i].end <= boundary.y1) {
5692              i++;
5693            }
5694            var j = horizon.length - 1;
5695            while (j >= 0 && horizon[j].start >= boundary.y2) {
5696              j--;
5697            }
5698
5699            var horizonPart, affectedBoundary;
5700            var q,
5701              k,
5702              maxXNew = -Infinity;
5703            for (q = i; q <= j; q++) {
5704              horizonPart = horizon[q];
5705              affectedBoundary = horizonPart.boundary;
5706              var xNew;
5707              if (affectedBoundary.x2 > boundary.x1) {
5708                // In the middle of the previous element, new x shall be at the
5709                // boundary start. Extending if further if the affected bondary
5710                // placed on top of the current one.
5711                xNew = affectedBoundary.index > boundary.index ? affectedBoundary.x1New : boundary.x1;
5712              } else if (affectedBoundary.x2New === undefined) {
5713                // We have some space in between, new x in middle will be a fair
5714                // choice.
5715                xNew = (affectedBoundary.x2 + boundary.x1) / 2;
5716              } else {
5717                // Affected boundary has x2new set, using it as new x.
5718                xNew = affectedBoundary.x2New;
5719              }
5720              if (xNew > maxXNew) {
5721                maxXNew = xNew;
5722              }
5723            }
5724
5725            // Set new x1 for current boundary.
5726            boundary.x1New = maxXNew;
5727
5728            // Adjusts new x2 for the affected boundaries.
5729            for (q = i; q <= j; q++) {
5730              horizonPart = horizon[q];
5731              affectedBoundary = horizonPart.boundary;
5732              if (affectedBoundary.x2New === undefined) {
5733                // Was not set yet, choosing new x if possible.
5734                if (affectedBoundary.x2 > boundary.x1) {
5735                  // Current and affected boundaries intersect. If affected boundary
5736                  // is placed on top of the current, shrinking the affected.
5737                  if (affectedBoundary.index > boundary.index) {
5738                    affectedBoundary.x2New = affectedBoundary.x2;
5739                  }
5740                } else {
5741                  affectedBoundary.x2New = maxXNew;
5742                }
5743              } else if (affectedBoundary.x2New > maxXNew) {
5744                // Affected boundary is touching new x, pushing it back.
5745                affectedBoundary.x2New = Math.max(maxXNew, affectedBoundary.x2);
5746              }
5747            }
5748
5749            // Fixing the horizon.
5750            var changedHorizon = [],
5751              lastBoundary = null;
5752            for (q = i; q <= j; q++) {
5753              horizonPart = horizon[q];
5754              affectedBoundary = horizonPart.boundary;
5755              // Checking which boundary will be visible.
5756              var useBoundary = affectedBoundary.x2 > boundary.x2 ? affectedBoundary : boundary;
5757              if (lastBoundary === useBoundary) {
5758                // Merging with previous.
5759                changedHorizon[changedHorizon.length - 1].end = horizonPart.end;
5760              } else {
5761                changedHorizon.push({
5762                  start: horizonPart.start,
5763                  end: horizonPart.end,
5764                  boundary: useBoundary,
5765                });
5766                lastBoundary = useBoundary;
5767              }
5768            }
5769            if (horizon[i].start < boundary.y1) {
5770              changedHorizon[0].start = boundary.y1;
5771              changedHorizon.unshift({
5772                start: horizon[i].start,
5773                end: boundary.y1,
5774                boundary: horizon[i].boundary,
5775              });
5776            }
5777            if (boundary.y2 < horizon[j].end) {
5778              changedHorizon[changedHorizon.length - 1].end = boundary.y2;
5779              changedHorizon.push({
5780                start: boundary.y2,
5781                end: horizon[j].end,
5782                boundary: horizon[j].boundary,
5783              });
5784            }
5785
5786            // Set x2 new of boundary that is no longer visible (see overlapping case
5787            // above).
5788            // TODO more efficient, e.g. via reference counting.
5789            for (q = i; q <= j; q++) {
5790              horizonPart = horizon[q];
5791              affectedBoundary = horizonPart.boundary;
5792              if (affectedBoundary.x2New !== undefined) {
5793                continue;
5794              }
5795              var used = false;
5796              for (k = i - 1; !used && k >= 0 && horizon[k].start >= affectedBoundary.y1; k--) {
5797                used = horizon[k].boundary === affectedBoundary;
5798              }
5799              for (k = j + 1; !used && k < horizon.length && horizon[k].end <= affectedBoundary.y2; k++) {
5800                used = horizon[k].boundary === affectedBoundary;
5801              }
5802              for (k = 0; !used && k < changedHorizon.length; k++) {
5803                used = changedHorizon[k].boundary === affectedBoundary;
5804              }
5805              if (!used) {
5806                affectedBoundary.x2New = maxXNew;
5807              }
5808            }
5809
5810            Array.prototype.splice.apply(horizon, [i, j - i + 1].concat(changedHorizon));
5811          });
5812
5813          // Set new x2 for all unset boundaries.
5814          horizon.forEach(function (horizonPart) {
5815            var affectedBoundary = horizonPart.boundary;
5816            if (affectedBoundary.x2New === undefined) {
5817              affectedBoundary.x2New = Math.max(width, affectedBoundary.x2);
5818            }
5819          });
5820        }
5821
5822        /**
5823         * Text layer rendering task.
5824         *
5825         * @param {TextContent} textContent
5826         * @param {HTMLElement} container
5827         * @param {PageViewport} viewport
5828         * @param {Array} textDivs
5829         * @param {boolean} enhanceTextSelection
5830         * @private
5831         */
5832        function TextLayerRenderTask(textContent, container, viewport, textDivs, enhanceTextSelection) {
5833          this._textContent = textContent;
5834          this._container = container;
5835          this._viewport = viewport;
5836          this._textDivs = textDivs || [];
5837          this._textDivProperties = new WeakMap();
5838          this._renderingDone = false;
5839          this._canceled = false;
5840          this._capability = createPromiseCapability();
5841          this._renderTimer = null;
5842          this._bounds = [];
5843          this._enhanceTextSelection = !!enhanceTextSelection;
5844        }
5845
5846        TextLayerRenderTask.prototype = {
5847          get promise() {
5848            return this._capability.promise;
5849          },
5850
5851          cancel: function TextLayer_cancel() {
5852            this._canceled = true;
5853            if (this._renderTimer !== null) {
5854              clearTimeout(this._renderTimer);
5855              this._renderTimer = null;
5856            }
5857            this._capability.reject('canceled');
5858          },
5859
5860          _render: function TextLayer_render(timeout) {
5861            var textItems = this._textContent.items;
5862            var textStyles = this._textContent.styles;
5863            for (var i = 0, len = textItems.length; i < len; i++) {
5864              appendText(this, textItems[i], textStyles);
5865            }
5866
5867            if (!timeout) {
5868              // Render right away
5869              render(this);
5870            } else {
5871              // Schedule
5872              var self = this;
5873              this._renderTimer = setTimeout(function () {
5874                render(self);
5875                self._renderTimer = null;
5876              }, timeout);
5877            }
5878          },
5879
5880          expandTextDivs: function TextLayer_expandTextDivs(expandDivs) {
5881            if (!this._enhanceTextSelection || !this._renderingDone) {
5882              return;
5883            }
5884            if (this._bounds !== null) {
5885              expand(this);
5886              this._bounds = null;
5887            }
5888
5889            for (var i = 0, ii = this._textDivs.length; i < ii; i++) {
5890              var div = this._textDivs[i];
5891              var divProperties = this._textDivProperties.get(div);
5892
5893              if (divProperties.isWhitespace) {
5894                continue;
5895              }
5896              if (expandDivs) {
5897                var transform = '',
5898                  padding = '';
5899
5900                if (divProperties.scale !== 1) {
5901                  transform = 'scaleX(' + divProperties.scale + ')';
5902                }
5903                if (divProperties.angle !== 0) {
5904                  transform = 'rotate(' + divProperties.angle + 'deg) ' + transform;
5905                }
5906                if (divProperties.paddingLeft !== 0) {
5907                  padding += ' padding-left: ' + divProperties.paddingLeft / divProperties.scale + 'px;';
5908                  transform += ' translateX(' + -divProperties.paddingLeft / divProperties.scale + 'px)';
5909                }
5910                if (divProperties.paddingTop !== 0) {
5911                  padding += ' padding-top: ' + divProperties.paddingTop + 'px;';
5912                  transform += ' translateY(' + -divProperties.paddingTop + 'px)';
5913                }
5914                if (divProperties.paddingRight !== 0) {
5915                  padding += ' padding-right: ' + divProperties.paddingRight / divProperties.scale + 'px;';
5916                }
5917                if (divProperties.paddingBottom !== 0) {
5918                  padding += ' padding-bottom: ' + divProperties.paddingBottom + 'px;';
5919                }
5920
5921                if (padding !== '') {
5922                  div.setAttribute('style', divProperties.style + padding);
5923                }
5924                if (transform !== '') {
5925                  CustomStyle.setProp('transform', div, transform);
5926                }
5927              } else {
5928                div.style.padding = 0;
5929                CustomStyle.setProp('transform', div, divProperties.originalTransform || '');
5930              }
5931            }
5932          },
5933        };
5934
5935        /**
5936         * Starts rendering of the text layer.
5937         *
5938         * @param {TextLayerRenderParameters} renderParameters
5939         * @returns {TextLayerRenderTask}
5940         */
5941        function renderTextLayer(renderParameters) {
5942          var task = new TextLayerRenderTask(
5943            renderParameters.textContent,
5944            renderParameters.container,
5945            renderParameters.viewport,
5946            renderParameters.textDivs,
5947            renderParameters.enhanceTextSelection
5948          );
5949          task._render(renderParameters.timeout);
5950          return task;
5951        }
5952
5953        return renderTextLayer;
5954      })();
5955
5956      exports.renderTextLayer = renderTextLayer;
5957    });
5958
5959    (function (root, factory) {
5960      {
5961        factory((root.pdfjsDisplayWebGL = {}), root.pdfjsSharedUtil, root.pdfjsDisplayDOMUtils);
5962      }
5963    })(this, function (exports, sharedUtil, displayDOMUtils) {
5964      var shadow = sharedUtil.shadow;
5965      var getDefaultSetting = displayDOMUtils.getDefaultSetting;
5966
5967      var WebGLUtils = (function WebGLUtilsClosure() {
5968        function loadShader(gl, code, shaderType) {
5969          var shader = gl.createShader(shaderType);
vendor: 24,909 bytes, lines 5970-6591
5970          gl.shaderSource(shader, code);
5971          gl.compileShader(shader);
5972          var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
5973          if (!compiled) {
5974            var errorMsg = gl.getShaderInfoLog(shader);
5975            throw new Error('Error during shader compilation: ' + errorMsg);
5976          }
5977          return shader;
5978        }
5979
5980        function createVertexShader(gl, code) {
5981          return loadShader(gl, code, gl.VERTEX_SHADER);
5982        }
5983
5984        function createFragmentShader(gl, code) {
5985          return loadShader(gl, code, gl.FRAGMENT_SHADER);
5986        }
5987
5988        function createProgram(gl, shaders) {
5989          var program = gl.createProgram();
5990          for (var i = 0, ii = shaders.length; i < ii; ++i) {
5991            gl.attachShader(program, shaders[i]);
5992          }
5993          gl.linkProgram(program);
5994          var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
5995          if (!linked) {
5996            var errorMsg = gl.getProgramInfoLog(program);
5997            throw new Error('Error during program linking: ' + errorMsg);
5998          }
5999          return program;
6000        }
6001
6002        function createTexture(gl, image, textureId) {
6003          gl.activeTexture(textureId);
6004          var texture = gl.createTexture();
6005          gl.bindTexture(gl.TEXTURE_2D, texture);
6006
6007          // Set the parameters so we can render any size image.
6008          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
6009          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
6010          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
6011          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
6012
6013          // Upload the image into the texture.
6014          gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
6015          return texture;
6016        }
6017
6018        var currentGL, currentCanvas;
6019
6020        function generateGL() {
6021          if (currentGL) {
6022            return;
6023          }
6024          currentCanvas = document.createElement('canvas');
6025          currentGL = currentCanvas.getContext('webgl', {
6026            premultipliedalpha: false,
6027          });
6028        }
6029
6030        var smaskVertexShaderCode =
6031          '\
6032  attribute vec2 a_position;                                    \
6033  attribute vec2 a_texCoord;                                    \
6034                                                                \
6035  uniform vec2 u_resolution;                                    \
6036                                                                \
6037  varying vec2 v_texCoord;                                      \
6038                                                                \
6039  void main() {                                                 \
6040    vec2 clipSpace = (a_position / u_resolution) * 2.0 - 1.0;   \
6041    gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);          \
6042                                                                \
6043    v_texCoord = a_texCoord;                                    \
6044  }                                                             ';
6045
6046        var smaskFragmentShaderCode =
6047          '\
6048  precision mediump float;                                      \
6049                                                                \
6050  uniform vec4 u_backdrop;                                      \
6051  uniform int u_subtype;                                        \
6052  uniform sampler2D u_image;                                    \
6053  uniform sampler2D u_mask;                                     \
6054                                                                \
6055  varying vec2 v_texCoord;                                      \
6056                                                                \
6057  void main() {                                                 \
6058    vec4 imageColor = texture2D(u_image, v_texCoord);           \
6059    vec4 maskColor = texture2D(u_mask, v_texCoord);             \
6060    if (u_backdrop.a > 0.0) {                                   \
6061      maskColor.rgb = maskColor.rgb * maskColor.a +             \
6062                      u_backdrop.rgb * (1.0 - maskColor.a);     \
6063    }                                                           \
6064    float lum;                                                  \
6065    if (u_subtype == 0) {                                       \
6066      lum = maskColor.a;                                        \
6067    } else {                                                    \
6068      lum = maskColor.r * 0.3 + maskColor.g * 0.59 +            \
6069            maskColor.b * 0.11;                                 \
6070    }                                                           \
6071    imageColor.a *= lum;                                        \
6072    imageColor.rgb *= imageColor.a;                             \
6073    gl_FragColor = imageColor;                                  \
6074  }                                                             ';
6075
6076        var smaskCache = null;
6077
6078        function initSmaskGL() {
6079          var canvas, gl;
6080
6081          generateGL();
6082          canvas = currentCanvas;
6083          currentCanvas = null;
6084          gl = currentGL;
6085          currentGL = null;
6086
6087          // setup a GLSL program
6088          var vertexShader = createVertexShader(gl, smaskVertexShaderCode);
6089          var fragmentShader = createFragmentShader(gl, smaskFragmentShaderCode);
6090          var program = createProgram(gl, [vertexShader, fragmentShader]);
6091          gl.useProgram(program);
6092
6093          var cache = {};
6094          cache.gl = gl;
6095          cache.canvas = canvas;
6096          cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
6097          cache.positionLocation = gl.getAttribLocation(program, 'a_position');
6098          cache.backdropLocation = gl.getUniformLocation(program, 'u_backdrop');
6099          cache.subtypeLocation = gl.getUniformLocation(program, 'u_subtype');
6100
6101          var texCoordLocation = gl.getAttribLocation(program, 'a_texCoord');
6102          var texLayerLocation = gl.getUniformLocation(program, 'u_image');
6103          var texMaskLocation = gl.getUniformLocation(program, 'u_mask');
6104
6105          // provide texture coordinates for the rectangle.
6106          var texCoordBuffer = gl.createBuffer();
6107          gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
6108          gl.bufferData(
6109            gl.ARRAY_BUFFER,
6110            new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0]),
6111            gl.STATIC_DRAW
6112          );
6113          gl.enableVertexAttribArray(texCoordLocation);
6114          gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
6115
6116          gl.uniform1i(texLayerLocation, 0);
6117          gl.uniform1i(texMaskLocation, 1);
6118
6119          smaskCache = cache;
6120        }
6121
6122        function composeSMask(layer, mask, properties) {
6123          var width = layer.width,
6124            height = layer.height;
6125
6126          if (!smaskCache) {
6127            initSmaskGL();
6128          }
6129          var cache = smaskCache,
6130            canvas = cache.canvas,
6131            gl = cache.gl;
6132          canvas.width = width;
6133          canvas.height = height;
6134          gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
6135          gl.uniform2f(cache.resolutionLocation, width, height);
6136
6137          if (properties.backdrop) {
6138            gl.uniform4f(
6139              cache.resolutionLocation,
6140              properties.backdrop[0],
6141              properties.backdrop[1],
6142              properties.backdrop[2],
6143              1
6144            );
6145          } else {
6146            gl.uniform4f(cache.resolutionLocation, 0, 0, 0, 0);
6147          }
6148          gl.uniform1i(cache.subtypeLocation, properties.subtype === 'Luminosity' ? 1 : 0);
6149
6150          // Create a textures
6151          var texture = createTexture(gl, layer, gl.TEXTURE0);
6152          var maskTexture = createTexture(gl, mask, gl.TEXTURE1);
6153
6154          // Create a buffer and put a single clipspace rectangle in
6155          // it (2 triangles)
6156          var buffer = gl.createBuffer();
6157          gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
6158          gl.bufferData(
6159            gl.ARRAY_BUFFER,
6160            new Float32Array([0, 0, width, 0, 0, height, 0, height, width, 0, width, height]),
6161            gl.STATIC_DRAW
6162          );
6163          gl.enableVertexAttribArray(cache.positionLocation);
6164          gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0);
6165
6166          // draw
6167          gl.clearColor(0, 0, 0, 0);
6168          gl.enable(gl.BLEND);
6169          gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
6170          gl.clear(gl.COLOR_BUFFER_BIT);
6171
6172          gl.drawArrays(gl.TRIANGLES, 0, 6);
6173
6174          gl.flush();
6175
6176          gl.deleteTexture(texture);
6177          gl.deleteTexture(maskTexture);
6178          gl.deleteBuffer(buffer);
6179
6180          return canvas;
6181        }
6182
6183        var figuresVertexShaderCode =
6184          '\
6185  attribute vec2 a_position;                                    \
6186  attribute vec3 a_color;                                       \
6187                                                                \
6188  uniform vec2 u_resolution;                                    \
6189  uniform vec2 u_scale;                                         \
6190  uniform vec2 u_offset;                                        \
6191                                                                \
6192  varying vec4 v_color;                                         \
6193                                                                \
6194  void main() {                                                 \
6195    vec2 position = (a_position + u_offset) * u_scale;          \
6196    vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0;     \
6197    gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);          \
6198                                                                \
6199    v_color = vec4(a_color / 255.0, 1.0);                       \
6200  }                                                             ';
6201
6202        var figuresFragmentShaderCode =
6203          '\
6204  precision mediump float;                                      \
6205                                                                \
6206  varying vec4 v_color;                                         \
6207                                                                \
6208  void main() {                                                 \
6209    gl_FragColor = v_color;                                     \
6210  }                                                             ';
6211
6212        var figuresCache = null;
6213
6214        function initFiguresGL() {
6215          var canvas, gl;
6216
6217          generateGL();
6218          canvas = currentCanvas;
6219          currentCanvas = null;
6220          gl = currentGL;
6221          currentGL = null;
6222
6223          // setup a GLSL program
6224          var vertexShader = createVertexShader(gl, figuresVertexShaderCode);
6225          var fragmentShader = createFragmentShader(gl, figuresFragmentShaderCode);
6226          var program = createProgram(gl, [vertexShader, fragmentShader]);
6227          gl.useProgram(program);
6228
6229          var cache = {};
6230          cache.gl = gl;
6231          cache.canvas = canvas;
6232          cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
6233          cache.scaleLocation = gl.getUniformLocation(program, 'u_scale');
6234          cache.offsetLocation = gl.getUniformLocation(program, 'u_offset');
6235          cache.positionLocation = gl.getAttribLocation(program, 'a_position');
6236          cache.colorLocation = gl.getAttribLocation(program, 'a_color');
6237
6238          figuresCache = cache;
6239        }
6240
6241        function drawFigures(width, height, backgroundColor, figures, context) {
6242          if (!figuresCache) {
6243            initFiguresGL();
6244          }
6245          var cache = figuresCache,
6246            canvas = cache.canvas,
6247            gl = cache.gl;
6248
6249          canvas.width = width;
6250          canvas.height = height;
6251          gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
6252          gl.uniform2f(cache.resolutionLocation, width, height);
6253
6254          // count triangle points
6255          var count = 0;
6256          var i, ii, rows;
6257          for (i = 0, ii = figures.length; i < ii; i++) {
6258            switch (figures[i].type) {
6259              case 'lattice':
6260                rows = (figures[i].coords.length / figures[i].verticesPerRow) | 0;
6261                count += (rows - 1) * (figures[i].verticesPerRow - 1) * 6;
6262                break;
6263              case 'triangles':
6264                count += figures[i].coords.length;
6265                break;
6266            }
6267          }
6268          // transfer data
6269          var coords = new Float32Array(count * 2);
6270          var colors = new Uint8Array(count * 3);
6271          var coordsMap = context.coords,
6272            colorsMap = context.colors;
6273          var pIndex = 0,
6274            cIndex = 0;
6275          for (i = 0, ii = figures.length; i < ii; i++) {
6276            var figure = figures[i],
6277              ps = figure.coords,
6278              cs = figure.colors;
6279            switch (figure.type) {
6280              case 'lattice':
6281                var cols = figure.verticesPerRow;
6282                rows = (ps.length / cols) | 0;
6283                for (var row = 1; row < rows; row++) {
6284                  var offset = row * cols + 1;
6285                  for (var col = 1; col < cols; col++, offset++) {
6286                    coords[pIndex] = coordsMap[ps[offset - cols - 1]];
6287                    coords[pIndex + 1] = coordsMap[ps[offset - cols - 1] + 1];
6288                    coords[pIndex + 2] = coordsMap[ps[offset - cols]];
6289                    coords[pIndex + 3] = coordsMap[ps[offset - cols] + 1];
6290                    coords[pIndex + 4] = coordsMap[ps[offset - 1]];
6291                    coords[pIndex + 5] = coordsMap[ps[offset - 1] + 1];
6292                    colors[cIndex] = colorsMap[cs[offset - cols - 1]];
6293                    colors[cIndex + 1] = colorsMap[cs[offset - cols - 1] + 1];
6294                    colors[cIndex + 2] = colorsMap[cs[offset - cols - 1] + 2];
6295                    colors[cIndex + 3] = colorsMap[cs[offset - cols]];
6296                    colors[cIndex + 4] = colorsMap[cs[offset - cols] + 1];
6297                    colors[cIndex + 5] = colorsMap[cs[offset - cols] + 2];
6298                    colors[cIndex + 6] = colorsMap[cs[offset - 1]];
6299                    colors[cIndex + 7] = colorsMap[cs[offset - 1] + 1];
6300                    colors[cIndex + 8] = colorsMap[cs[offset - 1] + 2];
6301
6302                    coords[pIndex + 6] = coords[pIndex + 2];
6303                    coords[pIndex + 7] = coords[pIndex + 3];
6304                    coords[pIndex + 8] = coords[pIndex + 4];
6305                    coords[pIndex + 9] = coords[pIndex + 5];
6306                    coords[pIndex + 10] = coordsMap[ps[offset]];
6307                    coords[pIndex + 11] = coordsMap[ps[offset] + 1];
6308                    colors[cIndex + 9] = colors[cIndex + 3];
6309                    colors[cIndex + 10] = colors[cIndex + 4];
6310                    colors[cIndex + 11] = colors[cIndex + 5];
6311                    colors[cIndex + 12] = colors[cIndex + 6];
6312                    colors[cIndex + 13] = colors[cIndex + 7];
6313                    colors[cIndex + 14] = colors[cIndex + 8];
6314                    colors[cIndex + 15] = colorsMap[cs[offset]];
6315                    colors[cIndex + 16] = colorsMap[cs[offset] + 1];
6316                    colors[cIndex + 17] = colorsMap[cs[offset] + 2];
6317                    pIndex += 12;
6318                    cIndex += 18;
6319                  }
6320                }
6321                break;
6322              case 'triangles':
6323                for (var j = 0, jj = ps.length; j < jj; j++) {
6324                  coords[pIndex] = coordsMap[ps[j]];
6325                  coords[pIndex + 1] = coordsMap[ps[j] + 1];
6326                  colors[cIndex] = colorsMap[cs[j]];
6327                  colors[cIndex + 1] = colorsMap[cs[j] + 1];
6328                  colors[cIndex + 2] = colorsMap[cs[j] + 2];
6329                  pIndex += 2;
6330                  cIndex += 3;
6331                }
6332                break;
6333            }
6334          }
6335
6336          // draw
6337          if (backgroundColor) {
6338            gl.clearColor(backgroundColor[0] / 255, backgroundColor[1] / 255, backgroundColor[2] / 255, 1.0);
6339          } else {
6340            gl.clearColor(0, 0, 0, 0);
6341          }
6342          gl.clear(gl.COLOR_BUFFER_BIT);
6343
6344          var coordsBuffer = gl.createBuffer();
6345          gl.bindBuffer(gl.ARRAY_BUFFER, coordsBuffer);
6346          gl.bufferData(gl.ARRAY_BUFFER, coords, gl.STATIC_DRAW);
6347          gl.enableVertexAttribArray(cache.positionLocation);
6348          gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0);
6349
6350          var colorsBuffer = gl.createBuffer();
6351          gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer);
6352          gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
6353          gl.enableVertexAttribArray(cache.colorLocation);
6354          gl.vertexAttribPointer(cache.colorLocation, 3, gl.UNSIGNED_BYTE, false, 0, 0);
6355
6356          gl.uniform2f(cache.scaleLocation, context.scaleX, context.scaleY);
6357          gl.uniform2f(cache.offsetLocation, context.offsetX, context.offsetY);
6358
6359          gl.drawArrays(gl.TRIANGLES, 0, count);
6360
6361          gl.flush();
6362
6363          gl.deleteBuffer(coordsBuffer);
6364          gl.deleteBuffer(colorsBuffer);
6365
6366          return canvas;
6367        }
6368
6369        function cleanup() {
6370          if (smaskCache && smaskCache.canvas) {
6371            smaskCache.canvas.width = 0;
6372            smaskCache.canvas.height = 0;
6373          }
6374          if (figuresCache && figuresCache.canvas) {
6375            figuresCache.canvas.width = 0;
6376            figuresCache.canvas.height = 0;
6377          }
6378          smaskCache = null;
6379          figuresCache = null;
6380        }
6381
6382        return {
6383          get isEnabled() {
6384            if (getDefaultSetting('disableWebGL')) {
6385              return false;
6386            }
6387            var enabled = false;
6388            try {
6389              generateGL();
6390              enabled = !!currentGL;
6391            } catch (e) {}
6392            return shadow(this, 'isEnabled', enabled);
6393          },
6394          composeSMask: composeSMask,
6395          drawFigures: drawFigures,
6396          clear: cleanup,
6397        };
6398      })();
6399
6400      exports.WebGLUtils = WebGLUtils;
6401    });
6402
6403    (function (root, factory) {
6404      {
6405        factory((root.pdfjsDisplayPatternHelper = {}), root.pdfjsSharedUtil, root.pdfjsDisplayWebGL);
6406      }
6407    })(this, function (exports, sharedUtil, displayWebGL) {
6408      var Util = sharedUtil.Util;
6409      var info = sharedUtil.info;
6410      var isArray = sharedUtil.isArray;
6411      var error = sharedUtil.error;
6412      var WebGLUtils = displayWebGL.WebGLUtils;
6413
6414      var ShadingIRs = {};
6415
6416      ShadingIRs.RadialAxial = {
6417        fromIR: function RadialAxial_fromIR(raw) {
6418          var type = raw[1];
6419          var colorStops = raw[2];
6420          var p0 = raw[3];
6421          var p1 = raw[4];
6422          var r0 = raw[5];
6423          var r1 = raw[6];
6424          return {
6425            type: 'Pattern',
6426            getPattern: function RadialAxial_getPattern(ctx) {
6427              var grad;
6428              if (type === 'axial') {
6429                grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
6430              } else if (type === 'radial') {
6431                grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
6432              }
6433
6434              for (var i = 0, ii = colorStops.length; i < ii; ++i) {
6435                var c = colorStops[i];
6436                grad.addColorStop(c[0], c[1]);
6437              }
6438              return grad;
6439            },
6440          };
6441        },
6442      };
6443
6444      var createMeshCanvas = (function createMeshCanvasClosure() {
6445        function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
6446          // Very basic Gouraud-shaded triangle rasterization algorithm.
6447          var coords = context.coords,
6448            colors = context.colors;
6449          var bytes = data.data,
6450            rowSize = data.width * 4;
6451          var tmp;
6452          if (coords[p1 + 1] > coords[p2 + 1]) {
6453            tmp = p1;
6454            p1 = p2;
6455            p2 = tmp;
6456            tmp = c1;
6457            c1 = c2;
6458            c2 = tmp;
6459          }
6460          if (coords[p2 + 1] > coords[p3 + 1]) {
6461            tmp = p2;
6462            p2 = p3;
6463            p3 = tmp;
6464            tmp = c2;
6465            c2 = c3;
6466            c3 = tmp;
6467          }
6468          if (coords[p1 + 1] > coords[p2 + 1]) {
6469            tmp = p1;
6470            p1 = p2;
6471            p2 = tmp;
6472            tmp = c1;
6473            c1 = c2;
6474            c2 = tmp;
6475          }
6476          var x1 = (coords[p1] + context.offsetX) * context.scaleX;
6477          var y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY;
6478          var x2 = (coords[p2] + context.offsetX) * context.scaleX;
6479          var y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY;
6480          var x3 = (coords[p3] + context.offsetX) * context.scaleX;
6481          var y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY;
6482          if (y1 >= y3) {
6483            return;
6484          }
6485          var c1r = colors[c1],
6486            c1g = colors[c1 + 1],
6487            c1b = colors[c1 + 2];
6488          var c2r = colors[c2],
6489            c2g = colors[c2 + 1],
6490            c2b = colors[c2 + 2];
6491          var c3r = colors[c3],
6492            c3g = colors[c3 + 1],
6493            c3b = colors[c3 + 2];
6494
6495          var minY = Math.round(y1),
6496            maxY = Math.round(y3);
6497          var xa, car, cag, cab;
6498          var xb, cbr, cbg, cbb;
6499          var k;
6500          for (var y = minY; y <= maxY; y++) {
6501            if (y < y2) {
6502              k = y < y1 ? 0 : y1 === y2 ? 1 : (y1 - y) / (y1 - y2);
6503              xa = x1 - (x1 - x2) * k;
6504              car = c1r - (c1r - c2r) * k;
6505              cag = c1g - (c1g - c2g) * k;
6506              cab = c1b - (c1b - c2b) * k;
6507            } else {
6508              k = y > y3 ? 1 : y2 === y3 ? 0 : (y2 - y) / (y2 - y3);
6509              xa = x2 - (x2 - x3) * k;
6510              car = c2r - (c2r - c3r) * k;
6511              cag = c2g - (c2g - c3g) * k;
6512              cab = c2b - (c2b - c3b) * k;
6513            }
6514            k = y < y1 ? 0 : y > y3 ? 1 : (y1 - y) / (y1 - y3);
6515            xb = x1 - (x1 - x3) * k;
6516            cbr = c1r - (c1r - c3r) * k;
6517            cbg = c1g - (c1g - c3g) * k;
6518            cbb = c1b - (c1b - c3b) * k;
6519            var x1_ = Math.round(Math.min(xa, xb));
6520            var x2_ = Math.round(Math.max(xa, xb));
6521            var j = rowSize * y + x1_ * 4;
6522            for (var x = x1_; x <= x2_; x++) {
6523              k = (xa - x) / (xa - xb);
6524              k = k < 0 ? 0 : k > 1 ? 1 : k;
6525              bytes[j++] = (car - (car - cbr) * k) | 0;
6526              bytes[j++] = (cag - (cag - cbg) * k) | 0;
6527              bytes[j++] = (cab - (cab - cbb) * k) | 0;
6528              bytes[j++] = 255;
6529            }
6530          }
6531        }
6532
6533        function drawFigure(data, figure, context) {
6534          var ps = figure.coords;
6535          var cs = figure.colors;
6536          var i, ii;
6537          switch (figure.type) {
6538            case 'lattice':
6539              var verticesPerRow = figure.verticesPerRow;
6540              var rows = Math.floor(ps.length / verticesPerRow) - 1;
6541              var cols = verticesPerRow - 1;
6542              for (i = 0; i < rows; i++) {
6543                var q = i * verticesPerRow;
6544                for (var j = 0; j < cols; j++, q++) {
6545                  drawTriangle(
6546                    data,
6547                    context,
6548                    ps[q],
6549                    ps[q + 1],
6550                    ps[q + verticesPerRow],
6551                    cs[q],
6552                    cs[q + 1],
6553                    cs[q + verticesPerRow]
6554                  );
6555                  drawTriangle(
6556                    data,
6557                    context,
6558                    ps[q + verticesPerRow + 1],
6559                    ps[q + 1],
6560                    ps[q + verticesPerRow],
6561                    cs[q + verticesPerRow + 1],
6562                    cs[q + 1],
6563                    cs[q + verticesPerRow]
6564                  );
6565                }
6566              }
6567              break;
6568            case 'triangles':
6569              for (i = 0, ii = ps.length; i < ii; i += 3) {
6570                drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]);
6571              }
6572              break;
6573            default:
6574              error('illigal figure');
6575              break;
6576          }
6577        }
6578
6579        function createMeshCanvas(bounds, combinesScale, coords, colors, figures, backgroundColor, cachedCanvases) {
6580          // we will increase scale on some weird factor to let antialiasing take
6581          // care of "rough" edges
6582          var EXPECTED_SCALE = 1.1;
6583          // MAX_PATTERN_SIZE is used to avoid OOM situation.
6584          var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough
6585          // We need to keep transparent border around our pattern for fill():
6586          // createPattern with 'no-repeat' will bleed edges across entire area.
6587          var BORDER_SIZE = 2;
6588
6589          var offsetX = Math.floor(bounds[0]);
6590          var offsetY = Math.floor(bounds[1]);
6591          var boundsWidth = Math.ceil(bounds[2]) - offsetX;
6592          var boundsHeight = Math.ceil(bounds[3]) - offsetY;
6593
6594          var width = Math.min(Math.ceil(Math.abs(boundsWidth * combinesScale[0] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
6595          var height = Math.min(
6596            Math.ceil(Math.abs(boundsHeight * combinesScale[1] * EXPECTED_SCALE)),
6597            MAX_PATTERN_SIZE
6598          );
6599          var scaleX = boundsWidth / width;
6600          var scaleY = boundsHeight / height;
6601
6602          var context = {
6603            coords: coords,
6604            colors: colors,
6605            offsetX: -offsetX,
6606            offsetY: -offsetY,
6607            scaleX: 1 / scaleX,
6608            scaleY: 1 / scaleY,
6609          };
6610
6611          var paddedWidth = width + BORDER_SIZE * 2;
6612          var paddedHeight = height + BORDER_SIZE * 2;
6613
6614          var canvas, tmpCanvas, i, ii;
6615          if (WebGLUtils.isEnabled) {
6616            canvas = WebGLUtils.drawFigures(width, height, backgroundColor, figures, context);
6617
6618            // https://bugzilla.mozilla.org/show_bug.cgi?id=972126
6619            tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight, false);
6620            tmpCanvas.context.drawImage(canvas, BORDER_SIZE, BORDER_SIZE);
6621            canvas = tmpCanvas.canvas;
6622          } else {
6623            tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight, false);
6624            var tmpCtx = tmpCanvas.context;
6625
6626            var data = tmpCtx.createImageData(width, height);
6627            if (backgroundColor) {
6628              var bytes = data.data;
6629              for (i = 0, ii = bytes.length; i < ii; i += 4) {
6630                bytes[i] = backgroundColor[0];
6631                bytes[i + 1] = backgroundColor[1];
6632                bytes[i + 2] = backgroundColor[2];
6633                bytes[i + 3] = 255;
6634              }
6635            }
6636            for (i = 0; i < figures.length; i++) {
6637              drawFigure(data, figures[i], context);
6638            }
6639            tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE);
6640            canvas = tmpCanvas.canvas;
6641          }
6642
6643          return {
6644            canvas: canvas,
6645            offsetX: offsetX - BORDER_SIZE * scaleX,
6646            offsetY: offsetY - BORDER_SIZE * scaleY,
6647            scaleX: scaleX,
6648            scaleY: scaleY,
6649          };
6650        }
6651
6652        return createMeshCanvas;
6653      })();
6654
6655      ShadingIRs.Mesh = {
6656        fromIR: function Mesh_fromIR(raw) {
6657          //var type = raw[1];
6658          var coords = raw[2];
6659          var colors = raw[3];
6660          var figures = raw[4];
6661          var bounds = raw[5];
6662          var matrix = raw[6];
6663          //var bbox = raw[7];
6664          var background = raw[8];
6665          return {
6666            type: 'Pattern',
6667            getPattern: function Mesh_getPattern(ctx, owner, shadingFill) {
6668              var scale;
6669              if (shadingFill) {
6670                scale = Util.singularValueDecompose2dScale(ctx.mozCurrentTransform);
6671              } else {
6672                // Obtain scale from matrix and current transformation matrix.
6673                scale = Util.singularValueDecompose2dScale(owner.baseTransform);
6674                if (matrix) {
6675                  var matrixScale = Util.singularValueDecompose2dScale(matrix);
6676                  scale = [scale[0] * matrixScale[0], scale[1] * matrixScale[1]];
6677                }
6678              }
6679
6680              // Rasterizing on the main thread since sending/queue large canvases
6681              // might cause OOM.
6682              var temporaryPatternCanvas = createMeshCanvas(
6683                bounds,
6684                scale,
6685                coords,
6686                colors,
6687                figures,
6688                shadingFill ? null : background,
6689                owner.cachedCanvases
6690              );
6691
6692              if (!shadingFill) {
6693                ctx.setTransform.apply(ctx, owner.baseTransform);
6694                if (matrix) {
6695                  ctx.transform.apply(ctx, matrix);
6696                }
6697              }
6698
6699              ctx.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
6700              ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY);
6701
6702              return ctx.createPattern(temporaryPatternCanvas.canvas, 'no-repeat');
6703            },
6704          };
6705        },
6706      };
6707
6708      ShadingIRs.Dummy = {
6709        fromIR: function Dummy_fromIR() {
6710          return {
6711            type: 'Pattern',
6712            getPattern: function Dummy_fromIR_getPattern() {
6713              return 'hotpink';
6714            },
6715          };
6716        },
6717      };
6718
6719      function getShadingPatternFromIR(raw) {
6720        var shadingIR = ShadingIRs[raw[0]];
6721        if (!shadingIR) {
6722          error('Unknown IR type: ' + raw[0]);
6723        }
6724        return shadingIR.fromIR(raw);
6725      }
6726
6727      var TilingPattern = (function TilingPatternClosure() {
6728        var PaintType = {
6729          COLORED: 1,
6730          UNCOLORED: 2,
6731        };
6732
6733        var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough
6734
6735        function TilingPattern(IR, color, ctx, canvasGraphicsFactory, baseTransform) {
6736          this.operatorList = IR[2];
6737          this.matrix = IR[3] || [1, 0, 0, 1, 0, 0];
6738          this.bbox = IR[4];
6739          this.xstep = IR[5];
6740          this.ystep = IR[6];
6741          this.paintType = IR[7];
6742          this.tilingType = IR[8];
6743          this.color = color;
6744          this.canvasGraphicsFactory = canvasGraphicsFactory;
6745          this.baseTransform = baseTransform;
6746          this.type = 'Pattern';
6747          this.ctx = ctx;
6748        }
6749
6750        TilingPattern.prototype = {
6751          createPatternCanvas: function TilinPattern_createPatternCanvas(owner) {
6752            var operatorList = this.operatorList;
6753            var bbox = this.bbox;
6754            var xstep = this.xstep;
6755            var ystep = this.ystep;
6756            var paintType = this.paintType;
6757            var tilingType = this.tilingType;
6758            var color = this.color;
6759            var canvasGraphicsFactory = this.canvasGraphicsFactory;
6760
6761            info('TilingType: ' + tilingType);
6762
6763            var x0 = bbox[0],
6764              y0 = bbox[1],
6765              x1 = bbox[2],
6766              y1 = bbox[3];
6767
6768            var topLeft = [x0, y0];
6769            // we want the canvas to be as large as the step size
6770            var botRight = [x0 + xstep, y0 + ystep];
6771
6772            var width = botRight[0] - topLeft[0];
6773            var height = botRight[1] - topLeft[1];
6774
6775            // Obtain scale from matrix and current transformation matrix.
6776            var matrixScale = Util.singularValueDecompose2dScale(this.matrix
vendor: 24,667 bytes, lines 6776-7447
6776);
6777            var curMatrixScale = Util.singularValueDecompose2dScale(this.baseTransform);
6778            var combinedScale = [matrixScale[0] * curMatrixScale[0], matrixScale[1] * curMatrixScale[1]];
6779
6780            // MAX_PATTERN_SIZE is used to avoid OOM situation.
6781            // Use width and height values that are as close as possible to the end
6782            // result when the pattern is used. Too low value makes the pattern look
6783            // blurry. Too large value makes it look too crispy.
6784            width = Math.min(Math.ceil(Math.abs(width * combinedScale[0])), MAX_PATTERN_SIZE);
6785
6786            height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])), MAX_PATTERN_SIZE);
6787
6788            var tmpCanvas = owner.cachedCanvases.getCanvas('pattern', width, height, true);
6789            var tmpCtx = tmpCanvas.context;
6790            var graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx);
6791            graphics.groupLevel = owner.groupLevel;
6792
6793            this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color);
6794
6795            this.setScale(width, height, xstep, ystep);
6796            this.transformToScale(graphics);
6797
6798            // transform coordinates to pattern space
6799            var tmpTranslate = [1, 0, 0, 1, -topLeft[0], -topLeft[1]];
6800            graphics.transform.apply(graphics, tmpTranslate);
6801
6802            this.clipBbox(graphics, bbox, x0, y0, x1, y1);
6803
6804            graphics.executeOperatorList(operatorList);
6805            return tmpCanvas.canvas;
6806          },
6807
6808          setScale: function TilingPattern_setScale(width, height, xstep, ystep) {
6809            this.scale = [width / xstep, height / ystep];
6810          },
6811
6812          transformToScale: function TilingPattern_transformToScale(graphics) {
6813            var scale = this.scale;
6814            var tmpScale = [scale[0], 0, 0, scale[1], 0, 0];
6815            graphics.transform.apply(graphics, tmpScale);
6816          },
6817
6818          scaleToContext: function TilingPattern_scaleToContext() {
6819            var scale = this.scale;
6820            this.ctx.scale(1 / scale[0], 1 / scale[1]);
6821          },
6822
6823          clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
6824            if (bbox && isArray(bbox) && bbox.length === 4) {
6825              var bboxWidth = x1 - x0;
6826              var bboxHeight = y1 - y0;
6827              graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight);
6828              graphics.clip();
6829              graphics.endPath();
6830            }
6831          },
6832
6833          setFillAndStrokeStyleToContext: function setFillAndStrokeStyleToContext(context, paintType, color) {
6834            switch (paintType) {
6835              case PaintType.COLORED:
6836                var ctx = this.ctx;
6837                context.fillStyle = ctx.fillStyle;
6838                context.strokeStyle = ctx.strokeStyle;
6839                break;
6840              case PaintType.UNCOLORED:
6841                var cssColor = Util.makeCssRgb(color[0], color[1], color[2]);
6842                context.fillStyle = cssColor;
6843                context.strokeStyle = cssColor;
6844                break;
6845              default:
6846                error('Unsupported paint type: ' + paintType);
6847            }
6848          },
6849
6850          getPattern: function TilingPattern_getPattern(ctx, owner) {
6851            var temporaryPatternCanvas = this.createPatternCanvas(owner);
6852
6853            ctx = this.ctx;
6854            ctx.setTransform.apply(ctx, this.baseTransform);
6855            ctx.transform.apply(ctx, this.matrix);
6856            this.scaleToContext();
6857
6858            return ctx.createPattern(temporaryPatternCanvas, 'repeat');
6859          },
6860        };
6861
6862        return TilingPattern;
6863      })();
6864
6865      exports.getShadingPatternFromIR = getShadingPatternFromIR;
6866      exports.TilingPattern = TilingPattern;
6867    });
6868
6869    (function (root, factory) {
6870      {
6871        factory(
6872          (root.pdfjsDisplayCanvas = {}),
6873          root.pdfjsSharedUtil,
6874          root.pdfjsDisplayDOMUtils,
6875          root.pdfjsDisplayPatternHelper,
6876          root.pdfjsDisplayWebGL
6877        );
6878      }
6879    })(this, function (exports, sharedUtil, displayDOMUtils, displayPatternHelper, displayWebGL) {
6880      var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX;
6881      var IDENTITY_MATRIX = sharedUtil.IDENTITY_MATRIX;
6882      var ImageKind = sharedUtil.ImageKind;
6883      var OPS = sharedUtil.OPS;
6884      var TextRenderingMode = sharedUtil.TextRenderingMode;
6885      var Uint32ArrayView = sharedUtil.Uint32ArrayView;
6886      var Util = sharedUtil.Util;
6887      var assert = sharedUtil.assert;
6888      var info = sharedUtil.info;
6889      var isNum = sharedUtil.isNum;
6890      var isArray = sharedUtil.isArray;
6891      var isLittleEndian = sharedUtil.isLittleEndian;
6892      var error = sharedUtil.error;
6893      var shadow = sharedUtil.shadow;
6894      var warn = sharedUtil.warn;
6895      var TilingPattern = displayPatternHelper.TilingPattern;
6896      var getShadingPatternFromIR = displayPatternHelper.getShadingPatternFromIR;
6897      var WebGLUtils = displayWebGL.WebGLUtils;
6898      var hasCanvasTypedArrays = displayDOMUtils.hasCanvasTypedArrays;
6899
6900      // <canvas> contexts store most of the state we need natively.
6901      // However, PDF needs a bit more state, which we store here.
6902
6903      // Minimal font size that would be used during canvas fillText operations.
6904      var MIN_FONT_SIZE = 16;
6905      // Maximum font size that would be used during canvas fillText operations.
6906      var MAX_FONT_SIZE = 100;
6907      var MAX_GROUP_SIZE = 4096;
6908
6909      // Heuristic value used when enforcing minimum line widths.
6910      var MIN_WIDTH_FACTOR = 0.65;
6911
6912      var COMPILE_TYPE3_GLYPHS = true;
6913      var MAX_SIZE_TO_COMPILE = 1000;
6914
6915      var FULL_CHUNK_HEIGHT = 16;
6916
6917      var HasCanvasTypedArraysCached = {
6918        get value() {
6919          return shadow(HasCanvasTypedArraysCached, 'value', hasCanvasTypedArrays());
6920        },
6921      };
6922
6923      var IsLittleEndianCached = {
6924        get value() {
6925          return shadow(IsLittleEndianCached, 'value', isLittleEndian());
6926        },
6927      };
6928
6929      function createScratchCanvas(width, height) {
6930        var canvas = document.createElement('canvas');
6931        canvas.width = width;
6932        canvas.height = height;
6933        return canvas;
6934      }
6935
6936      function addContextCurrentTransform(ctx) {
6937        // If the context doesn't expose a `mozCurrentTransform`, add a JS based one.
6938        if (!ctx.mozCurrentTransform) {
6939          ctx._originalSave = ctx.save;
6940          ctx._originalRestore = ctx.restore;
6941          ctx._originalRotate = ctx.rotate;
6942          ctx._originalScale = ctx.scale;
6943          ctx._originalTranslate = ctx.translate;
6944          ctx._originalTransform = ctx.transform;
6945          ctx._originalSetTransform = ctx.setTransform;
6946
6947          ctx._transformMatrix = ctx._transformMatrix || [1, 0, 0, 1, 0, 0];
6948          ctx._transformStack = [];
6949
6950          Object.defineProperty(ctx, 'mozCurrentTransform', {
6951            get: function getCurrentTransform() {
6952              return this._transformMatrix;
6953            },
6954          });
6955
6956          Object.defineProperty(ctx, 'mozCurrentTransformInverse', {
6957            get: function getCurrentTransformInverse() {
6958              // Calculation done using WolframAlpha:
6959              // http://www.wolframalpha.com/input/?
6960              //   i=Inverse+{{a%2C+c%2C+e}%2C+{b%2C+d%2C+f}%2C+{0%2C+0%2C+1}}
6961
6962              var m = this._transformMatrix;
6963              var a = m[0],
6964                b = m[1],
6965                c = m[2],
6966                d = m[3],
6967                e = m[4],
6968                f = m[5];
6969
6970              var ad_bc = a * d - b * c;
6971              var bc_ad = b * c - a * d;
6972
6973              return [d / ad_bc, b / bc_ad, c / bc_ad, a / ad_bc, (d * e - c * f) / bc_ad, (b * e - a * f) / ad_bc];
6974            },
6975          });
6976
6977          ctx.save = function ctxSave() {
6978            var old = this._transformMatrix;
6979            this._transformStack.push(old);
6980            this._transformMatrix = old.slice(0, 6);
6981
6982            this._originalSave();
6983          };
6984
6985          ctx.restore = function ctxRestore() {
6986            var prev = this._transformStack.pop();
6987            if (prev) {
6988              this._transformMatrix = prev;
6989              this._originalRestore();
6990            }
6991          };
6992
6993          ctx.translate = function ctxTranslate(x, y) {
6994            var m = this._transformMatrix;
6995            m[4] = m[0] * x + m[2] * y + m[4];
6996            m[5] = m[1] * x + m[3] * y + m[5];
6997
6998            this._originalTranslate(x, y);
6999          };
7000
7001          ctx.scale = function ctxScale(x, y) {
7002            var m = this._transformMatrix;
7003            m[0] = m[0] * x;
7004            m[1] = m[1] * x;
7005            m[2] = m[2] * y;
7006            m[3] = m[3] * y;
7007
7008            this._originalScale(x, y);
7009          };
7010
7011          ctx.transform = function ctxTransform(a, b, c, d, e, f) {
7012            var m = this._transformMatrix;
7013            this._transformMatrix = [
7014              m[0] * a + m[2] * b,
7015              m[1] * a + m[3] * b,
7016              m[0] * c + m[2] * d,
7017              m[1] * c + m[3] * d,
7018              m[0] * e + m[2] * f + m[4],
7019              m[1] * e + m[3] * f + m[5],
7020            ];
7021
7022            ctx._originalTransform(a, b, c, d, e, f);
7023          };
7024
7025          ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) {
7026            this._transformMatrix = [a, b, c, d, e, f];
7027
7028            ctx._originalSetTransform(a, b, c, d, e, f);
7029          };
7030
7031          ctx.rotate = function ctxRotate(angle) {
7032            var cosValue = Math.cos(angle);
7033            var sinValue = Math.sin(angle);
7034
7035            var m = this._transformMatrix;
7036            this._transformMatrix = [
7037              m[0] * cosValue + m[2] * sinValue,
7038              m[1] * cosValue + m[3] * sinValue,
7039              m[0] * -sinValue + m[2] * cosValue,
7040              m[1] * -sinValue + m[3] * cosValue,
7041              m[4],
7042              m[5],
7043            ];
7044
7045            this._originalRotate(angle);
7046          };
7047        }
7048      }
7049
7050      var CachedCanvases = (function CachedCanvasesClosure() {
7051        function CachedCanvases() {
7052          this.cache = Object.create(null);
7053        }
7054
7055        CachedCanvases.prototype = {
7056          getCanvas: function CachedCanvases_getCanvas(id, width, height, trackTransform) {
7057            var canvasEntry;
7058            if (this.cache[id] !== undefined) {
7059              canvasEntry = this.cache[id];
7060              canvasEntry.canvas.width = width;
7061              canvasEntry.canvas.height = height;
7062              // reset canvas transform for emulated mozCurrentTransform, if needed
7063              canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0);
7064            } else {
7065              var canvas = createScratchCanvas(width, height);
7066              var ctx = canvas.getContext('2d');
7067              if (trackTransform) {
7068                addContextCurrentTransform(ctx);
7069              }
7070              this.cache[id] = canvasEntry = { canvas: canvas, context: ctx };
7071            }
7072            return canvasEntry;
7073          },
7074          clear: function () {
7075            for (var id in this.cache) {
7076              var canvasEntry = this.cache[id];
7077              // Zeroing the width and height causes Firefox to release graphics
7078              // resources immediately, which can greatly reduce memory consumption.
7079              canvasEntry.canvas.width = 0;
7080              canvasEntry.canvas.height = 0;
7081              delete this.cache[id];
7082            }
7083          },
7084        };
7085        return CachedCanvases;
7086      })();
7087
7088      function compileType3Glyph(imgData) {
7089        var POINT_TO_PROCESS_LIMIT = 1000;
7090
7091        var width = imgData.width,
7092          height = imgData.height;
7093        var i,
7094          j,
7095          j0,
7096          width1 = width + 1;
7097        var points = new Uint8Array(width1 * (height + 1));
7098        var POINT_TYPES = new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]);
7099
7100        // decodes bit-packed mask data
7101        var lineSize = (width + 7) & ~7,
7102          data0 = imgData.data;
7103        var data = new Uint8Array(lineSize * height),
7104          pos = 0,
7105          ii;
7106        for (i = 0, ii = data0.length; i < ii; i++) {
7107          var mask = 128,
7108            elem = data0[i];
7109          while (mask > 0) {
7110            data[pos++] = elem & mask ? 0 : 255;
7111            mask >>= 1;
7112          }
7113        }
7114
7115        // finding iteresting points: every point is located between mask pixels,
7116        // so there will be points of the (width + 1)x(height + 1) grid. Every point
7117        // will have flags assigned based on neighboring mask pixels:
7118        //   4 | 8
7119        //   --P--
7120        //   2 | 1
7121        // We are interested only in points with the flags:
7122        //   - outside corners: 1, 2, 4, 8;
7123        //   - inside corners: 7, 11, 13, 14;
7124        //   - and, intersections: 5, 10.
7125        var count = 0;
7126        pos = 0;
7127        if (data[pos] !== 0) {
7128          points[0] = 1;
7129          ++count;
7130        }
7131        for (j = 1; j < width; j++) {
7132          if (data[pos] !== data[pos + 1]) {
7133            points[j] = data[pos] ? 2 : 1;
7134            ++count;
7135          }
7136          pos++;
7137        }
7138        if (data[pos] !== 0) {
7139          points[j] = 2;
7140          ++count;
7141        }
7142        for (i = 1; i < height; i++) {
7143          pos = i * lineSize;
7144          j0 = i * width1;
7145          if (data[pos - lineSize] !== data[pos]) {
7146            points[j0] = data[pos] ? 1 : 8;
7147            ++count;
7148          }
7149          // 'sum' is the position of the current pixel configuration in the 'TYPES'
7150          // array (in order 8-1-2-4, so we can use '>>2' to shift the column).
7151          var sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0);
7152          for (j = 1; j < width; j++) {
7153            sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + (data[pos - lineSize + 1] ? 8 : 0);
7154            if (POINT_TYPES[sum]) {
7155              points[j0 + j] = POINT_TYPES[sum];
7156              ++count;
7157            }
7158            pos++;
7159          }
7160          if (data[pos - lineSize] !== data[pos]) {
7161            points[j0 + j] = data[pos] ? 2 : 4;
7162            ++count;
7163          }
7164
7165          if (count > POINT_TO_PROCESS_LIMIT) {
7166            return null;
7167          }
7168        }
7169
7170        pos = lineSize * (height - 1);
7171        j0 = i * width1;
7172        if (data[pos] !== 0) {
7173          points[j0] = 8;
7174          ++count;
7175        }
7176        for (j = 1; j < width; j++) {
7177          if (data[pos] !== data[pos + 1]) {
7178            points[j0 + j] = data[pos] ? 4 : 8;
7179            ++count;
7180          }
7181          pos++;
7182        }
7183        if (data[pos] !== 0) {
7184          points[j0 + j] = 4;
7185          ++count;
7186        }
7187        if (count > POINT_TO_PROCESS_LIMIT) {
7188          return null;
7189        }
7190
7191        // building outlines
7192        var steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]);
7193        var outlines = [];
7194        for (i = 0; count && i <= height; i++) {
7195          var p = i * width1;
7196          var end = p + width;
7197          while (p < end && !points[p]) {
7198            p++;
7199          }
7200          if (p === end) {
7201            continue;
7202          }
7203          var coords = [p % width1, i];
7204
7205          var type = points[p],
7206            p0 = p,
7207            pp;
7208          do {
7209            var step = steps[type];
7210            do {
7211              p += step;
7212            } while (!points[p]);
7213
7214            pp = points[p];
7215            if (pp !== 5 && pp !== 10) {
7216              // set new direction
7217              type = pp;
7218              // delete mark
7219              points[p] = 0;
7220            } else {
7221              // type is 5 or 10, ie, a crossing
7222              // set new direction
7223              type = pp & ((0x33 * type) >> 4);
7224              // set new type for "future hit"
7225              points[p] &= (type >> 2) | (type << 2);
7226            }
7227
7228            coords.push(p % width1);
7229            coords.push((p / width1) | 0);
7230            --count;
7231          } while (p0 !== p);
7232          outlines.push(coords);
7233          --i;
7234        }
7235
7236        var drawOutline = function (c) {
7237          c.save();
7238          // the path shall be painted in [0..1]x[0..1] space
7239          c.scale(1 / width, -1 / height);
7240          c.translate(0, -height);
7241          c.beginPath();
7242          for (var i = 0, ii = outlines.length; i < ii; i++) {
7243            var o = outlines[i];
7244            c.moveTo(o[0], o[1]);
7245            for (var j = 2, jj = o.length; j < jj; j += 2) {
7246              c.lineTo(o[j], o[j + 1]);
7247            }
7248          }
7249          c.fill();
7250          c.beginPath();
7251          c.restore();
7252        };
7253
7254        return drawOutline;
7255      }
7256
7257      var CanvasExtraState = (function CanvasExtraStateClosure() {
7258        function CanvasExtraState(old) {
7259          // Are soft masks and alpha values shapes or opacities?
7260          this.alphaIsShape = false;
7261          this.fontSize = 0;
7262          this.fontSizeScale = 1;
7263          this.textMatrix = IDENTITY_MATRIX;
7264          this.textMatrixScale = 1;
7265          this.fontMatrix = FONT_IDENTITY_MATRIX;
7266          this.leading = 0;
7267          // Current point (in user coordinates)
7268          this.x = 0;
7269          this.y = 0;
7270          // Start of text line (in text coordinates)
7271          this.lineX = 0;
7272          this.lineY = 0;
7273          // Character and word spacing
7274          this.charSpacing = 0;
7275          this.wordSpacing = 0;
7276          this.textHScale = 1;
7277          this.textRenderingMode = TextRenderingMode.FILL;
7278          this.textRise = 0;
7279          // Default fore and background colors
7280          this.fillColor = '#000000';
7281          this.strokeColor = '#000000';
7282          this.patternFill = false;
7283          // Note: fill alpha applies to all non-stroking operations
7284          this.fillAlpha = 1;
7285          this.strokeAlpha = 1;
7286          this.lineWidth = 1;
7287          this.activeSMask = null;
7288          this.resumeSMaskCtx = null; // nonclonable field (see the save method below)
7289
7290          this.old = old;
7291        }
7292
7293        CanvasExtraState.prototype = {
7294          clone: function CanvasExtraState_clone() {
7295            return Object.create(this);
7296          },
7297          setCurrentPoint: function CanvasExtraState_setCurrentPoint(x, y) {
7298            this.x = x;
7299            this.y = y;
7300          },
7301        };
7302        return CanvasExtraState;
7303      })();
7304
7305      var CanvasGraphics = (function CanvasGraphicsClosure() {
7306        // Defines the time the executeOperatorList is going to be executing
7307        // before it stops and shedules a continue of execution.
7308        var EXECUTION_TIME = 15;
7309        // Defines the number of steps before checking the execution time
7310        var EXECUTION_STEPS = 10;
7311
7312        function CanvasGraphics(canvasCtx, commonObjs, objs, imageLayer) {
7313          this.ctx = canvasCtx;
7314          this.current = new CanvasExtraState();
7315          this.stateStack = [];
7316          this.pendingClip = null;
7317          this.pendingEOFill = false;
7318          this.res = null;
7319          this.xobjs = null;
7320          this.commonObjs = commonObjs;
7321          this.objs = objs;
7322          this.imageLayer = imageLayer;
7323          this.groupStack = [];
7324          this.processingType3 = null;
7325          // Patterns are painted relative to the initial page/form transform, see pdf
7326          // spec 8.7.2 NOTE 1.
7327          this.baseTransform = null;
7328          this.baseTransformStack = [];
7329          this.groupLevel = 0;
7330          this.smaskStack = [];
7331          this.smaskCounter = 0;
7332          this.tempSMask = null;
7333          this.cachedCanvases = new CachedCanvases();
7334          if (canvasCtx) {
7335            // NOTE: if mozCurrentTransform is polyfilled, then the current state of
7336            // the transformation must already be set in canvasCtx._transformMatrix.
7337            addContextCurrentTransform(canvasCtx);
7338          }
7339          this.cachedGetSinglePixelWidth = null;
7340        }
7341
7342        function putBinaryImageData(ctx, imgData) {
7343          if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) {
7344            ctx.putImageData(imgData, 0, 0);
7345            return;
7346          }
7347
7348          // Put the image data to the canvas in chunks, rather than putting the
7349          // whole image at once.  This saves JS memory, because the ImageData object
7350          // is smaller. It also possibly saves C++ memory within the implementation
7351          // of putImageData(). (E.g. in Firefox we make two short-lived copies of
7352          // the data passed to putImageData()). |n| shouldn't be too small, however,
7353          // because too many putImageData() calls will slow things down.
7354          //
7355          // Note: as written, if the last chunk is partial, the putImageData() call
7356          // will (conceptually) put pixels past the bounds of the canvas.  But
7357          // that's ok; any such pixels are ignored.
7358
7359          var height = imgData.height,
7360            width = imgData.width;
7361          var partialChunkHeight = height % FULL_CHUNK_HEIGHT;
7362          var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
7363          var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
7364
7365          var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
7366          var srcPos = 0,
7367            destPos;
7368          var src = imgData.data;
7369          var dest = chunkImgData.data;
7370          var i, j, thisChunkHeight, elemsInThisChunk;
7371
7372          // There are multiple forms in which the pixel data can be passed, and
7373          // imgData.kind tells us which one this is.
7374          if (imgData.kind === ImageKind.GRAYSCALE_1BPP) {
7375            // Grayscale, 1 bit per pixel (i.e. black-and-white).
7376            var srcLength = src.byteLength;
7377            var dest32 = HasCanvasTypedArraysCached.value ? new Uint32Array(dest.buffer) : new Uint32ArrayView(dest);
7378            var dest32DataLength = dest32.length;
7379            var fullSrcDiff = (width + 7) >> 3;
7380            var white = 0xffffffff;
7381            var black = IsLittleEndianCached.value || !HasCanvasTypedArraysCached.value ? 0xff000000 : 0x000000ff;
7382            for (i = 0; i < totalChunks; i++) {
7383              thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
7384              destPos = 0;
7385              for (j = 0; j < thisChunkHeight; j++) {
7386                var srcDiff = srcLength - srcPos;
7387                var k = 0;
7388                var kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7;
7389                var kEndUnrolled = kEnd & ~7;
7390                var mask = 0;
7391                var srcByte = 0;
7392                for (; k < kEndUnrolled; k += 8) {
7393                  srcByte = src[srcPos++];
7394                  dest32[destPos++] = srcByte & 128 ? white : black;
7395                  dest32[destPos++] = srcByte & 64 ? white : black;
7396                  dest32[destPos++] = srcByte & 32 ? white : black;
7397                  dest32[destPos++] = srcByte & 16 ? white : black;
7398                  dest32[destPos++] = srcByte & 8 ? white : black;
7399                  dest32[destPos++] = srcByte & 4 ? white : black;
7400                  dest32[destPos++] = srcByte & 2 ? white : black;
7401                  dest32[destPos++] = srcByte & 1 ? white : black;
7402                }
7403                for (; k < kEnd; k++) {
7404                  if (mask === 0) {
7405                    srcByte = src[srcPos++];
7406                    mask = 128;
7407                  }
7408
7409                  dest32[destPos++] = srcByte & mask ? white : black;
7410                  mask >>= 1;
7411                }
7412              }
7413              // We ran out of input. Make all remaining pixels transparent.
7414              while (destPos < dest32DataLength) {
7415                dest32[destPos++] = 0;
7416              }
7417
7418              ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
7419            }
7420          } else if (imgData.kind === ImageKind.RGBA_32BPP) {
7421            // RGBA, 32-bits per pixel.
7422
7423            j = 0;
7424            elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4;
7425            for (i = 0; i < fullChunks; i++) {
7426              dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
7427              srcPos += elemsInThisChunk;
7428
7429              ctx.putImageData(chunkImgData, 0, j);
7430              j += FULL_CHUNK_HEIGHT;
7431            }
7432            if (i < totalChunks) {
7433              elemsInThisChunk = width * partialChunkHeight * 4;
7434              dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
7435              ctx.putImageData(chunkImgData, 0, j);
7436            }
7437          } else if (imgData.kind === ImageKind.RGB_24BPP) {
7438            // RGB, 24-bits per pixel.
7439            thisChunkHeight = FULL_CHUNK_HEIGHT;
7440            elemsInThisChunk = width * thisChunkHeight;
7441            for (i = 0; i < totalChunks; i++) {
7442              if (i >= fullChunks) {
7443                thisChunkHeight = partialChunkHeight;
7444                elemsInThisChunk = width * thisChunkHeight;
7445              }
7446
7447              destPos = 0;
7448              for (j = elemsInThisChunk; j--; ) {
7449                dest[destPos++] = src[srcPos++];
7450                dest[destPos++] = src[srcPos++];
7451                dest[destPos++] = src[srcPos++];
7452                dest[destPos++] = 255;
7453              }
7454              ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
7455            }
7456          } else {
7457            error('bad image kind: ' + imgData.kind);
7458          }
7459        }
7460
7461        function putBinaryImageMask(ctx, imgData) {
7462          var height = imgData.height,
7463            width = imgData.width;
7464          var partialChunkHeight = height % FULL_CHUNK_HEIGHT;
7465          var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
7466          var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
7467
7468          var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
7469          var srcPos = 0;
7470          var src = imgData.data;
7471          var dest = chunkImgData.data;
7472
7473          for (var i = 0; i < totalChunks; i++) {
7474            var thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
7475
7476            // Expand the mask so it can be used by the canvas.  Any required
7477            // inversion has already been handled.
7478            var destPos = 3; // alpha component offset
7479            for (var j = 0; j < thisChunkHeight; j++) {
7480              var mask = 0;
7481              for (var k = 0; k < width; k++) {
7482                if (!mask) {
7483                  var elem = src[srcPos++];
7484                  mask = 128;
7485                }
7486                dest[destPos] = elem & mask ? 0 : 255;
7487                destPos += 4;
7488                mask >>= 1;
7489              }
7490            }
7491            ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
7492          }
7493        }
7494
7495        function copyCtxState(sourceCtx, destCtx) {
7496          var properties = [
7497            'strokeStyle',
7498            'fillStyle',
7499            'fillRule',
7500            'globalAlpha',
7501            'lineWidth',
7502            'lineCap',
7503            'lineJoin',
7504            'miterLimit',
7505            'globalCompositeOperation',
7506            'font',
7507          ];
7508          for (var i = 0, ii = properties.length; i < ii; i++) {
7509            var property = properties[i];
7510            if (sourceCtx[property] !== undefined) {
7511              destCtx[property] = sourceCtx[property];
7512            }
7513          }
7514          if (sourceCtx.setLineDash !== undefined) {
7515            destCtx.setLineDash(sourceCtx.getLineDash());
7516            destCtx.lineDashOffset = sourceCtx.lineDashOffset;
7517          }
7518        }
7519
7520        function composeSMaskBackdrop(bytes, r0, g0, b0) {
7521          var length = bytes.length;
7522          for (var i = 3; i < length; i += 4) {
7523            var alpha = bytes[i];
7524            if (alpha === 0) {
7525              bytes[i - 3] = r0;
7526              bytes[i - 2] = g0;
7527              bytes[i - 1] = b0;
7528            } else if (alpha < 255) {
7529              var alpha_ = 255 - alpha;
7530              bytes[i - 3] = (bytes[i - 3] * alpha + r0 * alpha_) >> 8;
7531              bytes[i - 2] = (bytes[i - 2] * alpha + g0 * alpha_) >> 8;
7532              bytes[i - 1] = (bytes[i - 1] * alpha + b0 * alpha_) >> 8;
7533            }
7534          }
7535        }
7536
7537        function composeSMaskAlpha(maskData, layerData, transferMap) {
7538          var length = maskData.length;
7539          var scale = 1 / 255;
7540          for (var i = 3; i < length; i += 4) {
7541            var alpha = transferMap ? transferMap[maskData[i]] : maskData[i];
7542            layerData[i] = (layerData[i] * alpha * scale) | 0;
7543          }
7544        }
7545
7546        function composeSMaskLuminosity(maskData, layerData, transferMap) {
7547          var length = maskData.length;
7548          for (var i = 3; i < length; i += 4) {
7549            var y =
7550              maskData[i - 3] * 77 + // * 0.3 / 255 * 0x10000
7551              maskData[i - 2] * 152 + // * 0.59 ....
7552              maskData[i - 1] * 28; // * 0.11 ....
7553            layerData[i] = transferMap ? (layerData[i] * transferMap[y >> 8]) >> 8 : (layerData[i] * y) >> 16;
7554          }
7555        }
7556
7557        function genericComposeSMask(maskCtx, layerCtx, width, height, subtype, backdrop, transferMap) {
7558          var hasBackdrop = !!backdrop;
7559          var r0 = hasBackdrop ? backdrop[0] : 0;
7560          var g0 = hasBackdrop ? backdrop[1] : 0;
7561          var b0 = hasBackdrop ? backdrop[2] : 0;
7562
7563          var composeFn;
7564          if (subtype === 'Luminosity') {
7565            composeFn = composeSMaskLuminosity;
7566          } else {
7567            composeFn = composeSMaskAlpha;
7568          }
7569
7570          // processing image in chunks to save memory
7571          var PIXELS_TO_PROCESS = 1048576;
7572          var chunkSize = Math.min(height, Math.ceil(PIXELS_TO_PROCESS / width));
7573          for (var row = 0; row < height; row += chunkSize) {
7574            var chunkHeight = Math.min(chunkSize, height - row);
7575            var maskData = maskCtx.getImageData(0, row, width, chunkHeight);
7576            var layerData = layerCtx.getImageData(0, row, width, chunkHeight);
7577
7578            if (hasBackdrop) {
7579              composeSMaskBackdrop(maskData.data, r0, g0, b0);
7580            }
7581            composeFn(maskData.data, layerData.data, transferMap);
7582
7583            maskCtx.putImageData(layerData, 0, row);
7584          }
7585        }
7586
7587        function composeSMask(ctx, smask, layerCtx) {
7588          var mask = smask.canvas;
7589          var maskCtx = smask.context;
7590
7591          ctx.setTransform(smask.scaleX, 0, 0, smask.scaleY, smask.offsetX, smask.offsetY);
7592
7593          var backdrop = smask.backdrop || null;
7594          if (!smask.transferMap && WebGLUtils.isEnabled) {
7595            var composed = WebGLUtils.composeSMask(layerCtx.canvas, mask, {
7596              subtype: smask.subtype,
7597              backdrop: backdrop,
7598            });
7599            ctx.setTransform(1, 0, 0, 1, 0, 0);
7600            ctx.drawImage(composed, smask.offsetX, smask.offsetY);
7601            return;
7602          }
7603          genericComposeSMask(maskCtx, layerCtx, mask.width, mask.height, smask.subtype, backdrop, smask.transferMap);
7604          ctx.drawImage(mask, 0, 0);
7605        }
7606
7607        var LINE_CAP_STYLES = ['butt', 'round', 'square'];
7608        var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
7609        var NORMAL_CLIP = {};
7610        var EO_CLIP = {};
7611
7612        CanvasGraphics.prototype = {
7613          beginDrawing: function CanvasGraphics_beginDrawing(transform, viewport, transparency) {
7614            // For pdfs that use blend modes we have to clear the canvas else certain
7615            // blend modes can look wrong since we'd be blending with a white
7616            // backdrop. The problem with a transparent backdrop though is we then
7617            // don't get sub pixel anti aliasing on text, creating temporary
7618            // transparent canvas when we have blend modes.
7619            var width = this.ctx.canvas.width;
7620            var height = this.ctx.canvas.height;
7621
7622            this.ctx.save();
7623            this.ctx.fillStyle = 'rgb(255, 255, 255)';
7624            this.ctx.fillRect(0, 0, width, height);
7625            this.ctx.restore();
7626
7627            if (transparency) {
7628              var transparentCanvas = this.cachedCanvases.getCanvas('transparent', width, height, true);
7629              this.compositeCtx = this.ctx;
7630              this.transparentCanvas = transparentCanvas.canvas;
7631              this.ctx = transparentCanvas.context;
7632              this.ctx.save();
7633              // The transform can be applied before rendering, transferring it to
7634              // the new canvas.
7635              this.ctx.transform.apply(this.ctx, this.compositeCtx.mozCurrentTransform);
7636            }
7637
7638            this.ctx.save();
7639            if (transform) {
7640              this.ctx.transform.apply(this.ctx, transform);
7641            }
7642            this.ctx.transform.apply(this.ctx, viewport.transform);
7643
7644            this.baseTransform = this.ctx.mozCurrentTransform.slice();
7645
7646            if (this.imageLayer) {
7647              this.imageLayer.beginLayout();
7648            }
7649          },
7650
7651          executeOperatorList: function CanvasGraphics_executeOperatorList(
7652            operatorList,
7653            executionStartIdx,
7654            continueCallback,
7655            stepper
7656          ) {
7657            var argsArray = operatorList.argsArray;
7658            var fnArray = operatorList.fnArray;
7659            var i = executionStartIdx || 0;
7660            var argsArrayLen = argsArray.length;
7661
7662            // Sometimes the OperatorList to execute is empty.
7663            if (argsArrayLen === i) {
7664              return i;
7665            }
7666
7667            var chunkOperations = argsArrayLen - i > EXECUTION_STEPS && typeof continueCallback === 'function';
7668            var endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0;
7669            var steps = 0;
7670
7671            var commonObjs = this.commonObjs;
7672            var objs = this.objs;
7673            var fnId;
7674
7675            while (true) {
7676              if (stepper !== undefined && i === stepper.nextBreakPoint) {
7677                stepper.breakIt(i, continueCallback);
7678                return i;
7679              }
7680
7681              fnId = fnArray[i];
7682
7683              if (fnId !== OPS.dependency) {
7684                this[fnId].apply(this, argsArray[i]);
7685              } else {
7686                var deps = argsArray[i];
7687                for (var n = 0, nn = deps.length; n < nn; n++) {
7688                  var depObjId = deps[n];
7689                  var common = depObjId[0] === 'g' && depObjId[1] === '_';
7690                  var objsPool = common ? commonObjs : objs;
7691
7692                  // If the promise isn't resolved yet, add the continueCallback
7693                  // to the promise and bail out.
7694                  if (!objsPool.isResolved(depObjId)) {
7695                    objsPool.get(depObjId, continueCallback);
7696                    return i;
7697                  }
7698                }
7699              }
7700
7701              i++;
7702
7703              // If the entire operatorList was executed, stop as were done.
7704              if (i === argsArrayLen) {
7705                return i;
7706              }
7707
7708              // If the execution took longer then a certain amount of time and
7709              // `continueCallback` is specified, interrupt the execution.
7710              if (chunkOperations && ++steps > EXECUTION_STEPS) {
7711                if (Date.now() > endTime) {
7712                  continueCallback();
7713                  return i;
7714                }
7715                steps = 0;
7716              }
7717
7718              // If the operatorList isn't executed completely yet OR the execution
7719              // time was short enough, do another execution round.
7720            }
7721          },
7722
7723          endDrawing: function CanvasGraphics_endDrawing() {
7724            // Finishing all opened operations such as SMask group painting.
7725            if (this.current.activeSMask !== null) {
7726              this.endSMaskGroup();
7727            }
7728
7729            this.ctx.restore();
7730
7731            if (this.transparentCanvas) {
7732              this.ctx = this.compositeCtx;
7733              this.ctx.save();
7734              this.ctx.setTransform(1, 0, 0, 1, 0, 0); // Avoid apply transform twice
7735              this.ctx.drawImage(this.transparentCanvas, 0, 0);
7736              this.ctx.restore();
7737              this.transparentCanvas = null;
7738            }
7739
7740            this.cachedCanvases.clear();
7741            WebGLUtils.clear();
7742
7743            if (this.imageLayer) {
7744              this.imageLayer.endLayout();
7745            }
7746          },
7747
7748          // Graphics state
7749          setLineWidth: function CanvasGraphics_setLineWidth(width) {
7750            this.current.lineWidth = width;
7751            this.ctx.lineWidth = width;
7752          },
7753          setLineCap: function CanvasGraphics_setLineCap(style) {
7754            this.ctx.lineCap = LINE_CAP_STYLES[style];
7755          },
7756          setLineJoin: function CanvasGraphics_setLineJoin(style) {
7757            this.ctx.lineJoin = LINE_JOIN_STYLES[style];
7758          },
7759          setMiterLimit: function CanvasGraphics_setMiterLimit(limit) {
7760            this.ctx.miterLimit = limit;
7761          },
7762          setDash: function CanvasGraphics_setDash(dashArray, dashPhase) {
7763            var ctx = this.ctx;
7764            if (ctx.setLineDash !== undefined) {
7765              ctx.setLineDash(dashArray);
7766              ctx.lineDashOffset = dashPhase;
7767            }
7768          },
7769          setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) {
7770            // Maybe if we one day fully support color spaces this will be important
7771            // for now we can ignore.
7772            // TODO set rendering intent?
7773          },
7774          setFlatness: function CanvasGraphics_setFlatness(flatness) {
7775            // There's no way to control this with canvas, but we can safely ignore.
7776            // TODO set flatness?
7777          },
7778          setGState: function CanvasGraphics_setGState(states) {
7779            for (var i = 0, ii = states.length; i < ii; i++) {
7780              var state = states[i];
7781              var key = state[0];
7782              var value = state[1];
7783
7784              switch (key) {
7785                case 'LW':
7786                  this.setLineWidth(value);
7787                  break;
7788                case 'LC':
7789                  this.setLineCap(value);
7790                  break;
7791                case 'LJ':
7792                  this.setLineJoin(value);
7793                  break;
7794                case 'ML':
7795                  this.setMiterLimit(value);
7796                  break;
7797                case 'D':
7798                  this.setDash(value[0], value[1]);
7799                  break;
7800                case 'RI':
7801                  this.setRenderingIntent(value);
7802                  break;
7803                case 'FL':
7804                  this.setFlatness(value);
7805                  break;
7806                case 'Font':
7807                  this.setFont(value[0], value[1]);
7808                  break;
7809                case 'CA':
7810                  this.current.strokeAlpha = state[1];
7811                  break;
7812                case 'ca':
7813                  this.current.fillAlpha = state[1];
7814                  this.ctx.globalAlpha = state[1];
7815                  break;
7816                case 'BM':
7817                  if (value && value.name && value.name !== 'Normal') {
7818                    var mode = value.name
7819                      .replace(/([A-Z])/g, function (c) {
7820                        return '-' + c.toLowerCase();
7821                      })
7822                      .substring(1);
7823                    this.ctx.globalCompositeOperation = mode;
7824                    if (this.ctx.globalCompositeOperation !== mode) {
7825                      warn('globalCompositeOperation "' + mode + '" is not supported');
7826                    }
7827                  } else {
7828                    this.ctx.globalCompositeOperation = 'source-over';
7829                  }
7830                  break;
7831                case 'SMask':
7832                  if (this.current.activeSMask) {
7833                    // If SMask is currrenly used, it needs to be suspended or
7834                    // finished. Suspend only makes sense when at least one save()
7835                    // was performed and state needs to be reverted on restore().
7836                    if (
7837                      this.stateStack.length > 0 &&
7838                      this.stateStack[this.stateStack.length - 1].activeSMask === this.current.activeSMask
7839                    ) {
7840                      this.suspendSMaskGroup();
7841                    } else {
7842                      this.endSMaskGroup();
7843                    }
7844                  }
7845                  this.current.activeSMask = value ? this.tempSMask : null;
7846                  if (this.current.activeSMask) {
7847                    this.beginSMaskGroup();
7848                  }
7849                  this.tempSMask = null;
7850                  break;
7851              }
7852            }
7853          },
7854          beginSMaskGroup: function CanvasGraphics_beginSMaskGroup() {
7855            var activeSMask = this.current.activeSMask;
7856            var drawnWidth = activeSMask.canvas.width;
7857            var drawnHeight = activeSMask.canvas.height;
7858            var cacheId = 'smaskGroupAt' + this.groupLevel;
7859            var scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight, true);
7860
7861            var currentCtx = this.ctx;
7862            var currentTransform = currentCtx.mozCurrentTransform;
7863            this.ctx.save();
7864
7865            var groupCtx = scratchCanvas.context;
7866            groupCtx.scale(1 / activeSMask.scaleX, 1 / activeSMask.scaleY);
7867            groupCtx.translate(-activeSMask.offsetX, -activeSMask.offsetY);
7868            groupCtx.transform.apply(groupCtx, currentTransform);
7869
7870            activeSMask.startTransformInverse = groupCtx.mozCurrentTransformInverse;
7871
7872            copyCtxState(currentCtx, groupCtx);
7873            this.ctx = groupCtx;
7874            this.setGState([
7875              ['BM', 'Normal'],
7876              ['ca', 1],
7877              ['CA', 1],
7878            ]);
7879            this.groupStack.push(currentCtx);
7880            this.groupLevel++;
7881          },
7882          suspendSMaskGroup: function CanvasGraphics_endSMaskGroup() {
7883            // Similar to endSMaskGroup, the intermediate canvas has to be composed
7884            // and future ctx state restored.
7885            var groupCtx = this.ctx;
7886            this.groupLevel--;
7887            this.ctx = this.groupStack.pop();
7888
7889            composeSMask(this.ctx, this.current.activeSMask, groupCtx);
7890            this.ctx.restore();
7891            this.ctx.save(); // save is needed since SMask will be resumed.
7892            copyCtxState(groupCtx, this.ctx);
7893
7894            // Saving state for resuming.
7895            this.current.resumeSMaskCtx = groupCtx;
7896            // Transform was changed in the SMask canvas, reflecting this change on
7897            // this.ctx.
7898            var deltaTransform = Util.transform(
7899              this.current.activeSMask.startTransformInverse,
7900              groupCtx.mozCurrentTransform
7901            );
7902            this.ctx.transform.apply(this.ctx, deltaTransform);
7903
7904            // SMask was composed, the results at the groupCtx can be cleared.
7905            groupCtx.save();
7906            groupCtx.setTransform(1, 0, 0, 1, 0, 0);
7907            groupCtx.clearRect(0, 0, groupCtx.canvas.width, groupCtx.canvas.height);
7908            groupCtx.restore();
7909          },
7910          resumeSMaskGroup: function CanvasGraphics_endSMaskGroup() {
7911            // Resuming state saved by suspendSMaskGroup. We don't need to restore
7912            // any groupCtx state since restore() command (the only caller) will do
7913            // that for us. See also beginSMaskGroup.
7914            var groupCtx = this.current.resumeSMaskCtx;
7915            var currentCtx = this.ctx;
7916            this.ctx = groupCtx;
7917            this.groupStack.push(currentCtx);
7918            this.groupLevel++;
7919          },
7920          endSMaskGroup: function CanvasGraphics_endSMaskGroup() {
7921            var groupCtx = this.ctx;
7922            this.groupLevel--;
7923            this.ctx = this.groupStack.pop();
7924
7925            composeSMask(this.ctx, this.current.activeSMask, groupCtx);
7926            this.ctx.restore();
7927            copyCtxState(groupCtx, this.ctx);
7928            // Transform was changed in the SMask canvas, reflecting this change on
7929            // this.ctx.
7930            var deltaTransform = Util.transform(
7931              this.current.activeSMask.startTransformInverse,
7932              groupCtx.mozCurrentTransform
7933            );
7934            this.ctx.transform.apply(this.ctx, deltaTransform);
7935          },
7936          save: function CanvasGraphics_save() {
7937            this.ctx.save();
7938            var old = this.current;
7939            this.stateStack.push(old);
7940            this.current = old.clone();
7941            this.current.resumeSMaskCtx = null;
7942          },
7943          restore: function CanvasGraphics_restore() {
7944            // SMask was suspended, we just need to resume it.
7945            if (this.current.resumeSMaskCtx) {
7946              this.resumeSMaskGroup();
7947            }
7948            // SMask has to be finished once there is no states that are using the
7949            // same SMask.
7950            if (
7951              this.current.activeSMask !== null &&
7952              (this.stateStack.length === 0 ||
7953                this.stateStack[this.stateStack.length - 1].activeSMask !== this.current.activeSMask)
7954            ) {
7955              this.endSMaskGroup();
7956            }
7957
7958            if (this.stateStack.length !== 0) {
7959              this.current = this.stateStack.pop();
7960              this.ctx.restore();
7961
7962              // Ensure that the clipping path is reset (fixes issue6413.pdf).
7963              this.pendingClip = null;
7964
7965              this.cachedGetSinglePixelWidth = null;
7966            }
7967          },
7968          transform: function CanvasGraphics_transform(a, b, c, d, e, f) {
7969            this.ctx.transform(a, b, c, d, e, f);
7970
7971            this.cachedGetSinglePixelWidth = null;
7972          },
7973
7974          // Path
7975          constructPath: function CanvasGraphics_constructPath(ops, args) {
7976            var ctx = this.ctx;
7977            var current = this.current;
7978            var x = current.x,
7979              y = current.y;
7980            for (var i = 0, j = 0, ii = ops.length; i < ii; i++) {
7981              switch (ops[i] | 0) {
7982                case OPS.rectangle:
7983                  x = args[j++];
7984                  y = args[j++];
7985                  var width = args[j++];
7986                  var height = args[j++];
7987                  if (width === 0) {
vendor: 15,608 bytes, lines 7988-8387
7988                    width = this.getSinglePixelWidth();
7989                  }
7990                  if (height === 0) {
7991                    height = this.getSinglePixelWidth();
7992                  }
7993                  var xw = x + width;
7994                  var yh = y + height;
7995                  this.ctx.moveTo(x, y);
7996                  this.ctx.lineTo(xw, y);
7997                  this.ctx.lineTo(xw, yh);
7998                  this.ctx.lineTo(x, yh);
7999                  this.ctx.lineTo(x, y);
8000                  this.ctx.closePath();
8001                  break;
8002                case OPS.moveTo:
8003                  x = args[j++];
8004                  y = args[j++];
8005                  ctx.moveTo(x, y);
8006                  break;
8007                case OPS.lineTo:
8008                  x = args[j++];
8009                  y = args[j++];
8010                  ctx.lineTo(x, y);
8011                  break;
8012                case OPS.curveTo:
8013                  x = args[j + 4];
8014                  y = args[j + 5];
8015                  ctx.bezierCurveTo(args[j], args[j + 1], args[j + 2], args[j + 3], x, y);
8016                  j += 6;
8017                  break;
8018                case OPS.curveTo2:
8019                  ctx.bezierCurveTo(x, y, args[j], args[j + 1], args[j + 2], args[j + 3]);
8020                  x = args[j + 2];
8021                  y = args[j + 3];
8022                  j += 4;
8023                  break;
8024                case OPS.curveTo3:
8025                  x = args[j + 2];
8026                  y = args[j + 3];
8027                  ctx.bezierCurveTo(args[j], args[j + 1], x, y, x, y);
8028                  j += 4;
8029                  break;
8030                case OPS.closePath:
8031                  ctx.closePath();
8032                  break;
8033              }
8034            }
8035            current.setCurrentPoint(x, y);
8036          },
8037          closePath: function CanvasGraphics_closePath() {
8038            this.ctx.closePath();
8039          },
8040          stroke: function CanvasGraphics_stroke(consumePath) {
8041            consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
8042            var ctx = this.ctx;
8043            var strokeColor = this.current.strokeColor;
8044            // Prevent drawing too thin lines by enforcing a minimum line width.
8045            ctx.lineWidth = Math.max(this.getSinglePixelWidth() * MIN_WIDTH_FACTOR, this.current.lineWidth);
8046            // For stroke we want to temporarily change the global alpha to the
8047            // stroking alpha.
8048            ctx.globalAlpha = this.current.strokeAlpha;
8049            if (strokeColor && strokeColor.hasOwnProperty('type') && strokeColor.type === 'Pattern') {
8050              // for patterns, we transform to pattern space, calculate
8051              // the pattern, call stroke, and restore to user space
8052              ctx.save();
8053              ctx.strokeStyle = strokeColor.getPattern(ctx, this);
8054              ctx.stroke();
8055              ctx.restore();
8056            } else {
8057              ctx.stroke();
8058            }
8059            if (consumePath) {
8060              this.consumePath();
8061            }
8062            // Restore the global alpha to the fill alpha
8063            ctx.globalAlpha = this.current.fillAlpha;
8064          },
8065          closeStroke: function CanvasGraphics_closeStroke() {
8066            this.closePath();
8067            this.stroke();
8068          },
8069          fill: function CanvasGraphics_fill(consumePath) {
8070            consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
8071            var ctx = this.ctx;
8072            var fillColor = this.current.fillColor;
8073            var isPatternFill = this.current.patternFill;
8074            var needRestore = false;
8075
8076            if (isPatternFill) {
8077              ctx.save();
8078              if (this.baseTransform) {
8079                ctx.setTransform.apply(ctx, this.baseTransform);
8080              }
8081              ctx.fillStyle = fillColor.getPattern(ctx, this);
8082              needRestore = true;
8083            }
8084
8085            if (this.pendingEOFill) {
8086              if (ctx.mozFillRule !== undefined) {
8087                ctx.mozFillRule = 'evenodd';
8088                ctx.fill();
8089                ctx.mozFillRule = 'nonzero';
8090              } else {
8091                ctx.fill('evenodd');
8092              }
8093              this.pendingEOFill = false;
8094            } else {
8095              ctx.fill();
8096            }
8097
8098            if (needRestore) {
8099              ctx.restore();
8100            }
8101            if (consumePath) {
8102              this.consumePath();
8103            }
8104          },
8105          eoFill: function CanvasGraphics_eoFill() {
8106            this.pendingEOFill = true;
8107            this.fill();
8108          },
8109          fillStroke: function CanvasGraphics_fillStroke() {
8110            this.fill(false);
8111            this.stroke(false);
8112
8113            this.consumePath();
8114          },
8115          eoFillStroke: function CanvasGraphics_eoFillStroke() {
8116            this.pendingEOFill = true;
8117            this.fillStroke();
8118          },
8119          closeFillStroke: function CanvasGraphics_closeFillStroke() {
8120            this.closePath();
8121            this.fillStroke();
8122          },
8123          closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() {
8124            this.pendingEOFill = true;
8125            this.closePath();
8126            this.fillStroke();
8127          },
8128          endPath: function CanvasGraphics_endPath() {
8129            this.consumePath();
8130          },
8131
8132          // Clipping
8133          clip: function CanvasGraphics_clip() {
8134            this.pendingClip = NORMAL_CLIP;
8135          },
8136          eoClip: function CanvasGraphics_eoClip() {
8137            this.pendingClip = EO_CLIP;
8138          },
8139
8140          // Text
8141          beginText: function CanvasGraphics_beginText() {
8142            this.current.textMatrix = IDENTITY_MATRIX;
8143            this.current.textMatrixScale = 1;
8144            this.current.x = this.current.lineX = 0;
8145            this.current.y = this.current.lineY = 0;
8146          },
8147          endText: function CanvasGraphics_endText() {
8148            var paths = this.pendingTextPaths;
8149            var ctx = this.ctx;
8150            if (paths === undefined) {
8151              ctx.beginPath();
8152              return;
8153            }
8154
8155            ctx.save();
8156            ctx.beginPath();
8157            for (var i = 0; i < paths.length; i++) {
8158              var path = paths[i];
8159              ctx.setTransform.apply(ctx, path.transform);
8160              ctx.translate(path.x, path.y);
8161              path.addToPath(ctx, path.fontSize);
8162            }
8163            ctx.restore();
8164            ctx.clip();
8165            ctx.beginPath();
8166            delete this.pendingTextPaths;
8167          },
8168          setCharSpacing: function CanvasGraphics_setCharSpacing(spacing) {
8169            this.current.charSpacing = spacing;
8170          },
8171          setWordSpacing: function CanvasGraphics_setWordSpacing(spacing) {
8172            this.current.wordSpacing = spacing;
8173          },
8174          setHScale: function CanvasGraphics_setHScale(scale) {
8175            this.current.textHScale = scale / 100;
8176          },
8177          setLeading: function CanvasGraphics_setLeading(leading) {
8178            this.current.leading = -leading;
8179          },
8180          setFont: function CanvasGraphics_setFont(fontRefName, size) {
8181            var fontObj = this.commonObjs.get(fontRefName);
8182            var current = this.current;
8183
8184            if (!fontObj) {
8185              error("Can't find font for " + fontRefName);
8186            }
8187
8188            current.fontMatrix = fontObj.fontMatrix ? fontObj.fontMatrix : FONT_IDENTITY_MATRIX;
8189
8190            // A valid matrix needs all main diagonal elements to be non-zero
8191            // This also ensures we bypass FF bugzilla bug #719844.
8192            if (current.fontMatrix[0] === 0 || current.fontMatrix[3] === 0) {
8193              warn('Invalid font matrix for font ' + fontRefName);
8194            }
8195
8196            // The spec for Tf (setFont) says that 'size' specifies the font 'scale',
8197            // and in some docs this can be negative (inverted x-y axes).
8198            if (size < 0) {
8199              size = -size;
8200              current.fontDirection = -1;
8201            } else {
8202              current.fontDirection = 1;
8203            }
8204
8205            this.current.font = fontObj;
8206            this.current.fontSize = size;
8207
8208            if (fontObj.isType3Font) {
8209              return; // we don't need ctx.font for Type3 fonts
8210            }
8211
8212            var name = fontObj.loadedName || 'sans-serif';
8213            var bold = fontObj.black ? (fontObj.bold ? '900' : 'bold') : fontObj.bold ? 'bold' : 'normal';
8214
8215            var italic = fontObj.italic ? 'italic' : 'normal';
8216            var typeface = '"' + name + '", ' + fontObj.fallbackName;
8217
8218            // Some font backends cannot handle fonts below certain size.
8219            // Keeping the font at minimal size and using the fontSizeScale to change
8220            // the current transformation matrix before the fillText/strokeText.
8221            // See https://bugzilla.mozilla.org/show_bug.cgi?id=726227
8222            var browserFontSize = size < MIN_FONT_SIZE ? MIN_FONT_SIZE : size > MAX_FONT_SIZE ? MAX_FONT_SIZE : size;
8223            this.current.fontSizeScale = size / browserFontSize;
8224
8225            var rule = italic + ' ' + bold + ' ' + browserFontSize + 'px ' + typeface;
8226            this.ctx.font = rule;
8227          },
8228          setTextRenderingMode: function CanvasGraphics_setTextRenderingMode(mode) {
8229            this.current.textRenderingMode = mode;
8230          },
8231          setTextRise: function CanvasGraphics_setTextRise(rise) {
8232            this.current.textRise = rise;
8233          },
8234          moveText: function CanvasGraphics_moveText(x, y) {
8235            this.current.x = this.current.lineX += x;
8236            this.current.y = this.current.lineY += y;
8237          },
8238          setLeadingMoveText: function CanvasGraphics_setLeadingMoveText(x, y) {
8239            this.setLeading(-y);
8240            this.moveText(x, y);
8241          },
8242          setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) {
8243            this.current.textMatrix = [a, b, c, d, e, f];
8244            this.current.textMatrixScale = Math.sqrt(a * a + b * b);
8245
8246            this.current.x = this.current.lineX = 0;
8247            this.current.y = this.current.lineY = 0;
8248          },
8249          nextLine: function CanvasGraphics_nextLine() {
8250            this.moveText(0, this.current.leading);
8251          },
8252
8253          paintChar: function CanvasGraphics_paintChar(character, x, y) {
8254            var ctx = this.ctx;
8255            var current = this.current;
8256            var font = current.font;
8257            var textRenderingMode = current.textRenderingMode;
8258            var fontSize = current.fontSize / current.fontSizeScale;
8259            var fillStrokeMode = textRenderingMode & TextRenderingMode.FILL_STROKE_MASK;
8260            var isAddToPathSet = !!(textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG);
8261
8262            var addToPath;
8263            if (font.disableFontFace || isAddToPathSet) {
8264              addToPath = font.getPathGenerator(this.commonObjs, character);
8265            }
8266
8267            if (font.disableFontFace) {
8268              ctx.save();
8269              ctx.translate(x, y);
8270              ctx.beginPath();
8271              addToPath(ctx, fontSize);
8272              if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
8273                ctx.fill();
8274              }
8275              if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
8276                ctx.stroke();
8277              }
8278              ctx.restore();
8279            } else {
8280              if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
8281                ctx.fillText(character, x, y);
8282              }
8283              if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
8284                ctx.strokeText(character, x, y);
8285              }
8286            }
8287
8288            if (isAddToPathSet) {
8289              var paths = this.pendingTextPaths || (this.pendingTextPaths = []);
8290              paths.push({
8291                transform: ctx.mozCurrentTransform,
8292                x: x,
8293                y: y,
8294                fontSize: fontSize,
8295                addToPath: addToPath,
8296              });
8297            }
8298          },
8299
8300          get isFontSubpixelAAEnabled() {
8301            // Checks if anti-aliasing is enabled when scaled text is painted.
8302            // On Windows GDI scaled fonts looks bad.
8303            var ctx = document.createElement('canvas').getContext('2d');
8304            ctx.scale(1.5, 1);
8305            ctx.fillText('I', 0, 10);
8306            var data = ctx.getImageData(0, 0, 10, 10).data;
8307            var enabled = false;
8308            for (var i = 3; i < data.length; i += 4) {
8309              if (data[i] > 0 && data[i] < 255) {
8310                enabled = true;
8311                break;
8312              }
8313            }
8314            return shadow(this, 'isFontSubpixelAAEnabled', enabled);
8315          },
8316
8317          showText: function CanvasGraphics_showText(glyphs) {
8318            var current = this.current;
8319            var font = current.font;
8320            if (font.isType3Font) {
8321              return this.showType3Text(glyphs);
8322            }
8323
8324            var fontSize = current.fontSize;
8325            if (fontSize === 0) {
8326              return;
8327            }
8328
8329            var ctx = this.ctx;
8330            var fontSizeScale = current.fontSizeScale;
8331            var charSpacing = current.charSpacing;
8332            var wordSpacing = current.wordSpacing;
8333            var fontDirection = current.fontDirection;
8334            var textHScale = current.textHScale * fontDirection;
8335            var glyphsLength = glyphs.length;
8336            var vertical = font.vertical;
8337            var spacingDir = vertical ? 1 : -1;
8338            var defaultVMetrics = font.defaultVMetrics;
8339            var widthAdvanceScale = fontSize * current.fontMatrix[0];
8340
8341            var simpleFillText = current.textRenderingMode === TextRenderingMode.FILL && !font.disableFontFace;
8342
8343            ctx.save();
8344            ctx.transform.apply(ctx, current.textMatrix);
8345            ctx.translate(current.x, current.y + current.textRise);
8346
8347            if (current.patternFill) {
8348              // TODO: Some shading patterns are not applied correctly to text,
8349              //       e.g. issues 3988 and 5432, and ShowText-ShadingPattern.pdf.
8350              ctx.fillStyle = current.fillColor.getPattern(ctx, this);
8351            }
8352
8353            if (fontDirection > 0) {
8354              ctx.scale(textHScale, -1);
8355            } else {
8356              ctx.scale(textHScale, 1);
8357            }
8358
8359            var lineWidth = current.lineWidth;
8360            var scale = current.textMatrixScale;
8361            if (scale === 0 || lineWidth === 0) {
8362              var fillStrokeMode = current.textRenderingMode & TextRenderingMode.FILL_STROKE_MASK;
8363              if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
8364                this.cachedGetSinglePixelWidth = null;
8365                lineWidth = this.getSinglePixelWidth() * MIN_WIDTH_FACTOR;
8366              }
8367            } else {
8368              lineWidth /= scale;
8369            }
8370
8371            if (fontSizeScale !== 1.0) {
8372              ctx.scale(fontSizeScale, fontSizeScale);
8373              lineWidth /= fontSizeScale;
8374            }
8375
8376            ctx.lineWidth = lineWidth;
8377
8378            var x = 0,
8379              i;
8380            for (i = 0; i < glyphsLength; ++i) {
8381              var glyph = glyphs[i];
8382              if (isNum(glyph)) {
8383                x += (spacingDir * glyph * fontSize) / 1000;
8384                continue;
8385              }
8386
8387              var restoreNeeded = false;
8388              var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
8389              var character = glyph.fontChar;
8390              var accent = glyph.accent;
8391              var scaledX, scaledY, scaledAccentX, scaledAccentY;
8392              var width = glyph.width;
8393              if (vertical) {
8394                var vmetric, vx, vy;
8395                vmetric = glyph.vmetric || defaultVMetrics;
8396                vx = glyph.vmetric ? vmetric[1] : width * 0.5;
8397                vx = -vx * widthAdvanceScale;
8398                vy = vmetric[2] * widthAdvanceScale;
8399
8400                width = vmetric ? -vmetric[0] : width;
8401                scaledX = vx / fontSizeScale;
8402                scaledY = (x + vy) / fontSizeScale;
8403              } else {
8404                scaledX = x / fontSizeScale;
8405                scaledY = 0;
8406              }
8407
8408              if (font.remeasure && width > 0) {
8409                // Some standard fonts may not have the exact width: rescale per
8410                // character if measured width is greater than expected glyph width
8411                // and subpixel-aa is enabled, otherwise just center the glyph.
8412                var measuredWidth = ((ctx.measureText(character).width * 1000) / fontSize) * fontSizeScale;
8413                if (width < measuredWidth && this.isFontSubpixelAAEnabled) {
8414                  var characterScaleX = width / measuredWidth;
8415                  restoreNeeded = true;
8416                  ctx.save();
8417                  ctx.scale(characterScaleX, 1);
8418                  scaledX /= characterScaleX;
8419                } else if (width !== measuredWidth) {
8420                  scaledX += (((width - measuredWidth) / 2000) * fontSize) / fontSizeScale;
8421                }
8422              }
8423
8424              // Only attempt to draw the glyph if it is actually in the embedded font
8425              // file or if there isn't a font file so the fallback font is shown.
8426              if (glyph.isInFont || font.missingFile) {
8427                if (simpleFillText && !accent) {
8428                  // common case
8429                  ctx.fillText(character, scaledX, scaledY);
8430                } else {
8431                  this.paintChar(character, scaledX, scaledY);
8432                  if (accent) {
8433                    scaledAccentX = scaledX + accent.offset.x / fontSizeScale;
8434                    scaledAccentY = scaledY - accent.offset.y / fontSizeScale;
8435                    this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY);
8436                  }
8437                }
8438              }
8439
8440              var charWidth = width * widthAdvanceScale + spacing * fontDirection;
8441              x += charWidth;
8442
8443              if (restoreNeeded) {
8444                ctx.restore();
8445              }
8446            }
8447            if (vertical) {
8448              current.y -= x * textHScale;
8449            } else {
8450              current.x += x * textHScale;
8451            }
8452            ctx.restore();
8453          },
8454
8455          showType3Text: function CanvasGraphics_showType3Text(glyphs) {
8456            // Type3 fonts - each glyph is a "mini-PDF"
8457            var ctx = this.ctx;
8458            var current = this.current;
8459            var font = current.font;
8460            var fontSize = current.fontSize;
8461            var fontDirection = current.fontDirection;
8462            var spacingDir = font.vertical ? 1 : -1;
8463            var charSpacing = current.charSpacing;
8464            var wordSpacing = current.wordSpacing;
8465            var textHScale = current.textHScale * fontDirection;
8466            var fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX;
8467            var glyphsLength = glyphs.length;
8468            var isTextInvisible = current.textRenderingMode === TextRenderingMode.INVISIBLE;
8469            var i, glyph, width, spacingLength;
8470
8471            if (isTextInvisible || fontSize === 0) {
8472              return;
8473            }
8474            this.cachedGetSinglePixelWidth = null;
8475
8476            ctx.save();
8477            ctx.transform.apply(ctx, current.textMatrix);
8478            ctx.translate(current.x, current.y);
8479
8480            ctx.scale(textHScale, fontDirection);
8481
8482            for (i = 0; i < glyphsLength; ++i) {
8483              glyph = glyphs[i];
8484              if (isNum(glyph)) {
8485                spacingLength = (spacingDir * glyph * fontSize) / 1000;
8486                this.ctx.translate(spacingLength, 0);
8487                current.x += spacingLength * textHScale;
8488                continue;
8489              }
8490
8491              var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
8492              var operatorList = font.charProcOperatorList[glyph.operatorListId];
8493              if (!operatorList) {
8494                warn('Type3 character "' + glyph.operatorListId + '" is not available');
8495                continue;
8496              }
8497              this.processingType3 = glyph;
8498              this.save();
8499              ctx.scale(fontSize, fontSize);
8500              ctx.transform.apply(ctx, fontMatrix);
8501              this.executeOperatorList(operatorList);
vendor: 9,911 bytes, lines 8502-8727
8502              this.restore();
8503
8504              var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
8505              width = transformed[0] * fontSize + spacing;
8506
8507              ctx.translate(width, 0);
8508              current.x += width * textHScale;
8509            }
8510            ctx.restore();
8511            this.processingType3 = null;
8512          },
8513
8514          // Type3 fonts
8515          setCharWidth: function CanvasGraphics_setCharWidth(xWidth, yWidth) {
8516            // We can safely ignore this since the width should be the same
8517            // as the width in the Widths array.
8518          },
8519          setCharWidthAndBounds: function CanvasGraphics_setCharWidthAndBounds(xWidth, yWidth, llx, lly, urx, ury) {
8520            // TODO According to the spec we're also suppose to ignore any operators
8521            // that set color or include images while processing this type3 font.
8522            this.ctx.rect(llx, lly, urx - llx, ury - lly);
8523            this.clip();
8524            this.endPath();
8525          },
8526
8527          // Color
8528          getColorN_Pattern: function CanvasGraphics_getColorN_Pattern(IR) {
8529            var pattern;
8530            if (IR[0] === 'TilingPattern') {
8531              var color = IR[1];
8532              var baseTransform = this.baseTransform || this.ctx.mozCurrentTransform.slice();
8533              var self = this;
8534              var canvasGraphicsFactory = {
8535                createCanvasGraphics: function (ctx) {
8536                  return new CanvasGraphics(ctx, self.commonObjs, self.objs);
8537                },
8538              };
8539              pattern = new TilingPattern(IR, color, this.ctx, canvasGraphicsFactory, baseTransform);
8540            } else {
8541              pattern = getShadingPatternFromIR(IR);
8542            }
8543            return pattern;
8544          },
8545          setStrokeColorN: function CanvasGraphics_setStrokeColorN(/*...*/) {
8546            this.current.strokeColor = this.getColorN_Pattern(arguments);
8547          },
8548          setFillColorN: function CanvasGraphics_setFillColorN(/*...*/) {
8549            this.current.fillColor = this.getColorN_Pattern(arguments);
8550            this.current.patternFill = true;
8551          },
8552          setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) {
8553            var color = Util.makeCssRgb(r, g, b);
8554            this.ctx.strokeStyle = color;
8555            this.current.strokeColor = color;
8556          },
8557          setFillRGBColor: function CanvasGraphics_setFillRGBColor(r, g, b) {
8558            var color = Util.makeCssRgb(r, g, b);
8559            this.ctx.fillStyle = color;
8560            this.current.fillColor = color;
8561            this.current.patternFill = false;
8562          },
8563
8564          shadingFill: function CanvasGraphics_shadingFill(patternIR) {
8565            var ctx = this.ctx;
8566
8567            this.save();
8568            var pattern = getShadingPatternFromIR(patternIR);
8569            ctx.fillStyle = pattern.getPattern(ctx, this, true);
8570
8571            var inv = ctx.mozCurrentTransformInverse;
8572            if (inv) {
8573              var canvas = ctx.canvas;
8574              var width = canvas.width;
8575              var height = canvas.height;
8576
8577              var bl = Util.applyTransform([0, 0], inv);
8578              var br = Util.applyTransform([0, height], inv);
8579              var ul = Util.applyTransform([width, 0], inv);
8580              var ur = Util.applyTransform([width, height], inv);
8581
8582              var x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
8583              var y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
8584              var x1 = Math.max(bl[0], br[0], ul[0], ur[0]);
8585              var y1 = Math.max(bl[1], br[1], ul[1], ur[1]);
8586
8587              this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0);
8588            } else {
8589              // HACK to draw the gradient onto an infinite rectangle.
8590              // PDF gradients are drawn across the entire image while
8591              // Canvas only allows gradients to be drawn in a rectangle
8592              // The following bug should allow us to remove this.
8593              // https://bugzilla.mozilla.org/show_bug.cgi?id=664884
8594
8595              this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
8596            }
8597
8598            this.restore();
8599          },
8600
8601          // Images
8602          beginInlineImage: function CanvasGraphics_beginInlineImage() {
8603            error('Should not call beginInlineImage');
8604          },
8605          beginImageData: function CanvasGraphics_beginImageData() {
8606            error('Should not call beginImageData');
8607          },
8608
8609          paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix, bbox) {
8610            this.save();
8611            this.baseTransformStack.push(this.baseTransform);
8612
8613            if (isArray(matrix) && 6 === matrix.length) {
8614              this.transform.apply(this, matrix);
8615            }
8616
8617            this.baseTransform = this.ctx.mozCurrentTransform;
8618
8619            if (isArray(bbox) && 4 === bbox.length) {
8620              var width = bbox[2] - bbox[0];
8621              var height = bbox[3] - bbox[1];
8622              this.ctx.rect(bbox[0], bbox[1], width, height);
8623              this.clip();
8624              this.endPath();
8625            }
8626          },
8627
8628          paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() {
8629            this.restore();
8630            this.baseTransform = this.baseTransformStack.pop();
8631          },
8632
8633          beginGroup: function CanvasGraphics_beginGroup(group) {
8634            this.save();
8635            var currentCtx = this.ctx;
8636            // TODO non-isolated groups - according to Rik at adobe non-isolated
8637            // group results aren't usually that different and they even have tools
8638            // that ignore this setting. Notes from Rik on implementing:
8639            // - When you encounter an transparency group, create a new canvas with
8640            // the dimensions of the bbox
8641            // - copy the content from the previous canvas to the new canvas
8642            // - draw as usual
8643            // - remove the backdrop alpha:
8644            // alphaNew = 1 - (1 - alpha)/(1 - alphaBackdrop) with 'alpha' the alpha
8645            // value of your transparency group and 'alphaBackdrop' the alpha of the
8646            // backdrop
8647            // - remove background color:
8648            // colorNew = color - alphaNew *colorBackdrop /(1 - alphaNew)
8649            if (!group.isolated) {
8650              info('TODO: Support non-isolated groups.');
8651            }
8652
8653            // TODO knockout - supposedly possible with the clever use of compositing
8654            // modes.
8655            if (group.knockout) {
8656              warn('Knockout groups not supported.');
8657            }
8658
8659            var currentTransform = currentCtx.mozCurrentTransform;
8660            if (group.matrix) {
8661              currentCtx.transform.apply(currentCtx, group.matrix);
8662            }
8663            assert(group.bbox, 'Bounding box is required.');
8664
8665            // Based on the current transform figure out how big the bounding box
8666            // will actually be.
8667            var bounds = Util.getAxialAlignedBoundingBox(group.bbox, currentCtx.mozCurrentTransform);
8668            // Clip the bounding box to the current canvas.
8669            var canvasBounds = [0, 0, currentCtx.canvas.width, currentCtx.canvas.height];
8670            bounds = Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0];
8671            // Use ceil in case we're between sizes so we don't create canvas that is
8672            // too small and make the canvas at least 1x1 pixels.
8673            var offsetX = Math.floor(bounds[0]);
8674            var offsetY = Math.floor(bounds[1]);
8675            var drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1);
8676            var drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1);
8677            var scaleX = 1,
8678              scaleY = 1;
8679            if (drawnWidth > MAX_GROUP_SIZE) {
8680              scaleX = drawnWidth / MAX_GROUP_SIZE;
8681              drawnWidth = MAX_GROUP_SIZE;
8682            }
8683            if (drawnHeight > MAX_GROUP_SIZE) {
8684              scaleY = drawnHeight / MAX_GROUP_SIZE;
8685              drawnHeight = MAX_GROUP_SIZE;
8686            }
8687
8688            var cacheId = 'groupAt' + this.groupLevel;
8689            if (group.smask) {
8690              // Using two cache entries is case if masks are used one after another.
8691              cacheId += '_smask_' + (this.smaskCounter++ % 2);
8692            }
8693            var scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight, true);
8694            var groupCtx = scratchCanvas.context;
8695
8696            // Since we created a new canvas that is just the size of the bounding box
8697            // we have to translate the group ctx.
8698            groupCtx.scale(1 / scaleX, 1 / scaleY);
8699            groupCtx.translate(-offsetX, -offsetY);
8700            groupCtx.transform.apply(groupCtx, currentTransform);
8701
8702            if (group.smask) {
8703              // Saving state and cached mask to be used in setGState.
8704              this.smaskStack.push({
8705                canvas: scratchCanvas.canvas,
8706                context: groupCtx,
8707                offsetX: offsetX,
8708                offsetY: offsetY,
8709                scaleX: scaleX,
8710                scaleY: scaleY,
8711                subtype: group.smask.subtype,
8712                backdrop: group.smask.backdrop,
8713                transferMap: group.smask.transferMap || null,
8714                startTransformInverse: null, // used during suspend operation
8715              });
8716            } else {
8717              // Setup the current ctx so when the group is popped we draw it at the
8718              // right location.
8719              currentCtx.setTransform(1, 0, 0, 1, 0, 0);
8720              currentCtx.translate(offsetX, offsetY);
8721              currentCtx.scale(scaleX, scaleY);
8722            }
8723            // The transparency group inherits all off the current graphics state
8724            // except the blend mode, soft mask, and alpha constants.
8725            copyCtxState(currentCtx, groupCtx);
8726            this.ctx = groupCtx;
8727            this.setGState([
8728              ['BM', 'Normal'],
8729              ['ca', 1],
8730              ['CA', 1],
8731            ]);
8732            this.groupStack.push(currentCtx);
8733            this.groupLevel++;
8734
8735            // Reseting mask state, masks will be applied on restore of the group.
8736            this.current.activeSMask = null;
8737          },
8738
8739          endGroup: function CanvasGraphics_endGroup(group) {
8740            this.groupLevel--;
8741            var groupCtx = this.ctx;
8742            this.ctx = this.groupStack.pop();
8743            // Turn off image smoothing to avoid sub pixel interpolation which can
8744            // look kind of blurry for some pdfs.
8745            if (this.ctx.imageSmoothingEnabled !== undefined) {
8746              this.ctx.imageSmoothingEnabled = false;
8747            } else {
8748              this.ctx.mozImageSmoothingEnabled = false;
8749            }
8750            if (group.smask) {
8751              this.tempSMask = this.smaskStack.pop();
8752            } else {
8753              this.ctx.drawImage(groupCtx.canvas, 0, 0);
8754            }
8755            this.restore();
8756          },
8757
8758          beginAnnotations: function CanvasGraphics_beginAnnotations() {
8759            this.save();
8760            this.current = new CanvasExtraState();
8761
8762            if (this.baseTransform) {
8763              this.ctx.setTransform.apply(this.ctx, this.baseTransform);
8764            }
8765          },
8766
8767          endAnnotations: function CanvasGraphics_endAnnotations() {
8768            this.restore();
8769          },
8770
8771          beginAnnotation: function CanvasGraphics_beginAnnotation(rect, transform, matrix) {
8772            this.save();
8773
vendor: 9,388 bytes, lines 8774-9022
8774            if (isArray(rect) && 4 === rect.length) {
8775              var width = rect[2] - rect[0];
8776              var height = rect[3] - rect[1];
8777              this.ctx.rect(rect[0], rect[1], width, height);
8778              this.clip();
8779              this.endPath();
8780            }
8781
8782            this.transform.apply(this, transform);
8783            this.transform.apply(this, matrix);
8784          },
8785
8786          endAnnotation: function CanvasGraphics_endAnnotation() {
8787            this.restore();
8788          },
8789
8790          paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
8791            var domImage = this.objs.get(objId);
8792            if (!domImage) {
8793              warn("Dependent image isn't ready yet");
8794              return;
8795            }
8796
8797            this.save();
8798
8799            var ctx = this.ctx;
8800            // scale the image to the unit square
8801            ctx.scale(1 / w, -1 / h);
8802
8803            ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height, 0, -h, w, h);
8804            if (this.imageLayer) {
8805              var currentTransform = ctx.mozCurrentTransformInverse;
8806              var position = this.getCanvasPosition(0, 0);
8807              this.imageLayer.appendImage({
8808                objId: objId,
8809                left: position[0],
8810                top: position[1],
8811                width: w / currentTransform[0],
8812                height: h / currentTransform[3],
8813              });
8814            }
8815            this.restore();
8816          },
8817
8818          paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(img) {
8819            var ctx = this.ctx;
8820            var width = img.width,
8821              height = img.height;
8822            var fillColor = this.current.fillColor;
8823            var isPatternFill = this.current.patternFill;
8824
8825            var glyph = this.processingType3;
8826
8827            if (COMPILE_TYPE3_GLYPHS && glyph && glyph.compiled === undefined) {
8828              if (width <= MAX_SIZE_TO_COMPILE && height <= MAX_SIZE_TO_COMPILE) {
8829                glyph.compiled = compileType3Glyph({
8830                  data: img.data,
8831                  width: width,
8832                  height: height,
8833                });
8834              } else {
8835                glyph.compiled = null;
8836              }
8837            }
8838
8839            if (glyph && glyph.compiled) {
8840              glyph.compiled(ctx);
8841              return;
8842            }
8843
8844            var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas', width, height);
8845            var maskCtx = maskCanvas.context;
8846            maskCtx.save();
8847
8848            putBinaryImageMask(maskCtx, img);
8849
8850            maskCtx.globalCompositeOperation = 'source-in';
8851
8852            maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this) : fillColor;
8853            maskCtx.fillRect(0, 0, width, height);
8854
8855            maskCtx.restore();
8856
8857            this.paintInlineImageXObject(maskCanvas.canvas);
8858          },
8859
8860          paintImageMaskXObjectRepeat: function CanvasGraphics_paintImageMaskXObjectRepeat(
8861            imgData,
8862            scaleX,
8863            scaleY,
8864            positions
8865          ) {
8866            var width = imgData.width;
8867            var height = imgData.height;
8868            var fillColor = this.current.fillColor;
8869            var isPatternFill = this.current.patternFill;
8870
8871            var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas', width, height);
8872            var maskCtx = maskCanvas.context;
8873            maskCtx.save();
8874
8875            putBinaryImageMask(maskCtx, imgData);
8876
8877            maskCtx.globalCompositeOperation = 'source-in';
8878
8879            maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this) : fillColor;
8880            maskCtx.fillRect(0, 0, width, height);
8881
8882            maskCtx.restore();
8883
8884            var ctx = this.ctx;
8885            for (var i = 0, ii = positions.length; i < ii; i += 2) {
8886              ctx.save();
8887              ctx.transform(scaleX, 0, 0, scaleY, positions[i], positions[i + 1]);
8888              ctx.scale(1, -1);
8889              ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);
8890              ctx.restore();
8891            }
8892          },
8893
8894          paintImageMaskXObjectGroup: function CanvasGraphics_paintImageMaskXObjectGroup(images) {
8895            var ctx = this.ctx;
8896
8897            var fillColor = this.current.fillColor;
8898            var isPatternFill = this.current.patternFill;
8899            for (var i = 0, ii = images.length; i < ii; i++) {
8900              var image = images[i];
8901              var width = image.width,
8902                height = image.height;
8903
8904              var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas', width, height);
8905              var maskCtx = maskCanvas.context;
8906              maskCtx.save();
8907
8908              putBinaryImageMask(maskCtx, image);
8909
8910              maskCtx.globalCompositeOperation = 'source-in';
8911
8912              maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this) : fillColor;
8913              maskCtx.fillRect(0, 0, width, height);
8914
8915              maskCtx.restore();
8916
8917              ctx.save();
8918              ctx.transform.apply(ctx, image.transform);
8919              ctx.scale(1, -1);
8920              ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);
8921              ctx.restore();
8922            }
8923          },
8924
8925          paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
8926            var imgData = this.objs.get(objId);
8927            if (!imgData) {
8928              warn("Dependent image isn't ready yet");
8929              return;
8930            }
8931
8932            this.paintInlineImageXObject(imgData);
8933          },
8934
8935          paintImageXObjectRepeat: function CanvasGraphics_paintImageXObjectRepeat(objId, scaleX, scaleY, positions) {
8936            var imgData = this.objs.get(objId);
8937            if (!imgData) {
8938              warn("Dependent image isn't ready yet");
8939              return;
8940            }
8941
8942            var width = imgData.width;
8943            var height = imgData.height;
8944            var map = [];
8945            for (var i = 0, ii = positions.length; i < ii; i += 2) {
8946              map.push({
8947                transform: [scaleX, 0, 0, scaleY, positions[i], positions[i + 1]],
8948                x: 0,
8949                y: 0,
8950                w: width,
8951                h: height,
8952              });
8953            }
8954            this.paintInlineImageXObjectGroup(imgData, map);
8955          },
8956
8957          paintInlineImageXObject: function CanvasGraphics_paintInlineImageXObject(imgData) {
8958            var width = imgData.width;
8959            var height = imgData.height;
8960            var ctx = this.ctx;
8961
8962            this.save();
8963            // scale the image to the unit square
8964            ctx.scale(1 / width, -1 / height);
8965
8966            var currentTransform = ctx.mozCurrentTransformInverse;
8967            var a = currentTransform[0],
8968              b = currentTransform[1];
8969            var widthScale = Math.max(Math.sqrt(a * a + b * b), 1);
8970            var c = currentTransform[2],
8971              d = currentTransform[3];
8972            var heightScale = Math.max(Math.sqrt(c * c + d * d), 1);
8973
8974            var imgToPaint, tmpCanvas;
8975            // instanceof HTMLElement does not work in jsdom node.js module
8976            if (imgData instanceof HTMLElement || !imgData.data) {
8977              imgToPaint = imgData;
8978            } else {
8979              tmpCanvas = this.cachedCanvases.getCanvas('inlineImage', width, height);
8980              var tmpCtx = tmpCanvas.context;
8981              putBinaryImageData(tmpCtx, imgData);
8982              imgToPaint = tmpCanvas.canvas;
8983            }
8984
8985            var paintWidth = width,
8986              paintHeight = height;
8987            var tmpCanvasId = 'prescale1';
8988            // Vertial or horizontal scaling shall not be more than 2 to not loose the
8989            // pixels during drawImage operation, painting on the temporary canvas(es)
8990            // that are twice smaller in size
8991            while ((widthScale > 2 && paintWidth > 1) || (heightScale > 2 && paintHeight > 1)) {
8992              var newWidth = paintWidth,
8993                newHeight = paintHeight;
8994              if (widthScale > 2 && paintWidth > 1) {
8995                newWidth = Math.ceil(paintWidth / 2);
8996                widthScale /= paintWidth / newWidth;
8997              }
8998              if (heightScale > 2 && paintHeight > 1) {
8999                newHeight = Math.ceil(paintHeight / 2);
9000                heightScale /= paintHeight / newHeight;
9001              }
9002              tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight);
9003              tmpCtx = tmpCanvas.context;
9004              tmpCtx.clearRect(0, 0, newWidth, newHeight);
9005              tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight);
9006              imgToPaint = tmpCanvas.canvas;
9007              paintWidth = newWidth;
9008              paintHeight = newHeight;
9009              tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1';
9010            }
9011            ctx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, 0, -height, width, height);
9012
9013            if (this.imageLayer) {
9014              var position = this.getCanvasPosition(0, -height);
9015              this.imageLayer.appendImage({
9016                imgData: imgData,
9017                left: position[0],
9018                top: position[1],
9019                width: width / currentTransform[0],
9020                height: height / currentTransform[3],
9021              });
9022            }
9023            this.restore();
9024          },
9025
9026          paintInlineImageXObjectGroup: function CanvasGraphics_paintInlineImageXObjectGroup(imgData, map) {
9027            var ctx = this.ctx;
9028            var w = imgData.width;
9029            var h = imgData.height;
9030
9031            var tmpCanvas = this.cachedCanvases.getCanvas('inlineImage', w, h);
9032            var tmpCtx = tmpCanvas.context;
9033            putBinaryImageData(tmpCtx, imgData);
9034
9035            for (var i = 0, ii = map.length; i < ii; i++) {
9036              var entry = map[i];
9037              ctx.save();
9038              ctx.transform.apply(ctx, entry.transform);
9039              ctx.scale(1, -1);
9040              ctx.drawImage(tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1);
9041              if (this.imageLayer) {
9042                var position = this.getCanvasPosition(entry.x, entry.y);
9043                this.imageLayer.appendImage({
9044                  imgData: imgData,
9045                  left: position[0],
9046                  top: position[1],
9047                  width: w,
9048                  height: h,
9049                });
9050              }
9051              ctx.restore();
9052            }
9053          },
9054
9055          paintSolidColorImageMask: function CanvasGraphics_paintSolidColorImageMask() {
9056            this.ctx.fillRect(0, 0, 1, 1);
9057          },
9058
9059          paintXObject: function CanvasGraphics_paintXObject() {
9060            warn("Unsupported 'paintXObject' command.");
9061          },
9062
9063          // Marked content
9064
9065          markPoint: function CanvasGraphics_markPoint(tag) {
9066            // TODO Marked content.
9067          },
9068          markPointProps: function CanvasGraphics_markPointProps(tag, properties) {
9069            // TODO Marked content.
9070          },
9071          beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) {
9072            // TODO Marked content.
9073          },
9074          beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps(tag, properties) {
9075            // TODO Marked content.
9076          },
9077          endMarkedContent: function CanvasGraphics_endMarkedContent() {
9078            // TODO Marked content.
9079          },
9080
9081          // Compatibility
9082
9083          beginCompat: function CanvasGraphics_beginCompat() {
9084            // TODO ignore undefined operators (should we do that anyway?)
9085          },
9086          endCompat: function CanvasGraphics_endCompat() {
9087            // TODO stop ignoring undefined operators
9088          },
9089
9090          // Helper functions
9091
9092          consumePath: function CanvasGraphics_consumePath() {
9093            var ctx = this.ctx;
9094            if (this.pendingClip) {
9095              if (this.pendingClip === EO_CLIP) {
9096                if (ctx.mozFillRule !== undefined) {
9097                  ctx.mozFillRule = 'evenodd';
9098                  ctx.clip();
9099                  ctx.mozFillRule = 'nonzero';
9100                } else {
9101                  ctx.clip('evenodd');
9102                }
9103              } else {
9104                ctx.clip();
9105              }
9106              this.pendingClip = null;
9107            }
9108            ctx.beginPath();
9109          },
9110          getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) {
9111            if (this.cachedGetSinglePixelWidth === null) {
9112              // NOTE: The `save` and `restore` commands used below is a workaround
9113              // that is necessary in order to prevent `mozCurrentTransformInverse`
9114              // from intermittently returning incorrect values in Firefox, see:
9115              // https://github.com/mozilla/pdf.js/issues/7188.
9116              this.ctx.save();
9117              var inverse = this.ctx.mozCurrentTransformInverse;
9118              this.ctx.restore();
9119              // max of the current horizontal and vertical scale
9120              this.cachedGetSinglePixelWidth = Math.sqrt(
9121                Math.max(
9122                  inverse[0] * inverse[0] + inverse[1] * inverse[1],
9123                  inverse[2] * inverse[2] + inverse[3] * inverse[3]
9124                )
9125              );
9126            }
9127            return this.cachedGetSinglePixelWidth;
9128          },
9129          getCanvasPosition: function CanvasGraphics_getCanvasPosition(x, y) {
9130            var transform = this.ctx.mozCurrentTransform;
9131            return [
9132              transform[0] * x + transform[2] * y + transform[4],
9133              transform[1] * x + transform[3] * y + transform[5],
9134            ];
9135          },
9136        };
9137
9138        for (var op in OPS) {
9139          CanvasGraphics.prototype[OPS[op]] = CanvasGraphics.prototype[op];
9140        }
9141
9142        return CanvasGraphics;
9143      })();
9144
9145      exports.CanvasGraphics = CanvasGraphics;
9146      exports.createScratchCanvas = createScratchCanvas;
9147    });
9148
9149    (function (root, factory) {
9150      {
9151        factory(
9152          (root.pdfjsDisplayAPI = {}),
9153          root.pdfjsSharedUtil,
9154          root.pdfjsDisplayFontLoader,
9155          root.pdfjsDisplayCanvas,
9156          root.pdfjsDisplayMetadata,
9157          root.pdfjsDisplayDOMUtils
9158        );
9159      }
9160    })(
9161      this,
9162      function (exports, sharedUtil, displayFontLoader, displayCanvas, displayMetadata, displayDOMUtils, amdRequire) {
9163        var InvalidPDFException = sharedUtil.InvalidPDFException;
9164        var MessageHandler = sharedUtil.MessageHandler;
9165        var MissingPDFException = sharedUtil.MissingPDFException;
9166        var PageViewport = sharedUtil.PageViewport;
9167        var PasswordResponses = sharedUtil.PasswordResponses;
9168        var PasswordException = sharedUtil.PasswordException;
9169        var StatTimer = sharedUtil.StatTimer;
9170        var UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
9171        var UnknownErrorException = sharedUtil.UnknownErrorException;
9172        var Util = sharedUtil.Util;
9173        var createPromiseCapability = sharedUtil.createPromiseCapability;
9174        var error = sharedUtil.error;
9175        var deprecated = sharedUtil.deprecated;
9176        var getVerbosityLevel = sharedUtil.getVerbosityLevel;
9177        var info = sharedUtil.info;
9178        var isInt = sharedUtil.isInt;
9179        var isArray = sharedUtil.isArray;
9180        var isArrayBuffer = sharedUtil.isArrayBuffer;
9181        var isSameOrigin = sharedUtil.isSameOrigin;
9182        var loadJpegStream = sharedUtil.loadJpegStream;
9183        var stringToBytes = sharedUtil.stringToBytes;
9184        var globalScope = sharedUtil.globalScope;
9185        var warn = sharedUtil.warn;
9186        var FontFaceObject = displayFontLoader.FontFaceObject;
9187        var FontLoader = displayFontLoader.FontLoader;
9188        var CanvasGraphics = displayCanvas.CanvasGraphics;
9189        var createScratchCanvas = displayCanvas.createScratchCanvas;
9190        var Metadata = displayMetadata.Metadata;
9191        var getDefaultSetting = displayDOMUtils.getDefaultSetting;
9192
9193        var DEFAULT_RANGE_CHUNK_SIZE = 65536; // 2^16 = 65536
9194
9195        var isWorkerDisabled = false;
9196        var workerSrc;
9197        var isPostMessageTransfersDisabled = false;
9198
9199        var useRequireEnsure = false;
9200        if (typeof window === 'undefined') {
9201          // node.js - disable worker and set require.ensure.
9202          isWorkerDisabled = true;
9203          if (typeof require.ensure === 'undefined') {
9204            require.ensure = require('node-ensure');
9205          }
9206          useRequireEnsure = true;
9207        }
9208        if (typeof __webpack_require__ !== 'undefined') {
9209          useRequireEnsure = true;
9210        }
9211        if (typeof requirejs !== 'undefined' && requirejs.toUrl) {
9212          workerSrc = requirejs.toUrl('pdfjs-dist/build/pdf.worker.js');
9213        }
9214        var dynamicLoaderSupported = typeof requirejs !== 'undefined' && requirejs.load;
9215        var fakeWorkerFilesLoader = useRequireEnsure
9216          ? function (callback) {
9217              require.ensure([], function () {
9218                var worker = require('./pdf.worker.js');
9219                callback(worker.WorkerMessageHandler);
9220              });
9221            }
9222          : dynamicLoaderSupported
9223            ? function (callback) {
9224                requirejs(['pdfjs-dist/build/pdf.worker'], function (worker) {
9225                  callback(worker.WorkerMessageHandler);
9226                });
9227              }
9228            : null;
9229
9230        /**
9231         * Document initialization / loading parameters object.
9232         *
9233         * @typedef {Object} DocumentInitParameters
9234         * @property {string}     url   - The URL of the PDF.
9235         * @property {TypedArray|Array|string} data - Binary PDF data. Use typed arrays
9236         *   (Uint8Array) to improve the memory usage. If PDF data is BASE64-encoded,
9237         *   use atob() to convert it to a binary string first.
9238         * @property {Object}     httpHeaders - Basic authentication headers.
9239         * @property {boolean}    withCredentials - Indicates whether or not cross-site
9240         *   Access-Control requests should be made using credentials such as cookies
9241         *   or authorization headers. The default is false.
9242         * @property {string}     password - For decrypting password-protected PDFs.
9243         * @property {TypedArray} initialData - A typed array with the first portion or
9244         *   all of the pdf data. Used by the extension since some data is already
9245         *   loaded before the switch to range requests.
9246         * @property {number}     length - The PDF file length. It's used for progress
9247         *   reports and range requests operations.
9248         * @property {PDFDataRangeTransport} range
9249         * @property {number}     rangeChunkSize - Optional parameter to specify
9250         *   maximum number of bytes fetched per range request. The default value is
9251         *   2^16 = 65536.
9252         * @property {PDFWorker}  worker - The worker that will be used for the loading
9253         *   and parsing of the PDF data.
9254         */
9255
9256        /**
9257         * @typedef {Object} PDFDocumentStats
9258         * @property {Array} streamTypes - Used stream types in the document (an item
9259         *   is set to true if specific stream ID was used in the document).
9260         * @property {Array} fontTypes - Used font type in the document (an item is set
9261         *   to true if specific font ID was used in the document).
9262         */
9263
9264        /**
9265         * This is the main entry point for loading a PDF and interacting with it.
9266         * NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR)
9267         * is used, which means it must follow the same origin rules that any XHR does
9268         * e.g. No cross domain requests without CORS.
9269         *
9270         * @param {string|TypedArray|DocumentInitParameters|PDFDataRangeTransport} src
9271         * Can be a url to where a PDF is located, a typed array (Uint8Array)
9272         * already populated with data or parameter object.
9273         *
9274         * @param {PDFDataRangeTransport} pdfDataRangeTransport (deprecated) It is used
9275         * if you want to manually serve range requests for data in the PDF.
9276         *
9277         * @param {function} passwordCallback (deprecated) It is used to request a
9278         * password if wrong or no password was provided. The callback receives two
9279         * parameters: function that needs to be called with new password and reason
9280         * (see {PasswordResponses}).
9281         *
9282         * @param {function} progressCallback (deprecated) It is used to be able to
9283         * monitor the loading progress of the PDF file (necessary to implement e.g.
9284         * a loading bar). The callback receives an {Object} with the properties:
9285         * {number} loaded and {number} total.
9286         *
9287         * @return {PDFDocumentLoadingTask}
9288         */
9289        function getDocument(src, pdfDataRangeTransport, passwordCallback, progressCallback) {
9290          var task = new PDFDocumentLoadingTask();
9291
9292          // Support of the obsolete arguments (for compatibility with API v1.0)
9293          if (arguments.length > 1) {
9294            deprecated(
9295              'getDocument is called with pdfDataRangeTransport, ' + 'passwordCallback or progressCallback argument'
9296            );
9297          }
9298          if (pdfDataRangeTransport) {
9299            if (!(pdfDataRangeTransport instanceof PDFDataRangeTransport)) {
9300              // Not a PDFDataRangeTransport instance, trying to add missing properties.
9301              pdfDataRangeTransport = Object.create(pdfDataRangeTransport);
9302              pdfDataRangeTransport.length = src.length;
9303              pdfDataRangeTransport.initialData = src.initialData;
9304              if (!pdfDataRangeTransport.abort) {
9305                pdfDataRangeTransport.abort = function () {};
9306              }
9307            }
9308            src = Object.create(src);
9309            src.range = pdfDataRangeTransport;
9310          }
9311          task.onPassword = passwordCallback || null;
9312          task.onProgress = progressCallback || null;
9313
9314          var source;
9315          if (typeof src === 'string') {
9316            source = { url: src };
9317          } else if (isArrayBuffer(src)) {
9318            source = { data: src };
9319          } else if (src instanceof PDFDataRangeTransport) {
9320            source = { range: src };
9321          } else {
9322            if (typeof src !== 'object') {
9323              error('Invalid parameter in getDocument, need either Uint8Array, ' + 'string or a parameter object');
9324            }
9325            if (!src.url && !src.data && !src.range) {
9326              error('Invalid parameter object: need either .data, .range or .url');
9327            }
9328
9329            source = src;
9330          }
9331
9332          var params = {};
9333          var rangeTransport = null;
9334          var worker = null;
9335          for (var key in source) {
9336            if (key === 'url' && typeof window !== 'undefined') {
9337              // The full path is required in the 'url' field.
9338              params[key] = new URL(source[key], window.location).href;
9339              continue;
9340            } else if (key === 'range') {
9341              rangeTransport = source[key];
9342              continue;
9343            } else if (key === 'worker') {
9344              worker = source[key];
9345              continue;
9346            } else if (key === 'data' && !(source[key] instanceof Uint8Array)) {
9347              // Converting string or array-like data to Uint8Array.
9348              var pdfBytes = source[key];
9349              if (typeof pdfBytes === 'string') {
9350                params[key] = stringToBytes(pdfBytes);
9351              } else if (typeof pdfBytes === 'object' && pdfBytes !== null && !isNaN(pdfBytes.length)) {
9352                params[key] = new Uint8Array(pdfBytes);
9353              } else if (isArrayBuffer(pdfBytes)) {
9354                params[key] = new Uint8Array(pdfBytes);
9355              } else {
9356                error(
9357                  'Invalid PDF binary data: either typed array, string or ' +
9358                    'array-like object is expected in the data property.'
9359                );
9360              }
9361              continue;
9362            }
9363            params[key] = source[key];
9364          }
9365
9366          params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
9367
9368          if (!worker) {
9369            // Worker was not provided -- creating and owning our own.
9370            worker = new PDFWorker();
9371            task._worker = worker;
9372          }
9373          var docId = task.docId;
9374          worker.promise
9375            .then(function () {
9376              if (task.destroyed) {
9377                throw new Error('Loading aborted');
9378              }
9379              return _fetchDocument(worker, params, rangeTransport, docId).then(function (workerId) {
9380                if (task.destroyed) {
9381                  throw new Error('Loading aborted');
9382                }
9383                var messageHandler = new MessageHandler(docId, workerId, worker.port);
9384                var transport = new WorkerTransport(messageHandler, task, rangeTransport);
9385                task._transport = transport;
9386                messageHandler.send('Ready', null);
9387              });
9388            })
9389            .catch(task._capability.reject);
9390
9391          return task;
9392        }
9393
9394        /**
9395         * Starts fetching of specified PDF document/data.
9396         * @param {PDFWorker} worker
9397         * @param {Object} source
9398         * @param {PDFDataRangeTransport} pdfDataRangeTransport
9399         * @param {string} docId Unique document id, used as MessageHandler id.
9400         * @returns {Promise} The promise, which is resolved when worker id of
9401         *                    MessageHandler is known.
9402         * @private
9403         */
9404        function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
9405          if (worker.destroyed) {
9406            return Promise.reject(new Error('Worker was destroyed'));
9407          }
9408
9409          source.disableAutoFetch = getDefaultSetting('disableAutoFetch');
9410          source.disableStream = getDefaultSetting('disableStream');
9411          source.chunkedViewerLoading = !!pdfDataRangeTransport;
9412          if (pdfDataRangeTransport) {
9413            source.length = pdfDataRangeTransport.length;
9414            source.initialData = pdfDataRangeTransport.initialData;
9415          }
9416          return worker.messageHandler
9417            .sendWithPromise('GetDocRequest', {
9418              docId: docId,
9419              source: source,
9420              disableRange: getDefaultSetting('disableRange'),
9421              maxImageSize: getDefaultSetting('maxImageSize'),
9422              cMapUrl: getDefaultSetting('cMapUrl'),
9423              cMapPacked: getDefaultSetting('cMapPacked'),
9424              disableFontFace: getDefaultSetting('disableFontFace'),
9425              disableCreateObjectURL: getDefaultSetting('disableCreateObjectURL'),
9426              postMessageTransfers: getDefaultSetting('postMessageTransfers') && !isPostMessageTransfersDisabled,
9427            })
9428            .then(function (workerId) {
9429              if (worker.destroyed) {
9430                throw new Error('Worker was destroyed');
9431              }
9432              return workerId;
9433            });
9434        }
9435
9436        /**
9437         * PDF document loading operation.
9438         * @class
9439         * @alias PDFDocumentLoadingTask
9440         */
9441        var PDFDocumentLoadingTask = (function PDFDocumentLoadingTaskClosure() {
9442          var nextDocumentId = 0;
9443
9444          /** @constructs PDFDocumentLoadingTask */
9445          function PDFDocumentLoadingTask() {
9446            this._capability = createPromiseCapability();
9447            this._transport = null;
9448            this._worker = null;
9449
9450            /**
9451             * Unique document loading task id -- used in MessageHandlers.
9452             * @type {string}
9453             */
9454            this.docId = 'd' + nextDocumentId++;
9455
9456            /**
9457             * Shows if loading task is destroyed.
9458             * @type {boolean}
9459             */
9460            this.destroyed = false;
9461
9462            /**
9463             * Callback to request a password if wrong or no password was provided.
9464             * The callback receives two parameters: function that needs to be called
9465             * with new password and reason (see {PasswordResponses}).
9466             */
9467            this.onPassword = null;
9468
9469            /**
9470             * Callback to be able to monitor the loading progress of the PDF file
9471             * (necessary to implement e.g. a loading bar). The callback receives
9472             * an {Object} with the properties: {number} loaded and {number} total.
9473             */
9474            this.onProgress = null;
9475
9476            /**
9477             * Callback to when unsupported feature is used. The callback receives
9478             * an {UNSUPPORTED_FEATURES} argument.
9479             */
9480            this.onUnsupportedFeature = null;
9481          }
9482
9483          PDFDocumentLoadingTask.prototype = /** @lends PDFDocumentLoadingTask.prototype */ {
9484            /**
9485             * @return {Promise}
9486             */
9487            get promise() {
9488              return this._capability.promise;
9489            },
9490
9491            /**
9492             * Aborts all network requests and destroys worker.
9493             * @return {Promise} A promise that is resolved after destruction activity
9494             *                   is completed.
9495             */
9496            destroy: function () {
9497              this.destroyed = true;
9498
9499              var transportDestroyed = !this._transport ? Promise.resolve() : this._transport.destroy();
9500              return transportDestroyed.then(
9501                function () {
9502                  this._transport = null;
9503                  if (this._worker) {
9504                    this._worker.destroy();
9505                    this._worker = null;
9506                  }
9507                }.bind(this)
9508              );
9509            },
9510
9511            /**
9512             * Registers callbacks to indicate the document loading completion.
9513             *
9514             * @param {function} onFulfilled The callback for the loading completion.
9515             * @param {function} onRejected The callback for the loading failure.
9516             * @return {Promise} A promise that is resolved after the onFulfilled or
9517             *                   onRejected callback.
9518             */
9519            then: function PDFDocumentLoadingTask_then(onFulfilled, onRejected) {
9520              return this.promise.then.apply(this.promise, arguments);
9521            },
9522          };
9523
9524          return PDFDocumentLoadingTask;
9525        })();
9526
9527        /**
9528         * Abstract class to support range requests file loading.
9529         * @class
9530         * @alias PDFDataRangeTransport
9531         * @param {number} length
9532         * @param {Uint8Array} initialData
9533         */
9534        var PDFDataRangeTransport = (function pdfDataRangeTransportClosure() {
9535          function PDFDataRangeTransport(length, initialData) {
9536            this.length = length;
9537            this.initialData = initialData;
9538
9539            this._rangeListeners = [];
9540            this._progressListeners = [];
9541            this._progressiveReadListeners = [];
9542            this._readyCapability = createPromiseCapability();
9543          }
9544
9545          PDFDataRangeTransport.prototype = /** @lends PDFDataRangeTransport.prototype */ {
9546            addRangeListener: function PDFDataRangeTransport_addRangeListener(listener) {
9547              this._rangeListeners.push(listener);
9548            },
9549
9550            addProgressListener: function PDFDataRangeTransport_addProgressListener(listener) {
9551              this._progressListeners.push(listener);
9552            },
9553
9554            addProgressiveReadListener: function PDFDataRangeTransport_addProgressiveReadListener(listener) {
9555              this._progressiveReadListeners.push(listener);
9556            },
9557
9558            onDataRange: function PDFDataRangeTransport_onDataRange(begin, chunk) {
9559              var listeners = this._rangeListeners;
9560              for (var i = 0, n = listeners.length; i < n; ++i) {
9561                listeners[i](begin, chunk);
9562              }
9563            },
9564
9565            onDataProgress: function PDFDataRangeTransport_onDataProgress(loaded) {
9566              this._readyCapability.promise.then(
9567                function () {
9568                  var listeners = this._progressListeners;
9569                  for (var i = 0, n = listeners.length; i < n; ++i) {
9570                    listeners[i](loaded);
9571                  }
9572                }.bind(this)
9573              );
9574            },
9575
9576            onDataProgressiveRead: function PDFDataRangeTransport_onDataProgress(chunk) {
9577              this._readyCapability.promise.then(
9578                function () {
9579                  var listeners = this._progressiveReadListeners;
9580                  for (var i = 0, n = listeners.length; i < n; ++i) {
9581                    listeners[i](chunk);
9582                  }
9583                }.bind(this)
9584              );
9585            },
9586
9587            transportReady: function PDFDataRangeTransport_transportReady() {
9588              this._readyCapability.resolve();
9589            },
9590
9591            requestDataRange: function PDFDataRangeTransport_requestDataRange(begin, end) {
9592              throw new Error('Abstract method PDFDataRangeTransport.requestDataRange');
9593            },
9594
9595            abort: function PDFDataRangeTransport_abort() {},
9596          };
9597          return PDFDataRangeTransport;
9598        })();
9599
9600        /**
9601         * Proxy to a PDFDocument in the worker thread. Also, contains commonly used
9602         * properties that can be read synchronously.
9603         * @class
9604         * @alias PDFDocumentProxy
9605         */
9606        var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
9607          function PDFDocumentProxy(pdfInfo, transport, loadingTask) {
9608            this.pdfInfo = pdfInfo;
9609            this.transport = transport;
9610            this.loadingTask = loadingTask;
9611          }
9612
9613          PDFDocumentProxy.prototype = /** @lends PDFDocumentProxy.prototype */ {
9614            /**
9615             * @return {number} Total number of pages the PDF contains.
9616             */
9617            get numPages() {
9618              return this.pdfInfo.numPages;
9619            },
9620            /**
9621             * @return {string} A unique ID to identify a PDF. Not guaranteed to be
9622             * unique.
9623             */
9624            get fingerprint() {
9625              return this.pdfInfo.fingerprint;
9626            },
9627            /**
9628             * @param {number} pageNumber The page number to get. The first page is 1.
9629             * @return {Promise} A promise that is resolved with a {@link PDFPageProxy}
9630             * object.
9631             */
9632            getPage: function PDFDocumentProxy_getPage(pageNumber) {
9633              return this.transport.getPage(pageNumber);
9634            },
9635            /**
9636             * @param {{num: number, gen: number}} ref The page reference. Must have
9637             *   the 'num' and 'gen' properties.
9638             * @return {Promise} A promise that is resolved with the page index that is
9639             * associated with the reference.
9640             */
9641            getPageIndex: function PDFDocumentProxy_getPageIndex(ref) {
9642              return this.transport.getPageIndex(ref);
9643            },
9644            /**
9645             * @return {Promise} A promise that is resolved with a lookup table for
9646             * mapping named destinations to reference numbers.
9647             *
9648             * This can be slow for large documents: use getDestination instead
9649             */
9650            getDestinations: function PDFDocumentProxy_getDestinations() {
9651              return this.transport.getDestinations();
9652            },
9653            /**
9654             * @param {string} id The named destination to get.
9655             * @return {Promise} A promise that is resolved with all information
9656             * of the given named destination.
9657             */
9658            getDestination: function PDFDocumentProxy_getDestination(id) {
9659              return this.transport.getDestination(id);
9660            },
9661            /**
9662             * @return {Promise} A promise that is resolved with:
9663             *   an Array containing the pageLabels that correspond to the pageIndexes,
9664             *   or `null` when no pageLabels are present in the PDF file.
9665             */
9666            getPageLabels: function PDFDocumentProxy_getPageLabels() {
9667              return this.transport.getPageLabels();
9668            },
9669            /**
9670             * @return {Promise} A promise that is resolved with a lookup table for
9671             * mapping named attachments to their content.
9672             */
9673            getAttachments: function PDFDocumentProxy_getAttachments() {
9674              return this.transport.getAttachments();
9675            },
9676            /**
9677             * @return {Promise} A promise that is resolved with an array of all the
9678             * JavaScript strings in the name tree.
9679             */
9680            getJavaScript: function PDFDocumentProxy_getJavaScript() {
9681              return this.transport.getJavaScript();
9682            },
9683            /**
9684             * @return {Promise} A promise that is resolved with an {Array} that is a
9685             * tree outline (if it has one) of the PDF. The tree is in the format of:
9686             * [
9687             *  {
9688             *   title: string,
9689             *   bold: boolean,
9690             *   italic: boolean,
9691             *   color: rgb Uint8Array,
9692             *   dest: dest obj,
9693             *   url: string,
9694             *   items: array of more items like this
9695             *  },
9696             *  ...
9697             * ].
9698             */
9699            getOutline: function PDFDocumentProxy_getOutline() {
9700              return this.transport.getOutline();
9701            },
9702            /**
9703             * @return {Promise} A promise that is resolved with an {Object} that has
9704             * info and metadata properties.  Info is an {Object} filled with anything
9705             * available in the information dictionary and similarly metadata is a
9706             * {Metadata} object with information from the metadata section of the PDF.
9707             */
9708            getMetadata: function PDFDocumentProxy_getMetadata() {
9709              return this.transport.getMetadata();
9710            },
9711            /**
9712             * @return {Promise} A promise that is resolved with a TypedArray that has
9713             * the raw data from the PDF.
9714             */
9715            getData: function PDFDocumentProxy_getData() {
9716              return this.transport.getData();
9717            },
9718            /**
9719             * @return {Promise} A promise that is resolved when the document's data
9720             * is loaded. It is resolved with an {Object} that contains the length
9721             * property that indicates size of the PDF data in bytes.
9722             */
9723            getDownloadInfo: function PDFDocumentProxy_getDownloadInfo() {
9724              return this.transport.downloadInfoCapability.promise;
9725            },
9726            /**
9727             * @return {Promise} A promise this is resolved with current stats about
9728             * document structures (see {@link PDFDocumentStats}).
9729             */
9730            getStats: function PDFDocumentProxy_getStats() {
9731              return this.transport.getStats();
9732            },
9733            /**
9734             * Cleans up resources allocated by the document, e.g. created @font-face.
9735             */
9736            cleanup: function PDFDocumentProxy_cleanup() {
9737              this.transport.startCleanup();
9738            },
9739            /**
9740             * Destroys current document instance and terminates worker.
9741             */
9742            destroy: function PDFDocumentProxy_destroy() {
9743              return this.loadingTask.destroy();
9744            },
9745          };
9746          return PDFDocumentProxy;
9747        })();
9748
9749        /**
9750         * Page getTextContent parameters.
9751         *
9752         * @typedef {Object} getTextContentParameters
9753         * @param {boolean} normalizeWhitespace - replaces all occurrences of
9754         *   whitespace with standard spaces (0x20). The default value is `false`.
9755         * @param {boolean} disableCombineTextItems - do not attempt to combine
9756         *   same line {@link TextItem}'s. The default value is `false`.
9757         */
9758
9759        /**
9760         * Page text content.
9761         *
9762         * @typedef {Object} TextContent
9763         * @property {array} items - array of {@link TextItem}
9764         * @property {Object} styles - {@link TextStyles} objects, indexed by font
9765         *                    name.
9766         */
9767
9768        /**
9769         * Page text content part.
9770         *
9771         * @typedef {Object} TextItem
9772         * @property {string} str - text content.
9773         * @property {string} dir - text direction: 'ttb', 'ltr' or 'rtl'.
9774         * @property {array} transform - transformation matrix.
9775         * @property {number} width - width in device space.
9776         * @property {number} height - height in device space.
9777         * @property {string} fontName - font name used by pdf.js for converted font.
9778         */
9779
9780        /**
9781         * Text style.
9782         *
9783         * @typedef {Object} TextStyle
9784         * @property {number} ascent - font ascent.
9785         * @property {number} descent - font descent.
9786         * @property {boolean} vertical - text is in vertical mode.
9787         * @property {string} fontFamily - possible font family
9788         */
9789
9790        /**
9791         * Page annotation parameters.
9792         *
9793         * @typedef {Object} GetAnnotationsParameters
9794         * @param {string} intent - Determines the annotations that will be fetched,
9795         *                 can be either 'display' (viewable annotations) or 'print'
9796         *                 (printable annotations).
9797         *                 If the parameter is omitted, all annotations are fetched.
9798         */
9799
9800        /**
9801         * Page render parameters.
9802         *
9803         * @typedef {Object} RenderParameters
9804         * @property {Object} canvasContext - A 2D context of a DOM Canvas object.
9805         * @property {PageViewport} viewport - Rendering viewport obtained by
9806         *                                calling of PDFPage.getViewport method.
9807         * @property {string} intent - Rendering intent, can be 'display' or 'print'
9808         *                    (default value is 'display').
9809         * @property {boolean} renderInteractiveForms - (optional) Whether or not
9810         *                     interactive form elements are rendered in the display
9811         *                     layer. If so, we do not render them on canvas as well.
9812         * @property {Array}  transform - (optional) Additional transform, applied
9813         *                    just before viewport transform.
9814         * @property {Object} imageLayer - (optional) An object that has beginLayout,
9815         *                    endLayout and appendImage functions.
9816         * @property {function} continueCallback - (deprecated) A function that will be
9817         *                      called each time the rendering is paused.  To continue
9818         *                      rendering call the function that is the first argument
9819         *                      to the callback.
9820         */
9821
9822        /**
9823         * PDF page operator list.
9824         *
9825         * @typedef {Object} PDFOperatorList
9826         * @property {Array} fnArray - Array containing the operator functions.
9827         * @property {Array} argsArray - Array containing the arguments of the
9828         *                               functions.
9829         */
9830
9831        /**
9832         * Proxy to a PDFPage in the worker thread.
9833         * @class
9834         * @alias PDFPageProxy
9835         */
9836        var PDFPageProxy = (function PDFPageProxyClosure() {
9837          function PDFPageProxy(pageIndex, pageInfo, transport) {
9838            this.pageIndex = pageIndex;
9839            this.pageInfo = pageInfo;
9840            this.transport = transport;
9841            this.stats = new StatTimer();
9842            this.stats.enabled = getDefaultSetting('enableStats');
9843            this.commonObjs = transport.commonObjs;
9844            this.objs = new PDFObjects();
9845            this.cleanupAfterRender = false;
9846            this.pendingCleanup = false;
9847            this.intentStates = Object.create(null);
9848            this.destroyed = false;
9849          }
9850
9851          PDFPageProxy.prototype = /** @lends PDFPageProxy.prototype */ {
9852            /**
9853             * @return {number} Page number of the page. First page is 1.
9854             */
9855            get pageNumber() {
9856              return this.pageIndex + 1;
9857            },
9858            /**
9859             * @return {number} The number of degrees the page is rotated clockwise.
9860             */
9861            get rotate() {
9862              return this.pageInfo.rotate;
9863            },
9864            /**
9865             * @return {Object} The reference that points to this page. It has 'num' and
9866             * 'gen' properties.
9867             */
9868            get ref() {
9869              return this.pageInfo.ref;
9870            },
9871            /**
9872             * @return {Array} An array of the visible portion of the PDF page in the
9873             * user space units - [x1, y1, x2, y2].
9874             */
9875            get view() {
9876              return this.pageInfo.view;
9877            },
9878            /**
9879             * @param {number} scale The desired scale of the viewport.
9880             * @param {number} rotate Degrees to rotate the viewport. If omitted this
9881             * defaults to the page rotation.
9882             * @return {PageViewport} Contains 'width' and 'height' properties
9883             * along with transforms required for rendering.
9884             */
9885            getViewport: function PDFPageProxy_getViewport(scale, rotate) {
9886              if (arguments.length < 2) {
9887                rotate = this.rotate;
9888              }
9889              return new PageViewport(this.view, scale, rotate, 0, 0);
9890            },
9891            /**
9892             * @param {GetAnnotationsParameters} params - Annotation parameters.
9893             * @return {Promise} A promise that is resolved with an {Array} of the
9894             * annotation objects.
9895             */
9896            getAnnotations: function PDFPageProxy_getAnnotations(params) {
9897              var intent = (params && params.intent) || null;
9898
9899              if (!this.annotationsPromise || this.annotationsIntent !== intent) {
9900                this.annotationsPromise = this.transport.getAnnotations(this.pageIndex, intent);
9901                this.annotationsIntent = intent;
9902              }
9903              return this.annotationsPromise;
9904            },
9905            /**
9906             * Begins the process of rendering a page to the desired context.
9907             * @param {RenderParameters} params Page render parameters.
9908             * @return {RenderTask} An object that contains the promise, which
9909             *                      is resolved when the page finishes rendering.
9910             */
9911            render: function PDFPageProxy_render(params) {
9912              var stats = this.stats;
9913              stats.time('Overall');
9914
9915              // If there was a pending destroy cancel it so no cleanup happens during
9916              // this call to render.
9917              this.pendingCleanup = false;
9918
9919              var renderingIntent = params.intent === 'print' ? 'print' : 'display';
9920              var renderInteractiveForms = params.renderInteractiveForms === true ? true : /* Default */ false;
9921
9922              if (!this.intentStates[renderingIntent]) {
9923                this.intentStates[renderingIntent] = Object.create(null);
9924              }
9925              var intentState = this.intentStates[renderingIntent];
9926
9927              // If there's no displayReadyCapability yet, then the operatorList
9928              // was never requested before. Make the request and create the promise.
9929              if (!intentState.displayReadyCapability) {
9930                intentState.receivingOperatorList = true;
9931                intentState.displayReadyCapability = createPromiseCapability();
9932                intentState.operatorList = {
9933                  fnArray: [],
9934                  argsArray: [],
9935                  lastChunk: false,
9936                };
9937
9938                this.stats.time('Page Request');
9939                this.transport.messageHandler.send('RenderPageRequest', {
9940                  pageIndex: this.pageNumber - 1,
9941                  intent: renderingIntent,
9942                  renderInteractiveForms: renderInteractiveForms,
9943                });
9944              }
9945
9946              var internalRenderTask = new InternalRenderTask(
9947                complete,
9948                params,
9949                this.objs,
9950                this.commonObjs,
9951                intentState.operatorList,
9952                this.pageNumber
9953              );
9954              internalRenderTask.useRequestAnimationFrame = renderingIntent !== 'print';
9955              if (!intentState.renderTasks) {
9956                intentState.renderTasks = [];
9957              }
9958              intentState.renderTasks.push(internalRenderTask);
9959              var renderTask = internalRenderTask.task;
9960
9961              // Obsolete parameter support
9962              if (params.continueCallback) {
9963                deprecated('render is used with continueCallback parameter');
9964                renderTask.onContinue = params.continueCallback;
9965              }
9966
9967              var self = this;
9968              intentState.displayReadyCapability.promise.then(
9969                function pageDisplayReadyPromise(transparency) {
9970                  if (self.pendingCleanup) {
9971                    complete();
9972                    return;
9973                  }
9974                  stats.time('Rendering');
9975                  internalRenderTask.initializeGraphics(transparency);
9976                  internalRenderTask.operatorListChanged();
9977                },
9978                function pageDisplayReadPromiseError(reason) {
9979                  complete(reason);
9980                }
9981              );
9982
9983              function complete(error) {
9984                var i = intentState.renderTasks.indexOf(internalRenderTask);
9985                if (i >= 0) {
9986                  intentState.renderTasks.splice(i, 1);
9987                }
9988
9989                if (self.cleanupAfterRender) {
9990                  self.pendingCleanup = true;
9991                }
9992                self._tryCleanup();
9993
9994                if (error) {
9995                  internalRenderTask.capability.reject(error);
9996                } else {
9997                  internalRenderTask.capability.resolve();
9998                }
9999                stats.timeEnd('Rendering');
10000                stats.timeEnd('Overall');
10001              }
10002
10003              return renderTask;
10004            },
10005
10006            /**
10007             * @return {Promise} A promise resolved with an {@link PDFOperatorList}
10008             * object that represents page's operator list.
10009             */
10010            getOperatorList: function PDFPageProxy_getOperatorList() {
10011              function operatorListChanged() {
10012                if (intentState.operatorList.lastChunk) {
10013                  intentState.opListReadCapability.resolve(intentState.operatorList);
10014
10015                  var i = intentState.renderTasks.indexOf(opListTask);
10016                  if (i >= 0) {
10017                    intentState.renderTasks.splice(i, 1);
10018                  }
10019                }
10020              }
10021
10022              var renderingIntent = 'oplist';
10023              if (!this.intentStates[renderingIntent]) {
10024                this.intentStates[renderingIntent] = Object.create(null);
10025              }
10026              var intentState = this.intentStates[renderingIntent];
10027              var opListTask;
10028
10029              if (!intentState.opListReadCapability) {
10030                opListTask = {};
10031                opListTask.operatorListChanged = operatorListChanged;
10032                intentState.receivingOperatorList = true;
10033                intentState.opListReadCapability = createPromiseCapability();
10034                intentState.renderTasks = [];
10035                intentState.renderTasks.push(opListTask);
10036                intentState.operatorList = {
10037                  fnArray: [],
10038                  argsArray: [],
10039                  lastChunk: false,
10040                };
10041
10042                this.transport.messageHandler.send('RenderPageRequest', {
10043                  pageIndex: this.pageIndex,
10044                  intent: renderingIntent,
10045                });
10046              }
10047              return intentState.opListReadCapability.promise;
10048            },
10049
10050            /**
10051             * @param {getTextContentParameters} params - getTextContent parameters.
10052             * @return {Promise} That is resolved a {@link TextContent}
10053             * object that represent the page text content.
10054             */
10055            getTextContent: function PDFPageProxy_getTextContent(params) {
10056              return this.transport.messageHandler.sendWithPromise('GetTextContent', {
10057                pageIndex: this.pageNumber - 1,
10058                normalizeWhitespace: params && params.normalizeWhitespace === true ? true : /* Default */ false,
10059                combineTextItems: params && params.disableCombineTextItems === true ? false : /* Default */ true,
10060              });
10061            },
10062
10063            /**
10064             * Destroys page object.
10065             */
10066            _destroy: function PDFPageProxy_destroy() {
10067              this.destroyed = true;
10068              this.transport.pageCache[this.pageIndex] = null;
10069
10070              var waitOn = [];
10071              Object.keys(this.intentStates).forEach(function (intent) {
10072                if (intent === 'oplist') {
10073                  // Avoid errors below, since the renderTasks are just stubs.
10074                  return;
10075                }
10076                var intentState = this.intentStates[intent];
10077                intentState.renderTasks.forEach(function (renderTask) {
10078                  var renderCompleted = renderTask.capability.promise.catch(function () {}); // ignoring failures
10079                  waitOn.push(renderCompleted);
10080                  renderTask.cancel();
10081                });
10082              }, this);
10083              this.objs.clear();
10084              this.annotationsPromise = null;
10085              this.pendingCleanup = false;
10086              return Promise.all(waitOn);
10087            },
10088
10089            /**
10090             * Cleans up resources allocated by the page. (deprecated)
10091             */
10092            destroy: function () {
10093              deprecated('page destroy method, use cleanup() instead');
10094              this.cleanup();
10095            },
10096
10097            /**
10098             * Cleans up resources allocated by the page.
10099             */
10100            cleanup: function PDFPageProxy_cleanup() {
10101              this.pendingCleanup = true;
10102              this._tryCleanup();
10103            },
10104            /**
10105             * For internal use only. Attempts to clean up if rendering is in a state
10106             * where that's possible.
10107             * @ignore
10108             */
10109            _tryCleanup: function PDFPageProxy_tryCleanup() {
10110              if (
10111                !this.pendingCleanup ||
10112                Object.keys(this.intentStates).some(function (intent) {
10113                  var intentState = this.intentStates[intent];
10114                  return intentState.renderTasks.length !== 0 || intentState.receivingOperatorList;
10115                }, this)
10116              ) {
10117                return;
10118              }
10119
10120              Object.keys(this.intentStates).forEach(function (intent) {
10121                delete this.intentStates[intent];
10122              }, this);
10123              this.objs.clear();
10124              this.annotationsPromise = null;
10125              this.pendingCleanup = false;
10126            },
10127            /**
10128             * For internal use only.
10129             * @ignore
10130             */
10131            _startRenderPage: function PDFPageProxy_startRenderPage(transparency, intent) {
10132              var intentState = this.intentStates[intent];
10133              // TODO Refactor RenderPageRequest to separate rendering
10134              // and operator list logic
10135              if (intentState.displayReadyCapability) {
10136                intentState.displayReadyCapability.resolve(transparency);
10137              }
10138            },
10139            /**
10140             * For internal use only.
10141             * @ignore
10142             */
10143            _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk, intent) {
10144              var intentState = this.intentStates[intent];
10145              var i, ii;
10146              // Add the new chunk to the current operator list.
10147              for (i = 0, ii = operatorListChunk.length; i < ii; i++) {
10148                intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
10149                intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
10150              }
10151              intentState.operatorList.lastChunk = operatorListChunk.lastChunk;
10152
10153              // Notify all the rendering tasks there are more operators to be consumed.
10154              for (i = 0; i < intentState.renderTasks.length; i++) {
10155                intentState.renderTasks[i].operatorListChanged();
10156              }
10157
10158              if (operatorListChunk.lastChunk) {
10159                intentState.receivingOperatorList = false;
10160                this._tryCleanup();
10161              }
10162            },
10163          };
10164          return PDFPageProxy;
10165        })();
10166
10167        /**
10168         * PDF.js web worker abstraction, it controls instantiation of PDF documents and
10169         * WorkerTransport for them.  If creation of a web worker is not possible,
10170         * a "fake" worker will be used instead.
10171         * @class
10172         */
10173        var PDFWorker = (function PDFWorkerClosure() {
10174          var nextFakeWorkerId = 0;
10175
10176          function getWorkerSrc() {
10177            if (typeof workerSrc !== 'undefined') {
10178              return workerSrc;
10179            }
10180            if (getDefaultSetting('workerSrc')) {
10181              return getDefaultSetting('workerSrc');
10182            }
10183            if (pdfjsFilePath) {
10184              return pdfjsFilePath.replace(/\.js$/i, '.worker.js');
10185            }
10186            error('No PDFJS.workerSrc specified');
10187          }
10188
10189          var fakeWorkerFilesLoadedCapability;
10190
10191          // Loads worker code into main thread.
10192          function setupFakeWorkerGlobal() {
10193            var WorkerMessageHandler;
10194            if (!fakeWorkerFilesLoadedCapability) {
10195              fakeWorkerFilesLoadedCapability = createPromiseCapability();
10196              // In the developer build load worker_loader which in turn loads all the
10197              // other files and resolves the promise. In production only the
10198              // pdf.worker.js file is needed.
10199              var loader =
10200                fakeWorkerFilesLoader ||
10201                function (callback) {
10202                  Util.loadScript(getWorkerSrc(), function () {
10203                    callback(window.pdfjsDistBuildPdfWorker.WorkerMessageHandler);
10204                  });
10205                };
10206              loader(fakeWorkerFilesLoadedCapability.resolve);
10207            }
10208            return fakeWorkerFilesLoadedCapability.promise;
10209          }
10210
10211          function FakeWorkerPort(defer) {
10212            this._listeners = [];
10213            this._defer = defer;
10214            this._deferred = Promise.resolve(undefined);
10215          }
10216
10217          FakeWorkerPort.prototype = {
10218            postMessage: function (obj, transfers) {
10219              function cloneValue(value) {
10220                // Trying to perform a structured clone close to the spec, including
10221                // transfers.
10222                if (typeof value !== 'object' || value === null) {
10223                  return value;
10224                }
10225                if (cloned.has(value)) {
10226                  // already cloned the object
10227                  return cloned.get(value);
10228                }
10229                var result;
10230                var buffer;
10231                if ((buffer = value.buffer) && isArrayBuffer(buffer)) {
10232                  // We found object with ArrayBuffer (typed array).
10233                  var transferable = transfers && transfers.indexOf(buffer) >= 0;
10234                  if (value === buffer) {
10235                    // Special case when we are faking typed arrays in compatibility.js.
10236                    result = value;
10237                  } else if (transferable) {
10238                    result = new value.constructor(buffer, value.byteOffset, value.byteLength);
10239                  } else {
10240                    result = new value.constructor(value);
10241                  }
10242                  cloned.set(value, result);
10243                  return result;
10244                }
10245                result = isArray(value) ? [] : {};
10246                cloned.set(value, result); // adding to cache now for cyclic references
10247                // Cloning all value and object properties, however ignoring properties
10248                // defined via getter.
10249                for (var i in value) {
10250                  var desc,
10251                    p = value;
10252                  while (!(desc = Object.getOwnPropertyDescriptor(p, i))) {
10253                    p = Object.getPrototypeOf(p);
10254                  }
10255                  if (typeof desc.value === 'undefined' || typeof desc.value === 'function') {
10256                    continue;
10257                  }
10258                  result[i] = cloneValue(desc.value);
10259                }
10260                return result;
10261              }
10262
10263              if (!this._defer) {
10264                this._listeners.forEach(function (listener) {
10265                  listener.call(this, { data: obj });
10266                }, this);
10267                return;
10268              }
10269
10270              var cloned = new WeakMap();
10271              var e = { data: cloneValue(obj) };
10272              this._deferred.then(
10273                function () {
10274                  this._listeners.forEach(function (listener) {
10275                    listener.call(this, e);
10276                  }, this);
10277                }.bind(this)
10278              );
10279            },
10280            addEventListener: function (name, listener) {
10281              this._listeners.push(listener);
10282            },
10283            removeEventListener: function (name, listener) {
10284              var i = this._listeners.indexOf(listener);
10285              this._listeners.splice(i, 1);
10286            },
10287            terminate: function () {
10288              this._listeners = [];
10289            },
10290          };
10291
10292          function createCDNWrapper(url) {
10293            // We will rely on blob URL's property to specify origin.
10294            // We want this function to fail in case if createObjectURL or Blob do not
10295            // exist or fail for some reason -- our Worker creation will fail anyway.
10296            var wrapper = "importScripts('" + url + "');";
10297            return URL.createObjectURL(new Blob([wrapper]));
10298          }
10299
10300          function PDFWorker(name) {
10301            this.name = name;
10302            this.destroyed = false;
10303
10304            this._readyCapability = createPromiseCapability();
10305            this._port = null;
10306            this._webWorker = null;
10307            this._messageHandler = null;
10308            this._initialize();
10309          }
10310
10311          PDFWorker.prototype = /** @lends PDFWorker.prototype */ {
10312            get promise() {
10313              return this._readyCapability.promise;
10314            },
10315
10316            get port() {
10317              return this._port;
10318            },
10319
10320            get messageHandler() {
10321              return this._messageHandler;
10322            },
10323
10324            _initialize: function PDFWorker_initialize() {
10325              // If worker support isn't disabled explicit and the browser has worker
10326              // support, create a new web worker and test if it/the browser fulfills
10327              // all requirements to run parts of pdf.js in a web worker.
10328              // Right now, the requirement is, that an Uint8Array is still an
10329              // Uint8Array as it arrives on the worker. (Chrome added this with v.15.)
10330              if (!isWorkerDisabled && !getDefaultSetting('disableWorker') && typeof Worker !== 'undefined') {
10331                var workerSrc = getWorkerSrc();
10332
10333                try {
10334                  // Wraps workerSrc path into blob URL, if the former does not belong
10335                  // to the same origin.
10336                  if (!isSameOrigin(window.location.href, workerSrc)) {
10337                    workerSrc = createCDNWrapper(new URL(workerSrc, window.location).href);
10338                  }
10339                  // Some versions of FF can't create a worker on localhost, see:
10340                  // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
10341                  var worker = new Worker(workerSrc);
10342                  var messageHandler = new MessageHandler('main', 'worker', worker);
10343                  var terminateEarly = function () {
10344                    worker.removeEventListener('error', onWorkerError);
10345                    messageHandler.destroy();
10346                    worker.terminate();
10347                    if (this.destroyed) {
10348                      this._readyCapability.reject(new Error('Worker was destroyed'));
10349                    } else {
10350                      // Fall back to fake worker if the termination is caused by an
10351                      // error (e.g. NetworkError / SecurityError).
10352                      this._setupFakeWorker();
10353                    }
10354                  }.bind(this);
10355
10356                  var onWorkerError = function (event) {
10357                    if (!this._webWorker) {
10358                      // Worker failed to initialize due to an error. Clean up and fall
10359                      // back to the fake worker.
10360                      terminateEarly();
10361                    }
10362                  }.bind(this);
10363                  worker.addEventListener('error', onWorkerError);
10364
10365                  messageHandler.on(
10366                    'test',
10367                    function PDFWorker_test(data) {
10368                      worker.removeEventListener('error', onWorkerError);
10369                      if (this.destroyed) {
10370                        terminateEarly();
10371                        return; // worker was destroyed
10372                      }
10373                      var supportTypedArray = data && data.supportTypedArray;
10374                      if (supportTypedArray) {
10375                        this._messageHandler = messageHandler;
10376                        this._port = worker;
10377                        this._webWorker = worker;
10378                        if (!data.supportTransfers) {
10379                          isPostMessageTransfersDisabled = true;
10380                        }
10381                        this._readyCapability.resolve();
10382                        // Send global setting, e.g. verbosity level.
10383                        messageHandler.send('configure', {
10384                          verbosity: getVerbosityLevel(),
10385                        });
10386                      } else {
10387                        this._setupFakeWorker();
10388                        messageHandler.destroy();
10389                        worker.terminate();
10390                      }
10391                    }.bind(this)
10392                  );
10393
10394                  messageHandler.on('console_log', function (data) {
10395                    console.log.apply(console, data);
10396                  });
10397                  messageHandler.on('console_error', function (data) {
10398                    console.error.apply(console, data);
10399                  });
10400
10401                  messageHandler.on(
10402                    'ready',
10403                    function (data) {
10404                      worker.removeEventListener('error', onWorkerError);
10405                      if (this.destroyed) {
10406                        terminateEarly();
10407                        return; // worker was destroyed
10408                      }
10409                      try {
10410                        sendTest();
10411                      } catch (e) {
10412                        // We need fallback to a faked worker.
10413                        this._setupFakeWorker();
10414                      }
10415                    }.bind(this)
10416                  );
10417
10418                  var sendTest = function () {
10419                    var postMessageTransfers =
10420                      getDefaultSetting('postMessageTransfers') && !isPostMessageTransfersDisabled;
10421                    var testObj = new Uint8Array([postMessageTransfers ? 255 : 0]);
10422                    // Some versions of Opera throw a DATA_CLONE_ERR on serializing the
10423                    // typed array. Also, checking if we can use transfers.
10424                    try {
10425                      messageHandler.send('test', testObj, [testObj.buffer]);
10426                    } catch (ex) {
10427                      info('Cannot use postMessage transfers');
10428                      testObj[0] = 0;
10429                      messageHandler.send('test', testObj);
10430                    }
10431                  };
10432
10433                  // It might take time for worker to initialize (especially when AMD
10434                  // loader is used). We will try to send test immediately, and then
10435                  // when 'ready' message will arrive. The worker shall process only
10436                  // first received 'test'.
10437                  sendTest();
10438                  return;
10439                } catch (e) {
10440                  info('The worker has been disabled.');
10441                }
10442              }
10443              // Either workers are disabled, not supported or have thrown an exception.
10444              // Thus, we fallback to a faked worker.
10445              this._setupFakeWorker();
10446            },
10447
10448            _setupFakeWorker: function PDFWorker_setupFakeWorker() {
10449              if (!isWorkerDisabled && !getDefaultSetting('disableWorker')) {
10450                warn('Setting up fake worker.');
10451                isWorkerDisabled = true;
10452              }
10453
10454              setupFakeWorkerGlobal().then(
10455                function (WorkerMessageHandler) {
10456                  if (this.destroyed) {
10457                    this._readyCapability.reject(new Error('Worker was destroyed'));
10458                    return;
10459                  }
10460
10461                  // We cannot turn on proper fake port simulation (this includes
10462                  // structured cloning) when typed arrays are not supported. Relying
10463                  // on a chance that messages will be sent in proper order.
10464                  var isTypedArraysPresent = Uint8Array !== Float32Array;
10465                  var port = new FakeWorkerPort(isTypedArraysPresent);
10466                  this._port = port;
10467
10468                  // All fake workers use the same port, making id unique.
10469                  var id = 'fake' + nextFakeWorkerId++;
10470
10471                  // If the main thread is our worker, setup the handling for the
10472                  // messages -- the main thread sends to it self.
10473                  var workerHandler = new MessageHandler(id + '_worker', id, port);
10474                  WorkerMessageHandler.setup(workerHandler, port);
10475
10476                  var messageHandler = new MessageHandler(id, id + '_worker', port);
10477                  this._messageHandler = messageHandler;
10478                  this._readyCapability.resolve();
10479                }.bind(this)
10480              );
10481            },
10482
10483            /**
10484             * Destroys the worker instance.
10485             */
10486            destroy: function PDFWorker_destroy() {
10487              this.destroyed = true;
10488              if (this._webWorker) {
10489                // We need to terminate only web worker created resource.
10490                this._webWorker.terminate();
10491                this._webWorker = null;
10492              }
10493              this._port = null;
10494              if (this._messageHandler) {
10495                this._messageHandler.destroy();
10496                this._messageHandler = null;
10497              }
10498            },
10499          };
10500
10501          return PDFWorker;
10502        })();
10503
10504        /**
10505         * For internal use only.
10506         * @ignore
10507         */
10508        var WorkerTransport = (function WorkerTransportClosure() {
10509          function WorkerTransport(messageHandler, loadingTask, pdfDataRangeTransport) {
10510            this.messageHandler = messageHandler;
10511            this.loadingTask = loadingTask;
10512            this.pdfDataRangeTransport = pdfDataRangeTransport;
10513            this.commonObjs = new PDFObjects();
10514            this.fontLoader = new FontLoader(loadingTask.docId);
10515
10516            this.destroyed = false;
10517            this.destroyCapability = null;
10518
10519            this.pageCache = [];
10520            this.pagePromises = [];
10521            this.downloadInfoCapability = createPromiseCapability();
10522
10523            this.setupMessageHandler();
10524          }
10525
10526          WorkerTransport.prototype = {
10527            destroy: function WorkerTransport_destroy() {
10528              if (this.destroyCapability) {
10529                return this.destroyCapability.promise;
10530              }
10531
10532              this.destroyed = true;
10533              this.destroyCapability = createPromiseCapability();
10534
10535              var waitOn = [];
10536              // We need to wait for all renderings to be completed, e.g.
10537              // timeout/rAF can take a long time.
10538              this.pageCache.forEach(function (page) {
10539                if (page) {
10540                  waitOn.push(page._destroy());
10541                }
10542              });
10543              this.pageCache = [];
10544              this.pagePromises = [];
10545              var self = this;
10546              // We also need to wait for the worker to finish its long running tasks.
10547              var terminated = this.messageHandler.sendWithPromise('Terminate', null);
10548              waitOn.push(terminated);
10549              Promise.all(waitOn).then(function () {
10550                self.fontLoader.clear();
10551                if (self.pdfDataRangeTransport) {
10552                  self.pdfDataRangeTransport.abort();
10553                  self.pdfDataRangeTransport = null;
10554                }
10555                if (self.messageHandler) {
10556                  self.messageHandler.destroy();
10557                  self.messageHandler = null;
10558                }
10559                self.destroyCapability.resolve();
10560              }, this.destroyCapability.reject);
10561              return this.destroyCapability.promise;
10562            },
10563
10564            setupMessageHandler: function WorkerTransport_setupMessageHandler() {
10565              var messageHandler = this.messageHandler;
10566
10567              function updatePassword(password) {
10568                messageHandler.send('UpdatePassword', password);
10569              }
10570
10571              var pdfDataRangeTransport = this.pdfDataRangeTransport;
10572              if (pdfDataRangeTransport) {
10573                pdfDataRangeTransport.addRangeListener(function (begin, chunk) {
10574                  messageHandler.send('OnDataRange', {
10575                    begin: begin,
10576                    chunk: chunk,
10577                  });
10578                });
10579
10580                pdfDataRangeTransport.addProgressListener(function (loaded) {
10581                  messageHandler.send('OnDataProgress', {
10582                    loaded: loaded,
10583                  });
10584                });
10585
10586                pdfDataRangeTransport.addProgressiveReadListener(function (chunk) {
10587                  messageHandler.send('OnDataRange', {
10588                    chunk: chunk,
10589                  });
10590                });
10591
10592                messageHandler.on(
10593                  'RequestDataRange',
10594                  function transportDataRange(data) {
10595                    pdfDataRangeTransport.requestDataRange(data.begin, data.end);
10596                  },
10597                  this
10598                );
10599              }
10600
10601              messageHandler.on(
10602                'GetDoc',
10603                function transportDoc(data) {
10604                  var pdfInfo = data.pdfInfo;
10605                  this.numPages = data.pdfInfo.numPages;
10606                  var loadingTask = this.loadingTask;
10607                  var pdfDocument = new PDFDocumentProxy(pdfInfo, this, loadingTask);
10608                  this.pdfDocument = pdfDocument;
10609                  loadingTask._capability.resolve(pdfDocument);
10610                },
10611                this
10612              );
10613
10614              messageHandler.on(
10615                'NeedPassword',
10616                function transportNeedPassword(exception) {
10617                  var loadingTask = this.loadingTask;
10618                  if (loadingTask.onPassword) {
10619                    return loadingTask.onPassword(updatePassword, PasswordResponses.NEED_PASSWORD);
10620                  }
10621                  loadingTask._capability.reject(new PasswordException(exception.message, exception.code));
10622                },
10623                this
10624              );
10625
10626              messageHandler.on(
10627                'IncorrectPassword',
10628                function transportIncorrectPassword(exception) {
10629                  var loadingTask = this.loadingTask;
10630                  if (loadingTask.onPassword) {
10631                    return loadingTask.onPassword(updatePassword, PasswordResponses.INCORRECT_PASSWORD);
10632                  }
10633                  loadingTask._capability.reject(new PasswordException(exception.message, exception.code));
10634                },
10635                this
10636              );
10637
10638              messageHandler.on(
10639                'InvalidPDF',
10640                function transportInvalidPDF(exception) {
10641                  this.loadingTask._capability.reject(new InvalidPDFException(exception.message));
10642                },
10643                this
10644              );
10645
10646              messageHandler.on(
10647                'MissingPDF',
10648                function transportMissingPDF(exception) {
10649                  this.loadingTask._capability.reject(new MissingPDFException(exception.message));
10650                },
10651                this
10652              );
10653
10654              messageHandler.on(
10655                'UnexpectedResponse',
10656                function transportUnexpectedResponse(exception) {
10657                  this.loadingTask._capability.reject(
10658                    new UnexpectedResponseException(exception.message, exception.status)
10659                  );
10660                },
10661                this
10662              );
10663
10664              messageHandler.on(
10665                'UnknownError',
10666                function transportUnknownError(exception) {
10667                  this.loadingTask._capability.reject(new UnknownErrorException(exception.message, exception.details));
10668                },
10669                this
10670              );
10671
10672              messageHandler.on(
10673                'DataLoaded',
10674                function transportPage(data) {
10675                  this.downloadInfoCapability.resolve(data);
10676                },
10677                this
10678              );
10679
10680              messageHandler.on(
10681                'PDFManagerReady',
10682                function transportPage(data) {
10683                  if (this.pdfDataRangeTransport) {
10684                    this.pdfDataRangeTransport.transportReady();
10685                  }
10686                },
10687                this
10688              );
10689
10690              messageHandler.on(
10691                'StartRenderPage',
10692                function transportRender(data) {
10693                  if (this.destroyed) {
10694                    return;
10694 // Ignore any pending requests if the worker was terminated.
10695                  }
10696                  var page = this.pageCache[data.pageIndex];
10697
10698                  page.stats.timeEnd('Page Request');
10699                  page._startRenderPage(data.transparency, data.intent);
10700                },
10701                this
10702              );
10703
10704              messageHandler.on(
10705                'RenderPageChunk',
10706                function transportRender(data) {
10707                  if (this.destroyed) {
10708                    return; // Ignore any pending requests if the worker was terminated.
10709                  }
10710                  var page = this.pageCache[data.pageIndex];
10711
10712                  page._renderPageChunk(data.operatorList, data.intent);
10713                },
10714                this
10715              );
10716
10717              messageHandler.on(
10718                'commonobj',
10719                function transportObj(data) {
10720                  if (this.destroyed) {
10721                    return; // Ignore any pending requests if the worker was terminated.
10722                  }
10723
10724                  var id = data[0];
10725                  var type = data[1];
10726                  if (this.commonObjs.hasData(id)) {
10727                    return;
10728                  }
10729
10730                  switch (type) {
10731                    case 'Font':
10732                      var exportedData = data[2];
10733
10734                      if ('error' in exportedData) {
10735                        var exportedError = exportedData.error;
10736                        warn('Error during font loading: ' + exportedError);
10737                        this.commonObjs.resolve(id, exportedError);
10738                        break;
10739                      }
10740                      var fontRegistry = null;
10741                      if (
10742                        getDefaultSetting('pdfBug') &&
10743                        globalScope.FontInspector &&
10744                        globalScope['FontInspector'].enabled
10745                      ) {
10746                        fontRegistry = {
10747                          registerFont: function (font, url) {
10748                            globalScope['FontInspector'].fontAdded(font, url);
10749                          },
10750                        };
10751                      }
10752                      var font = new FontFaceObject(exportedData, {
10753                        isEvalSuported: getDefaultSetting('isEvalSupported'),
10754                        disableFontFace: getDefaultSetting('disableFontFace'),
10755                        fontRegistry: fontRegistry,
10756                      });
10757
10758                      this.fontLoader.bind(
10759                        [font],
10760                        function fontReady(fontObjs) {
10761                          this.commonObjs.resolve(id, font);
10762                        }.bind(this)
10763                      );
10764                      break;
10765                    case 'FontPath':
10766                      this.commonObjs.resolve(id, data[2]);
10767                      break;
10768                    default:
10769                      error('Got unknown common object type ' + type);
10770                  }
10771                },
10772                this
10773              );
10774
10775              messageHandler.on(
10776                'obj',
10777                function transportObj(data) {
10778                  if (this.destroyed) {
10779                    return;
vendor: 1,468 bytes, lines 10779-10817
10779 // Ignore any pending requests if the worker was terminated.
10780                  }
10781
10782                  var id = data[0];
10783                  var pageIndex = data[1];
10784                  var type = data[2];
10785                  var pageProxy = this.pageCache[pageIndex];
10786                  var imageData;
10787                  if (pageProxy.objs.hasData(id)) {
10788                    return;
10789                  }
10790
10791                  switch (type) {
10792                    case 'JpegStream':
10793                      imageData = data[3];
10794                      loadJpegStream(id, imageData, pageProxy.objs);
10795                      break;
10796                    case 'Image':
10797                      imageData = data[3];
10798                      pageProxy.objs.resolve(id, imageData);
10799
10800                      // heuristics that will allow not to store large data
10801                      var MAX_IMAGE_SIZE_TO_STORE = 8000000;
10802                      if (imageData && 'data' in imageData && imageData.data.length > MAX_IMAGE_SIZE_TO_STORE) {
10803                        pageProxy.cleanupAfterRender = true;
10804                      }
10805                      break;
10806                    default:
10807                      error('Got unknown object type ' + type);
10808                  }
10809                },
10810                this
10811              );
10812
10813              messageHandler.on(
10814                'DocProgress',
10815                function transportDocProgress(data) {
10816                  if (this.destroyed) {
10817                    return;
10817 // Ignore any pending requests if the worker was terminated.
10818                  }
10819
10820                  var loadingTask = this.loadingTask;
10821                  if (loadingTask.onProgress) {
10822                    loadingTask.onProgress({
10823                      loaded: data.loaded,
10824                      total: data.total,
10825                    });
10826                  }
10827                },
10828                this
10829              );
10830
10831              messageHandler.on(
10832                'PageError',
10833                function transportError(data) {
10834                  if (this.destroyed) {
10835                    return; // Ignore any pending requests if the worker was terminated.
10836                  }
10837
10838                  var page = this.pageCache[data.pageNum - 1];
10839                  var intentState = page.intentStates[data.intent];
10840
10841                  if (intentState.displayReadyCapability) {
10842                    intentState.displayReadyCapability.reject(data.error);
10843                  } else {
10844                    error(data.error);
10845                  }
10846
10847                  if (intentState.operatorList) {
10848                    // Mark operator list as complete.
10849                    intentState.operatorList.lastChunk = true;
10850                    for (var i = 0; i < intentState.renderTasks.length; i++) {
10851                      intentState.renderTasks[i].operatorListChanged();
10852                    }
10853                  }
10854                },
10855                this
10856              );
10857
10858              messageHandler.on(
10859                'UnsupportedFeature',
10860                function transportUnsupportedFeature(data) {
10861                  if (this.destroyed) {
10862                    return;
10862 // Ignore any pending requests if the worker was terminated.
10863                  }
10864                  var featureId = data.featureId;
10865                  var loadingTask = this.loadingTask;
10866                  if (loadingTask.onUnsupportedFeature) {
10867                    loadingTask.onUnsupportedFeature(featureId);
10868                  }
10869                  _UnsupportedManager.notify(featureId);
10870                },
10871                this
10872              );
10873
10874              messageHandler.on(
10875                'JpegDecode',
10876                function (data) {
10877                  if (this.destroyed) {
10878                    return Promise.reject(new Error('Worker was destroyed'));
10879                  }
10880
10881                  var imageUrl = data[0];
10882                  var components = data[1];
10883                  if (components !== 3 && components !== 1) {
10884                    return Promise.reject(new Error('Only 3 components or 1 component can be returned'));
10885                  }
10886
10887                  return new Promise(function (resolve, reject) {
10888                    var img = new Image();
10889                    img.onload = function () {
10890                      var width = img.width;
10891                      var height = img.height;
10892                      var size = width * height;
10893                      var rgbaLength = size * 4;
10894                      var buf = new Uint8Array(size * components);
10895                      var tmpCanvas = createScratchCanvas(width, height);
10896                      var tmpCtx = tmpCanvas.getContext('2d');
10897                      tmpCtx.drawImage(img, 0, 0);
10898                      var data = tmpCtx.getImageData(0, 0, width, height).data;
10899                      var i, j;
10900
10901                      if (components === 3) {
10902                        for (i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
10903                          buf[j] = data[i];
10904                          buf[j + 1] = data[i + 1];
10905                          buf[j + 2] = data[i + 2];
10906                        }
10907                      } else if (components === 1) {
10908                        for (i = 0, j = 0; i < rgbaLength; i += 4, j++) {
10909                          buf[j] = data[i];
10910                        }
10911                      }
10912                      resolve({ data: buf, width: width, height: height });
10913                    };
10914                    img.onerror = function () {
10915                      reject(new Error('JpegDecode failed to load image'));
10916                    };
10917                    img.src = imageUrl;
10918                  });
10919                },
10920                this
10921              );
10922            },
10923
10924            getData: function WorkerTransport_getData() {
10925              return this.messageHandler.sendWithPromise('GetData', null);
10926            },
10927
10928            getPage: function WorkerTransport_getPage(pageNumber, capability) {
10929              if (!isInt(pageNumber) || pageNumber <= 0 || pageNumber > this.numPages) {
10930                return Promise.reject(new Error('Invalid page request'));
10931              }
10932
10933              var pageIndex = pageNumber - 1;
10934              if (pageIndex in this.pagePromises) {
10935                return this.pagePromises[pageIndex];
10936              }
10937              var promise = this.messageHandler
10938                .sendWithPromise('GetPage', {
10939                  pageIndex: pageIndex,
10940                })
10941                .then(
10942                  function (pageInfo) {
10943                    if (this.destroyed) {
10944                      throw new Error('Transport destroyed');
10945                    }
10946                    var page = new PDFPageProxy(pageIndex, pageInfo, this);
10947                    this.pageCache[pageIndex] = page;
10948                    return page;
10949                  }.bind(this)
10950                );
10951              this.pagePromises[pageIndex] = promise;
10952              return promise;
10953            },
10954
10955            getPageIndex: function WorkerTransport_getPageIndexByRef(ref) {
10956              return this.messageHandler
10957                .sendWithPromise('GetPageIndex', {
10958                  ref: ref,
10959                })
10960                .catch(function (reason) {
10961                  return Promise.reject(new Error(reason));
10962                });
10963            },
10964
10965            getAnnotations: function WorkerTransport_getAnnotations(pageIndex, intent) {
10966              return this.messageHandler.sendWithPromise('GetAnnotations', {
10967                pageIndex: pageIndex,
10968                intent: intent,
10969              });
10970            },
10971
10972            getDestinations: function WorkerTransport_getDestinations() {
10973              return this.messageHandler.sendWithPromise('GetDestinations', null);
10974            },
10975
10976            getDestination: function WorkerTransport_getDestination(id) {
10977              return this.messageHandler.sendWithPromise('GetDestination', {
10978                id: id,
10979              });
10980            },
10981
10982            getPageLabels: function WorkerTransport_getPageLabels() {
10983              return this.messageHandler.sendWithPromise('GetPageLabels', null);
10984            },
10985
10986            getAttachments: function WorkerTransport_getAttachments() {
10987              return this.messageHandler.sendWithPromise('GetAttachments', null);
10988            },
10989
10990            getJavaScript: function WorkerTransport_getJavaScript() {
10991              return this.messageHandler.sendWithPromise('GetJavaScript', null);
10992            },
10993
10994            getOutline: function WorkerTransport_getOutline() {
10995              return this.messageHandler.sendWithPromise('GetOutline', null);
10996            },
10997
10998            getMetadata: function WorkerTransport_getMetadata() {
10999              return this.messageHandler.sendWithPromise('GetMetadata', null).then(function transportMetadata(results) {
11000                return {
11001                  info: results[0],
11002                  metadata: results[1] ? new Metadata(results[1]) : null,
11003                };
11004              });
11005            },
11006
11007            getStats: function WorkerTransport_getStats() {
11008              return this.messageHandler.sendWithPromise('GetStats', null);
11009            },
11010
11011            startCleanup: function WorkerTransport_startCleanup() {
11012              this.messageHandler.sendWithPromise('Cleanup', null).then(
11013                function endCleanup() {
11014                  for (var i = 0, ii = this.pageCache.length; i < ii; i++) {
11015                    var page = this.pageCache[i];
11016                    if (page) {
11017                      page.cleanup();
11018                    }
11019                  }
11020                  this.commonObjs.clear();
11021                  this.fontLoader.clear();
11022                }.bind(this)
11023              );
11024            },
11025          };
11026          return WorkerTransport;
11027        })();
11028
11029        /**
11030         * A PDF document and page is built of many objects. E.g. there are objects
11031         * for fonts, images, rendering code and such. These objects might get processed
11032         * inside of a worker. The `PDFObjects` implements some basic functions to
11033         * manage these objects.
11034         * @ignore
11035         */
11036        var PDFObjects = (function PDFObjectsClosure() {
11037          function PDFObjects() {
11038            this.objs = Object.create(null);
11039          }
11040
11041          PDFObjects.prototype = {
11042            /**
11043             * Internal function.
11044             * Ensures there is an object defined for `objId`.
11045             */
11046            ensureObj: function PDFObjects_ensureObj(objId) {
11047              if (this.objs[objId]) {
11048                return this.objs[objId];
11049              }
11050
11051              var obj = {
11052                capability: createPromiseCapability(),
11053                data: null,
11054                resolved: false,
11055              };
11056              this.objs[objId] = obj;
11057
11058              return obj;
11059            },
11060
11061            /**
11062             * If called *without* callback, this returns the data of `objId` but the
11063             * object needs to be resolved. If it isn't, this function throws.
11064             *
11065             * If called *with* a callback, the callback is called with the data of the
11066             * object once the object is resolved. That means, if you call this
11067             * function and the object is already resolved, the callback gets called
11068             * right away.
11069             */
11070            get: function PDFObjects_get(objId, callback) {
11071              // If there is a callback, then the get can be async and the object is
11072              // not required to be resolved right now
11073              if (callback) {
11074                this.ensureObj(objId).capability.promise.then(callback);
11075                return null;
11076              }
11077
11078              // If there isn't a callback, the user expects to get the resolved data
11079              // directly.
11080              var obj = this.objs[objId];
11081
11082              // If there isn't an object yet or the object isn't resolved, then the
11083              // data isn't ready yet!
11084              if (!obj || !obj.resolved) {
11085                error("Requesting object that isn't resolved yet " + objId);
11086              }
11087
11088              return obj.data;
11089            },
11090
11091            /**
11092             * Resolves the object `objId` with optional `data`.
11093             */
11094            resolve: function PDFObjects_resolve(objId, data) {
11095              var obj = this.ensureObj(objId);
11096
11097              obj.resolved = true;
11098              obj.data = data;
11099              obj.capability.resolve(data);
11100            },
11101
vendor: 4,116 bytes, lines 11102-11214
11102            isResolved: function PDFObjects_isResolved(objId) {
11103              var objs = this.objs;
11104
11105              if (!objs[objId]) {
11106                return false;
11107              } else {
11108                return objs[objId].resolved;
11109              }
11110            },
11111
11112            hasData: function PDFObjects_hasData(objId) {
11113              return this.isResolved(objId);
11114            },
11115
11116            /**
11117             * Returns the data of `objId` if object exists, null otherwise.
11118             */
11119            getData: function PDFObjects_getData(objId) {
11120              var objs = this.objs;
11121              if (!objs[objId] || !objs[objId].resolved) {
11122                return null;
11123              } else {
11124                return objs[objId].data;
11125              }
11126            },
11127
11128            clear: function PDFObjects_clear() {
11129              this.objs = Object.create(null);
11130            },
11131          };
11132          return PDFObjects;
11133        })();
11134
11135        /**
11136         * Allows controlling of the rendering tasks.
11137         * @class
11138         * @alias RenderTask
11139         */
11140        var RenderTask = (function RenderTaskClosure() {
11141          function RenderTask(internalRenderTask) {
11142            this._internalRenderTask = internalRenderTask;
11143
11144            /**
11145             * Callback for incremental rendering -- a function that will be called
11146             * each time the rendering is paused.  To continue rendering call the
11147             * function that is the first argument to the callback.
11148             * @type {function}
11149             */
11150            this.onContinue = null;
11151          }
11152
11153          RenderTask.prototype = /** @lends RenderTask.prototype */ {
11154            /**
11155             * Promise for rendering task completion.
11156             * @return {Promise}
11157             */
11158            get promise() {
11159              return this._internalRenderTask.capability.promise;
11160            },
11161
11162            /**
11163             * Cancels the rendering task. If the task is currently rendering it will
11164             * not be cancelled until graphics pauses with a timeout. The promise that
11165             * this object extends will resolved when cancelled.
11166             */
11167            cancel: function RenderTask_cancel() {
11168              this._internalRenderTask.cancel();
11169            },
11170
11171            /**
11172             * Registers callbacks to indicate the rendering task completion.
11173             *
11174             * @param {function} onFulfilled The callback for the rendering completion.
11175             * @param {function} onRejected The callback for the rendering failure.
11176             * @return {Promise} A promise that is resolved after the onFulfilled or
11177             *                   onRejected callback.
11178             */
11179            then: function RenderTask_then(onFulfilled, onRejected) {
11180              return this.promise.then.apply(this.promise, arguments);
11181            },
11182          };
11183
11184          return RenderTask;
11185        })();
11186
11187        /**
11188         * For internal use only.
11189         * @ignore
11190         */
11191        var InternalRenderTask = (function InternalRenderTaskClosure() {
11192          function InternalRenderTask(callback, params, objs, commonObjs, operatorList, pageNumber) {
11193            this.callback = callback;
11194            this.params = params;
11195            this.objs = objs;
11196            this.commonObjs = commonObjs;
11197            this.operatorListIdx = null;
11198            this.operatorList = operatorList;
11199            this.pageNumber = pageNumber;
11200            this.running = false;
11201            this.graphicsReadyCallback = null;
11202            this.graphicsReady = false;
11203            this.useRequestAnimationFrame = false;
11204            this.cancelled = false;
11205            this.capability = createPromiseCapability();
11206            this.task = new RenderTask(this);
11207            // caching this-bound methods
11208            this._continueBound = this._continue.bind(this);
11209            this._scheduleNextBound = this._scheduleNext.bind(this);
11210            this._nextBound = this._next.bind(this);
11211          }
11212
11213          InternalRenderTask.prototype = {
11214            initializeGraphics: function InternalRenderTask_initializeGraphics(trans
11214parency) {
11215              if (this.cancelled) {
11216                return;
11217              }
11218              if (getDefaultSetting('pdfBug') && globalScope.StepperManager && globalScope.StepperManager.enabled) {
11219                this.stepper = globalScope.StepperManager.create(this.pageNumber - 1);
11220                this.stepper.init(this.operatorList);
11221                this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
11222              }
11223
11224              var params = this.params;
11225              this.gfx = new CanvasGraphics(params.canvasContext, this.commonObjs, this.objs, params.imageLayer);
11226
11227              this.gfx.beginDrawing(params.transform, params.viewport, transparency);
11228              this.operatorListIdx = 0;
11229              this.graphicsReady = true;
11230              if (this.graphicsReadyCallback) {
11231                this.graphicsReadyCallback();
11232              }
11233            },
11234
11235            cancel: function InternalRenderTask_cancel() {
11236              this.running = false;
11237              this.cancelled = true;
11238              this.callback('cancelled');
11239            },
11240
11241            operatorListChanged: function InternalRenderTask_operatorListChanged() {
11242              if (!this.graphicsReady) {
11243                if (!this.graphicsReadyCallback) {
11244                  this.graphicsReadyCallback = this._continueBound;
11245                }
11246                return;
11247              }
11248
11249              if (this.stepper) {
11250                this.stepper.updateOperatorList(this.operatorList);
11251              }
11252
11253              if (this.running) {
11254                return;
11255              }
11256              this._continue();
11257            },
11258
11259            _continue: function InternalRenderTask__continue() {
11260              this.running = true;
11261              if (this.cancelled) {
11262                return;
11263              }
11264              if (this.task.onContinue) {
11265                this.task.onContinue.call(this.task, this._scheduleNextBound);
11266              } else {
11267                this._scheduleNext();
11268              }
11269            },
11270
11271            _scheduleNext: function InternalRenderTask__scheduleNext() {
11272              if (this.useRequestAnimationFrame && typeof window !== 'undefined') {
11273                window.requestAnimationFrame(this._nextBound);
11274              } else {
11275                Promise.resolve(undefined).then(this._nextBound);
11276              }
11277            },
11278
11279            _next: function InternalRenderTask__next() {
11280              if (this.cancelled) {
11281                return;
11282              }
11283              this.operatorListIdx = this.gfx.executeOperatorList(
11284                this.operatorList,
11285                this.operatorListIdx,
11286                this._continueBound,
11287                this.stepper
11288              );
11289              if (this.operatorListIdx === this.operatorList.argsArray.length) {
11290                this.running = false;
11291                if (this.operatorList.lastChunk) {
11292                  this.gfx.endDrawing();
11293                  this.callback();
11294                }
11295              }
11296            },
11297          };
11298
11299          return InternalRenderTask;
11300        })();
11301
11302        /**
11303         * (Deprecated) Global observer of unsupported feature usages. Use
11304         * onUnsupportedFeature callback of the {PDFDocumentLoadingTask} instance.
11305         */
11306        var _UnsupportedManager = (function UnsupportedManagerClosure() {
11307          var listeners = [];
11308          return {
11309            listen: function (cb) {
11310              deprecated(
11311                'Global UnsupportedManager.listen is used: ' +
11312                  ' use PDFDocumentLoadingTask.onUnsupportedFeature instead'
11313              );
11314              listeners.push(cb);
11315            },
11316            notify: function (featureId) {
11317              for (var i = 0, ii = listeners.length; i < ii; i++) {
11318                listeners[i](featureId);
11319              }
11320            },
11321          };
11322        })();
11323
11324        if (typeof pdfjsVersion !== 'undefined') {
11325          exports.version = pdfjsVersion;
11326        }
11327        if (typeof pdfjsBuild !== 'undefined') {
11328          exports.build = pdfjsBuild;
11329        }
11330
11331        exports.getDocument = getDocument;
11332        exports.PDFDataRangeTransport = PDFDataRangeTransport;
11333        exports.PDFWorker = PDFWorker;
11334        exports.PDFDocumentProxy = PDFDocumentProxy;
11335        exports.PDFPageProxy = PDFPageProxy;
11336        exports._UnsupportedManager = _UnsupportedManager;
11337      }
11338    );
11339
11340    (function (root, factory) {
11341      {
11342        factory(
11343          (root.pdfjsDisplayGlobal = {}),
11344          root.pdfjsSharedUtil,
11345          root.pdfjsDisplayDOMUtils,
11346          root.pdfjsDisplayAPI,
11347          root.pdfjsDisplayAnnotationLayer,
11348          root.pdfjsDisplayTextLayer,
11349          root.pdfjsDisplayMetadata,
11350          root.pdfjsDisplaySVG
11351        );
11352      }
11353    })(
11354      this,
11355      function (
11356        exports,
11357        sharedUtil,
11358        displayDOMUtils,
11359        displayAPI,
11360        displayAnnotationLayer,
11361        displayTextLayer,
11362        displayMetadata,
11363        displaySVG
11364      ) {
11365        var globalScope = sharedUtil.globalScope;
11366        var deprecated = sharedUtil.deprecated;
11367        var warn = sharedUtil.warn;
11368        var LinkTarget = displayDOMUtils.LinkTarget;
11369
11370        var isWorker = typeof window === 'undefined';
11371
11372        // The global PDFJS object is now deprecated and will not be supported in
11373        // the future. The members below are maintained for backward  compatibility
11374        // and shall not be extended or modified. If the global.js is included as
11375        // a module, we will create a global PDFJS object instance or use existing.
11376        if (!globalScope.PDFJS) {
11377          globalScope.PDFJS = {};
11378        }
11379        var PDFJS = globalScope.PDFJS;
11380
11381        if (typeof pdfjsVersion !== 'undefined') {
11382          PDFJS.version = pdfjsVersion;
11383        }
11384        if (typeof pdfjsBuild !== 'undefined') {
11385          PDFJS.build = pdfjsBuild;
11386        }
11387
11388        PDFJS.pdfBug = false;
11389
11390        if (PDFJS.verbosity !== undefined) {
11391          sharedUtil.setVerbosityLevel(PDFJS.verbosity);
11392        }
11393        delete PDFJS.verbosity;
11394        Object.defineProperty(PDFJS, 'verbosity', {
11395          get: function () {
11396            return sharedUtil.getVerbosityLevel();
11397          },
11398          set: function (level) {
11399            sharedUtil.setVerbosityLevel(level);
11400          },
11401          enumerable: true,
11402          configurable: true,
11403        });
11404
11405        PDFJS.VERBOSITY_LEVELS = sharedUtil.VERBOSITY_LEVELS;
11406        PDFJS.OPS = sharedUtil.OPS;
11407        PDFJS.UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES;
11408        PDFJS.isValidUrl = sharedUtil.isValidUrl;
11409        PDFJS.shadow = sharedUtil.shadow;
11410        PDFJS.createBlob = sharedUtil.createBlob;
11411        PDFJS.createObjectURL = function PDFJS_createObjectURL(data, contentType) {
11412          return sharedUtil.createObjectURL(data, contentType, PDFJS.disableCreateObjectURL);
11413        };
11414        Object.defineProperty(PDFJS, 'isLittleEndian', {
11415          configurable: true,
11416          get: function PDFJS_isLittleEndian() {
11417            var value = sharedUtil.isLittleEndian();
11418            return sharedUtil.shadow(PDFJS, 'isLittleEndian', value);
11419          },
11420        });
11421        PDFJS.removeNullCharacters = sharedUtil.removeNullCharacters;
11422        PDFJS.PasswordResponses = sharedUtil.PasswordResponses;
11423        PDFJS.PasswordException = sharedUtil.PasswordException;
11424        PDFJS.UnknownErrorException = sharedUtil.UnknownErrorException;
11425        PDFJS.InvalidPDFException = sharedUtil.InvalidPDFException;
11426        PDFJS.MissingPDFException = sharedUtil.MissingPDFException;
11427        PDFJS.UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
11428        PDFJS.Util = sharedUtil.Util;
11429        PDFJS.PageViewport = sharedUtil.PageViewport;
11430        PDFJS.createPromiseCapability = sharedUtil.createPromiseCapability;
11431
11432        /**
11433         * The maximum allowed image size in total pixels e.g. width * height. Images
11434         * above this value will not be drawn. Use -1 for no limit.
11435         * @var {number}
11436         */
11437        PDFJS.maxImageSize = PDFJS.maxImageSize === undefined ? -1 : PDFJS.maxImageSize;
11438
11439        /**
11440         * The url of where the predefined Adobe CMaps are located. Include trailing
11441         * slash.
11442         * @var {string}
11443         */
11444        PDFJS.cMapUrl = PDFJS.cMapUrl === undefined ? null : PDFJS.cMapUrl;
11445
11446        /**
11447         * Specifies if CMaps are binary packed.
11448         * @var {boolean}
11449         */
11450        PDFJS.cMapPacked = PDFJS.cMapPacked === undefined ? false : PDFJS.cMapPacked;
11451
11452        /**
11453         * By default fonts are converted to OpenType fonts and loaded via font face
11454         * rules. If disabled, the font will be rendered using a built in font
11455         * renderer that constructs the glyphs with primitive path commands.
11456         * @var {boolean}
11457         */
11458        PDFJS.disableFontFace = PDFJS.disableFontFace === undefined ? false : PDFJS.disableFontFace;
11459
11460        /**
11461         * Path for image resources, mainly for annotation icons. Include trailing
11462         * slash.
11463         * @var {string}
11464         */
11465        PDFJS.imageResourcesPath = PDFJS.imageResourcesPath === undefined ? '' : PDFJS.imageResourcesPath;
11466
11467        /**
11468         * Disable the web worker and run all code on the main thread. This will
11469         * happen automatically if the browser doesn't support workers or sending
11470         * typed arrays to workers.
11471         * @var {boolean}
11472         */
11473        PDFJS.disableWorker = PDFJS.disableWorker === undefined ? false : PDFJS.disableWorker;
11474
11475        /**
11476         * Path and filename of the worker file. Required when the worker is enabled
11477         * in development mode. If unspecified in the production build, the worker
11478         * will be loaded based on the location of the pdf.js file. It is recommended
11479         * that the workerSrc is set in a custom application to prevent issues caused
11480         * by third-party frameworks and libraries.
11481         * @var {string}
11482         */
11483        PDFJS.workerSrc = PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc;
11484
11485        /**
11486         * Disable range request loading of PDF files. When enabled and if the server
11487         * supports partial content requests then the PDF will be fetched in chunks.
11488         * Enabled (false) by default.
11489         * @var {boolean}
11490         */
11491        PDFJS.disableRange = PDFJS.disableRange === undefined ? false : PDFJS.disableRange;
11492
11493        /**
11494         * Disable streaming of PDF file data. By default PDF.js attempts to load PDF
11495         * in chunks. This default behavior can be disabled.
11496         * @var {boolean}
11497         */
11498        PDFJS.disableStream = PDFJS.disableStream === undefined ? false : PDFJS.disableStream;
11499
11500        /**
11501         * Disable pre-fetching of PDF file data. When range requests are enabled
11502         * PDF.js will automatically keep fetching more data even if it isn't needed
11503         * to display the current page. This default behavior can be disabled.
11504         *
11505         * NOTE: It is also necessary to disable streaming, see above,
11506         *       in order for disabling of pre-fetching to work correctly.
11507         * @var {boolean}
11508         */
11509        PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ? false : PDFJS.disableAutoFetch;
11510
11511        /**
11512         * Enables special hooks for debugging PDF.js.
11513         * @var {boolean}
11514         */
11515        PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug;
11516
11517        /**
11518         * Enables transfer usage in postMessage for ArrayBuffers.
11519         * @var {boolean}
11520         */
11521        PDFJS.postMessageTransfers = PDFJS.postMessageTransfers === undefined ? true : PDFJS.postMessageTransfers;
11522
11523        /**
11524         * Disables URL.createObjectURL usage.
11525         * @var {boolean}
11526         */
11527        PDFJS.disableCreateObjectURL =
11528          PDFJS.disableCreateObjectURL === undefined ? false : PDFJS.disableCreateObjectURL;
11529
11530        /**
11531         * Disables WebGL usage.
11532         * @var {boolean}
11533         */
11534        PDFJS.disableWebGL = PDFJS.disableWebGL === undefined ? true : PDFJS.disableWebGL;
11535
11536        /**
11537         * Specifies the |target| attribute for external links.
11538         * The constants from PDFJS.LinkTarget should be used:
11539         *  - NONE [default]
11540         *  - SELF
11541         *  - BLANK
11542         *  - PARENT
11543         *  - TOP
11544         * @var {number}
11545         */
11546        PDFJS.externalLinkTarget = PDFJS.externalLinkTarget === undefined ? LinkTarget.NONE : PDFJS.externalLinkTarget;
11547
11548        /**
11549         * Specifies the |rel| attribute for external links. Defaults to stripping
11550         * the referrer.
11551         * @var {string}
11552         */
11553        PDFJS.externalLinkRel = PDFJS.externalLinkRel === undefined ? 'noreferrer' : PDFJS.externalLinkRel;
11554
11555        /**
11556         * Determines if we can eval strings as JS. Primarily used to improve
11557         * performance for font rendering.
11558         * @var {boolean}
11559         */
11560        PDFJS.isEvalSupported = PDFJS.isEvalSupported === undefined ? true : PDFJS.isEvalSupported;
11561
11562        var savedOpenExternalLinksInNewWindow = PDFJS.openExternalLinksInNewWindow;
11563        delete PDFJS.openExternalLinksInNewWindow;
11564        Object.defineProperty(PDFJS, 'openExternalLinksInNewWindow', {
11565          get: function () {
11566            return PDFJS.externalLinkTarget === LinkTarget.BLANK;
11567          },
11568          set: function (value) {
11569            if (value) {
11570              deprecated(
11571                'PDFJS.openExternalLinksInNewWindow, please use ' +
11572                  '"PDFJS.externalLinkTarget = PDFJS.LinkTarget.BLANK" instead.'
11573              );
11574            }
11575            if (PDFJS.externalLinkTarget !== LinkTarget.NONE) {
11576              warn('PDFJS.externalLinkTarget is already initialized');
11577              return;
11578            }
11579            PDFJS.externalLinkTarget = value ? LinkTarget.BLANK : LinkTarget.NONE;
11580          },
11581          enumerable: true,
11582          configurable: true,
11583        });
11584        if (savedOpenExternalLinksInNewWindow) {
11585          /**
11586           * (Deprecated) Opens external links in a new window if enabled.
11587           * The default behavior opens external links in the PDF.js 
11587window.
11588           *
11589           * NOTE: This property has been deprecated, please use
11590           *       `PDFJS.externalLinkTarget = PDFJS.LinkTarget.BLANK` instead.
11591           * @var {boolean}
11592           */
11593          PDFJS.openExternalLinksInNewWindow = savedOpenExternalLinksInNewWindow;
11594        }
11595
11596        PDFJS.getDocument = displayAPI.getDocument;
11597        PDFJS.PDFDataRangeTransport = displayAPI.PDFDataRangeTransport;
11598        PDFJS.PDFWorker = displayAPI.PDFWorker;
11599
11600        Object.defineProperty(PDFJS, 'hasCanvasTypedArrays', {
11601          configurable: true,
11602          get: function PDFJS_hasCanvasTypedArrays() {
11603            var value = displayDOMUtils.hasCanvasTypedArrays();
11604            return sharedUtil.shadow(PDFJS, 'hasCanvasTypedArrays', value);
11605          },
11606        });
11607        PDFJS.CustomStyle = displayDOMUtils.CustomStyle;
11608        PDFJS.LinkTarget = LinkTarget;
11609        PDFJS.addLinkAttributes = displayDOMUtils.addLinkAttributes;
11610        PDFJS.getFilenameFromUrl = displayDOMUtils.getFilenameFromUrl;
11611        PDFJS.isExternalLinkTargetSet = displayDOMUtils.isExternalLinkTargetSet;
11612
11613        PDFJS.AnnotationLayer = displayAnnotationLayer.AnnotationLayer;
11614
11615        PDFJS.renderTextLayer = displayTextLayer.renderTextLayer;
11616
11617        PDFJS.Metadata = displayMetadata.Metadata;
11618
11619        PDFJS.SVGGraphics = displaySVG.SVGGraphics;
11620
11621        PDFJS.UnsupportedManager = displayAPI._UnsupportedManager;
11622
11623        exports.globalScope = globalScope;
11624        exports.isWorker = isWorker;
11625        exports.PDFJS = globalScope.PDFJS;
11626      }
11627    );
11628  }).call(pdfjsLibs);
11629
11630  exports.PDFJS = pdfjsLibs.pdfjsDisplayGlobal.PDFJS;
11631  exports.build = pdfjsLibs.pdfjsDisplayAPI.build;
11632  exports.version = pdfjsLibs.pdfjsDisplayAPI.version;
11633  exports.getDocument = pdfjsLibs.pdfjsDisplayAPI.getDocument;
11634  exports.PDFDataRangeTransport = pdfjsLibs.pdfjsDisplayAPI.PDFDataRangeTransport;
11635  exports.PDFWorker = pdfjsLibs.pdfjsDisplayAPI.PDFWorker;
11636  exports.renderTextLayer = pdfjsLibs.pdfjsDisplayTextLayer.renderTextLayer;
11637  exports.AnnotationLayer = pdfjsLibs.pdfjsDisplayAnnotationLayer.AnnotationLayer;
11638  exports.CustomStyle = pdfjsLibs.pdfjsDisplayDOMUtils.CustomStyle;
11639  exports.PasswordResponses = pdfjsLibs.pdfjsSharedUtil.PasswordResponses;
11640  exports.InvalidPDFException = pdfjsLibs.pdfjsSharedUtil.InvalidPDFException;
11641  exports.MissingPDFException = pdfjsLibs.pdfjsSharedUtil.MissingPDFException;
11642  exports.SVGGraphics = pdfjsLibs.pdfjsDisplaySVG.SVGGraphics;
11643  exports.UnexpectedResponseException = pdfjsLibs.pdfjsSharedUtil.UnexpectedResponseException;
11644  exports.OPS = pdfjsLibs.pdfjsSharedUtil.OPS;
11645  exports.UNSUPPORTED_FEATURES = pdfjsLibs.pdfjsSharedUtil.UNSUPPORTED_FEATURES;
11646  exports.isValidUrl = pdfjsLibs.pdfjsSharedUtil.isValidUrl;
11647  exports.createObjectURL = pdfjsLibs.pdfjsSharedUtil.createObjectURL;
11648  exports.removeNullCharacters = pdfjsLibs.pdfjsSharedUtil.removeNullCharacters;
11649  exports.shadow = pdfjsLibs.pdfjsSharedUtil.shadow;
11650  exports.createBlob = pdfjsLibs.pdfjsSharedUtil.createBlob;
11651  exports.getFilenameFromUrl = pdfjsLibs.pdfjsDisplayDOMUtils.getFilenameFromUrl;
11652  exports.addLinkAttributes = pdfjsLibs.pdfjsDisplayDOMUtils.addLinkAttributes;
11653});

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