PageSourceSearch

https://lism.catholic.edu.au/theme/_blueprint/js/pdf/build/pdf.js

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

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.