mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-03 21:28:21 -05:00 
			
		
		
		
	- Set up Elixir for asset management - CSS + JS will be handled via Elixir/Gulp in gulpfile.js - Removed outdates public/js files
		
			
				
	
	
		
			7421 lines
		
	
	
		
			232 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			7421 lines
		
	
	
		
			232 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 | 
						|
/* Copyright 2012 Mozilla Foundation
 | 
						|
 *
 | 
						|
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
 * you may not use this file except in compliance with the License.
 | 
						|
 * You may obtain a copy of the License at
 | 
						|
 *
 | 
						|
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 *
 | 
						|
 * Unless required by applicable law or agreed to in writing, software
 | 
						|
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 * See the License for the specific language governing permissions and
 | 
						|
 * limitations under the License.
 | 
						|
 */
 | 
						|
 | 
						|
// Initializing PDFJS global object (if still undefined)
 | 
						|
if (typeof PDFJS === 'undefined') {
 | 
						|
  (typeof window !== 'undefined' ? window : this).PDFJS = {};
 | 
						|
}
 | 
						|
 | 
						|
PDFJS.version = '0.8.765';
 | 
						|
PDFJS.build = '88ec2bd';
 | 
						|
 | 
						|
(function pdfjsWrapper() {
 | 
						|
  // Use strict in our context only - users might not want it
 | 
						|
  'use strict';
 | 
						|
 | 
						|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 | 
						|
/* Copyright 2012 Mozilla Foundation
 | 
						|
 *
 | 
						|
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
 * you may not use this file except in compliance with the License.
 | 
						|
 * You may obtain a copy of the License at
 | 
						|
 *
 | 
						|
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 *
 | 
						|
 * Unless required by applicable law or agreed to in writing, software
 | 
						|
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 * See the License for the specific language governing permissions and
 | 
						|
 * limitations under the License.
 | 
						|
 */
 | 
						|
/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL */
 | 
						|
 | 
						|
'use strict';
 | 
						|
 | 
						|
var globalScope = (typeof window === 'undefined') ? this : window;
 | 
						|
 | 
						|
var isWorker = (typeof window == 'undefined');
 | 
						|
 | 
						|
var ERRORS = 0, WARNINGS = 1, INFOS = 5;
 | 
						|
var verbosity = WARNINGS;
 | 
						|
 | 
						|
var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
 | 
						|
 | 
						|
var TextRenderingMode = {
 | 
						|
  FILL: 0,
 | 
						|
  STROKE: 1,
 | 
						|
  FILL_STROKE: 2,
 | 
						|
  INVISIBLE: 3,
 | 
						|
  FILL_ADD_TO_PATH: 4,
 | 
						|
  STROKE_ADD_TO_PATH: 5,
 | 
						|
  FILL_STROKE_ADD_TO_PATH: 6,
 | 
						|
  ADD_TO_PATH: 7,
 | 
						|
  FILL_STROKE_MASK: 3,
 | 
						|
  ADD_TO_PATH_FLAG: 4
 | 
						|
};
 | 
						|
 | 
						|
// The global PDFJS object exposes the API
 | 
						|
// In production, it will be declared outside a global wrapper
 | 
						|
// In development, it will be declared here
 | 
						|
if (!globalScope.PDFJS) {
 | 
						|
  globalScope.PDFJS = {};
 | 
						|
}
 | 
						|
 | 
						|
globalScope.PDFJS.pdfBug = false;
 | 
						|
 | 
						|
// All the possible operations for an operator list.
 | 
						|
var OPS = PDFJS.OPS = {
 | 
						|
  // Intentionally start from 1 so it is easy to spot bad operators that will be
 | 
						|
  // 0's.
 | 
						|
  dependency: 1,
 | 
						|
  setLineWidth: 2,
 | 
						|
  setLineCap: 3,
 | 
						|
  setLineJoin: 4,
 | 
						|
  setMiterLimit: 5,
 | 
						|
  setDash: 6,
 | 
						|
  setRenderingIntent: 7,
 | 
						|
  setFlatness: 8,
 | 
						|
  setGState: 9,
 | 
						|
  save: 10,
 | 
						|
  restore: 11,
 | 
						|
  transform: 12,
 | 
						|
  moveTo: 13,
 | 
						|
  lineTo: 14,
 | 
						|
  curveTo: 15,
 | 
						|
  curveTo2: 16,
 | 
						|
  curveTo3: 17,
 | 
						|
  closePath: 18,
 | 
						|
  rectangle: 19,
 | 
						|
  stroke: 20,
 | 
						|
  closeStroke: 21,
 | 
						|
  fill: 22,
 | 
						|
  eoFill: 23,
 | 
						|
  fillStroke: 24,
 | 
						|
  eoFillStroke: 25,
 | 
						|
  closeFillStroke: 26,
 | 
						|
  closeEOFillStroke: 27,
 | 
						|
  endPath: 28,
 | 
						|
  clip: 29,
 | 
						|
  eoClip: 30,
 | 
						|
  beginText: 31,
 | 
						|
  endText: 32,
 | 
						|
  setCharSpacing: 33,
 | 
						|
  setWordSpacing: 34,
 | 
						|
  setHScale: 35,
 | 
						|
  setLeading: 36,
 | 
						|
  setFont: 37,
 | 
						|
  setTextRenderingMode: 38,
 | 
						|
  setTextRise: 39,
 | 
						|
  moveText: 40,
 | 
						|
  setLeadingMoveText: 41,
 | 
						|
  setTextMatrix: 42,
 | 
						|
  nextLine: 43,
 | 
						|
  showText: 44,
 | 
						|
  showSpacedText: 45,
 | 
						|
  nextLineShowText: 46,
 | 
						|
  nextLineSetSpacingShowText: 47,
 | 
						|
  setCharWidth: 48,
 | 
						|
  setCharWidthAndBounds: 49,
 | 
						|
  setStrokeColorSpace: 50,
 | 
						|
  setFillColorSpace: 51,
 | 
						|
  setStrokeColor: 52,
 | 
						|
  setStrokeColorN: 53,
 | 
						|
  setFillColor: 54,
 | 
						|
  setFillColorN: 55,
 | 
						|
  setStrokeGray: 56,
 | 
						|
  setFillGray: 57,
 | 
						|
  setStrokeRGBColor: 58,
 | 
						|
  setFillRGBColor: 59,
 | 
						|
  setStrokeCMYKColor: 60,
 | 
						|
  setFillCMYKColor: 61,
 | 
						|
  shadingFill: 62,
 | 
						|
  beginInlineImage: 63,
 | 
						|
  beginImageData: 64,
 | 
						|
  endInlineImage: 65,
 | 
						|
  paintXObject: 66,
 | 
						|
  markPoint: 67,
 | 
						|
  markPointProps: 68,
 | 
						|
  beginMarkedContent: 69,
 | 
						|
  beginMarkedContentProps: 70,
 | 
						|
  endMarkedContent: 71,
 | 
						|
  beginCompat: 72,
 | 
						|
  endCompat: 73,
 | 
						|
  paintFormXObjectBegin: 74,
 | 
						|
  paintFormXObjectEnd: 75,
 | 
						|
  beginGroup: 76,
 | 
						|
  endGroup: 77,
 | 
						|
  beginAnnotations: 78,
 | 
						|
  endAnnotations: 79,
 | 
						|
  beginAnnotation: 80,
 | 
						|
  endAnnotation: 81,
 | 
						|
  paintJpegXObject: 82,
 | 
						|
  paintImageMaskXObject: 83,
 | 
						|
  paintImageMaskXObjectGroup: 84,
 | 
						|
  paintImageXObject: 85,
 | 
						|
  paintInlineImageXObject: 86,
 | 
						|
  paintInlineImageXObjectGroup: 87
 | 
						|
};
 | 
						|
 | 
						|
// Use only for debugging purposes. This should not be used in any code that is
 | 
						|
// in mozilla master.
 | 
						|
var log = (function() {
 | 
						|
  if ('console' in globalScope && 'log' in globalScope['console']) {
 | 
						|
    return globalScope['console']['log'].bind(globalScope['console']);
 | 
						|
  } else {
 | 
						|
    return function nop() {
 | 
						|
    };
 | 
						|
  }
 | 
						|
})();
 | 
						|
 | 
						|
// A notice for devs that will not trigger the fallback UI.  These are good
 | 
						|
// for things that are helpful to devs, such as warning that Workers were
 | 
						|
// disabled, which is important to devs but not end users.
 | 
						|
function info(msg) {
 | 
						|
  if (verbosity >= INFOS) {
 | 
						|
    log('Info: ' + msg);
 | 
						|
    PDFJS.LogManager.notify('info', msg);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Non-fatal warnings that should trigger the fallback UI.
 | 
						|
function warn(msg) {
 | 
						|
  if (verbosity >= WARNINGS) {
 | 
						|
    log('Warning: ' + msg);
 | 
						|
    PDFJS.LogManager.notify('warn', msg);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Fatal errors that should trigger the fallback UI and halt execution by
 | 
						|
// throwing an exception.
 | 
						|
function error(msg) {
 | 
						|
  // If multiple arguments were passed, pass them all to the log function.
 | 
						|
  if (arguments.length > 1) {
 | 
						|
    var logArguments = ['Error:'];
 | 
						|
    logArguments.push.apply(logArguments, arguments);
 | 
						|
    log.apply(null, logArguments);
 | 
						|
    // Join the arguments into a single string for the lines below.
 | 
						|
    msg = [].join.call(arguments, ' ');
 | 
						|
  } else {
 | 
						|
    log('Error: ' + msg);
 | 
						|
  }
 | 
						|
  log(backtrace());
 | 
						|
  PDFJS.LogManager.notify('error', msg);
 | 
						|
  throw new Error(msg);
 | 
						|
}
 | 
						|
 | 
						|
// Missing features that should trigger the fallback UI.
 | 
						|
function TODO(what) {
 | 
						|
  warn('TODO: ' + what);
 | 
						|
}
 | 
						|
 | 
						|
function backtrace() {
 | 
						|
  try {
 | 
						|
    throw new Error();
 | 
						|
  } catch (e) {
 | 
						|
    return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function assert(cond, msg) {
 | 
						|
  if (!cond)
 | 
						|
    error(msg);
 | 
						|
}
 | 
						|
 | 
						|
// Combines two URLs. The baseUrl shall be absolute URL. If the url is an
 | 
						|
// absolute URL, it will be returned as is.
 | 
						|
function combineUrl(baseUrl, url) {
 | 
						|
  if (!url)
 | 
						|
    return baseUrl;
 | 
						|
  if (url.indexOf(':') >= 0)
 | 
						|
    return url;
 | 
						|
  if (url.charAt(0) == '/') {
 | 
						|
    // absolute path
 | 
						|
    var i = baseUrl.indexOf('://');
 | 
						|
    i = baseUrl.indexOf('/', i + 3);
 | 
						|
    return baseUrl.substring(0, i) + url;
 | 
						|
  } else {
 | 
						|
    // relative path
 | 
						|
    var pathLength = baseUrl.length, i;
 | 
						|
    i = baseUrl.lastIndexOf('#');
 | 
						|
    pathLength = i >= 0 ? i : pathLength;
 | 
						|
    i = baseUrl.lastIndexOf('?', pathLength);
 | 
						|
    pathLength = i >= 0 ? i : pathLength;
 | 
						|
    var prefixLength = baseUrl.lastIndexOf('/', pathLength);
 | 
						|
    return baseUrl.substring(0, prefixLength + 1) + url;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Validates if URL is safe and allowed, e.g. to avoid XSS.
 | 
						|
function isValidUrl(url, allowRelative) {
 | 
						|
  if (!url) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  var colon = url.indexOf(':');
 | 
						|
  if (colon < 0) {
 | 
						|
    return allowRelative;
 | 
						|
  }
 | 
						|
  var protocol = url.substr(0, colon);
 | 
						|
  switch (protocol) {
 | 
						|
    case 'http':
 | 
						|
    case 'https':
 | 
						|
    case 'ftp':
 | 
						|
    case 'mailto':
 | 
						|
      return true;
 | 
						|
    default:
 | 
						|
      return false;
 | 
						|
  }
 | 
						|
}
 | 
						|
PDFJS.isValidUrl = isValidUrl;
 | 
						|
 | 
						|
// In a well-formed PDF, |cond| holds.  If it doesn't, subsequent
 | 
						|
// behavior is undefined.
 | 
						|
function assertWellFormed(cond, msg) {
 | 
						|
  if (!cond)
 | 
						|
    error(msg);
 | 
						|
}
 | 
						|
 | 
						|
var LogManager = PDFJS.LogManager = (function LogManagerClosure() {
 | 
						|
  var loggers = [];
 | 
						|
  return {
 | 
						|
    addLogger: function logManager_addLogger(logger) {
 | 
						|
      loggers.push(logger);
 | 
						|
    },
 | 
						|
    notify: function(type, message) {
 | 
						|
      for (var i = 0, ii = loggers.length; i < ii; i++) {
 | 
						|
        var logger = loggers[i];
 | 
						|
        if (logger[type])
 | 
						|
          logger[type](message);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  };
 | 
						|
})();
 | 
						|
 | 
						|
function shadow(obj, prop, value) {
 | 
						|
  Object.defineProperty(obj, prop, { value: value,
 | 
						|
                                     enumerable: true,
 | 
						|
                                     configurable: true,
 | 
						|
                                     writable: false });
 | 
						|
  return value;
 | 
						|
}
 | 
						|
 | 
						|
var PasswordResponses = PDFJS.PasswordResponses = {
 | 
						|
  NEED_PASSWORD: 1,
 | 
						|
  INCORRECT_PASSWORD: 2
 | 
						|
};
 | 
						|
 | 
						|
var PasswordException = (function PasswordExceptionClosure() {
 | 
						|
  function PasswordException(msg, code) {
 | 
						|
    this.name = 'PasswordException';
 | 
						|
    this.message = msg;
 | 
						|
    this.code = code;
 | 
						|
  }
 | 
						|
 | 
						|
  PasswordException.prototype = new Error();
 | 
						|
  PasswordException.constructor = PasswordException;
 | 
						|
 | 
						|
  return PasswordException;
 | 
						|
})();
 | 
						|
 | 
						|
var UnknownErrorException = (function UnknownErrorExceptionClosure() {
 | 
						|
  function UnknownErrorException(msg, details) {
 | 
						|
    this.name = 'UnknownErrorException';
 | 
						|
    this.message = msg;
 | 
						|
    this.details = details;
 | 
						|
  }
 | 
						|
 | 
						|
  UnknownErrorException.prototype = new Error();
 | 
						|
  UnknownErrorException.constructor = UnknownErrorException;
 | 
						|
 | 
						|
  return UnknownErrorException;
 | 
						|
})();
 | 
						|
 | 
						|
var InvalidPDFException = (function InvalidPDFExceptionClosure() {
 | 
						|
  function InvalidPDFException(msg) {
 | 
						|
    this.name = 'InvalidPDFException';
 | 
						|
    this.message = msg;
 | 
						|
  }
 | 
						|
 | 
						|
  InvalidPDFException.prototype = new Error();
 | 
						|
  InvalidPDFException.constructor = InvalidPDFException;
 | 
						|
 | 
						|
  return InvalidPDFException;
 | 
						|
})();
 | 
						|
 | 
						|
var MissingPDFException = (function MissingPDFExceptionClosure() {
 | 
						|
  function MissingPDFException(msg) {
 | 
						|
    this.name = 'MissingPDFException';
 | 
						|
    this.message = msg;
 | 
						|
  }
 | 
						|
 | 
						|
  MissingPDFException.prototype = new Error();
 | 
						|
  MissingPDFException.constructor = MissingPDFException;
 | 
						|
 | 
						|
  return MissingPDFException;
 | 
						|
})();
 | 
						|
 | 
						|
var NotImplementedException = (function NotImplementedExceptionClosure() {
 | 
						|
  function NotImplementedException(msg) {
 | 
						|
    this.message = msg;
 | 
						|
  }
 | 
						|
 | 
						|
  NotImplementedException.prototype = new Error();
 | 
						|
  NotImplementedException.prototype.name = 'NotImplementedException';
 | 
						|
  NotImplementedException.constructor = NotImplementedException;
 | 
						|
 | 
						|
  return NotImplementedException;
 | 
						|
})();
 | 
						|
 | 
						|
var MissingDataException = (function MissingDataExceptionClosure() {
 | 
						|
  function MissingDataException(begin, end) {
 | 
						|
    this.begin = begin;
 | 
						|
    this.end = end;
 | 
						|
    this.message = 'Missing data [' + begin + ', ' + end + ')';
 | 
						|
  }
 | 
						|
 | 
						|
  MissingDataException.prototype = new Error();
 | 
						|
  MissingDataException.prototype.name = 'MissingDataException';
 | 
						|
  MissingDataException.constructor = MissingDataException;
 | 
						|
 | 
						|
  return MissingDataException;
 | 
						|
})();
 | 
						|
 | 
						|
var XRefParseException = (function XRefParseExceptionClosure() {
 | 
						|
  function XRefParseException(msg) {
 | 
						|
    this.message = msg;
 | 
						|
  }
 | 
						|
 | 
						|
  XRefParseException.prototype = new Error();
 | 
						|
  XRefParseException.prototype.name = 'XRefParseException';
 | 
						|
  XRefParseException.constructor = XRefParseException;
 | 
						|
 | 
						|
  return XRefParseException;
 | 
						|
})();
 | 
						|
 | 
						|
 | 
						|
function bytesToString(bytes) {
 | 
						|
  var str = '';
 | 
						|
  var length = bytes.length;
 | 
						|
  for (var n = 0; n < length; ++n)
 | 
						|
    str += String.fromCharCode(bytes[n]);
 | 
						|
  return str;
 | 
						|
}
 | 
						|
 | 
						|
function stringToBytes(str) {
 | 
						|
  var length = str.length;
 | 
						|
  var bytes = new Uint8Array(length);
 | 
						|
  for (var n = 0; n < length; ++n)
 | 
						|
    bytes[n] = str.charCodeAt(n) & 0xFF;
 | 
						|
  return bytes;
 | 
						|
}
 | 
						|
 | 
						|
var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
 | 
						|
 | 
						|
var Util = PDFJS.Util = (function UtilClosure() {
 | 
						|
  function Util() {}
 | 
						|
 | 
						|
  Util.makeCssRgb = function Util_makeCssRgb(rgb) {
 | 
						|
    return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
 | 
						|
  };
 | 
						|
 | 
						|
  Util.makeCssCmyk = function Util_makeCssCmyk(cmyk) {
 | 
						|
    var rgb = ColorSpace.singletons.cmyk.getRgb(cmyk, 0);
 | 
						|
    return Util.makeCssRgb(rgb);
 | 
						|
  };
 | 
						|
 | 
						|
  // Concatenates two transformation matrices together and returns the result.
 | 
						|
  Util.transform = function Util_transform(m1, m2) {
 | 
						|
    return [
 | 
						|
      m1[0] * m2[0] + m1[2] * m2[1],
 | 
						|
      m1[1] * m2[0] + m1[3] * m2[1],
 | 
						|
      m1[0] * m2[2] + m1[2] * m2[3],
 | 
						|
      m1[1] * m2[2] + m1[3] * m2[3],
 | 
						|
      m1[0] * m2[4] + m1[2] * m2[5] + m1[4],
 | 
						|
      m1[1] * m2[4] + m1[3] * m2[5] + m1[5]
 | 
						|
    ];
 | 
						|
  };
 | 
						|
 | 
						|
  // For 2d affine transforms
 | 
						|
  Util.applyTransform = function Util_applyTransform(p, m) {
 | 
						|
    var xt = p[0] * m[0] + p[1] * m[2] + m[4];
 | 
						|
    var yt = p[0] * m[1] + p[1] * m[3] + m[5];
 | 
						|
    return [xt, yt];
 | 
						|
  };
 | 
						|
 | 
						|
  Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
 | 
						|
    var d = m[0] * m[3] - m[1] * m[2];
 | 
						|
    var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
 | 
						|
    var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
 | 
						|
    return [xt, yt];
 | 
						|
  };
 | 
						|
 | 
						|
  // Applies the transform to the rectangle and finds the minimum axially
 | 
						|
  // aligned bounding box.
 | 
						|
  Util.getAxialAlignedBoundingBox =
 | 
						|
    function Util_getAxialAlignedBoundingBox(r, m) {
 | 
						|
 | 
						|
    var p1 = Util.applyTransform(r, m);
 | 
						|
    var p2 = Util.applyTransform(r.slice(2, 4), m);
 | 
						|
    var p3 = Util.applyTransform([r[0], r[3]], m);
 | 
						|
    var p4 = Util.applyTransform([r[2], r[1]], m);
 | 
						|
    return [
 | 
						|
      Math.min(p1[0], p2[0], p3[0], p4[0]),
 | 
						|
      Math.min(p1[1], p2[1], p3[1], p4[1]),
 | 
						|
      Math.max(p1[0], p2[0], p3[0], p4[0]),
 | 
						|
      Math.max(p1[1], p2[1], p3[1], p4[1])
 | 
						|
    ];
 | 
						|
  };
 | 
						|
 | 
						|
  Util.inverseTransform = function Util_inverseTransform(m) {
 | 
						|
    var d = m[0] * m[3] - m[1] * m[2];
 | 
						|
    return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d,
 | 
						|
      (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
 | 
						|
  };
 | 
						|
 | 
						|
  // Apply a generic 3d matrix M on a 3-vector v:
 | 
						|
  //   | a b c |   | X |
 | 
						|
  //   | d e f | x | Y |
 | 
						|
  //   | g h i |   | Z |
 | 
						|
  // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
 | 
						|
  // with v as [X,Y,Z]
 | 
						|
  Util.apply3dTransform = function Util_apply3dTransform(m, v) {
 | 
						|
    return [
 | 
						|
      m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
 | 
						|
      m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
 | 
						|
      m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
 | 
						|
    ];
 | 
						|
  };
 | 
						|
 | 
						|
  // This calculation uses Singular Value Decomposition.
 | 
						|
  // The SVD can be represented with formula A = USV. We are interested in the
 | 
						|
  // matrix S here because it represents the scale values.
 | 
						|
  Util.singularValueDecompose2dScale =
 | 
						|
    function Util_singularValueDecompose2dScale(m) {
 | 
						|
 | 
						|
    var transpose = [m[0], m[2], m[1], m[3]];
 | 
						|
 | 
						|
    // Multiply matrix m with its transpose.
 | 
						|
    var a = m[0] * transpose[0] + m[1] * transpose[2];
 | 
						|
    var b = m[0] * transpose[1] + m[1] * transpose[3];
 | 
						|
    var c = m[2] * transpose[0] + m[3] * transpose[2];
 | 
						|
    var d = m[2] * transpose[1] + m[3] * transpose[3];
 | 
						|
 | 
						|
    // Solve the second degree polynomial to get roots.
 | 
						|
    var first = (a + d) / 2;
 | 
						|
    var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
 | 
						|
    var sx = first + second || 1;
 | 
						|
    var sy = first - second || 1;
 | 
						|
 | 
						|
    // Scale values are the square roots of the eigenvalues.
 | 
						|
    return [Math.sqrt(sx), Math.sqrt(sy)];
 | 
						|
  };
 | 
						|
 | 
						|
  // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
 | 
						|
  // For coordinate systems whose origin lies in the bottom-left, this
 | 
						|
  // means normalization to (BL,TR) ordering. For systems with origin in the
 | 
						|
  // top-left, this means (TL,BR) ordering.
 | 
						|
  Util.normalizeRect = function Util_normalizeRect(rect) {
 | 
						|
    var r = rect.slice(0); // clone rect
 | 
						|
    if (rect[0] > rect[2]) {
 | 
						|
      r[0] = rect[2];
 | 
						|
      r[2] = rect[0];
 | 
						|
    }
 | 
						|
    if (rect[1] > rect[3]) {
 | 
						|
      r[1] = rect[3];
 | 
						|
      r[3] = rect[1];
 | 
						|
    }
 | 
						|
    return r;
 | 
						|
  };
 | 
						|
 | 
						|
  // Returns a rectangle [x1, y1, x2, y2] corresponding to the
 | 
						|
  // intersection of rect1 and rect2. If no intersection, returns 'false'
 | 
						|
  // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
 | 
						|
  Util.intersect = function Util_intersect(rect1, rect2) {
 | 
						|
    function compare(a, b) {
 | 
						|
      return a - b;
 | 
						|
    }
 | 
						|
 | 
						|
    // Order points along the axes
 | 
						|
    var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
 | 
						|
        orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
 | 
						|
        result = [];
 | 
						|
 | 
						|
    rect1 = Util.normalizeRect(rect1);
 | 
						|
    rect2 = Util.normalizeRect(rect2);
 | 
						|
 | 
						|
    // X: first and second points belong to different rectangles?
 | 
						|
    if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) ||
 | 
						|
        (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) {
 | 
						|
      // Intersection must be between second and third points
 | 
						|
      result[0] = orderedX[1];
 | 
						|
      result[2] = orderedX[2];
 | 
						|
    } else {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    // Y: first and second points belong to different rectangles?
 | 
						|
    if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) ||
 | 
						|
        (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) {
 | 
						|
      // Intersection must be between second and third points
 | 
						|
      result[1] = orderedY[1];
 | 
						|
      result[3] = orderedY[2];
 | 
						|
    } else {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
  };
 | 
						|
 | 
						|
  Util.sign = function Util_sign(num) {
 | 
						|
    return num < 0 ? -1 : 1;
 | 
						|
  };
 | 
						|
 | 
						|
  // TODO(mack): Rename appendToArray
 | 
						|
  Util.concatenateToArray = function concatenateToArray(arr1, arr2) {
 | 
						|
    Array.prototype.push.apply(arr1, arr2);
 | 
						|
  };
 | 
						|
 | 
						|
  Util.prependToArray = function concatenateToArray(arr1, arr2) {
 | 
						|
    Array.prototype.unshift.apply(arr1, arr2);
 | 
						|
  };
 | 
						|
 | 
						|
  Util.extendObj = function extendObj(obj1, obj2) {
 | 
						|
    for (var key in obj2) {
 | 
						|
      obj1[key] = obj2[key];
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  Util.getInheritableProperty = function Util_getInheritableProperty(dict,
 | 
						|
                                                                     name) {
 | 
						|
    while (dict && !dict.has(name)) {
 | 
						|
      dict = dict.get('Parent');
 | 
						|
    }
 | 
						|
    if (!dict) {
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
    return dict.get(name);
 | 
						|
  };
 | 
						|
 | 
						|
  Util.inherit = function Util_inherit(sub, base, prototype) {
 | 
						|
    sub.prototype = Object.create(base.prototype);
 | 
						|
    sub.prototype.constructor = sub;
 | 
						|
    for (var prop in prototype) {
 | 
						|
      sub.prototype[prop] = prototype[prop];
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  Util.loadScript = function Util_loadScript(src, callback) {
 | 
						|
    var script = document.createElement('script');
 | 
						|
    var loaded = false;
 | 
						|
    script.setAttribute('src', src);
 | 
						|
    if (callback) {
 | 
						|
      script.onload = function() {
 | 
						|
        if (!loaded) {
 | 
						|
          callback();
 | 
						|
        }
 | 
						|
        loaded = true;
 | 
						|
      };
 | 
						|
    }
 | 
						|
    document.getElementsByTagName('head')[0].appendChild(script);
 | 
						|
  };
 | 
						|
 | 
						|
  return Util;
 | 
						|
})();
 | 
						|
 | 
						|
var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
 | 
						|
  function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) {
 | 
						|
    this.viewBox = viewBox;
 | 
						|
    this.scale = scale;
 | 
						|
    this.rotation = rotation;
 | 
						|
    this.offsetX = offsetX;
 | 
						|
    this.offsetY = offsetY;
 | 
						|
 | 
						|
    // creating transform to convert pdf coordinate system to the normal
 | 
						|
    // canvas like coordinates taking in account scale and rotation
 | 
						|
    var centerX = (viewBox[2] + viewBox[0]) / 2;
 | 
						|
    var centerY = (viewBox[3] + viewBox[1]) / 2;
 | 
						|
    var rotateA, rotateB, rotateC, rotateD;
 | 
						|
    rotation = rotation % 360;
 | 
						|
    rotation = rotation < 0 ? rotation + 360 : rotation;
 | 
						|
    switch (rotation) {
 | 
						|
      case 180:
 | 
						|
        rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
 | 
						|
        break;
 | 
						|
      case 90:
 | 
						|
        rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
 | 
						|
        break;
 | 
						|
      case 270:
 | 
						|
        rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
 | 
						|
        break;
 | 
						|
      //case 0:
 | 
						|
      default:
 | 
						|
        rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (dontFlip) {
 | 
						|
      rotateC = -rotateC; rotateD = -rotateD;
 | 
						|
    }
 | 
						|
 | 
						|
    var offsetCanvasX, offsetCanvasY;
 | 
						|
    var width, height;
 | 
						|
    if (rotateA === 0) {
 | 
						|
      offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
 | 
						|
      offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
 | 
						|
      width = Math.abs(viewBox[3] - viewBox[1]) * scale;
 | 
						|
      height = Math.abs(viewBox[2] - viewBox[0]) * scale;
 | 
						|
    } else {
 | 
						|
      offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
 | 
						|
      offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
 | 
						|
      width = Math.abs(viewBox[2] - viewBox[0]) * scale;
 | 
						|
      height = Math.abs(viewBox[3] - viewBox[1]) * scale;
 | 
						|
    }
 | 
						|
    // creating transform for the following operations:
 | 
						|
    // translate(-centerX, -centerY), rotate and flip vertically,
 | 
						|
    // scale, and translate(offsetCanvasX, offsetCanvasY)
 | 
						|
    this.transform = [
 | 
						|
      rotateA * scale,
 | 
						|
      rotateB * scale,
 | 
						|
      rotateC * scale,
 | 
						|
      rotateD * scale,
 | 
						|
      offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
 | 
						|
      offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
 | 
						|
    ];
 | 
						|
 | 
						|
    this.width = width;
 | 
						|
    this.height = height;
 | 
						|
    this.fontScale = scale;
 | 
						|
  }
 | 
						|
  PageViewport.prototype = {
 | 
						|
    clone: function PageViewPort_clone(args) {
 | 
						|
      args = args || {};
 | 
						|
      var scale = 'scale' in args ? args.scale : this.scale;
 | 
						|
      var rotation = 'rotation' in args ? args.rotation : this.rotation;
 | 
						|
      return new PageViewport(this.viewBox.slice(), scale, rotation,
 | 
						|
                              this.offsetX, this.offsetY, args.dontFlip);
 | 
						|
    },
 | 
						|
    convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
 | 
						|
      return Util.applyTransform([x, y], this.transform);
 | 
						|
    },
 | 
						|
    convertToViewportRectangle:
 | 
						|
      function PageViewport_convertToViewportRectangle(rect) {
 | 
						|
      var tl = Util.applyTransform([rect[0], rect[1]], this.transform);
 | 
						|
      var br = Util.applyTransform([rect[2], rect[3]], this.transform);
 | 
						|
      return [tl[0], tl[1], br[0], br[1]];
 | 
						|
    },
 | 
						|
    convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
 | 
						|
      return Util.applyInverseTransform([x, y], this.transform);
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return PageViewport;
 | 
						|
})();
 | 
						|
 | 
						|
var PDFStringTranslateTable = [
 | 
						|
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | 
						|
  0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0,
 | 
						|
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | 
						|
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | 
						|
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | 
						|
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014,
 | 
						|
  0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C,
 | 
						|
  0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160,
 | 
						|
  0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC
 | 
						|
];
 | 
						|
 | 
						|
function stringToPDFString(str) {
 | 
						|
  var i, n = str.length, str2 = '';
 | 
						|
  if (str[0] === '\xFE' && str[1] === '\xFF') {
 | 
						|
    // UTF16BE BOM
 | 
						|
    for (i = 2; i < n; i += 2)
 | 
						|
      str2 += String.fromCharCode(
 | 
						|
        (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1));
 | 
						|
  } else {
 | 
						|
    for (i = 0; i < n; ++i) {
 | 
						|
      var code = PDFStringTranslateTable[str.charCodeAt(i)];
 | 
						|
      str2 += code ? String.fromCharCode(code) : str.charAt(i);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return str2;
 | 
						|
}
 | 
						|
 | 
						|
function stringToUTF8String(str) {
 | 
						|
  return decodeURIComponent(escape(str));
 | 
						|
}
 | 
						|
 | 
						|
function isEmptyObj(obj) {
 | 
						|
  for (var key in obj) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
function isBool(v) {
 | 
						|
  return typeof v == 'boolean';
 | 
						|
}
 | 
						|
 | 
						|
function isInt(v) {
 | 
						|
  return typeof v == 'number' && ((v | 0) == v);
 | 
						|
}
 | 
						|
 | 
						|
function isNum(v) {
 | 
						|
  return typeof v == 'number';
 | 
						|
}
 | 
						|
 | 
						|
function isString(v) {
 | 
						|
  return typeof v == 'string';
 | 
						|
}
 | 
						|
 | 
						|
function isNull(v) {
 | 
						|
  return v === null;
 | 
						|
}
 | 
						|
 | 
						|
function isName(v) {
 | 
						|
  return v instanceof Name;
 | 
						|
}
 | 
						|
 | 
						|
function isCmd(v, cmd) {
 | 
						|
  return v instanceof Cmd && (!cmd || v.cmd == cmd);
 | 
						|
}
 | 
						|
 | 
						|
function isDict(v, type) {
 | 
						|
  if (!(v instanceof Dict)) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  if (!type) {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
  var dictType = v.get('Type');
 | 
						|
  return isName(dictType) && dictType.name == type;
 | 
						|
}
 | 
						|
 | 
						|
function isArray(v) {
 | 
						|
  return v instanceof Array;
 | 
						|
}
 | 
						|
 | 
						|
function isStream(v) {
 | 
						|
  return typeof v == 'object' && v !== null && v !== undefined &&
 | 
						|
         ('getBytes' in v);
 | 
						|
}
 | 
						|
 | 
						|
function isArrayBuffer(v) {
 | 
						|
  return typeof v == 'object' && v !== null && v !== undefined &&
 | 
						|
         ('byteLength' in v);
 | 
						|
}
 | 
						|
 | 
						|
function isRef(v) {
 | 
						|
  return v instanceof Ref;
 | 
						|
}
 | 
						|
 | 
						|
function isPDFFunction(v) {
 | 
						|
  var fnDict;
 | 
						|
  if (typeof v != 'object')
 | 
						|
    return false;
 | 
						|
  else if (isDict(v))
 | 
						|
    fnDict = v;
 | 
						|
  else if (isStream(v))
 | 
						|
    fnDict = v.dict;
 | 
						|
  else
 | 
						|
    return false;
 | 
						|
  return fnDict.has('FunctionType');
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * The following promise implementation tries to generally implment the
 | 
						|
 * Promise/A+ spec. Some notable differences from other promise libaries are:
 | 
						|
 * - There currently isn't a seperate deferred and promise object.
 | 
						|
 * - Unhandled rejections eventually show an error if they aren't handled.
 | 
						|
 *
 | 
						|
 * Based off of the work in:
 | 
						|
 * https://bugzilla.mozilla.org/show_bug.cgi?id=810490
 | 
						|
 */
 | 
						|
var Promise = PDFJS.Promise = (function PromiseClosure() {
 | 
						|
  var STATUS_PENDING = 0;
 | 
						|
  var STATUS_RESOLVED = 1;
 | 
						|
  var STATUS_REJECTED = 2;
 | 
						|
 | 
						|
  // In an attempt to avoid silent exceptions, unhandled rejections are
 | 
						|
  // tracked and if they aren't handled in a certain amount of time an
 | 
						|
  // error is logged.
 | 
						|
  var REJECTION_TIMEOUT = 500;
 | 
						|
 | 
						|
  var HandlerManager = {
 | 
						|
    handlers: [],
 | 
						|
    running: false,
 | 
						|
    unhandledRejections: [],
 | 
						|
    pendingRejectionCheck: false,
 | 
						|
 | 
						|
    scheduleHandlers: function scheduleHandlers(promise) {
 | 
						|
      if (promise._status == STATUS_PENDING) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      this.handlers = this.handlers.concat(promise._handlers);
 | 
						|
      promise._handlers = [];
 | 
						|
 | 
						|
      if (this.running) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      this.running = true;
 | 
						|
 | 
						|
      setTimeout(this.runHandlers.bind(this), 0);
 | 
						|
    },
 | 
						|
 | 
						|
    runHandlers: function runHandlers() {
 | 
						|
      while (this.handlers.length > 0) {
 | 
						|
        var handler = this.handlers.shift();
 | 
						|
 | 
						|
        var nextStatus = handler.thisPromise._status;
 | 
						|
        var nextValue = handler.thisPromise._value;
 | 
						|
 | 
						|
        try {
 | 
						|
          if (nextStatus === STATUS_RESOLVED) {
 | 
						|
            if (typeof(handler.onResolve) == 'function') {
 | 
						|
              nextValue = handler.onResolve(nextValue);
 | 
						|
            }
 | 
						|
          } else if (typeof(handler.onReject) === 'function') {
 | 
						|
              nextValue = handler.onReject(nextValue);
 | 
						|
              nextStatus = STATUS_RESOLVED;
 | 
						|
 | 
						|
              if (handler.thisPromise._unhandledRejection) {
 | 
						|
                this.removeUnhandeledRejection(handler.thisPromise);
 | 
						|
              }
 | 
						|
          }
 | 
						|
        } catch (ex) {
 | 
						|
          nextStatus = STATUS_REJECTED;
 | 
						|
          nextValue = ex;
 | 
						|
        }
 | 
						|
 | 
						|
        handler.nextPromise._updateStatus(nextStatus, nextValue);
 | 
						|
      }
 | 
						|
 | 
						|
      this.running = false;
 | 
						|
    },
 | 
						|
 | 
						|
    addUnhandledRejection: function addUnhandledRejection(promise) {
 | 
						|
      this.unhandledRejections.push({
 | 
						|
        promise: promise,
 | 
						|
        time: Date.now()
 | 
						|
      });
 | 
						|
      this.scheduleRejectionCheck();
 | 
						|
    },
 | 
						|
 | 
						|
    removeUnhandeledRejection: function removeUnhandeledRejection(promise) {
 | 
						|
      promise._unhandledRejection = false;
 | 
						|
      for (var i = 0; i < this.unhandledRejections.length; i++) {
 | 
						|
        if (this.unhandledRejections[i].promise === promise) {
 | 
						|
          this.unhandledRejections.splice(i);
 | 
						|
          i--;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    scheduleRejectionCheck: function scheduleRejectionCheck() {
 | 
						|
      if (this.pendingRejectionCheck) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      this.pendingRejectionCheck = true;
 | 
						|
      setTimeout(function rejectionCheck() {
 | 
						|
        this.pendingRejectionCheck = false;
 | 
						|
        var now = Date.now();
 | 
						|
        for (var i = 0; i < this.unhandledRejections.length; i++) {
 | 
						|
          if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) {
 | 
						|
            var unhandled = this.unhandledRejections[i].promise._value;
 | 
						|
            var msg = 'Unhandled rejection: ' + unhandled;
 | 
						|
            if (unhandled.stack) {
 | 
						|
              msg += '\n' + unhandled.stack;
 | 
						|
            }
 | 
						|
            warn(msg);
 | 
						|
            this.unhandledRejections.splice(i);
 | 
						|
            i--;
 | 
						|
          }
 | 
						|
        }
 | 
						|
        if (this.unhandledRejections.length) {
 | 
						|
          this.scheduleRejectionCheck();
 | 
						|
        }
 | 
						|
      }.bind(this), REJECTION_TIMEOUT);
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  function Promise() {
 | 
						|
    this._status = STATUS_PENDING;
 | 
						|
    this._handlers = [];
 | 
						|
  }
 | 
						|
  /**
 | 
						|
   * Builds a promise that is resolved when all the passed in promises are
 | 
						|
   * resolved.
 | 
						|
   * @param {array} array of data and/or promises to wait for.
 | 
						|
   * @return {Promise} New dependant promise.
 | 
						|
   */
 | 
						|
  Promise.all = function Promise_all(promises) {
 | 
						|
    var deferred = new Promise();
 | 
						|
    var unresolved = promises.length;
 | 
						|
    var results = [];
 | 
						|
    if (unresolved === 0) {
 | 
						|
      deferred.resolve(results);
 | 
						|
      return deferred;
 | 
						|
    }
 | 
						|
    function reject(reason) {
 | 
						|
      if (deferred._status === STATUS_REJECTED) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      results = [];
 | 
						|
      deferred.reject(reason);
 | 
						|
    }
 | 
						|
    for (var i = 0, ii = promises.length; i < ii; ++i) {
 | 
						|
      var promise = promises[i];
 | 
						|
      var resolve = (function(i) {
 | 
						|
        return function(value) {
 | 
						|
          if (deferred._status === STATUS_REJECTED) {
 | 
						|
            return;
 | 
						|
          }
 | 
						|
          results[i] = value;
 | 
						|
          unresolved--;
 | 
						|
          if (unresolved === 0)
 | 
						|
            deferred.resolve(results);
 | 
						|
        };
 | 
						|
      })(i);
 | 
						|
      if (Promise.isPromise(promise)) {
 | 
						|
        promise.then(resolve, reject);
 | 
						|
      } else {
 | 
						|
        resolve(promise);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return deferred;
 | 
						|
  };
 | 
						|
 | 
						|
  /**
 | 
						|
   * Checks if the value is likely a promise (has a 'then' function).
 | 
						|
   * @return {boolean} true if x is thenable
 | 
						|
   */
 | 
						|
  Promise.isPromise = function Promise_isPromise(value) {
 | 
						|
    return value && typeof value.then === 'function';
 | 
						|
  };
 | 
						|
 | 
						|
  Promise.prototype = {
 | 
						|
    _status: null,
 | 
						|
    _value: null,
 | 
						|
    _handlers: null,
 | 
						|
    _unhandledRejection: null,
 | 
						|
 | 
						|
    _updateStatus: function Promise__updateStatus(status, value) {
 | 
						|
      if (this._status === STATUS_RESOLVED ||
 | 
						|
          this._status === STATUS_REJECTED) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      if (status == STATUS_RESOLVED &&
 | 
						|
          Promise.isPromise(value)) {
 | 
						|
        value.then(this._updateStatus.bind(this, STATUS_RESOLVED),
 | 
						|
                   this._updateStatus.bind(this, STATUS_REJECTED));
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      this._status = status;
 | 
						|
      this._value = value;
 | 
						|
 | 
						|
      if (status === STATUS_REJECTED && this._handlers.length === 0) {
 | 
						|
        this._unhandledRejection = true;
 | 
						|
        HandlerManager.addUnhandledRejection(this);
 | 
						|
      }
 | 
						|
 | 
						|
      HandlerManager.scheduleHandlers(this);
 | 
						|
    },
 | 
						|
 | 
						|
    get isResolved() {
 | 
						|
      return this._status === STATUS_RESOLVED;
 | 
						|
    },
 | 
						|
 | 
						|
    get isRejected() {
 | 
						|
      return this._status === STATUS_REJECTED;
 | 
						|
    },
 | 
						|
 | 
						|
    resolve: function Promise_resolve(value) {
 | 
						|
      this._updateStatus(STATUS_RESOLVED, value);
 | 
						|
    },
 | 
						|
 | 
						|
    reject: function Promise_reject(reason) {
 | 
						|
      this._updateStatus(STATUS_REJECTED, reason);
 | 
						|
    },
 | 
						|
 | 
						|
    then: function Promise_then(onResolve, onReject) {
 | 
						|
      var nextPromise = new Promise();
 | 
						|
      this._handlers.push({
 | 
						|
        thisPromise: this,
 | 
						|
        onResolve: onResolve,
 | 
						|
        onReject: onReject,
 | 
						|
        nextPromise: nextPromise
 | 
						|
      });
 | 
						|
      HandlerManager.scheduleHandlers(this);
 | 
						|
      return nextPromise;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  return Promise;
 | 
						|
})();
 | 
						|
 | 
						|
var StatTimer = (function StatTimerClosure() {
 | 
						|
  function rpad(str, pad, length) {
 | 
						|
    while (str.length < length)
 | 
						|
      str += pad;
 | 
						|
    return str;
 | 
						|
  }
 | 
						|
  function StatTimer() {
 | 
						|
    this.started = {};
 | 
						|
    this.times = [];
 | 
						|
    this.enabled = true;
 | 
						|
  }
 | 
						|
  StatTimer.prototype = {
 | 
						|
    time: function StatTimer_time(name) {
 | 
						|
      if (!this.enabled)
 | 
						|
        return;
 | 
						|
      if (name in this.started)
 | 
						|
        warn('Timer is already running for ' + name);
 | 
						|
      this.started[name] = Date.now();
 | 
						|
    },
 | 
						|
    timeEnd: function StatTimer_timeEnd(name) {
 | 
						|
      if (!this.enabled)
 | 
						|
        return;
 | 
						|
      if (!(name in this.started))
 | 
						|
        warn('Timer has not been started for ' + name);
 | 
						|
      this.times.push({
 | 
						|
        'name': name,
 | 
						|
        'start': this.started[name],
 | 
						|
        'end': Date.now()
 | 
						|
      });
 | 
						|
      // Remove timer from started so it can be called again.
 | 
						|
      delete this.started[name];
 | 
						|
    },
 | 
						|
    toString: function StatTimer_toString() {
 | 
						|
      var times = this.times;
 | 
						|
      var out = '';
 | 
						|
      // Find the longest name for padding purposes.
 | 
						|
      var longest = 0;
 | 
						|
      for (var i = 0, ii = times.length; i < ii; ++i) {
 | 
						|
        var name = times[i]['name'];
 | 
						|
        if (name.length > longest)
 | 
						|
          longest = name.length;
 | 
						|
      }
 | 
						|
      for (var i = 0, ii = times.length; i < ii; ++i) {
 | 
						|
        var span = times[i];
 | 
						|
        var duration = span.end - span.start;
 | 
						|
        out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
 | 
						|
      }
 | 
						|
      return out;
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return StatTimer;
 | 
						|
})();
 | 
						|
 | 
						|
PDFJS.createBlob = function createBlob(data, contentType) {
 | 
						|
  if (typeof Blob !== 'undefined')
 | 
						|
    return new Blob([data], { type: contentType });
 | 
						|
  // Blob builder is deprecated in FF14 and removed in FF18.
 | 
						|
  var bb = new MozBlobBuilder();
 | 
						|
  bb.append(data);
 | 
						|
  return bb.getBlob(contentType);
 | 
						|
};
 | 
						|
 | 
						|
PDFJS.createObjectURL = (function createObjectURLClosure() {
 | 
						|
  if (typeof URL !== 'undefined' && URL.createObjectURL) {
 | 
						|
    return function createObjectURL(data, contentType) {
 | 
						|
      var blob = PDFJS.createBlob(data, contentType);
 | 
						|
      return URL.createObjectURL(blob);
 | 
						|
    };
 | 
						|
  }
 | 
						|
 | 
						|
  // Blob/createObjectURL is not available, falling back to data schema.
 | 
						|
  var digits =
 | 
						|
    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
 | 
						|
 | 
						|
  return function createObjectURL(data, contentType) {
 | 
						|
    var buffer = 'data:' + contentType + ';base64,';
 | 
						|
    for (var i = 0, ii = data.length; i < ii; i += 3) {
 | 
						|
      var b1 = data[i] & 0xFF;
 | 
						|
      var b2 = data[i + 1] & 0xFF;
 | 
						|
      var b3 = data[i + 2] & 0xFF;
 | 
						|
      var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
 | 
						|
      var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
 | 
						|
      var d4 = i + 2 < ii ? (b3 & 0x3F) : 64;
 | 
						|
      buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
 | 
						|
    }
 | 
						|
    return buffer;
 | 
						|
  };
 | 
						|
})();
 | 
						|
 | 
						|
function MessageHandler(name, comObj) {
 | 
						|
  this.name = name;
 | 
						|
  this.comObj = comObj;
 | 
						|
  this.callbackIndex = 1;
 | 
						|
  this.postMessageTransfers = true;
 | 
						|
  var callbacks = this.callbacks = {};
 | 
						|
  var ah = this.actionHandler = {};
 | 
						|
 | 
						|
  ah['console_log'] = [function ahConsoleLog(data) {
 | 
						|
    log.apply(null, data);
 | 
						|
  }];
 | 
						|
  // If there's no console available, console_error in the
 | 
						|
  // action handler will do nothing.
 | 
						|
  if ('console' in globalScope) {
 | 
						|
    ah['console_error'] = [function ahConsoleError(data) {
 | 
						|
      globalScope['console'].error.apply(null, data);
 | 
						|
    }];
 | 
						|
  } else {
 | 
						|
    ah['console_error'] = [function ahConsoleError(data) {
 | 
						|
      log.apply(null, data);
 | 
						|
    }];
 | 
						|
  }
 | 
						|
  ah['_warn'] = [function ah_Warn(data) {
 | 
						|
    warn(data);
 | 
						|
  }];
 | 
						|
 | 
						|
  comObj.onmessage = function messageHandlerComObjOnMessage(event) {
 | 
						|
    var data = event.data;
 | 
						|
    if (data.isReply) {
 | 
						|
      var callbackId = data.callbackId;
 | 
						|
      if (data.callbackId in callbacks) {
 | 
						|
        var callback = callbacks[callbackId];
 | 
						|
        delete callbacks[callbackId];
 | 
						|
        callback(data.data);
 | 
						|
      } else {
 | 
						|
        error('Cannot resolve callback ' + callbackId);
 | 
						|
      }
 | 
						|
    } else if (data.action in ah) {
 | 
						|
      var action = ah[data.action];
 | 
						|
      if (data.callbackId) {
 | 
						|
        var promise = new Promise();
 | 
						|
        promise.then(function(resolvedData) {
 | 
						|
          comObj.postMessage({
 | 
						|
            isReply: true,
 | 
						|
            callbackId: data.callbackId,
 | 
						|
            data: resolvedData
 | 
						|
          });
 | 
						|
        });
 | 
						|
        action[0].call(action[1], data.data, promise);
 | 
						|
      } else {
 | 
						|
        action[0].call(action[1], data.data);
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      error('Unkown action from worker: ' + data.action);
 | 
						|
    }
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
MessageHandler.prototype = {
 | 
						|
  on: function messageHandlerOn(actionName, handler, scope) {
 | 
						|
    var ah = this.actionHandler;
 | 
						|
    if (ah[actionName]) {
 | 
						|
      error('There is already an actionName called "' + actionName + '"');
 | 
						|
    }
 | 
						|
    ah[actionName] = [handler, scope];
 | 
						|
  },
 | 
						|
  /**
 | 
						|
   * Sends a message to the comObj to invoke the action with the supplied data.
 | 
						|
   * @param {String} actionName Action to call.
 | 
						|
   * @param {JSON} data JSON data to send.
 | 
						|
   * @param {function} [callback] Optional callback that will handle a reply.
 | 
						|
   * @param {Array} [transfers] Optional list of transfers/ArrayBuffers
 | 
						|
   */
 | 
						|
  send: function messageHandlerSend(actionName, data, callback, transfers) {
 | 
						|
    var message = {
 | 
						|
      action: actionName,
 | 
						|
      data: data
 | 
						|
    };
 | 
						|
    if (callback) {
 | 
						|
      var callbackId = this.callbackIndex++;
 | 
						|
      this.callbacks[callbackId] = callback;
 | 
						|
      message.callbackId = callbackId;
 | 
						|
    }
 | 
						|
    if (transfers && this.postMessageTransfers) {
 | 
						|
      this.comObj.postMessage(message, transfers);
 | 
						|
    } else {
 | 
						|
      this.comObj.postMessage(message);
 | 
						|
    }
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
function loadJpegStream(id, imageUrl, objs) {
 | 
						|
  var img = new Image();
 | 
						|
  img.onload = (function loadJpegStream_onloadClosure() {
 | 
						|
    objs.resolve(id, img);
 | 
						|
  });
 | 
						|
  img.src = imageUrl;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
var ColorSpace = (function ColorSpaceClosure() {
 | 
						|
  // Constructor should define this.numComps, this.defaultColor, this.name
 | 
						|
  function ColorSpace() {
 | 
						|
    error('should not call ColorSpace constructor');
 | 
						|
  }
 | 
						|
 | 
						|
  ColorSpace.prototype = {
 | 
						|
    /**
 | 
						|
     * Converts the color value to the RGB color. The color components are
 | 
						|
     * located in the src array starting from the srcOffset. Returns the array
 | 
						|
     * of the rgb components, each value ranging from [0,255].
 | 
						|
     */
 | 
						|
    getRgb: function ColorSpace_getRgb(src, srcOffset) {
 | 
						|
      error('Should not call ColorSpace.getRgb');
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * Converts the color value to the RGB color, similar to the getRgb method.
 | 
						|
     * The result placed into the dest array starting from the destOffset.
 | 
						|
     */
 | 
						|
    getRgbItem: function ColorSpace_getRgb(src, srcOffset, dest, destOffset) {
 | 
						|
      error('Should not call ColorSpace.getRgbItem');
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * Converts the specified number of the color values to the RGB colors.
 | 
						|
     * The colors are located in the src array starting from the srcOffset.
 | 
						|
     * The result is placed into the dest array starting from the destOffset.
 | 
						|
     * The src array items shall be in [0,2^bits) range, the dest array items
 | 
						|
     * will be in [0,255] range.
 | 
						|
     */
 | 
						|
    getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count,
 | 
						|
                                                   dest, destOffset, bits) {
 | 
						|
      error('Should not call ColorSpace.getRgbBuffer');
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * Determines amount of the bytes is required to store the reslut of the
 | 
						|
     * conversion that done by the getRgbBuffer method.
 | 
						|
     */
 | 
						|
    getOutputLength: function ColorSpace_getOutputLength(inputLength) {
 | 
						|
      error('Should not call ColorSpace.getOutputLength');
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * Returns true if source data will be equal the result/output data.
 | 
						|
     */
 | 
						|
    isPassthrough: function ColorSpace_isPassthrough(bits) {
 | 
						|
      return false;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * Creates the output buffer and converts the specified number of the color
 | 
						|
     * values to the RGB colors, similar to the getRgbBuffer.
 | 
						|
     */
 | 
						|
    createRgbBuffer: function ColorSpace_createRgbBuffer(src, srcOffset,
 | 
						|
                                                         count, bits) {
 | 
						|
      if (this.isPassthrough(bits)) {
 | 
						|
        return src.subarray(srcOffset);
 | 
						|
      }
 | 
						|
      var dest = new Uint8Array(count * 3);
 | 
						|
      var numComponentColors = 1 << bits;
 | 
						|
      // Optimization: create a color map when there is just one component and
 | 
						|
      // we are converting more colors than the size of the color map. We
 | 
						|
      // don't build the map if the colorspace is gray or rgb since those
 | 
						|
      // methods are faster than building a map. This mainly offers big speed
 | 
						|
      // ups for indexed and alternate colorspaces.
 | 
						|
      if (this.numComps === 1 && count > numComponentColors &&
 | 
						|
          this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') {
 | 
						|
        // TODO it may be worth while to cache the color map. While running
 | 
						|
        // testing I never hit a cache so I will leave that out for now (perhaps
 | 
						|
        // we are reparsing colorspaces too much?).
 | 
						|
        var allColors = bits <= 8 ? new Uint8Array(numComponentColors) :
 | 
						|
                                    new Uint16Array(numComponentColors);
 | 
						|
        for (var i = 0; i < numComponentColors; i++) {
 | 
						|
          allColors[i] = i;
 | 
						|
        }
 | 
						|
        var colorMap = new Uint8Array(numComponentColors * 3);
 | 
						|
        this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bits);
 | 
						|
 | 
						|
        var destOffset = 0;
 | 
						|
        for (var i = 0; i < count; ++i) {
 | 
						|
          var key = src[srcOffset++] * 3;
 | 
						|
          dest[destOffset++] = colorMap[key];
 | 
						|
          dest[destOffset++] = colorMap[key + 1];
 | 
						|
          dest[destOffset++] = colorMap[key + 2];
 | 
						|
        }
 | 
						|
        return dest;
 | 
						|
      }
 | 
						|
      this.getRgbBuffer(src, srcOffset, count, dest, 0, bits);
 | 
						|
      return dest;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * True if the colorspace has components in the default range of [0, 1].
 | 
						|
     * This should be true for all colorspaces except for lab color spaces
 | 
						|
     * which are [0,100], [-128, 127], [-128, 127].
 | 
						|
     */
 | 
						|
    usesZeroToOneRange: true
 | 
						|
  };
 | 
						|
 | 
						|
  ColorSpace.parse = function ColorSpace_parse(cs, xref, res) {
 | 
						|
    var IR = ColorSpace.parseToIR(cs, xref, res);
 | 
						|
    if (IR instanceof AlternateCS)
 | 
						|
      return IR;
 | 
						|
 | 
						|
    return ColorSpace.fromIR(IR);
 | 
						|
  };
 | 
						|
 | 
						|
  ColorSpace.fromIR = function ColorSpace_fromIR(IR) {
 | 
						|
    var name = isArray(IR) ? IR[0] : IR;
 | 
						|
 | 
						|
    switch (name) {
 | 
						|
      case 'DeviceGrayCS':
 | 
						|
        return this.singletons.gray;
 | 
						|
      case 'DeviceRgbCS':
 | 
						|
        return this.singletons.rgb;
 | 
						|
      case 'DeviceCmykCS':
 | 
						|
        return this.singletons.cmyk;
 | 
						|
      case 'CalGrayCS':
 | 
						|
        var whitePoint = IR[1].WhitePoint;
 | 
						|
        var blackPoint = IR[1].BlackPoint;
 | 
						|
        var gamma = IR[1].Gamma;
 | 
						|
        return new CalGrayCS(whitePoint, blackPoint, gamma);
 | 
						|
      case 'PatternCS':
 | 
						|
        var basePatternCS = IR[1];
 | 
						|
        if (basePatternCS)
 | 
						|
          basePatternCS = ColorSpace.fromIR(basePatternCS);
 | 
						|
        return new PatternCS(basePatternCS);
 | 
						|
      case 'IndexedCS':
 | 
						|
        var baseIndexedCS = IR[1];
 | 
						|
        var hiVal = IR[2];
 | 
						|
        var lookup = IR[3];
 | 
						|
        return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup);
 | 
						|
      case 'AlternateCS':
 | 
						|
        var numComps = IR[1];
 | 
						|
        var alt = IR[2];
 | 
						|
        var tintFnIR = IR[3];
 | 
						|
 | 
						|
        return new AlternateCS(numComps, ColorSpace.fromIR(alt),
 | 
						|
                                PDFFunction.fromIR(tintFnIR));
 | 
						|
      case 'LabCS':
 | 
						|
        var whitePoint = IR[1].WhitePoint;
 | 
						|
        var blackPoint = IR[1].BlackPoint;
 | 
						|
        var range = IR[1].Range;
 | 
						|
        return new LabCS(whitePoint, blackPoint, range);
 | 
						|
      default:
 | 
						|
        error('Unkown name ' + name);
 | 
						|
    }
 | 
						|
    return null;
 | 
						|
  };
 | 
						|
 | 
						|
  ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) {
 | 
						|
    if (isName(cs)) {
 | 
						|
      var colorSpaces = res.get('ColorSpace');
 | 
						|
      if (isDict(colorSpaces)) {
 | 
						|
        var refcs = colorSpaces.get(cs.name);
 | 
						|
        if (refcs)
 | 
						|
          cs = refcs;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    cs = xref.fetchIfRef(cs);
 | 
						|
    var mode;
 | 
						|
 | 
						|
    if (isName(cs)) {
 | 
						|
      mode = cs.name;
 | 
						|
      this.mode = mode;
 | 
						|
 | 
						|
      switch (mode) {
 | 
						|
        case 'DeviceGray':
 | 
						|
        case 'G':
 | 
						|
          return 'DeviceGrayCS';
 | 
						|
        case 'DeviceRGB':
 | 
						|
        case 'RGB':
 | 
						|
          return 'DeviceRgbCS';
 | 
						|
        case 'DeviceCMYK':
 | 
						|
        case 'CMYK':
 | 
						|
          return 'DeviceCmykCS';
 | 
						|
        case 'Pattern':
 | 
						|
          return ['PatternCS', null];
 | 
						|
        default:
 | 
						|
          error('unrecognized colorspace ' + mode);
 | 
						|
      }
 | 
						|
    } else if (isArray(cs)) {
 | 
						|
      mode = cs[0].name;
 | 
						|
      this.mode = mode;
 | 
						|
 | 
						|
      switch (mode) {
 | 
						|
        case 'DeviceGray':
 | 
						|
        case 'G':
 | 
						|
          return 'DeviceGrayCS';
 | 
						|
        case 'DeviceRGB':
 | 
						|
        case 'RGB':
 | 
						|
          return 'DeviceRgbCS';
 | 
						|
        case 'DeviceCMYK':
 | 
						|
        case 'CMYK':
 | 
						|
          return 'DeviceCmykCS';
 | 
						|
        case 'CalGray':
 | 
						|
          var params = cs[1].getAll();
 | 
						|
          return ['CalGrayCS', params];
 | 
						|
        case 'CalRGB':
 | 
						|
          return 'DeviceRgbCS';
 | 
						|
        case 'ICCBased':
 | 
						|
          var stream = xref.fetchIfRef(cs[1]);
 | 
						|
          var dict = stream.dict;
 | 
						|
          var numComps = dict.get('N');
 | 
						|
          if (numComps == 1)
 | 
						|
            return 'DeviceGrayCS';
 | 
						|
          if (numComps == 3)
 | 
						|
            return 'DeviceRgbCS';
 | 
						|
          if (numComps == 4)
 | 
						|
            return 'DeviceCmykCS';
 | 
						|
          break;
 | 
						|
        case 'Pattern':
 | 
						|
          var basePatternCS = cs[1];
 | 
						|
          if (basePatternCS)
 | 
						|
            basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
 | 
						|
          return ['PatternCS', basePatternCS];
 | 
						|
        case 'Indexed':
 | 
						|
        case 'I':
 | 
						|
          var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
 | 
						|
          var hiVal = cs[2] + 1;
 | 
						|
          var lookup = xref.fetchIfRef(cs[3]);
 | 
						|
          if (isStream(lookup)) {
 | 
						|
            lookup = lookup.getBytes();
 | 
						|
          }
 | 
						|
          return ['IndexedCS', baseIndexedCS, hiVal, lookup];
 | 
						|
        case 'Separation':
 | 
						|
        case 'DeviceN':
 | 
						|
          var name = cs[1];
 | 
						|
          var numComps = 1;
 | 
						|
          if (isName(name))
 | 
						|
            numComps = 1;
 | 
						|
          else if (isArray(name))
 | 
						|
            numComps = name.length;
 | 
						|
          var alt = ColorSpace.parseToIR(cs[2], xref, res);
 | 
						|
          var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3]));
 | 
						|
          return ['AlternateCS', numComps, alt, tintFnIR];
 | 
						|
        case 'Lab':
 | 
						|
          var params = cs[1].getAll();
 | 
						|
          return ['LabCS', params];
 | 
						|
        default:
 | 
						|
          error('unimplemented color space object "' + mode + '"');
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      error('unrecognized color space object: "' + cs + '"');
 | 
						|
    }
 | 
						|
    return null;
 | 
						|
  };
 | 
						|
  /**
 | 
						|
   * Checks if a decode map matches the default decode map for a color space.
 | 
						|
   * This handles the general decode maps where there are two values per
 | 
						|
   * component. e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
 | 
						|
   * This does not handle Lab, Indexed, or Pattern decode maps since they are
 | 
						|
   * slightly different.
 | 
						|
   * @param {Array} decode Decode map (usually from an image).
 | 
						|
   * @param {Number} n Number of components the color space has.
 | 
						|
   */
 | 
						|
  ColorSpace.isDefaultDecode = function ColorSpace_isDefaultDecode(decode, n) {
 | 
						|
    if (!decode)
 | 
						|
      return true;
 | 
						|
 | 
						|
    if (n * 2 !== decode.length) {
 | 
						|
      warn('The decode map is not the correct length');
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
    for (var i = 0, ii = decode.length; i < ii; i += 2) {
 | 
						|
      if (decode[i] !== 0 || decode[i + 1] != 1)
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
  };
 | 
						|
 | 
						|
  ColorSpace.singletons = {
 | 
						|
    get gray() {
 | 
						|
      return shadow(this, 'gray', new DeviceGrayCS());
 | 
						|
    },
 | 
						|
    get rgb() {
 | 
						|
      return shadow(this, 'rgb', new DeviceRgbCS());
 | 
						|
    },
 | 
						|
    get cmyk() {
 | 
						|
      return shadow(this, 'cmyk', new DeviceCmykCS());
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  return ColorSpace;
 | 
						|
})();
 | 
						|
 | 
						|
/**
 | 
						|
 * Alternate color space handles both Separation and DeviceN color spaces.  A
 | 
						|
 * Separation color space is actually just a DeviceN with one color component.
 | 
						|
 * Both color spaces use a tinting function to convert colors to a base color
 | 
						|
 * space.
 | 
						|
 */
 | 
						|
var AlternateCS = (function AlternateCSClosure() {
 | 
						|
  function AlternateCS(numComps, base, tintFn) {
 | 
						|
    this.name = 'Alternate';
 | 
						|
    this.numComps = numComps;
 | 
						|
    this.defaultColor = new Float32Array(numComps);
 | 
						|
    for (var i = 0; i < numComps; ++i) {
 | 
						|
      this.defaultColor[i] = 1;
 | 
						|
    }
 | 
						|
    this.base = base;
 | 
						|
    this.tintFn = tintFn;
 | 
						|
  }
 | 
						|
 | 
						|
  AlternateCS.prototype = {
 | 
						|
    getRgb: function AlternateCS_getRgb(src, srcOffset) {
 | 
						|
      var rgb = new Uint8Array(3);
 | 
						|
      this.getRgbItem(src, srcOffset, rgb, 0);
 | 
						|
      return rgb;
 | 
						|
    },
 | 
						|
    getRgbItem: function AlternateCS_getRgbItem(src, srcOffset,
 | 
						|
                                                dest, destOffset) {
 | 
						|
      var baseNumComps = this.base.numComps;
 | 
						|
      var input = 'subarray' in src ?
 | 
						|
        src.subarray(srcOffset, srcOffset + this.numComps) :
 | 
						|
        Array.prototype.slice.call(src, srcOffset, srcOffset + this.numComps);
 | 
						|
      var tinted = this.tintFn(input);
 | 
						|
      this.base.getRgbItem(tinted, 0, dest, destOffset);
 | 
						|
    },
 | 
						|
    getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count,
 | 
						|
                                                    dest, destOffset, bits) {
 | 
						|
      var tintFn = this.tintFn;
 | 
						|
      var base = this.base;
 | 
						|
      var scale = 1 / ((1 << bits) - 1);
 | 
						|
      var baseNumComps = base.numComps;
 | 
						|
      var usesZeroToOneRange = base.usesZeroToOneRange;
 | 
						|
      var isPassthrough = base.isPassthrough(8) || !usesZeroToOneRange;
 | 
						|
      var pos = isPassthrough ? destOffset : 0;
 | 
						|
      var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count);
 | 
						|
      var numComps = this.numComps;
 | 
						|
 | 
						|
      var scaled = new Float32Array(numComps);
 | 
						|
      for (var i = 0; i < count; i++) {
 | 
						|
        for (var j = 0; j < numComps; j++) {
 | 
						|
          scaled[j] = src[srcOffset++] * scale;
 | 
						|
        }
 | 
						|
        var tinted = tintFn(scaled);
 | 
						|
        if (usesZeroToOneRange) {
 | 
						|
          for (var j = 0; j < baseNumComps; j++) {
 | 
						|
            baseBuf[pos++] = tinted[j] * 255;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          base.getRgbItem(tinted, 0, baseBuf, pos);
 | 
						|
          pos += baseNumComps;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (!isPassthrough) {
 | 
						|
        base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8);
 | 
						|
      }
 | 
						|
    },
 | 
						|
    getOutputLength: function AlternateCS_getOutputLength(inputLength) {
 | 
						|
      return this.base.getOutputLength(inputLength *
 | 
						|
                                       this.base.numComps / this.numComps);
 | 
						|
    },
 | 
						|
    isPassthrough: ColorSpace.prototype.isPassthrough,
 | 
						|
    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
 | 
						|
    isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) {
 | 
						|
      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
 | 
						|
    },
 | 
						|
    usesZeroToOneRange: true
 | 
						|
  };
 | 
						|
 | 
						|
  return AlternateCS;
 | 
						|
})();
 | 
						|
 | 
						|
var PatternCS = (function PatternCSClosure() {
 | 
						|
  function PatternCS(baseCS) {
 | 
						|
    this.name = 'Pattern';
 | 
						|
    this.base = baseCS;
 | 
						|
  }
 | 
						|
  PatternCS.prototype = {};
 | 
						|
 | 
						|
  return PatternCS;
 | 
						|
})();
 | 
						|
 | 
						|
var IndexedCS = (function IndexedCSClosure() {
 | 
						|
  function IndexedCS(base, highVal, lookup) {
 | 
						|
    this.name = 'Indexed';
 | 
						|
    this.numComps = 1;
 | 
						|
    this.defaultColor = new Uint8Array([0]);
 | 
						|
    this.base = base;
 | 
						|
    this.highVal = highVal;
 | 
						|
 | 
						|
    var baseNumComps = base.numComps;
 | 
						|
    var length = baseNumComps * highVal;
 | 
						|
    var lookupArray;
 | 
						|
 | 
						|
    if (isStream(lookup)) {
 | 
						|
      lookupArray = new Uint8Array(length);
 | 
						|
      var bytes = lookup.getBytes(length);
 | 
						|
      lookupArray.set(bytes);
 | 
						|
    } else if (isString(lookup)) {
 | 
						|
      lookupArray = new Uint8Array(length);
 | 
						|
      for (var i = 0; i < length; ++i)
 | 
						|
        lookupArray[i] = lookup.charCodeAt(i);
 | 
						|
    } else if (lookup instanceof Uint8Array || lookup instanceof Array) {
 | 
						|
      lookupArray = lookup;
 | 
						|
    } else {
 | 
						|
      error('Unrecognized lookup table: ' + lookup);
 | 
						|
    }
 | 
						|
    this.lookup = lookupArray;
 | 
						|
  }
 | 
						|
 | 
						|
  IndexedCS.prototype = {
 | 
						|
    getRgb: function IndexedCS_getRgb(src, srcOffset) {
 | 
						|
      var numComps = this.base.numComps;
 | 
						|
      var start = src[srcOffset] * numComps;
 | 
						|
      return this.base.getRgb(this.lookup, start);
 | 
						|
    },
 | 
						|
    getRgbItem: function IndexedCS_getRgbItem(src, srcOffset,
 | 
						|
                                              dest, destOffset) {
 | 
						|
      var numComps = this.base.numComps;
 | 
						|
      var start = src[srcOffset] * numComps;
 | 
						|
      this.base.getRgbItem(this.lookup, start, dest, destOffset);
 | 
						|
    },
 | 
						|
    getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count,
 | 
						|
                                                  dest, destOffset) {
 | 
						|
      var base = this.base;
 | 
						|
      var numComps = base.numComps;
 | 
						|
      var outputDelta = base.getOutputLength(numComps);
 | 
						|
      var lookup = this.lookup;
 | 
						|
 | 
						|
      for (var i = 0; i < count; ++i) {
 | 
						|
        var lookupPos = src[srcOffset++] * numComps;
 | 
						|
        base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8);
 | 
						|
        destOffset += outputDelta;
 | 
						|
      }
 | 
						|
    },
 | 
						|
    getOutputLength: function IndexedCS_getOutputLength(inputLength) {
 | 
						|
      return this.base.getOutputLength(inputLength * this.base.numComps);
 | 
						|
    },
 | 
						|
    isPassthrough: ColorSpace.prototype.isPassthrough,
 | 
						|
    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
 | 
						|
    isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) {
 | 
						|
      // indexed color maps shouldn't be changed
 | 
						|
      return true;
 | 
						|
    },
 | 
						|
    usesZeroToOneRange: true
 | 
						|
  };
 | 
						|
  return IndexedCS;
 | 
						|
})();
 | 
						|
 | 
						|
var DeviceGrayCS = (function DeviceGrayCSClosure() {
 | 
						|
  function DeviceGrayCS() {
 | 
						|
    this.name = 'DeviceGray';
 | 
						|
    this.numComps = 1;
 | 
						|
    this.defaultColor = new Float32Array([0]);
 | 
						|
  }
 | 
						|
 | 
						|
  DeviceGrayCS.prototype = {
 | 
						|
    getRgb: function DeviceGrayCS_getRgb(src, srcOffset) {
 | 
						|
      var rgb = new Uint8Array(3);
 | 
						|
      this.getRgbItem(src, srcOffset, rgb, 0);
 | 
						|
      return rgb;
 | 
						|
    },
 | 
						|
    getRgbItem: function DeviceGrayCS_getRgbItem(src, srcOffset,
 | 
						|
                                                 dest, destOffset) {
 | 
						|
      var c = (src[srcOffset] * 255) | 0;
 | 
						|
      c = c < 0 ? 0 : c > 255 ? 255 : c;
 | 
						|
      dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c;
 | 
						|
    },
 | 
						|
    getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count,
 | 
						|
                                                     dest, destOffset, bits) {
 | 
						|
      var scale = 255 / ((1 << bits) - 1);
 | 
						|
      var j = srcOffset, q = destOffset;
 | 
						|
      for (var i = 0; i < count; ++i) {
 | 
						|
        var c = (scale * src[j++]) | 0;
 | 
						|
        dest[q++] = c;
 | 
						|
        dest[q++] = c;
 | 
						|
        dest[q++] = c;
 | 
						|
      }
 | 
						|
    },
 | 
						|
    getOutputLength: function DeviceGrayCS_getOutputLength(inputLength) {
 | 
						|
      return inputLength * 3;
 | 
						|
    },
 | 
						|
    isPassthrough: ColorSpace.prototype.isPassthrough,
 | 
						|
    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
 | 
						|
    isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) {
 | 
						|
      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
 | 
						|
    },
 | 
						|
    usesZeroToOneRange: true
 | 
						|
  };
 | 
						|
  return DeviceGrayCS;
 | 
						|
})();
 | 
						|
 | 
						|
var DeviceRgbCS = (function DeviceRgbCSClosure() {
 | 
						|
  function DeviceRgbCS() {
 | 
						|
    this.name = 'DeviceRGB';
 | 
						|
    this.numComps = 3;
 | 
						|
    this.defaultColor = new Float32Array([0, 0, 0]);
 | 
						|
  }
 | 
						|
  DeviceRgbCS.prototype = {
 | 
						|
    getRgb: function DeviceRgbCS_getRgb(src, srcOffset) {
 | 
						|
      var rgb = new Uint8Array(3);
 | 
						|
      this.getRgbItem(src, srcOffset, rgb, 0);
 | 
						|
      return rgb;
 | 
						|
    },
 | 
						|
    getRgbItem: function DeviceRgbCS_getRgbItem(src, srcOffset,
 | 
						|
                                                dest, destOffset) {
 | 
						|
      var r = (src[srcOffset] * 255) | 0;
 | 
						|
      var g = (src[srcOffset + 1] * 255) | 0;
 | 
						|
      var b = (src[srcOffset + 2] * 255) | 0;
 | 
						|
      dest[destOffset] = r < 0 ? 0 : r > 255 ? 255 : r;
 | 
						|
      dest[destOffset + 1] = g < 0 ? 0 : g > 255 ? 255 : g;
 | 
						|
      dest[destOffset + 2] = b < 0 ? 0 : b > 255 ? 255 : b;
 | 
						|
    },
 | 
						|
    getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count,
 | 
						|
                                                    dest, destOffset, bits) {
 | 
						|
      var length = count * 3;
 | 
						|
      if (bits == 8) {
 | 
						|
        dest.set(src.subarray(srcOffset, srcOffset + length), destOffset);
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      var scale = 255 / ((1 << bits) - 1);
 | 
						|
      var j = srcOffset, q = destOffset;
 | 
						|
      for (var i = 0; i < length; ++i) {
 | 
						|
        dest[q++] = (scale * src[j++]) | 0;
 | 
						|
      }
 | 
						|
    },
 | 
						|
    getOutputLength: function DeviceRgbCS_getOutputLength(inputLength) {
 | 
						|
      return inputLength;
 | 
						|
    },
 | 
						|
    isPassthrough: function DeviceRgbCS_isPassthrough(bits) {
 | 
						|
      return bits == 8;
 | 
						|
    },
 | 
						|
    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
 | 
						|
    isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) {
 | 
						|
      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
 | 
						|
    },
 | 
						|
    usesZeroToOneRange: true
 | 
						|
  };
 | 
						|
  return DeviceRgbCS;
 | 
						|
})();
 | 
						|
 | 
						|
var DeviceCmykCS = (function DeviceCmykCSClosure() {
 | 
						|
  // The coefficients below was found using numerical analysis: the method of
 | 
						|
  // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
 | 
						|
  // where color_value is the tabular value from the table of sampled RGB colors
 | 
						|
  // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
 | 
						|
  // CMYK color conversion using the estimation below:
 | 
						|
  //   f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
 | 
						|
  function convertToRgb(src, srcOffset, srcScale, dest, destOffset) {
 | 
						|
    var c = src[srcOffset + 0] * srcScale;
 | 
						|
    var m = src[srcOffset + 1] * srcScale;
 | 
						|
    var y = src[srcOffset + 2] * srcScale;
 | 
						|
    var k = src[srcOffset + 3] * srcScale;
 | 
						|
 | 
						|
    var r =
 | 
						|
      c * (-4.387332384609988 * c + 54.48615194189176 * m +
 | 
						|
           18.82290502165302 * y + 212.25662451639585 * k +
 | 
						|
           -285.2331026137004) +
 | 
						|
      m * (1.7149763477362134 * m - 5.6096736904047315 * y +
 | 
						|
           -17.873870861415444 * k - 5.497006427196366) +
 | 
						|
      y * (-2.5217340131683033 * y - 21.248923337353073 * k +
 | 
						|
           17.5119270841813) +
 | 
						|
      k * (-21.86122147463605 * k - 189.48180835922747) + 255;
 | 
						|
    var g =
 | 
						|
      c * (8.841041422036149 * c + 60.118027045597366 * m +
 | 
						|
           6.871425592049007 * y + 31.159100130055922 * k +
 | 
						|
           -79.2970844816548) +
 | 
						|
      m * (-15.310361306967817 * m + 17.575251261109482 * y +
 | 
						|
           131.35250912493976 * k - 190.9453302588951) +
 | 
						|
      y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) +
 | 
						|
      k * (-20.737325471181034 * k - 187.80453709719578) + 255;
 | 
						|
    var b =
 | 
						|
      c * (0.8842522430003296 * c + 8.078677503112928 * m +
 | 
						|
           30.89978309703729 * y - 0.23883238689178934 * k +
 | 
						|
           -14.183576799673286) +
 | 
						|
      m * (10.49593273432072 * m + 63.02378494754052 * y +
 | 
						|
           50.606957656360734 * k - 112.23884253719248) +
 | 
						|
      y * (0.03296041114873217 * y + 115.60384449646641 * k +
 | 
						|
           -193.58209356861505) +
 | 
						|
      k * (-22.33816807309886 * k - 180.12613974708367) + 255;
 | 
						|
 | 
						|
    dest[destOffset] = r > 255 ? 255 : r < 0 ? 0 : r;
 | 
						|
    dest[destOffset + 1] = g > 255 ? 255 : g < 0 ? 0 : g;
 | 
						|
    dest[destOffset + 2] = b > 255 ? 255 : b < 0 ? 0 : b;
 | 
						|
  }
 | 
						|
 | 
						|
  function DeviceCmykCS() {
 | 
						|
    this.name = 'DeviceCMYK';
 | 
						|
    this.numComps = 4;
 | 
						|
    this.defaultColor = new Float32Array([0, 0, 0, 1]);
 | 
						|
  }
 | 
						|
  DeviceCmykCS.prototype = {
 | 
						|
    getRgb: function DeviceCmykCS_getRgb(src, srcOffset) {
 | 
						|
      var rgb = new Uint8Array(3);
 | 
						|
      convertToRgb(src, srcOffset, 1, rgb, 0);
 | 
						|
      return rgb;
 | 
						|
    },
 | 
						|
    getRgbItem: function DeviceCmykCS_getRgbItem(src, srcOffset,
 | 
						|
                                                 dest, destOffset) {
 | 
						|
      convertToRgb(src, srcOffset, 1, dest, destOffset);
 | 
						|
    },
 | 
						|
    getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count,
 | 
						|
                                                     dest, destOffset, bits) {
 | 
						|
      var scale = 1 / ((1 << bits) - 1);
 | 
						|
      for (var i = 0; i < count; i++) {
 | 
						|
        convertToRgb(src, srcOffset, scale, dest, destOffset);
 | 
						|
        srcOffset += 4;
 | 
						|
        destOffset += 3;
 | 
						|
      }
 | 
						|
    },
 | 
						|
    getOutputLength: function DeviceCmykCS_getOutputLength(inputLength) {
 | 
						|
      return (inputLength >> 2) * 3;
 | 
						|
    },
 | 
						|
    isPassthrough: ColorSpace.prototype.isPassthrough,
 | 
						|
    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
 | 
						|
    isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) {
 | 
						|
      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
 | 
						|
    },
 | 
						|
    usesZeroToOneRange: true
 | 
						|
  };
 | 
						|
 | 
						|
  return DeviceCmykCS;
 | 
						|
})();
 | 
						|
 | 
						|
//
 | 
						|
// CalGrayCS: Based on "PDF Reference, Sixth Ed", p.245
 | 
						|
//
 | 
						|
var CalGrayCS = (function CalGrayCSClosure() {
 | 
						|
  function CalGrayCS(whitePoint, blackPoint, gamma) {
 | 
						|
    this.name = 'CalGray';
 | 
						|
    this.numComps = 3;
 | 
						|
    this.defaultColor = new Float32Array([0, 0, 0]);
 | 
						|
 | 
						|
    if (!whitePoint) {
 | 
						|
      error('WhitePoint missing - required for color space CalGray');
 | 
						|
    }
 | 
						|
    blackPoint = blackPoint || [0, 0, 0];
 | 
						|
    gamma = gamma || 1;
 | 
						|
 | 
						|
    // Translate arguments to spec variables.
 | 
						|
    this.XW = whitePoint[0];
 | 
						|
    this.YW = whitePoint[1];
 | 
						|
    this.ZW = whitePoint[2];
 | 
						|
 | 
						|
    this.XB = blackPoint[0];
 | 
						|
    this.YB = blackPoint[1];
 | 
						|
    this.ZB = blackPoint[2];
 | 
						|
 | 
						|
    this.G = gamma;
 | 
						|
 | 
						|
    // Validate variables as per spec.
 | 
						|
    if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
 | 
						|
      error('Invalid WhitePoint components for ' + this.name +
 | 
						|
            ', no fallback available');
 | 
						|
    }
 | 
						|
 | 
						|
    if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
 | 
						|
      info('Invalid BlackPoint for ' + this.name + ', falling back to default');
 | 
						|
      this.XB = this.YB = this.ZB = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
 | 
						|
      TODO(this.name + ', BlackPoint: XB: ' + this.XB + ', YB: ' + this.YB +
 | 
						|
           ', ZB: ' + this.ZB + ', only default values are supported.');
 | 
						|
    }
 | 
						|
 | 
						|
    if (this.G < 1) {
 | 
						|
      info('Invalid Gamma: ' + this.G + ' for ' + this.name +
 | 
						|
           ', falling back to default');
 | 
						|
      this.G = 1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  CalGrayCS.prototype = {
 | 
						|
    getRgb: function CalGrayCS_getRgb(src, srcOffset) {
 | 
						|
      var rgb = new Uint8Array(3);
 | 
						|
      this.getRgbItem(src, srcOffset, rgb, 0);
 | 
						|
      return rgb;
 | 
						|
    },
 | 
						|
    getRgbItem: function CalGrayCS_getRgbItem(src, srcOffset,
 | 
						|
                                              dest, destOffset) {
 | 
						|
      // A represents a gray component of a calibrated gray space.
 | 
						|
      // A <---> AG in the spec
 | 
						|
      var A = src[srcOffset];
 | 
						|
      var AG = Math.pow(A, this.G);
 | 
						|
 | 
						|
      // Computes intermediate variables M, L, N as per spec.
 | 
						|
      // Except if other than default BlackPoint values are used.
 | 
						|
      var M = this.XW * AG;
 | 
						|
      var L = this.YW * AG;
 | 
						|
      var N = this.ZW * AG;
 | 
						|
 | 
						|
      // Decode XYZ, as per spec.
 | 
						|
      var X = M;
 | 
						|
      var Y = L;
 | 
						|
      var Z = N;
 | 
						|
 | 
						|
      // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html, Ch 4.
 | 
						|
      // This yields values in range [0, 100].
 | 
						|
      var Lstar = Math.max(116 * Math.pow(Y, 1 / 3) - 16, 0);
 | 
						|
 | 
						|
      // Convert values to rgb range [0, 255].
 | 
						|
      dest[destOffset] = Lstar * 255 / 100;
 | 
						|
      dest[destOffset + 1] = Lstar * 255 / 100;
 | 
						|
      dest[destOffset + 2] = Lstar * 255 / 100;
 | 
						|
    },
 | 
						|
    getRgbBuffer: function CalGrayCS_getRgbBuffer(src, srcOffset, count,
 | 
						|
                                                  dest, destOffset, bits) {
 | 
						|
      // TODO: This part is copied from DeviceGray. Make this utility function.
 | 
						|
      var scale = 255 / ((1 << bits) - 1);
 | 
						|
      var j = srcOffset, q = destOffset;
 | 
						|
      for (var i = 0; i < count; ++i) {
 | 
						|
        var c = (scale * src[j++]) | 0;
 | 
						|
        dest[q++] = c;
 | 
						|
        dest[q++] = c;
 | 
						|
        dest[q++] = c;
 | 
						|
      }
 | 
						|
    },
 | 
						|
    getOutputLength: function CalGrayCS_getOutputLength(inputLength) {
 | 
						|
      return inputLength * 3;
 | 
						|
    },
 | 
						|
    isPassthrough: ColorSpace.prototype.isPassthrough,
 | 
						|
    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
 | 
						|
    isDefaultDecode: function CalGrayCS_isDefaultDecode(decodeMap) {
 | 
						|
      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
 | 
						|
    },
 | 
						|
    usesZeroToOneRange: true
 | 
						|
  };
 | 
						|
  return CalGrayCS;
 | 
						|
})();
 | 
						|
 | 
						|
//
 | 
						|
// LabCS: Based on "PDF Reference, Sixth Ed", p.250
 | 
						|
//
 | 
						|
var LabCS = (function LabCSClosure() {
 | 
						|
  function LabCS(whitePoint, blackPoint, range) {
 | 
						|
    this.name = 'Lab';
 | 
						|
    this.numComps = 3;
 | 
						|
    this.defaultColor = new Float32Array([0, 0, 0]);
 | 
						|
 | 
						|
    if (!whitePoint)
 | 
						|
      error('WhitePoint missing - required for color space Lab');
 | 
						|
    blackPoint = blackPoint || [0, 0, 0];
 | 
						|
    range = range || [-100, 100, -100, 100];
 | 
						|
 | 
						|
    // Translate args to spec variables
 | 
						|
    this.XW = whitePoint[0];
 | 
						|
    this.YW = whitePoint[1];
 | 
						|
    this.ZW = whitePoint[2];
 | 
						|
    this.amin = range[0];
 | 
						|
    this.amax = range[1];
 | 
						|
    this.bmin = range[2];
 | 
						|
    this.bmax = range[3];
 | 
						|
 | 
						|
    // These are here just for completeness - the spec doesn't offer any
 | 
						|
    // formulas that use BlackPoint in Lab
 | 
						|
    this.XB = blackPoint[0];
 | 
						|
    this.YB = blackPoint[1];
 | 
						|
    this.ZB = blackPoint[2];
 | 
						|
 | 
						|
    // Validate vars as per spec
 | 
						|
    if (this.XW < 0 || this.ZW < 0 || this.YW !== 1)
 | 
						|
      error('Invalid WhitePoint components, no fallback available');
 | 
						|
 | 
						|
    if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
 | 
						|
      info('Invalid BlackPoint, falling back to default');
 | 
						|
      this.XB = this.YB = this.ZB = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if (this.amin > this.amax || this.bmin > this.bmax) {
 | 
						|
      info('Invalid Range, falling back to defaults');
 | 
						|
      this.amin = -100;
 | 
						|
      this.amax = 100;
 | 
						|
      this.bmin = -100;
 | 
						|
      this.bmax = 100;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Function g(x) from spec
 | 
						|
  function fn_g(x) {
 | 
						|
    if (x >= 6 / 29)
 | 
						|
      return x * x * x;
 | 
						|
    else
 | 
						|
      return (108 / 841) * (x - 4 / 29);
 | 
						|
  }
 | 
						|
 | 
						|
  function decode(value, high1, low2, high2) {
 | 
						|
    return low2 + (value) * (high2 - low2) / (high1);
 | 
						|
  }
 | 
						|
 | 
						|
  // If decoding is needed maxVal should be 2^bits per component - 1.
 | 
						|
  function convertToRgb(cs, src, srcOffset, maxVal, dest, destOffset) {
 | 
						|
    // XXX: Lab input is in the range of [0, 100], [amin, amax], [bmin, bmax]
 | 
						|
    // not the usual [0, 1]. If a command like setFillColor is used the src
 | 
						|
    // values will already be within the correct range. However, if we are
 | 
						|
    // converting an image we have to map the values to the correct range given
 | 
						|
    // above.
 | 
						|
    // Ls,as,bs <---> L*,a*,b* in the spec
 | 
						|
    var Ls = src[srcOffset];
 | 
						|
    var as = src[srcOffset + 1];
 | 
						|
    var bs = src[srcOffset + 2];
 | 
						|
    if (maxVal !== false) {
 | 
						|
      Ls = decode(Ls, maxVal, 0, 100);
 | 
						|
      as = decode(as, maxVal, cs.amin, cs.amax);
 | 
						|
      bs = decode(bs, maxVal, cs.bmin, cs.bmax);
 | 
						|
    }
 | 
						|
 | 
						|
    // Adjust limits of 'as' and 'bs'
 | 
						|
    as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as;
 | 
						|
    bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs;
 | 
						|
 | 
						|
    // Computes intermediate variables X,Y,Z as per spec
 | 
						|
    var M = (Ls + 16) / 116;
 | 
						|
    var L = M + (as / 500);
 | 
						|
    var N = M - (bs / 200);
 | 
						|
 | 
						|
    var X = cs.XW * fn_g(L);
 | 
						|
    var Y = cs.YW * fn_g(M);
 | 
						|
    var Z = cs.ZW * fn_g(N);
 | 
						|
 | 
						|
    var r, g, b;
 | 
						|
    // Using different conversions for D50 and D65 white points,
 | 
						|
    // per http://www.color.org/srgb.pdf
 | 
						|
    if (cs.ZW < 1) {
 | 
						|
      // Assuming D50 (X=0.9642, Y=1.00, Z=0.8249)
 | 
						|
      r = X * 3.1339 + Y * -1.6170 + Z * -0.4906;
 | 
						|
      g = X * -0.9785 + Y * 1.9160 + Z * 0.0333;
 | 
						|
      b = X * 0.0720 + Y * -0.2290 + Z * 1.4057;
 | 
						|
    } else {
 | 
						|
      // Assuming D65 (X=0.9505, Y=1.00, Z=1.0888)
 | 
						|
      r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
 | 
						|
      g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
 | 
						|
      b = X * 0.0557 + Y * -0.2040 + Z * 1.0570;
 | 
						|
    }
 | 
						|
    // clamp color values to [0,1] range then convert to [0,255] range.
 | 
						|
    dest[destOffset] = Math.sqrt(r < 0 ? 0 : r > 1 ? 1 : r) * 255;
 | 
						|
    dest[destOffset + 1] = Math.sqrt(g < 0 ? 0 : g > 1 ? 1 : g) * 255;
 | 
						|
    dest[destOffset + 2] = Math.sqrt(b < 0 ? 0 : b > 1 ? 1 : b) * 255;
 | 
						|
  }
 | 
						|
 | 
						|
  LabCS.prototype = {
 | 
						|
    getRgb: function LabCS_getRgb(src, srcOffset) {
 | 
						|
      var rgb = new Uint8Array(3);
 | 
						|
      convertToRgb(this, src, srcOffset, false, rgb, 0);
 | 
						|
      return rgb;
 | 
						|
    },
 | 
						|
    getRgbItem: function LabCS_getRgbItem(src, srcOffset, dest, destOffset) {
 | 
						|
      convertToRgb(this, src, srcOffset, false, dest, destOffset);
 | 
						|
    },
 | 
						|
    getRgbBuffer: function LabCS_getRgbBuffer(src, srcOffset, count,
 | 
						|
                                              dest, destOffset, bits) {
 | 
						|
      var maxVal = (1 << bits) - 1;
 | 
						|
      for (var i = 0; i < count; i++) {
 | 
						|
        convertToRgb(this, src, srcOffset, maxVal, dest, destOffset);
 | 
						|
        srcOffset += 3;
 | 
						|
        destOffset += 3;
 | 
						|
      }
 | 
						|
    },
 | 
						|
    getOutputLength: function LabCS_getOutputLength(inputLength) {
 | 
						|
      return inputLength;
 | 
						|
    },
 | 
						|
    isPassthrough: ColorSpace.prototype.isPassthrough,
 | 
						|
    isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) {
 | 
						|
      // XXX: Decoding is handled with the lab conversion because of the strange
 | 
						|
      // ranges that are used.
 | 
						|
      return true;
 | 
						|
    },
 | 
						|
    usesZeroToOneRange: false
 | 
						|
  };
 | 
						|
  return LabCS;
 | 
						|
})();
 | 
						|
 | 
						|
 | 
						|
 | 
						|
var PatternType = {
 | 
						|
  AXIAL: 2,
 | 
						|
  RADIAL: 3
 | 
						|
};
 | 
						|
 | 
						|
var Pattern = (function PatternClosure() {
 | 
						|
  // Constructor should define this.getPattern
 | 
						|
  function Pattern() {
 | 
						|
    error('should not call Pattern constructor');
 | 
						|
  }
 | 
						|
 | 
						|
  Pattern.prototype = {
 | 
						|
    // Input: current Canvas context
 | 
						|
    // Output: the appropriate fillStyle or strokeStyle
 | 
						|
    getPattern: function Pattern_getPattern(ctx) {
 | 
						|
      error('Should not call Pattern.getStyle: ' + ctx);
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  Pattern.shadingFromIR = function Pattern_shadingFromIR(raw) {
 | 
						|
    return Shadings[raw[0]].fromIR(raw);
 | 
						|
  };
 | 
						|
 | 
						|
  Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref,
 | 
						|
                                                       res) {
 | 
						|
 | 
						|
    var dict = isStream(shading) ? shading.dict : shading;
 | 
						|
    var type = dict.get('ShadingType');
 | 
						|
 | 
						|
    switch (type) {
 | 
						|
      case PatternType.AXIAL:
 | 
						|
      case PatternType.RADIAL:
 | 
						|
        // Both radial and axial shadings are handled by RadialAxial shading.
 | 
						|
        return new Shadings.RadialAxial(dict, matrix, xref, res);
 | 
						|
      default:
 | 
						|
        TODO('Unsupported shading type: ' + type);
 | 
						|
        return new Shadings.Dummy();
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return Pattern;
 | 
						|
})();
 | 
						|
 | 
						|
var Shadings = {};
 | 
						|
 | 
						|
// A small number to offset the first/last color stops so we can insert ones to
 | 
						|
// support extend.  Number.MIN_VALUE appears to be too small and breaks the
 | 
						|
// extend. 1e-7 works in FF but chrome seems to use an even smaller sized number
 | 
						|
// internally so we have to go bigger.
 | 
						|
Shadings.SMALL_NUMBER = 1e-2;
 | 
						|
 | 
						|
// Radial and axial shading have very similar implementations
 | 
						|
// If needed, the implementations can be broken into two classes
 | 
						|
Shadings.RadialAxial = (function RadialAxialClosure() {
 | 
						|
  function RadialAxial(dict, matrix, xref, res, ctx) {
 | 
						|
    this.matrix = matrix;
 | 
						|
    this.coordsArr = dict.get('Coords');
 | 
						|
    this.shadingType = dict.get('ShadingType');
 | 
						|
    this.type = 'Pattern';
 | 
						|
    this.ctx = ctx;
 | 
						|
    var cs = dict.get('ColorSpace', 'CS');
 | 
						|
    cs = ColorSpace.parse(cs, xref, res);
 | 
						|
    this.cs = cs;
 | 
						|
 | 
						|
    var t0 = 0.0, t1 = 1.0;
 | 
						|
    if (dict.has('Domain')) {
 | 
						|
      var domainArr = dict.get('Domain');
 | 
						|
      t0 = domainArr[0];
 | 
						|
      t1 = domainArr[1];
 | 
						|
    }
 | 
						|
 | 
						|
    var extendStart = false, extendEnd = false;
 | 
						|
    if (dict.has('Extend')) {
 | 
						|
      var extendArr = dict.get('Extend');
 | 
						|
      extendStart = extendArr[0];
 | 
						|
      extendEnd = extendArr[1];
 | 
						|
    }
 | 
						|
 | 
						|
    if (this.shadingType === PatternType.RADIAL &&
 | 
						|
       (!extendStart || !extendEnd)) {
 | 
						|
      // Radial gradient only currently works if either circle is fully within
 | 
						|
      // the other circle.
 | 
						|
      var x1 = this.coordsArr[0];
 | 
						|
      var y1 = this.coordsArr[1];
 | 
						|
      var r1 = this.coordsArr[2];
 | 
						|
      var x2 = this.coordsArr[3];
 | 
						|
      var y2 = this.coordsArr[4];
 | 
						|
      var r2 = this.coordsArr[5];
 | 
						|
      var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
 | 
						|
      if (r1 <= r2 + distance &&
 | 
						|
          r2 <= r1 + distance) {
 | 
						|
        warn('Unsupported radial gradient.');
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    this.extendStart = extendStart;
 | 
						|
    this.extendEnd = extendEnd;
 | 
						|
 | 
						|
    var fnObj = dict.get('Function');
 | 
						|
    var fn;
 | 
						|
    if (isArray(fnObj)) {
 | 
						|
      var fnArray = [];
 | 
						|
      for (var j = 0, jj = fnObj.length; j < jj; j++) {
 | 
						|
        var obj = xref.fetchIfRef(fnObj[j]);
 | 
						|
        if (!isPDFFunction(obj)) {
 | 
						|
          error('Invalid function');
 | 
						|
        }
 | 
						|
        fnArray.push(PDFFunction.parse(xref, obj));
 | 
						|
      }
 | 
						|
      fn = function radialAxialColorFunction(arg) {
 | 
						|
        var out = [];
 | 
						|
        for (var i = 0, ii = fnArray.length; i < ii; i++) {
 | 
						|
          out.push(fnArray[i](arg)[0]);
 | 
						|
        }
 | 
						|
        return out;
 | 
						|
      };
 | 
						|
    } else {
 | 
						|
      if (!isPDFFunction(fnObj)) {
 | 
						|
        error('Invalid function');
 | 
						|
      }
 | 
						|
      fn = PDFFunction.parse(xref, fnObj);
 | 
						|
    }
 | 
						|
 | 
						|
    // 10 samples seems good enough for now, but probably won't work
 | 
						|
    // if there are sharp color changes. Ideally, we would implement
 | 
						|
    // the spec faithfully and add lossless optimizations.
 | 
						|
    var diff = t1 - t0;
 | 
						|
    var step = diff / 10;
 | 
						|
 | 
						|
    var colorStops = this.colorStops = [];
 | 
						|
 | 
						|
    // Protect against bad domains so we don't end up in an infinte loop below.
 | 
						|
    if (t0 >= t1 || step <= 0) {
 | 
						|
      // Acrobat doesn't seem to handle these cases so we'll ignore for
 | 
						|
      // now.
 | 
						|
      info('Bad shading domain.');
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    for (var i = t0; i <= t1; i += step) {
 | 
						|
      var rgbColor = cs.getRgb(fn([i]), 0);
 | 
						|
      var cssColor = Util.makeCssRgb(rgbColor);
 | 
						|
      colorStops.push([(i - t0) / diff, cssColor]);
 | 
						|
    }
 | 
						|
 | 
						|
    var background = 'transparent';
 | 
						|
    if (dict.has('Background')) {
 | 
						|
      var rgbColor = cs.getRgb(dict.get('Background'), 0);
 | 
						|
      background = Util.makeCssRgb(rgbColor);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!extendStart) {
 | 
						|
      // Insert a color stop at the front and offset the first real color stop
 | 
						|
      // so it doesn't conflict with the one we insert.
 | 
						|
      colorStops.unshift([0, background]);
 | 
						|
      colorStops[1][0] += Shadings.SMALL_NUMBER;
 | 
						|
    }
 | 
						|
    if (!extendEnd) {
 | 
						|
      // Same idea as above in extendStart but for the end.
 | 
						|
      colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER;
 | 
						|
      colorStops.push([1, background]);
 | 
						|
    }
 | 
						|
 | 
						|
    this.colorStops = colorStops;
 | 
						|
  }
 | 
						|
 | 
						|
  RadialAxial.fromIR = function RadialAxial_fromIR(raw) {
 | 
						|
    var type = raw[1];
 | 
						|
    var colorStops = raw[2];
 | 
						|
    var p0 = raw[3];
 | 
						|
    var p1 = raw[4];
 | 
						|
    var r0 = raw[5];
 | 
						|
    var r1 = raw[6];
 | 
						|
    return {
 | 
						|
      type: 'Pattern',
 | 
						|
      getPattern: function RadialAxial_getPattern(ctx) {
 | 
						|
        var grad;
 | 
						|
        if (type == PatternType.AXIAL)
 | 
						|
          grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
 | 
						|
        else if (type == PatternType.RADIAL)
 | 
						|
          grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
 | 
						|
 | 
						|
        for (var i = 0, ii = colorStops.length; i < ii; ++i) {
 | 
						|
          var c = colorStops[i];
 | 
						|
          grad.addColorStop(c[0], c[1]);
 | 
						|
        }
 | 
						|
        return grad;
 | 
						|
      }
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  RadialAxial.prototype = {
 | 
						|
    getIR: function RadialAxial_getIR() {
 | 
						|
      var coordsArr = this.coordsArr;
 | 
						|
      var type = this.shadingType;
 | 
						|
      if (type == PatternType.AXIAL) {
 | 
						|
        var p0 = [coordsArr[0], coordsArr[1]];
 | 
						|
        var p1 = [coordsArr[2], coordsArr[3]];
 | 
						|
        var r0 = null;
 | 
						|
        var r1 = null;
 | 
						|
      } else if (type == PatternType.RADIAL) {
 | 
						|
        var p0 = [coordsArr[0], coordsArr[1]];
 | 
						|
        var p1 = [coordsArr[3], coordsArr[4]];
 | 
						|
        var r0 = coordsArr[2];
 | 
						|
        var r1 = coordsArr[5];
 | 
						|
      } else {
 | 
						|
        error('getPattern type unknown: ' + type);
 | 
						|
      }
 | 
						|
 | 
						|
      var matrix = this.matrix;
 | 
						|
      if (matrix) {
 | 
						|
        p0 = Util.applyTransform(p0, matrix);
 | 
						|
        p1 = Util.applyTransform(p1, matrix);
 | 
						|
      }
 | 
						|
 | 
						|
      return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1];
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  return RadialAxial;
 | 
						|
})();
 | 
						|
 | 
						|
Shadings.Dummy = (function DummyClosure() {
 | 
						|
  function Dummy() {
 | 
						|
    this.type = 'Pattern';
 | 
						|
  }
 | 
						|
 | 
						|
  Dummy.fromIR = function Dummy_fromIR() {
 | 
						|
    return {
 | 
						|
      type: 'Pattern',
 | 
						|
      getPattern: function Dummy_fromIR_getPattern() {
 | 
						|
        return 'hotpink';
 | 
						|
      }
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  Dummy.prototype = {
 | 
						|
    getIR: function Dummy_getIR() {
 | 
						|
      return ['Dummy'];
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return Dummy;
 | 
						|
})();
 | 
						|
 | 
						|
var TilingPattern = (function TilingPatternClosure() {
 | 
						|
  var PaintType = {
 | 
						|
    COLORED: 1,
 | 
						|
    UNCOLORED: 2
 | 
						|
  };
 | 
						|
 | 
						|
  var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough
 | 
						|
 | 
						|
  function TilingPattern(IR, color, ctx, objs, commonObjs, baseTransform) {
 | 
						|
    this.name = IR[1][0].name;
 | 
						|
    this.operatorList = IR[2];
 | 
						|
    this.matrix = IR[3] || [1, 0, 0, 1, 0, 0];
 | 
						|
    this.bbox = IR[4];
 | 
						|
    this.xstep = IR[5];
 | 
						|
    this.ystep = IR[6];
 | 
						|
    this.paintType = IR[7];
 | 
						|
    this.tilingType = IR[8];
 | 
						|
    this.color = color;
 | 
						|
    this.objs = objs;
 | 
						|
    this.commonObjs = commonObjs;
 | 
						|
    this.baseTransform = baseTransform;
 | 
						|
    this.type = 'Pattern';
 | 
						|
    this.ctx = ctx;
 | 
						|
  }
 | 
						|
 | 
						|
  TilingPattern.getIR = function TilingPattern_getIR(operatorList, dict, args) {
 | 
						|
    var matrix = dict.get('Matrix');
 | 
						|
    var bbox = dict.get('BBox');
 | 
						|
    var xstep = dict.get('XStep');
 | 
						|
    var ystep = dict.get('YStep');
 | 
						|
    var paintType = dict.get('PaintType');
 | 
						|
    var tilingType = dict.get('TilingType');
 | 
						|
 | 
						|
    return [
 | 
						|
      'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep,
 | 
						|
      paintType, tilingType
 | 
						|
    ];
 | 
						|
  };
 | 
						|
 | 
						|
  TilingPattern.prototype = {
 | 
						|
    createPatternCanvas: function TilinPattern_createPatternCanvas(owner) {
 | 
						|
      var operatorList = this.operatorList;
 | 
						|
      var bbox = this.bbox;
 | 
						|
      var xstep = this.xstep;
 | 
						|
      var ystep = this.ystep;
 | 
						|
      var paintType = this.paintType;
 | 
						|
      var tilingType = this.tilingType;
 | 
						|
      var color = this.color;
 | 
						|
      var objs = this.objs;
 | 
						|
      var commonObjs = this.commonObjs;
 | 
						|
      var ctx = this.ctx;
 | 
						|
 | 
						|
      TODO('TilingType: ' + tilingType);
 | 
						|
 | 
						|
      var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3];
 | 
						|
 | 
						|
      var topLeft = [x0, y0];
 | 
						|
      // we want the canvas to be as large as the step size
 | 
						|
      var botRight = [x0 + xstep, y0 + ystep];
 | 
						|
 | 
						|
      var width = botRight[0] - topLeft[0];
 | 
						|
      var height = botRight[1] - topLeft[1];
 | 
						|
 | 
						|
      // Obtain scale from matrix and current transformation matrix.
 | 
						|
      var matrixScale = Util.singularValueDecompose2dScale(this.matrix);
 | 
						|
      var curMatrixScale = Util.singularValueDecompose2dScale(
 | 
						|
                             this.baseTransform);
 | 
						|
      var combinedScale = [matrixScale[0] * curMatrixScale[0],
 | 
						|
                           matrixScale[1] * curMatrixScale[1]];
 | 
						|
 | 
						|
      // MAX_PATTERN_SIZE is used to avoid OOM situation.
 | 
						|
      // Use width and height values that are as close as possible to the end
 | 
						|
      // result when the pattern is used. Too low value makes the pattern look
 | 
						|
      // blurry. Too large value makes it look too crispy.
 | 
						|
      width = Math.min(Math.ceil(Math.abs(width * combinedScale[0])),
 | 
						|
                       MAX_PATTERN_SIZE);
 | 
						|
 | 
						|
      height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])),
 | 
						|
                        MAX_PATTERN_SIZE);
 | 
						|
 | 
						|
      var tmpCanvas = CachedCanvases.getCanvas('pattern', width, height, true);
 | 
						|
      var tmpCtx = tmpCanvas.context;
 | 
						|
      var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs);
 | 
						|
      graphics.groupLevel = owner.groupLevel;
 | 
						|
 | 
						|
      this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color);
 | 
						|
 | 
						|
      this.setScale(width, height, xstep, ystep);
 | 
						|
      this.transformToScale(graphics);
 | 
						|
 | 
						|
      // transform coordinates to pattern space
 | 
						|
      var tmpTranslate = [1, 0, 0, 1, -topLeft[0], -topLeft[1]];
 | 
						|
      graphics.transform.apply(graphics, tmpTranslate);
 | 
						|
 | 
						|
      this.clipBbox(graphics, bbox, x0, y0, x1, y1);
 | 
						|
 | 
						|
      graphics.executeOperatorList(operatorList);
 | 
						|
      return tmpCanvas.canvas;
 | 
						|
    },
 | 
						|
 | 
						|
    setScale: function TilingPattern_setScale(width, height, xstep, ystep) {
 | 
						|
      this.scale = [width / xstep, height / ystep];
 | 
						|
    },
 | 
						|
 | 
						|
    transformToScale: function TilingPattern_transformToScale(graphics) {
 | 
						|
      var scale = this.scale;
 | 
						|
      var tmpScale = [scale[0], 0, 0, scale[1], 0, 0];
 | 
						|
      graphics.transform.apply(graphics, tmpScale);
 | 
						|
    },
 | 
						|
 | 
						|
    scaleToContext: function TilingPattern_scaleToContext() {
 | 
						|
      var scale = this.scale;
 | 
						|
      this.ctx.scale(1 / scale[0], 1 / scale[1]);
 | 
						|
    },
 | 
						|
 | 
						|
    clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
 | 
						|
      if (bbox && isArray(bbox) && 4 == bbox.length) {
 | 
						|
        var bboxWidth = x1 - x0;
 | 
						|
        var bboxHeight = y1 - y0;
 | 
						|
        graphics.rectangle(x0, y0, bboxWidth, bboxHeight);
 | 
						|
        graphics.clip();
 | 
						|
        graphics.endPath();
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    setFillAndStrokeStyleToContext:
 | 
						|
      function setFillAndStrokeStyleToContext(context, paintType, color) {
 | 
						|
      switch (paintType) {
 | 
						|
        case PaintType.COLORED:
 | 
						|
          var ctx = this.ctx;
 | 
						|
          context.fillStyle = ctx.fillStyle;
 | 
						|
          context.strokeStyle = ctx.strokeStyle;
 | 
						|
          break;
 | 
						|
        case PaintType.UNCOLORED:
 | 
						|
          var rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0);
 | 
						|
          var cssColor = Util.makeCssRgb(rgbColor);
 | 
						|
          context.fillStyle = cssColor;
 | 
						|
          context.strokeStyle = cssColor;
 | 
						|
          break;
 | 
						|
        default:
 | 
						|
          error('Unsupported paint type: ' + paintType);
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    getPattern: function TilingPattern_getPattern(ctx, owner) {
 | 
						|
      var temporaryPatternCanvas = this.createPatternCanvas(owner);
 | 
						|
 | 
						|
      var ctx = this.ctx;
 | 
						|
      ctx.setTransform.apply(ctx, this.baseTransform);
 | 
						|
      ctx.transform.apply(ctx, this.matrix);
 | 
						|
      this.scaleToContext();
 | 
						|
 | 
						|
      return ctx.createPattern(temporaryPatternCanvas, 'repeat');
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  return TilingPattern;
 | 
						|
})();
 | 
						|
 | 
						|
 | 
						|
 | 
						|
var PDFFunction = (function PDFFunctionClosure() {
 | 
						|
  var CONSTRUCT_SAMPLED = 0;
 | 
						|
  var CONSTRUCT_INTERPOLATED = 2;
 | 
						|
  var CONSTRUCT_STICHED = 3;
 | 
						|
  var CONSTRUCT_POSTSCRIPT = 4;
 | 
						|
 | 
						|
  return {
 | 
						|
    getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps,
 | 
						|
                                                       str) {
 | 
						|
      var length = 1;
 | 
						|
      for (var i = 0, ii = size.length; i < ii; i++)
 | 
						|
        length *= size[i];
 | 
						|
      length *= outputSize;
 | 
						|
 | 
						|
      var array = [];
 | 
						|
      var codeSize = 0;
 | 
						|
      var codeBuf = 0;
 | 
						|
      // 32 is a valid bps so shifting won't work
 | 
						|
      var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1);
 | 
						|
 | 
						|
      var strBytes = str.getBytes((length * bps + 7) / 8);
 | 
						|
      var strIdx = 0;
 | 
						|
      for (var i = 0; i < length; i++) {
 | 
						|
        while (codeSize < bps) {
 | 
						|
          codeBuf <<= 8;
 | 
						|
          codeBuf |= strBytes[strIdx++];
 | 
						|
          codeSize += 8;
 | 
						|
        }
 | 
						|
        codeSize -= bps;
 | 
						|
        array.push((codeBuf >> codeSize) * sampleMul);
 | 
						|
        codeBuf &= (1 << codeSize) - 1;
 | 
						|
      }
 | 
						|
      return array;
 | 
						|
    },
 | 
						|
 | 
						|
    getIR: function PDFFunction_getIR(xref, fn) {
 | 
						|
      var dict = fn.dict;
 | 
						|
      if (!dict)
 | 
						|
        dict = fn;
 | 
						|
 | 
						|
      var types = [this.constructSampled,
 | 
						|
                   null,
 | 
						|
                   this.constructInterpolated,
 | 
						|
                   this.constructStiched,
 | 
						|
                   this.constructPostScript];
 | 
						|
 | 
						|
      var typeNum = dict.get('FunctionType');
 | 
						|
      var typeFn = types[typeNum];
 | 
						|
      if (!typeFn)
 | 
						|
        error('Unknown type of function');
 | 
						|
 | 
						|
      return typeFn.call(this, fn, dict, xref);
 | 
						|
    },
 | 
						|
 | 
						|
    fromIR: function PDFFunction_fromIR(IR) {
 | 
						|
      var type = IR[0];
 | 
						|
      switch (type) {
 | 
						|
        case CONSTRUCT_SAMPLED:
 | 
						|
          return this.constructSampledFromIR(IR);
 | 
						|
        case CONSTRUCT_INTERPOLATED:
 | 
						|
          return this.constructInterpolatedFromIR(IR);
 | 
						|
        case CONSTRUCT_STICHED:
 | 
						|
          return this.constructStichedFromIR(IR);
 | 
						|
        //case CONSTRUCT_POSTSCRIPT:
 | 
						|
        default:
 | 
						|
          return this.constructPostScriptFromIR(IR);
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    parse: function PDFFunction_parse(xref, fn) {
 | 
						|
      var IR = this.getIR(xref, fn);
 | 
						|
      return this.fromIR(IR);
 | 
						|
    },
 | 
						|
 | 
						|
    constructSampled: function PDFFunction_constructSampled(str, dict) {
 | 
						|
      function toMultiArray(arr) {
 | 
						|
        var inputLength = arr.length;
 | 
						|
        var outputLength = arr.length / 2;
 | 
						|
        var out = [];
 | 
						|
        var index = 0;
 | 
						|
        for (var i = 0; i < inputLength; i += 2) {
 | 
						|
          out[index] = [arr[i], arr[i + 1]];
 | 
						|
          ++index;
 | 
						|
        }
 | 
						|
        return out;
 | 
						|
      }
 | 
						|
      var domain = dict.get('Domain');
 | 
						|
      var range = dict.get('Range');
 | 
						|
 | 
						|
      if (!domain || !range)
 | 
						|
        error('No domain or range');
 | 
						|
 | 
						|
      var inputSize = domain.length / 2;
 | 
						|
      var outputSize = range.length / 2;
 | 
						|
 | 
						|
      domain = toMultiArray(domain);
 | 
						|
      range = toMultiArray(range);
 | 
						|
 | 
						|
      var size = dict.get('Size');
 | 
						|
      var bps = dict.get('BitsPerSample');
 | 
						|
      var order = dict.get('Order') || 1;
 | 
						|
      if (order !== 1) {
 | 
						|
        // No description how cubic spline interpolation works in PDF32000:2008
 | 
						|
        // As in poppler, ignoring order, linear interpolation may work as good
 | 
						|
        TODO('No support for cubic spline interpolation: ' + order);
 | 
						|
      }
 | 
						|
 | 
						|
      var encode = dict.get('Encode');
 | 
						|
      if (!encode) {
 | 
						|
        encode = [];
 | 
						|
        for (var i = 0; i < inputSize; ++i) {
 | 
						|
          encode.push(0);
 | 
						|
          encode.push(size[i] - 1);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      encode = toMultiArray(encode);
 | 
						|
 | 
						|
      var decode = dict.get('Decode');
 | 
						|
      if (!decode)
 | 
						|
        decode = range;
 | 
						|
      else
 | 
						|
        decode = toMultiArray(decode);
 | 
						|
 | 
						|
      var samples = this.getSampleArray(size, outputSize, bps, str);
 | 
						|
 | 
						|
      return [
 | 
						|
        CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size,
 | 
						|
        outputSize, Math.pow(2, bps) - 1, range
 | 
						|
      ];
 | 
						|
    },
 | 
						|
 | 
						|
    constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) {
 | 
						|
      // See chapter 3, page 109 of the PDF reference
 | 
						|
      function interpolate(x, xmin, xmax, ymin, ymax) {
 | 
						|
        return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin)));
 | 
						|
      }
 | 
						|
 | 
						|
      return function constructSampledFromIRResult(args) {
 | 
						|
        // See chapter 3, page 110 of the PDF reference.
 | 
						|
        var m = IR[1];
 | 
						|
        var domain = IR[2];
 | 
						|
        var encode = IR[3];
 | 
						|
        var decode = IR[4];
 | 
						|
        var samples = IR[5];
 | 
						|
        var size = IR[6];
 | 
						|
        var n = IR[7];
 | 
						|
        var mask = IR[8];
 | 
						|
        var range = IR[9];
 | 
						|
 | 
						|
        if (m != args.length)
 | 
						|
          error('Incorrect number of arguments: ' + m + ' != ' +
 | 
						|
                args.length);
 | 
						|
 | 
						|
        var x = args;
 | 
						|
 | 
						|
        // Building the cube vertices: its part and sample index
 | 
						|
        // http://rjwagner49.com/Mathematics/Interpolation.pdf
 | 
						|
        var cubeVertices = 1 << m;
 | 
						|
        var cubeN = new Float64Array(cubeVertices);
 | 
						|
        var cubeVertex = new Uint32Array(cubeVertices);
 | 
						|
        for (var j = 0; j < cubeVertices; j++)
 | 
						|
          cubeN[j] = 1;
 | 
						|
 | 
						|
        var k = n, pos = 1;
 | 
						|
        // Map x_i to y_j for 0 <= i < m using the sampled function.
 | 
						|
        for (var i = 0; i < m; ++i) {
 | 
						|
          // x_i' = min(max(x_i, Domain_2i), Domain_2i+1)
 | 
						|
          var domain_2i = domain[i][0];
 | 
						|
          var domain_2i_1 = domain[i][1];
 | 
						|
          var xi = Math.min(Math.max(x[i], domain_2i), domain_2i_1);
 | 
						|
 | 
						|
          // e_i = Interpolate(x_i', Domain_2i, Domain_2i+1,
 | 
						|
          //                   Encode_2i, Encode_2i+1)
 | 
						|
          var e = interpolate(xi, domain_2i, domain_2i_1,
 | 
						|
                              encode[i][0], encode[i][1]);
 | 
						|
 | 
						|
          // e_i' = min(max(e_i, 0), Size_i - 1)
 | 
						|
          var size_i = size[i];
 | 
						|
          e = Math.min(Math.max(e, 0), size_i - 1);
 | 
						|
 | 
						|
          // Adjusting the cube: N and vertex sample index
 | 
						|
          var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; // e1 = e0 + 1;
 | 
						|
          var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
 | 
						|
          var n1 = e - e0; // (e - e0) / (e1 - e0);
 | 
						|
          var offset0 = e0 * k;
 | 
						|
          var offset1 = offset0 + k; // e1 * k
 | 
						|
          for (var j = 0; j < cubeVertices; j++) {
 | 
						|
            if (j & pos) {
 | 
						|
              cubeN[j] *= n1;
 | 
						|
              cubeVertex[j] += offset1;
 | 
						|
            } else {
 | 
						|
              cubeN[j] *= n0;
 | 
						|
              cubeVertex[j] += offset0;
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          k *= size_i;
 | 
						|
          pos <<= 1;
 | 
						|
        }
 | 
						|
 | 
						|
        var y = new Float64Array(n);
 | 
						|
        for (var j = 0; j < n; ++j) {
 | 
						|
          // Sum all cube vertices' samples portions
 | 
						|
          var rj = 0;
 | 
						|
          for (var i = 0; i < cubeVertices; i++)
 | 
						|
            rj += samples[cubeVertex[i] + j] * cubeN[i];
 | 
						|
 | 
						|
          // r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1,
 | 
						|
          //                    Decode_2j, Decode_2j+1)
 | 
						|
          rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
 | 
						|
 | 
						|
          // y_j = min(max(r_j, range_2j), range_2j+1)
 | 
						|
          y[j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
 | 
						|
        }
 | 
						|
 | 
						|
        return y;
 | 
						|
      };
 | 
						|
    },
 | 
						|
 | 
						|
    constructInterpolated: function PDFFunction_constructInterpolated(str,
 | 
						|
                                                                      dict) {
 | 
						|
      var c0 = dict.get('C0') || [0];
 | 
						|
      var c1 = dict.get('C1') || [1];
 | 
						|
      var n = dict.get('N');
 | 
						|
 | 
						|
      if (!isArray(c0) || !isArray(c1))
 | 
						|
        error('Illegal dictionary for interpolated function');
 | 
						|
 | 
						|
      var length = c0.length;
 | 
						|
      var diff = [];
 | 
						|
      for (var i = 0; i < length; ++i)
 | 
						|
        diff.push(c1[i] - c0[i]);
 | 
						|
 | 
						|
      return [CONSTRUCT_INTERPOLATED, c0, diff, n];
 | 
						|
    },
 | 
						|
 | 
						|
    constructInterpolatedFromIR:
 | 
						|
      function PDFFunction_constructInterpolatedFromIR(IR) {
 | 
						|
      var c0 = IR[1];
 | 
						|
      var diff = IR[2];
 | 
						|
      var n = IR[3];
 | 
						|
 | 
						|
      var length = diff.length;
 | 
						|
 | 
						|
      return function constructInterpolatedFromIRResult(args) {
 | 
						|
        var x = n == 1 ? args[0] : Math.pow(args[0], n);
 | 
						|
 | 
						|
        var out = [];
 | 
						|
        for (var j = 0; j < length; ++j)
 | 
						|
          out.push(c0[j] + (x * diff[j]));
 | 
						|
 | 
						|
        return out;
 | 
						|
 | 
						|
      };
 | 
						|
    },
 | 
						|
 | 
						|
    constructStiched: function PDFFunction_constructStiched(fn, dict, xref) {
 | 
						|
      var domain = dict.get('Domain');
 | 
						|
 | 
						|
      if (!domain)
 | 
						|
        error('No domain');
 | 
						|
 | 
						|
      var inputSize = domain.length / 2;
 | 
						|
      if (inputSize != 1)
 | 
						|
        error('Bad domain for stiched function');
 | 
						|
 | 
						|
      var fnRefs = dict.get('Functions');
 | 
						|
      var fns = [];
 | 
						|
      for (var i = 0, ii = fnRefs.length; i < ii; ++i)
 | 
						|
        fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i])));
 | 
						|
 | 
						|
      var bounds = dict.get('Bounds');
 | 
						|
      var encode = dict.get('Encode');
 | 
						|
 | 
						|
      return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
 | 
						|
    },
 | 
						|
 | 
						|
    constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) {
 | 
						|
      var domain = IR[1];
 | 
						|
      var bounds = IR[2];
 | 
						|
      var encode = IR[3];
 | 
						|
      var fnsIR = IR[4];
 | 
						|
      var fns = [];
 | 
						|
 | 
						|
      for (var i = 0, ii = fnsIR.length; i < ii; i++) {
 | 
						|
        fns.push(PDFFunction.fromIR(fnsIR[i]));
 | 
						|
      }
 | 
						|
 | 
						|
      return function constructStichedFromIRResult(args) {
 | 
						|
        var clip = function constructStichedFromIRClip(v, min, max) {
 | 
						|
          if (v > max)
 | 
						|
            v = max;
 | 
						|
          else if (v < min)
 | 
						|
            v = min;
 | 
						|
          return v;
 | 
						|
        };
 | 
						|
 | 
						|
        // clip to domain
 | 
						|
        var v = clip(args[0], domain[0], domain[1]);
 | 
						|
        // calulate which bound the value is in
 | 
						|
        for (var i = 0, ii = bounds.length; i < ii; ++i) {
 | 
						|
          if (v < bounds[i])
 | 
						|
            break;
 | 
						|
        }
 | 
						|
 | 
						|
        // encode value into domain of function
 | 
						|
        var dmin = domain[0];
 | 
						|
        if (i > 0)
 | 
						|
          dmin = bounds[i - 1];
 | 
						|
        var dmax = domain[1];
 | 
						|
        if (i < bounds.length)
 | 
						|
          dmax = bounds[i];
 | 
						|
 | 
						|
        var rmin = encode[2 * i];
 | 
						|
        var rmax = encode[2 * i + 1];
 | 
						|
 | 
						|
        var v2 = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
 | 
						|
 | 
						|
        // call the appropropriate function
 | 
						|
        return fns[i]([v2]);
 | 
						|
      };
 | 
						|
    },
 | 
						|
 | 
						|
    constructPostScript: function PDFFunction_constructPostScript(fn, dict,
 | 
						|
                                                                  xref) {
 | 
						|
      var domain = dict.get('Domain');
 | 
						|
      var range = dict.get('Range');
 | 
						|
 | 
						|
      if (!domain)
 | 
						|
        error('No domain.');
 | 
						|
 | 
						|
      if (!range)
 | 
						|
        error('No range.');
 | 
						|
 | 
						|
      var lexer = new PostScriptLexer(fn);
 | 
						|
      var parser = new PostScriptParser(lexer);
 | 
						|
      var code = parser.parse();
 | 
						|
 | 
						|
      return [CONSTRUCT_POSTSCRIPT, domain, range, code];
 | 
						|
    },
 | 
						|
 | 
						|
    constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR(
 | 
						|
                                          IR) {
 | 
						|
      var domain = IR[1];
 | 
						|
      var range = IR[2];
 | 
						|
      var code = IR[3];
 | 
						|
      var numOutputs = range.length / 2;
 | 
						|
      var evaluator = new PostScriptEvaluator(code);
 | 
						|
      // Cache the values for a big speed up, the cache size is limited though
 | 
						|
      // since the number of possible values can be huge from a PS function.
 | 
						|
      var cache = new FunctionCache();
 | 
						|
      return function constructPostScriptFromIRResult(args) {
 | 
						|
        var initialStack = [];
 | 
						|
        for (var i = 0, ii = (domain.length / 2); i < ii; ++i) {
 | 
						|
          initialStack.push(args[i]);
 | 
						|
        }
 | 
						|
 | 
						|
        var key = initialStack.join('_');
 | 
						|
        if (cache.has(key))
 | 
						|
          return cache.get(key);
 | 
						|
 | 
						|
        var stack = evaluator.execute(initialStack);
 | 
						|
        var transformed = [];
 | 
						|
        for (i = numOutputs - 1; i >= 0; --i) {
 | 
						|
          var out = stack.pop();
 | 
						|
          var rangeIndex = 2 * i;
 | 
						|
          if (out < range[rangeIndex])
 | 
						|
            out = range[rangeIndex];
 | 
						|
          else if (out > range[rangeIndex + 1])
 | 
						|
            out = range[rangeIndex + 1];
 | 
						|
          transformed[i] = out;
 | 
						|
        }
 | 
						|
        cache.set(key, transformed);
 | 
						|
        return transformed;
 | 
						|
      };
 | 
						|
    }
 | 
						|
  };
 | 
						|
})();
 | 
						|
 | 
						|
var FunctionCache = (function FunctionCacheClosure() {
 | 
						|
  // Of 10 PDF's with type4 functions the maxium number of distinct values seen
 | 
						|
  // was 256. This still may need some tweaking in the future though.
 | 
						|
  var MAX_CACHE_SIZE = 1024;
 | 
						|
  function FunctionCache() {
 | 
						|
    this.cache = {};
 | 
						|
    this.total = 0;
 | 
						|
  }
 | 
						|
  FunctionCache.prototype = {
 | 
						|
    has: function FunctionCache_has(key) {
 | 
						|
      return key in this.cache;
 | 
						|
    },
 | 
						|
    get: function FunctionCache_get(key) {
 | 
						|
      return this.cache[key];
 | 
						|
    },
 | 
						|
    set: function FunctionCache_set(key, value) {
 | 
						|
      if (this.total < MAX_CACHE_SIZE) {
 | 
						|
        this.cache[key] = value;
 | 
						|
        this.total++;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return FunctionCache;
 | 
						|
})();
 | 
						|
 | 
						|
var PostScriptStack = (function PostScriptStackClosure() {
 | 
						|
  var MAX_STACK_SIZE = 100;
 | 
						|
  function PostScriptStack(initialStack) {
 | 
						|
    this.stack = initialStack || [];
 | 
						|
  }
 | 
						|
 | 
						|
  PostScriptStack.prototype = {
 | 
						|
    push: function PostScriptStack_push(value) {
 | 
						|
      if (this.stack.length >= MAX_STACK_SIZE)
 | 
						|
        error('PostScript function stack overflow.');
 | 
						|
      this.stack.push(value);
 | 
						|
    },
 | 
						|
    pop: function PostScriptStack_pop() {
 | 
						|
      if (this.stack.length <= 0)
 | 
						|
        error('PostScript function stack underflow.');
 | 
						|
      return this.stack.pop();
 | 
						|
    },
 | 
						|
    copy: function PostScriptStack_copy(n) {
 | 
						|
      if (this.stack.length + n >= MAX_STACK_SIZE)
 | 
						|
        error('PostScript function stack overflow.');
 | 
						|
      var stack = this.stack;
 | 
						|
      for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++)
 | 
						|
        stack.push(stack[i]);
 | 
						|
    },
 | 
						|
    index: function PostScriptStack_index(n) {
 | 
						|
      this.push(this.stack[this.stack.length - n - 1]);
 | 
						|
    },
 | 
						|
    // rotate the last n stack elements p times
 | 
						|
    roll: function PostScriptStack_roll(n, p) {
 | 
						|
      var stack = this.stack;
 | 
						|
      var l = stack.length - n;
 | 
						|
      var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t;
 | 
						|
      for (i = l, j = r; i < j; i++, j--) {
 | 
						|
        t = stack[i]; stack[i] = stack[j]; stack[j] = t;
 | 
						|
      }
 | 
						|
      for (i = l, j = c - 1; i < j; i++, j--) {
 | 
						|
        t = stack[i]; stack[i] = stack[j]; stack[j] = t;
 | 
						|
      }
 | 
						|
      for (i = c, j = r; i < j; i++, j--) {
 | 
						|
        t = stack[i]; stack[i] = stack[j]; stack[j] = t;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return PostScriptStack;
 | 
						|
})();
 | 
						|
var PostScriptEvaluator = (function PostScriptEvaluatorClosure() {
 | 
						|
  function PostScriptEvaluator(operators, operands) {
 | 
						|
    this.operators = operators;
 | 
						|
    this.operands = operands;
 | 
						|
  }
 | 
						|
  PostScriptEvaluator.prototype = {
 | 
						|
    execute: function PostScriptEvaluator_execute(initialStack) {
 | 
						|
      var stack = new PostScriptStack(initialStack);
 | 
						|
      var counter = 0;
 | 
						|
      var operators = this.operators;
 | 
						|
      var length = operators.length;
 | 
						|
      var operator, a, b;
 | 
						|
      while (counter < length) {
 | 
						|
        operator = operators[counter++];
 | 
						|
        if (typeof operator == 'number') {
 | 
						|
          // Operator is really an operand and should be pushed to the stack.
 | 
						|
          stack.push(operator);
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
        switch (operator) {
 | 
						|
          // non standard ps operators
 | 
						|
          case 'jz': // jump if false
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            if (!a)
 | 
						|
              counter = b;
 | 
						|
            break;
 | 
						|
          case 'j': // jump
 | 
						|
            a = stack.pop();
 | 
						|
            counter = a;
 | 
						|
            break;
 | 
						|
 | 
						|
          // all ps operators in alphabetical order (excluding if/ifelse)
 | 
						|
          case 'abs':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(Math.abs(a));
 | 
						|
            break;
 | 
						|
          case 'add':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(a + b);
 | 
						|
            break;
 | 
						|
          case 'and':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            if (isBool(a) && isBool(b))
 | 
						|
              stack.push(a && b);
 | 
						|
            else
 | 
						|
              stack.push(a & b);
 | 
						|
            break;
 | 
						|
          case 'atan':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(Math.atan(a));
 | 
						|
            break;
 | 
						|
          case 'bitshift':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            if (a > 0)
 | 
						|
              stack.push(a << b);
 | 
						|
            else
 | 
						|
              stack.push(a >> b);
 | 
						|
            break;
 | 
						|
          case 'ceiling':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(Math.ceil(a));
 | 
						|
            break;
 | 
						|
          case 'copy':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.copy(a);
 | 
						|
            break;
 | 
						|
          case 'cos':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(Math.cos(a));
 | 
						|
            break;
 | 
						|
          case 'cvi':
 | 
						|
            a = stack.pop() | 0;
 | 
						|
            stack.push(a);
 | 
						|
            break;
 | 
						|
          case 'cvr':
 | 
						|
            // noop
 | 
						|
            break;
 | 
						|
          case 'div':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(a / b);
 | 
						|
            break;
 | 
						|
          case 'dup':
 | 
						|
            stack.copy(1);
 | 
						|
            break;
 | 
						|
          case 'eq':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(a == b);
 | 
						|
            break;
 | 
						|
          case 'exch':
 | 
						|
            stack.roll(2, 1);
 | 
						|
            break;
 | 
						|
          case 'exp':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(Math.pow(a, b));
 | 
						|
            break;
 | 
						|
          case 'false':
 | 
						|
            stack.push(false);
 | 
						|
            break;
 | 
						|
          case 'floor':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(Math.floor(a));
 | 
						|
            break;
 | 
						|
          case 'ge':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(a >= b);
 | 
						|
            break;
 | 
						|
          case 'gt':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(a > b);
 | 
						|
            break;
 | 
						|
          case 'idiv':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push((a / b) | 0);
 | 
						|
            break;
 | 
						|
          case 'index':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.index(a);
 | 
						|
            break;
 | 
						|
          case 'le':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(a <= b);
 | 
						|
            break;
 | 
						|
          case 'ln':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(Math.log(a));
 | 
						|
            break;
 | 
						|
          case 'log':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(Math.log(a) / Math.LN10);
 | 
						|
            break;
 | 
						|
          case 'lt':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(a < b);
 | 
						|
            break;
 | 
						|
          case 'mod':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(a % b);
 | 
						|
            break;
 | 
						|
          case 'mul':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(a * b);
 | 
						|
            break;
 | 
						|
          case 'ne':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(a != b);
 | 
						|
            break;
 | 
						|
          case 'neg':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(-b);
 | 
						|
            break;
 | 
						|
          case 'not':
 | 
						|
            a = stack.pop();
 | 
						|
            if (isBool(a) && isBool(b))
 | 
						|
              stack.push(a && b);
 | 
						|
            else
 | 
						|
              stack.push(a & b);
 | 
						|
            break;
 | 
						|
          case 'or':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            if (isBool(a) && isBool(b))
 | 
						|
              stack.push(a || b);
 | 
						|
            else
 | 
						|
              stack.push(a | b);
 | 
						|
            break;
 | 
						|
          case 'pop':
 | 
						|
            stack.pop();
 | 
						|
            break;
 | 
						|
          case 'roll':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.roll(a, b);
 | 
						|
            break;
 | 
						|
          case 'round':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(Math.round(a));
 | 
						|
            break;
 | 
						|
          case 'sin':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(Math.sin(a));
 | 
						|
            break;
 | 
						|
          case 'sqrt':
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(Math.sqrt(a));
 | 
						|
            break;
 | 
						|
          case 'sub':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            stack.push(a - b);
 | 
						|
            break;
 | 
						|
          case 'true':
 | 
						|
            stack.push(true);
 | 
						|
            break;
 | 
						|
          case 'truncate':
 | 
						|
            a = stack.pop();
 | 
						|
            a = a < 0 ? Math.ceil(a) : Math.floor(a);
 | 
						|
            stack.push(a);
 | 
						|
            break;
 | 
						|
          case 'xor':
 | 
						|
            b = stack.pop();
 | 
						|
            a = stack.pop();
 | 
						|
            if (isBool(a) && isBool(b))
 | 
						|
              stack.push(a != b);
 | 
						|
            else
 | 
						|
              stack.push(a ^ b);
 | 
						|
            break;
 | 
						|
          default:
 | 
						|
            error('Unknown operator ' + operator);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      return stack.stack;
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return PostScriptEvaluator;
 | 
						|
})();
 | 
						|
 | 
						|
var PostScriptParser = (function PostScriptParserClosure() {
 | 
						|
  function PostScriptParser(lexer) {
 | 
						|
    this.lexer = lexer;
 | 
						|
    this.operators = [];
 | 
						|
    this.token = null;
 | 
						|
    this.prev = null;
 | 
						|
  }
 | 
						|
  PostScriptParser.prototype = {
 | 
						|
    nextToken: function PostScriptParser_nextToken() {
 | 
						|
      this.prev = this.token;
 | 
						|
      this.token = this.lexer.getToken();
 | 
						|
    },
 | 
						|
    accept: function PostScriptParser_accept(type) {
 | 
						|
      if (this.token.type == type) {
 | 
						|
        this.nextToken();
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
      return false;
 | 
						|
    },
 | 
						|
    expect: function PostScriptParser_expect(type) {
 | 
						|
      if (this.accept(type))
 | 
						|
        return true;
 | 
						|
      error('Unexpected symbol: found ' + this.token.type + ' expected ' +
 | 
						|
            type + '.');
 | 
						|
    },
 | 
						|
    parse: function PostScriptParser_parse() {
 | 
						|
      this.nextToken();
 | 
						|
      this.expect(PostScriptTokenTypes.LBRACE);
 | 
						|
      this.parseBlock();
 | 
						|
      this.expect(PostScriptTokenTypes.RBRACE);
 | 
						|
      return this.operators;
 | 
						|
    },
 | 
						|
    parseBlock: function PostScriptParser_parseBlock() {
 | 
						|
      while (true) {
 | 
						|
        if (this.accept(PostScriptTokenTypes.NUMBER)) {
 | 
						|
          this.operators.push(this.prev.value);
 | 
						|
        } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
 | 
						|
          this.operators.push(this.prev.value);
 | 
						|
        } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
 | 
						|
          this.parseCondition();
 | 
						|
        } else {
 | 
						|
          return;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    },
 | 
						|
    parseCondition: function PostScriptParser_parseCondition() {
 | 
						|
      // Add two place holders that will be updated later
 | 
						|
      var conditionLocation = this.operators.length;
 | 
						|
      this.operators.push(null, null);
 | 
						|
 | 
						|
      this.parseBlock();
 | 
						|
      this.expect(PostScriptTokenTypes.RBRACE);
 | 
						|
      if (this.accept(PostScriptTokenTypes.IF)) {
 | 
						|
        // The true block is right after the 'if' so it just falls through on
 | 
						|
        // true else it jumps and skips the true block.
 | 
						|
        this.operators[conditionLocation] = this.operators.length;
 | 
						|
        this.operators[conditionLocation + 1] = 'jz';
 | 
						|
      } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
 | 
						|
        var jumpLocation = this.operators.length;
 | 
						|
        this.operators.push(null, null);
 | 
						|
        var endOfTrue = this.operators.length;
 | 
						|
        this.parseBlock();
 | 
						|
        this.expect(PostScriptTokenTypes.RBRACE);
 | 
						|
        this.expect(PostScriptTokenTypes.IFELSE);
 | 
						|
        // The jump is added at the end of the true block to skip the false
 | 
						|
        // block.
 | 
						|
        this.operators[jumpLocation] = this.operators.length;
 | 
						|
        this.operators[jumpLocation + 1] = 'j';
 | 
						|
 | 
						|
        this.operators[conditionLocation] = endOfTrue;
 | 
						|
        this.operators[conditionLocation + 1] = 'jz';
 | 
						|
      } else {
 | 
						|
        error('PS Function: error parsing conditional.');
 | 
						|
      }
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return PostScriptParser;
 | 
						|
})();
 | 
						|
 | 
						|
var PostScriptTokenTypes = {
 | 
						|
  LBRACE: 0,
 | 
						|
  RBRACE: 1,
 | 
						|
  NUMBER: 2,
 | 
						|
  OPERATOR: 3,
 | 
						|
  IF: 4,
 | 
						|
  IFELSE: 5
 | 
						|
};
 | 
						|
 | 
						|
var PostScriptToken = (function PostScriptTokenClosure() {
 | 
						|
  function PostScriptToken(type, value) {
 | 
						|
    this.type = type;
 | 
						|
    this.value = value;
 | 
						|
  }
 | 
						|
 | 
						|
  var opCache = {};
 | 
						|
 | 
						|
  PostScriptToken.getOperator = function PostScriptToken_getOperator(op) {
 | 
						|
    var opValue = opCache[op];
 | 
						|
    if (opValue)
 | 
						|
      return opValue;
 | 
						|
 | 
						|
    return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
 | 
						|
  };
 | 
						|
 | 
						|
  PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE,
 | 
						|
                                                '{');
 | 
						|
  PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE,
 | 
						|
                                                '}');
 | 
						|
  PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF');
 | 
						|
  PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE,
 | 
						|
                                                'IFELSE');
 | 
						|
  return PostScriptToken;
 | 
						|
})();
 | 
						|
 | 
						|
var PostScriptLexer = (function PostScriptLexerClosure() {
 | 
						|
  function PostScriptLexer(stream) {
 | 
						|
    this.stream = stream;
 | 
						|
    this.nextChar();
 | 
						|
  }
 | 
						|
  PostScriptLexer.prototype = {
 | 
						|
    nextChar: function PostScriptLexer_nextChar() {
 | 
						|
      return (this.currentChar = this.stream.getByte());
 | 
						|
    },
 | 
						|
    getToken: function PostScriptLexer_getToken() {
 | 
						|
      var s = '';
 | 
						|
      var comment = false;
 | 
						|
      var ch = this.currentChar;
 | 
						|
 | 
						|
      // skip comments
 | 
						|
      while (true) {
 | 
						|
        if (ch < 0) {
 | 
						|
          return EOF;
 | 
						|
        }
 | 
						|
 | 
						|
        if (comment) {
 | 
						|
          if (ch === 0x0A || ch === 0x0D) {
 | 
						|
            comment = false;
 | 
						|
          }
 | 
						|
        } else if (ch == 0x25) { // '%'
 | 
						|
          comment = true;
 | 
						|
        } else if (!Lexer.isSpace(ch)) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        ch = this.nextChar();
 | 
						|
      }
 | 
						|
      switch (ch | 0) {
 | 
						|
        case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4'
 | 
						|
        case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9'
 | 
						|
        case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.'
 | 
						|
          return new PostScriptToken(PostScriptTokenTypes.NUMBER,
 | 
						|
                                      this.getNumber());
 | 
						|
        case 0x7B: // '{'
 | 
						|
          this.nextChar();
 | 
						|
          return PostScriptToken.LBRACE;
 | 
						|
        case 0x7D: // '}'
 | 
						|
          this.nextChar();
 | 
						|
          return PostScriptToken.RBRACE;
 | 
						|
      }
 | 
						|
      // operator
 | 
						|
      var str = String.fromCharCode(ch);
 | 
						|
      while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
 | 
						|
             ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) {
 | 
						|
        str += String.fromCharCode(ch);
 | 
						|
      }
 | 
						|
      switch (str.toLowerCase()) {
 | 
						|
        case 'if':
 | 
						|
          return PostScriptToken.IF;
 | 
						|
        case 'ifelse':
 | 
						|
          return PostScriptToken.IFELSE;
 | 
						|
        default:
 | 
						|
          return PostScriptToken.getOperator(str);
 | 
						|
      }
 | 
						|
    },
 | 
						|
    getNumber: function PostScriptLexer_getNumber() {
 | 
						|
      var ch = this.currentChar;
 | 
						|
      var str = String.fromCharCode(ch);
 | 
						|
      while ((ch = this.nextChar()) >= 0) {
 | 
						|
        if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9'
 | 
						|
             ch === 0x2D || ch === 0x2E) { // '-', '.'
 | 
						|
          str += String.fromCharCode(ch);
 | 
						|
        } else {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      var value = parseFloat(str);
 | 
						|
      if (isNaN(value))
 | 
						|
        error('Invalid floating point number: ' + value);
 | 
						|
      return value;
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return PostScriptLexer;
 | 
						|
})();
 | 
						|
 | 
						|
 | 
						|
 | 
						|
var Annotation = (function AnnotationClosure() {
 | 
						|
  // 12.5.5: Algorithm: Appearance streams
 | 
						|
  function getTransformMatrix(rect, bbox, matrix) {
 | 
						|
    var bounds = Util.getAxialAlignedBoundingBox(bbox, matrix);
 | 
						|
    var minX = bounds[0];
 | 
						|
    var minY = bounds[1];
 | 
						|
    var maxX = bounds[2];
 | 
						|
    var maxY = bounds[3];
 | 
						|
 | 
						|
    if (minX === maxX || minY === maxY) {
 | 
						|
      // From real-life file, bbox was [0, 0, 0, 0]. In this case,
 | 
						|
      // just apply the transform for rect
 | 
						|
      return [1, 0, 0, 1, rect[0], rect[1]];
 | 
						|
    }
 | 
						|
 | 
						|
    var xRatio = (rect[2] - rect[0]) / (maxX - minX);
 | 
						|
    var yRatio = (rect[3] - rect[1]) / (maxY - minY);
 | 
						|
    return [
 | 
						|
      xRatio,
 | 
						|
      0,
 | 
						|
      0,
 | 
						|
      yRatio,
 | 
						|
      rect[0] - minX * xRatio,
 | 
						|
      rect[1] - minY * yRatio
 | 
						|
    ];
 | 
						|
  }
 | 
						|
 | 
						|
  function getDefaultAppearance(dict) {
 | 
						|
    var appearanceState = dict.get('AP');
 | 
						|
    if (!isDict(appearanceState)) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    var appearance;
 | 
						|
    var appearances = appearanceState.get('N');
 | 
						|
    if (isDict(appearances)) {
 | 
						|
      var as = dict.get('AS');
 | 
						|
      if (as && appearances.has(as.name)) {
 | 
						|
        appearance = appearances.get(as.name);
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      appearance = appearances;
 | 
						|
    }
 | 
						|
    return appearance;
 | 
						|
  }
 | 
						|
 | 
						|
  function Annotation(params) {
 | 
						|
    if (params.data) {
 | 
						|
      this.data = params.data;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    var dict = params.dict;
 | 
						|
    var data = this.data = {};
 | 
						|
 | 
						|
    data.subtype = dict.get('Subtype').name;
 | 
						|
    var rect = dict.get('Rect');
 | 
						|
    data.rect = Util.normalizeRect(rect);
 | 
						|
    data.annotationFlags = dict.get('F');
 | 
						|
 | 
						|
    var color = dict.get('C');
 | 
						|
    if (isArray(color) && color.length === 3) {
 | 
						|
      // TODO(mack): currently only supporting rgb; need support different
 | 
						|
      // colorspaces
 | 
						|
      data.color = color;
 | 
						|
    } else {
 | 
						|
      data.color = [0, 0, 0];
 | 
						|
    }
 | 
						|
 | 
						|
    // Some types of annotations have border style dict which has more
 | 
						|
    // info than the border array
 | 
						|
    if (dict.has('BS')) {
 | 
						|
      var borderStyle = dict.get('BS');
 | 
						|
      data.borderWidth = borderStyle.has('W') ? borderStyle.get('W') : 1;
 | 
						|
    } else {
 | 
						|
      var borderArray = dict.get('Border') || [0, 0, 1];
 | 
						|
      data.borderWidth = borderArray[2] || 0;
 | 
						|
    }
 | 
						|
 | 
						|
    this.appearance = getDefaultAppearance(dict);
 | 
						|
    data.hasAppearance = !!this.appearance;
 | 
						|
  }
 | 
						|
 | 
						|
  Annotation.prototype = {
 | 
						|
 | 
						|
    getData: function Annotation_getData() {
 | 
						|
      return this.data;
 | 
						|
    },
 | 
						|
 | 
						|
    hasHtml: function Annotation_hasHtml() {
 | 
						|
      return false;
 | 
						|
    },
 | 
						|
 | 
						|
    getHtmlElement: function Annotation_getHtmlElement(commonObjs) {
 | 
						|
      throw new NotImplementedException(
 | 
						|
        'getHtmlElement() should be implemented in subclass');
 | 
						|
    },
 | 
						|
 | 
						|
    // TODO(mack): Remove this, it's not really that helpful.
 | 
						|
    getEmptyContainer: function Annotation_getEmptyContainer(tagName, rect) {
 | 
						|
      assert(!isWorker,
 | 
						|
        'getEmptyContainer() should be called from main thread');
 | 
						|
 | 
						|
      rect = rect || this.data.rect;
 | 
						|
      var element = document.createElement(tagName);
 | 
						|
      element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
 | 
						|
      element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
 | 
						|
      return element;
 | 
						|
    },
 | 
						|
 | 
						|
    isViewable: function Annotation_isViewable() {
 | 
						|
      var data = this.data;
 | 
						|
      return !!(
 | 
						|
        data &&
 | 
						|
        (!data.annotationFlags ||
 | 
						|
         !(data.annotationFlags & 0x22)) && // Hidden or NoView
 | 
						|
        data.rect                            // rectangle is nessessary
 | 
						|
      );
 | 
						|
    },
 | 
						|
 | 
						|
    loadResources: function(keys) {
 | 
						|
      var promise = new Promise();
 | 
						|
      this.appearance.dict.getAsync('Resources').then(function(resources) {
 | 
						|
        if (!resources) {
 | 
						|
          promise.resolve();
 | 
						|
          return;
 | 
						|
        }
 | 
						|
        var objectLoader = new ObjectLoader(resources.map,
 | 
						|
                                            keys,
 | 
						|
                                            resources.xref);
 | 
						|
        objectLoader.load().then(function() {
 | 
						|
          promise.resolve(resources);
 | 
						|
        });
 | 
						|
      }.bind(this));
 | 
						|
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
 | 
						|
    getOperatorList: function Annotation_getToOperatorList(evaluator) {
 | 
						|
 | 
						|
      var promise = new Promise();
 | 
						|
 | 
						|
      if (!this.appearance) {
 | 
						|
        promise.resolve(new OperatorList());
 | 
						|
        return promise;
 | 
						|
      }
 | 
						|
 | 
						|
      var data = this.data;
 | 
						|
 | 
						|
      var appearanceDict = this.appearance.dict;
 | 
						|
      var resourcesPromise = this.loadResources([
 | 
						|
        'ExtGState',
 | 
						|
        'ColorSpace',
 | 
						|
        'Pattern',
 | 
						|
        'Shading',
 | 
						|
        'XObject',
 | 
						|
        'Font'
 | 
						|
        // ProcSet
 | 
						|
        // Properties
 | 
						|
      ]);
 | 
						|
      var bbox = appearanceDict.get('BBox') || [0, 0, 1, 1];
 | 
						|
      var matrix = appearanceDict.get('Matrix') || [1, 0, 0, 1, 0 ,0];
 | 
						|
      var transform = getTransformMatrix(data.rect, bbox, matrix);
 | 
						|
 | 
						|
      var border = data.border;
 | 
						|
 | 
						|
      resourcesPromise.then(function(resources) {
 | 
						|
        var opList = new OperatorList();
 | 
						|
        opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
 | 
						|
        evaluator.getOperatorList(this.appearance, resources, opList);
 | 
						|
        opList.addOp(OPS.endAnnotation, []);
 | 
						|
        promise.resolve(opList);
 | 
						|
      }.bind(this));
 | 
						|
 | 
						|
      return promise;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  Annotation.getConstructor =
 | 
						|
      function Annotation_getConstructor(subtype, fieldType) {
 | 
						|
 | 
						|
    if (!subtype) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    // TODO(mack): Implement FreeText annotations
 | 
						|
    if (subtype === 'Link') {
 | 
						|
      return LinkAnnotation;
 | 
						|
    } else if (subtype === 'Text') {
 | 
						|
      return TextAnnotation;
 | 
						|
    } else if (subtype === 'Widget') {
 | 
						|
      if (!fieldType) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      if (fieldType === 'Tx') {
 | 
						|
        return TextWidgetAnnotation;
 | 
						|
      } else {
 | 
						|
        return WidgetAnnotation;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      return Annotation;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  // TODO(mack): Support loading annotation from data
 | 
						|
  Annotation.fromData = function Annotation_fromData(data) {
 | 
						|
    var subtype = data.subtype;
 | 
						|
    var fieldType = data.fieldType;
 | 
						|
    var Constructor = Annotation.getConstructor(subtype, fieldType);
 | 
						|
    if (Constructor) {
 | 
						|
      return new Constructor({ data: data });
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  Annotation.fromRef = function Annotation_fromRef(xref, ref) {
 | 
						|
 | 
						|
    var dict = xref.fetchIfRef(ref);
 | 
						|
    if (!isDict(dict)) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    var subtype = dict.get('Subtype');
 | 
						|
    subtype = isName(subtype) ? subtype.name : '';
 | 
						|
    if (!subtype) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    var fieldType = Util.getInheritableProperty(dict, 'FT');
 | 
						|
    fieldType = isName(fieldType) ? fieldType.name : '';
 | 
						|
 | 
						|
    var Constructor = Annotation.getConstructor(subtype, fieldType);
 | 
						|
    if (!Constructor) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    var params = {
 | 
						|
      dict: dict,
 | 
						|
      ref: ref,
 | 
						|
    };
 | 
						|
 | 
						|
    var annotation = new Constructor(params);
 | 
						|
 | 
						|
    if (annotation.isViewable()) {
 | 
						|
      return annotation;
 | 
						|
    } else {
 | 
						|
      TODO('unimplemented annotation type: ' + subtype);
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
 | 
						|
      annotations, opList, pdfManager, partialEvaluator) {
 | 
						|
 | 
						|
    function reject(e) {
 | 
						|
      annotationsReadyPromise.reject(e);
 | 
						|
    }
 | 
						|
 | 
						|
    var annotationsReadyPromise = new Promise();
 | 
						|
 | 
						|
    var annotationPromises = [];
 | 
						|
    for (var i = 0, n = annotations.length; i < n; ++i) {
 | 
						|
      annotationPromises.push(annotations[i].getOperatorList(partialEvaluator));
 | 
						|
    }
 | 
						|
    Promise.all(annotationPromises).then(function(datas) {
 | 
						|
      opList.addOp(OPS.beginAnnotations, []);
 | 
						|
      for (var i = 0, n = datas.length; i < n; ++i) {
 | 
						|
        var annotOpList = datas[i];
 | 
						|
        opList.addOpList(annotOpList);
 | 
						|
      }
 | 
						|
      opList.addOp(OPS.endAnnotations, []);
 | 
						|
      annotationsReadyPromise.resolve();
 | 
						|
    }, reject);
 | 
						|
 | 
						|
    return annotationsReadyPromise;
 | 
						|
  };
 | 
						|
 | 
						|
  return Annotation;
 | 
						|
})();
 | 
						|
PDFJS.Annotation = Annotation;
 | 
						|
 | 
						|
 | 
						|
var WidgetAnnotation = (function WidgetAnnotationClosure() {
 | 
						|
 | 
						|
  function WidgetAnnotation(params) {
 | 
						|
    Annotation.call(this, params);
 | 
						|
 | 
						|
    if (params.data) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    var dict = params.dict;
 | 
						|
    var data = this.data;
 | 
						|
 | 
						|
    data.fieldValue = stringToPDFString(
 | 
						|
      Util.getInheritableProperty(dict, 'V') || '');
 | 
						|
    data.alternativeText = stringToPDFString(dict.get('TU') || '');
 | 
						|
    data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || '';
 | 
						|
    var fieldType = Util.getInheritableProperty(dict, 'FT');
 | 
						|
    data.fieldType = isName(fieldType) ? fieldType.name : '';
 | 
						|
    data.fieldFlags = Util.getInheritableProperty(dict, 'Ff') || 0;
 | 
						|
    this.fieldResources = Util.getInheritableProperty(dict, 'DR') || new Dict();
 | 
						|
 | 
						|
    // Building the full field name by collecting the field and
 | 
						|
    // its ancestors 'T' data and joining them using '.'.
 | 
						|
    var fieldName = [];
 | 
						|
    var namedItem = dict;
 | 
						|
    var ref = params.ref;
 | 
						|
    while (namedItem) {
 | 
						|
      var parent = namedItem.get('Parent');
 | 
						|
      var parentRef = namedItem.getRaw('Parent');
 | 
						|
      var name = namedItem.get('T');
 | 
						|
      if (name) {
 | 
						|
        fieldName.unshift(stringToPDFString(name));
 | 
						|
      } else {
 | 
						|
        // The field name is absent, that means more than one field
 | 
						|
        // with the same name may exist. Replacing the empty name
 | 
						|
        // with the '`' plus index in the parent's 'Kids' array.
 | 
						|
        // This is not in the PDF spec but necessary to id the
 | 
						|
        // the input controls.
 | 
						|
        var kids = parent.get('Kids');
 | 
						|
        var j, jj;
 | 
						|
        for (j = 0, jj = kids.length; j < jj; j++) {
 | 
						|
          var kidRef = kids[j];
 | 
						|
          if (kidRef.num == ref.num && kidRef.gen == ref.gen)
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        fieldName.unshift('`' + j);
 | 
						|
      }
 | 
						|
      namedItem = parent;
 | 
						|
      ref = parentRef;
 | 
						|
    }
 | 
						|
    data.fullName = fieldName.join('.');
 | 
						|
  }
 | 
						|
 | 
						|
  var parent = Annotation.prototype;
 | 
						|
  Util.inherit(WidgetAnnotation, Annotation, {
 | 
						|
    isViewable: function WidgetAnnotation_isViewable() {
 | 
						|
      if (this.data.fieldType === 'Sig') {
 | 
						|
        TODO('unimplemented annotation type: Widget signature');
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
 | 
						|
      return parent.isViewable.call(this);
 | 
						|
    }
 | 
						|
  });
 | 
						|
 | 
						|
  return WidgetAnnotation;
 | 
						|
})();
 | 
						|
 | 
						|
var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
 | 
						|
  function TextWidgetAnnotation(params) {
 | 
						|
    WidgetAnnotation.call(this, params);
 | 
						|
 | 
						|
    if (params.data) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    this.data.textAlignment = Util.getInheritableProperty(params.dict, 'Q');
 | 
						|
  }
 | 
						|
 | 
						|
  // TODO(mack): This dupes some of the logic in CanvasGraphics.setFont()
 | 
						|
  function setTextStyles(element, item, fontObj) {
 | 
						|
 | 
						|
    var style = element.style;
 | 
						|
    style.fontSize = item.fontSize + 'px';
 | 
						|
    style.direction = item.fontDirection < 0 ? 'rtl': 'ltr';
 | 
						|
 | 
						|
    if (!fontObj) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    style.fontWeight = fontObj.black ?
 | 
						|
                            (fontObj.bold ? 'bolder' : 'bold') :
 | 
						|
                            (fontObj.bold ? 'bold' : 'normal');
 | 
						|
    style.fontStyle = fontObj.italic ? 'italic' : 'normal';
 | 
						|
 | 
						|
    var fontName = fontObj.loadedName;
 | 
						|
    var fontFamily = fontName ? '"' + fontName + '", ' : '';
 | 
						|
    // Use a reasonable default font if the font doesn't specify a fallback
 | 
						|
    var fallbackName = fontObj.fallbackName || 'Helvetica, sans-serif';
 | 
						|
    style.fontFamily = fontFamily + fallbackName;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  var parent = WidgetAnnotation.prototype;
 | 
						|
  Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {
 | 
						|
    hasHtml: function TextWidgetAnnotation_hasHtml() {
 | 
						|
      return !this.data.hasAppearance && !!this.data.fieldValue;
 | 
						|
    },
 | 
						|
 | 
						|
    getHtmlElement: function TextWidgetAnnotation_getHtmlElement(commonObjs) {
 | 
						|
      assert(!isWorker, 'getHtmlElement() shall be called from main thread');
 | 
						|
 | 
						|
      var item = this.data;
 | 
						|
 | 
						|
      var element = this.getEmptyContainer('div');
 | 
						|
      element.style.display = 'table';
 | 
						|
 | 
						|
      var content = document.createElement('div');
 | 
						|
      content.textContent = item.fieldValue;
 | 
						|
      var textAlignment = item.textAlignment;
 | 
						|
      content.style.textAlign = ['left', 'center', 'right'][textAlignment];
 | 
						|
      content.style.verticalAlign = 'middle';
 | 
						|
      content.style.display = 'table-cell';
 | 
						|
 | 
						|
      var fontObj = item.fontRefName ?
 | 
						|
                    commonObjs.getData(item.fontRefName) : null;
 | 
						|
      var cssRules = setTextStyles(content, item, fontObj);
 | 
						|
 | 
						|
      element.appendChild(content);
 | 
						|
 | 
						|
      return element;
 | 
						|
    },
 | 
						|
 | 
						|
    getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) {
 | 
						|
      if (this.appearance) {
 | 
						|
        return Annotation.prototype.getOperatorList.call(this, evaluator);
 | 
						|
      }
 | 
						|
 | 
						|
      var promise = new Promise();
 | 
						|
      var opList = new OperatorList();
 | 
						|
      var data = this.data;
 | 
						|
 | 
						|
      // Even if there is an appearance stream, ignore it. This is the
 | 
						|
      // behaviour used by Adobe Reader.
 | 
						|
 | 
						|
      var defaultAppearance = data.defaultAppearance;
 | 
						|
      if (!defaultAppearance) {
 | 
						|
        promise.resolve(opList);
 | 
						|
        return promise;
 | 
						|
      }
 | 
						|
 | 
						|
      // Include any font resources found in the default appearance
 | 
						|
 | 
						|
      var stream = new Stream(stringToBytes(defaultAppearance));
 | 
						|
      evaluator.getOperatorList(stream, this.fieldResources, opList);
 | 
						|
      var appearanceFnArray = opList.fnArray;
 | 
						|
      var appearanceArgsArray = opList.argsArray;
 | 
						|
      var fnArray = [];
 | 
						|
      var argsArray = [];
 | 
						|
 | 
						|
      // TODO(mack): Add support for stroke color
 | 
						|
      data.rgb = [0, 0, 0];
 | 
						|
      // TODO THIS DOESN'T MAKE ANY SENSE SINCE THE fnArray IS EMPTY!
 | 
						|
      for (var i = 0, n = fnArray.length; i < n; ++i) {
 | 
						|
        var fnId = appearanceFnArray[i];
 | 
						|
        var args = appearanceArgsArray[i];
 | 
						|
 | 
						|
        if (fnId === OPS.setFont) {
 | 
						|
          data.fontRefName = args[0];
 | 
						|
          var size = args[1];
 | 
						|
          if (size < 0) {
 | 
						|
            data.fontDirection = -1;
 | 
						|
            data.fontSize = -size;
 | 
						|
          } else {
 | 
						|
            data.fontDirection = 1;
 | 
						|
            data.fontSize = size;
 | 
						|
          }
 | 
						|
        } else if (fnId === OPS.setFillRGBColor) {
 | 
						|
          data.rgb = args;
 | 
						|
        } else if (fnId === OPS.setFillGray) {
 | 
						|
          var rgbValue = args[0] * 255;
 | 
						|
          data.rgb = [rgbValue, rgbValue, rgbValue];
 | 
						|
        }
 | 
						|
      }
 | 
						|
      promise.resolve(opList);
 | 
						|
      return promise;
 | 
						|
    }
 | 
						|
  });
 | 
						|
 | 
						|
  return TextWidgetAnnotation;
 | 
						|
})();
 | 
						|
 | 
						|
var TextAnnotation = (function TextAnnotationClosure() {
 | 
						|
  function TextAnnotation(params) {
 | 
						|
    Annotation.call(this, params);
 | 
						|
 | 
						|
    if (params.data) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    var dict = params.dict;
 | 
						|
    var data = this.data;
 | 
						|
 | 
						|
    var content = dict.get('Contents');
 | 
						|
    var title = dict.get('T');
 | 
						|
    data.content = stringToPDFString(content || '');
 | 
						|
    data.title = stringToPDFString(title || '');
 | 
						|
    data.name = !dict.has('Name') ? 'Note' : dict.get('Name').name;
 | 
						|
  }
 | 
						|
 | 
						|
  var ANNOT_MIN_SIZE = 10;
 | 
						|
 | 
						|
  Util.inherit(TextAnnotation, Annotation, {
 | 
						|
 | 
						|
    getOperatorList: function TextAnnotation_getOperatorList(evaluator) {
 | 
						|
      var promise = new Promise();
 | 
						|
      promise.resolve(new OperatorList());
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
 | 
						|
    hasHtml: function TextAnnotation_hasHtml() {
 | 
						|
      return true;
 | 
						|
    },
 | 
						|
 | 
						|
    getHtmlElement: function TextAnnotation_getHtmlElement(commonObjs) {
 | 
						|
      assert(!isWorker, 'getHtmlElement() shall be called from main thread');
 | 
						|
 | 
						|
      var item = this.data;
 | 
						|
      var rect = item.rect;
 | 
						|
 | 
						|
      // sanity check because of OOo-generated PDFs
 | 
						|
      if ((rect[3] - rect[1]) < ANNOT_MIN_SIZE) {
 | 
						|
        rect[3] = rect[1] + ANNOT_MIN_SIZE;
 | 
						|
      }
 | 
						|
      if ((rect[2] - rect[0]) < ANNOT_MIN_SIZE) {
 | 
						|
        rect[2] = rect[0] + (rect[3] - rect[1]); // make it square
 | 
						|
      }
 | 
						|
 | 
						|
      var container = this.getEmptyContainer('section', rect);
 | 
						|
      container.className = 'annotText';
 | 
						|
 | 
						|
      var image = document.createElement('img');
 | 
						|
      image.style.height = container.style.height;
 | 
						|
      var iconName = item.name;
 | 
						|
      image.src = PDFJS.imageResourcesPath + 'annotation-' +
 | 
						|
        iconName.toLowerCase() + '.svg';
 | 
						|
      image.alt = '[{{type}} Annotation]';
 | 
						|
      image.dataset.l10nId = 'text_annotation_type';
 | 
						|
      image.dataset.l10nArgs = JSON.stringify({type: iconName});
 | 
						|
      var content = document.createElement('div');
 | 
						|
      content.setAttribute('hidden', true);
 | 
						|
      var title = document.createElement('h1');
 | 
						|
      var text = document.createElement('p');
 | 
						|
      content.style.left = Math.floor(rect[2] - rect[0]) + 'px';
 | 
						|
      content.style.top = '0px';
 | 
						|
      title.textContent = item.title;
 | 
						|
 | 
						|
      if (!item.content && !item.title) {
 | 
						|
        content.setAttribute('hidden', true);
 | 
						|
      } else {
 | 
						|
        var e = document.createElement('span');
 | 
						|
        var lines = item.content.split(/(?:\r\n?|\n)/);
 | 
						|
        for (var i = 0, ii = lines.length; i < ii; ++i) {
 | 
						|
          var line = lines[i];
 | 
						|
          e.appendChild(document.createTextNode(line));
 | 
						|
          if (i < (ii - 1))
 | 
						|
            e.appendChild(document.createElement('br'));
 | 
						|
        }
 | 
						|
        text.appendChild(e);
 | 
						|
 | 
						|
        var showAnnotation = function showAnnotation() {
 | 
						|
          container.style.zIndex += 1;
 | 
						|
          content.removeAttribute('hidden');
 | 
						|
        };
 | 
						|
 | 
						|
        var hideAnnotation = function hideAnnotation(e) {
 | 
						|
          if (e.toElement || e.relatedTarget) { // No context menu is used
 | 
						|
            container.style.zIndex -= 1;
 | 
						|
            content.setAttribute('hidden', true);
 | 
						|
          }
 | 
						|
        };
 | 
						|
 | 
						|
        content.addEventListener('mouseover', showAnnotation, false);
 | 
						|
        content.addEventListener('mouseout', hideAnnotation, false);
 | 
						|
        image.addEventListener('mouseover', showAnnotation, false);
 | 
						|
        image.addEventListener('mouseout', hideAnnotation, false);
 | 
						|
      }
 | 
						|
 | 
						|
      content.appendChild(title);
 | 
						|
      content.appendChild(text);
 | 
						|
      container.appendChild(image);
 | 
						|
      container.appendChild(content);
 | 
						|
 | 
						|
      return container;
 | 
						|
    }
 | 
						|
  });
 | 
						|
 | 
						|
  return TextAnnotation;
 | 
						|
})();
 | 
						|
 | 
						|
var LinkAnnotation = (function LinkAnnotationClosure() {
 | 
						|
  function LinkAnnotation(params) {
 | 
						|
    Annotation.call(this, params);
 | 
						|
 | 
						|
    if (params.data) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    var dict = params.dict;
 | 
						|
    var data = this.data;
 | 
						|
 | 
						|
    var action = dict.get('A');
 | 
						|
    if (action) {
 | 
						|
      var linkType = action.get('S').name;
 | 
						|
      if (linkType === 'URI') {
 | 
						|
        var url = addDefaultProtocolToUrl(action.get('URI'));
 | 
						|
        // TODO: pdf spec mentions urls can be relative to a Base
 | 
						|
        // entry in the dictionary.
 | 
						|
        if (!isValidUrl(url, false)) {
 | 
						|
          url = '';
 | 
						|
        }
 | 
						|
        data.url = url;
 | 
						|
      } else if (linkType === 'GoTo') {
 | 
						|
        data.dest = action.get('D');
 | 
						|
      } else if (linkType === 'GoToR') {
 | 
						|
        var urlDict = action.get('F');
 | 
						|
        if (isDict(urlDict)) {
 | 
						|
          // We assume that the 'url' is a Filspec dictionary
 | 
						|
          // and fetch the url without checking any further
 | 
						|
          url = urlDict.get('F') || '';
 | 
						|
        }
 | 
						|
 | 
						|
        // TODO: pdf reference says that GoToR
 | 
						|
        // can also have 'NewWindow' attribute
 | 
						|
        if (!isValidUrl(url, false)) {
 | 
						|
          url = '';
 | 
						|
        }
 | 
						|
        data.url = url;
 | 
						|
        data.dest = action.get('D');
 | 
						|
      } else if (linkType === 'Named') {
 | 
						|
        data.action = action.get('N').name;
 | 
						|
      } else {
 | 
						|
        TODO('unrecognized link type: ' + linkType);
 | 
						|
      }
 | 
						|
    } else if (dict.has('Dest')) {
 | 
						|
      // simple destination link
 | 
						|
      var dest = dict.get('Dest');
 | 
						|
      data.dest = isName(dest) ? dest.name : dest;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Lets URLs beginning with 'www.' default to using the 'http://' protocol.
 | 
						|
  function addDefaultProtocolToUrl(url) {
 | 
						|
    if (url.indexOf('www.') === 0) {
 | 
						|
      return ('http://' + url);
 | 
						|
    }
 | 
						|
    return url;
 | 
						|
  }
 | 
						|
 | 
						|
  Util.inherit(LinkAnnotation, Annotation, {
 | 
						|
    hasOperatorList: function LinkAnnotation_hasOperatorList() {
 | 
						|
      return false;
 | 
						|
    },
 | 
						|
 | 
						|
    hasHtml: function LinkAnnotation_hasHtml() {
 | 
						|
      return true;
 | 
						|
    },
 | 
						|
 | 
						|
    getHtmlElement: function LinkAnnotation_getHtmlElement(commonObjs) {
 | 
						|
      var rect = this.data.rect;
 | 
						|
      var element = document.createElement('a');
 | 
						|
      var borderWidth = this.data.borderWidth;
 | 
						|
 | 
						|
      element.style.borderWidth = borderWidth + 'px';
 | 
						|
      var color = this.data.color;
 | 
						|
      var rgb = [];
 | 
						|
      for (var i = 0; i < 3; ++i) {
 | 
						|
        rgb[i] = Math.round(color[i] * 255);
 | 
						|
      }
 | 
						|
      element.style.borderColor = Util.makeCssRgb(rgb);
 | 
						|
      element.style.borderStyle = 'solid';
 | 
						|
 | 
						|
      var width = rect[2] - rect[0] - 2 * borderWidth;
 | 
						|
      var height = rect[3] - rect[1] - 2 * borderWidth;
 | 
						|
      element.style.width = width + 'px';
 | 
						|
      element.style.height = height + 'px';
 | 
						|
 | 
						|
      element.href = this.data.url || '';
 | 
						|
      return element;
 | 
						|
    }
 | 
						|
  });
 | 
						|
 | 
						|
  return LinkAnnotation;
 | 
						|
})();
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * The maximum allowed image size in total pixels e.g. width * height. Images
 | 
						|
 * above this value will not be drawn. Use -1 for no limit.
 | 
						|
 * @var {Number}
 | 
						|
 */
 | 
						|
PDFJS.maxImageSize = PDFJS.maxImageSize === undefined ? -1 : PDFJS.maxImageSize;
 | 
						|
 | 
						|
/**
 | 
						|
 * By default fonts are converted to OpenType fonts and loaded via font face
 | 
						|
 * rules. If disabled, the font will be rendered using a built in font renderer
 | 
						|
 * that constructs the glyphs with primitive path commands.
 | 
						|
 * @var {Boolean}
 | 
						|
 */
 | 
						|
PDFJS.disableFontFace = PDFJS.disableFontFace === undefined ?
 | 
						|
                        false : PDFJS.disableFontFace;
 | 
						|
 | 
						|
/**
 | 
						|
 * Path for image resources, mainly for annotation icons. Include trailing
 | 
						|
 * slash.
 | 
						|
 * @var {String}
 | 
						|
 */
 | 
						|
PDFJS.imageResourcesPath = PDFJS.imageResourcesPath === undefined ?
 | 
						|
                           '' : PDFJS.imageResourcesPath;
 | 
						|
 | 
						|
/**
 | 
						|
 * Disable the web worker and run all code on the main thread. This will happen
 | 
						|
 * automatically if the browser doesn't support workers or sending typed arrays
 | 
						|
 * to workers.
 | 
						|
 * @var {Boolean}
 | 
						|
 */
 | 
						|
PDFJS.disableWorker = PDFJS.disableWorker === undefined ?
 | 
						|
                      false : PDFJS.disableWorker;
 | 
						|
 | 
						|
/**
 | 
						|
 * Path and filename of the worker file. Required when the worker is enabled in
 | 
						|
 * development mode. If unspecified in the production build, the worker will be
 | 
						|
 * loaded based on the location of the pdf.js file.
 | 
						|
 * @var {String}
 | 
						|
 */
 | 
						|
PDFJS.workerSrc = PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc;
 | 
						|
 | 
						|
/**
 | 
						|
 * Disable range request loading of PDF files. When enabled and if the server
 | 
						|
 * supports partial content requests then the PDF will be fetched in chunks.
 | 
						|
 * Enabled (false) by default.
 | 
						|
 * @var {Boolean}
 | 
						|
 */
 | 
						|
PDFJS.disableRange = PDFJS.disableRange === undefined ?
 | 
						|
                     false : PDFJS.disableRange;
 | 
						|
 | 
						|
/**
 | 
						|
 * Disable pre-fetching of PDF file data. When range requests are enabled PDF.js
 | 
						|
 * will automatically keep fetching more data even if it isn't needed to display
 | 
						|
 * the current page. This default behavior can be disabled.
 | 
						|
 * @var {Boolean}
 | 
						|
 */
 | 
						|
PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ?
 | 
						|
                         false : PDFJS.disableAutoFetch;
 | 
						|
 | 
						|
/**
 | 
						|
 * Enables special hooks for debugging PDF.js.
 | 
						|
 * @var {Boolean}
 | 
						|
 */
 | 
						|
PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug;
 | 
						|
 | 
						|
/**
 | 
						|
 * Enables transfer usage in postMessage for ArrayBuffers.
 | 
						|
 * @var {boolean}
 | 
						|
 */
 | 
						|
PDFJS.postMessageTransfers = PDFJS.postMessageTransfers === undefined ?
 | 
						|
                             true : PDFJS.postMessageTransfers;
 | 
						|
/**
 | 
						|
 * This is the main entry point for loading a PDF and interacting with it.
 | 
						|
 * NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR)
 | 
						|
 * is used, which means it must follow the same origin rules that any XHR does
 | 
						|
 * e.g. No cross domain requests without CORS.
 | 
						|
 *
 | 
						|
 * @param {string|TypedAray|object} source Can be an url to where a PDF is
 | 
						|
 * located, a typed array (Uint8Array) already populated with data or
 | 
						|
 * and parameter object with the following possible fields:
 | 
						|
 *  - url   - The URL of the PDF.
 | 
						|
 *  - data  - A typed array with PDF data.
 | 
						|
 *  - httpHeaders - Basic authentication headers.
 | 
						|
 *  - password - For decrypting password-protected PDFs.
 | 
						|
 *  - initialData - A typed array with the first portion or all of the pdf data.
 | 
						|
 *                  Used by the extension since some data is already loaded
 | 
						|
 *                  before the switch to range requests. 
 | 
						|
 *
 | 
						|
 * @param {object} pdfDataRangeTransport is optional. It is used if you want
 | 
						|
 * to manually serve range requests for data in the PDF. See viewer.js for
 | 
						|
 * an example of pdfDataRangeTransport's interface.
 | 
						|
 *
 | 
						|
 * @param {function} passwordCallback is optional. It is used to request a
 | 
						|
 * password if wrong or no password was provided. The callback receives two
 | 
						|
 * parameters: function that needs to be called with new password and reason
 | 
						|
 * (see {PasswordResponses}).
 | 
						|
 *
 | 
						|
 * @return {Promise} A promise that is resolved with {PDFDocumentProxy} object.
 | 
						|
 */
 | 
						|
PDFJS.getDocument = function getDocument(source,
 | 
						|
                                         pdfDataRangeTransport,
 | 
						|
                                         passwordCallback,
 | 
						|
                                         progressCallback) {
 | 
						|
  var workerInitializedPromise, workerReadyPromise, transport;
 | 
						|
 | 
						|
  if (typeof source === 'string') {
 | 
						|
    source = { url: source };
 | 
						|
  } else if (isArrayBuffer(source)) {
 | 
						|
    source = { data: source };
 | 
						|
  } else if (typeof source !== 'object') {
 | 
						|
    error('Invalid parameter in getDocument, need either Uint8Array, ' +
 | 
						|
          'string or a parameter object');
 | 
						|
  }
 | 
						|
 | 
						|
  if (!source.url && !source.data)
 | 
						|
    error('Invalid parameter array, need either .data or .url');
 | 
						|
 | 
						|
  // copy/use all keys as is except 'url' -- full path is required
 | 
						|
  var params = {};
 | 
						|
  for (var key in source) {
 | 
						|
    if (key === 'url' && typeof window !== 'undefined') {
 | 
						|
      params[key] = combineUrl(window.location.href, source[key]);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    params[key] = source[key];
 | 
						|
  }
 | 
						|
 | 
						|
  workerInitializedPromise = new PDFJS.Promise();
 | 
						|
  workerReadyPromise = new PDFJS.Promise();
 | 
						|
  transport = new WorkerTransport(workerInitializedPromise,
 | 
						|
      workerReadyPromise, pdfDataRangeTransport, progressCallback);
 | 
						|
  workerInitializedPromise.then(function transportInitialized() {
 | 
						|
    transport.passwordCallback = passwordCallback;
 | 
						|
    transport.fetchDocument(params);
 | 
						|
  });
 | 
						|
  return workerReadyPromise;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Proxy to a PDFDocument in the worker thread. Also, contains commonly used
 | 
						|
 * properties that can be read synchronously.
 | 
						|
 */
 | 
						|
var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
 | 
						|
  function PDFDocumentProxy(pdfInfo, transport) {
 | 
						|
    this.pdfInfo = pdfInfo;
 | 
						|
    this.transport = transport;
 | 
						|
  }
 | 
						|
  PDFDocumentProxy.prototype = {
 | 
						|
    /**
 | 
						|
     * @return {number} Total number of pages the PDF contains.
 | 
						|
     */
 | 
						|
    get numPages() {
 | 
						|
      return this.pdfInfo.numPages;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {string} A unique ID to identify a PDF. Not guaranteed to be
 | 
						|
     * unique.
 | 
						|
     */
 | 
						|
    get fingerprint() {
 | 
						|
      return this.pdfInfo.fingerprint;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {boolean} true if embedded document fonts are in use. Will be
 | 
						|
     * set during rendering of the pages.
 | 
						|
     */
 | 
						|
    get embeddedFontsUsed() {
 | 
						|
      return this.transport.embeddedFontsUsed;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @param {number} The page number to get. The first page is 1.
 | 
						|
     * @return {Promise} A promise that is resolved with a {PDFPageProxy}
 | 
						|
     * object.
 | 
						|
     */
 | 
						|
    getPage: function PDFDocumentProxy_getPage(number) {
 | 
						|
      return this.transport.getPage(number);
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @param {object} Must have 'num' and 'gen' properties.
 | 
						|
     * @return {Promise} A promise that is resolved with the page index that is
 | 
						|
     * associated with the reference.
 | 
						|
     */
 | 
						|
    getPageIndex: function PDFDocumentProxy_getPageIndex(ref) {
 | 
						|
      return this.transport.getPageIndex(ref);
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {Promise} A promise that is resolved with a lookup table for
 | 
						|
     * mapping named destinations to reference numbers.
 | 
						|
     */
 | 
						|
    getDestinations: function PDFDocumentProxy_getDestinations() {
 | 
						|
      return this.transport.getDestinations();
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {Promise} A promise that is resolved with an array of all the
 | 
						|
     * JavaScript strings in the name tree.
 | 
						|
     */
 | 
						|
    getJavaScript: function PDFDocumentProxy_getDestinations() {
 | 
						|
      var promise = new PDFJS.Promise();
 | 
						|
      var js = this.pdfInfo.javaScript;
 | 
						|
      promise.resolve(js);
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {Promise} A promise that is resolved with an {array} that is a
 | 
						|
     * tree outline (if it has one) of the PDF. The tree is in the format of:
 | 
						|
     * [
 | 
						|
     *  {
 | 
						|
     *   title: string,
 | 
						|
     *   bold: boolean,
 | 
						|
     *   italic: boolean,
 | 
						|
     *   color: rgb array,
 | 
						|
     *   dest: dest obj,
 | 
						|
     *   items: array of more items like this
 | 
						|
     *  },
 | 
						|
     *  ...
 | 
						|
     * ].
 | 
						|
     */
 | 
						|
    getOutline: function PDFDocumentProxy_getOutline() {
 | 
						|
      var promise = new PDFJS.Promise();
 | 
						|
      var outline = this.pdfInfo.outline;
 | 
						|
      promise.resolve(outline);
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {Promise} A promise that is resolved with an {object} that has
 | 
						|
     * info and metadata properties.  Info is an {object} filled with anything
 | 
						|
     * available in the information dictionary and similarly metadata is a
 | 
						|
     * {Metadata} object with information from the metadata section of the PDF.
 | 
						|
     */
 | 
						|
    getMetadata: function PDFDocumentProxy_getMetadata() {
 | 
						|
      var promise = new PDFJS.Promise();
 | 
						|
      var info = this.pdfInfo.info;
 | 
						|
      var metadata = this.pdfInfo.metadata;
 | 
						|
      promise.resolve({
 | 
						|
        info: info,
 | 
						|
        metadata: metadata ? new PDFJS.Metadata(metadata) : null
 | 
						|
      });
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
    isEncrypted: function PDFDocumentProxy_isEncrypted() {
 | 
						|
      var promise = new PDFJS.Promise();
 | 
						|
      promise.resolve(this.pdfInfo.encrypted);
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {Promise} A promise that is resolved with a TypedArray that has
 | 
						|
     * the raw data from the PDF.
 | 
						|
     */
 | 
						|
    getData: function PDFDocumentProxy_getData() {
 | 
						|
      var promise = new PDFJS.Promise();
 | 
						|
      this.transport.getData(promise);
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {Promise} A promise that is resolved when the document's data
 | 
						|
     * is loaded
 | 
						|
     */
 | 
						|
    dataLoaded: function PDFDocumentProxy_dataLoaded() {
 | 
						|
      return this.transport.dataLoaded();
 | 
						|
    },
 | 
						|
    cleanup: function PDFDocumentProxy_cleanup() {
 | 
						|
      this.transport.startCleanup();
 | 
						|
    },
 | 
						|
    destroy: function PDFDocumentProxy_destroy() {
 | 
						|
      this.transport.destroy();
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return PDFDocumentProxy;
 | 
						|
})();
 | 
						|
 | 
						|
var PDFPageProxy = (function PDFPageProxyClosure() {
 | 
						|
  function PDFPageProxy(pageInfo, transport) {
 | 
						|
    this.pageInfo = pageInfo;
 | 
						|
    this.transport = transport;
 | 
						|
    this.stats = new StatTimer();
 | 
						|
    this.stats.enabled = !!globalScope.PDFJS.enableStats;
 | 
						|
    this.commonObjs = transport.commonObjs;
 | 
						|
    this.objs = new PDFObjects();
 | 
						|
    this.receivingOperatorList  = false;
 | 
						|
    this.cleanupAfterRender = false;
 | 
						|
    this.pendingDestroy = false;
 | 
						|
    this.renderTasks = [];
 | 
						|
  }
 | 
						|
  PDFPageProxy.prototype = {
 | 
						|
    /**
 | 
						|
     * @return {number} Page number of the page. First page is 1.
 | 
						|
     */
 | 
						|
    get pageNumber() {
 | 
						|
      return this.pageInfo.pageIndex + 1;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {number} The number of degrees the page is rotated clockwise.
 | 
						|
     */
 | 
						|
    get rotate() {
 | 
						|
      return this.pageInfo.rotate;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {object} The reference that points to this page. It has 'num' and
 | 
						|
     * 'gen' properties.
 | 
						|
     */
 | 
						|
    get ref() {
 | 
						|
      return this.pageInfo.ref;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {array} An array of the visible portion of the PDF page in the
 | 
						|
     * user space units - [x1, y1, x2, y2].
 | 
						|
     */
 | 
						|
    get view() {
 | 
						|
      return this.pageInfo.view;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @param {number} scale The desired scale of the viewport.
 | 
						|
     * @param {number} rotate Degrees to rotate the viewport. If omitted this
 | 
						|
     * defaults to the page rotation.
 | 
						|
     * @return {PageViewport} Contains 'width' and 'height' properties along
 | 
						|
     * with transforms required for rendering.
 | 
						|
     */
 | 
						|
    getViewport: function PDFPageProxy_getViewport(scale, rotate) {
 | 
						|
      if (arguments.length < 2)
 | 
						|
        rotate = this.rotate;
 | 
						|
      return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {Promise} A promise that is resolved with an {array} of the
 | 
						|
     * annotation objects.
 | 
						|
     */
 | 
						|
    getAnnotations: function PDFPageProxy_getAnnotations() {
 | 
						|
      if (this.annotationsPromise)
 | 
						|
        return this.annotationsPromise;
 | 
						|
 | 
						|
      var promise = new PDFJS.Promise();
 | 
						|
      this.annotationsPromise = promise;
 | 
						|
      this.transport.getAnnotations(this.pageInfo.pageIndex);
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * Begins the process of rendering a page to the desired context.
 | 
						|
     * @param {object} params A parameter object that supports:
 | 
						|
     * {
 | 
						|
     *   canvasContext(required): A 2D context of a DOM Canvas object.,
 | 
						|
     *   textLayer(optional): An object that has beginLayout, endLayout, and
 | 
						|
     *                        appendText functions.,
 | 
						|
     *   imageLayer(optional): An object that has beginLayout, endLayout and
 | 
						|
     *                         appendImage functions.,
 | 
						|
     *   continueCallback(optional): A function that will be called each time
 | 
						|
     *                               the rendering is paused.  To continue
 | 
						|
     *                               rendering call the function that is the
 | 
						|
     *                               first argument to the callback.
 | 
						|
     * }.
 | 
						|
     * @return {RenderTask} An extended promise that is resolved when the page
 | 
						|
     * finishes rendering (see RenderTask).
 | 
						|
     */
 | 
						|
    render: function PDFPageProxy_render(params) {
 | 
						|
      var stats = this.stats;
 | 
						|
      stats.time('Overall');
 | 
						|
 | 
						|
      // If there was a pending destroy cancel it so no cleanup happens during
 | 
						|
      // this call to render.
 | 
						|
      this.pendingDestroy = false;
 | 
						|
 | 
						|
      // If there is no displayReadyPromise yet, then the operatorList was never
 | 
						|
      // requested before. Make the request and create the promise.
 | 
						|
      if (!this.displayReadyPromise) {
 | 
						|
        this.receivingOperatorList = true;
 | 
						|
        this.displayReadyPromise = new Promise();
 | 
						|
        this.operatorList = {
 | 
						|
          fnArray: [],
 | 
						|
          argsArray: [],
 | 
						|
          lastChunk: false
 | 
						|
        };
 | 
						|
 | 
						|
        this.stats.time('Page Request');
 | 
						|
        this.transport.messageHandler.send('RenderPageRequest', {
 | 
						|
          pageIndex: this.pageNumber - 1
 | 
						|
        });
 | 
						|
      }
 | 
						|
 | 
						|
      var internalRenderTask = new InternalRenderTask(complete, params,
 | 
						|
                                       this.objs, this.commonObjs,
 | 
						|
                                       this.operatorList, this.pageNumber);
 | 
						|
      this.renderTasks.push(internalRenderTask);
 | 
						|
      var renderTask = new RenderTask(internalRenderTask);
 | 
						|
 | 
						|
      var self = this;
 | 
						|
      this.displayReadyPromise.then(
 | 
						|
        function pageDisplayReadyPromise(transparency) {
 | 
						|
          if (self.pendingDestroy) {
 | 
						|
            complete();
 | 
						|
            return;
 | 
						|
          }
 | 
						|
          stats.time('Rendering');
 | 
						|
          internalRenderTask.initalizeGraphics(transparency);
 | 
						|
          internalRenderTask.operatorListChanged();
 | 
						|
        },
 | 
						|
        function pageDisplayReadPromiseError(reason) {
 | 
						|
          complete(reason);
 | 
						|
        }
 | 
						|
      );
 | 
						|
 | 
						|
      function complete(error) {
 | 
						|
        var i = self.renderTasks.indexOf(internalRenderTask);
 | 
						|
        if (i >= 0) {
 | 
						|
          self.renderTasks.splice(i, 1);
 | 
						|
        }
 | 
						|
 | 
						|
        if (self.cleanupAfterRender) {
 | 
						|
          self.pendingDestroy = true;
 | 
						|
        }
 | 
						|
        self._tryDestroy();
 | 
						|
 | 
						|
        if (error) {
 | 
						|
          renderTask.reject(error);
 | 
						|
        } else {
 | 
						|
          renderTask.resolve();
 | 
						|
        }
 | 
						|
        stats.timeEnd('Rendering');
 | 
						|
        stats.timeEnd('Overall');
 | 
						|
      }
 | 
						|
 | 
						|
      return renderTask;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * @return {Promise} That is resolved with the a {string} that is the text
 | 
						|
     * content from the page.
 | 
						|
     */
 | 
						|
    getTextContent: function PDFPageProxy_getTextContent() {
 | 
						|
      var promise = new PDFJS.Promise();
 | 
						|
      this.transport.messageHandler.send('GetTextContent', {
 | 
						|
          pageIndex: this.pageNumber - 1
 | 
						|
        },
 | 
						|
        function textContentCallback(textContent) {
 | 
						|
          promise.resolve(textContent);
 | 
						|
        }
 | 
						|
      );
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * Stub for future feature.
 | 
						|
     */
 | 
						|
    getOperationList: function PDFPageProxy_getOperationList() {
 | 
						|
      var promise = new PDFJS.Promise();
 | 
						|
      var operationList = { // not implemented
 | 
						|
        dependencyFontsID: null,
 | 
						|
        operatorList: null
 | 
						|
      };
 | 
						|
      promise.resolve(operationList);
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * Destroys resources allocated by the page.
 | 
						|
     */
 | 
						|
    destroy: function PDFPageProxy_destroy() {
 | 
						|
      this.pendingDestroy = true;
 | 
						|
      this._tryDestroy();
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * For internal use only. Attempts to clean up if rendering is in a state
 | 
						|
     * where that's possible.
 | 
						|
     */
 | 
						|
    _tryDestroy: function PDFPageProxy__destroy() {
 | 
						|
      if (!this.pendingDestroy ||
 | 
						|
          this.renderTasks.length !== 0 ||
 | 
						|
          this.receivingOperatorList) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      delete this.operatorList;
 | 
						|
      delete this.displayReadyPromise;
 | 
						|
      this.objs.clear();
 | 
						|
      this.pendingDestroy = false;
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * For internal use only.
 | 
						|
     */
 | 
						|
    _startRenderPage: function PDFPageProxy_startRenderPage(transparency) {
 | 
						|
      this.displayReadyPromise.resolve(transparency);
 | 
						|
    },
 | 
						|
    /**
 | 
						|
     * For internal use only.
 | 
						|
     */
 | 
						|
    _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk) {
 | 
						|
      // Add the new chunk to the current operator list.
 | 
						|
      for (var i = 0, ii = operatorListChunk.length; i < ii; i++) {
 | 
						|
        this.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
 | 
						|
        this.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
 | 
						|
      }
 | 
						|
      this.operatorList.lastChunk = operatorListChunk.lastChunk;
 | 
						|
 | 
						|
      // Notify all the rendering tasks there are more operators to be consumed.
 | 
						|
      for (var i = 0; i < this.renderTasks.length; i++) {
 | 
						|
        this.renderTasks[i].operatorListChanged();
 | 
						|
      }
 | 
						|
 | 
						|
      if (operatorListChunk.lastChunk) {
 | 
						|
        this.receivingOperatorList = false;
 | 
						|
        this._tryDestroy();
 | 
						|
      }
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return PDFPageProxy;
 | 
						|
})();
 | 
						|
/**
 | 
						|
 * For internal use only.
 | 
						|
 */
 | 
						|
var WorkerTransport = (function WorkerTransportClosure() {
 | 
						|
  function WorkerTransport(workerInitializedPromise, workerReadyPromise,
 | 
						|
      pdfDataRangeTransport, progressCallback) {
 | 
						|
    this.pdfDataRangeTransport = pdfDataRangeTransport;
 | 
						|
 | 
						|
    this.workerReadyPromise = workerReadyPromise;
 | 
						|
    this.progressCallback = progressCallback;
 | 
						|
    this.commonObjs = new PDFObjects();
 | 
						|
 | 
						|
    this.pageCache = [];
 | 
						|
    this.pagePromises = [];
 | 
						|
    this.embeddedFontsUsed = false;
 | 
						|
 | 
						|
    this.passwordCallback = null;
 | 
						|
 | 
						|
    // If worker support isn't disabled explicit and the browser has worker
 | 
						|
    // support, create a new web worker and test if it/the browser fullfills
 | 
						|
    // all requirements to run parts of pdf.js in a web worker.
 | 
						|
    // Right now, the requirement is, that an Uint8Array is still an Uint8Array
 | 
						|
    // as it arrives on the worker. Chrome added this with version 15.
 | 
						|
    if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
 | 
						|
      var workerSrc = PDFJS.workerSrc;
 | 
						|
      if (!workerSrc) {
 | 
						|
        error('No PDFJS.workerSrc specified');
 | 
						|
      }
 | 
						|
 | 
						|
      try {
 | 
						|
        // Some versions of FF can't create a worker on localhost, see:
 | 
						|
        // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
 | 
						|
        var worker = new Worker(workerSrc);
 | 
						|
        var messageHandler = new MessageHandler('main', worker);
 | 
						|
        this.messageHandler = messageHandler;
 | 
						|
 | 
						|
        messageHandler.on('test', function transportTest(data) {
 | 
						|
          var supportTypedArray = data && data.supportTypedArray;
 | 
						|
          if (supportTypedArray) {
 | 
						|
            this.worker = worker;
 | 
						|
            if (!data.supportTransfers) {
 | 
						|
              PDFJS.postMessageTransfers = false;
 | 
						|
            }
 | 
						|
            this.setupMessageHandler(messageHandler);
 | 
						|
            workerInitializedPromise.resolve();
 | 
						|
          } else {
 | 
						|
            globalScope.PDFJS.disableWorker = true;
 | 
						|
            this.loadFakeWorkerFiles().then(function() {
 | 
						|
              this.setupFakeWorker();
 | 
						|
              workerInitializedPromise.resolve();
 | 
						|
            }.bind(this));
 | 
						|
          }
 | 
						|
        }.bind(this));
 | 
						|
 | 
						|
        var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]);
 | 
						|
        // Some versions of Opera throw a DATA_CLONE_ERR on serializing the
 | 
						|
        // typed array. Also, checking if we can use transfers.
 | 
						|
        try {
 | 
						|
          messageHandler.send('test', testObj, null, [testObj.buffer]);
 | 
						|
        } catch (ex) {
 | 
						|
          info('Cannot use postMessage transfers');
 | 
						|
          testObj[0] = 0;
 | 
						|
          messageHandler.send('test', testObj);
 | 
						|
        }
 | 
						|
        return;
 | 
						|
      } catch (e) {
 | 
						|
        info('The worker has been disabled.');
 | 
						|
      }
 | 
						|
    }
 | 
						|
    // Either workers are disabled, not supported or have thrown an exception.
 | 
						|
    // Thus, we fallback to a faked worker.
 | 
						|
    globalScope.PDFJS.disableWorker = true;
 | 
						|
    this.loadFakeWorkerFiles().then(function() {
 | 
						|
      this.setupFakeWorker();
 | 
						|
      workerInitializedPromise.resolve();
 | 
						|
    }.bind(this));
 | 
						|
  }
 | 
						|
  WorkerTransport.prototype = {
 | 
						|
    destroy: function WorkerTransport_destroy() {
 | 
						|
      this.pageCache = [];
 | 
						|
      this.pagePromises = [];
 | 
						|
      var self = this;
 | 
						|
      this.messageHandler.send('Terminate', null, function () {
 | 
						|
        if (self.worker) {
 | 
						|
          self.worker.terminate();
 | 
						|
        }
 | 
						|
      });
 | 
						|
    },
 | 
						|
 | 
						|
    loadFakeWorkerFiles: function WorkerTransport_loadFakeWorkerFiles() {
 | 
						|
      if (!PDFJS.fakeWorkerFilesLoadedPromise) {
 | 
						|
        PDFJS.fakeWorkerFilesLoadedPromise = new Promise();
 | 
						|
        // In the developer build load worker_loader which in turn loads all the
 | 
						|
        // other files and resolves the promise. In production only the
 | 
						|
        // pdf.worker.js file is needed.
 | 
						|
        Util.loadScript(PDFJS.workerSrc, function() {
 | 
						|
          PDFJS.fakeWorkerFilesLoadedPromise.resolve();
 | 
						|
        });
 | 
						|
      }
 | 
						|
      return PDFJS.fakeWorkerFilesLoadedPromise;
 | 
						|
    },
 | 
						|
 | 
						|
    setupFakeWorker: function WorkerTransport_setupFakeWorker() {
 | 
						|
      warn('Setting up fake worker.');
 | 
						|
      // If we don't use a worker, just post/sendMessage to the main thread.
 | 
						|
      var fakeWorker = {
 | 
						|
        postMessage: function WorkerTransport_postMessage(obj) {
 | 
						|
          fakeWorker.onmessage({data: obj});
 | 
						|
        },
 | 
						|
        terminate: function WorkerTransport_terminate() {}
 | 
						|
      };
 | 
						|
 | 
						|
      var messageHandler = new MessageHandler('main', fakeWorker);
 | 
						|
      this.setupMessageHandler(messageHandler);
 | 
						|
 | 
						|
      // If the main thread is our worker, setup the handling for the messages
 | 
						|
      // the main thread sends to it self.
 | 
						|
      PDFJS.WorkerMessageHandler.setup(messageHandler);
 | 
						|
    },
 | 
						|
 | 
						|
    setupMessageHandler:
 | 
						|
      function WorkerTransport_setupMessageHandler(messageHandler) {
 | 
						|
      this.messageHandler = messageHandler;
 | 
						|
 | 
						|
      function updatePassword(password) {
 | 
						|
        messageHandler.send('UpdatePassword', password);
 | 
						|
      }
 | 
						|
 | 
						|
      var pdfDataRangeTransport = this.pdfDataRangeTransport;
 | 
						|
      if (pdfDataRangeTransport) {
 | 
						|
        pdfDataRangeTransport.addRangeListener(function(begin, chunk) {
 | 
						|
          messageHandler.send('OnDataRange', {
 | 
						|
            begin: begin,
 | 
						|
            chunk: chunk
 | 
						|
          });
 | 
						|
        });
 | 
						|
 | 
						|
        pdfDataRangeTransport.addProgressListener(function(loaded) {
 | 
						|
          messageHandler.send('OnDataProgress', {
 | 
						|
            loaded: loaded
 | 
						|
          });
 | 
						|
        });
 | 
						|
 | 
						|
        messageHandler.on('RequestDataRange',
 | 
						|
          function transportDataRange(data) {
 | 
						|
            pdfDataRangeTransport.requestDataRange(data.begin, data.end);
 | 
						|
          }, this);
 | 
						|
      }
 | 
						|
 | 
						|
      messageHandler.on('GetDoc', function transportDoc(data) {
 | 
						|
        var pdfInfo = data.pdfInfo;
 | 
						|
        var pdfDocument = new PDFDocumentProxy(pdfInfo, this);
 | 
						|
        this.pdfDocument = pdfDocument;
 | 
						|
        this.workerReadyPromise.resolve(pdfDocument);
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('NeedPassword', function transportPassword(data) {
 | 
						|
        if (this.passwordCallback) {
 | 
						|
          return this.passwordCallback(updatePassword,
 | 
						|
                                       PasswordResponses.NEED_PASSWORD);
 | 
						|
        }
 | 
						|
        this.workerReadyPromise.reject(data.exception.message, data.exception);
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('IncorrectPassword', function transportBadPass(data) {
 | 
						|
        if (this.passwordCallback) {
 | 
						|
          return this.passwordCallback(updatePassword,
 | 
						|
                                       PasswordResponses.INCORRECT_PASSWORD);
 | 
						|
        }
 | 
						|
        this.workerReadyPromise.reject(data.exception.message, data.exception);
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('InvalidPDF', function transportInvalidPDF(data) {
 | 
						|
        this.workerReadyPromise.reject(data.exception.name, data.exception);
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('MissingPDF', function transportMissingPDF(data) {
 | 
						|
        this.workerReadyPromise.reject(data.exception.message, data.exception);
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('UnknownError', function transportUnknownError(data) {
 | 
						|
        this.workerReadyPromise.reject(data.exception.message, data.exception);
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('GetPage', function transportPage(data) {
 | 
						|
        var pageInfo = data.pageInfo;
 | 
						|
        var page = new PDFPageProxy(pageInfo, this);
 | 
						|
        this.pageCache[pageInfo.pageIndex] = page;
 | 
						|
        var promise = this.pagePromises[pageInfo.pageIndex];
 | 
						|
        promise.resolve(page);
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('GetAnnotations', function transportAnnotations(data) {
 | 
						|
        var annotations = data.annotations;
 | 
						|
        var promise = this.pageCache[data.pageIndex].annotationsPromise;
 | 
						|
        promise.resolve(annotations);
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('StartRenderPage', function transportRender(data) {
 | 
						|
        var page = this.pageCache[data.pageIndex];
 | 
						|
 | 
						|
        page.stats.timeEnd('Page Request');
 | 
						|
        page._startRenderPage(data.transparency);
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('RenderPageChunk', function transportRender(data) {
 | 
						|
        var page = this.pageCache[data.pageIndex];
 | 
						|
 | 
						|
        page._renderPageChunk(data.operatorList);
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('commonobj', function transportObj(data) {
 | 
						|
        var id = data[0];
 | 
						|
        var type = data[1];
 | 
						|
        if (this.commonObjs.hasData(id))
 | 
						|
          return;
 | 
						|
 | 
						|
        switch (type) {
 | 
						|
          case 'Font':
 | 
						|
            var exportedData = data[2];
 | 
						|
 | 
						|
            var font;
 | 
						|
            if ('error' in exportedData) {
 | 
						|
              var error = exportedData.error;
 | 
						|
              warn('Error during font loading: ' + error);
 | 
						|
              this.commonObjs.resolve(id, error);
 | 
						|
              break;
 | 
						|
            } else {
 | 
						|
              font = new FontFace(exportedData);
 | 
						|
            }
 | 
						|
 | 
						|
            FontLoader.bind(
 | 
						|
              [font],
 | 
						|
              function fontReady(fontObjs) {
 | 
						|
                this.commonObjs.resolve(id, font);
 | 
						|
              }.bind(this)
 | 
						|
            );
 | 
						|
            break;
 | 
						|
          case 'FontPath':
 | 
						|
            this.commonObjs.resolve(id, data[2]);
 | 
						|
            break;
 | 
						|
          default:
 | 
						|
            error('Got unknown common object type ' + type);
 | 
						|
        }
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('obj', function transportObj(data) {
 | 
						|
        var id = data[0];
 | 
						|
        var pageIndex = data[1];
 | 
						|
        var type = data[2];
 | 
						|
        var pageProxy = this.pageCache[pageIndex];
 | 
						|
        if (pageProxy.objs.hasData(id))
 | 
						|
          return;
 | 
						|
 | 
						|
        switch (type) {
 | 
						|
          case 'JpegStream':
 | 
						|
            var imageData = data[3];
 | 
						|
            loadJpegStream(id, imageData, pageProxy.objs);
 | 
						|
            break;
 | 
						|
          case 'Image':
 | 
						|
            var imageData = data[3];
 | 
						|
            pageProxy.objs.resolve(id, imageData);
 | 
						|
 | 
						|
            // heuristics that will allow not to store large data
 | 
						|
            var MAX_IMAGE_SIZE_TO_STORE = 8000000;
 | 
						|
            if ('data' in imageData &&
 | 
						|
                imageData.data.length > MAX_IMAGE_SIZE_TO_STORE) {
 | 
						|
              pageProxy.cleanupAfterRender = true;
 | 
						|
            }
 | 
						|
            break;
 | 
						|
          default:
 | 
						|
            error('Got unknown object type ' + type);
 | 
						|
        }
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('DocProgress', function transportDocProgress(data) {
 | 
						|
        if (this.progressCallback) {
 | 
						|
          this.progressCallback({
 | 
						|
            loaded: data.loaded,
 | 
						|
            total: data.total
 | 
						|
          });
 | 
						|
        }
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('DocError', function transportDocError(data) {
 | 
						|
        this.workerReadyPromise.reject(data);
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('PageError', function transportError(data) {
 | 
						|
        var page = this.pageCache[data.pageNum - 1];
 | 
						|
        if (page.displayReadyPromise)
 | 
						|
          page.displayReadyPromise.reject(data.error);
 | 
						|
        else
 | 
						|
          error(data.error);
 | 
						|
      }, this);
 | 
						|
 | 
						|
      messageHandler.on('JpegDecode', function(data, promise) {
 | 
						|
        var imageUrl = data[0];
 | 
						|
        var components = data[1];
 | 
						|
        if (components != 3 && components != 1)
 | 
						|
          error('Only 3 component or 1 component can be returned');
 | 
						|
 | 
						|
        var img = new Image();
 | 
						|
        img.onload = (function messageHandler_onloadClosure() {
 | 
						|
          var width = img.width;
 | 
						|
          var height = img.height;
 | 
						|
          var size = width * height;
 | 
						|
          var rgbaLength = size * 4;
 | 
						|
          var buf = new Uint8Array(size * components);
 | 
						|
          var tmpCanvas = createScratchCanvas(width, height);
 | 
						|
          var tmpCtx = tmpCanvas.getContext('2d');
 | 
						|
          tmpCtx.drawImage(img, 0, 0);
 | 
						|
          var data = tmpCtx.getImageData(0, 0, width, height).data;
 | 
						|
 | 
						|
          if (components == 3) {
 | 
						|
            for (var i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
 | 
						|
              buf[j] = data[i];
 | 
						|
              buf[j + 1] = data[i + 1];
 | 
						|
              buf[j + 2] = data[i + 2];
 | 
						|
            }
 | 
						|
          } else if (components == 1) {
 | 
						|
            for (var i = 0, j = 0; i < rgbaLength; i += 4, j++) {
 | 
						|
              buf[j] = data[i];
 | 
						|
            }
 | 
						|
          }
 | 
						|
          promise.resolve({ data: buf, width: width, height: height});
 | 
						|
        }).bind(this);
 | 
						|
        img.src = imageUrl;
 | 
						|
      });
 | 
						|
    },
 | 
						|
 | 
						|
    fetchDocument: function WorkerTransport_fetchDocument(source) {
 | 
						|
      source.disableAutoFetch = PDFJS.disableAutoFetch;
 | 
						|
      source.chunkedViewerLoading = !!this.pdfDataRangeTransport;
 | 
						|
      this.messageHandler.send('GetDocRequest', {
 | 
						|
        source: source,
 | 
						|
        disableRange: PDFJS.disableRange,
 | 
						|
        maxImageSize: PDFJS.maxImageSize,
 | 
						|
        disableFontFace: PDFJS.disableFontFace
 | 
						|
      });
 | 
						|
    },
 | 
						|
 | 
						|
    getData: function WorkerTransport_getData(promise) {
 | 
						|
      this.messageHandler.send('GetData', null, function(data) {
 | 
						|
        promise.resolve(data);
 | 
						|
      });
 | 
						|
    },
 | 
						|
 | 
						|
    dataLoaded: function WorkerTransport_dataLoaded() {
 | 
						|
      var promise = new PDFJS.Promise();
 | 
						|
      this.messageHandler.send('DataLoaded', null, function(args) {
 | 
						|
        promise.resolve(args);
 | 
						|
      });
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
 | 
						|
    getPage: function WorkerTransport_getPage(pageNumber, promise) {
 | 
						|
      var pageIndex = pageNumber - 1;
 | 
						|
      if (pageIndex in this.pagePromises)
 | 
						|
        return this.pagePromises[pageIndex];
 | 
						|
      var promise = new PDFJS.Promise('Page ' + pageNumber);
 | 
						|
      this.pagePromises[pageIndex] = promise;
 | 
						|
      this.messageHandler.send('GetPageRequest', { pageIndex: pageIndex });
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
 | 
						|
    getPageIndex: function WorkerTransport_getPageIndexByRef(ref) {
 | 
						|
      var promise = new PDFJS.Promise();
 | 
						|
      this.messageHandler.send('GetPageIndex', { ref: ref },
 | 
						|
        function (pageIndex) {
 | 
						|
          promise.resolve(pageIndex);
 | 
						|
        }
 | 
						|
      );
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
 | 
						|
    getAnnotations: function WorkerTransport_getAnnotations(pageIndex) {
 | 
						|
      this.messageHandler.send('GetAnnotationsRequest',
 | 
						|
        { pageIndex: pageIndex });
 | 
						|
    },
 | 
						|
 | 
						|
    getDestinations: function WorkerTransport_getDestinations() {
 | 
						|
      var promise = new PDFJS.Promise();
 | 
						|
      this.messageHandler.send('GetDestinations', null,
 | 
						|
        function transportDestinations(destinations) {
 | 
						|
          promise.resolve(destinations);
 | 
						|
        }
 | 
						|
      );
 | 
						|
      return promise;
 | 
						|
    },
 | 
						|
 | 
						|
    startCleanup: function WorkerTransport_startCleanup() {
 | 
						|
      this.messageHandler.send('Cleanup', null,
 | 
						|
        function endCleanup() {
 | 
						|
          for (var i = 0, ii = this.pageCache.length; i < ii; i++) {
 | 
						|
            var page = this.pageCache[i];
 | 
						|
            if (page) {
 | 
						|
              page.destroy();
 | 
						|
            }
 | 
						|
          }
 | 
						|
          this.commonObjs.clear();
 | 
						|
          FontLoader.clear();
 | 
						|
        }.bind(this)
 | 
						|
      );
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return WorkerTransport;
 | 
						|
 | 
						|
})();
 | 
						|
 | 
						|
/**
 | 
						|
 * A PDF document and page is built of many objects. E.g. there are objects
 | 
						|
 * for fonts, images, rendering code and such. These objects might get processed
 | 
						|
 * inside of a worker. The `PDFObjects` implements some basic functions to
 | 
						|
 * manage these objects.
 | 
						|
 */
 | 
						|
var PDFObjects = (function PDFObjectsClosure() {
 | 
						|
  function PDFObjects() {
 | 
						|
    this.objs = {};
 | 
						|
  }
 | 
						|
 | 
						|
  PDFObjects.prototype = {
 | 
						|
    /**
 | 
						|
     * Internal function.
 | 
						|
     * Ensures there is an object defined for `objId`.
 | 
						|
     */
 | 
						|
    ensureObj: function PDFObjects_ensureObj(objId) {
 | 
						|
      if (this.objs[objId])
 | 
						|
        return this.objs[objId];
 | 
						|
 | 
						|
      var obj = {
 | 
						|
        promise: new Promise(objId),
 | 
						|
        data: null,
 | 
						|
        resolved: false
 | 
						|
      };
 | 
						|
      this.objs[objId] = obj;
 | 
						|
 | 
						|
      return obj;
 | 
						|
    },
 | 
						|
 | 
						|
    /**
 | 
						|
     * If called *without* callback, this returns the data of `objId` but the
 | 
						|
     * object needs to be resolved. If it isn't, this function throws.
 | 
						|
     *
 | 
						|
     * If called *with* a callback, the callback is called with the data of the
 | 
						|
     * object once the object is resolved. That means, if you call this
 | 
						|
     * function and the object is already resolved, the callback gets called
 | 
						|
     * right away.
 | 
						|
     */
 | 
						|
    get: function PDFObjects_get(objId, callback) {
 | 
						|
      // If there is a callback, then the get can be async and the object is
 | 
						|
      // not required to be resolved right now
 | 
						|
      if (callback) {
 | 
						|
        this.ensureObj(objId).promise.then(callback);
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      // If there isn't a callback, the user expects to get the resolved data
 | 
						|
      // directly.
 | 
						|
      var obj = this.objs[objId];
 | 
						|
 | 
						|
      // If there isn't an object yet or the object isn't resolved, then the
 | 
						|
      // data isn't ready yet!
 | 
						|
      if (!obj || !obj.resolved)
 | 
						|
        error('Requesting object that isn\'t resolved yet ' + objId);
 | 
						|
 | 
						|
      return obj.data;
 | 
						|
    },
 | 
						|
 | 
						|
    /**
 | 
						|
     * Resolves the object `objId` with optional `data`.
 | 
						|
     */
 | 
						|
    resolve: function PDFObjects_resolve(objId, data) {
 | 
						|
      var obj = this.ensureObj(objId);
 | 
						|
 | 
						|
      obj.resolved = true;
 | 
						|
      obj.data = data;
 | 
						|
      obj.promise.resolve(data);
 | 
						|
    },
 | 
						|
 | 
						|
    isResolved: function PDFObjects_isResolved(objId) {
 | 
						|
      var objs = this.objs;
 | 
						|
 | 
						|
      if (!objs[objId]) {
 | 
						|
        return false;
 | 
						|
      } else {
 | 
						|
        return objs[objId].resolved;
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    hasData: function PDFObjects_hasData(objId) {
 | 
						|
      return this.isResolved(objId);
 | 
						|
    },
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the data of `objId` if object exists, null otherwise.
 | 
						|
     */
 | 
						|
    getData: function PDFObjects_getData(objId) {
 | 
						|
      var objs = this.objs;
 | 
						|
      if (!objs[objId] || !objs[objId].resolved) {
 | 
						|
        return null;
 | 
						|
      } else {
 | 
						|
        return objs[objId].data;
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    clear: function PDFObjects_clear() {
 | 
						|
      this.objs = {};
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return PDFObjects;
 | 
						|
})();
 | 
						|
/*
 | 
						|
 * RenderTask is basically a promise but adds a cancel function to terminate it.
 | 
						|
 */
 | 
						|
var RenderTask = (function RenderTaskClosure() {
 | 
						|
  function RenderTask(internalRenderTask) {
 | 
						|
    this.internalRenderTask = internalRenderTask;
 | 
						|
    Promise.call(this);
 | 
						|
  }
 | 
						|
 | 
						|
  RenderTask.prototype = Object.create(Promise.prototype);
 | 
						|
 | 
						|
  /**
 | 
						|
   * Cancel the rendering task. If the task is curently rendering it will not be
 | 
						|
   * cancelled until graphics pauses with a timeout. The promise that this
 | 
						|
   * object extends will resolved when cancelled.
 | 
						|
   */
 | 
						|
  RenderTask.prototype.cancel = function RenderTask_cancel() {
 | 
						|
    this.internalRenderTask.cancel();
 | 
						|
  };
 | 
						|
 | 
						|
  return RenderTask;
 | 
						|
})();
 | 
						|
 | 
						|
var InternalRenderTask = (function InternalRenderTaskClosure() {
 | 
						|
 | 
						|
  function InternalRenderTask(callback, params, objs, commonObjs, operatorList,
 | 
						|
                              pageNumber) {
 | 
						|
    this.callback = callback;
 | 
						|
    this.params = params;
 | 
						|
    this.objs = objs;
 | 
						|
    this.commonObjs = commonObjs;
 | 
						|
    this.operatorListIdx = null;
 | 
						|
    this.operatorList = operatorList;
 | 
						|
    this.pageNumber = pageNumber;
 | 
						|
    this.running = false;
 | 
						|
    this.graphicsReadyCallback = null;
 | 
						|
    this.graphicsReady = false;
 | 
						|
    this.cancelled = false;
 | 
						|
  }
 | 
						|
 | 
						|
  InternalRenderTask.prototype = {
 | 
						|
 | 
						|
    initalizeGraphics:
 | 
						|
        function InternalRenderTask_initalizeGraphics(transparency) {
 | 
						|
 | 
						|
      if (this.cancelled) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      if (PDFJS.pdfBug && 'StepperManager' in globalScope &&
 | 
						|
          globalScope.StepperManager.enabled) {
 | 
						|
        this.stepper = globalScope.StepperManager.create(this.pageNumber - 1);
 | 
						|
        this.stepper.init(this.operatorList);
 | 
						|
        this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
 | 
						|
      }
 | 
						|
 | 
						|
      var params = this.params;
 | 
						|
      this.gfx = new CanvasGraphics(params.canvasContext, this.commonObjs,
 | 
						|
                                    this.objs, params.textLayer,
 | 
						|
                                    params.imageLayer);
 | 
						|
 | 
						|
      this.gfx.beginDrawing(params.viewport, transparency);
 | 
						|
      this.operatorListIdx = 0;
 | 
						|
      this.graphicsReady = true;
 | 
						|
      if (this.graphicsReadyCallback) {
 | 
						|
        this.graphicsReadyCallback();
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    cancel: function InternalRenderTask_cancel() {
 | 
						|
      this.running = false;
 | 
						|
      this.cancelled = true;
 | 
						|
      this.callback('cancelled');
 | 
						|
    },
 | 
						|
 | 
						|
    operatorListChanged: function InternalRenderTask_operatorListChanged() {
 | 
						|
      if (!this.graphicsReady) {
 | 
						|
        if (!this.graphicsReadyCallback) {
 | 
						|
          this.graphicsReadyCallback = this._continue.bind(this);
 | 
						|
        }
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      if (this.stepper) {
 | 
						|
        this.stepper.updateOperatorList(this.operatorList);
 | 
						|
      }
 | 
						|
 | 
						|
      if (this.running) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      this._continue();
 | 
						|
    },
 | 
						|
 | 
						|
    _continue: function InternalRenderTask__continue() {
 | 
						|
      this.running = true;
 | 
						|
      if (this.cancelled) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      if (this.params.continueCallback) {
 | 
						|
        this.params.continueCallback(this._next.bind(this));
 | 
						|
      } else {
 | 
						|
        this._next();
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    _next: function InternalRenderTask__next() {
 | 
						|
      if (this.cancelled) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList,
 | 
						|
                                        this.operatorListIdx,
 | 
						|
                                        this._continue.bind(this),
 | 
						|
                                        this.stepper);
 | 
						|
      if (this.operatorListIdx === this.operatorList.argsArray.length) {
 | 
						|
        this.running = false;
 | 
						|
        if (this.operatorList.lastChunk) {
 | 
						|
          this.gfx.endDrawing();
 | 
						|
          this.callback();
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
  };
 | 
						|
 | 
						|
  return InternalRenderTask;
 | 
						|
})();
 | 
						|
 | 
						|
 | 
						|
var Metadata = PDFJS.Metadata = (function MetadataClosure() {
 | 
						|
  function fixMetadata(meta) {
 | 
						|
    return meta.replace(/>\\376\\377([^<]+)/g, function(all, codes) {
 | 
						|
      var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g,
 | 
						|
                                function(code, d1, d2, d3) {
 | 
						|
        return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
 | 
						|
      });
 | 
						|
      var chars = '';
 | 
						|
      for (var i = 0; i < bytes.length; i += 2) {
 | 
						|
        var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
 | 
						|
        chars += code >= 32 && code < 127 && code != 60 && code != 62 &&
 | 
						|
          code != 38 && false ? String.fromCharCode(code) :
 | 
						|
          '&#x' + (0x10000 + code).toString(16).substring(1) + ';';
 | 
						|
      }
 | 
						|
      return '>' + chars;
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  function Metadata(meta) {
 | 
						|
    if (typeof meta === 'string') {
 | 
						|
      // Ghostscript produces invalid metadata
 | 
						|
      meta = fixMetadata(meta);
 | 
						|
 | 
						|
      var parser = new DOMParser();
 | 
						|
      meta = parser.parseFromString(meta, 'application/xml');
 | 
						|
    } else if (!(meta instanceof Document)) {
 | 
						|
      error('Metadata: Invalid metadata object');
 | 
						|
    }
 | 
						|
 | 
						|
    this.metaDocument = meta;
 | 
						|
    this.metadata = {};
 | 
						|
    this.parse();
 | 
						|
  }
 | 
						|
 | 
						|
  Metadata.prototype = {
 | 
						|
    parse: function Metadata_parse() {
 | 
						|
      var doc = this.metaDocument;
 | 
						|
      var rdf = doc.documentElement;
 | 
						|
 | 
						|
      if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in <xmpmeta>
 | 
						|
        rdf = rdf.firstChild;
 | 
						|
        while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf')
 | 
						|
          rdf = rdf.nextSibling;
 | 
						|
      }
 | 
						|
 | 
						|
      var nodeName = (rdf) ? rdf.nodeName.toLowerCase() : null;
 | 
						|
      if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes())
 | 
						|
        return;
 | 
						|
 | 
						|
      var children = rdf.childNodes, desc, entry, name, i, ii, length, iLength;
 | 
						|
 | 
						|
      for (i = 0, length = children.length; i < length; i++) {
 | 
						|
        desc = children[i];
 | 
						|
        if (desc.nodeName.toLowerCase() !== 'rdf:description')
 | 
						|
          continue;
 | 
						|
 | 
						|
        for (ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) {
 | 
						|
          if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text') {
 | 
						|
            entry = desc.childNodes[ii];
 | 
						|
            name = entry.nodeName.toLowerCase();
 | 
						|
            this.metadata[name] = entry.textContent.trim();
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    get: function Metadata_get(name) {
 | 
						|
      return this.metadata[name] || null;
 | 
						|
    },
 | 
						|
 | 
						|
    has: function Metadata_has(name) {
 | 
						|
      return typeof this.metadata[name] !== 'undefined';
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  return Metadata;
 | 
						|
})();
 | 
						|
 | 
						|
 | 
						|
// <canvas> contexts store most of the state we need natively.
 | 
						|
// However, PDF needs a bit more state, which we store here.
 | 
						|
 | 
						|
// Minimal font size that would be used during canvas fillText operations.
 | 
						|
var MIN_FONT_SIZE = 16;
 | 
						|
 | 
						|
var COMPILE_TYPE3_GLYPHS = true;
 | 
						|
 | 
						|
function createScratchCanvas(width, height) {
 | 
						|
  var canvas = document.createElement('canvas');
 | 
						|
  canvas.width = width;
 | 
						|
  canvas.height = height;
 | 
						|
  return canvas;
 | 
						|
}
 | 
						|
 | 
						|
function addContextCurrentTransform(ctx) {
 | 
						|
  // If the context doesn't expose a `mozCurrentTransform`, add a JS based on.
 | 
						|
  if (!ctx.mozCurrentTransform) {
 | 
						|
    // Store the original context
 | 
						|
    ctx._scaleX = ctx._scaleX || 1.0;
 | 
						|
    ctx._scaleY = ctx._scaleY || 1.0;
 | 
						|
    ctx._originalSave = ctx.save;
 | 
						|
    ctx._originalRestore = ctx.restore;
 | 
						|
    ctx._originalRotate = ctx.rotate;
 | 
						|
    ctx._originalScale = ctx.scale;
 | 
						|
    ctx._originalTranslate = ctx.translate;
 | 
						|
    ctx._originalTransform = ctx.transform;
 | 
						|
    ctx._originalSetTransform = ctx.setTransform;
 | 
						|
 | 
						|
    ctx._transformMatrix = [ctx._scaleX, 0, 0, ctx._scaleY, 0, 0];
 | 
						|
    ctx._transformStack = [];
 | 
						|
 | 
						|
    Object.defineProperty(ctx, 'mozCurrentTransform', {
 | 
						|
      get: function getCurrentTransform() {
 | 
						|
        return this._transformMatrix;
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    Object.defineProperty(ctx, 'mozCurrentTransformInverse', {
 | 
						|
      get: function getCurrentTransformInverse() {
 | 
						|
        // Calculation done using WolframAlpha:
 | 
						|
        // http://www.wolframalpha.com/input/?
 | 
						|
        //   i=Inverse+{{a%2C+c%2C+e}%2C+{b%2C+d%2C+f}%2C+{0%2C+0%2C+1}}
 | 
						|
 | 
						|
        var m = this._transformMatrix;
 | 
						|
        var a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5];
 | 
						|
 | 
						|
        var ad_bc = a * d - b * c;
 | 
						|
        var bc_ad = b * c - a * d;
 | 
						|
 | 
						|
        return [
 | 
						|
          d / ad_bc,
 | 
						|
          b / bc_ad,
 | 
						|
          c / bc_ad,
 | 
						|
          a / ad_bc,
 | 
						|
          (d * e - c * f) / bc_ad,
 | 
						|
          (b * e - a * f) / ad_bc
 | 
						|
        ];
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    ctx.save = function ctxSave() {
 | 
						|
      var old = this._transformMatrix;
 | 
						|
      this._transformStack.push(old);
 | 
						|
      this._transformMatrix = old.slice(0, 6);
 | 
						|
 | 
						|
      this._originalSave();
 | 
						|
    };
 | 
						|
 | 
						|
    ctx.restore = function ctxRestore() {
 | 
						|
      var prev = this._transformStack.pop();
 | 
						|
      if (prev) {
 | 
						|
        this._transformMatrix = prev;
 | 
						|
        this._originalRestore();
 | 
						|
      }
 | 
						|
    };
 | 
						|
 | 
						|
    ctx.translate = function ctxTranslate(x, y) {
 | 
						|
      var m = this._transformMatrix;
 | 
						|
      m[4] = m[0] * x + m[2] * y + m[4];
 | 
						|
      m[5] = m[1] * x + m[3] * y + m[5];
 | 
						|
 | 
						|
      this._originalTranslate(x, y);
 | 
						|
    };
 | 
						|
 | 
						|
    ctx.scale = function ctxScale(x, y) {
 | 
						|
      var m = this._transformMatrix;
 | 
						|
      m[0] = m[0] * x;
 | 
						|
      m[1] = m[1] * x;
 | 
						|
      m[2] = m[2] * y;
 | 
						|
      m[3] = m[3] * y;
 | 
						|
 | 
						|
      this._originalScale(x, y);
 | 
						|
    };
 | 
						|
 | 
						|
    ctx.transform = function ctxTransform(a, b, c, d, e, f) {
 | 
						|
      var m = this._transformMatrix;
 | 
						|
      this._transformMatrix = [
 | 
						|
        m[0] * a + m[2] * b,
 | 
						|
        m[1] * a + m[3] * b,
 | 
						|
        m[0] * c + m[2] * d,
 | 
						|
        m[1] * c + m[3] * d,
 | 
						|
        m[0] * e + m[2] * f + m[4],
 | 
						|
        m[1] * e + m[3] * f + m[5]
 | 
						|
      ];
 | 
						|
 | 
						|
      ctx._originalTransform(a, b, c, d, e, f);
 | 
						|
    };
 | 
						|
 | 
						|
    ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) {
 | 
						|
      this._transformMatrix = [a, b, c, d, e, f];
 | 
						|
 | 
						|
      ctx._originalSetTransform(a, b, c, d, e, f);
 | 
						|
    };
 | 
						|
 | 
						|
    ctx.rotate = function ctxRotate(angle) {
 | 
						|
      var cosValue = Math.cos(angle);
 | 
						|
      var sinValue = Math.sin(angle);
 | 
						|
 | 
						|
      var m = this._transformMatrix;
 | 
						|
      this._transformMatrix = [
 | 
						|
        m[0] * cosValue + m[2] * sinValue,
 | 
						|
        m[1] * cosValue + m[3] * sinValue,
 | 
						|
        m[0] * (-sinValue) + m[2] * cosValue,
 | 
						|
        m[1] * (-sinValue) + m[3] * cosValue,
 | 
						|
        m[4],
 | 
						|
        m[5]
 | 
						|
      ];
 | 
						|
 | 
						|
      this._originalRotate(angle);
 | 
						|
    };
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
var CachedCanvases = (function CachedCanvasesClosure() {
 | 
						|
  var cache = {};
 | 
						|
  return {
 | 
						|
    getCanvas: function CachedCanvases_getCanvas(id, width, height,
 | 
						|
                                                 trackTransform) {
 | 
						|
      var canvasEntry;
 | 
						|
      if (id in cache) {
 | 
						|
        canvasEntry = cache[id];
 | 
						|
        canvasEntry.canvas.width = width;
 | 
						|
        canvasEntry.canvas.height = height;
 | 
						|
        // reset canvas transform for emulated mozCurrentTransform, if needed
 | 
						|
        canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0);
 | 
						|
      } else {
 | 
						|
        var canvas = createScratchCanvas(width, height);
 | 
						|
        var ctx = canvas.getContext('2d');
 | 
						|
        if (trackTransform) {
 | 
						|
          addContextCurrentTransform(ctx);
 | 
						|
        }
 | 
						|
        cache[id] = canvasEntry = {canvas: canvas, context: ctx};
 | 
						|
      }
 | 
						|
      return canvasEntry;
 | 
						|
    },
 | 
						|
    clear: function () {
 | 
						|
      cache = {};
 | 
						|
    }
 | 
						|
  };
 | 
						|
})();
 | 
						|
 | 
						|
function compileType3Glyph(imgData) {
 | 
						|
  var POINT_TO_PROCESS_LIMIT = 1000;
 | 
						|
 | 
						|
  var width = imgData.width, height = imgData.height;
 | 
						|
  var i, j, j0, width1 = width + 1;
 | 
						|
  var points = new Uint8Array(width1 * (height + 1));
 | 
						|
  var POINT_TYPES =
 | 
						|
      new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]);
 | 
						|
  // finding iteresting points: every point is located between mask pixels,
 | 
						|
  // so there will be points of the (width + 1)x(height + 1) grid. Every point
 | 
						|
  // will have flags assigned based on neighboring mask pixels:
 | 
						|
  //   4 | 8
 | 
						|
  //   --P--
 | 
						|
  //   2 | 1
 | 
						|
  // We are interested only in points with the flags:
 | 
						|
  //   - outside corners: 1, 2, 4, 8;
 | 
						|
  //   - inside corners: 7, 11, 13, 14;
 | 
						|
  //   - and, intersections: 5, 10.
 | 
						|
  var pos = 3, data = imgData.data, lineSize = width * 4, count = 0;
 | 
						|
  if (data[3] !== 0) {
 | 
						|
    points[0] = 1;
 | 
						|
    ++count;
 | 
						|
  }
 | 
						|
  for (j = 1; j < width; j++) {
 | 
						|
    if (data[pos] !== data[pos + 4]) {
 | 
						|
      points[j] = data[pos] ? 2 : 1;
 | 
						|
      ++count;
 | 
						|
    }
 | 
						|
    pos += 4;
 | 
						|
  }
 | 
						|
  if (data[pos] !== 0) {
 | 
						|
    points[j] = 2;
 | 
						|
    ++count;
 | 
						|
  }
 | 
						|
  pos += 4;
 | 
						|
  for (i = 1; i < height; i++) {
 | 
						|
    j0 = i * width1;
 | 
						|
    if (data[pos - lineSize] !== data[pos]) {
 | 
						|
      points[j0] = data[pos] ? 1 : 8;
 | 
						|
      ++count;
 | 
						|
    }
 | 
						|
    // 'sum' is the position of the current pixel configuration in the 'TYPES'
 | 
						|
    // array (in order 8-1-2-4, so we can use '>>2' to shift the column).
 | 
						|
    var sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0);
 | 
						|
    for (j = 1; j < width; j++) {
 | 
						|
      sum = (sum >> 2) + (data[pos + 4] ? 4 : 0) +
 | 
						|
            (data[pos - lineSize + 4] ? 8 : 0);
 | 
						|
      if (POINT_TYPES[sum]) {
 | 
						|
        points[j0 + j] = POINT_TYPES[sum];
 | 
						|
        ++count;
 | 
						|
      }
 | 
						|
      pos += 4;
 | 
						|
    }
 | 
						|
    if (data[pos - lineSize] !== data[pos]) {
 | 
						|
      points[j0 + j] = data[pos] ? 2 : 4;
 | 
						|
      ++count;
 | 
						|
    }
 | 
						|
    pos += 4;
 | 
						|
 | 
						|
    if (count > POINT_TO_PROCESS_LIMIT) {
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  pos -= lineSize;
 | 
						|
  j0 = i * width1;
 | 
						|
  if (data[pos] !== 0) {
 | 
						|
    points[j0] = 8;
 | 
						|
    ++count;
 | 
						|
  }
 | 
						|
  for (j = 1; j < width; j++) {
 | 
						|
    if (data[pos] !== data[pos + 4]) {
 | 
						|
      points[j0 + j] = data[pos] ? 4 : 8;
 | 
						|
      ++count;
 | 
						|
    }
 | 
						|
    pos += 4;
 | 
						|
  }
 | 
						|
  if (data[pos] !== 0) {
 | 
						|
    points[j0 + j] = 4;
 | 
						|
    ++count;
 | 
						|
  }
 | 
						|
  if (count > POINT_TO_PROCESS_LIMIT) {
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
 | 
						|
  // building outlines
 | 
						|
  var steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]);
 | 
						|
  var outlines = [];
 | 
						|
  for (i = 0; count && i <= height; i++) {
 | 
						|
    var p = i * width1;
 | 
						|
    var end = p + width;
 | 
						|
    while (p < end && !points[p]) {
 | 
						|
      p++;
 | 
						|
    }
 | 
						|
    if (p === end) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    var coords = [p % width1, i];
 | 
						|
 | 
						|
    var type = points[p], p0 = p, pp;
 | 
						|
    do {
 | 
						|
      var step = steps[type];
 | 
						|
      do { p += step; } while (!points[p]);
 | 
						|
 | 
						|
      pp = points[p];
 | 
						|
      if (pp !== 5 && pp !== 10) {
 | 
						|
        // set new direction
 | 
						|
        type = pp;
 | 
						|
        // delete mark
 | 
						|
        points[p] = 0;
 | 
						|
      } else { // type is 5 or 10, ie, a crossing
 | 
						|
        // set new direction
 | 
						|
        type = pp & ((0x33 * type) >> 4);
 | 
						|
        // set new type for "future hit"
 | 
						|
        points[p] &= (type >> 2 | type << 2);
 | 
						|
      }
 | 
						|
 | 
						|
      coords.push(p % width1);
 | 
						|
      coords.push((p / width1) | 0);
 | 
						|
      --count;
 | 
						|
    } while (p0 !== p);
 | 
						|
    outlines.push(coords);
 | 
						|
    --i;
 | 
						|
  }
 | 
						|
 | 
						|
  var drawOutline = function(c) {
 | 
						|
    c.save();
 | 
						|
    // the path shall be painted in [0..1]x[0..1] space
 | 
						|
    c.scale(1 / width, -1 / height);
 | 
						|
    c.translate(0, -height);
 | 
						|
    c.beginPath();
 | 
						|
    for (var i = 0, ii = outlines.length; i < ii; i++) {
 | 
						|
      var o = outlines[i];
 | 
						|
      c.moveTo(o[0], o[1]);
 | 
						|
      for (var j = 2, jj = o.length; j < jj; j += 2) {
 | 
						|
        c.lineTo(o[j], o[j+1]);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    c.fill();
 | 
						|
    c.beginPath();
 | 
						|
    c.restore();
 | 
						|
  };
 | 
						|
 | 
						|
  return drawOutline;
 | 
						|
}
 | 
						|
 | 
						|
var CanvasExtraState = (function CanvasExtraStateClosure() {
 | 
						|
  function CanvasExtraState(old) {
 | 
						|
    // Are soft masks and alpha values shapes or opacities?
 | 
						|
    this.alphaIsShape = false;
 | 
						|
    this.fontSize = 0;
 | 
						|
    this.fontSizeScale = 1;
 | 
						|
    this.textMatrix = IDENTITY_MATRIX;
 | 
						|
    this.fontMatrix = FONT_IDENTITY_MATRIX;
 | 
						|
    this.leading = 0;
 | 
						|
    // Current point (in user coordinates)
 | 
						|
    this.x = 0;
 | 
						|
    this.y = 0;
 | 
						|
    // Start of text line (in text coordinates)
 | 
						|
    this.lineX = 0;
 | 
						|
    this.lineY = 0;
 | 
						|
    // Character and word spacing
 | 
						|
    this.charSpacing = 0;
 | 
						|
    this.wordSpacing = 0;
 | 
						|
    this.textHScale = 1;
 | 
						|
    this.textRenderingMode = TextRenderingMode.FILL;
 | 
						|
    this.textRise = 0;
 | 
						|
    // Color spaces
 | 
						|
    this.fillColorSpace = ColorSpace.singletons.gray;
 | 
						|
    this.fillColorSpaceObj = null;
 | 
						|
    this.strokeColorSpace = ColorSpace.singletons.gray;
 | 
						|
    this.strokeColorSpaceObj = null;
 | 
						|
    this.fillColorObj = null;
 | 
						|
    this.strokeColorObj = null;
 | 
						|
    // Default fore and background colors
 | 
						|
    this.fillColor = '#000000';
 | 
						|
    this.strokeColor = '#000000';
 | 
						|
    // Note: fill alpha applies to all non-stroking operations
 | 
						|
    this.fillAlpha = 1;
 | 
						|
    this.strokeAlpha = 1;
 | 
						|
    this.lineWidth = 1;
 | 
						|
    this.paintFormXObjectDepth = 0;
 | 
						|
 | 
						|
    this.old = old;
 | 
						|
  }
 | 
						|
 | 
						|
  CanvasExtraState.prototype = {
 | 
						|
    clone: function CanvasExtraState_clone() {
 | 
						|
      return Object.create(this);
 | 
						|
    },
 | 
						|
    setCurrentPoint: function CanvasExtraState_setCurrentPoint(x, y) {
 | 
						|
      this.x = x;
 | 
						|
      this.y = y;
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return CanvasExtraState;
 | 
						|
})();
 | 
						|
 | 
						|
var CanvasGraphics = (function CanvasGraphicsClosure() {
 | 
						|
  // Defines the time the executeOperatorList is going to be executing
 | 
						|
  // before it stops and shedules a continue of execution.
 | 
						|
  var EXECUTION_TIME = 15;
 | 
						|
 | 
						|
  function CanvasGraphics(canvasCtx, commonObjs, objs, textLayer, imageLayer) {
 | 
						|
    this.ctx = canvasCtx;
 | 
						|
    this.current = new CanvasExtraState();
 | 
						|
    this.stateStack = [];
 | 
						|
    this.pendingClip = null;
 | 
						|
    this.pendingEOFill = false;
 | 
						|
    this.res = null;
 | 
						|
    this.xobjs = null;
 | 
						|
    this.commonObjs = commonObjs;
 | 
						|
    this.objs = objs;
 | 
						|
    this.textLayer = textLayer;
 | 
						|
    this.imageLayer = imageLayer;
 | 
						|
    this.groupStack = [];
 | 
						|
    this.processingType3 = null;
 | 
						|
    // Patterns are painted relative to the initial page/form transform, see pdf
 | 
						|
    // spec 8.7.2 NOTE 1.
 | 
						|
    this.baseTransform = null;
 | 
						|
    this.baseTransformStack = [];
 | 
						|
    this.groupLevel = 0;
 | 
						|
    if (canvasCtx) {
 | 
						|
      addContextCurrentTransform(canvasCtx);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  function putBinaryImageData(ctx, imgData) {
 | 
						|
    if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) {
 | 
						|
      ctx.putImageData(imgData, 0, 0);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    var tmpImgData = ctx.createImageData(imgData.width, imgData.height);
 | 
						|
 | 
						|
    var data = imgData.data;
 | 
						|
    var tmpImgDataPixels = tmpImgData.data;
 | 
						|
    if ('set' in tmpImgDataPixels)
 | 
						|
      tmpImgDataPixels.set(data);
 | 
						|
    else {
 | 
						|
      // Copy over the imageData pixel by pixel.
 | 
						|
      for (var i = 0, ii = tmpImgDataPixels.length; i < ii; i++)
 | 
						|
        tmpImgDataPixels[i] = data[i];
 | 
						|
    }
 | 
						|
 | 
						|
    ctx.putImageData(tmpImgData, 0, 0);
 | 
						|
  }
 | 
						|
 | 
						|
  function copyCtxState(sourceCtx, destCtx) {
 | 
						|
    var properties = ['strokeStyle', 'fillStyle', 'fillRule', 'globalAlpha',
 | 
						|
                      'lineWidth', 'lineCap', 'lineJoin', 'miterLimit',
 | 
						|
                      'globalCompositeOperation', 'font'];
 | 
						|
    for (var i = 0, ii = properties.length; i < ii; i++) {
 | 
						|
      var property = properties[i];
 | 
						|
      if (property in sourceCtx) {
 | 
						|
        destCtx[property] = sourceCtx[property];
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if ('setLineDash' in sourceCtx) {
 | 
						|
      destCtx.setLineDash(sourceCtx.getLineDash());
 | 
						|
      destCtx.lineDashOffset =  sourceCtx.lineDashOffset;
 | 
						|
    } else if ('mozDash' in sourceCtx) {
 | 
						|
      destCtx.mozDash = sourceCtx.mozDash;
 | 
						|
      destCtx.mozDashOffset = sourceCtx.mozDashOffset;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  var LINE_CAP_STYLES = ['butt', 'round', 'square'];
 | 
						|
  var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
 | 
						|
  var NORMAL_CLIP = {};
 | 
						|
  var EO_CLIP = {};
 | 
						|
 | 
						|
  CanvasGraphics.prototype = {
 | 
						|
 | 
						|
    beginDrawing: function CanvasGraphics_beginDrawing(viewport, transparency) {
 | 
						|
      // For pdfs that use blend modes we have to clear the canvas else certain
 | 
						|
      // blend modes can look wrong since we'd be blending with a white
 | 
						|
      // backdrop. The problem with a transparent backdrop though is we then
 | 
						|
      // don't get sub pixel anti aliasing on text, so we fill with white if
 | 
						|
      // we can.
 | 
						|
      var width = this.ctx.canvas.width;
 | 
						|
      var height = this.ctx.canvas.height;
 | 
						|
      if (transparency) {
 | 
						|
        this.ctx.clearRect(0, 0, width, height);
 | 
						|
      } else {
 | 
						|
        this.ctx.mozOpaque = true;
 | 
						|
        this.ctx.save();
 | 
						|
        this.ctx.fillStyle = 'rgb(255, 255, 255)';
 | 
						|
        this.ctx.fillRect(0, 0, width, height);
 | 
						|
        this.ctx.restore();
 | 
						|
      }
 | 
						|
 | 
						|
      var transform = viewport.transform;
 | 
						|
      this.baseTransform = transform.slice();
 | 
						|
      this.ctx.save();
 | 
						|
      this.ctx.transform.apply(this.ctx, transform);
 | 
						|
 | 
						|
      if (this.textLayer) {
 | 
						|
        this.textLayer.beginLayout();
 | 
						|
      }
 | 
						|
      if (this.imageLayer) {
 | 
						|
        this.imageLayer.beginLayout();
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    executeOperatorList: function CanvasGraphics_executeOperatorList(
 | 
						|
                                    operatorList,
 | 
						|
                                    executionStartIdx, continueCallback,
 | 
						|
                                    stepper) {
 | 
						|
      var argsArray = operatorList.argsArray;
 | 
						|
      var fnArray = operatorList.fnArray;
 | 
						|
      var i = executionStartIdx || 0;
 | 
						|
      var argsArrayLen = argsArray.length;
 | 
						|
 | 
						|
      // Sometimes the OperatorList to execute is empty.
 | 
						|
      if (argsArrayLen == i) {
 | 
						|
        return i;
 | 
						|
      }
 | 
						|
 | 
						|
      var executionEndIdx;
 | 
						|
      var endTime = Date.now() + EXECUTION_TIME;
 | 
						|
 | 
						|
      var commonObjs = this.commonObjs;
 | 
						|
      var objs = this.objs;
 | 
						|
      var fnId;
 | 
						|
 | 
						|
      while (true) {
 | 
						|
        if (stepper && i === stepper.nextBreakPoint) {
 | 
						|
          stepper.breakIt(i, continueCallback);
 | 
						|
          return i;
 | 
						|
        }
 | 
						|
 | 
						|
        fnId = fnArray[i];
 | 
						|
 | 
						|
        if (fnId !== OPS.dependency) {
 | 
						|
          this[fnId].apply(this, argsArray[i]);
 | 
						|
        } else {
 | 
						|
          var deps = argsArray[i];
 | 
						|
          for (var n = 0, nn = deps.length; n < nn; n++) {
 | 
						|
            var depObjId = deps[n];
 | 
						|
            var common = depObjId.substring(0, 2) == 'g_';
 | 
						|
 | 
						|
            // If the promise isn't resolved yet, add the continueCallback
 | 
						|
            // to the promise and bail out.
 | 
						|
            if (!common && !objs.isResolved(depObjId)) {
 | 
						|
              objs.get(depObjId, continueCallback);
 | 
						|
              return i;
 | 
						|
            }
 | 
						|
            if (common && !commonObjs.isResolved(depObjId)) {
 | 
						|
              commonObjs.get(depObjId, continueCallback);
 | 
						|
              return i;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        i++;
 | 
						|
 | 
						|
        // If the entire operatorList was executed, stop as were done.
 | 
						|
        if (i == argsArrayLen) {
 | 
						|
          return i;
 | 
						|
        }
 | 
						|
 | 
						|
        // If the execution took longer then a certain amount of time, schedule
 | 
						|
        // to continue exeution after a short delay.
 | 
						|
        // However, this is only possible if a 'continueCallback' is passed in.
 | 
						|
        if (continueCallback && Date.now() > endTime) {
 | 
						|
          setTimeout(continueCallback, 0);
 | 
						|
          return i;
 | 
						|
        }
 | 
						|
 | 
						|
        // If the operatorList isn't executed completely yet OR the execution
 | 
						|
        // time was short enough, do another execution round.
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    endDrawing: function CanvasGraphics_endDrawing() {
 | 
						|
      this.ctx.restore();
 | 
						|
      CachedCanvases.clear();
 | 
						|
 | 
						|
      if (this.textLayer) {
 | 
						|
        this.textLayer.endLayout();
 | 
						|
      }
 | 
						|
      if (this.imageLayer) {
 | 
						|
        this.imageLayer.endLayout();
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    // Graphics state
 | 
						|
    setLineWidth: function CanvasGraphics_setLineWidth(width) {
 | 
						|
      this.current.lineWidth = width;
 | 
						|
      this.ctx.lineWidth = width;
 | 
						|
    },
 | 
						|
    setLineCap: function CanvasGraphics_setLineCap(style) {
 | 
						|
      this.ctx.lineCap = LINE_CAP_STYLES[style];
 | 
						|
    },
 | 
						|
    setLineJoin: function CanvasGraphics_setLineJoin(style) {
 | 
						|
      this.ctx.lineJoin = LINE_JOIN_STYLES[style];
 | 
						|
    },
 | 
						|
    setMiterLimit: function CanvasGraphics_setMiterLimit(limit) {
 | 
						|
      this.ctx.miterLimit = limit;
 | 
						|
    },
 | 
						|
    setDash: function CanvasGraphics_setDash(dashArray, dashPhase) {
 | 
						|
      var ctx = this.ctx;
 | 
						|
      if ('setLineDash' in ctx) {
 | 
						|
        ctx.setLineDash(dashArray);
 | 
						|
        ctx.lineDashOffset = dashPhase;
 | 
						|
      } else {
 | 
						|
        ctx.mozDash = dashArray;
 | 
						|
        ctx.mozDashOffset = dashPhase;
 | 
						|
      }
 | 
						|
    },
 | 
						|
    setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) {
 | 
						|
      // Maybe if we one day fully support color spaces this will be important
 | 
						|
      // for now we can ignore.
 | 
						|
      // TODO set rendering intent?
 | 
						|
    },
 | 
						|
    setFlatness: function CanvasGraphics_setFlatness(flatness) {
 | 
						|
      // There's no way to control this with canvas, but we can safely ignore.
 | 
						|
      // TODO set flatness?
 | 
						|
    },
 | 
						|
    setGState: function CanvasGraphics_setGState(states) {
 | 
						|
      for (var i = 0, ii = states.length; i < ii; i++) {
 | 
						|
        var state = states[i];
 | 
						|
        var key = state[0];
 | 
						|
        var value = state[1];
 | 
						|
 | 
						|
        switch (key) {
 | 
						|
          case 'LW':
 | 
						|
            this.setLineWidth(value);
 | 
						|
            break;
 | 
						|
          case 'LC':
 | 
						|
            this.setLineCap(value);
 | 
						|
            break;
 | 
						|
          case 'LJ':
 | 
						|
            this.setLineJoin(value);
 | 
						|
            break;
 | 
						|
          case 'ML':
 | 
						|
            this.setMiterLimit(value);
 | 
						|
            break;
 | 
						|
          case 'D':
 | 
						|
            this.setDash(value[0], value[1]);
 | 
						|
            break;
 | 
						|
          case 'RI':
 | 
						|
            this.setRenderingIntent(value);
 | 
						|
            break;
 | 
						|
          case 'FL':
 | 
						|
            this.setFlatness(value);
 | 
						|
            break;
 | 
						|
          case 'Font':
 | 
						|
            this.setFont(value[0], value[1]);
 | 
						|
            break;
 | 
						|
          case 'CA':
 | 
						|
            this.current.strokeAlpha = state[1];
 | 
						|
            break;
 | 
						|
          case 'ca':
 | 
						|
            this.current.fillAlpha = state[1];
 | 
						|
            this.ctx.globalAlpha = state[1];
 | 
						|
            break;
 | 
						|
          case 'BM':
 | 
						|
            if (value && value.name && (value.name !== 'Normal')) {
 | 
						|
              var mode = value.name.replace(/([A-Z])/g,
 | 
						|
                function(c) {
 | 
						|
                  return '-' + c.toLowerCase();
 | 
						|
                }
 | 
						|
              ).substring(1);
 | 
						|
              this.ctx.globalCompositeOperation = mode;
 | 
						|
              if (this.ctx.globalCompositeOperation !== mode) {
 | 
						|
                warn('globalCompositeOperation "' + mode +
 | 
						|
                     '" is not supported');
 | 
						|
              }
 | 
						|
            } else {
 | 
						|
              this.ctx.globalCompositeOperation = 'source-over';
 | 
						|
            }
 | 
						|
            break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    },
 | 
						|
    save: function CanvasGraphics_save() {
 | 
						|
      this.ctx.save();
 | 
						|
      var old = this.current;
 | 
						|
      this.stateStack.push(old);
 | 
						|
      this.current = old.clone();
 | 
						|
    },
 | 
						|
    restore: function CanvasGraphics_restore() {
 | 
						|
      var prev = this.stateStack.pop();
 | 
						|
      if (prev) {
 | 
						|
        this.current = prev;
 | 
						|
        this.ctx.restore();
 | 
						|
      }
 | 
						|
    },
 | 
						|
    transform: function CanvasGraphics_transform(a, b, c, d, e, f) {
 | 
						|
      this.ctx.transform(a, b, c, d, e, f);
 | 
						|
    },
 | 
						|
 | 
						|
    // Path
 | 
						|
    moveTo: function CanvasGraphics_moveTo(x, y) {
 | 
						|
      this.ctx.moveTo(x, y);
 | 
						|
      this.current.setCurrentPoint(x, y);
 | 
						|
    },
 | 
						|
    lineTo: function CanvasGraphics_lineTo(x, y) {
 | 
						|
      this.ctx.lineTo(x, y);
 | 
						|
      this.current.setCurrentPoint(x, y);
 | 
						|
    },
 | 
						|
    curveTo: function CanvasGraphics_curveTo(x1, y1, x2, y2, x3, y3) {
 | 
						|
      this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
 | 
						|
      this.current.setCurrentPoint(x3, y3);
 | 
						|
    },
 | 
						|
    curveTo2: function CanvasGraphics_curveTo2(x2, y2, x3, y3) {
 | 
						|
      var current = this.current;
 | 
						|
      this.ctx.bezierCurveTo(current.x, current.y, x2, y2, x3, y3);
 | 
						|
      current.setCurrentPoint(x3, y3);
 | 
						|
    },
 | 
						|
    curveTo3: function CanvasGraphics_curveTo3(x1, y1, x3, y3) {
 | 
						|
      this.curveTo(x1, y1, x3, y3, x3, y3);
 | 
						|
      this.current.setCurrentPoint(x3, y3);
 | 
						|
    },
 | 
						|
    closePath: function CanvasGraphics_closePath() {
 | 
						|
      this.ctx.closePath();
 | 
						|
    },
 | 
						|
    rectangle: function CanvasGraphics_rectangle(x, y, width, height) {
 | 
						|
      this.ctx.rect(x, y, width, height);
 | 
						|
    },
 | 
						|
    stroke: function CanvasGraphics_stroke(consumePath) {
 | 
						|
      consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
 | 
						|
      var ctx = this.ctx;
 | 
						|
      var strokeColor = this.current.strokeColor;
 | 
						|
      if (this.current.lineWidth === 0)
 | 
						|
        ctx.lineWidth = this.getSinglePixelWidth();
 | 
						|
      // For stroke we want to temporarily change the global alpha to the
 | 
						|
      // stroking alpha.
 | 
						|
      ctx.globalAlpha = this.current.strokeAlpha;
 | 
						|
      if (strokeColor && strokeColor.hasOwnProperty('type') &&
 | 
						|
          strokeColor.type === 'Pattern') {
 | 
						|
        // for patterns, we transform to pattern space, calculate
 | 
						|
        // the pattern, call stroke, and restore to user space
 | 
						|
        ctx.save();
 | 
						|
        ctx.strokeStyle = strokeColor.getPattern(ctx, this);
 | 
						|
        ctx.stroke();
 | 
						|
        ctx.restore();
 | 
						|
      } else {
 | 
						|
        ctx.stroke();
 | 
						|
      }
 | 
						|
      if (consumePath)
 | 
						|
        this.consumePath();
 | 
						|
      // Restore the global alpha to the fill alpha
 | 
						|
      ctx.globalAlpha = this.current.fillAlpha;
 | 
						|
    },
 | 
						|
    closeStroke: function CanvasGraphics_closeStroke() {
 | 
						|
      this.closePath();
 | 
						|
      this.stroke();
 | 
						|
    },
 | 
						|
    fill: function CanvasGraphics_fill(consumePath) {
 | 
						|
      consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
 | 
						|
      var ctx = this.ctx;
 | 
						|
      var fillColor = this.current.fillColor;
 | 
						|
      var needRestore = false;
 | 
						|
 | 
						|
      if (fillColor && fillColor.hasOwnProperty('type') &&
 | 
						|
          fillColor.type === 'Pattern') {
 | 
						|
        ctx.save();
 | 
						|
        ctx.fillStyle = fillColor.getPattern(ctx, this);
 | 
						|
        needRestore = true;
 | 
						|
      }
 | 
						|
 | 
						|
      if (this.pendingEOFill) {
 | 
						|
        if ('mozFillRule' in this.ctx) {
 | 
						|
          this.ctx.mozFillRule = 'evenodd';
 | 
						|
          this.ctx.fill();
 | 
						|
          this.ctx.mozFillRule = 'nonzero';
 | 
						|
        } else {
 | 
						|
          try {
 | 
						|
            this.ctx.fill('evenodd');
 | 
						|
          } catch (ex) {
 | 
						|
            // shouldn't really happen, but browsers might think differently
 | 
						|
            this.ctx.fill();
 | 
						|
          }
 | 
						|
        }
 | 
						|
        this.pendingEOFill = false;
 | 
						|
      } else {
 | 
						|
        this.ctx.fill();
 | 
						|
      }
 | 
						|
 | 
						|
      if (needRestore) {
 | 
						|
        ctx.restore();
 | 
						|
      }
 | 
						|
      if (consumePath) {
 | 
						|
        this.consumePath();
 | 
						|
      }
 | 
						|
    },
 | 
						|
    eoFill: function CanvasGraphics_eoFill() {
 | 
						|
      this.pendingEOFill = true;
 | 
						|
      this.fill();
 | 
						|
    },
 | 
						|
    fillStroke: function CanvasGraphics_fillStroke() {
 | 
						|
      this.fill(false);
 | 
						|
      this.stroke(false);
 | 
						|
 | 
						|
      this.consumePath();
 | 
						|
    },
 | 
						|
    eoFillStroke: function CanvasGraphics_eoFillStroke() {
 | 
						|
      this.pendingEOFill = true;
 | 
						|
      this.fillStroke();
 | 
						|
    },
 | 
						|
    closeFillStroke: function CanvasGraphics_closeFillStroke() {
 | 
						|
      this.closePath();
 | 
						|
      this.fillStroke();
 | 
						|
    },
 | 
						|
    closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() {
 | 
						|
      this.pendingEOFill = true;
 | 
						|
      this.closePath();
 | 
						|
      this.fillStroke();
 | 
						|
    },
 | 
						|
    endPath: function CanvasGraphics_endPath() {
 | 
						|
      this.consumePath();
 | 
						|
    },
 | 
						|
 | 
						|
    // Clipping
 | 
						|
    clip: function CanvasGraphics_clip() {
 | 
						|
      this.pendingClip = NORMAL_CLIP;
 | 
						|
    },
 | 
						|
    eoClip: function CanvasGraphics_eoClip() {
 | 
						|
      this.pendingClip = EO_CLIP;
 | 
						|
    },
 | 
						|
 | 
						|
    // Text
 | 
						|
    beginText: function CanvasGraphics_beginText() {
 | 
						|
      this.current.textMatrix = IDENTITY_MATRIX;
 | 
						|
      this.current.x = this.current.lineX = 0;
 | 
						|
      this.current.y = this.current.lineY = 0;
 | 
						|
    },
 | 
						|
    endText: function CanvasGraphics_endText() {
 | 
						|
      if (!('pendingTextPaths' in this)) {
 | 
						|
        this.ctx.beginPath();
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      var paths = this.pendingTextPaths;
 | 
						|
      var ctx = this.ctx;
 | 
						|
 | 
						|
      ctx.save();
 | 
						|
      ctx.beginPath();
 | 
						|
      for (var i = 0; i < paths.length; i++) {
 | 
						|
        var path = paths[i];
 | 
						|
        ctx.setTransform.apply(ctx, path.transform);
 | 
						|
        ctx.translate(path.x, path.y);
 | 
						|
        path.addToPath(ctx, path.fontSize);
 | 
						|
      }
 | 
						|
      ctx.restore();
 | 
						|
      ctx.clip();
 | 
						|
      ctx.beginPath();
 | 
						|
      delete this.pendingTextPaths;
 | 
						|
    },
 | 
						|
    setCharSpacing: function CanvasGraphics_setCharSpacing(spacing) {
 | 
						|
      this.current.charSpacing = spacing;
 | 
						|
    },
 | 
						|
    setWordSpacing: function CanvasGraphics_setWordSpacing(spacing) {
 | 
						|
      this.current.wordSpacing = spacing;
 | 
						|
    },
 | 
						|
    setHScale: function CanvasGraphics_setHScale(scale) {
 | 
						|
      this.current.textHScale = scale / 100;
 | 
						|
    },
 | 
						|
    setLeading: function CanvasGraphics_setLeading(leading) {
 | 
						|
      this.current.leading = -leading;
 | 
						|
    },
 | 
						|
    setFont: function CanvasGraphics_setFont(fontRefName, size) {
 | 
						|
      var fontObj = this.commonObjs.get(fontRefName);
 | 
						|
      var current = this.current;
 | 
						|
 | 
						|
      if (!fontObj)
 | 
						|
        error('Can\'t find font for ' + fontRefName);
 | 
						|
 | 
						|
      current.fontMatrix = fontObj.fontMatrix ? fontObj.fontMatrix :
 | 
						|
                                                FONT_IDENTITY_MATRIX;
 | 
						|
 | 
						|
      // A valid matrix needs all main diagonal elements to be non-zero
 | 
						|
      // This also ensures we bypass FF bugzilla bug #719844.
 | 
						|
      if (current.fontMatrix[0] === 0 ||
 | 
						|
          current.fontMatrix[3] === 0) {
 | 
						|
        warn('Invalid font matrix for font ' + fontRefName);
 | 
						|
      }
 | 
						|
 | 
						|
      // The spec for Tf (setFont) says that 'size' specifies the font 'scale',
 | 
						|
      // and in some docs this can be negative (inverted x-y axes).
 | 
						|
      if (size < 0) {
 | 
						|
        size = -size;
 | 
						|
        current.fontDirection = -1;
 | 
						|
      } else {
 | 
						|
        current.fontDirection = 1;
 | 
						|
      }
 | 
						|
 | 
						|
      this.current.font = fontObj;
 | 
						|
      this.current.fontSize = size;
 | 
						|
 | 
						|
      if (fontObj.coded)
 | 
						|
        return; // we don't need ctx.font for Type3 fonts
 | 
						|
 | 
						|
      var name = fontObj.loadedName || 'sans-serif';
 | 
						|
      var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') :
 | 
						|
                                 (fontObj.bold ? 'bold' : 'normal');
 | 
						|
 | 
						|
      var italic = fontObj.italic ? 'italic' : 'normal';
 | 
						|
      var typeface = '"' + name + '", ' + fontObj.fallbackName;
 | 
						|
 | 
						|
      // Some font backends cannot handle fonts below certain size.
 | 
						|
      // Keeping the font at minimal size and using the fontSizeScale to change
 | 
						|
      // the current transformation matrix before the fillText/strokeText.
 | 
						|
      // See https://bugzilla.mozilla.org/show_bug.cgi?id=726227
 | 
						|
      var browserFontSize = size >= MIN_FONT_SIZE ? size : MIN_FONT_SIZE;
 | 
						|
      this.current.fontSizeScale = browserFontSize != MIN_FONT_SIZE ? 1.0 :
 | 
						|
                                   size / MIN_FONT_SIZE;
 | 
						|
 | 
						|
      var rule = italic + ' ' + bold + ' ' + browserFontSize + 'px ' + typeface;
 | 
						|
      this.ctx.font = rule;
 | 
						|
    },
 | 
						|
    setTextRenderingMode: function CanvasGraphics_setTextRenderingMode(mode) {
 | 
						|
      this.current.textRenderingMode = mode;
 | 
						|
    },
 | 
						|
    setTextRise: function CanvasGraphics_setTextRise(rise) {
 | 
						|
      this.current.textRise = rise;
 | 
						|
    },
 | 
						|
    moveText: function CanvasGraphics_moveText(x, y) {
 | 
						|
      this.current.x = this.current.lineX += x;
 | 
						|
      this.current.y = this.current.lineY += y;
 | 
						|
    },
 | 
						|
    setLeadingMoveText: function CanvasGraphics_setLeadingMoveText(x, y) {
 | 
						|
      this.setLeading(-y);
 | 
						|
      this.moveText(x, y);
 | 
						|
    },
 | 
						|
    setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) {
 | 
						|
      this.current.textMatrix = [a, b, c, d, e, f];
 | 
						|
 | 
						|
      this.current.x = this.current.lineX = 0;
 | 
						|
      this.current.y = this.current.lineY = 0;
 | 
						|
    },
 | 
						|
    nextLine: function CanvasGraphics_nextLine() {
 | 
						|
      this.moveText(0, this.current.leading);
 | 
						|
    },
 | 
						|
    applyTextTransforms: function CanvasGraphics_applyTextTransforms() {
 | 
						|
      var ctx = this.ctx;
 | 
						|
      var current = this.current;
 | 
						|
      ctx.transform.apply(ctx, current.textMatrix);
 | 
						|
      ctx.translate(current.x, current.y + current.textRise);
 | 
						|
      if (current.fontDirection > 0) {
 | 
						|
        ctx.scale(current.textHScale, -1);
 | 
						|
      } else {
 | 
						|
        ctx.scale(-current.textHScale, 1);
 | 
						|
      }
 | 
						|
    },
 | 
						|
    createTextGeometry: function CanvasGraphics_createTextGeometry() {
 | 
						|
      var geometry = {};
 | 
						|
      var ctx = this.ctx;
 | 
						|
      var font = this.current.font;
 | 
						|
      var ctxMatrix = ctx.mozCurrentTransform;
 | 
						|
      var a = ctxMatrix[0], b = ctxMatrix[1], c = ctxMatrix[2];
 | 
						|
      var d = ctxMatrix[3], e = ctxMatrix[4], f = ctxMatrix[5];
 | 
						|
      var sx = (a >= 0) ?
 | 
						|
          Math.sqrt((a * a) + (b * b)) : -Math.sqrt((a * a) + (b * b));
 | 
						|
      var sy = (d >= 0) ?
 | 
						|
          Math.sqrt((c * c) + (d * d)) : -Math.sqrt((c * c) + (d * d));
 | 
						|
      var angle = Math.atan2(b, a);
 | 
						|
      var x = e;
 | 
						|
      var y = f;
 | 
						|
      geometry.x = x;
 | 
						|
      geometry.y = y;
 | 
						|
      geometry.hScale = sx;
 | 
						|
      geometry.vScale = sy;
 | 
						|
      geometry.angle = angle;
 | 
						|
      geometry.spaceWidth = font.spaceWidth;
 | 
						|
      geometry.fontName = font.loadedName;
 | 
						|
      geometry.fontFamily = font.fallbackName;
 | 
						|
      geometry.fontSize = this.current.fontSize;
 | 
						|
      return geometry;
 | 
						|
    },
 | 
						|
 | 
						|
    paintChar: function (character, x, y) {
 | 
						|
      var ctx = this.ctx;
 | 
						|
      var current = this.current;
 | 
						|
      var font = current.font;
 | 
						|
      var fontSize = current.fontSize / current.fontSizeScale;
 | 
						|
      var textRenderingMode = current.textRenderingMode;
 | 
						|
      var fillStrokeMode = textRenderingMode &
 | 
						|
        TextRenderingMode.FILL_STROKE_MASK;
 | 
						|
      var isAddToPathSet = !!(textRenderingMode &
 | 
						|
        TextRenderingMode.ADD_TO_PATH_FLAG);
 | 
						|
 | 
						|
      var addToPath;
 | 
						|
      if (font.disableFontFace || isAddToPathSet) {
 | 
						|
        addToPath = font.getPathGenerator(this.commonObjs, character);
 | 
						|
      }
 | 
						|
 | 
						|
      if (font.disableFontFace) {
 | 
						|
        ctx.save();
 | 
						|
        ctx.translate(x, y);
 | 
						|
        ctx.beginPath();
 | 
						|
        addToPath(ctx, fontSize);
 | 
						|
        if (fillStrokeMode === TextRenderingMode.FILL ||
 | 
						|
            fillStrokeMode === TextRenderingMode.FILL_STROKE) {
 | 
						|
          ctx.fill();
 | 
						|
        }
 | 
						|
        if (fillStrokeMode === TextRenderingMode.STROKE ||
 | 
						|
            fillStrokeMode === TextRenderingMode.FILL_STROKE) {
 | 
						|
          ctx.stroke();
 | 
						|
        }
 | 
						|
        ctx.restore();
 | 
						|
      } else {
 | 
						|
        if (fillStrokeMode === TextRenderingMode.FILL ||
 | 
						|
            fillStrokeMode === TextRenderingMode.FILL_STROKE) {
 | 
						|
          ctx.fillText(character, x, y);
 | 
						|
        }
 | 
						|
        if (fillStrokeMode === TextRenderingMode.STROKE ||
 | 
						|
            fillStrokeMode === TextRenderingMode.FILL_STROKE) {
 | 
						|
          ctx.strokeText(character, x, y);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (isAddToPathSet) {
 | 
						|
        var paths = this.pendingTextPaths || (this.pendingTextPaths = []);
 | 
						|
        paths.push({
 | 
						|
          transform: ctx.mozCurrentTransform,
 | 
						|
          x: x,
 | 
						|
          y: y,
 | 
						|
          fontSize: fontSize,
 | 
						|
          addToPath: addToPath
 | 
						|
        });
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    showText: function CanvasGraphics_showText(glyphs, skipTextSelection) {
 | 
						|
      var ctx = this.ctx;
 | 
						|
      var current = this.current;
 | 
						|
      var font = current.font;
 | 
						|
      var fontSize = current.fontSize;
 | 
						|
      var fontSizeScale = current.fontSizeScale;
 | 
						|
      var charSpacing = current.charSpacing;
 | 
						|
      var wordSpacing = current.wordSpacing;
 | 
						|
      var textHScale = current.textHScale * current.fontDirection;
 | 
						|
      var fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX;
 | 
						|
      var glyphsLength = glyphs.length;
 | 
						|
      var textLayer = this.textLayer;
 | 
						|
      var geom;
 | 
						|
      var textSelection = textLayer && !skipTextSelection ? true : false;
 | 
						|
      var canvasWidth = 0.0;
 | 
						|
      var vertical = font.vertical;
 | 
						|
      var defaultVMetrics = font.defaultVMetrics;
 | 
						|
 | 
						|
      // Type3 fonts - each glyph is a "mini-PDF"
 | 
						|
      if (font.coded) {
 | 
						|
        ctx.save();
 | 
						|
        ctx.transform.apply(ctx, current.textMatrix);
 | 
						|
        ctx.translate(current.x, current.y);
 | 
						|
 | 
						|
        ctx.scale(textHScale, 1);
 | 
						|
 | 
						|
        if (textSelection) {
 | 
						|
          this.save();
 | 
						|
          ctx.scale(1, -1);
 | 
						|
          geom = this.createTextGeometry();
 | 
						|
          this.restore();
 | 
						|
        }
 | 
						|
        for (var i = 0; i < glyphsLength; ++i) {
 | 
						|
 | 
						|
          var glyph = glyphs[i];
 | 
						|
          if (glyph === null) {
 | 
						|
            // word break
 | 
						|
            this.ctx.translate(wordSpacing, 0);
 | 
						|
            current.x += wordSpacing * textHScale;
 | 
						|
            continue;
 | 
						|
          }
 | 
						|
 | 
						|
          this.processingType3 = glyph;
 | 
						|
          this.save();
 | 
						|
          ctx.scale(fontSize, fontSize);
 | 
						|
          ctx.transform.apply(ctx, fontMatrix);
 | 
						|
          this.executeOperatorList(glyph.operatorList);
 | 
						|
          this.restore();
 | 
						|
 | 
						|
          var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
 | 
						|
          var width = (transformed[0] * fontSize + charSpacing) *
 | 
						|
                      current.fontDirection;
 | 
						|
 | 
						|
          ctx.translate(width, 0);
 | 
						|
          current.x += width * textHScale;
 | 
						|
 | 
						|
          canvasWidth += width;
 | 
						|
        }
 | 
						|
        ctx.restore();
 | 
						|
        this.processingType3 = null;
 | 
						|
      } else {
 | 
						|
        ctx.save();
 | 
						|
        this.applyTextTransforms();
 | 
						|
 | 
						|
        var lineWidth = current.lineWidth;
 | 
						|
        var a1 = current.textMatrix[0], b1 = current.textMatrix[1];
 | 
						|
        var scale = Math.sqrt(a1 * a1 + b1 * b1);
 | 
						|
        if (scale === 0 || lineWidth === 0)
 | 
						|
          lineWidth = this.getSinglePixelWidth();
 | 
						|
        else
 | 
						|
          lineWidth /= scale;
 | 
						|
 | 
						|
        if (textSelection)
 | 
						|
          geom = this.createTextGeometry();
 | 
						|
 | 
						|
        if (fontSizeScale != 1.0) {
 | 
						|
          ctx.scale(fontSizeScale, fontSizeScale);
 | 
						|
          lineWidth /= fontSizeScale;
 | 
						|
        }
 | 
						|
 | 
						|
        ctx.lineWidth = lineWidth;
 | 
						|
 | 
						|
        var x = 0;
 | 
						|
        for (var i = 0; i < glyphsLength; ++i) {
 | 
						|
          var glyph = glyphs[i];
 | 
						|
          if (glyph === null) {
 | 
						|
            // word break
 | 
						|
            x += current.fontDirection * wordSpacing;
 | 
						|
            continue;
 | 
						|
          }
 | 
						|
 | 
						|
          var restoreNeeded = false;
 | 
						|
          var character = glyph.fontChar;
 | 
						|
          var vmetric = glyph.vmetric || defaultVMetrics;
 | 
						|
          if (vertical) {
 | 
						|
            var vx = glyph.vmetric ? vmetric[1] : glyph.width * 0.5;
 | 
						|
            vx = -vx * fontSize * current.fontMatrix[0];
 | 
						|
            var vy = vmetric[2] * fontSize * current.fontMatrix[0];
 | 
						|
          }
 | 
						|
          var width = vmetric ? -vmetric[0] : glyph.width;
 | 
						|
          var charWidth = width * fontSize * current.fontMatrix[0] +
 | 
						|
                          charSpacing * current.fontDirection;
 | 
						|
          var accent = glyph.accent;
 | 
						|
 | 
						|
          var scaledX, scaledY, scaledAccentX, scaledAccentY;
 | 
						|
          if (!glyph.disabled) {
 | 
						|
            if (vertical) {
 | 
						|
              scaledX = vx / fontSizeScale;
 | 
						|
              scaledY = (x + vy) / fontSizeScale;
 | 
						|
            } else {
 | 
						|
              scaledX = x / fontSizeScale;
 | 
						|
              scaledY = 0;
 | 
						|
            }
 | 
						|
 | 
						|
            if (font.remeasure && width > 0) {
 | 
						|
              // some standard fonts may not have the exact width, trying to
 | 
						|
              // rescale per character
 | 
						|
              var measuredWidth = ctx.measureText(character).width * 1000 /
 | 
						|
                current.fontSize * current.fontSizeScale;
 | 
						|
              var characterScaleX = width / measuredWidth;
 | 
						|
              restoreNeeded = true;
 | 
						|
              ctx.save();
 | 
						|
              ctx.scale(characterScaleX, 1);
 | 
						|
              scaledX /= characterScaleX;
 | 
						|
              if (accent) {
 | 
						|
                scaledAccentX /= characterScaleX;
 | 
						|
              }
 | 
						|
            }
 | 
						|
 | 
						|
            this.paintChar(character, scaledX, scaledY);
 | 
						|
            if (accent) {
 | 
						|
              scaledAccentX = scaledX + accent.offset.x / fontSizeScale;
 | 
						|
              scaledAccentY = scaledY - accent.offset.y / fontSizeScale;
 | 
						|
              this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY);
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          x += charWidth;
 | 
						|
 | 
						|
          canvasWidth += charWidth;
 | 
						|
 | 
						|
          if (restoreNeeded) {
 | 
						|
            ctx.restore();
 | 
						|
          }
 | 
						|
        }
 | 
						|
        if (vertical) {
 | 
						|
          current.y -= x * textHScale;
 | 
						|
        } else {
 | 
						|
          current.x += x * textHScale;
 | 
						|
        }
 | 
						|
        ctx.restore();
 | 
						|
      }
 | 
						|
 | 
						|
      if (textSelection) {
 | 
						|
        geom.canvasWidth = canvasWidth;
 | 
						|
        if (vertical) {
 | 
						|
          var VERTICAL_TEXT_ROTATION = Math.PI / 2;
 | 
						|
          geom.angle += VERTICAL_TEXT_ROTATION;
 | 
						|
        }
 | 
						|
        this.textLayer.appendText(geom);
 | 
						|
      }
 | 
						|
 | 
						|
      return canvasWidth;
 | 
						|
    },
 | 
						|
    showSpacedText: function CanvasGraphics_showSpacedText(arr) {
 | 
						|
      var ctx = this.ctx;
 | 
						|
      var current = this.current;
 | 
						|
      var font = current.font;
 | 
						|
      var fontSize = current.fontSize;
 | 
						|
      // TJ array's number is independent from fontMatrix
 | 
						|
      var textHScale = current.textHScale * 0.001 * current.fontDirection;
 | 
						|
      var arrLength = arr.length;
 | 
						|
      var textLayer = this.textLayer;
 | 
						|
      var geom;
 | 
						|
      var canvasWidth = 0.0;
 | 
						|
      var textSelection = textLayer ? true : false;
 | 
						|
      var vertical = font.vertical;
 | 
						|
      var spacingAccumulator = 0;
 | 
						|
 | 
						|
      if (textSelection) {
 | 
						|
        ctx.save();
 | 
						|
        this.applyTextTransforms();
 | 
						|
        geom = this.createTextGeometry();
 | 
						|
        ctx.restore();
 | 
						|
      }
 | 
						|
 | 
						|
      for (var i = 0; i < arrLength; ++i) {
 | 
						|
        var e = arr[i];
 | 
						|
        if (isNum(e)) {
 | 
						|
          var spacingLength = -e * fontSize * textHScale;
 | 
						|
          if (vertical) {
 | 
						|
            current.y += spacingLength;
 | 
						|
          } else {
 | 
						|
            current.x += spacingLength;
 | 
						|
          }
 | 
						|
 | 
						|
          if (textSelection)
 | 
						|
            spacingAccumulator += spacingLength;
 | 
						|
        } else {
 | 
						|
          var shownCanvasWidth = this.showText(e, true);
 | 
						|
 | 
						|
          if (textSelection) {
 | 
						|
            canvasWidth += spacingAccumulator + shownCanvasWidth;
 | 
						|
            spacingAccumulator = 0;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (textSelection) {
 | 
						|
        geom.canvasWidth = canvasWidth;
 | 
						|
        if (vertical) {
 | 
						|
          var VERTICAL_TEXT_ROTATION = Math.PI / 2;
 | 
						|
          geom.angle += VERTICAL_TEXT_ROTATION;
 | 
						|
        }
 | 
						|
        this.textLayer.appendText(geom);
 | 
						|
      }
 | 
						|
    },
 | 
						|
    nextLineShowText: function CanvasGraphics_nextLineShowText(text) {
 | 
						|
      this.nextLine();
 | 
						|
      this.showText(text);
 | 
						|
    },
 | 
						|
    nextLineSetSpacingShowText:
 | 
						|
      function CanvasGraphics_nextLineSetSpacingShowText(wordSpacing,
 | 
						|
                                                         charSpacing,
 | 
						|
                                                         text) {
 | 
						|
      this.setWordSpacing(wordSpacing);
 | 
						|
      this.setCharSpacing(charSpacing);
 | 
						|
      this.nextLineShowText(text);
 | 
						|
    },
 | 
						|
 | 
						|
    // Type3 fonts
 | 
						|
    setCharWidth: function CanvasGraphics_setCharWidth(xWidth, yWidth) {
 | 
						|
      // We can safely ignore this since the width should be the same
 | 
						|
      // as the width in the Widths array.
 | 
						|
    },
 | 
						|
    setCharWidthAndBounds: function CanvasGraphics_setCharWidthAndBounds(xWidth,
 | 
						|
                                                                        yWidth,
 | 
						|
                                                                        llx,
 | 
						|
                                                                        lly,
 | 
						|
                                                                        urx,
 | 
						|
                                                                        ury) {
 | 
						|
      // TODO According to the spec we're also suppose to ignore any operators
 | 
						|
      // that set color or include images while processing this type3 font.
 | 
						|
      this.rectangle(llx, lly, urx - llx, ury - lly);
 | 
						|
      this.clip();
 | 
						|
      this.endPath();
 | 
						|
    },
 | 
						|
 | 
						|
    // Color
 | 
						|
    setStrokeColorSpace: function CanvasGraphics_setStrokeColorSpace(raw) {
 | 
						|
      this.current.strokeColorSpace = ColorSpace.fromIR(raw);
 | 
						|
    },
 | 
						|
    setFillColorSpace: function CanvasGraphics_setFillColorSpace(raw) {
 | 
						|
      this.current.fillColorSpace = ColorSpace.fromIR(raw);
 | 
						|
    },
 | 
						|
    setStrokeColor: function CanvasGraphics_setStrokeColor(/*...*/) {
 | 
						|
      var cs = this.current.strokeColorSpace;
 | 
						|
      var rgbColor = cs.getRgb(arguments, 0);
 | 
						|
      var color = Util.makeCssRgb(rgbColor);
 | 
						|
      this.ctx.strokeStyle = color;
 | 
						|
      this.current.strokeColor = color;
 | 
						|
    },
 | 
						|
    getColorN_Pattern: function CanvasGraphics_getColorN_Pattern(IR, cs) {
 | 
						|
      if (IR[0] == 'TilingPattern') {
 | 
						|
        var args = IR[1];
 | 
						|
        var base = cs.base;
 | 
						|
        var color;
 | 
						|
        if (base) {
 | 
						|
          var baseComps = base.numComps;
 | 
						|
 | 
						|
          color = base.getRgb(args, 0);
 | 
						|
        }
 | 
						|
        var pattern = new TilingPattern(IR, color, this.ctx, this.objs,
 | 
						|
                                        this.commonObjs, this.baseTransform);
 | 
						|
      } else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') {
 | 
						|
        var pattern = Pattern.shadingFromIR(IR);
 | 
						|
      } else {
 | 
						|
        error('Unkown IR type ' + IR[0]);
 | 
						|
      }
 | 
						|
      return pattern;
 | 
						|
    },
 | 
						|
    setStrokeColorN: function CanvasGraphics_setStrokeColorN(/*...*/) {
 | 
						|
      var cs = this.current.strokeColorSpace;
 | 
						|
 | 
						|
      if (cs.name == 'Pattern') {
 | 
						|
        this.current.strokeColor = this.getColorN_Pattern(arguments, cs);
 | 
						|
      } else {
 | 
						|
        this.setStrokeColor.apply(this, arguments);
 | 
						|
      }
 | 
						|
    },
 | 
						|
    setFillColor: function CanvasGraphics_setFillColor(/*...*/) {
 | 
						|
      var cs = this.current.fillColorSpace;
 | 
						|
      var rgbColor = cs.getRgb(arguments, 0);
 | 
						|
      var color = Util.makeCssRgb(rgbColor);
 | 
						|
      this.ctx.fillStyle = color;
 | 
						|
      this.current.fillColor = color;
 | 
						|
    },
 | 
						|
    setFillColorN: function CanvasGraphics_setFillColorN(/*...*/) {
 | 
						|
      var cs = this.current.fillColorSpace;
 | 
						|
 | 
						|
      if (cs.name == 'Pattern') {
 | 
						|
        this.current.fillColor = this.getColorN_Pattern(arguments, cs);
 | 
						|
      } else {
 | 
						|
        this.setFillColor.apply(this, arguments);
 | 
						|
      }
 | 
						|
    },
 | 
						|
    setStrokeGray: function CanvasGraphics_setStrokeGray(gray) {
 | 
						|
      this.current.strokeColorSpace = ColorSpace.singletons.gray;
 | 
						|
 | 
						|
      var rgbColor = this.current.strokeColorSpace.getRgb(arguments, 0);
 | 
						|
      var color = Util.makeCssRgb(rgbColor);
 | 
						|
      this.ctx.strokeStyle = color;
 | 
						|
      this.current.strokeColor = color;
 | 
						|
    },
 | 
						|
    setFillGray: function CanvasGraphics_setFillGray(gray) {
 | 
						|
      this.current.fillColorSpace = ColorSpace.singletons.gray;
 | 
						|
 | 
						|
      var rgbColor = this.current.fillColorSpace.getRgb(arguments, 0);
 | 
						|
      var color = Util.makeCssRgb(rgbColor);
 | 
						|
      this.ctx.fillStyle = color;
 | 
						|
      this.current.fillColor = color;
 | 
						|
    },
 | 
						|
    setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) {
 | 
						|
      this.current.strokeColorSpace = ColorSpace.singletons.rgb;
 | 
						|
 | 
						|
      var rgbColor = this.current.strokeColorSpace.getRgb(arguments, 0);
 | 
						|
      var color = Util.makeCssRgb(rgbColor);
 | 
						|
      this.ctx.strokeStyle = color;
 | 
						|
      this.current.strokeColor = color;
 | 
						|
    },
 | 
						|
    setFillRGBColor: function CanvasGraphics_setFillRGBColor(r, g, b) {
 | 
						|
      this.current.fillColorSpace = ColorSpace.singletons.rgb;
 | 
						|
 | 
						|
      var rgbColor = this.current.fillColorSpace.getRgb(arguments, 0);
 | 
						|
      var color = Util.makeCssRgb(rgbColor);
 | 
						|
      this.ctx.fillStyle = color;
 | 
						|
      this.current.fillColor = color;
 | 
						|
    },
 | 
						|
    setStrokeCMYKColor: function CanvasGraphics_setStrokeCMYKColor(c, m, y, k) {
 | 
						|
      this.current.strokeColorSpace = ColorSpace.singletons.cmyk;
 | 
						|
 | 
						|
      var color = Util.makeCssCmyk(arguments);
 | 
						|
      this.ctx.strokeStyle = color;
 | 
						|
      this.current.strokeColor = color;
 | 
						|
    },
 | 
						|
    setFillCMYKColor: function CanvasGraphics_setFillCMYKColor(c, m, y, k) {
 | 
						|
      this.current.fillColorSpace = ColorSpace.singletons.cmyk;
 | 
						|
 | 
						|
      var color = Util.makeCssCmyk(arguments);
 | 
						|
      this.ctx.fillStyle = color;
 | 
						|
      this.current.fillColor = color;
 | 
						|
    },
 | 
						|
 | 
						|
    shadingFill: function CanvasGraphics_shadingFill(patternIR) {
 | 
						|
      var ctx = this.ctx;
 | 
						|
 | 
						|
      this.save();
 | 
						|
      var pattern = Pattern.shadingFromIR(patternIR);
 | 
						|
      ctx.fillStyle = pattern.getPattern(ctx, this);
 | 
						|
 | 
						|
      var inv = ctx.mozCurrentTransformInverse;
 | 
						|
      if (inv) {
 | 
						|
        var canvas = ctx.canvas;
 | 
						|
        var width = canvas.width;
 | 
						|
        var height = canvas.height;
 | 
						|
 | 
						|
        var bl = Util.applyTransform([0, 0], inv);
 | 
						|
        var br = Util.applyTransform([0, height], inv);
 | 
						|
        var ul = Util.applyTransform([width, 0], inv);
 | 
						|
        var ur = Util.applyTransform([width, height], inv);
 | 
						|
 | 
						|
        var x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
 | 
						|
        var y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
 | 
						|
        var x1 = Math.max(bl[0], br[0], ul[0], ur[0]);
 | 
						|
        var y1 = Math.max(bl[1], br[1], ul[1], ur[1]);
 | 
						|
 | 
						|
        this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0);
 | 
						|
      } else {
 | 
						|
        // HACK to draw the gradient onto an infinite rectangle.
 | 
						|
        // PDF gradients are drawn across the entire image while
 | 
						|
        // Canvas only allows gradients to be drawn in a rectangle
 | 
						|
        // The following bug should allow us to remove this.
 | 
						|
        // https://bugzilla.mozilla.org/show_bug.cgi?id=664884
 | 
						|
 | 
						|
        this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
 | 
						|
      }
 | 
						|
 | 
						|
      this.restore();
 | 
						|
    },
 | 
						|
 | 
						|
    // Images
 | 
						|
    beginInlineImage: function CanvasGraphics_beginInlineImage() {
 | 
						|
      error('Should not call beginInlineImage');
 | 
						|
    },
 | 
						|
    beginImageData: function CanvasGraphics_beginImageData() {
 | 
						|
      error('Should not call beginImageData');
 | 
						|
    },
 | 
						|
 | 
						|
    paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix,
 | 
						|
                                                                        bbox) {
 | 
						|
      this.save();
 | 
						|
      this.current.paintFormXObjectDepth++;
 | 
						|
      this.baseTransformStack.push(this.baseTransform);
 | 
						|
 | 
						|
      if (matrix && isArray(matrix) && 6 == matrix.length)
 | 
						|
        this.transform.apply(this, matrix);
 | 
						|
 | 
						|
      this.baseTransform = this.ctx.mozCurrentTransform;
 | 
						|
 | 
						|
      if (bbox && isArray(bbox) && 4 == bbox.length) {
 | 
						|
        var width = bbox[2] - bbox[0];
 | 
						|
        var height = bbox[3] - bbox[1];
 | 
						|
        this.rectangle(bbox[0], bbox[1], width, height);
 | 
						|
        this.clip();
 | 
						|
        this.endPath();
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() {
 | 
						|
      var depth = this.current.paintFormXObjectDepth;
 | 
						|
      do {
 | 
						|
        this.restore();
 | 
						|
        // some pdf don't close all restores inside object
 | 
						|
        // closing those for them
 | 
						|
      } while (this.current.paintFormXObjectDepth >= depth);
 | 
						|
      this.baseTransform = this.baseTransformStack.pop();
 | 
						|
    },
 | 
						|
 | 
						|
    beginGroup: function CanvasGraphics_beginGroup(group) {
 | 
						|
      this.save();
 | 
						|
      var currentCtx = this.ctx;
 | 
						|
      // TODO non-isolated groups - according to Rik at adobe non-isolated
 | 
						|
      // group results aren't usually that different and they even have tools
 | 
						|
      // that ignore this setting. Notes from Rik on implmenting:
 | 
						|
      // - When you encounter an transparency group, create a new canvas with
 | 
						|
      // the dimensions of the bbox
 | 
						|
      // - copy the content from the previous canvas to the new canvas
 | 
						|
      // - draw as usual
 | 
						|
      // - remove the backdrop alpha:
 | 
						|
      // alphaNew = 1 - (1 - alpha)/(1 - alphaBackdrop) with 'alpha' the alpha
 | 
						|
      // value of your transparency group and 'alphaBackdrop' the alpha of the
 | 
						|
      // backdrop
 | 
						|
      // - remove background color:
 | 
						|
      // colorNew = color - alphaNew *colorBackdrop /(1 - alphaNew)
 | 
						|
      if (!group.isolated) {
 | 
						|
        info('TODO: Support non-isolated groups.');
 | 
						|
      }
 | 
						|
 | 
						|
      // TODO knockout - supposedly possible with the clever use of compositing
 | 
						|
      // modes.
 | 
						|
      if (group.knockout) {
 | 
						|
        TODO('Support knockout groups.');
 | 
						|
      }
 | 
						|
 | 
						|
      var currentTransform = currentCtx.mozCurrentTransform;
 | 
						|
      if (group.matrix) {
 | 
						|
        currentCtx.transform.apply(currentCtx, group.matrix);
 | 
						|
      }
 | 
						|
      assert(group.bbox, 'Bounding box is required.');
 | 
						|
 | 
						|
      // Based on the current transform figure out how big the bounding box
 | 
						|
      // will actually be.
 | 
						|
      var bounds = Util.getAxialAlignedBoundingBox(
 | 
						|
                    group.bbox,
 | 
						|
                    currentCtx.mozCurrentTransform);
 | 
						|
      // Clip the bounding box to the current canvas.
 | 
						|
      var canvasBounds = [0,
 | 
						|
                          0,
 | 
						|
                          currentCtx.canvas.width,
 | 
						|
                          currentCtx.canvas.height];
 | 
						|
      bounds = Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0];
 | 
						|
      // Use ceil in case we're between sizes so we don't create canvas that is
 | 
						|
      // too small and make the canvas at least 1x1 pixels.
 | 
						|
      var drawnWidth = Math.max(Math.ceil(bounds[2] - bounds[0]), 1);
 | 
						|
      var drawnHeight = Math.max(Math.ceil(bounds[3] - bounds[1]), 1);
 | 
						|
 | 
						|
      var scratchCanvas = CachedCanvases.getCanvas(
 | 
						|
        'groupAt' + this.groupLevel, drawnWidth, drawnHeight, true);
 | 
						|
      var groupCtx = scratchCanvas.context;
 | 
						|
      // Since we created a new canvas that is just the size of the bounding box
 | 
						|
      // we have to translate the group ctx.
 | 
						|
      var offsetX = bounds[0];
 | 
						|
      var offsetY = bounds[1];
 | 
						|
      groupCtx.translate(-offsetX, -offsetY);
 | 
						|
      groupCtx.transform.apply(groupCtx, currentTransform);
 | 
						|
 | 
						|
      // Setup the current ctx so when the group is popped we draw it the right
 | 
						|
      // location.
 | 
						|
      currentCtx.setTransform(1, 0, 0, 1, 0, 0);
 | 
						|
      currentCtx.translate(offsetX, offsetY);
 | 
						|
      // The transparency group inherits all off the current graphics state
 | 
						|
      // except the blend mode, soft mask, and alpha constants.
 | 
						|
      copyCtxState(currentCtx, groupCtx);
 | 
						|
      this.ctx = groupCtx;
 | 
						|
      this.setGState([
 | 
						|
        ['SMask', 'None'],
 | 
						|
        ['BM', 'Normal'],
 | 
						|
        ['ca', 1],
 | 
						|
        ['CA', 1]
 | 
						|
      ]);
 | 
						|
      this.groupStack.push(currentCtx);
 | 
						|
      this.groupLevel++;
 | 
						|
    },
 | 
						|
 | 
						|
    endGroup: function CanvasGraphics_endGroup(group) {
 | 
						|
      this.groupLevel--;
 | 
						|
      var groupCtx = this.ctx;
 | 
						|
      this.ctx = this.groupStack.pop();
 | 
						|
      // Turn off image smoothing to avoid sub pixel interpolation which can
 | 
						|
      // look kind of blurry for some pdfs.
 | 
						|
      if ('imageSmoothingEnabled' in this.ctx) {
 | 
						|
        this.ctx.imageSmoothingEnabled = false;
 | 
						|
      } else {
 | 
						|
        this.ctx.mozImageSmoothingEnabled = false;
 | 
						|
      }
 | 
						|
      this.ctx.drawImage(groupCtx.canvas, 0, 0);
 | 
						|
      this.restore();
 | 
						|
    },
 | 
						|
 | 
						|
    beginAnnotations: function CanvasGraphics_beginAnnotations() {
 | 
						|
      this.save();
 | 
						|
      this.current = new CanvasExtraState();
 | 
						|
    },
 | 
						|
 | 
						|
    endAnnotations: function CanvasGraphics_endAnnotations() {
 | 
						|
      this.restore();
 | 
						|
    },
 | 
						|
 | 
						|
    beginAnnotation: function CanvasGraphics_beginAnnotation(rect, transform,
 | 
						|
                                                             matrix) {
 | 
						|
      this.save();
 | 
						|
 | 
						|
      if (rect && isArray(rect) && 4 == rect.length) {
 | 
						|
        var width = rect[2] - rect[0];
 | 
						|
        var height = rect[3] - rect[1];
 | 
						|
        this.rectangle(rect[0], rect[1], width, height);
 | 
						|
        this.clip();
 | 
						|
        this.endPath();
 | 
						|
      }
 | 
						|
 | 
						|
      this.transform.apply(this, transform);
 | 
						|
      this.transform.apply(this, matrix);
 | 
						|
    },
 | 
						|
 | 
						|
    endAnnotation: function CanvasGraphics_endAnnotation() {
 | 
						|
      this.restore();
 | 
						|
    },
 | 
						|
 | 
						|
    paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
 | 
						|
      var domImage = this.objs.get(objId);
 | 
						|
      if (!domImage) {
 | 
						|
        error('Dependent image isn\'t ready yet');
 | 
						|
      }
 | 
						|
 | 
						|
      this.save();
 | 
						|
 | 
						|
      var ctx = this.ctx;
 | 
						|
      // scale the image to the unit square
 | 
						|
      ctx.scale(1 / w, -1 / h);
 | 
						|
 | 
						|
      ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
 | 
						|
                    0, -h, w, h);
 | 
						|
      if (this.imageLayer) {
 | 
						|
        var currentTransform = ctx.mozCurrentTransformInverse;
 | 
						|
        var position = this.getCanvasPosition(0, 0);
 | 
						|
        this.imageLayer.appendImage({
 | 
						|
          objId: objId,
 | 
						|
          left: position[0],
 | 
						|
          top: position[1],
 | 
						|
          width: w / currentTransform[0],
 | 
						|
          height: h / currentTransform[3]
 | 
						|
        });
 | 
						|
      }
 | 
						|
      this.restore();
 | 
						|
    },
 | 
						|
 | 
						|
    paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(img) {
 | 
						|
      var ctx = this.ctx;
 | 
						|
      var width = img.width, height = img.height;
 | 
						|
 | 
						|
      var glyph = this.processingType3;
 | 
						|
 | 
						|
      if (COMPILE_TYPE3_GLYPHS && glyph && !('compiled' in glyph)) {
 | 
						|
        var MAX_SIZE_TO_COMPILE = 1000;
 | 
						|
        if (width <= MAX_SIZE_TO_COMPILE && height <= MAX_SIZE_TO_COMPILE) {
 | 
						|
          glyph.compiled =
 | 
						|
            compileType3Glyph({data: img.data, width: width, height: height});
 | 
						|
        } else {
 | 
						|
          glyph.compiled = null;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (glyph && glyph.compiled) {
 | 
						|
        glyph.compiled(ctx);
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
 | 
						|
      var maskCtx = maskCanvas.context;
 | 
						|
      maskCtx.save();
 | 
						|
 | 
						|
      putBinaryImageData(maskCtx, img);
 | 
						|
 | 
						|
      maskCtx.globalCompositeOperation = 'source-in';
 | 
						|
 | 
						|
      var fillColor = this.current.fillColor;
 | 
						|
      maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
 | 
						|
                          fillColor.type === 'Pattern') ?
 | 
						|
                          fillColor.getPattern(maskCtx, this) : fillColor;
 | 
						|
      maskCtx.fillRect(0, 0, width, height);
 | 
						|
 | 
						|
      maskCtx.restore();
 | 
						|
 | 
						|
      this.paintInlineImageXObject(maskCanvas.canvas);
 | 
						|
    },
 | 
						|
 | 
						|
    paintImageMaskXObjectGroup:
 | 
						|
      function CanvasGraphics_paintImageMaskXObjectGroup(images) {
 | 
						|
      var ctx = this.ctx;
 | 
						|
 | 
						|
      for (var i = 0, ii = images.length; i < ii; i++) {
 | 
						|
        var image = images[i];
 | 
						|
        var width = image.width, height = image.height;
 | 
						|
 | 
						|
        var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
 | 
						|
        var maskCtx = maskCanvas.context;
 | 
						|
        maskCtx.save();
 | 
						|
 | 
						|
        putBinaryImageData(maskCtx, image);
 | 
						|
 | 
						|
        maskCtx.globalCompositeOperation = 'source-in';
 | 
						|
 | 
						|
        var fillColor = this.current.fillColor;
 | 
						|
        maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
 | 
						|
                            fillColor.type === 'Pattern') ?
 | 
						|
                            fillColor.getPattern(maskCtx, this) : fillColor;
 | 
						|
        maskCtx.fillRect(0, 0, width, height);
 | 
						|
 | 
						|
        maskCtx.restore();
 | 
						|
 | 
						|
        ctx.save();
 | 
						|
        ctx.transform.apply(ctx, image.transform);
 | 
						|
        ctx.scale(1, -1);
 | 
						|
        ctx.drawImage(maskCanvas.canvas, 0, 0, width, height,
 | 
						|
                      0, -1, 1, 1);
 | 
						|
        ctx.restore();
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
 | 
						|
      var imgData = this.objs.get(objId);
 | 
						|
      if (!imgData)
 | 
						|
        error('Dependent image isn\'t ready yet');
 | 
						|
 | 
						|
      this.paintInlineImageXObject(imgData);
 | 
						|
    },
 | 
						|
 | 
						|
    paintInlineImageXObject:
 | 
						|
      function CanvasGraphics_paintInlineImageXObject(imgData) {
 | 
						|
      var width = imgData.width;
 | 
						|
      var height = imgData.height;
 | 
						|
      var ctx = this.ctx;
 | 
						|
 | 
						|
      this.save();
 | 
						|
      // scale the image to the unit square
 | 
						|
      ctx.scale(1 / width, -1 / height);
 | 
						|
 | 
						|
      var currentTransform = ctx.mozCurrentTransformInverse;
 | 
						|
      var a = currentTransform[0], b = currentTransform[1];
 | 
						|
      var widthScale = Math.max(Math.sqrt(a * a + b * b), 1);
 | 
						|
      var c = currentTransform[2], d = currentTransform[3];
 | 
						|
      var heightScale = Math.max(Math.sqrt(c * c + d * d), 1);
 | 
						|
 | 
						|
      var imgToPaint;
 | 
						|
      // instanceof HTMLElement does not work in jsdom node.js module
 | 
						|
      if (imgData instanceof HTMLElement || !imgData.data) {
 | 
						|
        imgToPaint = imgData;
 | 
						|
      } else {
 | 
						|
        var tmpCanvas = CachedCanvases.getCanvas('inlineImage', width, height);
 | 
						|
        var tmpCtx = tmpCanvas.context;
 | 
						|
        putBinaryImageData(tmpCtx, imgData);
 | 
						|
        imgToPaint = tmpCanvas.canvas;
 | 
						|
      }
 | 
						|
 | 
						|
      var paintWidth = width, paintHeight = height;
 | 
						|
      var tmpCanvasId = 'prescale1';
 | 
						|
      // Vertial or horizontal scaling shall not be more than 2 to not loose the
 | 
						|
      // pixels during drawImage operation, painting on the temporary canvas(es)
 | 
						|
      // that are twice smaller in size
 | 
						|
      while ((widthScale > 2 && paintWidth > 1) ||
 | 
						|
             (heightScale > 2 && paintHeight > 1)) {
 | 
						|
        var newWidth = paintWidth, newHeight = paintHeight;
 | 
						|
        if (widthScale > 2 && paintWidth > 1) {
 | 
						|
          newWidth = Math.ceil(paintWidth / 2);
 | 
						|
          widthScale /= paintWidth / newWidth;
 | 
						|
        }
 | 
						|
        if (heightScale > 2 && paintHeight > 1) {
 | 
						|
          newHeight = Math.ceil(paintHeight / 2);
 | 
						|
          heightScale /= paintHeight / newHeight;
 | 
						|
        }
 | 
						|
        var tmpCanvas = CachedCanvases.getCanvas(tmpCanvasId,
 | 
						|
                                                 newWidth, newHeight);
 | 
						|
        tmpCtx = tmpCanvas.context;
 | 
						|
        tmpCtx.clearRect(0, 0, newWidth, newHeight);
 | 
						|
        tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight,
 | 
						|
                                     0, 0, newWidth, newHeight);
 | 
						|
        imgToPaint = tmpCanvas.canvas;
 | 
						|
        paintWidth = newWidth;
 | 
						|
        paintHeight = newHeight;
 | 
						|
        tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1';
 | 
						|
      }
 | 
						|
      ctx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight,
 | 
						|
                                0, -height, width, height);
 | 
						|
 | 
						|
      if (this.imageLayer) {
 | 
						|
        var position = this.getCanvasPosition(0, -height);
 | 
						|
        this.imageLayer.appendImage({
 | 
						|
          imgData: imgData,
 | 
						|
          left: position[0],
 | 
						|
          top: position[1],
 | 
						|
          width: width / currentTransform[0],
 | 
						|
          height: height / currentTransform[3]
 | 
						|
        });
 | 
						|
      }
 | 
						|
      this.restore();
 | 
						|
    },
 | 
						|
 | 
						|
    paintInlineImageXObjectGroup:
 | 
						|
      function CanvasGraphics_paintInlineImageXObjectGroup(imgData, map) {
 | 
						|
      var ctx = this.ctx;
 | 
						|
      var w = imgData.width;
 | 
						|
      var h = imgData.height;
 | 
						|
 | 
						|
      var tmpCanvas = CachedCanvases.getCanvas('inlineImage', w, h);
 | 
						|
      var tmpCtx = tmpCanvas.context;
 | 
						|
      putBinaryImageData(tmpCtx, imgData);
 | 
						|
 | 
						|
      for (var i = 0, ii = map.length; i < ii; i++) {
 | 
						|
        var entry = map[i];
 | 
						|
        ctx.save();
 | 
						|
        ctx.transform.apply(ctx, entry.transform);
 | 
						|
        ctx.scale(1, -1);
 | 
						|
        ctx.drawImage(tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h,
 | 
						|
                      0, -1, 1, 1);
 | 
						|
        if (this.imageLayer) {
 | 
						|
          var position = this.getCanvasPosition(entry.x, entry.y);
 | 
						|
          this.imageLayer.appendImage({
 | 
						|
            imgData: imgData,
 | 
						|
            left: position[0],
 | 
						|
            top: position[1],
 | 
						|
            width: w,
 | 
						|
            height: h
 | 
						|
          });
 | 
						|
        }
 | 
						|
        ctx.restore();
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    // Marked content
 | 
						|
 | 
						|
    markPoint: function CanvasGraphics_markPoint(tag) {
 | 
						|
      // TODO Marked content.
 | 
						|
    },
 | 
						|
    markPointProps: function CanvasGraphics_markPointProps(tag, properties) {
 | 
						|
      // TODO Marked content.
 | 
						|
    },
 | 
						|
    beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) {
 | 
						|
      // TODO Marked content.
 | 
						|
    },
 | 
						|
    beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps(
 | 
						|
                                        tag, properties) {
 | 
						|
      // TODO Marked content.
 | 
						|
    },
 | 
						|
    endMarkedContent: function CanvasGraphics_endMarkedContent() {
 | 
						|
      // TODO Marked content.
 | 
						|
    },
 | 
						|
 | 
						|
    // Compatibility
 | 
						|
 | 
						|
    beginCompat: function CanvasGraphics_beginCompat() {
 | 
						|
      // TODO ignore undefined operators (should we do that anyway?)
 | 
						|
    },
 | 
						|
    endCompat: function CanvasGraphics_endCompat() {
 | 
						|
      // TODO stop ignoring undefined operators
 | 
						|
    },
 | 
						|
 | 
						|
    // Helper functions
 | 
						|
 | 
						|
    consumePath: function CanvasGraphics_consumePath() {
 | 
						|
      if (this.pendingClip) {
 | 
						|
        if (this.pendingClip == EO_CLIP) {
 | 
						|
          if ('mozFillRule' in this.ctx) {
 | 
						|
            this.ctx.mozFillRule = 'evenodd';
 | 
						|
            this.ctx.clip();
 | 
						|
            this.ctx.mozFillRule = 'nonzero';
 | 
						|
          } else {
 | 
						|
            try {
 | 
						|
              this.ctx.clip('evenodd');
 | 
						|
            } catch (ex) {
 | 
						|
              // shouldn't really happen, but browsers might think differently
 | 
						|
              this.ctx.clip();
 | 
						|
            }
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          this.ctx.clip();
 | 
						|
        }
 | 
						|
        this.pendingClip = null;
 | 
						|
      }
 | 
						|
      this.ctx.beginPath();
 | 
						|
    },
 | 
						|
    getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) {
 | 
						|
      var inverse = this.ctx.mozCurrentTransformInverse;
 | 
						|
      // max of the current horizontal and vertical scale
 | 
						|
      return Math.sqrt(Math.max(
 | 
						|
        (inverse[0] * inverse[0] + inverse[1] * inverse[1]),
 | 
						|
        (inverse[2] * inverse[2] + inverse[3] * inverse[3])));
 | 
						|
    },
 | 
						|
    getCanvasPosition: function CanvasGraphics_getCanvasPosition(x, y) {
 | 
						|
        var transform = this.ctx.mozCurrentTransform;
 | 
						|
        return [
 | 
						|
          transform[0] * x + transform[2] * y + transform[4],
 | 
						|
          transform[1] * x + transform[3] * y + transform[5]
 | 
						|
        ];
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  for (var op in OPS) {
 | 
						|
    CanvasGraphics.prototype[OPS[op]] = CanvasGraphics.prototype[op];
 | 
						|
  }
 | 
						|
 | 
						|
  return CanvasGraphics;
 | 
						|
})();
 | 
						|
 | 
						|
 | 
						|
 | 
						|
PDFJS.disableFontFace = false;
 | 
						|
 | 
						|
var FontLoader = {
 | 
						|
  insertRule: function fontLoaderInsertRule(rule) {
 | 
						|
    var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
 | 
						|
    if (!styleElement) {
 | 
						|
        styleElement = document.createElement('style');
 | 
						|
        styleElement.id = 'PDFJS_FONT_STYLE_TAG';
 | 
						|
        document.documentElement.getElementsByTagName('head')[0].appendChild(
 | 
						|
          styleElement);
 | 
						|
    }
 | 
						|
 | 
						|
    var styleSheet = styleElement.sheet;
 | 
						|
    styleSheet.insertRule(rule, styleSheet.cssRules.length);
 | 
						|
  },
 | 
						|
  clear: function fontLoaderClear() {
 | 
						|
    var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
 | 
						|
    if (styleElement) {
 | 
						|
      styleElement.parentNode.removeChild(styleElement);
 | 
						|
    }
 | 
						|
  },
 | 
						|
  get loadTestFont() {
 | 
						|
    // This is a CFF font with 1 glyph for '.' that fills its entire width and
 | 
						|
    // height.
 | 
						|
    return shadow(this, 'loadTestFont', atob(
 | 
						|
      'T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQ' +
 | 
						|
      'AABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwA' +
 | 
						|
      'AAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbm' +
 | 
						|
      'FtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAA' +
 | 
						|
      'AADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6A' +
 | 
						|
      'ABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAA' +
 | 
						|
      'MQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAA' +
 | 
						|
      'AAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAA' +
 | 
						|
      'AAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQ' +
 | 
						|
      'AAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMA' +
 | 
						|
      'AQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAA' +
 | 
						|
      'EAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAA' +
 | 
						|
      'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAA' +
 | 
						|
      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
 | 
						|
      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
 | 
						|
      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
 | 
						|
      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA' +
 | 
						|
      'AAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgc' +
 | 
						|
      'A/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF' +
 | 
						|
      'hYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQA' +
 | 
						|
      'AAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAg' +
 | 
						|
      'ABAAAAAAAAAAAD6AAAAAAAAA=='
 | 
						|
    ));
 | 
						|
  },
 | 
						|
 | 
						|
  loadTestFontId: 0,
 | 
						|
 | 
						|
  loadingContext: {
 | 
						|
    requests: [],
 | 
						|
    nextRequestId: 0
 | 
						|
  },
 | 
						|
 | 
						|
  isSyncFontLoadingSupported: (function detectSyncFontLoadingSupport() {
 | 
						|
    if (isWorker)
 | 
						|
      return false;
 | 
						|
 | 
						|
    // User agent string sniffing is bad, but there is no reliable way to tell
 | 
						|
    // if font is fully loaded and ready to be used with canvas.
 | 
						|
    var userAgent = window.navigator.userAgent;
 | 
						|
    var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent);
 | 
						|
    if (m && m[1] >= 14)
 | 
						|
      return true;
 | 
						|
    // TODO other browsers
 | 
						|
    return false;
 | 
						|
  })(),
 | 
						|
 | 
						|
  bind: function fontLoaderBind(fonts, callback) {
 | 
						|
    assert(!isWorker, 'bind() shall be called from main thread');
 | 
						|
 | 
						|
    var rules = [], fontsToLoad = [];
 | 
						|
    for (var i = 0, ii = fonts.length; i < ii; i++) {
 | 
						|
      var font = fonts[i];
 | 
						|
 | 
						|
      // Add the font to the DOM only once or skip if the font
 | 
						|
      // is already loaded.
 | 
						|
      if (font.attached || font.loading === false) {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      font.attached = true;
 | 
						|
 | 
						|
      var rule = font.bindDOM();
 | 
						|
      if (rule) {
 | 
						|
        rules.push(rule);
 | 
						|
        fontsToLoad.push(font);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    var request = FontLoader.queueLoadingCallback(callback);
 | 
						|
    if (rules.length > 0 && !this.isSyncFontLoadingSupported) {
 | 
						|
      FontLoader.prepareFontLoadEvent(rules, fontsToLoad, request);
 | 
						|
    } else {
 | 
						|
      request.complete();
 | 
						|
    }
 | 
						|
  },
 | 
						|
 | 
						|
  queueLoadingCallback: function FontLoader_queueLoadingCallback(callback) {
 | 
						|
    function LoadLoader_completeRequest() {
 | 
						|
      assert(!request.end, 'completeRequest() cannot be called twice');
 | 
						|
      request.end = Date.now();
 | 
						|
 | 
						|
      // sending all completed requests in order how they were queued
 | 
						|
      while (context.requests.length > 0 && context.requests[0].end) {
 | 
						|
        var otherRequest = context.requests.shift();
 | 
						|
        setTimeout(otherRequest.callback, 0);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    var context = FontLoader.loadingContext;
 | 
						|
    var requestId = 'pdfjs-font-loading-' + (context.nextRequestId++);
 | 
						|
    var request = {
 | 
						|
      id: requestId,
 | 
						|
      complete: LoadLoader_completeRequest,
 | 
						|
      callback: callback,
 | 
						|
      started: Date.now()
 | 
						|
    };
 | 
						|
    context.requests.push(request);
 | 
						|
    return request;
 | 
						|
  },
 | 
						|
 | 
						|
  prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules,
 | 
						|
                                                                fonts,
 | 
						|
                                                                request) {
 | 
						|
      /** Hack begin */
 | 
						|
      // There's currently no event when a font has finished downloading so the
 | 
						|
      // following code is a dirty hack to 'guess' when a font is
 | 
						|
      // ready. It's assumed fonts are loaded in order, so add a known test
 | 
						|
      // font after the desired fonts and then test for the loading of that
 | 
						|
      // test font.
 | 
						|
 | 
						|
      function int32(data, offset) {
 | 
						|
        return (data.charCodeAt(offset) << 24) |
 | 
						|
               (data.charCodeAt(offset + 1) << 16) |
 | 
						|
               (data.charCodeAt(offset + 2) << 8) |
 | 
						|
               (data.charCodeAt(offset + 3) & 0xff);
 | 
						|
      }
 | 
						|
 | 
						|
      function string32(value) {
 | 
						|
        return String.fromCharCode((value >> 24) & 0xff) +
 | 
						|
               String.fromCharCode((value >> 16) & 0xff) +
 | 
						|
               String.fromCharCode((value >> 8) & 0xff) +
 | 
						|
               String.fromCharCode(value & 0xff);
 | 
						|
      }
 | 
						|
 | 
						|
      function spliceString(s, offset, remove, insert) {
 | 
						|
        var chunk1 = data.substr(0, offset);
 | 
						|
        var chunk2 = data.substr(offset + remove);
 | 
						|
        return chunk1 + insert + chunk2;
 | 
						|
      }
 | 
						|
 | 
						|
      var i, ii;
 | 
						|
 | 
						|
      var canvas = document.createElement('canvas');
 | 
						|
      canvas.width = 1;
 | 
						|
      canvas.height = 1;
 | 
						|
      var ctx = canvas.getContext('2d');
 | 
						|
 | 
						|
      var called = 0;
 | 
						|
      function isFontReady(name, callback) {
 | 
						|
        called++;
 | 
						|
        // With setTimeout clamping this gives the font ~100ms to load.
 | 
						|
        if(called > 30) {
 | 
						|
          warn('Load test font never loaded.');
 | 
						|
          callback();
 | 
						|
          return;
 | 
						|
        }
 | 
						|
        ctx.font = '30px ' + name;
 | 
						|
        ctx.fillText('.', 0, 20);
 | 
						|
        var imageData = ctx.getImageData(0, 0, 1, 1);
 | 
						|
        if (imageData.data[3] > 0) {
 | 
						|
          callback();
 | 
						|
          return;
 | 
						|
        }
 | 
						|
        setTimeout(isFontReady.bind(null, name, callback));
 | 
						|
      }
 | 
						|
 | 
						|
      var loadTestFontId = 'lt' + Date.now() + this.loadTestFontId++;
 | 
						|
      // Chromium seems to cache fonts based on a hash of the actual font data,
 | 
						|
      // so the font must be modified for each load test else it will appear to
 | 
						|
      // be loaded already.
 | 
						|
      // TODO: This could maybe be made faster by avoiding the btoa of the full
 | 
						|
      // font by splitting it in chunks before hand and padding the font id.
 | 
						|
      var data = this.loadTestFont;
 | 
						|
      var COMMENT_OFFSET = 976; // has to be on 4 byte boundary (for checksum)
 | 
						|
      data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length,
 | 
						|
                          loadTestFontId);
 | 
						|
      // CFF checksum is important for IE, adjusting it
 | 
						|
      var CFF_CHECKSUM_OFFSET = 16;
 | 
						|
      var XXXX_VALUE = 0x58585858; // the "comment" filled with 'X'
 | 
						|
      var checksum = int32(data, CFF_CHECKSUM_OFFSET);
 | 
						|
      for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) {
 | 
						|
        checksum = (checksum - XXXX_VALUE + int32(loadTestFontId, i)) | 0;
 | 
						|
      }
 | 
						|
      if (i < loadTestFontId.length) { // align to 4 bytes boundary
 | 
						|
        checksum = (checksum - XXXX_VALUE +
 | 
						|
                    int32(loadTestFontId + 'XXX', i)) | 0;
 | 
						|
      }
 | 
						|
      data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum));
 | 
						|
 | 
						|
      var url = 'url(data:font/opentype;base64,' + btoa(data) + ');';
 | 
						|
      var rule = '@font-face { font-family:"' + loadTestFontId + '";src:' +
 | 
						|
                 url + '}';
 | 
						|
      FontLoader.insertRule(rule);
 | 
						|
 | 
						|
      var names = [];
 | 
						|
      for (i = 0, ii = fonts.length; i < ii; i++) {
 | 
						|
        names.push(fonts[i].loadedName);
 | 
						|
      }
 | 
						|
      names.push(loadTestFontId);
 | 
						|
 | 
						|
      var div = document.createElement('div');
 | 
						|
      div.setAttribute('style',
 | 
						|
                       'visibility: hidden;' +
 | 
						|
                       'width: 10px; height: 10px;' +
 | 
						|
                       'position: absolute; top: 0px; left: 0px;');
 | 
						|
      for (i = 0, ii = names.length; i < ii; ++i) {
 | 
						|
        var span = document.createElement('span');
 | 
						|
        span.textContent = 'Hi';
 | 
						|
        span.style.fontFamily = names[i];
 | 
						|
        div.appendChild(span);
 | 
						|
      }
 | 
						|
      document.body.appendChild(div);
 | 
						|
 | 
						|
      isFontReady(loadTestFontId, function() {
 | 
						|
        document.body.removeChild(div);
 | 
						|
        request.complete();
 | 
						|
      });
 | 
						|
      /** Hack end */
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
var FontFace = (function FontFaceClosure() {
 | 
						|
  function FontFace(name, file, properties) {
 | 
						|
    this.compiledGlyphs = {};
 | 
						|
    if (arguments.length === 1) {
 | 
						|
      // importing translated data
 | 
						|
      var data = arguments[0];
 | 
						|
      for (var i in data) {
 | 
						|
        this[i] = data[i];
 | 
						|
      }
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  FontFace.prototype = {
 | 
						|
    bindDOM: function FontFace_bindDOM() {
 | 
						|
      if (!this.data)
 | 
						|
        return null;
 | 
						|
 | 
						|
      if (PDFJS.disableFontFace) {
 | 
						|
        this.disableFontFace = true;
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      var data = bytesToString(this.data);
 | 
						|
      var fontName = this.loadedName;
 | 
						|
 | 
						|
      // Add the font-face rule to the document
 | 
						|
      var url = ('url(data:' + this.mimetype + ';base64,' +
 | 
						|
                 window.btoa(data) + ');');
 | 
						|
      var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}';
 | 
						|
 | 
						|
      FontLoader.insertRule(rule);
 | 
						|
 | 
						|
      if (PDFJS.pdfBug && 'FontInspector' in globalScope &&
 | 
						|
          globalScope['FontInspector'].enabled)
 | 
						|
        globalScope['FontInspector'].fontAdded(this, url);
 | 
						|
 | 
						|
      return rule;
 | 
						|
    },
 | 
						|
    getPathGenerator: function (objs, character) {
 | 
						|
      if (!(character in this.compiledGlyphs)) {
 | 
						|
        var js = objs.get(this.loadedName + '_path_' + character);
 | 
						|
        /*jshint -W054 */
 | 
						|
        this.compiledGlyphs[character] = new Function('c', 'size', js);
 | 
						|
      }
 | 
						|
      return this.compiledGlyphs[character];
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return FontFace;
 | 
						|
})();
 | 
						|
 | 
						|
 | 
						|
}).call((typeof window === 'undefined') ? this : window);
 | 
						|
 | 
						|
if (!PDFJS.workerSrc && typeof document !== 'undefined') {
 | 
						|
  // workerSrc is not set -- using last script url to define default location
 | 
						|
  PDFJS.workerSrc = (function () {
 | 
						|
    'use strict';
 | 
						|
    var scriptTagContainer = document.body ||
 | 
						|
                             document.getElementsByTagName('head')[0];
 | 
						|
    var pdfjsSrc = scriptTagContainer.lastChild.src;
 | 
						|
    return pdfjsSrc && pdfjsSrc.replace(/\.js$/i, '.worker.js');
 | 
						|
  })();
 | 
						|
}
 | 
						|
 | 
						|
 |