PageSourceSearch

https://szs.org.pl/wp-content/plugins/wp-file-download/app/site/assets/js/pdf-embed/pdf-old.js?ver=6.3.6

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

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.