Backed out changeset ad1af0ef7f50 (bug 960051) for potentially breaking xperf on an already CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Thu, 23 Jan 2014 18:54:09 -0800
changeset 165020 0e17908f897fb4bdc7a566186d8de510a06188db
parent 165019 7a7ba4d11e5ea80e0514e7a2213211294196ebbd
child 165021 1363da0cde92013878ed61502b1a912b2bc89ff6
child 165096 f9a4e354878bc5503def366a4c6275f4967798fd
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
bugs960051
milestone29.0a1
backs outad1af0ef7f50209010eaca64de8ed9a147b5ef9e
Backed out changeset ad1af0ef7f50 (bug 960051) for potentially breaking xperf on an already CLOSED TREE
browser/extensions/pdfjs/README.mozilla
browser/extensions/pdfjs/components/PdfStreamConverter.js
browser/extensions/pdfjs/content/build/pdf.js
browser/extensions/pdfjs/content/build/pdf.worker.js
browser/extensions/pdfjs/content/network.js
browser/extensions/pdfjs/content/web/images/findbarButton-next-rtl.png
browser/extensions/pdfjs/content/web/images/findbarButton-next.png
browser/extensions/pdfjs/content/web/images/findbarButton-previous-rtl.png
browser/extensions/pdfjs/content/web/images/findbarButton-previous.png
browser/extensions/pdfjs/content/web/images/grab.cur
browser/extensions/pdfjs/content/web/images/grabbing.cur
browser/extensions/pdfjs/content/web/images/loading-small.png
browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-documentProperties.png
browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-firstPage.png
browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-handTool.png
browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-lastPage.png
browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw.png
browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCw.png
browser/extensions/pdfjs/content/web/images/shadow.png
browser/extensions/pdfjs/content/web/images/texture.png
browser/extensions/pdfjs/content/web/images/toolbarButton-bookmark.png
browser/extensions/pdfjs/content/web/images/toolbarButton-download.png
browser/extensions/pdfjs/content/web/images/toolbarButton-menuArrows.png
browser/extensions/pdfjs/content/web/images/toolbarButton-openFile.png
browser/extensions/pdfjs/content/web/images/toolbarButton-pageDown-rtl.png
browser/extensions/pdfjs/content/web/images/toolbarButton-pageDown.png
browser/extensions/pdfjs/content/web/images/toolbarButton-pageUp-rtl.png
browser/extensions/pdfjs/content/web/images/toolbarButton-pageUp.png
browser/extensions/pdfjs/content/web/images/toolbarButton-presentationMode.png
browser/extensions/pdfjs/content/web/images/toolbarButton-print.png
browser/extensions/pdfjs/content/web/images/toolbarButton-search.png
browser/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle-rtl.png
browser/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle.png
browser/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle-rtl.png
browser/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle.png
browser/extensions/pdfjs/content/web/images/toolbarButton-viewOutline-rtl.png
browser/extensions/pdfjs/content/web/images/toolbarButton-viewOutline.png
browser/extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail.png
browser/extensions/pdfjs/content/web/images/toolbarButton-zoomOut.png
browser/extensions/pdfjs/content/web/viewer.css
browser/extensions/pdfjs/content/web/viewer.html
browser/extensions/pdfjs/content/web/viewer.js
browser/extensions/pdfjs/extension-files
browser/extensions/pdfjs/icon.png
browser/extensions/pdfjs/icon64.png
browser/locales/en-US/pdfviewer/chrome.properties
browser/locales/en-US/pdfviewer/viewer.properties
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,4 +1,4 @@
 This is the pdf.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 0.8.934
+Current extension version is: 0.8.759
 
--- a/browser/extensions/pdfjs/components/PdfStreamConverter.js
+++ b/browser/extensions/pdfjs/components/PdfStreamConverter.js
@@ -372,29 +372,21 @@ ChromeActions.prototype = {
               !this.telemetryState.streamTypesUsed[streamTypeId]) {
             PdfJsTelemetry.onStreamType(streamTypeId);
             this.telemetryState.streamTypesUsed[streamTypeId] = true;
           }
         }
         break;
     }
   },
-  fallback: function(args, sendResponse) {
-    var featureId = args.featureId;
-    var url = args.url;
-
+  fallback: function(url, sendResponse) {
     var self = this;
     var domWindow = this.domWindow;
     var strings = getLocalizedStrings('chrome.properties');
-    var message;
-    if (featureId === 'forms') {
-      message = getLocalizedString(strings, 'unsupported_feature_forms');
-    } else {
-      message = getLocalizedString(strings, 'unsupported_feature');
-    }
+    var message = getLocalizedString(strings, 'unsupported_feature');
 
     PdfJsTelemetry.onFallback();
 
     var notificationBox = null;
     try {
       // Based on MDN's "Working with windows in chrome code"
       var mainWindow = domWindow
         .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -15,18 +15,18 @@
  * 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.934';
-PDFJS.build = 'c80df60';
+PDFJS.version = '0.8.759';
+PDFJS.build = 'd3b5aa3';
 
 (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
@@ -38,25 +38,27 @@ PDFJS.build = 'c80df60';
  *     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,
-           Promise */
+/* 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,
@@ -71,22 +73,16 @@ var TextRenderingMode = {
 // 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;
 
-PDFJS.VERBOSITY_LEVELS = {
-  errors: 0,
-  warnings: 1,
-  infos: 5
-};
-
 // 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,
@@ -170,94 +166,87 @@ var OPS = PDFJS.OPS = {
   paintJpegXObject: 82,
   paintImageMaskXObject: 83,
   paintImageMaskXObjectGroup: 84,
   paintImageXObject: 85,
   paintInlineImageXObject: 86,
   paintInlineImageXObjectGroup: 87
 };
 
-// A notice for devs. 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.
+// 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 (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) {
-    console.log('Info: ' + msg);
+  if (verbosity >= INFOS) {
+    log('Info: ' + msg);
+    PDFJS.LogManager.notify('info', msg);
   }
 }
 
-// Non-fatal warnings.
+// Non-fatal warnings that should trigger the fallback UI.
 function warn(msg) {
-  if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) {
-    console.log('Warning: ' + 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);
-    console.log.apply(console, logArguments);
+    log.apply(null, logArguments);
     // Join the arguments into a single string for the lines below.
     msg = [].join.call(arguments, ' ');
   } else {
-    console.log('Error: ' + msg);
+    log('Error: ' + msg);
   }
-  console.log(backtrace());
-  UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown);
+  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);
 }
 
-var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = {
-  unknown: 'unknown',
-  forms: 'forms',
-  javaScript: 'javaScript',
-  smask: 'smask',
-  shadingPattern: 'shadingPattern',
-  font: 'font'
-};
-
-var UnsupportedManager = PDFJS.UnsupportedManager =
-  (function UnsupportedManagerClosure() {
-  var listeners = [];
-  return {
-    listen: function (cb) {
-      listeners.push(cb);
-    },
-    notify: function (featureId) {
-      warn('Unsupported feature "' + featureId + '"');
-      for (var i = 0, ii = listeners.length; i < ii; i++) {
-        listeners[i](featureId);
-      }
-    }
-  };
-})();
-
 // 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 (/^[a-z][a-z0-9+\-.]*:/i.test(url))
+  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
@@ -271,23 +260,21 @@ function combineUrl(baseUrl, url) {
   }
 }
 
 // Validates if URL is safe and allowed, e.g. to avoid XSS.
 function isValidUrl(url, allowRelative) {
   if (!url) {
     return false;
   }
-  // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1)
-  // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
-  var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url);
-  if (!protocol) {
+  var colon = url.indexOf(':');
+  if (colon < 0) {
     return allowRelative;
   }
-  protocol = protocol[0].toLowerCase();
+  var protocol = url.substr(0, colon);
   switch (protocol) {
     case 'http':
     case 'https':
     case 'ftp':
     case 'mailto':
       return true;
     default:
       return false;
@@ -297,16 +284,32 @@ 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;
 }
 
@@ -826,76 +829,247 @@ function isPDFFunction(v) {
   else if (isStream(v))
     fnDict = v.dict;
   else
     return false;
   return fnDict.has('FunctionType');
 }
 
 /**
- * Legacy support for PDFJS Promise implementation.
- * TODO remove eventually
- */
-var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
-  return function LegacyPromise() {
-    var resolve, reject;
-    var promise = new Promise(function (resolve_, reject_) {
-      resolve = resolve_;
-      reject = reject_;
-    });
-    promise.resolve = resolve;
-    promise.reject = reject;
-    return promise;
-  };
-})();
-
-/**
- * Polyfill for Promises:
  * 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
  */
-(function PromiseClosure() {
-  if (globalScope.Promise) {
-    // Promises existing in the DOM/Worker, checking presence of all/resolve
-    if (typeof globalScope.Promise.all !== 'function') {
-      globalScope.Promise.all = function (iterable) {
-        var count = 0, results = [], resolve, reject;
-        var promise = new globalScope.Promise(function (resolve_, reject_) {
-          resolve = resolve_;
-          reject = reject_;
-        });
-        iterable.forEach(function (p, i) {
-          count++;
-          p.then(function (result) {
-            results[i] = result;
-            count--;
-            if (count === 0) {
-              resolve(results);
+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;
             }
-          }, reject);
-        });
-        if (count === 0) {
-          resolve(results);
+            warn(msg);
+            this.unhandledRejections.splice(i);
+            i--;
+          }
+        }
+        if (this.unhandledRejections.length) {
+          this.scheduleRejectionCheck();
         }
-        return promise;
-      };
+      }.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);
+      }
     }
-    if (typeof globalScope.Promise.resolve !== 'function') {
-      globalScope.Promise.resolve = function (x) {
-        return new globalScope.Promise(function (resolve) { resolve(x); });
-      };
+    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;
-  }
-  throw new Error('DOM Promise is not present');
+  };
+
+  return Promise;
 })();
 
 var StatTimer = (function StatTimerClosure() {
   function rpad(str, pad, length) {
     while (str.length < length)
       str += pad;
     return str;
   }
@@ -951,27 +1125,28 @@ PDFJS.createBlob = function createBlob(d
     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) {
-    if (!PDFJS.disableCreateObjectURL &&
-        typeof URL !== 'undefined' && URL.createObjectURL) {
-      var blob = PDFJS.createBlob(data, contentType);
-      return URL.createObjectURL(blob);
-    }
-
     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;
@@ -985,53 +1160,56 @@ 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) {
-    console.log.apply(console, data);
+    log.apply(null, data);
   }];
-  ah['console_error'] = [function ahConsoleError(data) {
-    console.error.apply(console, data);
-  }];
-  ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) {
-    UnsupportedManager.notify(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 deferred = {};
-        var promise = new Promise(function (resolve, reject) {
-          deferred.resolve = resolve;
-          deferred.reject = reject;
-        });
-        deferred.promise = promise;
+        var promise = new Promise();
         promise.then(function(resolvedData) {
           comObj.postMessage({
             isReply: true,
             callbackId: data.callbackId,
             data: resolvedData
           });
         });
-        action[0].call(action[1], data.data, deferred);
+        action[0].call(action[1], data.data, promise);
       } else {
         action[0].call(action[1], data.data);
       }
     } else {
       error('Unkown action from worker: ' + data.action);
     }
   };
 }
@@ -1100,119 +1278,75 @@ var ColorSpace = (function ColorSpaceClo
     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. alpha01 indicates how many alpha components
-     * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
-     * array).
+     * will be in [0,255] range.
      */
     getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count,
-                                                   dest, destOffset, bits,
-                                                   alpha01) {
+                                                   dest, destOffset, bits) {
       error('Should not call ColorSpace.getRgbBuffer');
     },
     /**
-     * Determines the number of bytes required to store the result of the
-     * conversion done by the getRgbBuffer method. As in getRgbBuffer,
-     * |alpha01| is either 0 (RGB output) or 1 (RGBA output).
+     * 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,
-                                                         alpha01) {
+    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;
     },
     /**
-     * Fills in the RGB colors in an RGBA buffer.
+     * Creates the output buffer and converts the specified number of the color
+     * values to the RGB colors, similar to the getRgbBuffer.
      */
-    fillRgb: function ColorSpace_fillRgb(rgbaBuf, originalWidth,
-                                         originalHeight, width, height,
-                                         actualHeight, bpc, comps) {
-      var count = originalWidth * originalHeight;
-      var rgbBuf = null;
-      var numComponentColors = 1 << bpc;
-      var needsResizing = originalHeight != height || originalWidth != width;
-
-      if (this.isPassthrough(bpc)) {
-        rgbBuf = comps;
-
-      } else if (this.numComps === 1 && count > numComponentColors &&
+    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') {
-        // 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.
-        //
         // 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 = bpc <= 8 ? new Uint8Array(numComponentColors) :
-                                   new Uint16Array(numComponentColors);
+        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, bpc,
-                          /* alpha01 = */ 0);
-
-        if (!needsResizing) {
-          // Fill in the RGB values directly into |rgbaBuf|.
-          var rgbaPos = 0;
-          for (var i = 0; i < count; ++i) {
-            var key = comps[i] * 3;
-            rgbaBuf[rgbaPos++] = colorMap[key];
-            rgbaBuf[rgbaPos++] = colorMap[key + 1];
-            rgbaBuf[rgbaPos++] = colorMap[key + 2];
-            rgbaPos++;
-          }
-        } else {
-          rgbBuf = new Uint8Array(count * 3);
-          var rgbPos = 0;
-          for (var i = 0; i < count; ++i) {
-            var key = comps[i] * 3;
-            rgbBuf[rgbPos++] = colorMap[key];
-            rgbBuf[rgbPos++] = colorMap[key + 1];
-            rgbBuf[rgbPos++] = colorMap[key + 2];
-          }
+        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];
         }
-      } else {
-        if (!needsResizing) {
-          // Fill in the RGB values directly into |rgbaBuf|.
-          this.getRgbBuffer(comps, 0, width * actualHeight, rgbaBuf, 0, bpc,
-                            /* alpha01 = */ 1);
-        } else {
-          rgbBuf = new Uint8Array(count * 3);
-          this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc,
-                            /* alpha01 = */ 0);
-        }
-      }
-
-      if (rgbBuf) {
-        if (needsResizing) {
-          rgbBuf = PDFImage.resize(rgbBuf, bpc, 3, originalWidth,
-                                   originalHeight, width, height);
-        }
-        var rgbPos = 0;
-        var actualLength = width * actualHeight * 4;
-        for (var i = 0; i < actualLength; i += 4) {
-          rgbaBuf[i] = rgbBuf[rgbPos++];
-          rgbaBuf[i + 1] = rgbBuf[rgbPos++];
-          rgbaBuf[i + 2] = rgbBuf[rgbPos++];
-        }
-      }
+        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
   };
@@ -1434,25 +1568,23 @@ var AlternateCS = (function AlternateCSC
       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,
-                                                    alpha01) {
+                                                    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) &&
-                          alpha01 === 0;
+      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;
@@ -1463,27 +1595,25 @@ var AlternateCS = (function AlternateCSC
             baseBuf[pos++] = tinted[j] * 255;
           }
         } else {
           base.getRgbItem(tinted, 0, baseBuf, pos);
           pos += baseNumComps;
         }
       }
       if (!isPassthrough) {
-        base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01);
-      }
-    },
-    getOutputLength: function AlternateCS_getOutputLength(inputLength,
-                                                          alpha01) {
+        base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8);
+      }
+    },
+    getOutputLength: function AlternateCS_getOutputLength(inputLength) {
       return this.base.getOutputLength(inputLength *
-                                       this.base.numComps / this.numComps,
-                                       alpha01);
+                                       this.base.numComps / this.numComps);
     },
     isPassthrough: ColorSpace.prototype.isPassthrough,
-    fillRgb: ColorSpace.prototype.fillRgb,
+    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
     isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) {
       return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
     },
     usesZeroToOneRange: true
   };
 
   return AlternateCS;
 })();
@@ -1534,35 +1664,33 @@ var IndexedCS = (function IndexedCSClosu
     },
     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, bits,
-                                                  alpha01) {
+                                                  dest, destOffset) {
       var base = this.base;
       var numComps = base.numComps;
-      var outputDelta = base.getOutputLength(numComps, alpha01);
+      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, alpha01);
+        base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8);
         destOffset += outputDelta;
       }
     },
-    getOutputLength: function IndexedCS_getOutputLength(inputLength, alpha01) {
-      return this.base.getOutputLength(inputLength * this.base.numComps,
-                                       alpha01);
+    getOutputLength: function IndexedCS_getOutputLength(inputLength) {
+      return this.base.getOutputLength(inputLength * this.base.numComps);
     },
     isPassthrough: ColorSpace.prototype.isPassthrough,
-    fillRgb: ColorSpace.prototype.fillRgb,
+    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
     isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) {
       // indexed color maps shouldn't be changed
       return true;
     },
     usesZeroToOneRange: true
   };
   return IndexedCS;
 })();
@@ -1582,34 +1710,31 @@ var DeviceGrayCS = (function DeviceGrayC
     },
     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,
-                                                     alpha01) {
+                                                     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;
-        q += alpha01;
-      }
-    },
-    getOutputLength: function DeviceGrayCS_getOutputLength(inputLength,
-                                                           alpha01) {
-      return inputLength * (3 + alpha01);
+      }
+    },
+    getOutputLength: function DeviceGrayCS_getOutputLength(inputLength) {
+      return inputLength * 3;
     },
     isPassthrough: ColorSpace.prototype.isPassthrough,
-    fillRgb: ColorSpace.prototype.fillRgb,
+    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
     isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) {
       return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
     },
     usesZeroToOneRange: true
   };
   return DeviceGrayCS;
 })();
 
@@ -1630,39 +1755,35 @@ var DeviceRgbCS = (function DeviceRgbCSC
       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,
-                                                    alpha01) {
-      if (bits === 8 && alpha01 === 0) {
-        dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset);
+                                                    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 < count; ++i) {
-        dest[q++] = (scale * src[j++]) | 0;
-        dest[q++] = (scale * src[j++]) | 0;
+      for (var i = 0; i < length; ++i) {
         dest[q++] = (scale * src[j++]) | 0;
-        q += alpha01;
-      }
-    },
-    getOutputLength: function DeviceRgbCS_getOutputLength(inputLength,
-                                                          alpha01) {
-      return (inputLength * (3 + alpha01) / 3) | 0;
+      }
+    },
+    getOutputLength: function DeviceRgbCS_getOutputLength(inputLength) {
+      return inputLength;
     },
     isPassthrough: function DeviceRgbCS_isPassthrough(bits) {
       return bits == 8;
     },
-    fillRgb: ColorSpace.prototype.fillRgb,
+    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
     isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) {
       return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
     },
     usesZeroToOneRange: true
   };
   return DeviceRgbCS;
 })();
 
@@ -1722,48 +1843,46 @@ var DeviceCmykCS = (function DeviceCmykC
       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,
-                                                     alpha01) {
+                                                     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 + alpha01;
-      }
-    },
-    getOutputLength: function DeviceCmykCS_getOutputLength(inputLength,
-                                                           alpha01) {
-      return (inputLength / 4 * (3 + alpha01)) | 0;
+        destOffset += 3;
+      }
+    },
+    getOutputLength: function DeviceCmykCS_getOutputLength(inputLength) {
+      return (inputLength >> 2) * 3;
     },
     isPassthrough: ColorSpace.prototype.isPassthrough,
-    fillRgb: ColorSpace.prototype.fillRgb,
+    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 = 1;
-    this.defaultColor = new Float32Array([0]);
+    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.
@@ -1784,80 +1903,77 @@ var CalGrayCS = (function CalGrayCSClosu
     }
 
     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) {
-      warn(this.name + ', BlackPoint: XB: ' + this.XB + ', YB: ' + this.YB +
+      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;
     }
   }
 
-  function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) {
-    // A represents a gray component of a calibrated gray space.
-    // A <---> AG in the spec
-    var A = src[srcOffset] * scale;
-    var AG = Math.pow(A, cs.G);
-
-    // Computes intermediate variables M, L, N as per spec.
-    // Except if other than default BlackPoint values are used.
-    var M = cs.XW * AG;
-    var L = cs.YW * AG;
-    var N = cs.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;
-  }
-
   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) {
-      convertToRgb(this, src, srcOffset, dest, destOffset, 1);
+      // 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,
-                                                  alpha01) {
-      var scale = 1 / ((1 << bits) - 1);
-
+                                                  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) {
-        convertToRgb(this, src, srcOffset, dest, destOffset, scale);
-        srcOffset += 1;
-        destOffset += 3 + alpha01;
-      }
-    },
-    getOutputLength: function CalGrayCS_getOutputLength(inputLength, alpha01) {
-      return inputLength * (3 + alpha01);
+        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,
-    fillRgb: ColorSpace.prototype.fillRgb,
+    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
     isDefaultDecode: function CalGrayCS_isDefaultDecode(decodeMap) {
       return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
     },
     usesZeroToOneRange: true
   };
   return CalGrayCS;
 })();
 
@@ -1975,27 +2091,26 @@ var LabCS = (function LabCSClosure() {
       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,
-                                              alpha01) {
+                                              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 + alpha01;
-      }
-    },
-    getOutputLength: function LabCS_getOutputLength(inputLength, alpha01) {
-      return (inputLength * (3 + alpha01) / 3) | 0;
+        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
@@ -2035,17 +2150,17 @@ var Pattern = (function PatternClosure()
     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:
-        UnsupportedManager.notify(UNSUPPORTED_FEATURES.shadingPattern);
+        TODO('Unsupported shading type: ' + type);
         return new Shadings.Dummy();
     }
   };
   return Pattern;
 })();
 
 var Shadings = {};
 
@@ -2295,17 +2410,17 @@ var TilingPattern = (function TilingPatt
       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;
 
-      info('TilingType: ' + tilingType);
+      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];
@@ -2508,17 +2623,17 @@ var PDFFunction = (function PDFFunctionC
       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
-        info('No support for cubic spline interpolation: ' + order);
+        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);
@@ -3357,39 +3472,16 @@ var Annotation = (function AnnotationClo
     // 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;
-
-      // TODO: implement proper support for annotations with line dash patterns.
-      var dashArray = borderArray[3];
-      if (data.borderWidth > 0 && dashArray && isArray(dashArray)) {
-        var dashArrayLength = dashArray.length;
-        if (dashArrayLength > 0) {
-          // According to the PDF specification: the elements in a dashArray
-          // shall be numbers that are nonnegative and not all equal to zero.
-          var isInvalid = false;
-          var numPositive = 0;
-          for (var i = 0; i < dashArrayLength; i++) {
-            if (!(+dashArray[i] >= 0)) {
-              isInvalid = true;
-              break;
-            } else if (dashArray[i] > 0) {
-              numPositive++;
-            }
-          }
-          if (isInvalid || numPositive === 0) {
-            data.borderWidth = 0;
-          }
-        }
-      }
     }
 
     this.appearance = getDefaultAppearance(dict);
     data.hasAppearance = !!this.appearance;
   }
 
   Annotation.prototype = {
 
@@ -3424,17 +3516,17 @@ var Annotation = (function AnnotationClo
         data &&
         (!data.annotationFlags ||
          !(data.annotationFlags & 0x22)) && // Hidden or NoView
         data.rect                            // rectangle is nessessary
       );
     },
 
     loadResources: function(keys) {
-      var promise = new LegacyPromise();
+      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);
@@ -3443,17 +3535,17 @@ var Annotation = (function AnnotationClo
         });
       }.bind(this));
 
       return promise;
     },
 
     getOperatorList: function Annotation_getToOperatorList(evaluator) {
 
-      var promise = new LegacyPromise();
+      var promise = new Promise();
 
       if (!this.appearance) {
         promise.resolve(new OperatorList());
         return promise;
       }
 
       var data = this.data;
 
@@ -3549,28 +3641,28 @@ var Annotation = (function AnnotationClo
       ref: ref,
     };
 
     var annotation = new Constructor(params);
 
     if (annotation.isViewable()) {
       return annotation;
     } else {
-      warn('unimplemented annotation type: ' + subtype);
+      TODO('unimplemented annotation type: ' + subtype);
     }
   };
 
   Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
       annotations, opList, pdfManager, partialEvaluator) {
 
     function reject(e) {
       annotationsReadyPromise.reject(e);
     }
 
-    var annotationsReadyPromise = new LegacyPromise();
+    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) {
@@ -3641,17 +3733,17 @@ var WidgetAnnotation = (function WidgetA
     }
     data.fullName = fieldName.join('.');
   }
 
   var parent = Annotation.prototype;
   Util.inherit(WidgetAnnotation, Annotation, {
     isViewable: function WidgetAnnotation_isViewable() {
       if (this.data.fieldType === 'Sig') {
-        warn('unimplemented annotation type: Widget signature');
+        TODO('unimplemented annotation type: Widget signature');
         return false;
       }
 
       return parent.isViewable.call(this);
     }
   });
 
   return WidgetAnnotation;
@@ -3722,17 +3814,17 @@ var TextWidgetAnnotation = (function Tex
       return element;
     },
 
     getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) {
       if (this.appearance) {
         return Annotation.prototype.getOperatorList.call(this, evaluator);
       }
 
-      var promise = new LegacyPromise();
+      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) {
@@ -3799,17 +3891,17 @@ var TextAnnotation = (function TextAnnot
     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 LegacyPromise();
+      var promise = new Promise();
       promise.resolve(new OperatorList());
       return promise;
     },
 
     hasHtml: function TextAnnotation_hasHtml() {
       return true;
     },
 
@@ -3899,23 +3991,17 @@ var LinkAnnotation = (function LinkAnnot
 
     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 = action.get('URI');
-        if (isName(url)) {
-          // Some bad PDFs do not put parentheses around relative URLs.
-          url = '/' + url.name;
-        } else {
-          url = addDefaultProtocolToUrl(url);
-        }
+        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');
@@ -3932,17 +4018,17 @@ var LinkAnnotation = (function LinkAnnot
         if (!isValidUrl(url, false)) {
           url = '';
         }
         data.url = url;
         data.dest = action.get('D');
       } else if (linkType === 'Named') {
         data.action = action.get('N').name;
       } else {
-        warn('unrecognized link type: ' + linkType);
+        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;
     }
   }
 
@@ -3989,140 +4075,111 @@ var LinkAnnotation = (function LinkAnnot
 
   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}
+ * @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}
+ * @var {Boolean}
  */
 PDFJS.disableFontFace = PDFJS.disableFontFace === undefined ?
                         false : PDFJS.disableFontFace;
 
 /**
  * Path for image resources, mainly for annotation icons. Include trailing
  * slash.
- * @var {string}
+ * @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}
+ * @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}
+ * @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}
+ * @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}
+ * @var {Boolean}
  */
 PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ?
                          false : PDFJS.disableAutoFetch;
 
 /**
  * Enables special hooks for debugging PDF.js.
- * @var {boolean}
+ * @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;
-
-/**
- * Disables URL.createObjectURL usage.
- * @var {boolean}
- */
-PDFJS.disableCreateObjectURL = PDFJS.disableCreateObjectURL === undefined ?
-                               false : PDFJS.disableCreateObjectURL;
-
-/**
- * Controls the logging level.
- * The constants from PDFJS.VERBOSITY_LEVELS should be used:
- * - errors
- * - warnings [default]
- * - infos
- * @var {number}
- */
-PDFJS.verbosity = PDFJS.verbosity === undefined ?
-                  PDFJS.VERBOSITY_LEVELS.warnings : PDFJS.verbosity;
-
-/**
- * Document initialization / loading parameters object.
- *
- * @typedef {Object} DocumentInitParameters
- * @property {string}     url   - The URL of the PDF.
- * @property {TypedArray} data  - A typed array with PDF data.
- * @property {Object}     httpHeaders - Basic authentication headers.
- * @property {boolean}    withCredentials - Indicates whether or not cross-site
- *   Access-Control requests should be made using credentials such as cookies
- *   or authorization headers. The default is false.
- * @property {string}     password - For decrypting password-protected PDFs.
- * @property {TypedArray} 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.
- */
-
 /**
  * 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|TypedArray|DocumentInitParameters} source Can be a url to
- * where a PDF is located, a typed array (Uint8Array) already populated with
- * data or parameter object.
+ * @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
+ * @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 {@link PDFDocumentProxy}
- *   object.
+ * @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') {
@@ -4142,38 +4199,37 @@ PDFJS.getDocument = function getDocument
   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.LegacyPromise();
-  workerReadyPromise = new PDFJS.LegacyPromise();
+  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.
- * @class
  */
 var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
   function PDFDocumentProxy(pdfInfo, transport) {
     this.pdfInfo = pdfInfo;
     this.transport = transport;
   }
-  PDFDocumentProxy.prototype = /** @lends PDFDocumentProxy.prototype */ {
+  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
@@ -4185,26 +4241,25 @@ var PDFDocumentProxy = (function PDFDocu
     /**
      * @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} pageNumber The page number to get. The first page is 1.
-     * @return {Promise} A promise that is resolved with a {@link PDFPageProxy}
+     * @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(pageNumber) {
-      return this.transport.getPage(pageNumber);
+    getPage: function PDFDocumentProxy_getPage(number) {
+      return this.transport.getPage(number);
     },
     /**
-     * @param {{num: number, gen: number}} ref The page reference. Must have
-     *   the 'num' and 'gen' properties.
+     * @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
@@ -4212,142 +4267,125 @@ var PDFDocumentProxy = (function PDFDocu
      */
     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_getJavaScript() {
-      var promise = new PDFJS.LegacyPromise();
+    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
+     * @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.LegacyPromise();
+      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
+     * @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.LegacyPromise();
+      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.LegacyPromise();
+      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();
     },
-    /**
-     * Cleans up resources allocated by the document, e.g. created @font-face.
-     */
     cleanup: function PDFDocumentProxy_cleanup() {
       this.transport.startCleanup();
     },
-    /**
-     * Destroys current document instance and terminates worker.
-     */
     destroy: function PDFDocumentProxy_destroy() {
       this.transport.destroy();
     }
   };
   return PDFDocumentProxy;
 })();
 
-/**
- * Page text content part.
- *
- * @typedef {Object} BidiText
- * @property {string} str - text content.
- * @property {string} dir - text direction: 'ttb', 'ltr' or 'rtl'.
- * @property {number} x - x position of the text on the page.
- * @property {number} y - y position of the text on the page.
- * @property {number} angle - text rotation.
- * @property {number} size - font size.
- */
-
-/**
- * Proxy to a PDFPage in the worker thread.
- * @class
- */
 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 = /** @lends PDFPageProxy.prototype */ {
+  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
+     * @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
+     * @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
@@ -4356,31 +4394,31 @@ var PDFPageProxy = (function PDFPageProx
      * 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
+     * @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.LegacyPromise();
+      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:
+     * @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
@@ -4397,17 +4435,17 @@ var PDFPageProxy = (function PDFPageProx
       // 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 LegacyPromise();
+        this.displayReadyPromise = new Promise();
         this.operatorList = {
           fnArray: [],
           argsArray: [],
           lastChunk: false
         };
 
         this.stats.time('Page Request');
         this.transport.messageHandler.send('RenderPageRequest', {
@@ -4444,75 +4482,84 @@ var PDFPageProxy = (function PDFPageProx
         }
 
         if (self.cleanupAfterRender) {
           self.pendingDestroy = true;
         }
         self._tryDestroy();
 
         if (error) {
-          renderTask.promise.reject(error);
+          renderTask.reject(error);
         } else {
-          renderTask.promise.resolve();
+          renderTask.resolve();
         }
         stats.timeEnd('Rendering');
         stats.timeEnd('Overall');
       }
 
       return renderTask;
     },
     /**
-     * @return {Promise} That is resolved with the array of {@link BidiText}
-     * objects that represent the page text content.
+     * @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.LegacyPromise();
+      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.
-     * @ignore
      */
     _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.
-     * @ignore
      */
     _startRenderPage: function PDFPageProxy_startRenderPage(transparency) {
       this.displayReadyPromise.resolve(transparency);
     },
     /**
      * For internal use only.
-     * @ignore
      */
     _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;
@@ -4525,20 +4572,18 @@ var PDFPageProxy = (function PDFPageProx
       if (operatorListChunk.lastChunk) {
         this.receivingOperatorList = false;
         this._tryDestroy();
       }
     }
   };
   return PDFPageProxy;
 })();
-
 /**
  * For internal use only.
- * @ignore
  */
 var WorkerTransport = (function WorkerTransportClosure() {
   function WorkerTransport(workerInitializedPromise, workerReadyPromise,
       pdfDataRangeTransport, progressCallback) {
     this.pdfDataRangeTransport = pdfDataRangeTransport;
 
     this.workerReadyPromise = workerReadyPromise;
     this.progressCallback = progressCallback;
@@ -4610,26 +4655,25 @@ var WorkerTransport = (function WorkerTr
     }.bind(this));
   }
   WorkerTransport.prototype = {
     destroy: function WorkerTransport_destroy() {
       this.pageCache = [];
       this.pagePromises = [];
       var self = this;
       this.messageHandler.send('Terminate', null, function () {
-        FontLoader.clear();
         if (self.worker) {
           self.worker.terminate();
         }
       });
     },
 
     loadFakeWorkerFiles: function WorkerTransport_loadFakeWorkerFiles() {
       if (!PDFJS.fakeWorkerFilesLoadedPromise) {
-        PDFJS.fakeWorkerFilesLoadedPromise = new LegacyPromise();
+        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;
@@ -4824,17 +4868,17 @@ var WorkerTransport = (function WorkerTr
       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, deferred) {
+      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;
@@ -4853,80 +4897,74 @@ var WorkerTransport = (function WorkerTr
               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];
             }
           }
-          deferred.resolve({ data: buf, width: width, height: height});
+          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,
-        disableCreateObjectURL: PDFJS.disableCreateObjectURL,
-        verbosity: PDFJS.verbosity
+        disableFontFace: PDFJS.disableFontFace
       });
     },
 
     getData: function WorkerTransport_getData(promise) {
       this.messageHandler.send('GetData', null, function(data) {
         promise.resolve(data);
       });
     },
 
     dataLoaded: function WorkerTransport_dataLoaded() {
-      if (this.dataLoadedPromise) {
-        return this.dataLoadedPromise;
-      }
-      var promise = new PDFJS.LegacyPromise();
+      var promise = new PDFJS.Promise();
       this.messageHandler.send('DataLoaded', null, function(args) {
         promise.resolve(args);
       });
-      this.dataLoadedPromise = promise;
       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.LegacyPromise();
+      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.LegacyPromise();
+      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.LegacyPromise();
+      var promise = new PDFJS.Promise();
       this.messageHandler.send('GetDestinations', null,
         function transportDestinations(destinations) {
           promise.resolve(destinations);
         }
       );
       return promise;
     },
 
@@ -4949,34 +4987,33 @@ var WorkerTransport = (function WorkerTr
 
 })();
 
 /**
  * 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.
- * @ignore
  */
 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 LegacyPromise(),
+        promise: new Promise(objId),
         data: null,
         resolved: false
       };
       this.objs[objId] = obj;
 
       return obj;
     },
 
@@ -5047,50 +5084,39 @@ var PDFObjects = (function PDFObjectsClo
     },
 
     clear: function PDFObjects_clear() {
       this.objs = {};
     }
   };
   return PDFObjects;
 })();
-
-/**
- * Allows controlling of the rendering tasks.
- * @class
+/*
+ * RenderTask is basically a promise but adds a cancel function to terminate it.
  */
 var RenderTask = (function RenderTaskClosure() {
   function RenderTask(internalRenderTask) {
     this.internalRenderTask = internalRenderTask;
-    /**
-     * Promise for rendering task completion.
-     * @type {Promise}
-     */
-    this.promise = new PDFJS.LegacyPromise();
+    Promise.call(this);
   }
 
-  RenderTask.prototype = /** @lends RenderTask.prototype */ {
-    /**
-     * Cancels the rendering task. If the task is currently rendering it will
-     * not be cancelled until graphics pauses with a timeout. The promise that
-     * this object extends will resolved when cancelled.
-     */
-    cancel: function RenderTask_cancel() {
-      this.internalRenderTask.cancel();
-      this.promise.reject(new Error('Rendering is cancelled'));
-    }
+  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;
 })();
 
-/**
- * For internal use only.
- * @ignore
- */
 var InternalRenderTask = (function InternalRenderTaskClosure() {
 
   function InternalRenderTask(callback, params, objs, commonObjs, operatorList,
                               pageNumber) {
     this.callback = callback;
     this.params = params;
     this.objs = objs;
     this.commonObjs = commonObjs;
@@ -5434,96 +5460,84 @@ var CachedCanvases = (function CachedCan
 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]);
-
-  // decodes bit-packed mask data
-  var lineSize = (width + 7) & ~7, data0 = imgData.data;
-  var data = new Uint8Array(lineSize * height), pos = 0, ii;
-  for (i = 0, ii = data0.length; i < ii; i++) {
-    var mask = 128, elem = data0[i];
-    while (mask > 0) {
-      data[pos++] = (elem & mask) ? 0 : 255;
-      mask >>= 1;
-    }
-  }
-
   // 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 count = 0;
-  pos = 0;
-  if (data[pos] !== 0) {
+  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 + 1]) {
+    if (data[pos] !== data[pos + 4]) {
       points[j] = data[pos] ? 2 : 1;
       ++count;
     }
-    pos++;
+    pos += 4;
   }
   if (data[pos] !== 0) {
     points[j] = 2;
     ++count;
   }
+  pos += 4;
   for (i = 1; i < height; i++) {
-    pos = i * lineSize;
     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 + 1] ? 4 : 0) +
-            (data[pos - lineSize + 1] ? 8 : 0);
+      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++;
+      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 * (height - 1);
+  pos -= lineSize;
   j0 = i * width1;
   if (data[pos] !== 0) {
     points[j0] = 8;
     ++count;
   }
   for (j = 1; j < width; j++) {
-    if (data[pos] !== data[pos + 1]) {
+    if (data[pos] !== data[pos + 4]) {
       points[j0 + j] = data[pos] ? 4 : 8;
       ++count;
     }
-    pos++;
+    pos += 4;
   }
   if (data[pos] !== 0) {
     points[j0 + j] = 4;
     ++count;
   }
   if (count > POINT_TO_PROCESS_LIMIT) {
     return null;
   }
@@ -5619,16 +5633,17 @@ var CanvasExtraState = (function CanvasE
     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);
     },
@@ -5670,87 +5685,26 @@ var CanvasGraphics = (function CanvasGra
   }
 
   function putBinaryImageData(ctx, imgData) {
     if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) {
       ctx.putImageData(imgData, 0, 0);
       return;
     }
 
-    // Put the image data to the canvas in chunks, rather than putting the
-    // whole image at once.  This saves JS memory, because the ImageData object
-    // is smaller. It also possibly saves C++ memory within the implementation
-    // of putImageData(). (E.g. in Firefox we make two short-lived copies of
-    // the data passed to putImageData()). |n| shouldn't be too small, however,
-    // because too many putImageData() calls will slow things down.
-
-    var rowsInFullChunks = 16;
-    var fullChunks = (imgData.height / rowsInFullChunks) | 0;
-    var rowsInLastChunk = imgData.height - fullChunks * rowsInFullChunks;
-    var elemsInFullChunks = imgData.width * rowsInFullChunks * 4;
-    var elemsInLastChunk = imgData.width * rowsInLastChunk * 4;
-
-    var chunkImgData = ctx.createImageData(imgData.width, rowsInFullChunks);
-    var srcPos = 0;
-    var src = imgData.data;
-    var dst = chunkImgData.data;
-    var haveSetAndSubarray = 'set' in dst && 'subarray' in src;
-
-    // Do all the full-size chunks.
-    for (var i = 0; i < fullChunks; i++) {
-      if (haveSetAndSubarray) {
-        dst.set(src.subarray(srcPos, srcPos + elemsInFullChunks));
-        srcPos += elemsInFullChunks;
-      } else {
-        for (var j = 0; j < elemsInFullChunks; j++) {
-          chunkImgData.data[j] = imgData.data[srcPos++];
-        }
-      }
-      ctx.putImageData(chunkImgData, 0, i * rowsInFullChunks);
-    }
-
-    // Do the final, partial chunk, if required.
-    if (rowsInLastChunk !== 0) {
-      if (haveSetAndSubarray) {
-        dst.set(src.subarray(srcPos, srcPos + elemsInLastChunk));
-        srcPos += elemsInLastChunk;
-      } else {
-        for (var j = 0; j < elemsInLastChunk; j++) {
-          chunkImgData.data[j] = imgData.data[srcPos++];
-        }
-      }
-      // This (conceptually) puts pixels past the bounds of the canvas.  But
-      // that's ok; any such pixels are ignored.
-      ctx.putImageData(chunkImgData, 0, fullChunks * rowsInFullChunks);
-    }
-  }
-
-  function putBinaryImageMask(ctx, imgData) {
-    var width = imgData.width, height = imgData.height;
-    var tmpImgData = ctx.createImageData(width, height);
+    var tmpImgData = ctx.createImageData(imgData.width, imgData.height);
+
     var data = imgData.data;
     var tmpImgDataPixels = tmpImgData.data;
-    var dataPos = 0;
-
-    // Expand the mask so it can be used by the canvas.  Any required inversion
-    // has already been handled.
-    var tmpPos = 3; // alpha component offset
-    for (var i = 0; i < height; i++) {
-      var mask = 0;
-      for (var j = 0; j < width; j++) {
-        if (!mask) {
-          var elem = data[dataPos++];
-          mask = 128;
-        }
-        if (!(elem & mask)) {
-          tmpImgDataPixels[tmpPos] = 255;
-        }
-        tmpPos += 4;
-        mask >>= 1;
-      }
+    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',
@@ -5823,17 +5777,16 @@ var CanvasGraphics = (function CanvasGra
       }
 
       var executionEndIdx;
       var endTime = Date.now() + EXECUTION_TIME;
 
       var commonObjs = this.commonObjs;
       var objs = this.objs;
       var fnId;
-      var deferred = Promise.resolve();
 
       while (true) {
         if (stepper && i === stepper.nextBreakPoint) {
           stepper.breakIt(i, continueCallback);
           return i;
         }
 
         fnId = fnArray[i];
@@ -5865,17 +5818,17 @@ var CanvasGraphics = (function CanvasGra
         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) {
-          deferred.then(continueCallback);
+          setTimeout(continueCallback, 0);
           return i;
         }
 
         // If the operatorList isn't executed completely yet OR the execution
         // time was short enough, do another execution round.
       }
     },
 
@@ -6269,18 +6222,16 @@ var CanvasGraphics = (function CanvasGra
       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;
-      geometry.ascent = font.ascent;
-      geometry.descent = font.descent;
       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;
@@ -6327,33 +6278,16 @@ var CanvasGraphics = (function CanvasGra
           x: x,
           y: y,
           fontSize: fontSize,
           addToPath: addToPath
         });
       }
     },
 
-    get isFontSubpixelAAEnabled() {
-      // Checks if anti-aliasing is enabled when scaled text is painted.
-      // On Windows GDI scaled fonts looks bad.
-      var ctx = document.createElement('canvas').getContext('2d');
-      ctx.scale(1.5, 1);
-      ctx.fillText('I', 0, 10);
-      var data = ctx.getImageData(0, 0, 10, 10).data;
-      var enabled = false;
-      for (var i = 3; i < data.length; i += 4) {
-        if (data[i] > 0 && data[i] < 255) {
-          enabled = true;
-          break;
-        }
-      }
-      return shadow(this, 'isFontSubpixelAAEnabled', enabled);
-    },
-
     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;
@@ -6458,17 +6392,17 @@ var CanvasGraphics = (function CanvasGra
             if (vertical) {
               scaledX = vx / fontSizeScale;
               scaledY = (x + vy) / fontSizeScale;
             } else {
               scaledX = x / fontSizeScale;
               scaledY = 0;
             }
 
-            if (font.remeasure && width > 0 && this.isFontSubpixelAAEnabled) {
+            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);
@@ -6745,16 +6679,17 @@ var CanvasGraphics = (function CanvasGra
     },
     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) {
@@ -6762,17 +6697,22 @@ var CanvasGraphics = (function CanvasGra
         var height = bbox[3] - bbox[1];
         this.rectangle(bbox[0], bbox[1], width, height);
         this.clip();
         this.endPath();
       }
     },
 
     paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() {
-      this.restore();
+      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
@@ -6789,17 +6729,17 @@ var CanvasGraphics = (function CanvasGra
       // 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) {
-        warn('Knockout groups not supported.');
+        TODO('Support knockout groups.');
       }
 
       var currentTransform = currentCtx.mozCurrentTransform;
       if (group.matrix) {
         currentCtx.transform.apply(currentCtx, group.matrix);
       }
       assert(group.bbox, 'Bounding box is required.');
 
@@ -6939,17 +6879,17 @@ var CanvasGraphics = (function CanvasGra
         glyph.compiled(ctx);
         return;
       }
 
       var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
       var maskCtx = maskCanvas.context;
       maskCtx.save();
 
-      putBinaryImageMask(maskCtx, img);
+      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);
@@ -6966,17 +6906,17 @@ var CanvasGraphics = (function CanvasGra
       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();
 
-        putBinaryImageMask(maskCtx, image);
+        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);
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -15,18 +15,18 @@
  * 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.934';
-PDFJS.build = 'c80df60';
+PDFJS.version = '0.8.759';
+PDFJS.build = 'd3b5aa3';
 
 (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
@@ -38,25 +38,27 @@ PDFJS.build = 'c80df60';
  *     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,
-           Promise */
+/* 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,
@@ -71,22 +73,16 @@ var TextRenderingMode = {
 // 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;
 
-PDFJS.VERBOSITY_LEVELS = {
-  errors: 0,
-  warnings: 1,
-  infos: 5
-};
-
 // 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,
@@ -170,94 +166,87 @@ var OPS = PDFJS.OPS = {
   paintJpegXObject: 82,
   paintImageMaskXObject: 83,
   paintImageMaskXObjectGroup: 84,
   paintImageXObject: 85,
   paintInlineImageXObject: 86,
   paintInlineImageXObjectGroup: 87
 };
 
-// A notice for devs. 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.
+// 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 (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) {
-    console.log('Info: ' + msg);
-  }
-}
-
-// Non-fatal warnings.
+  if (verbosity >= INFOS) {
+    log('Info: ' + msg);
+    PDFJS.LogManager.notify('info', msg);
+  }
+}
+
+// Non-fatal warnings that should trigger the fallback UI.
 function warn(msg) {
-  if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) {
-    console.log('Warning: ' + 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);
-    console.log.apply(console, logArguments);
+    log.apply(null, logArguments);
     // Join the arguments into a single string for the lines below.
     msg = [].join.call(arguments, ' ');
   } else {
-    console.log('Error: ' + msg);
-  }
-  console.log(backtrace());
-  UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown);
+    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);
 }
 
-var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = {
-  unknown: 'unknown',
-  forms: 'forms',
-  javaScript: 'javaScript',
-  smask: 'smask',
-  shadingPattern: 'shadingPattern',
-  font: 'font'
-};
-
-var UnsupportedManager = PDFJS.UnsupportedManager =
-  (function UnsupportedManagerClosure() {
-  var listeners = [];
-  return {
-    listen: function (cb) {
-      listeners.push(cb);
-    },
-    notify: function (featureId) {
-      warn('Unsupported feature "' + featureId + '"');
-      for (var i = 0, ii = listeners.length; i < ii; i++) {
-        listeners[i](featureId);
-      }
-    }
-  };
-})();
-
 // 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 (/^[a-z][a-z0-9+\-.]*:/i.test(url))
+  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
@@ -271,23 +260,21 @@ function combineUrl(baseUrl, url) {
   }
 }
 
 // Validates if URL is safe and allowed, e.g. to avoid XSS.
 function isValidUrl(url, allowRelative) {
   if (!url) {
     return false;
   }
-  // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1)
-  // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
-  var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url);
-  if (!protocol) {
+  var colon = url.indexOf(':');
+  if (colon < 0) {
     return allowRelative;
   }
-  protocol = protocol[0].toLowerCase();
+  var protocol = url.substr(0, colon);
   switch (protocol) {
     case 'http':
     case 'https':
     case 'ftp':
     case 'mailto':
       return true;
     default:
       return false;
@@ -297,16 +284,32 @@ 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;
 }
 
@@ -826,76 +829,247 @@ function isPDFFunction(v) {
   else if (isStream(v))
     fnDict = v.dict;
   else
     return false;
   return fnDict.has('FunctionType');
 }
 
 /**
- * Legacy support for PDFJS Promise implementation.
- * TODO remove eventually
- */
-var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
-  return function LegacyPromise() {
-    var resolve, reject;
-    var promise = new Promise(function (resolve_, reject_) {
-      resolve = resolve_;
-      reject = reject_;
-    });
-    promise.resolve = resolve;
-    promise.reject = reject;
-    return promise;
-  };
-})();
-
-/**
- * Polyfill for Promises:
  * 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
  */
-(function PromiseClosure() {
-  if (globalScope.Promise) {
-    // Promises existing in the DOM/Worker, checking presence of all/resolve
-    if (typeof globalScope.Promise.all !== 'function') {
-      globalScope.Promise.all = function (iterable) {
-        var count = 0, results = [], resolve, reject;
-        var promise = new globalScope.Promise(function (resolve_, reject_) {
-          resolve = resolve_;
-          reject = reject_;
-        });
-        iterable.forEach(function (p, i) {
-          count++;
-          p.then(function (result) {
-            results[i] = result;
-            count--;
-            if (count === 0) {
-              resolve(results);
-            }
-          }, reject);
-        });
-        if (count === 0) {
-          resolve(results);
-        }
-        return promise;
-      };
-    }
-    if (typeof globalScope.Promise.resolve !== 'function') {
-      globalScope.Promise.resolve = function (x) {
-        return new globalScope.Promise(function (resolve) { resolve(x); });
-      };
-    }
-    return;
-  }
-  throw new Error('DOM Promise is not present');
+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;
   }
@@ -951,27 +1125,28 @@ PDFJS.createBlob = function createBlob(d
     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) {
-    if (!PDFJS.disableCreateObjectURL &&
-        typeof URL !== 'undefined' && URL.createObjectURL) {
-      var blob = PDFJS.createBlob(data, contentType);
-      return URL.createObjectURL(blob);
-    }
-
     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;
@@ -985,53 +1160,56 @@ 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) {
-    console.log.apply(console, data);
+    log.apply(null, data);
   }];
-  ah['console_error'] = [function ahConsoleError(data) {
-    console.error.apply(console, data);
-  }];
-  ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) {
-    UnsupportedManager.notify(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 deferred = {};
-        var promise = new Promise(function (resolve, reject) {
-          deferred.resolve = resolve;
-          deferred.reject = reject;
-        });
-        deferred.promise = promise;
+        var promise = new Promise();
         promise.then(function(resolvedData) {
           comObj.postMessage({
             isReply: true,
             callbackId: data.callbackId,
             data: resolvedData
           });
         });
-        action[0].call(action[1], data.data, deferred);
+        action[0].call(action[1], data.data, promise);
       } else {
         action[0].call(action[1], data.data);
       }
     } else {
       error('Unkown action from worker: ' + data.action);
     }
   };
 }
@@ -1073,943 +1251,16 @@ function loadJpegStream(id, imageUrl, ob
   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. alpha01 indicates how many alpha components
-     * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
-     * array).
-     */
-    getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count,
-                                                   dest, destOffset, bits,
-                                                   alpha01) {
-      error('Should not call ColorSpace.getRgbBuffer');
-    },
-    /**
-     * Determines the number of bytes required to store the result of the
-     * conversion done by the getRgbBuffer method. As in getRgbBuffer,
-     * |alpha01| is either 0 (RGB output) or 1 (RGBA output).
-     */
-    getOutputLength: function ColorSpace_getOutputLength(inputLength,
-                                                         alpha01) {
-      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;
-    },
-    /**
-     * Fills in the RGB colors in an RGBA buffer.
-     */
-    fillRgb: function ColorSpace_fillRgb(rgbaBuf, originalWidth,
-                                         originalHeight, width, height,
-                                         actualHeight, bpc, comps) {
-      var count = originalWidth * originalHeight;
-      var rgbBuf = null;
-      var numComponentColors = 1 << bpc;
-      var needsResizing = originalHeight != height || originalWidth != width;
-
-      if (this.isPassthrough(bpc)) {
-        rgbBuf = comps;
-
-      } else if (this.numComps === 1 && count > numComponentColors &&
-          this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') {
-        // 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.
-        //
-        // 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 = bpc <= 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, bpc,
-                          /* alpha01 = */ 0);
-
-        if (!needsResizing) {
-          // Fill in the RGB values directly into |rgbaBuf|.
-          var rgbaPos = 0;
-          for (var i = 0; i < count; ++i) {
-            var key = comps[i] * 3;
-            rgbaBuf[rgbaPos++] = colorMap[key];
-            rgbaBuf[rgbaPos++] = colorMap[key + 1];
-            rgbaBuf[rgbaPos++] = colorMap[key + 2];
-            rgbaPos++;
-          }
-        } else {
-          rgbBuf = new Uint8Array(count * 3);
-          var rgbPos = 0;
-          for (var i = 0; i < count; ++i) {
-            var key = comps[i] * 3;
-            rgbBuf[rgbPos++] = colorMap[key];
-            rgbBuf[rgbPos++] = colorMap[key + 1];
-            rgbBuf[rgbPos++] = colorMap[key + 2];
-          }
-        }
-      } else {
-        if (!needsResizing) {
-          // Fill in the RGB values directly into |rgbaBuf|.
-          this.getRgbBuffer(comps, 0, width * actualHeight, rgbaBuf, 0, bpc,
-                            /* alpha01 = */ 1);
-        } else {
-          rgbBuf = new Uint8Array(count * 3);
-          this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc,
-                            /* alpha01 = */ 0);
-        }
-      }
-
-      if (rgbBuf) {
-        if (needsResizing) {
-          rgbBuf = PDFImage.resize(rgbBuf, bpc, 3, originalWidth,
-                                   originalHeight, width, height);
-        }
-        var rgbPos = 0;
-        var actualLength = width * actualHeight * 4;
-        for (var i = 0; i < actualLength; i += 4) {
-          rgbaBuf[i] = rgbBuf[rgbPos++];
-          rgbaBuf[i + 1] = rgbBuf[rgbPos++];
-          rgbaBuf[i + 2] = rgbBuf[rgbPos++];
-        }
-      }
-    },
-    /**
-     * 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,
-                                                    alpha01) {
-      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) &&
-                          alpha01 === 0;
-      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, alpha01);
-      }
-    },
-    getOutputLength: function AlternateCS_getOutputLength(inputLength,
-                                                          alpha01) {
-      return this.base.getOutputLength(inputLength *
-                                       this.base.numComps / this.numComps,
-                                       alpha01);
-    },
-    isPassthrough: ColorSpace.prototype.isPassthrough,
-    fillRgb: ColorSpace.prototype.fillRgb,
-    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, bits,
-                                                  alpha01) {
-      var base = this.base;
-      var numComps = base.numComps;
-      var outputDelta = base.getOutputLength(numComps, alpha01);
-      var lookup = this.lookup;
-
-      for (var i = 0; i < count; ++i) {
-        var lookupPos = src[srcOffset++] * numComps;
-        base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01);
-        destOffset += outputDelta;
-      }
-    },
-    getOutputLength: function IndexedCS_getOutputLength(inputLength, alpha01) {
-      return this.base.getOutputLength(inputLength * this.base.numComps,
-                                       alpha01);
-    },
-    isPassthrough: ColorSpace.prototype.isPassthrough,
-    fillRgb: ColorSpace.prototype.fillRgb,
-    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,
-                                                     alpha01) {
-      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;
-        q += alpha01;
-      }
-    },
-    getOutputLength: function DeviceGrayCS_getOutputLength(inputLength,
-                                                           alpha01) {
-      return inputLength * (3 + alpha01);
-    },
-    isPassthrough: ColorSpace.prototype.isPassthrough,
-    fillRgb: ColorSpace.prototype.fillRgb,
-    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,
-                                                    alpha01) {
-      if (bits === 8 && alpha01 === 0) {
-        dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset);
-        return;
-      }
-      var scale = 255 / ((1 << bits) - 1);
-      var j = srcOffset, q = destOffset;
-      for (var i = 0; i < count; ++i) {
-        dest[q++] = (scale * src[j++]) | 0;
-        dest[q++] = (scale * src[j++]) | 0;
-        dest[q++] = (scale * src[j++]) | 0;
-        q += alpha01;
-      }
-    },
-    getOutputLength: function DeviceRgbCS_getOutputLength(inputLength,
-                                                          alpha01) {
-      return (inputLength * (3 + alpha01) / 3) | 0;
-    },
-    isPassthrough: function DeviceRgbCS_isPassthrough(bits) {
-      return bits == 8;
-    },
-    fillRgb: ColorSpace.prototype.fillRgb,
-    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,
-                                                     alpha01) {
-      var scale = 1 / ((1 << bits) - 1);
-      for (var i = 0; i < count; i++) {
-        convertToRgb(src, srcOffset, scale, dest, destOffset);
-        srcOffset += 4;
-        destOffset += 3 + alpha01;
-      }
-    },
-    getOutputLength: function DeviceCmykCS_getOutputLength(inputLength,
-                                                           alpha01) {
-      return (inputLength / 4 * (3 + alpha01)) | 0;
-    },
-    isPassthrough: ColorSpace.prototype.isPassthrough,
-    fillRgb: ColorSpace.prototype.fillRgb,
-    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 = 1;
-    this.defaultColor = new Float32Array([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) {
-      warn(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;
-    }
-  }
-
-  function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) {
-    // A represents a gray component of a calibrated gray space.
-    // A <---> AG in the spec
-    var A = src[srcOffset] * scale;
-    var AG = Math.pow(A, cs.G);
-
-    // Computes intermediate variables M, L, N as per spec.
-    // Except if other than default BlackPoint values are used.
-    var M = cs.XW * AG;
-    var L = cs.YW * AG;
-    var N = cs.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;
-  }
-
-  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) {
-      convertToRgb(this, src, srcOffset, dest, destOffset, 1);
-    },
-    getRgbBuffer: function CalGrayCS_getRgbBuffer(src, srcOffset, count,
-                                                  dest, destOffset, bits,
-                                                  alpha01) {
-      var scale = 1 / ((1 << bits) - 1);
-
-      for (var i = 0; i < count; ++i) {
-        convertToRgb(this, src, srcOffset, dest, destOffset, scale);
-        srcOffset += 1;
-        destOffset += 3 + alpha01;
-      }
-    },
-    getOutputLength: function CalGrayCS_getOutputLength(inputLength, alpha01) {
-      return inputLength * (3 + alpha01);
-    },
-    isPassthrough: ColorSpace.prototype.isPassthrough,
-    fillRgb: ColorSpace.prototype.fillRgb,
-    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,
-                                              alpha01) {
-      var maxVal = (1 << bits) - 1;
-      for (var i = 0; i < count; i++) {
-        convertToRgb(this, src, srcOffset, maxVal, dest, destOffset);
-        srcOffset += 3;
-        destOffset += 3 + alpha01;
-      }
-    },
-    getOutputLength: function LabCS_getOutputLength(inputLength, alpha01) {
-      return (inputLength * (3 + alpha01) / 3) | 0;
-    },
-    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() {
@@ -2035,17 +1286,17 @@ var Pattern = (function PatternClosure()
     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:
-        UnsupportedManager.notify(UNSUPPORTED_FEATURES.shadingPattern);
+        TODO('Unsupported shading type: ' + type);
         return new Shadings.Dummy();
     }
   };
   return Pattern;
 })();
 
 var Shadings = {};
 
@@ -2295,17 +1546,17 @@ var TilingPattern = (function TilingPatt
       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;
 
-      info('TilingType: ' + tilingType);
+      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];
@@ -2508,17 +1759,17 @@ var PDFFunction = (function PDFFunctionC
       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
-        info('No support for cubic spline interpolation: ' + order);
+        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);
@@ -3357,39 +2608,16 @@ var Annotation = (function AnnotationClo
     // 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;
-
-      // TODO: implement proper support for annotations with line dash patterns.
-      var dashArray = borderArray[3];
-      if (data.borderWidth > 0 && dashArray && isArray(dashArray)) {
-        var dashArrayLength = dashArray.length;
-        if (dashArrayLength > 0) {
-          // According to the PDF specification: the elements in a dashArray
-          // shall be numbers that are nonnegative and not all equal to zero.
-          var isInvalid = false;
-          var numPositive = 0;
-          for (var i = 0; i < dashArrayLength; i++) {
-            if (!(+dashArray[i] >= 0)) {
-              isInvalid = true;
-              break;
-            } else if (dashArray[i] > 0) {
-              numPositive++;
-            }
-          }
-          if (isInvalid || numPositive === 0) {
-            data.borderWidth = 0;
-          }
-        }
-      }
     }
 
     this.appearance = getDefaultAppearance(dict);
     data.hasAppearance = !!this.appearance;
   }
 
   Annotation.prototype = {
 
@@ -3424,17 +2652,17 @@ var Annotation = (function AnnotationClo
         data &&
         (!data.annotationFlags ||
          !(data.annotationFlags & 0x22)) && // Hidden or NoView
         data.rect                            // rectangle is nessessary
       );
     },
 
     loadResources: function(keys) {
-      var promise = new LegacyPromise();
+      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);
@@ -3443,17 +2671,17 @@ var Annotation = (function AnnotationClo
         });
       }.bind(this));
 
       return promise;
     },
 
     getOperatorList: function Annotation_getToOperatorList(evaluator) {
 
-      var promise = new LegacyPromise();
+      var promise = new Promise();
 
       if (!this.appearance) {
         promise.resolve(new OperatorList());
         return promise;
       }
 
       var data = this.data;
 
@@ -3549,28 +2777,28 @@ var Annotation = (function AnnotationClo
       ref: ref,
     };
 
     var annotation = new Constructor(params);
 
     if (annotation.isViewable()) {
       return annotation;
     } else {
-      warn('unimplemented annotation type: ' + subtype);
+      TODO('unimplemented annotation type: ' + subtype);
     }
   };
 
   Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
       annotations, opList, pdfManager, partialEvaluator) {
 
     function reject(e) {
       annotationsReadyPromise.reject(e);
     }
 
-    var annotationsReadyPromise = new LegacyPromise();
+    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) {
@@ -3641,17 +2869,17 @@ var WidgetAnnotation = (function WidgetA
     }
     data.fullName = fieldName.join('.');
   }
 
   var parent = Annotation.prototype;
   Util.inherit(WidgetAnnotation, Annotation, {
     isViewable: function WidgetAnnotation_isViewable() {
       if (this.data.fieldType === 'Sig') {
-        warn('unimplemented annotation type: Widget signature');
+        TODO('unimplemented annotation type: Widget signature');
         return false;
       }
 
       return parent.isViewable.call(this);
     }
   });
 
   return WidgetAnnotation;
@@ -3722,17 +2950,17 @@ var TextWidgetAnnotation = (function Tex
       return element;
     },
 
     getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) {
       if (this.appearance) {
         return Annotation.prototype.getOperatorList.call(this, evaluator);
       }
 
-      var promise = new LegacyPromise();
+      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) {
@@ -3799,17 +3027,17 @@ var TextAnnotation = (function TextAnnot
     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 LegacyPromise();
+      var promise = new Promise();
       promise.resolve(new OperatorList());
       return promise;
     },
 
     hasHtml: function TextAnnotation_hasHtml() {
       return true;
     },
 
@@ -3899,23 +3127,17 @@ var LinkAnnotation = (function LinkAnnot
 
     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 = action.get('URI');
-        if (isName(url)) {
-          // Some bad PDFs do not put parentheses around relative URLs.
-          url = '/' + url.name;
-        } else {
-          url = addDefaultProtocolToUrl(url);
-        }
+        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');
@@ -3932,17 +3154,17 @@ var LinkAnnotation = (function LinkAnnot
         if (!isValidUrl(url, false)) {
           url = '';
         }
         data.url = url;
         data.dest = action.get('D');
       } else if (linkType === 'Named') {
         data.action = action.get('N').name;
       } else {
-        warn('unrecognized link type: ' + linkType);
+        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;
     }
   }
 
@@ -4205,34 +3427,33 @@ var ChunkedStreamManager = (function Chu
       };
     } else {
 
       var getXhr = function getXhr() {
         return new XMLHttpRequest();
       };
       this.networkManager = new NetworkManager(this.url, {
         getXhr: getXhr,
-        httpHeaders: args.httpHeaders,
-        withCredentials: args.withCredentials
+        httpHeaders: args.httpHeaders
       });
       this.sendRequest = function ChunkedStreamManager_sendRequest(begin, end) {
         this.networkManager.requestRange(begin, end, {
           onDone: this.onReceiveData.bind(this),
           onProgress: this.onProgress.bind(this)
         });
       };
     }
 
     this.currRequestId = 0;
 
     this.chunksNeededByRequest = {};
     this.requestsByChunk = {};
     this.callbacksByRequest = {};
 
-    this.loadedStream = new LegacyPromise();
+    this.loadedStream = new Promise();
     if (args.initialData) {
       this.setInitialData(args.initialData);
     }
   }
 
   ChunkedStreamManager.prototype = {
 
     setInitialData: function ChunkedStreamManager_setInitialData(data) {
@@ -4533,26 +3754,26 @@ var BasePdfManager = (function BasePdfMa
 
   return BasePdfManager;
 })();
 
 var LocalPdfManager = (function LocalPdfManagerClosure() {
   function LocalPdfManager(data, password) {
     var stream = new Stream(data);
     this.pdfModel = new PDFDocument(this, stream, password);
-    this.loadedStream = new LegacyPromise();
+    this.loadedStream = new Promise();
     this.loadedStream.resolve(stream);
   }
 
   LocalPdfManager.prototype = Object.create(BasePdfManager.prototype);
   LocalPdfManager.prototype.constructor = LocalPdfManager;
 
   LocalPdfManager.prototype.ensure =
       function LocalPdfManager_ensure(obj, prop, args) {
-    var promise = new LegacyPromise();
+    var promise = new Promise();
     try {
       var value = obj[prop];
       var result;
       if (typeof(value) === 'function') {
         result = value.apply(obj, args);
       } else {
         result = value;
       }
@@ -4561,17 +3782,17 @@ var LocalPdfManager = (function LocalPdf
       console.log(e.stack);
       promise.reject(e);
     }
     return promise;
   };
 
   LocalPdfManager.prototype.requestRange =
       function LocalPdfManager_requestRange(begin, end) {
-    var promise = new LegacyPromise();
+    var promise = new Promise();
     promise.resolve();
     return promise;
   };
 
   LocalPdfManager.prototype.requestLoadedStream =
       function LocalPdfManager_requestLoadedStream() {
   };
 
@@ -4594,34 +3815,33 @@ var NetworkPdfManager = (function Networ
 
   function NetworkPdfManager(args, msgHandler) {
 
     this.msgHandler = msgHandler;
 
     var params = {
       msgHandler: msgHandler,
       httpHeaders: args.httpHeaders,
-      withCredentials: args.withCredentials,
       chunkedViewerLoading: args.chunkedViewerLoading,
       disableAutoFetch: args.disableAutoFetch,
       initialData: args.initialData
     };
     this.streamManager = new ChunkedStreamManager(args.length, CHUNK_SIZE,
                                                   args.url, params);
 
     this.pdfModel = new PDFDocument(this, this.streamManager.getStream(),
                                     args.password);
   }
 
   NetworkPdfManager.prototype = Object.create(BasePdfManager.prototype);
   NetworkPdfManager.prototype.constructor = NetworkPdfManager;
 
   NetworkPdfManager.prototype.ensure =
       function NetworkPdfManager_ensure(obj, prop, args) {
-    var promise = new LegacyPromise();
+    var promise = new Promise();
     this.ensureHelper(promise, obj, prop, args);
     return promise;
   };
 
   NetworkPdfManager.prototype.ensureHelper =
       function NetworkPdfManager_ensureHelper(promise, obj, prop, args) {
     try {
       var result;
@@ -4642,17 +3862,17 @@ var NetworkPdfManager = (function Networ
       this.streamManager.requestRange(e.begin, e.end, function() {
         this.ensureHelper(promise, obj, prop, args);
       }.bind(this));
     }
   };
 
   NetworkPdfManager.prototype.requestRange =
       function NetworkPdfManager_requestRange(begin, end) {
-    var promise = new LegacyPromise();
+    var promise = new Promise();
     this.streamManager.requestRange(begin, end, function() {
       promise.resolve();
     });
     return promise;
   };
 
   NetworkPdfManager.prototype.requestLoadedStream =
       function NetworkPdfManager_requestLoadedStream() {
@@ -4769,36 +3989,36 @@ var Page = (function PageClosure() {
       }
       return stream;
     },
     loadResources: function(keys) {
       if (!this.resourcesPromise) {
         // TODO: add async inheritPageProp and remove this.
         this.resourcesPromise = this.pdfManager.ensure(this, 'resources');
       }
-      var promise = new LegacyPromise();
+      var promise = new Promise();
       this.resourcesPromise.then(function resourceSuccess() {
         var objectLoader = new ObjectLoader(this.resources.map,
                                             keys,
                                             this.xref);
         objectLoader.load().then(function objectLoaderSuccess() {
           promise.resolve();
         });
       }.bind(this));
       return promise;
     },
     getOperatorList: function Page_getOperatorList(handler) {
       var self = this;
-      var promise = new LegacyPromise();
+      var promise = new Promise();
 
       function reject(e) {
         promise.reject(e);
       }
 
-      var pageListPromise = new LegacyPromise();
+      var pageListPromise = new Promise();
 
       var pdfManager = this.pdfManager;
       var contentStreamPromise = pdfManager.ensure(this, 'getContentStream',
                                                    []);
       var resourcesPromise = this.loadResources([
         'ExtGState',
         'ColorSpace',
         'Pattern',
@@ -4854,17 +4074,17 @@ var Page = (function PageClosure() {
     extractTextContent: function Page_extractTextContent() {
       var handler = {
         on: function nullHandlerOn() {},
         send: function nullHandlerSend() {}
       };
 
       var self = this;
 
-      var textContentPromise = new LegacyPromise();
+      var textContentPromise = new Promise();
 
       var pdfManager = this.pdfManager;
       var contentStreamPromise = pdfManager.ensure(this, 'getContentStream',
                                                    []);
 
       var resourcesPromise = this.loadResources([
         'ExtGState',
         'XObject',
@@ -5229,34 +4449,34 @@ var Dict = (function DictClosure() {
       var value;
       var promise;
       var xref = this.xref;
       if (typeof (value = this.map[key1]) !== undefined || key1 in this.map ||
           typeof key2 === undefined) {
         if (xref) {
           return xref.fetchIfRefAsync(value);
         }
-        promise = new LegacyPromise();
+        promise = new Promise();
         promise.resolve(value);
         return promise;
       }
       if (typeof (value = this.map[key2]) !== undefined || key2 in this.map ||
           typeof key3 === undefined) {
         if (xref) {
           return xref.fetchIfRefAsync(value);
         }
-        promise = new LegacyPromise();
+        promise = new Promise();
         promise.resolve(value);
         return promise;
       }
       value = this.map[key3] || null;
       if (xref) {
         return xref.fetchIfRefAsync(value);
       }
-      promise = new LegacyPromise();
+      promise = new Promise();
       promise.resolve(value);
       return promise;
     },
 
     // no dereferencing
     getRaw: function Dict_getRaw(key) {
       return this.map[key];
     },
@@ -5566,17 +4786,17 @@ var Catalog = (function CatalogClosure()
                             this.fontCache);
           }.bind(this)
         );
       }
       return this.pagePromises[pageIndex];
     },
 
     getPageDict: function Catalog_getPageDict(pageIndex) {
-      var promise = new LegacyPromise();
+      var promise = new Promise();
       var nodesToVisit = [this.catDict.getRaw('Pages')];
       var currentPageIndex = 0;
       var xref = this.xref;
 
       function next() {
         while (nodesToVisit.length) {
           var currentNode = nodesToVisit.pop();
 
@@ -6131,17 +5351,17 @@ var XRef = (function XRefClosure() {
           this.startXRefQueue.shift();
         }
 
         return this.topDict;
       } catch (e) {
         if (e instanceof MissingDataException) {
           throw e;
         }
-        info('(while reading XRef): ' + e);
+        log('(while reading XRef): ' + e);
       }
 
       if (recoveryMode)
         return;
       throw new XRefParseException();
     },
 
     getEntry: function XRef_getEntry(i) {
@@ -6252,24 +5472,24 @@ var XRef = (function XRefClosure() {
       e = entries[e.gen];
       if (e === undefined) {
         error('bad XRef entry for compressed object');
       }
       return e;
     },
     fetchIfRefAsync: function XRef_fetchIfRefAsync(obj) {
       if (!isRef(obj)) {
-        var promise = new LegacyPromise();
+        var promise = new Promise();
         promise.resolve(obj);
         return promise;
       }
       return this.fetchAsync(obj);
     },
     fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) {
-      var promise = new LegacyPromise();
+      var promise = new Promise();
       var tryFetch = function (promise) {
         try {
           promise.resolve(this.fetch(ref, suppressEncryption));
         } catch (e) {
           if (e instanceof MissingDataException) {
             this.stream.manager.requestRange(e.begin, e.end, tryFetch);
             return;
           }
@@ -6386,17 +5606,17 @@ var ObjectLoader = (function() {
     this.xref = xref;
     this.refSet = null;
   }
 
   ObjectLoader.prototype = {
 
     load: function ObjectLoader_load() {
       var keys = this.keys;
-      this.promise = new LegacyPromise();
+      this.promise = new Promise();
       // Don't walk the graph if all the data is already loaded.
       if (!(this.xref.stream instanceof ChunkedStream) ||
           this.xref.stream.getMissingChunks().length === 0) {
         this.promise.resolve();
         return this.promise;
       }
 
       this.refSet = new RefSet();
@@ -13513,16 +12733,880 @@ var CIDToUnicodeMaps = {
     {f: 50, c: 18760}, {f: 2, c: 18811}, {f: 4, c: 18814}, 18820,
     {f: 20, c: 18823}, {f: 3, c: 18844}, {f: 22, c: 18848}, {f: 703, c: 18872},
     {f: 39, c: 19576}, {f: 111, c: 19620}, {f: 148, c: 19738},
     {f: 7, c: 19887}]
 };
 
 
 
+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 ARCFourCipher = (function ARCFourCipherClosure() {
   function ARCFourCipher(key) {
     this.a = 0;
     this.b = 0;
     var s = new Uint8Array(256);
     var i, j = 0, tmp, keyLength = key.length;
     for (i = 0; i < 256; ++i)
       s[i] = i;
@@ -14184,16 +14268,129 @@ var PartialEvaluator = (function Partial
     this.xref = xref;
     this.handler = handler;
     this.pageIndex = pageIndex;
     this.uniquePrefix = uniquePrefix;
     this.idCounters = idCounters;
     this.fontCache = fontCache;
   }
 
+  // Specifies properties for each command
+  //
+  // If variableArgs === true: [0, `numArgs`] expected
+  // If variableArgs === false: exactly `numArgs` expected
+  var OP_MAP = {
+    // Graphic state
+    w: { id: OPS.setLineWidth, numArgs: 1, variableArgs: false },
+    J: { id: OPS.setLineCap, numArgs: 1, variableArgs: false },
+    j: { id: OPS.setLineJoin, numArgs: 1, variableArgs: false },
+    M: { id: OPS.setMiterLimit, numArgs: 1, variableArgs: false },
+    d: { id: OPS.setDash, numArgs: 2, variableArgs: false },
+    ri: { id: OPS.setRenderingIntent, numArgs: 1, variableArgs: false },
+    i: { id: OPS.setFlatness, numArgs: 1, variableArgs: false },
+    gs: { id: OPS.setGState, numArgs: 1, variableArgs: false },
+    q: { id: OPS.save, numArgs: 0, variableArgs: false },
+    Q: { id: OPS.restore, numArgs: 0, variableArgs: false },
+    cm: { id: OPS.transform, numArgs: 6, variableArgs: false },
+
+    // Path
+    m: { id: OPS.moveTo, numArgs: 2, variableArgs: false },
+    l: { id: OPS.lineTo, numArgs: 2, variableArgs: false },
+    c: { id: OPS.curveTo, numArgs: 6, variableArgs: false },
+    v: { id: OPS.curveTo2, numArgs: 4, variableArgs: false },
+    y: { id: OPS.curveTo3, numArgs: 4, variableArgs: false },
+    h: { id: OPS.closePath, numArgs: 0, variableArgs: false },
+    re: { id: OPS.rectangle, numArgs: 4, variableArgs: false },
+    S: { id: OPS.stroke, numArgs: 0, variableArgs: false },
+    s: { id: OPS.closeStroke, numArgs: 0, variableArgs: false },
+    f: { id: OPS.fill, numArgs: 0, variableArgs: false },
+    F: { id: OPS.fill, numArgs: 0, variableArgs: false },
+    'f*': { id: OPS.eoFill, numArgs: 0, variableArgs: false },
+    B: { id: OPS.fillStroke, numArgs: 0, variableArgs: false },
+    'B*': { id: OPS.eoFillStroke, numArgs: 0, variableArgs: false },
+    b: { id: OPS.closeFillStroke, numArgs: 0, variableArgs: false },
+    'b*': { id: OPS.closeEOFillStroke, numArgs: 0, variableArgs: false },
+    n: { id: OPS.endPath, numArgs: 0, variableArgs: false },
+
+    // Clipping
+    W: { id: OPS.clip, numArgs: 0, variableArgs: false },
+    'W*': { id: OPS.eoClip, numArgs: 0, variableArgs: false },
+
+    // Text
+    BT: { id: OPS.beginText, numArgs: 0, variableArgs: false },
+    ET: { id: OPS.endText, numArgs: 0, variableArgs: false },
+    Tc: { id: OPS.setCharSpacing, numArgs: 1, variableArgs: false },
+    Tw: { id: OPS.setWordSpacing, numArgs: 1, variableArgs: false },
+    Tz: { id: OPS.setHScale, numArgs: 1, variableArgs: false },
+    TL: { id: OPS.setLeading, numArgs: 1, variableArgs: false },
+    Tf: { id: OPS.setFont, numArgs: 2, variableArgs: false },
+    Tr: { id: OPS.setTextRenderingMode, numArgs: 1, variableArgs: false },
+    Ts: { id: OPS.setTextRise, numArgs: 1, variableArgs: false },
+    Td: { id: OPS.moveText, numArgs: 2, variableArgs: false },
+    TD: { id: OPS.setLeadingMoveText, numArgs: 2, variableArgs: false },
+    Tm: { id: OPS.setTextMatrix, numArgs: 6, variableArgs: false },
+    'T*': { id: OPS.nextLine, numArgs: 0, variableArgs: false },
+    Tj: { id: OPS.showText, numArgs: 1, variableArgs: false },
+    TJ: { id: OPS.showSpacedText, numArgs: 1, variableArgs: false },
+    '\'': { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false },
+    '"': { id: OPS.nextLineSetSpacingShowText, numArgs: 3,
+      variableArgs: false },
+
+    // Type3 fonts
+    d0: { id: OPS.setCharWidth, numArgs: 2, variableArgs: false },
+    d1: { id: OPS.setCharWidthAndBounds, numArgs: 6, variableArgs: false },
+
+    // Color
+    CS: { id: OPS.setStrokeColorSpace, numArgs: 1, variableArgs: false },
+    cs: { id: OPS.setFillColorSpace, numArgs: 1, variableArgs: false },
+    SC: { id: OPS.setStrokeColor, numArgs: 4, variableArgs: true },
+    SCN: { id: OPS.setStrokeColorN, numArgs: 33, variableArgs: true },
+    sc: { id: OPS.setFillColor, numArgs: 4, variableArgs: true },
+    scn: { id: OPS.setFillColorN, numArgs: 33, variableArgs: true },
+    G: { id: OPS.setStrokeGray, numArgs: 1, variableArgs: false },
+    g: { id: OPS.setFillGray, numArgs: 1, variableArgs: false },
+    RG: { id: OPS.setStrokeRGBColor, numArgs: 3, variableArgs: false },
+    rg: { id: OPS.setFillRGBColor, numArgs: 3, variableArgs: false },
+    K: { id: OPS.setStrokeCMYKColor, numArgs: 4, variableArgs: false },
+    k: { id: OPS.setFillCMYKColor, numArgs: 4, variableArgs: false },
+
+    // Shading
+    sh: { id: OPS.shadingFill, numArgs: 1, variableArgs: false },
+
+    // Images
+    BI: { id: OPS.beginInlineImage, numArgs: 0, variableArgs: false },
+    ID: { id: OPS.beginImageData, numArgs: 0, variableArgs: false },
+    EI: { id: OPS.endInlineImage, numArgs: 1, variableArgs: false },
+
+    // XObjects
+    Do: { id: OPS.paintXObject, numArgs: 1, variableArgs: false },
+    MP: { id: OPS.markPoint, numArgs: 1, variableArgs: false },
+    DP: { id: OPS.markPointProps, numArgs: 2, variableArgs: false },
+    BMC: { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false },
+    BDC: { id: OPS.beginMarkedContentProps, numArgs: 2,
+      variableArgs: false },
+    EMC: { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false },
+
+    // Compatibility
+    BX: { id: OPS.beginCompat, numArgs: 0, variableArgs: false },
+    EX: { id: OPS.endCompat, numArgs: 0, variableArgs: false },
+
+    // (reserved partial commands for the lexer)
+    BM: null,
+    BD: null,
+    'true': null,
+    fa: null,
+    fal: null,
+    fals: null,
+    'false': null,
+    nu: null,
+    nul: null,
+    'null': null
+  };
+
   var TILING_PATTERN = 1, SHADING_PATTERN = 2;
 
   PartialEvaluator.prototype = {
     hasBlendModes: function PartialEvaluator_hasBlendModes(resources) {
       if (!isDict(resources)) {
         return false;
       }
 
@@ -14229,18 +14426,17 @@ var PartialEvaluator = (function Partial
           }
         }
       }
       return false;
     },
 
     buildFormXObject: function PartialEvaluator_buildFormXObject(resources,
                                                                  xobj, smask,
-                                                                 operatorList,
-                                                                 state) {
+                                                                 operatorList) {
       var self = this;
 
       var matrix = xobj.dict.get('Matrix');
       var bbox = xobj.dict.get('BBox');
       var group = xobj.dict.get('Group');
       if (group) {
         var groupOptions = {
           matrix: matrix,
@@ -14258,17 +14454,17 @@ var PartialEvaluator = (function Partial
           // RGB I'm not sure we need it.
         }
         operatorList.addOp(OPS.beginGroup, [groupOptions]);
       }
 
       operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]);
 
       this.getOperatorList(xobj, xobj.dict.get('Resources') || resources,
-                           operatorList, state);
+                           operatorList);
       operatorList.addOp(OPS.paintFormXObjectEnd, []);
 
       if (group) {
         operatorList.addOp(OPS.endGroup, [groupOptions]);
       }
     },
 
     buildPaintImageXObject: function PartialEvaluator_buildPaintImageXObject(
@@ -14294,17 +14490,18 @@ var PartialEvaluator = (function Partial
         var width = dict.get('Width', 'W');
         var height = dict.get('Height', 'H');
         var bitStrideLength = (width + 7) >> 3;
         var imgArray = image.getBytes(bitStrideLength * height);
         var decode = dict.get('Decode', 'D');
         var inverseDecode = !!decode && decode[0] > 0;
 
         operatorList.addOp(OPS.paintImageMaskXObject,
-          [PDFImage.createMask(imgArray, width, height, inverseDecode)]
+          [PDFImage.createMask(imgArray, width, height,
+                                            inverseDecode)]
         );
         return;
       }
 
       var softMask = dict.get('SMask', 'SM') || false;
       var mask = dict.get('Mask') || false;
 
       var SMALL_IMAGE_DIMENSIONS = 200;
@@ -14439,19 +14636,19 @@ var PartialEvaluator = (function Partial
                                                 operatorList);
             operatorList.addDependency(loadedName);
             gStateObj.push([key, [loadedName, value[1]]]);
             break;
           case 'BM':
             gStateObj.push([key, value]);
             break;
           case 'SMask':
-            // We support the default so don't trigger a warning bar.
+            // We support the default so don't trigger the TODO.
             if (!isName(value) || value.name != 'None')
-              UnsupportedManager.notify(UNSUPPORTED_FEATURES.smask);
+              TODO('graphic state operator ' + key);
             break;
           // Only generate info log messages for the following since
           // they are unlikey to have a big impact on the rendering.
           case 'OP':
           case 'op':
           case 'OPM':
           case 'BG':
           case 'BG2':
@@ -14507,41 +14704,32 @@ var PartialEvaluator = (function Partial
           warn('fontRes not available');
           return errorFont();
         }
       }
       if (this.fontCache.has(fontRef)) {
         return this.fontCache.get(fontRef);
       }
 
+
       font = xref.fetchIfRef(fontRef);
       if (!isDict(font)) {
         return errorFont();
       }
-      // Workaround for bad PDF generators that doesn't reference fonts
-      // properly, i.e. by not using an object identifier.
-      // Check if the fontRef is a Dict (as opposed to a standard object),
-      // in which case we don't cache the font and instead reference it by
-      // fontName in font.loadedName below.
-      var fontRefIsDict = isDict(fontRef);
-      if (!fontRefIsDict) {
-        this.fontCache.put(fontRef, font);
-      }
+      this.fontCache.put(fontRef, font);
 
       // keep track of each font we translated so the caller can
       // load them asynchronously before calling display on a page
-      font.loadedName = 'g_font_' + (fontRefIsDict ?
-        fontName.replace(/\W/g, '') : (fontRef.num + '_' + fontRef.gen));
+      font.loadedName = 'g_font_' + fontRef.num + '_' + fontRef.gen;
 
       if (!font.translated) {
         var translated;
         try {
           translated = this.translateFont(font, xref);
         } catch (e) {
-          UnsupportedManager.notify(UNSUPPORTED_FEATURES.font);
           translated = new ErrorFont(e instanceof Error ? e.message : e);
         }
         font.translated = translated;
       }
 
       if (font.translated.loadCharProcs) {
         var charProcs = font.get('CharProcs').getAll();
         var fontResources = font.get('Resources') || resources;
@@ -14564,38 +14752,75 @@ var PartialEvaluator = (function Partial
       } else {
         font.loaded = true;
       }
       return font;
     },
 
     getOperatorList: function PartialEvaluator_getOperatorList(stream,
                                                                resources,
-                                                               operatorList,
-                                                               evaluatorState) {
+                                                               operatorList) {
 
       var self = this;
       var xref = this.xref;
       var handler = this.handler;
 
       operatorList = operatorList || new OperatorList();
 
       resources = resources || new Dict();
       var xobjs = resources.get('XObject') || new Dict();
       var patterns = resources.get('Pattern') || new Dict();
-      var preprocessor = new EvaluatorPreprocessor(stream, xref);
-      if (evaluatorState) {
-        preprocessor.setState(evaluatorState);
-      }
-
-      var promise = new LegacyPromise();
-      var operation;
-      while ((operation = preprocessor.read())) {
-          var args = operation.args;
-          var fn = operation.fn;
+      // TODO(mduan): pass array of knownCommands rather than OP_MAP
+      // dictionary
+      var parser = new Parser(new Lexer(stream, OP_MAP), false, xref);
+
+      var promise = new Promise();
+      var args = [];
+      while (true) {
+
+        var obj = parser.getObj();
+
+        if (isEOF(obj)) {
+          break;
+        }
+
+        if (isCmd(obj)) {
+          var cmd = obj.cmd;
+
+          // Check that the command is valid
+          var opSpec = OP_MAP[cmd];
+          if (!opSpec) {
+            warn('Unknown command "' + cmd + '"');
+            continue;
+          }
+
+          var fn = opSpec.id;
+
+          // Validate the number of arguments for the command
+          if (opSpec.variableArgs) {
+            if (args.length > opSpec.numArgs) {
+              info('Command ' + fn + ': expected [0,' + opSpec.numArgs +
+                  '] args, but received ' + args.length + ' args');
+            }
+          } else {
+            if (args.length < opSpec.numArgs) {
+              // If we receive too few args, it's not possible to possible
+              // to execute the command, so skip the command
+              info('Command ' + fn + ': because expected ' +
+                   opSpec.numArgs + ' args, but received ' + args.length +
+                   ' args; skipping');
+              args = [];
+              continue;
+            } else if (args.length > opSpec.numArgs) {
+              info('Command ' + fn + ': expected ' + opSpec.numArgs +
+                  ' args, but received ' + args.length + ' args');
+            }
+          }
+
+          // TODO figure out how to type-check vararg functions
 
           switch (fn) {
             case OPS.setStrokeColorN:
             case OPS.setFillColorN:
               if (args[args.length - 1].code) {
                 break;
               }
               // compile tiling patterns
@@ -14637,18 +14862,17 @@ var PartialEvaluator = (function Partial
 
                 var type = xobj.dict.get('Subtype');
                 assertWellFormed(
                   isName(type),
                   'XObject should have a Name subtype'
                 );
 
                 if ('Form' == type.name) {
-                  self.buildFormXObject(resources, xobj, null, operatorList,
-                                        preprocessor.getState());
+                  self.buildFormXObject(resources, xobj, null, operatorList);
                   args = [];
                   continue;
                 } else if ('Image' == type.name) {
                   self.buildPaintImageXObject(resources, xobj, false,
                                               operatorList);
                   args = [];
                   continue;
                 } else {
@@ -14729,96 +14953,117 @@ var PartialEvaluator = (function Partial
 
               var gState = extGState.get(dictName.name);
               self.setGState(resources, gState, operatorList);
               args = [];
               continue;
           } // switch
 
           operatorList.addOp(fn, args);
-      }
-
-      // some pdf don't close all restores inside object/form
-      // closing those for them
-      for (var i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) {
-        operatorList.addOp(OPS.restore, []);
+          args = [];
+          parser.saveState();
+        } else if (obj !== null && obj !== undefined) {
+          args.push(obj instanceof Dict ? obj.getAll() : obj);
+          assertWellFormed(args.length <= 33, 'Too many arguments');
+        }
       }
 
       return operatorList;
     },
 
     getTextContent: function PartialEvaluator_getTextContent(
-                                                 stream, resources, textState) {
-
-      textState = textState || new TextState();
-
-      var bidiTexts = [];
+                                                    stream, resources, state) {
+
+      var bidiTexts;
       var SPACE_FACTOR = 0.35;
       var MULTI_SPACE_FACTOR = 1.5;
+      var textState;
+
+      if (!state) {
+        textState = new TextState();
+        bidiTexts = [];
+        state = {
+          textState: textState,
+          bidiTexts: bidiTexts
+        };
+      } else {
+        bidiTexts = state.bidiTexts;
+        textState = state.textState;
+      }
 
       var self = this;
       var xref = this.xref;
 
       function handleSetFont(fontName, fontRef) {
         return self.loadFont(fontName, fontRef, xref, resources, null);
       }
 
       resources = xref.fetchIfRef(resources) || new Dict();
       // The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd.
       var xobjs = null;
 
-      var preprocessor = new EvaluatorPreprocessor(stream, xref);
+      var parser = new Parser(new Lexer(stream), false);
       var res = resources;
+      var args = [], obj;
 
       var chunk = '';
       var font = null;
       var charSpace = 0, wordSpace = 0;
-      var operation;
-      while ((operation = preprocessor.read())) {
-          var fn = operation.fn;
-          var args = operation.args;
-          switch (fn) {
+      while (!isEOF(obj = parser.getObj())) {
+        if (isCmd(obj)) {
+          var cmd = obj.cmd;
+          switch (cmd) {
             // TODO: Add support for SAVE/RESTORE and XFORM here.
-            case OPS.setFont:
+            case 'Tf':
               font = handleSetFont(args[0].name).translated;
               textState.fontSize = args[1];
               break;
-            case OPS.setTextRise:
+            case 'Ts':
               textState.textRise = args[0];
               break;
-            case OPS.setHScale:
+            case 'Tz':
               textState.textHScale = args[0] / 100;
               break;
-            case OPS.setLeading:
+            case 'TL':
               textState.leading = args[0];
               break;
-            case OPS.moveText:
+            case 'Td':
               textState.translateTextMatrix(args[0], args[1]);
               break;
-            case OPS.setLeadingMoveText:
+            case 'TD':
               textState.leading = -args[1];
               textState.translateTextMatrix(args[0], args[1]);
               break;
-            case OPS.nextLine:
+            case 'T*':
               textState.translateTextMatrix(0, -textState.leading);
               break;
-            case OPS.setTextMatrix:
+            case 'Tm':
               textState.setTextMatrix(args[0], args[1],
                                        args[2], args[3], args[4], args[5]);
               break;
-            case OPS.setCharSpacing:
+            case 'Tc':
               charSpace = args[0];
               break;
-            case OPS.setWordSpacing:
+            case 'Tw':
               wordSpace = args[0];
               break;
-            case OPS.beginText:
+            case 'q':
+              textState.push();
+              break;
+            case 'Q':
+              textState.pop();
+              break;
+            case 'BT':
               textState.initialiseTextObj();
               break;
-            case OPS.showSpacedText:
+            case 'cm':
+              textState.transformCTM(args[0], args[1], args[2],
+                                args[3], args[4], args[5]);
+              break;
+            case 'TJ':
               var items = args[0];
               for (var j = 0, jj = items.length; j < jj; j++) {
                 if (typeof items[j] === 'string') {
                   chunk += fontCharsToUnicode(items[j], font);
                 } else if (items[j] < 0 && font.spaceWidth > 0) {
                   var fakeSpaces = -items[j] / font.spaceWidth;
                   if (fakeSpaces > MULTI_SPACE_FACTOR) {
                     fakeSpaces = Math.round(fakeSpaces);
@@ -14826,30 +15071,30 @@ var PartialEvaluator = (function Partial
                       chunk += ' ';
                     }
                   } else if (fakeSpaces > SPACE_FACTOR) {
                     chunk += ' ';
                   }
                 }
               }
               break;
-            case OPS.showText:
+            case 'Tj':
               chunk += fontCharsToUnicode(args[0], font);
               break;
-            case OPS.nextLineShowText:
+            case '\'':
               // For search, adding a extra white space for line breaks would be
               // better here, but that causes too much spaces in the
               // text-selection divs.
               chunk += fontCharsToUnicode(args[0], font);
               break;
-            case OPS.nextLineSetSpacingShowText:
+            case '"':
               // Note comment in "'"
               chunk += fontCharsToUnicode(args[2], font);
               break;
-            case OPS.paintXObject:
+            case 'Do':
               // Set the chunk such that the following if won't add something
               // to the state.
               chunk = '';
 
               if (args[0].code) {
                 break;
               }
 
@@ -14867,24 +15112,23 @@ var PartialEvaluator = (function Partial
               assertWellFormed(
                 isName(type),
                 'XObject should have a Name subtype'
               );
 
               if ('Form' !== type.name)
                 break;
 
-              var formTexts = this.getTextContent(
+              state = this.getTextContent(
                 xobj,
                 xobj.dict.get('Resources') || resources,
-                textState
+                state
               );
-              Util.concatenateToArray(bidiTexts, formTexts);
-              break;
-            case OPS.setGState:
+              break;
+            case 'gs':
               var dictName = args[0];
               var extGState = resources.get('ExtGState');
 
               if (!isDict(extGState) || !extGState.has(dictName.name))
                 break;
 
               var gsState = extGState.get(dictName.name);
 
@@ -14892,46 +15136,39 @@ var PartialEvaluator = (function Partial
                 if (gsState[i] === 'Font') {
                   font = handleSetFont(args[0].name).translated;
                 }
               }
               break;
           } // switch
 
           if (chunk !== '') {
-            var bidiResult = PDFJS.bidi(chunk, -1, font.vertical);
-            var bidiText = {
-              str: bidiResult.str,
-              dir: bidiResult.dir
-            };
-            var renderParams = textState.calcRenderParams(preprocessor.ctm);
+            var bidiText = PDFJS.bidi(chunk, -1, font.vertical);
+            var renderParams = textState.calcRenderParams();
             bidiText.x = renderParams.renderMatrix[4] - (textState.fontSize *
                            renderParams.vScale * Math.sin(renderParams.angle));
             bidiText.y = renderParams.renderMatrix[5] + (textState.fontSize *
                            renderParams.vScale * Math.cos(renderParams.angle));
-            var fontHeight = textState.fontSize * renderParams.vScale;
-            var fontAscent = font.ascent ? font.ascent * fontHeight :
-              font.descent ? (1 + font.descent) * fontHeight : fontHeight;
-            bidiText.x = renderParams.renderMatrix[4] - (fontAscent *
-                           Math.sin(renderParams.angle));
-            bidiText.y = renderParams.renderMatrix[5] + (fontAscent *
-                           Math.cos(renderParams.angle));
             if (bidiText.dir == 'ttb') {
               bidiText.x += renderParams.vScale / 2;
               bidiText.y -= renderParams.vScale;
             }
-            bidiText.angle = renderParams.angle;
-            bidiText.size = fontHeight;
             bidiTexts.push(bidiText);
 
             chunk = '';
           }
+
+          args = [];
+        } else if (obj !== null && obj !== undefined) {
+          assertWellFormed(args.length <= 33, 'Too many arguments');
+          args.push(obj);
+        }
       } // while
 
-      return bidiTexts;
+      return state;
     },
 
     extractDataStructures: function
       partialEvaluatorExtractDataStructures(dict, baseDict,
                                             xref, properties) {
       // 9.10.2
       var toUnicode = dict.get('ToUnicode') ||
         baseDict.get('ToUnicode');
@@ -14966,21 +15203,20 @@ var PartialEvaluator = (function Partial
       var overridableEncoding = true;
       var hasEncoding = false;
       var flags = properties.flags;
       var differences = [];
       var baseEncoding = properties.type === 'TrueType' ?
                           Encodings.WinAnsiEncoding :
                           Encodings.StandardEncoding;
       // The Symbolic attribute can be misused for regular fonts
-      // Heuristic: we have to check if the font is a standard one and has
-      // Symbolic font name
+      // Heuristic: we have to check if the font is a standard one also
       if (!!(flags & FontFlags.Symbolic)) {
-        baseEncoding = !properties.file && /Symbol/i.test(properties.name) ?
-          Encodings.SymbolSetEncoding : Encodings.MacRomanEncoding;
+        baseEncoding = !properties.file ? Encodings.SymbolSetEncoding :
+                                          Encodings.MacRomanEncoding;
       }
       if (dict.has('Encoding')) {
         var encoding = dict.get('Encoding');
         if (isDict(encoding)) {
           var baseName = encoding.get('BaseEncoding');
           if (baseName) {
             overridableEncoding = false;
             hasEncoding = true;
@@ -14998,27 +15234,17 @@ var PartialEvaluator = (function Partial
                 index = data;
               else
                 differences[index++] = data.name;
             }
           }
         } else if (isName(encoding)) {
           overridableEncoding = false;
           hasEncoding = true;
-          var currentEncoding = Encodings[encoding.name];
-
-          // Some bad PDF files contain fonts whose encoding name is not among
-          // the predefined encodings, causing baseEncoding to be undefined.
-          // In this case, fallback to using the baseEncoding as defined above
-          // and let the font override the encoding if one is available.
-          if (currentEncoding) {
-            baseEncoding = currentEncoding;
-          } else {
-            overridableEncoding = true;
-          }
+          baseEncoding = Encodings[encoding.name];
         } else {
           error('Encoding is not a Name nor a Dict');
         }
       }
 
       properties.differences = differences;
       properties.baseEncoding = baseEncoding;
       properties.hasEncoding = hasEncoding;
@@ -15248,17 +15474,16 @@ var PartialEvaluator = (function Partial
           var flags = (
             this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) |
             (metrics.monospace ? FontFlags.FixedPitch : 0) |
             (symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic :
             FontFlags.Nonsymbolic);
 
           var properties = {
             type: type.name,
-            name: baseFontName,
             widths: metrics.widths,
             defaultWidth: metrics.defaultWidth,
             flags: flags,
             firstChar: 0,
             lastChar: maxCharIndex
           };
           this.extractDataStructures(dict, dict, xref, properties);
 
@@ -15307,17 +15532,16 @@ var PartialEvaluator = (function Partial
           var length1 = fontFile.dict.get('Length1');
 
           var length2 = fontFile.dict.get('Length2');
         }
       }
 
       var properties = {
         type: type.name,
-        name: fontName.name,
         subtype: subtype,
         file: fontFile,
         length1: length1,
         length2: length2,
         loadedName: baseDict.loadedName,
         composite: composite,
         wideChars: composite,
         fixedPitch: false,
@@ -15587,39 +15811,60 @@ var OperatorList = (function OperatorLis
   };
 
   return OperatorList;
 })();
 
 var TextState = (function TextStateClosure() {
   function TextState() {
     this.fontSize = 0;
+    this.ctm = [1, 0, 0, 1, 0, 0];
     this.textMatrix = [1, 0, 0, 1, 0, 0];
     this.stateStack = [];
     //textState variables
     this.leading = 0;
     this.textHScale = 1;
     this.textRise = 0;
   }
   TextState.prototype = {
+    push: function TextState_push() {
+      this.stateStack.push(this.ctm.slice());
+    },
+    pop: function TextState_pop() {
+      var prev = this.stateStack.pop();
+      if (prev) {
+        this.ctm = prev;
+      }
+    },
     initialiseTextObj: function TextState_initialiseTextObj() {
       var m = this.textMatrix;
       m[0] = 1, m[1] = 0, m[2] = 0, m[3] = 1, m[4] = 0, m[5] = 0;
     },
     setTextMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) {
       var m = this.textMatrix;
       m[0] = a, m[1] = b, m[2] = c, m[3] = d, m[4] = e, m[5] = f;
     },
+    transformCTM: function TextState_transformCTM(a, b, c, d, e, f) {
+      var m = this.ctm;
+      var m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3], m4 = m[4], m5 = m[5];
+      m[0] = m0 * a + m2 * b;
+      m[1] = m1 * a + m3 * b;
+      m[2] = m0 * c + m2 * d;
+      m[3] = m1 * c + m3 * d;
+      m[4] = m0 * e + m2 * f + m4;
+      m[5] = m1 * e + m3 * f + m5;
+    },
     translateTextMatrix: function TextState_translateTextMatrix(x, y) {
       var m = this.textMatrix;
       m[4] = m[0] * x + m[2] * y + m[4];
       m[5] = m[1] * x + m[3] * y + m[5];
     },
-    calcRenderParams: function TextState_calcRenderingParams(cm) {
+    calcRenderParams: function TextState_calcRenderingParams() {
       var tm = this.textMatrix;
+      var cm = this.ctm;
       var a = this.fontSize;
       var b = a * this.textHScale;
       var c = this.textRise;
       var vScale = Math.sqrt((tm[2] * tm[2]) + (tm[3] * tm[3]));
       var angle = Math.atan2(tm[1], tm[0]);
       var m0 = tm[0] * cm[0] + tm[1] * cm[2];
       var m1 = tm[0] * cm[1] + tm[1] * cm[3];
       var m2 = tm[2] * cm[0] + tm[3] * cm[2];
@@ -15652,231 +15897,16 @@ var EvalState = (function EvalStateClosu
   EvalState.prototype = {
     clone: function CanvasExtraState_clone() {
       return Object.create(this);
     },
   };
   return EvalState;
 })();
 
-var EvaluatorPreprocessor = (function EvaluatorPreprocessor() {
-  // Specifies properties for each command
-  //
-  // If variableArgs === true: [0, `numArgs`] expected
-  // If variableArgs === false: exactly `numArgs` expected
-  var OP_MAP = {
-    // Graphic state
-    w: { id: OPS.setLineWidth, numArgs: 1, variableArgs: false },
-    J: { id: OPS.setLineCap, numArgs: 1, variableArgs: false },
-    j: { id: OPS.setLineJoin, numArgs: 1, variableArgs: false },
-    M: { id: OPS.setMiterLimit, numArgs: 1, variableArgs: false },
-    d: { id: OPS.setDash, numArgs: 2, variableArgs: false },
-    ri: { id: OPS.setRenderingIntent, numArgs: 1, variableArgs: false },
-    i: { id: OPS.setFlatness, numArgs: 1, variableArgs: false },
-    gs: { id: OPS.setGState, numArgs: 1, variableArgs: false },
-    q: { id: OPS.save, numArgs: 0, variableArgs: false },
-    Q: { id: OPS.restore, numArgs: 0, variableArgs: false },
-    cm: { id: OPS.transform, numArgs: 6, variableArgs: false },
-
-    // Path
-    m: { id: OPS.moveTo, numArgs: 2, variableArgs: false },
-    l: { id: OPS.lineTo, numArgs: 2, variableArgs: false },
-    c: { id: OPS.curveTo, numArgs: 6, variableArgs: false },
-    v: { id: OPS.curveTo2, numArgs: 4, variableArgs: false },
-    y: { id: OPS.curveTo3, numArgs: 4, variableArgs: false },
-    h: { id: OPS.closePath, numArgs: 0, variableArgs: false },
-    re: { id: OPS.rectangle, numArgs: 4, variableArgs: false },
-    S: { id: OPS.stroke, numArgs: 0, variableArgs: false },
-    s: { id: OPS.closeStroke, numArgs: 0, variableArgs: false },
-    f: { id: OPS.fill, numArgs: 0, variableArgs: false },
-    F: { id: OPS.fill, numArgs: 0, variableArgs: false },
-    'f*': { id: OPS.eoFill, numArgs: 0, variableArgs: false },
-    B: { id: OPS.fillStroke, numArgs: 0, variableArgs: false },
-    'B*': { id: OPS.eoFillStroke, numArgs: 0, variableArgs: false },
-    b: { id: OPS.closeFillStroke, numArgs: 0, variableArgs: false },
-    'b*': { id: OPS.closeEOFillStroke, numArgs: 0, variableArgs: false },
-    n: { id: OPS.endPath, numArgs: 0, variableArgs: false },
-
-    // Clipping
-    W: { id: OPS.clip, numArgs: 0, variableArgs: false },
-    'W*': { id: OPS.eoClip, numArgs: 0, variableArgs: false },
-
-    // Text
-    BT: { id: OPS.beginText, numArgs: 0, variableArgs: false },
-    ET: { id: OPS.endText, numArgs: 0, variableArgs: false },
-    Tc: { id: OPS.setCharSpacing, numArgs: 1, variableArgs: false },
-    Tw: { id: OPS.setWordSpacing, numArgs: 1, variableArgs: false },
-    Tz: { id: OPS.setHScale, numArgs: 1, variableArgs: false },
-    TL: { id: OPS.setLeading, numArgs: 1, variableArgs: false },
-    Tf: { id: OPS.setFont, numArgs: 2, variableArgs: false },
-    Tr: { id: OPS.setTextRenderingMode, numArgs: 1, variableArgs: false },
-    Ts: { id: OPS.setTextRise, numArgs: 1, variableArgs: false },
-    Td: { id: OPS.moveText, numArgs: 2, variableArgs: false },
-    TD: { id: OPS.setLeadingMoveText, numArgs: 2, variableArgs: false },
-    Tm: { id: OPS.setTextMatrix, numArgs: 6, variableArgs: false },
-    'T*': { id: OPS.nextLine, numArgs: 0, variableArgs: false },
-    Tj: { id: OPS.showText, numArgs: 1, variableArgs: false },
-    TJ: { id: OPS.showSpacedText, numArgs: 1, variableArgs: false },
-    '\'': { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false },
-    '"': { id: OPS.nextLineSetSpacingShowText, numArgs: 3,
-      variableArgs: false },
-
-    // Type3 fonts
-    d0: { id: OPS.setCharWidth, numArgs: 2, variableArgs: false },
-    d1: { id: OPS.setCharWidthAndBounds, numArgs: 6, variableArgs: false },
-
-    // Color
-    CS: { id: OPS.setStrokeColorSpace, numArgs: 1, variableArgs: false },
-    cs: { id: OPS.setFillColorSpace, numArgs: 1, variableArgs: false },
-    SC: { id: OPS.setStrokeColor, numArgs: 4, variableArgs: true },
-    SCN: { id: OPS.setStrokeColorN, numArgs: 33, variableArgs: true },
-    sc: { id: OPS.setFillColor, numArgs: 4, variableArgs: true },
-    scn: { id: OPS.setFillColorN, numArgs: 33, variableArgs: true },
-    G: { id: OPS.setStrokeGray, numArgs: 1, variableArgs: false },
-    g: { id: OPS.setFillGray, numArgs: 1, variableArgs: false },
-    RG: { id: OPS.setStrokeRGBColor, numArgs: 3, variableArgs: false },
-    rg: { id: OPS.setFillRGBColor, numArgs: 3, variableArgs: false },
-    K: { id: OPS.setStrokeCMYKColor, numArgs: 4, variableArgs: false },
-    k: { id: OPS.setFillCMYKColor, numArgs: 4, variableArgs: false },
-
-    // Shading
-    sh: { id: OPS.shadingFill, numArgs: 1, variableArgs: false },
-
-    // Images
-    BI: { id: OPS.beginInlineImage, numArgs: 0, variableArgs: false },
-    ID: { id: OPS.beginImageData, numArgs: 0, variableArgs: false },
-    EI: { id: OPS.endInlineImage, numArgs: 1, variableArgs: false },
-
-    // XObjects
-    Do: { id: OPS.paintXObject, numArgs: 1, variableArgs: false },
-    MP: { id: OPS.markPoint, numArgs: 1, variableArgs: false },
-    DP: { id: OPS.markPointProps, numArgs: 2, variableArgs: false },
-    BMC: { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false },
-    BDC: { id: OPS.beginMarkedContentProps, numArgs: 2,
-      variableArgs: false },
-    EMC: { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false },
-
-    // Compatibility
-    BX: { id: OPS.beginCompat, numArgs: 0, variableArgs: false },
-    EX: { id: OPS.endCompat, numArgs: 0, variableArgs: false },
-
-    // (reserved partial commands for the lexer)
-    BM: null,
-    BD: null,
-    'true': null,
-    fa: null,
-    fal: null,
-    fals: null,
-    'false': null,
-    nu: null,
-    nul: null,
-    'null': null
-  };
-
-  function EvaluatorPreprocessor(stream, xref) {
-    // TODO(mduan): pass array of knownCommands rather than OP_MAP
-    // dictionary
-    this.parser = new Parser(new Lexer(stream, OP_MAP), false, xref);
-    this.ctm = new Float32Array([1, 0, 0, 1, 0, 0]);
-    this.savedStates = [];
-  }
-  EvaluatorPreprocessor.prototype = {
-    get savedStatesDepth() {
-      return this.savedStates.length;
-    },
-    read: function EvaluatorPreprocessor_read() {
-      var args = [];
-      while (true) {
-        var obj = this.parser.getObj();
-        if (isEOF(obj)) {
-          return null; // no more commands
-        }
-        if (!isCmd(obj)) {
-          // argument
-          if (obj !== null && obj !== undefined) {
-            args.push(obj instanceof Dict ? obj.getAll() : obj);
-            assertWellFormed(args.length <= 33, 'Too many arguments');
-          }
-          continue;
-        }
-
-        var cmd = obj.cmd;
-        // Check that the command is valid
-        var opSpec = OP_MAP[cmd];
-        if (!opSpec) {
-          warn('Unknown command "' + cmd + '"');
-          continue;
-        }
-
-        var fn = opSpec.id;
-
-        // Validate the number of arguments for the command
-        if (opSpec.variableArgs) {
-          if (args.length > opSpec.numArgs) {
-            info('Command ' + fn + ': expected [0,' + opSpec.numArgs +
-              '] args, but received ' + args.length + ' args');
-          }
-        } else {
-          if (args.length < opSpec.numArgs) {
-            // If we receive too few args, it's not possible to possible
-            // to execute the command, so skip the command
-            info('Command ' + fn + ': because expected ' +
-              opSpec.numArgs + ' args, but received ' + args.length +
-              ' args; skipping');
-            args = [];
-            continue;
-          } else if (args.length > opSpec.numArgs) {
-            info('Command ' + fn + ': expected ' + opSpec.numArgs +
-              ' args, but received ' + args.length + ' args');
-          }
-        }
-
-        // TODO figure out how to type-check vararg functions
-
-        this.preprocessCommand(fn, args);
-
-        return {fn: fn, args: args};
-      }
-    },
-    getState: function EvaluatorPreprocessor_getState() {
-      return {
-        ctm: this.ctm
-      };
-    },
-    setState: function EvaluatorPreprocessor_setState(state) {
-      this.ctm = state.ctm;
-    },
-    preprocessCommand: function EvaluatorPreprocessor_preprocessCommand(fn,
-                                                                        args) {
-      switch (fn | 0) {
-        case OPS.save:
-          this.savedStates.push(this.getState());
-          break;
-        case OPS.restore:
-          var previousState = this.savedStates.pop();
-          if (previousState) {
-            this.setState(previousState);
-          }
-          break;
-        case OPS.transform:
-          var ctm = this.ctm;
-          var m = new Float32Array(6);
-          m[0] = ctm[0] * args[0] + ctm[2] * args[1];
-          m[1] = ctm[1] * args[0] + ctm[3] * args[1];
-          m[2] = ctm[0] * args[2] + ctm[2] * args[3];
-          m[3] = ctm[1] * args[2] + ctm[3] * args[3];
-          m[4] = ctm[0] * args[4] + ctm[2] * args[5] + ctm[4];
-          m[5] = ctm[1] * args[4] + ctm[3] * args[5] + ctm[5];
-          this.ctm = m;
-          break;
-      }
-    }
-  };
-  return EvaluatorPreprocessor;
-})();
 
 
 // Unicode Private Use Area
 var CMAP_GLYPH_OFFSET = 0xE000;
 var GLYPH_AREA_SIZE = 0x1900;
 var SYMBOLIC_FONT_GLYPH_OFFSET = 0xF000;
 
 // PDF Glyph Space Units are one Thousandth of a TextSpace Unit
@@ -16303,86 +16333,16 @@ var HalfwidthCMaps = {
   'EUC-H': true,
   'EUC-V': true,
   '90ms-RKSJ-H': true,
   '90ms-RKSJ-V': true,
   'UniJIS-UCS2-HW-H': true,
   'UniJIS-UCS2-HW-V': true
 };
 
-// Glyph map for well-known standard fonts. Sometimes Ghostscript uses CID fonts
-// but does not embed the CID to GID mapping. The mapping is incomplete for all
-// glyphs, but common for some set of the standard fonts.
-var GlyphMapForStandardFonts = {
-  '2': 10, '3': 32, '4': 33, '5': 34, '6': 35, '7': 36, '8': 37, '9': 38,
-  '10': 39, '11': 40, '12': 41, '13': 42, '14': 43, '15': 44, '16': 173,
-  '17': 46, '18': 47, '19': 48, '20': 49, '21': 50, '22': 51, '23': 52,
-  '24': 53, '25': 54, '26': 55, '27': 56, '28': 57, '29': 58, '30': 894,
-  '31': 60, '32': 61, '33': 62, '34': 63, '35': 64, '36': 65, '37': 66,
-  '38': 67, '39': 68, '40': 69, '41': 70, '42': 71, '43': 72, '44': 73,
-  '45': 74, '46': 75, '47': 76, '48': 77, '49': 78, '50': 79, '51': 80,
-  '52': 81, '53': 82, '54': 83, '55': 84, '56': 85, '57': 86, '58': 87,
-  '59': 88, '60': 89, '61': 90, '62': 91, '63': 92, '64': 93, '65': 94,
-  '66': 95, '67': 96, '68': 97, '69': 98, '70': 99, '71': 100, '72': 101,
-  '73': 102, '74': 103, '75': 104, '76': 105, '77': 106, '78': 107, '79': 108,
-  '80': 109, '81': 110, '82': 111, '83': 112, '84': 113, '85': 114, '86': 115,
-  '87': 116, '88': 117, '89': 118, '90': 119, '91': 120, '92': 121, '93': 122,
-  '94': 123, '95': 124, '96': 125, '97': 126, '98': 196, '99': 197, '100': 199,
-  '101': 201, '102': 209, '103': 214, '104': 220, '105': 225, '106': 224,
-  '107': 226, '108': 228, '109': 227, '110': 229, '111': 231, '112': 233,
-  '113': 232, '114': 234, '115': 235, '116': 237, '117': 236, '118': 238,
-  '119': 239, '120': 241, '121': 243, '122': 242, '123': 244, '124': 246,
-  '125': 245, '126': 250, '127': 249, '128': 251, '129': 252, '130': 8224,
-  '131': 176, '132': 162, '133': 163, '134': 167, '135': 8226, '136': 182,
-  '137': 223, '138': 174, '139': 169, '140': 8482, '141': 180, '142': 168,
-  '143': 8800, '144': 198, '145': 216, '146': 8734, '147': 177, '148': 8804,
-  '149': 8805, '150': 165, '151': 181, '152': 8706, '153': 8721, '154': 8719,
-  '156': 8747, '157': 170, '158': 186, '159': 8486, '160': 230, '161': 248,
-  '162': 191, '163': 161, '164': 172, '165': 8730, '166': 402, '167': 8776,
-  '168': 8710, '169': 171, '170': 187, '171': 8230, '210': 218, '305': 963,
-  '306': 964, '307': 966, '308': 8215, '309': 8252, '310': 8319, '311': 8359,
-  '312': 8592, '313': 8593, '337': 9552, '493': 1039, '494': 1040, '705': 1524,
-  '706': 8362, '710': 64288, '711': 64298, '759': 1617, '761': 1776,
-  '763': 1778, '775': 1652, '777': 1764, '778': 1780, '779': 1781, '780': 1782,
-  '782': 771, '783': 64726, '786': 8363, '788': 8532, '790': 768, '791': 769,
-  '792': 768, '795': 803, '797': 64336, '798': 64337, '799': 64342,
-  '800': 64343, '801': 64344, '802': 64345, '803': 64362, '804': 64363,
-  '805': 64364, '2424': 7821, '2425': 7822, '2426': 7823, '2427': 7824,
-  '2428': 7825, '2429': 7826, '2430': 7827, '2433': 7682, '2678': 8045,
-  '2679': 8046, '2830': 1552, '2838': 686, '2840': 751, '2842': 753,
-  '2843': 754, '2844': 755, '2846': 757, '2856': 767, '2857': 848, '2858': 849,
-  '2862': 853, '2863': 854, '2864': 855, '2865': 861, '2866': 862, '2906': 7460,
-  '2908': 7462, '2909': 7463, '2910': 7464, '2912': 7466, '2913': 7467,
-  '2914': 7468, '2916': 7470, '2917': 7471, '2918': 7472, '2920': 7474,
-  '2921': 7475, '2922': 7476, '2924': 7478, '2925': 7479, '2926': 7480,
-  '2928': 7482, '2929': 7483, '2930': 7484, '2932': 7486, '2933': 7487,
-  '2934': 7488, '2936': 7490, '2937': 7491, '2938': 7492, '2940': 7494,
-  '2941': 7495, '2942': 7496, '2944': 7498, '2946': 7500, '2948': 7502,
-  '2950': 7504, '2951': 7505, '2952': 7506, '2954': 7508, '2955': 7509,
-  '2956': 7510, '2958': 7512, '2959': 7513, '2960': 7514, '2962': 7516,
-  '2963': 7517, '2964': 7518, '2966': 7520, '2967': 7521, '2968': 7522,
-  '2970': 7524, '2971': 7525, '2972': 7526, '2974': 7528, '2975': 7529,
-  '2976': 7530, '2978': 1537, '2979': 1538, '2980': 1539, '2982': 1549,
-  '2983': 1551, '2984': 1552, '2986': 1554, '2987': 1555, '2988': 1556,
-  '2990': 1623, '2991': 1624, '2995': 1775, '2999': 1791, '3002': 64290,
-  '3003': 64291, '3004': 64292, '3006': 64294, '3007': 64295, '3008': 64296,
-  '3011': 1900, '3014': 8223, '3015': 8244, '3017': 7532, '3018': 7533,
-  '3019': 7534, '3075': 7590, '3076': 7591, '3079': 7594, '3080': 7595,
-  '3083': 7598, '3084': 7599, '3087': 7602, '3088': 7603, '3091': 7606,
-  '3092': 7607, '3095': 7610, '3096': 7611, '3099': 7614, '3100': 7615,
-  '3103': 7618, '3104': 7619, '3107': 8337, '3108': 8338, '3116': 1884,
-  '3119': 1885, '3120': 1885, '3123': 1886, '3124': 1886, '3127': 1887,
-  '3128': 1887, '3131': 1888, '3132': 1888, '3135': 1889, '3136': 1889,
-  '3139': 1890, '3140': 1890, '3143': 1891, '3144': 1891, '3147': 1892,
-  '3148': 1892, '3153': 580, '3154': 581, '3157': 584, '3158': 585, '3161': 588,
-  '3162': 589, '3165': 891, '3166': 892, '3169': 1274, '3170': 1275,
-  '3173': 1278, '3174': 1279, '3181': 7622, '3182': 7623, '3282': 11799,
-  '3316': 578, '3379': 42785, '3393': 1159, '3416': 8377
-};
-
 var decodeBytes;
 if (typeof TextDecoder !== 'undefined') {
   // The encodings supported by TextDecoder can be found at:
   // http://encoding.spec.whatwg.org/#concept-encoding-get
   decodeBytes = function(bytes, encoding, fatal) {
     return new TextDecoder(encoding, {fatal: !!fatal}).decode(bytes);
   };
 } else if (typeof FileReaderSync !== 'undefined') {
@@ -16412,29 +16372,29 @@ function sjisToUnicode(str) {
 }
 
 function sjis83pvToUnicode(str) {
   var bytes = stringToBytes(str);
   try {
     // TODO: 83pv has incompatible mappings in ed40..ee9c range.
     return decodeBytes(bytes, 'shift_jis', true);
   } catch (e) {
-    warn('Unsupported 83pv character found');
+    TODO('Unsupported 83pv character found');
     // Just retry without checking errors for now.
     return decodeBytes(bytes, 'shift_jis');
   }
 }
 
 function sjis90pvToUnicode(str) {
   var bytes = stringToBytes(str);
   try {
     // TODO: 90pv has incompatible mappings in 8740..879c and eb41..ee9c.
     return decodeBytes(bytes, 'shift_jis', true);
   } catch (e) {
-    warn('Unsupported 90pv character found');
+    TODO('Unsupported 90pv character found');
     // Just retry without checking errors for now.
     return decodeBytes(bytes, 'shift_jis');
   }
 }
 
 function gbkToUnicode(str) {
   return decodeBytes(stringToBytes(str), 'gbk');
 }
@@ -18100,18 +18060,16 @@ var Font = (function FontClosure() {
 
     this.differences = properties.differences;
     this.widths = properties.widths;
     this.defaultWidth = properties.defaultWidth;
     this.composite = properties.composite;
     this.wideChars = properties.wideChars;
     this.hasEncoding = properties.hasEncoding;
     this.cmap = properties.cmap;
-    this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS;
-    this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS;
 
     this.fontMatrix = properties.fontMatrix;
     if (properties.type == 'Type3') {
       this.encoding = properties.baseEncoding;
       return;
     }
 
     // Trying to fix encoding using glyph CIDSystemInfo.
@@ -18129,43 +18087,31 @@ var Font = (function FontClosure() {
       this.rebuildToUnicode(properties);
 
     this.toFontChar = this.buildToFontChar(this.toUnicode);
 
     if (!file) {
       // The file data is not specified. Trying to fix the font name
       // to be used with the canvas.font.
       var fontName = name.replace(/[,_]/g, '-');
-      var isStandardFont = fontName in stdFontMap;
       fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName;
 
       this.bold = (fontName.search(/bold/gi) != -1);
       this.italic = (fontName.search(/oblique/gi) != -1) ||
                     (fontName.search(/italic/gi) != -1);
 
       // Use 'name' instead of 'fontName' here because the original
       // name ArialBlack for example will be replaced by Helvetica.
       this.black = (name.search(/Black/g) != -1);
 
       // if at least one width is present, remeasure all chars when exists
       this.remeasure = Object.keys(this.widths).length > 0;
 
       this.encoding = properties.baseEncoding;
       this.noUnicodeAdaptation = true;
-      if (isStandardFont && type === 'CIDFontType2' &&
-          properties.cidEncoding.indexOf('Identity-') === 0) {
-        // Standard fonts might be embedded as CID font without glyph mapping.
-        // Building one based on GlyphMapForStandardFonts.
-        var map = [];
-        for (var code in GlyphMapForStandardFonts) {
-          map[+code] = GlyphMapForStandardFonts[code];
-        }
-        this.toFontChar = map;
-        this.toUnicode = map;
-      }
       this.loadedName = fontName.split('-')[0];
       this.loading = false;
       return;
     }
 
     // Some fonts might use wrong font types for Type1C or CIDFontType0C
     var subtype = properties.subtype;
     if (subtype == 'Type1C' && (type != 'Type1' && type != 'MMType1'))
@@ -20270,17 +20216,17 @@ var Font = (function FontClosure() {
 
       var cidToUnicodeMap = [], unicodeToCIDMap = [];
       this.cidToUnicode = cidToUnicodeMap;
       this.unicodeToCID = unicodeToCIDMap;
 
       var cidEncoding = properties.cidEncoding;
       if (properties.toUnicode) {
         if (cidEncoding && cidEncoding.indexOf('Identity-') !== 0) {
-          warn('Need to create a reverse mapping from \'ToUnicode\' CMap');
+          TODO('Need to create a reverse mapping from \'ToUnicode\' CMap');
         }
         return; // 'ToUnicode' CMap will be used
       }
 
       var cidSystemInfo = properties.cidSystemInfo;
       var cidToUnicode;
       if (cidSystemInfo) {
         cidToUnicode = CIDToUnicodeMaps[
@@ -27951,17 +27897,17 @@ var PDFImage = (function PDFImageClosure
     // Clamp the value to the range
     return value < 0 ? 0 : value > max ? max : value;
   }
   function PDFImage(xref, res, image, inline, smask, mask, isMask) {
     this.image = image;
     if (image.getParams) {
       // JPX/JPEG2000 streams directly contain bits per component
       // and color space mode information.
-      warn('get params from actual stream');
+      TODO('get params from actual stream');
       // var bits = ...
       // var colorspace = ...
     }
     // TODO cache rendered images?
 
     var dict = image.dict;
     this.width = dict.get('Width', 'W');
     this.height = dict.get('Height', 'H');
@@ -27984,17 +27930,17 @@ var PDFImage = (function PDFImageClosure
           error('Bits per component missing in image: ' + this.imageMask);
       }
     }
     this.bpc = bitsPerComponent;
 
     if (!this.imageMask) {
       var colorSpace = dict.get('ColorSpace', 'CS');
       if (!colorSpace) {
-        warn('JPX images (which don"t require color spaces');
+        TODO('JPX images (which don"t require color spaces');
         colorSpace = new Name('DeviceRGB');
       }
       this.colorSpace = ColorSpace.parse(colorSpace, xref, res);
       this.numComps = this.colorSpace.numComps;
     }
 
     this.decode = dict.get('Decode', 'D');
     this.needsDecode = false;
@@ -28026,19 +27972,19 @@ var PDFImage = (function PDFImageClosure
     }
   }
   /**
    * Handles processing of image data and calls the callback with an argument
    * of a PDFImage when the image is ready to be used.
    */
   PDFImage.buildImage = function PDFImage_buildImage(callback, handler, xref,
                                                      res, image, inline) {
-    var imageDataPromise = new LegacyPromise();
-    var smaskPromise = new LegacyPromise();
-    var maskPromise = new LegacyPromise();
+    var imageDataPromise = new Promise();
+    var smaskPromise = new Promise();
+    var maskPromise = new Promise();
     // The image data and smask data may not be ready yet, wait till both are
     // resolved.
     Promise.all([imageDataPromise, smaskPromise, maskPromise]).then(
         function(results) {
       var imageData = results[0], smaskData = results[1], maskData = results[2];
       var image = new PDFImage(xref, res, imageData, inline, smaskData,
                                maskData);
       callback(image);
@@ -28106,31 +28052,36 @@ var PDFImage = (function PDFImageClosure
         }
       }
     }
     return temp;
   };
 
   PDFImage.createMask = function PDFImage_createMask(imgArray, width, height,
                                                      inverseDecode) {
-    // Copy imgArray into a typed array (inverting if necessary) so it can be
-    // transferred to the main thread.
-    var length = ((width + 7) >> 3) * height;
-    var data = new Uint8Array(length);
-    if (inverseDecode) {
-      for (var i = 0; i < length; i++) {
-        data[i] = ~imgArray[i];
-      }
-    } else {
-      for (var i = 0; i < length; i++) {
-        data[i] = imgArray[i];
-      }
-    }
-
-    return {data: data, width: width, height: height};
+    var buffer = new Uint8Array(width * height * 4);
+    var imgArrayPos = 0;
+    var i, j, mask, buf;
+    // removing making non-masked pixels transparent
+    var bufferPos = 3; // alpha component offset
+    for (i = 0; i < height; i++) {
+      mask = 0;
+      for (j = 0; j < width; j++) {
+        if (!mask) {
+          buf = imgArray[imgArrayPos++];
+          mask = 128;
+        }
+        if (!(buf & mask) !== inverseDecode) {
+          buffer[bufferPos] = 255;
+        }
+        bufferPos += 4;
+        mask >>= 1;
+      }
+    }
+    return {data: buffer, width: width, height: height};
   };
 
   PDFImage.prototype = {
     get drawWidth() {
       if (!this.smask)
         return this.width;
       return Math.max(this.width, this.smask.width);
     },
@@ -28223,78 +28174,71 @@ var PDFImage = (function PDFImageClosure
           var value = buf >> remainingBits;
           output[i] = value < 0 ? 0 : value > max ? max : value;
           buf = buf & ((1 << remainingBits) - 1);
           bits = remainingBits;
         }
       }
       return output;
     },
-    fillOpacity: function PDFImage_fillOpacity(rgbaBuf, width, height,
-                                               actualHeight, image) {
+    getOpacity: function PDFImage_getOpacity(width, height, image) {
       var smask = this.smask;
       var mask = this.mask;
-      var alphaBuf;
+      var originalWidth = this.width;
+      var originalHeight = this.height;
+      var buf;
 
       if (smask) {
         var sw = smask.width;
         var sh = smask.height;
-        alphaBuf = new Uint8Array(sw * sh);
-        smask.fillGrayBuffer(alphaBuf);
+        buf = new Uint8Array(sw * sh);
+        smask.fillGrayBuffer(buf);
         if (sw != width || sh != height)
-          alphaBuf = PDFImage.resize(alphaBuf, smask.bpc, 1, sw, sh, width,
-                                     height);
+          buf = PDFImage.resize(buf, smask.bpc, 1, sw, sh, width, height);
       } else if (mask) {
         if (mask instanceof PDFImage) {
           var sw = mask.width;
           var sh = mask.height;
-          alphaBuf = new Uint8Array(sw * sh);
+          buf = new Uint8Array(sw * sh);
           mask.numComps = 1;
-          mask.fillGrayBuffer(alphaBuf);
-
-          // Need to invert values in rgbaBuf
+          mask.fillGrayBuffer(buf);
+
+          // Need to invert values in buffer
           for (var i = 0, ii = sw * sh; i < ii; ++i)
-            alphaBuf[i] = 255 - alphaBuf[i];
+            buf[i] = 255 - buf[i];
 
           if (sw != width || sh != height)
-            alphaBuf = PDFImage.resize(alphaBuf, mask.bpc, 1, sw, sh, width,
-                                       height);
+            buf = PDFImage.resize(buf, mask.bpc, 1, sw, sh, width, height);
         } else if (isArray(mask)) {
           // Color key mask: if any of the compontents are outside the range
           // then they should be painted.
-          alphaBuf = new Uint8Array(width * height);
+          buf = new Uint8Array(width * height);
           var numComps = this.numComps;
           for (var i = 0, ii = width * height; i < ii; ++i) {
             var opacity = 0;
             var imageOffset = i * numComps;
             for (var j = 0; j < numComps; ++j) {
               var color = image[imageOffset + j];
               var maskOffset = j * 2;
               if (color < mask[maskOffset] || color > mask[maskOffset + 1]) {
                 opacity = 255;
                 break;
               }
             }
-            alphaBuf[i] = opacity;
+            buf[i] = opacity;
           }
         } else {
           error('Unknown mask format.');
         }
-      }
-
-      if (alphaBuf) {
-        for (var i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
-          rgbaBuf[j] = alphaBuf[i];
-        }
-      } else {
-        // Common case: no mask (and no need to allocate the extra buffer).
-        for (var i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
-          rgbaBuf[j] = 255;
-        }
-      }
+      } else {
+        buf = new Uint8Array(width * height);
+        for (var i = 0, ii = width * height; i < ii; ++i)
+          buf[i] = 255;
+      }
+      return buf;
     },
     undoPreblend: function PDFImage_undoPreblend(buffer, width, height) {
       var matte = this.smask && this.smask.matte;
       if (!matte) {
         return;
       }
 
       function clamp(value) {
@@ -28328,27 +28272,38 @@ var PDFImage = (function PDFImageClosure
       // rows start at byte boundary;
       var rowBytes = (originalWidth * numComps * bpc + 7) >> 3;
       var imgArray = this.getImageBytes(originalHeight * rowBytes);
 
       // imgArray can be incomplete (e.g. after CCITT fax encoding)
       var actualHeight = 0 | (imgArray.length / rowBytes *
                          height / originalHeight);
       var comps = this.getComponents(imgArray);
-
-      // Handle opacity here since color key masking needs to be performed on
+      // Build opacity here since color key masking needs to be perormed on
       // undecoded values.
-      this.fillOpacity(buffer, width, height, actualHeight, comps);
+      var opacity = this.getOpacity(width, height, comps);
 
       if (this.needsDecode) {
         this.decodeBuffer(comps);
       }
-
-      this.colorSpace.fillRgb(buffer, originalWidth, originalHeight, width,
-                              height, actualHeight, bpc, comps);
+      var rgbBuf = this.colorSpace.createRgbBuffer(comps, 0,
+                                    originalWidth * originalHeight, bpc);
+      if (originalWidth != width || originalHeight != height)
+        rgbBuf = PDFImage.resize(rgbBuf, this.bpc, 3, originalWidth,
+                                originalHeight, width, height);
+      var compsPos = 0;
+      var opacityPos = 0;
+      var length = width * actualHeight * 4;
+
+      for (var i = 0; i < length; i += 4) {
+        buffer[i] = rgbBuf[compsPos++];
+        buffer[i + 1] = rgbBuf[compsPos++];
+        buffer[i + 2] = rgbBuf[compsPos++];
+        buffer[i + 3] = opacity[opacityPos++];
+      }
 
       this.undoPreblend(buffer, width, actualHeight);
     },
     fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) {
       var numComps = this.numComps;
       if (numComps != 1)
         error('Reading gray scale from a color image: ' + numComps);
 
@@ -31345,16 +31300,31 @@ var Parser = (function ParserClosure() {
   function Parser(lexer, allowStreams, xref) {
     this.lexer = lexer;
     this.allowStreams = allowStreams;
     this.xref = xref;
     this.refill();
   }
 
   Parser.prototype = {
+    saveState: function Parser_saveState() {
+      this.state = {
+        buf1: this.buf1,
+        buf2: this.buf2,
+        streamPos: this.lexer.stream.pos
+      };
+    },
+
+    restoreState: function Parser_restoreState() {
+      var state = this.state;
+      this.buf1 = state.buf1;
+      this.buf2 = state.buf2;
+      this.lexer.stream.pos = state.streamPos;
+    },
+
     refill: function Parser_refill() {
       this.buf1 = this.lexer.getObj();
       this.buf2 = this.lexer.getObj();
     },
     shift: function Parser_shift() {
       if (isCmd(this.buf2, 'ID')) {
         this.buf1 = this.buf2;
         this.buf2 = null;
@@ -32549,28 +32519,22 @@ var FlateStream = (function FlateStreamC
 
       this.codeBuf = 0;
       this.codeSize = 0;
 
       var bufferLength = this.bufferLength;
       var buffer = this.ensureBuffer(bufferLength + blockLen);
       var end = bufferLength + blockLen;
       this.bufferLength = end;
-      if (blockLen === 0) {
-        if (typeof bytes[bytesPos] == 'undefined') {
+      for (var n = bufferLength; n < end; ++n) {
+        if (typeof (b = bytes[bytesPos++]) == 'undefined') {
           this.eof = true;
-        }
-      } else {
-        for (var n = bufferLength; n < end; ++n) {
-          if (typeof (b = bytes[bytesPos++]) == 'undefined') {
-            this.eof = true;
-            break;
-          }
-          buffer[n] = b;
-        }
+          break;
+        }
+        buffer[n] = b;
       }
       this.bytesPos = bytesPos;
       return;
     }
 
     var litCodeTable;
     var distCodeTable;
     if (hdr == 1) { // compressed block, fixed codes
@@ -33023,26 +32987,16 @@ var Jbig2Stream = (function Jbig2StreamC
 
   Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) {
     if (this.bufferLength)
       return;
 
     var jbig2Image = new Jbig2Image();
 
     var chunks = [], decodeParams = this.dict.get('DecodeParms');
-
-    // According to the PDF specification, DecodeParms can be either
-    // a dictionary, or an array whose elements are dictionaries.
-    if (isArray(decodeParams)) {
-      if (decodeParams.length > 1) {
-        warn('JBIG2 - \'DecodeParms\' array with multiple elements ' +
-             'not supported.');
-      }
-      decodeParams = decodeParams[0];
-    }
     if (decodeParams && decodeParams.has('JBIG2Globals')) {
       var globalsStream = decodeParams.get('JBIG2Globals');
       var globals = globalsStream.getBytes();
       chunks.push({data: globals, start: 0, end: globals.length});
     }
     chunks.push({data: this.bytes, start: 0, end: this.bytes.length});
     var data = jbig2Image.parseChunks(chunks);
     var dataLength = data.length;
@@ -34385,17 +34339,17 @@ var NullStream = (function NullStreamClo
 })();
 
 
 var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
   setup: function wphSetup(handler) {
     var pdfManager;
 
     function loadDocument(recoveryMode) {
-      var loadDocumentPromise = new LegacyPromise();
+      var loadDocumentPromise = new Promise();
 
       var parseSuccess = function parseSuccess() {
         var numPagesPromise = pdfManager.ensureModel('numPages');
         var fingerprintPromise = pdfManager.ensureModel('fingerprint');
         var outlinePromise = pdfManager.ensureCatalog('documentOutline');
         var infoPromise = pdfManager.ensureModel('documentInfo');
         var metadataPromise = pdfManager.ensureCatalog('metadata');
         var encryptedPromise = pdfManager.ensureXRef('encrypt');
@@ -34429,17 +34383,17 @@ var WorkerMessageHandler = PDFJS.WorkerM
               parseSuccess, parseFailure);
         }, parseFailure);
       }, parseFailure);
 
       return loadDocumentPromise;
     }
 
     function getPdfManager(data) {
-      var pdfManagerPromise = new LegacyPromise();
+      var pdfManagerPromise = new Promise();
 
       var source = data.source;
       var disableRange = data.disableRange;
       if (source.data) {
         try {
           pdfManager = new LocalPdfManager(source.data, source.password);
           pdfManagerPromise.resolve();
         } catch (ex) {
@@ -34452,18 +34406,17 @@ var WorkerMessageHandler = PDFJS.WorkerM
           pdfManagerPromise.resolve();
         } catch (ex) {
           pdfManagerPromise.reject(ex);
         }
         return pdfManagerPromise;
       }
 
       var networkManager = new NetworkManager(source.url, {
-        httpHeaders: source.httpHeaders,
-        withCredentials: source.withCredentials
+        httpHeaders: source.httpHeaders
       });
       var fullRequestXhrId = networkManager.requestFull({
         onHeadersReceived: function onHeadersReceived() {
           if (disableRange) {
             return;
           }
 
           var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId);
@@ -34589,28 +34542,25 @@ var WorkerMessageHandler = PDFJS.WorkerM
             exception: new UnknownErrorException(e.message, e.toString())
           });
         }
       };
 
       PDFJS.maxImageSize = data.maxImageSize === undefined ?
                            -1 : data.maxImageSize;
       PDFJS.disableFontFace = data.disableFontFace;
-      PDFJS.disableCreateObjectURL = data.disableCreateObjectURL;
-      PDFJS.verbosity = data.verbosity;
 
       getPdfManager(data).then(function pdfManagerReady() {
         loadDocument(false).then(onSuccess, function loadFailure(ex) {
           // Try again with recoveryMode == true
           if (!(ex instanceof XRefParseException)) {
             if (ex instanceof PasswordException) {
               // after password exception prepare to receive a new password
               // to repeat loading
-              pdfManager.passwordChangedPromise =
-                new LegacyPromise();
+              pdfManager.passwordChangedPromise = new Promise();
               pdfManager.passwordChangedPromise.then(pdfManagerReady);
             }
 
             onFailure(ex);
             return;
           }
 
           pdfManager.requestLoadedStream();
@@ -34637,41 +34587,41 @@ var WorkerMessageHandler = PDFJS.WorkerM
             view: results[2]
           };
 
           handler.send('GetPage', { pageInfo: page });
         });
       });
     });
 
-    handler.on('GetPageIndex', function wphSetupGetPageIndex(data, deferred) {
+    handler.on('GetPageIndex', function wphSetupGetPageIndex(data, promise) {
       var ref = new Ref(data.ref.num, data.ref.gen);
       pdfManager.pdfModel.catalog.getPageIndex(ref).then(function (pageIndex) {
-        deferred.resolve(pageIndex);
-      }, deferred.reject);
+        promise.resolve(pageIndex);
+      }, promise.reject.bind(promise));
     });
 
     handler.on('GetDestinations',
-      function wphSetupGetDestinations(data, deferred) {
+      function wphSetupGetDestinations(data, promise) {
         pdfManager.ensureCatalog('destinations').then(function(destinations) {
-          deferred.resolve(destinations);
+          promise.resolve(destinations);
         });
       }
     );
 
-    handler.on('GetData', function wphSetupGetData(data, deferred) {
+    handler.on('GetData', function wphSetupGetData(data, promise) {
       pdfManager.requestLoadedStream();
       pdfManager.onLoadedStream().then(function(stream) {
-        deferred.resolve(stream.bytes);
+        promise.resolve(stream.bytes);
       });
     });
 
-    handler.on('DataLoaded', function wphSetupDataLoaded(data, deferred) {
+    handler.on('DataLoaded', function wphSetupDataLoaded(data, promise) {
       pdfManager.onLoadedStream().then(function(stream) {
-        deferred.resolve({ length: stream.bytes.byteLength });
+        promise.resolve({ length: stream.bytes.byteLength });
       });
     });
 
     handler.on('UpdatePassword', function wphSetupUpdatePassword(data) {
       pdfManager.updatePassword(data);
     });
 
     handler.on('GetAnnotationsRequest', function wphSetupGetAnnotations(data) {
@@ -34690,17 +34640,17 @@ var WorkerMessageHandler = PDFJS.WorkerM
     handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
       pdfManager.getPage(data.pageIndex).then(function(page) {
 
         var pageNum = data.pageIndex + 1;
         var start = Date.now();
         // Pre compile the pdf page and fetch the fonts/images.
         page.getOperatorList(handler).then(function(operatorList) {
 
-          info('page=%d - getOperatorList: time=%dms, len=%d', pageNum,
+          log('page=%d - getOperatorList: time=%dms, len=%d', pageNum,
               Date.now() - start, operatorList.fnArray.length);
 
         }, function(e) {
 
           var minimumStackMessage =
               'worker.js: while trying to getPage() and getOperatorList()';
 
           var wrappedException;
@@ -34726,39 +34676,39 @@ var WorkerMessageHandler = PDFJS.WorkerM
           handler.send('PageError', {
             pageNum: pageNum,
             error: wrappedException
           });
         });
       });
     }, this);
 
-    handler.on('GetTextContent', function wphExtractText(data, deferred) {
+    handler.on('GetTextContent', function wphExtractText(data, promise) {
       pdfManager.getPage(data.pageIndex).then(function(page) {
         var pageNum = data.pageIndex + 1;
         var start = Date.now();
         page.extractTextContent().then(function(textContent) {
-          deferred.resolve(textContent);
-          info('text indexing: page=%d - time=%dms', pageNum,
+          promise.resolve(textContent);
+          log('text indexing: page=%d - time=%dms', pageNum,
               Date.now() - start);
         }, function (e) {
           // Skip errored pages
-          deferred.reject(e);
+          promise.reject(e);
         });
       });
     });
 
-    handler.on('Cleanup', function wphCleanup(data, deferred) {
+    handler.on('Cleanup', function wphCleanup(data, promise) {
       pdfManager.cleanup();
-      deferred.resolve(true);
+      promise.resolve(true);
     });
 
-    handler.on('Terminate', function wphTerminate(data, deferred) {
+    handler.on('Terminate', function wphTerminate(data, promise) {
       pdfManager.terminate();
-      deferred.resolve();
+      promise.resolve();
     });
   }
 };
 
 var consoleTimer = {};
 
 var workerConsole = {
   log: function log() {
@@ -34780,35 +34730,35 @@ var workerConsole = {
 
   time: function time(name) {
     consoleTimer[name] = Date.now();
   },
 
   timeEnd: function timeEnd(name) {
     var time = consoleTimer[name];
     if (!time) {
-      error('Unknown timer name ' + name);
+      error('Unkown timer name ' + name);
     }
     this.log('Timer:', name, Date.now() - time);
   }
 };
 
-
 // Worker thread?
 if (typeof window === 'undefined') {
-  if (!('console' in globalScope)) {
-    globalScope.console = workerConsole;
-  }
-
-  // Listen for unsupported features so we can pass them on to the main thread.
-  PDFJS.UnsupportedManager.listen(function (msg) {
-    globalScope.postMessage({
-      action: '_unsupported_feature',
-      data: msg
-    });
+  globalScope.console = workerConsole;
+
+  // Add a logger so we can pass warnings on to the main thread, errors will
+  // throw an exception which will be forwarded on automatically.
+  PDFJS.LogManager.addLogger({
+    warn: function(msg) {
+      globalScope.postMessage({
+        action: '_warn',
+        data: msg
+      });
+    }
   });
 
   var handler = new MessageHandler('worker_processor', this);
   WorkerMessageHandler.setup(handler);
 }
 
 
 var JpxImage = (function JpxImageClosure() {
--- a/browser/extensions/pdfjs/content/network.js
+++ b/browser/extensions/pdfjs/content/network.js
@@ -21,35 +21,32 @@
 'use strict';
 
 
   
   Components.utils.import('resource://gre/modules/Services.jsm');
   
   var EXPORTED_SYMBOLS = ['NetworkManager'];
   
-  var console = {
-    log: function console_log(aMsg) {
-      var msg = 'network.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
-      Services.console.logStringMessage(msg);
-      // TODO(mack): dump() doesn't seem to work here...
-      dump(msg + '\n');
-    }
+  function log(aMsg) {
+    var msg = 'network.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
+    Services.console.logStringMessage(msg);
+    // TODO(mack): dump() doesn't seem to work here...
+    dump(msg + '\n');
   }
 
 var NetworkManager = (function NetworkManagerClosure() {
 
   var OK_RESPONSE = 200;
   var PARTIAL_CONTENT_RESPONSE = 206;
 
   function NetworkManager(url, args) {
     this.url = url;
     args = args || {};
     this.httpHeaders = args.httpHeaders || {};
-    this.withCredentials = args.withCredentials || false;
     this.getXhr = args.getXhr ||
       function NetworkManager_getXhr() {
         return new XMLHttpRequest();
       };
 
     this.currXhrId = 0;
     this.pendingRequests = {};
     this.loadedRequests = {};
@@ -88,17 +85,16 @@ var NetworkManager = (function NetworkMa
     request: function NetworkManager_requestRange(args) {
       var xhr = this.getXhr();
       var xhrId = this.currXhrId++;
       var pendingRequest = this.pendingRequests[xhrId] = {
         xhr: xhr
       };
 
       xhr.open('GET', this.url);
-      xhr.withCredentials = this.withCredentials;
       for (var property in this.httpHeaders) {
         var value = this.httpHeaders[property];
         if (typeof value === 'undefined') {
           continue;
         }
         xhr.setRequestHeader(property, value);
       }
       if ('begin' in args && 'end' in args) {
index 4b5551e23600acf956df706d73cab427db50b90c..08a2c25327d7df3c77186cc3048bf02b7e72f393
GIT binary patch
literal 371
zc%17D@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6n3BBRT^Rni_n+Ah<Z%{wL>4nJ
za0`PlBg3pY5<o%r5>H=O_B&jxVj>1dW-W_hU|?kNba4#PIA1#9tk+=&k=FgQ+pdT`
zUbe$HMe!GtU6WGBI$aLYZm~5FlsUCLM9rJ>x)ki1v&;2jM441q`dLYetDQYE-*|TQ
z^E<_9?^Y%rUfkJzY)ZIaD_<MC&cmBh$CtgYp8dL|p1-2*N5P)WO~<yom=<t<b<MX{
zV0F4SV~dnB5HBwOxorLKx2`PB3<(U3Mv^-!Sehqq>wl!)(o;G8S#tSeKda!GbIv?G
zbmhsbOZ!$BA5pw%wO?3d{?EV_k<*RN+E-q_-@A4@_jI3mOCvtN%FsWiAoSU(>6p5s
zu;<LjPZQOdDxY?~D4*1|{qN@6tRl%q{~C{f`Y<K**{Z}4_g5KqIsN)|hXdZr_a9ya
P3?c?kS3j3^P6<r_kMx(q
index f681e4ee44e4dd520759b974a7a1f6f868f30894..beef8ccea48c932571c9c9009df916a61c850a1c
GIT binary patch
literal 381
zc$@)!0fPRCP)<h;3K|Lk000e1NJLTq000mG000mO1ONa4wfZ;e00002VoOIv0RM-N
z%)bBt010qNS#tmY3ljhU3ljkVnw%H_000McNliru+zJI29sn4uetG}^0S-w-K~yNu
zb&)+w13?gmpWQt!_hI5eD#4IKO<|GNA0TLBqfH`0&_WQwe<O&XAP9<DC}<P>Cn>#B
z0z$y#_7d0P?!t27TP(BlKC{g1C~Qf5JYZ(0Y`HA=4{6~34>Y$nUyp4>0?NXx%y!n^
zPO8lU5v<pjhGYCX!!bT>vjOn@v3E&~2En%3M*;>A02l=3;j?=|jFv2*(IokqkYu+`
z?f#Sot_0GOokeN4@_t0%AeiK{n7pfbJT>4jCFQRS;-#{C!?(j16Xd+w6vSiLIVVO7
zT0|%UMkoT>Cd44_!h@@9OoxH>aKs|3a2xe<yZqHZjL=WD-gRM@<<aV&v0^Vvl-BK`
bNbKrg3mRK+IzR8P00000NkvXXu0mjfaG9N{
index f681e4ee44e4dd520759b974a7a1f6f868f30894..beef8ccea48c932571c9c9009df916a61c850a1c
GIT binary patch
literal 381
zc$@)!0fPRCP)<h;3K|Lk000e1NJLTq000mG000mO1ONa4wfZ;e00002VoOIv0RM-N
z%)bBt010qNS#tmY3ljhU3ljkVnw%H_000McNliru+zJI29sn4uetG}^0S-w-K~yNu
zb&)+w13?gmpWQt!_hI5eD#4IKO<|GNA0TLBqfH`0&_WQwe<O&XAP9<DC}<P>Cn>#B
z0z$y#_7d0P?!t27TP(BlKC{g1C~Qf5JYZ(0Y`HA=4{6~34>Y$nUyp4>0?NXx%y!n^
zPO8lU5v<pjhGYCX!!bT>vjOn@v3E&~2En%3M*;>A02l=3;j?=|jFv2*(IokqkYu+`
z?f#Sot_0GOokeN4@_t0%AeiK{n7pfbJT>4jCFQRS;-#{C!?(j16Xd+w6vSiLIVVO7
zT0|%UMkoT>Cd44_!h@@9OoxH>aKs|3a2xe<yZqHZjL=WD-gRM@<<aV&v0^Vvl-BK`
bNbKrg3mRK+IzR8P00000NkvXXu0mjfaG9N{
index 4b5551e23600acf956df706d73cab427db50b90c..08a2c25327d7df3c77186cc3048bf02b7e72f393
GIT binary patch
literal 371
zc%17D@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6n3BBRT^Rni_n+Ah<Z%{wL>4nJ
za0`PlBg3pY5<o%r5>H=O_B&jxVj>1dW-W_hU|?kNba4#PIA1#9tk+=&k=FgQ+pdT`
zUbe$HMe!GtU6WGBI$aLYZm~5FlsUCLM9rJ>x)ki1v&;2jM441q`dLYetDQYE-*|TQ
z^E<_9?^Y%rUfkJzY)ZIaD_<MC&cmBh$CtgYp8dL|p1-2*N5P)WO~<yom=<t<b<MX{
zV0F4SV~dnB5HBwOxorLKx2`PB3<(U3Mv^-!Sehqq>wl!)(o;G8S#tSeKda!GbIv?G
zbmhsbOZ!$BA5pw%wO?3d{?EV_k<*RN+E-q_-@A4@_jI3mOCvtN%FsWiAoSU(>6p5s
zu;<LjPZQOdDxY?~D4*1|{qN@6tRl%q{~C{f`Y<K**{Z}4_g5KqIsN)|hXdZr_a9ya
P3?c?kS3j3^P6<r_kMx(q
deleted file mode 100644
index db7ad5aed3ef958aa13903afa769386382a87ad3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index e0dfd04e4d3fcbaa6588c8cbb9e9065609bcb862..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
index 51848a70fe3928e0e22f65be8a70a593211c4a22..1b2df8093d630ca5e4b7c9127fd4fc855655599b
GIT binary patch
literal 9025
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
deleted file mode 100644
index a9e82db331e9dfc6e3a0d660423bbca5f31d3dcd..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
index 2c1076d467cf676d338f8437a2dd062f27108106..59b3d345f055b098a42a8a7dcabc82328559df29
GIT binary patch
literal 1291
zc$}S7Z)n_P7|->X&b7tCKFqEKv&@3B-sO_^(q7uwOD?(gpx1TRgPj&ybC>seX`8%h
zl6u#IaBid6IYF5s7RG83{j}jBL$vCIUZD<A5FBgi2iZP2HeDH3hwaMwrt4LaQNcHV
z-uHR)`#sO|K7TUR)7??M@6bLB!>S{lVhqjuooDZ3=>7C>B^gaMwv@1YVcO2hCct<F
zCIKGN<UtSvvNAsU4QRtKcUp}n>_oJSO+n2oI~Z?HGcaegwdV{uH4JP#2?kZ2BUb0G
z5V)#v#0h`Y7d1j4qjpZ1pm(A>o|+g=1r(zFdAu#hA_W?-Wjv>i=oXvfh%LP=T07e$
zfp0<VVUBp{R3h4ghoA{?zqiqo@=+AdFkY(3&oER2PWvdD^r4&aP))3#Vd-Xkdl1N)
zsifJM7~ZypB#y|~w!xBQHk<Wk8@<pRB&k3k;OL-f4?=jXaov`49^E=p)*u2aWvYg)
zLLGNxISI#Xjv&fM(2QtwN3m{g2MUFZ%*h5xd3~g&k!7@H$3S{_v=tvW02u=o95YiW
zAL%3iFtt0?0U~eMW2TCdB9DkLHKqaGj))wAzIYW?VMTu!UCk212)sm76wfm)f*=JX
zzaUaV$XC|!C~lL$&^+&#1fFT8D2Z;7T0}8G2`C#aj70NgZbY|iSx<p7SN)qS?#g9D
zCXj7t#vvRjS3pk&+R(~C0}u5w__HTeU4dEaIVU~ao&r;S87N^BYWP-sS@jY2|NGnz
zxyt{E8Ht=B|5YsIEmVQda;Nl>u+uz1M;&9L)`+u(dl=?wjfi|ax14-XDz&@o^HZ-1
z!Gh~-@Y_8_I@s`J@r!3}eOXaFmdF=Bec_Yz!t&Bm%_|#!yz$mk=Np2?jpEcfRaGzJ
z<ZH)&a#L?s_Pa(sUB$)4y<)*t_~qKgz5~HJ2v_$6Z&UkAZ1!&5hg6WnEq?l)cRhXA
zD$m~V;8n>}#ToPZ+RRY@=eFA1b8`akuU@#rCvQ#WvBv52(!%QpKMHqr9Npa9xPSlq
z3+?Zf9{f4KSS+sf4Gau)N|H3Xx&C`LfBUP7djpF5>*<4@7vHX{tv&j<Qo@GT=dWH}
zuRP6<%v^^Y$MFDw`kBL7dD1uEL?%AQ4|~1chd!toVwo!Qi7T_Svp-B$*WNu<<yvT6
z{qB70ft8gNJNSN=vR3$Y`SP7Jb8{ONXL^a7`Jcmi%#9sCck*=Rvmfi7-%~{D7B2}e
Go%{=$J;0^_
deleted file mode 100644
index 10845c695d7b832450d530702ffab9f674427618..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
index 55a9efe42f1318ada3290f56edc9214eab3d7fdd..3967cc619606b37c53d2a62478143374fe950949
GIT binary patch
literal 1188
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3m8Da#=fE;F*!T6L?J0P
zJu}Z%>HY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBXRzL%CQ%e#R
zDspr3imfVamB8j&0ofp7eI*63l9Fs&C5WRUd;=7m^NUgyO!bU)lMM_F70k@^3{6bU
z%nWrDj0_Bo^bLT>OxMuF%GAut$Xo#mlz_GsrKDK}xwt{?0`hE?GD=Dctn~HE%ggo3
zjrH=2()A53EiFN27#ZmTRp=I1=9MH?=;jqG!%T2VElw`VEGWs$&r<;L6O-~wOKg>t
zU|z^AfE$}v3=Jk=fazBx7U&!58R#P^^!3HBG&dKny0|1LH4VS&;*iRMRQ;gT;{4L0
zWMIUlDT6c@SUDG^CYIzEh2-bwz(O$~BfliSI3vG6!8zDWK_fgfFD1XcSQD(?*VoE3
zuec;JFFDoI#a0O@qL-POVrArJVs7Z>YUt!>W^QQcYUF5a?q*@?=;-EV<Y;PX=nT{A
zlAm0fo0?Yw)0=|OYlKrTC@Da6rxs<FrKY$Q<>xAZy=;|<(=9G;xZMKLn}XXd1~~QV
z10AD}7SS*vVCn%e;mH=rfhYXbJYZ@s0w(JWf#^yG21W@_7srr_TS<TZ|F>sWZRl)t
za@fe&<8X%ch>^n@=caw<9sUS(%-_Jk`E0Ir`L5kNcQ*3;a9zTfv%Bo=u1D|Q?PGY-
zI^W^gwpMQOeN3Aw8)nR9c*eMr^(EuWR5qdd#viZSc%|QIYiqB5_4;+U)81n}ti?KU
zdwzJ<)cmPY_-%ON=$QcZM&8K%b$??;6)s%9Ed2lXcm2=j=i6KU`}6bgF&4%*-qUm{
z1;oY8*_TPKzTXg0`SQ}zy9d5(l<Nq0{#Z3Z!h>%WTRlUgh+g!zHR3A@xjC9|>@YEY
zWav`%`r2Afg}&|Ezca<0W0O=c%f7ZIhMSwactQPt0pa$Tn3(_kvQ{N}y1KbW!WTN%
opYUx}*ekN!<rw4nUIs=shPl^k8~E4xfXW~SPgg&ebxsLQ0Kkoy4gdfE
index d23d84a5435ebff9e4ae226659c25feba770dd1b..ffe62936c4a8000c0154cf5616eab93e1739694d
GIT binary patch
literal 3061
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
D7gnmq
index f36bba81e041f42e3e73ecac0413da2b7c6cc90b..1fe2a8ffefc523d7366d80c5869ae440f5ac7600
GIT binary patch
literal 3066
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
IM6N<$g5|-pU;qFB
index 31d3bdb14f1d67953d18dc04e73db834aaa200f2..dd009dc4ee1c0a7f6a05041c65e917890713564e
GIT binary patch
literal 454
zc%17D@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3HQwj^(N7X~o+>AbrhNO2Z;L>4nJ
za0`PlBg3pY5<o%r5>H=O_Pfl?{3=>vdGbm?A=%83h!W@g+}zZ>60m;fqSVBa)D(sC
z%#sWRcTeAd6une-1_nkgPZ!4!i_@)BZucEl;BjF$$o&2Pf0QPpdab0p^7MB~k$xO@
zAE!3mU(J+pWusr$dY)5B>lt5MIcCgyKy?FSLfQ(|0QL=m-&@ng72O^<{$+j5Ft3I6
z0tff`IZ1y4UCczTv3y$4QXbkfr)`(`!`+?Xwg=^eR#kmF9c}Je67OJcXg71c*3{B>
zz6`p2*H}XN&Fjk5_Ha~OTF0ot6`V0ytn!n3@TY4_E(sQ`UirMs#{A>AsSK(&MRclO
zOiG_#aBtEJ<GH)v`s|8wR~6d*Ibrg)8Jsd7E~gkXD3|`5IjJrnjcxXsS)S?I86Md?
z4wTjH-n;e6O)I6un9B?JXP$Px_r7qJ$%>T>#f-C=Zm+cE{}oYE7Ja~`(){1<^FA)`
oH)jW4wbyrVy>`@B`s)8E`L7w1WVtVIQ3D01r>mdKI;Vst0AARuQ~&?~
index eb5ccb5ec3cdf7f20c344483958a2684e11e6df5..df00864932368d75024b46b3a1993d0f51f1d59a
GIT binary patch
literal 2459
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
NEC^QkdSj2I{{pqTW8DA%
index b27050e2116e305c929ab43c02e3a0c05a00df90..1e5259a97ae3b79f7ea01ced902e0c43798dbc2d
GIT binary patch
literal 244
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`yFFbTLn?0dPPXMb<RIYIJgw10
z^9{?vOJN7Ko-o}zpnXH5BjScm*`X$G?v-nDa^Be9`Niv#BKUJo>+v(^&c9yfp;>!C
z`yk7ix`lg<?*A0?5sc@Vnb^eoXtJWQ&jyzogOWC`cRbw>j&0zuYI7|}jbIT6QfUz^
z>Oks6r=eWyo;1N6*7twq{!dk?jQ_7bLpg6wvGo&O3C*=vmZ%$lnc>8deT3~wf=0%@
qjDERb)?>R2G`?iUWv@R~e($|o)93%X-@1U_VDNPHb6Mw<&;$V3Ut?_m
index 7755eee779e5ad801d274ba8184673bcba08779c..8676d8e2c2c0bac77cfce486f6f18639a8caa987
GIT binary patch
literal 512
zc$@(M0{{JqP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzqDe$SRCwBaQ%_3*Q4oKtZM6^)ZEG9U
zC8O-%O>z}Is24wg34Vg0&(Nh)A4KqyCy|cYNsu~v@z2dmB9tj1uH`lp^J3U`8~E{N
z-p=3On^hdg5sIR03L*9Y+kk-hD<6Ofzy>Vo6d1ck4*P?_;4T~v8^TAR$Zf0DN+pxY
zdoYJGiL9nW@D^3_!$~5MNL4D8YtWAX>pTG(3u?~~8-RJKR61@po0nw&j-Zf}uM`Re
z1IBnHvj;%lW(tv*fb&ZHFIX|iIJtqC9%tO<h(scNaC$&QqtQNAqnD7_;Ufs*;8(ic
z?lT-usCPP@cQ{N}M?rT2+vR{2-<WQD&E?wxJ)Oh!g;#=rE5RZbi_KwfY<<MOjquL0
zthw~_O7KHoy<S(-=`_x_qVI@RCX-QXwVKL^_D*1$=B!$+p67D83*1orNAmf+1$Sqm
zP-x~(Aom~+XPl2V9*?zRu{hK;El@6(4|QGVoM22FV%n0#X`|6tWwY5Y>0lVf5?1zr
z%n1($UyPgb4t7C5rMH$zKiPV#uKO2UXNZ0M7GMAtm#g$qt>3!<0000<MNUMnLSTaC
CqvM?b
index 63a7c320e9a981f83c3416f754e4db1a6ab504d4..31b06b5af9e548b15e274677b8ecaac1c1d06e77
GIT binary patch
literal 237
zc%17D@N?(olHy`uVBq!ia0vp^>_9BQ!2%=;I@VSLDajJoh?3y^w370~qErUQl>DSr
z1<%~X^wgl##FWaylc_d9Mg5*Gjv*Y;$q5RA21W%&988AFF7neS9({Y$O^hc-fzNvT
zy{kX}UyqMIu=e<Ya|aX(*1Y_`>3{csed~)S6b>9XaCpJd2PXwsj@)uEyTHN9Cd}ro
z5XP`c@(2I(zwen39<Jp1<8V~R?6=qd>2I~4ZeZ0+OPe6@{r)uVcjpxtQ<xdGn^l_C
l1U4U<bN<W$wuuM%8Gh`M-xS!`BnfmHgQu&X%Q~loCIF<8Tc-d3
index e139f3017d6379d324fcdab5e850fc9bd80928ff..fc7023f2aafcdbb3b2412934c017225637c8bb9e
GIT binary patch
literal 417
zc$@*D0bc%zP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0004KNkl<Zc-p1X
zJxjwt7zgl^F4m=@tI(yT7>Y`u@r0Pg5(gItKS4o}g1A}g%jhT};$T7OAPy;H>flra
z2St?bnbSZL$Y+TEgF85m2n7#*aQD1j5<>Dk{}-_qVGT5BavG17$sDU1MbRrJ{zyK9
zAb6?OYC6B5c=6<(=Xqa_<9rLQ>rQ>&pH3!|N91>*sXm<;Tn)o;j2qwn@D3lU*=#mu
zy+CvXM(`|4({yNA*0pWh{VdCdY92<c7YN1SNfyWPfKqyj+y-o#rrAxBWT4iuULZR-
zJP7!h_qwhhBVLCxS8ugiCoCt|vR*OZPB0AP60tU{!UDthZ9LVLTq_T_l{nzCTgA`9
z_bxbctvujHg}5ONFp6sA0T(L7P3aZPq8c$^8;5gMqtWOfx5a3h)+wrCy+GFSx1Ax-
zRrH|G_0&A;VZA_BfWjdhF?@djHth4gny0*%lwb)euso*<?<xHPHO1-}!pO`$00000
LNkvXXu0mjf?Gd_1
index 9ba3667e94986235e8a27dff14d6a70f26e49193..c0051f8f040826d06f38468fcc4d657cfc69e880
GIT binary patch
literal 558
zc$@()0@3}6P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00001b5ch_0Itp)
z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iye$
z03Zn`nXL%`00FK^L_t(I%YBngi_=gPhMzl$*;sW%`~VAs{ROTol+ur1(dlx2L`zCZ
zZM*8KYj@SXxDX+Qgia}SrHfe%cH_3FIHNPPNhY~&ZX^xq96021Z{Fu}-n<cHmj>Jg
z4%Jgr`vGtXTmT**_lcibmUXgPt=@T__en}=$Gu!GUz?`+0yx-nIS)+JJc**{qm=T4
zl=6Mti^bv%@Cvve1N02Qqei1q6hd65560v1Iq)602BLj{!$P58sCjqFah!AD7ZApK
zSpdT@j38^a^?H4&%;PqI0Q^1v+@zh?0YiPRhrk`+D1A$!j)1>vyx+iu0PfkgeO#;6
zUM60=+5^bNi|KUwwO+5k)c}1mnRvNe?n$v&ya6`Kq^#Zmo6%_Wv)OFAzz<CwY;D`#
z>bm~CR4PTc0K$I1AGBJn8So9b(v&G4@W*kSjSwPVE|)XKmSsiVZub;8Q*n;sjQ@wY
zuDcDxFkh)uf~2_9>4;vhw@8Xf{3JV&*=*+fzMrpFs{s(T+iiU~9DYuV(|{ewd_E7P
wl#gB4m4m_HOO`keO;#PKY&?xam?Z}I2j`s8psXhcZU6uP07*qoM6N<$g6Zn_c>n+a
index 272a3ca8351f251e8e9c6179b5d0fc5496f3a5c7..762ac43e08cf71f688136dd9c391e1eeac8336b6
GIT binary patch
literal 353
zc$@)Y0iOPeP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0003fNkl<Zc-oDU
zu}Z{16h&tv$Rem<VFW?YW?8V>N)i16KOjF~A%cy9L}N?{*aRypMbKt#Y{Wu@^dWzc
zB43gw@m?5VSf4XKI1uvgxkJb(Jp(WVYhVPnHDj;=mcX2{j2A`GW>r;L-}l82ZQFh|
zO*2i?^oZrQ5>KD9SC-`y<adLQuIoN=085sYW!SzR1i?9^w^{1Ce#U-FIcDhl{vm|d
zS@1bi>?f{*0oaG|B7xlwaLz8mj}qKT!aP_teqVs_y##kUGoqtiwOACzF#-<;cM@iX
z4qc!Yz$DM}D=cpR1G99rt30p*4zet}M&QN<Gt6oSF2*cLlH?M>P=Y&2{#AlocLCwd
zgzqHz&yp|<c_U8=pC#E@636igvB=JnF|o<tj|Wxfd89a300000NkvXXu0mjfHK~&F
index da02bc69f7aab143771a3d6373b1c547605d0798..0d49d8e95e3fd732dfbfc16a12998f20ac337a4d
GIT binary patch
literal 426
zc$@*M0agBqP)<h;3K|Lk000e1NJLTq000mG000mO1ONa4wfZ;e00001b5ch_0Itp)
z=>Px#0%A)?L;(MXkIcUS000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iye$03R;e
zO)_2p00AyZL_t(2&sC8<OT$nUhM$|1inT=~h!hh`Q$Lnght94Fx^+}q3L=Pq#=lS$
z-LzdC6#M}WUBt-`q*}#AC}?7uuR6q#+k2PGd7caJIY%I$G#S9gO-f=68<$PkZt<2V
zs*KMLYvrZ<ih2HkMKCU;F-{M5O1StHZP~ndj1@J;C;Pi5LqbCQinds6KShcf;p4sf
z0uI6d^;Ty}X8Re7KqZaQYBuI291!5GO&8713zi^v)!Zn{jU}<K?>Ae53_1mJ6h^w#
zeV-oR^ysH>c;yp?Dznn>JGz9pxG6#$9N?FsB-jk1M=BneHkstGh{u!&Q|tLe=n5=Z
z5KK_0&*4R-kRyw)SWp1b(Aw3Shlls$->_wOZsP>eHWjky7-SLn4EW$3n^7eE0S7l~
UzTz2Va{vGU07*qoM6N<$f~2;q$p8QV
index a4d6c8ea7512a65aa46bc8dfa2eadf0d84911837..3155b8bd235c642f7f495ed8cff2900069162cfd
GIT binary patch
literal 344
zc$@)P0jK_nP)<h;3K|Lk000e1NJLTq000mG000mO1ONa4wfZ;e0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUy`bk7VR47w*&pk`SU=)VoyAfVOr6J%V
zIKGg<k5$k~2&HSNjv|6C6&fgYadHTRLdoP*mxh*P36iB93NHR8UFEo>CdBw$>ph$U
z)hTRj6#q=2*TFhKHzx|6MzWGs8Z{*folGT{Oft!nX+2Ts<wP<`3)yl~O%!?&N+NMZ
zvIw_{LdSv3<+WxW7w2|1Lz&4-gV|<C2iiDv=`)h3#E3p!9NJ)DVqxP-Si;4|!o(;)
zIg{rS=lt2}*OUC(bJ?i}M<0(e-tw-o>cPHu_w7sJZOjQKt!iL$+`E7GKObZu1M&0Q
qn}h0!&|(*d3p}p4q{kr^2K)fvg`AtvZ>v!N0000<MNUMnLSTXmnUQ(`
index 2bd1c1dfe84330ee65430f38f73abee8eb2bb72a..fa730955054b440a9e32ce282a3361cf13f198fa
GIT binary patch
literal 491
zc$@+20Tlj;P)<h;3K|Lk000e1NJLTq000mG000mO1ONa4wfZ;e0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzjY&j7R47wLQB5yHK@>gp@kF&{Rb5bN
zGzijG&{UKVshtpNClNu)%Ekhbw2`1J>Z6HtgGN0xKEhh;{0EDsrSU_qGw%`SWF~jc
zxpQak3{VFTy2*App+P}o)NW`Vy70=Y$@eYTjRgDq)}ID15R?~1J&mx+C#(qTX;VcI
z7?3B$uiL;R>R}-rT@%F{Q^f$#FZUOjQcfPeZ$<}E18p$$rORXa`Z6Q;=m%OKw=v~i
zDrMy^zYYg%xi!g`vmMKrqSFdWO=yItW9DoVJ*XuE>5afFEf*aJP=P8AjY%zNU{t}`
z&6S2q!}*1UI~}}%g2r}h|1FKpX|M(R^hMUF<}P<`VJOHX(}C-46~4}~;<03|R$zne
zd{Hvx6aP5;bX<T>PIK`>N>asx-f>p5`o;?TlKMQ-6LJb45R#;%<gl>UHjic=P>Ck@
z+{d0AQcWVHUUFA4oxlhWu<(*~7(R)cs(MMk>=;Zw$5hvZ{W->}h6+FUwIhgP8WFVd
hn-r{!B2=PuoIg4=n|)8MY<2(u002ovPDHLkV1hfJ)Vlxx
index ccc62089faef81a6390f53ccbc2ade2ca52a4b1b..fef84dd594937207a6e7bda8bb19f910033cea25
GIT binary patch
literal 474
zc$@*+0VV#4P)<h;3K|Lk000e1NJLTq000sI000mO1ONa4u@C3h0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzd`Uz>R2Ufr!B0z*aR30|=ePH_&CN9b
zGN^_S5((O&!lLLBgeMOj6rwNSAv$&FSRbGusH=zQ0~B<K&KX8{G=m~Y%9P46%}w8J
z@7wbPK-tL5iAo88M*GVz4Jkyx`0Bmcv+XqGKpv{aw`+4xZ9@cw$y2iv*WRpb=mAO#
z=aw%RvkeiHd*iKxm33=+fbz#uGHp~*hXNRVa$VQHhNh;brrp@8WXp3#pdcEnou41h
zJBp%2B9SO&CFx?#v|&j!^k`w}qSi5svm1q^3v|jiW~BXL@7Ck`gIA$6(^#r@<){b%
z=s7~za`IWMk5&HxjsO5)AQ*_9L`q2C$16ud-Uk4X6JyAv<O5py5cUB81X<kL`<;&S
zw=HQOAPYdhJg;CYIE<a0JG&1Di{V@0d3dp@4XE6nxSO5MeuVow{sa|uQ&-Qt>`t^>
zpB)1Fs#D*~H_PunS@$ytit4NLmr{cOfV~gJ%dc(f25{V@8oB_8*zr}9|K~7)w!vn|
QtpET307*qoM6N<$g4lo5;s5{u
index e52370e68dcaa9fd75a8764505d617d1cc8b2689..604e652e5ec48052efa7b342c41c33729dbd287c
GIT binary patch
literal 503
zc$@+E0SNwyP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0005LNkl<Zc-obb
zy-Px27{$$?$UZCyA`$~HWJC>7L`x76v;_%@mM9iB^r1sVf!&a+LRUjYsGy;SXlXDS
zqS4Xa%|ApGMeLk-iHe)y13!4)=bZC?+^cI*oxlhzV3LU5D72Q<MRPnJ-!GL)kJW1R
zov`PO8a=H}9?#`+$!4?p242AnVb2*gdj7h}U?dVbV4z;FKgVLRw8diCHJi-=_MB0p
zhhD7>ti@vS4yLDQG<t>g5*Q=w6NyBM8a-G`S{uxk%jE}{?yXkqCe|j<DHz6ViyA%j
zYHctN@fxOENs>0OHhj|zoKb`4hF+}=rVE9F3R6Z^Rhdr$-2y3-$y`vQ2kR-VKQN;x
z3QcOQR^uk8Hk)mQu*WP-&F}XI;T`=Q9`X5ne*E)Gm=u8uQbhDhGMNm+I|q7xguPy`
zr&6iJU^;I!8e!bzJfF{p@!n6^yWQ?Xco)GC==chIJf1CtWrR-<K6W~tN0_gHRj@8t
z1~xDN^g2;}fk0p#;WLCo2nQVwM@W2O6Lnw|^nxyNvM89c+3YsL`v~vZ?e;_QzJ6i+
tw+vuGmgQZS%eB*Pn57q2od8n1;SVuD34zFH^ql|z002ovPDHLkV1l!1+}HpB
index 145316b8345d08154a776009b3e0e548f8f72fca..97930244ced83a11e12fbce30c9565d124cbbb88
GIT binary patch
literal 1221
zc$@*n1UmbPP)<h;3K|Lk000e1NJLTq000mG000mO1ONa4wfZ;e00009a7bBm000XU
z000XU0RWnu7ytkR8)-vBP*7-ZbZ>KLZ*U+<Lqi~Na&Km7Y-Iodc-muNV4mRU;^fLC
zz`#&YR8r&~<QN$d8KuB}o`H>lnSp_Ufq@}0xwybFAi#%#fq@|}KQEO56)-X|e7nZL
z$iTqBa9P*U#mSX{G{Bl%P*lRez;J+pfx##xwK$o9f#C}S14DXwNkIt%17i#W1A|CX
zc0maP17iUL1A|C*NRTrF17iyV0~1e4YDEbH0|SF|enDkXW_m`6f}y3QrGjHhep0GJ
zaAk2xYHqQDXI^rCQ9*uDVo7QW0|Nup4h9AW240u^5(W3f%sd4{Q&k2kgNVo|1qcff
zJ_s=cNG>fZg9jx8g8+jTgC9dB!zzXcjM9uzjPn?uG8r;8FkNESU~Xi-%VNVakCmA<
zoAoN26Wb<s7514N0vw&3tenkU%v^2U+}sm+q<EI{8uK3F3+8*qUo9Xcuv*Yf@R3lX
zu%hr`k#tdB(XC=};+*1JB~m1XC67u~Nb5>Jk(nbKDkms+R=!8UN0C?Yg3=V_C>14@
z*Q#698rA(YWHsJu?$es6ovLH4E2R5M?}+|<gBrsqBTHjR<KHItOb?r_Fz>ghuuQb_
zv9_>LwH2{rvHNQO+~Kz41*c=qdtJ7=u6JAMzSLup=R&Uq-V1#e`!4fa<-a~)YvA6X
zW5MS`ZiPMz`x3zvDHx>`Z5-nk8x@xq-;yvpadXny<mahOX>#c{8Bv*4S+lbD<lM_+
z%2zM&DJ(9UU3|FYZJ9*5OGRPjysER+e{1#X;_D|h9BcgDY|xV4I<M_|hhV37S9|y2
zUWPvV{<;bKCjOu7IHh&!iRrvEf@jW}^=OXP+>&|w7H};LTeNub$E6O-CM<ur(s)(t
z>YHnI*EOxbxzS)#$L0rHt+q|w{$Z!@u2p+D_NMPUen9<T=b_g}{EluuE`Fl+<df6h
zXSSS^J>P!e)1|n}r><IDTXsYAX6vo5chc|Pyzleiz$4SgtDh=9oB2ZUW!G!wH+64+
zzAydo=~KbycVF|qz59{>^TY4rKi~dU{r?XDE({%upgajN0000WV@Og>004R=004l4
z008;_004mL004C`008P>0026e000+nl3&F}0003bNkl<Zc-o}VFH8b)7{>AMamR0*
zfT)4tu+Y?idNU9N-Kb)8vsht9gN|r3VU*^-qRHk=Y>YYCoJX-3D2%x|gU%qx9sCRj
z2T6l(`fN{l-#xD)`F%Wp<S4HEgz?kigLlM;2eCIH>#{EE<^kamk2xy>`a<W7HtoX)
zqw1S;UBUtgOs>c$S(CNBQ_>S_j`vSU-~|ZItjb4OmDOC4R5b0{Km#Bdm-n(P%bP`v
zgyDJ-)j3YHRXzbiP2ReZp&<!?+Wam|<)^VTF`-^O7xa7tI};OHsnKXfdp#5&q-VdD
z0dZ8>z4dLhmioTp70W4VT+3Q<KpdMpH`=;2-}faigC>KXTz3`_mAllnXWRApXw_Tz
ju&H4phF1Rl&7T1Pf`NpK<<{xM00000NkvXXu0mjf-Y_+(
index 02ed6c62ad8a22fc28d1c689a75bdff3b57bcc31..ddd8a8710be0004a0b5354278b995bc71da06542
GIT binary patch
literal 302
zc$@()0nz@6P)<h;3K|Lk000e1NJLTq000mG000mO1ONa4wfZ;e0002>Nkl<ZcmZRe
z0$^njV^CwzVNhh?Mq$GN*SW_3cR`TVf<X+4&5ba@zJ102t3Y^@!=Awt#^$tQ;6W&{
zD4+lTJP=+HaA0sQTL57T+8~s$Fc@Xb_<sTj&q_Np*umH`_6)p?P$kR^x?veBHGwQP
z%j^>jVQCPyT{?>`SpF~r!)yL042nSJkH5?eFJSCH%nX)52(&_~HTVDa{~P~r<gH@R
zg0ssR1R;);=_~%f;s2`tt2indv|(({G6sH#wEVR4|11A5{=b-|l0g^FE@j|@2GpSp
zpupV!bD2sR#F5y%h)^(R$Y97}NMYbcVN(qN0FGsWNDIB@Hvj+t07*qoM6N<$g0G;2
ASpWb4
index c308668b12c8304b567247622443d9b789f9acc5..d9946fd0ad71eeb0f31ff269b48cbcb6bb36a7f9
GIT binary patch
literal 1193
zc$@*L1XlZrP)<h;3K|Lk000e1NJLTq000mG000mO1ONa4wfZ;e00009a7bBm000XU
z000XU0RWnu7ytkR8)-vBP*7-ZbZ>KLZ*U+<Lqi~Na&Km7Y-Iodc-muNV4mRU;^fLC
zz`#&YR8r&~<QN$d8KuB}o`H>lnSp_Ufq@}0xwybFAi#%#fq@|}KQEO56)-X|e7nZL
z$iTqBa9P*U#mSX{G{Bl%P*lRez;J+pfx##xwK$o9f#C}S14DXwNkIt%17i#W1A|CX
zc0maP17iUL1A|C*NRTrF17iyV0~1e4YDEbH0|SF|enDkXW_m`6f}y3QrGjHhep0GJ
zaAk2xYHqQDXI^rCQ9*uDVo7QW0|Nup4h9AW240u^5(W3f%sd4{Q&k2kgNVo|1qcff
zJ_s=cNG>fZg9jx8g8+jTgC9dB!zzXcjM9uzjPn?uG8r;8FkNESU~Xi-%VNVakCmA<
zoAoN26Wb<s7514N0vw&3tenkU%v^2U+}sm+q<EI{8uK3F3+8*qUo9Xcuv*Yf@R3lX
zu%hr`k#tdB(XC=};+*1JB~m1XC67u~Nb5>Jk(nbKDkms+R=!8UN0C?Yg3=V_C>14@
z*Q#698rA(YWHsJu?$es6ovLH4E2R5M?}+|<gBrsqBTHjR<KHItOb?r_Fz>ghuuQb_
zv9_>LwH2{rvHNQO+~Kz41*c=qdtJ7=u6JAMzSLup=R&Uq-V1#e`!4fa<-a~)YvA6X
zW5MS`ZiPMz`x3zvDHx>`Z5-nk8x@xq-;yvpadXny<mahOX>#c{8Bv*4S+lbD<lM_+
z%2zM&DJ(9UU3|FYZJ9*5OGRPjysER+e{1#X;_D|h9BcgDY|xV4I<M_|hhV37S9|y2
zUWPvV{<;bKCjOu7IHh&!iRrvEf@jW}^=OXP+>&|w7H};LTeNub$E6O-CM<ur(s)(t
z>YHnI*EOxbxzS)#$L0rHt+q|w{$Z!@u2p+D_NMPUen9<T=b_g}{EluuE`Fl+<df6h
zXSSS^J>P!e)1|n}r><IDTXsYAX6vo5chc|Pyzleiz$4SgtDh=9oB2ZUW!G!wH+64+
zzAydo=~KbycVF|qz59{>^TY4rKi~dU{r?XDE({%upgajN0000WV@Og>004R=004l4
z008;_004mL004C`008P>0026e000+nl3&F}00039Nkl<Zc-oYaJxjw-6o#LqmmnIl
zR7o95!PHG~5En-s1fheYKgCIK@t61yD%7Q;2#$`mgIkOBqp^PEp4%ITG-_-X-{rtL
z5AS;pN3p;%0WR~h#EcZ--C49ksrnDiV?{Occ`FAZpQ^$mfmW}5ivUnhcaGdJ4pvWJ
z0Z-u|(7xgt1HcyB&Hmy2`8svLQGf=Xc_ank9qoT^jyo|LAP4Mh44|i`BA6c_`LkOh
z1`(6>bBEv3)?%#vhr=A81<_KB@NlttgqeQWiBq^@f8%m8b84V_;YqTz#vlVM0-b<^
z?}+imA`PApz$)Tyx@&kTY%$78w?eEK?%hyBmHf&uVE8ovdK7W}hb}fj00000NkvXX
Hu0mjfdG#Sg
index be9eceba944be98da1cbd80b54fc015de46b6f86..5a937c712b054defb99910aa8884e5a8e426f26e
GIT binary patch
literal 349
zc%17D@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6BuiW)N`mv#O3D+9QW+dm@{>{(
zJaZG%Q-e|yQz{EjrrH1%{r7Zn43UszJ!tC}5-7oN;q!xH1;GqArn>^|FHPP#a!Xx%
zV3)ICNs{aokqa{eqB0qEBO+h8F#Skq_-!nHp7Zp*h|LTP4a>@9&DQZ9d(FUb;QapE
z@rMfbB(X6t^n~*qc1X(K`rkIzI_s|a{sXJ;epeUfaawL*{lBKt#;EKed&lMK=od^g
z6aPQFe?9%?V(SY#rz%be6hFP^6hoYeBvWV5)F4%c2?`T3eRF-;7?1=`xSn)nV&G(&
z+5T?j)tx*E2OZiRo_)Rj_vX_!b>;5~na}6)EYy^_C$Vskj}OCD9^EhLZy(>0eIUhf
o&PjgR{C&4Y7#LRkoAHmG<wSvib=kXxz@T98boFyt=akR{0QSR*^Z)<=
index 21ceb3b165cc73de106009f21c8233fda247735b..d57a12c5d5b6d5eb9850d7d585bc5bf2c53c80eb
GIT binary patch
literal 3036
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
index 9b2e2f5be21be969516530f04a10a9c97659b527..cb3967b7f3c54c6d9da7d92ea6740622c872913a
GIT binary patch
literal 300
zc$@(&0n`48P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0002<Nkl<Zc-pPg
zu?m7v6b9f6Ek#kZ6orcrL>L7HL7NZJOXS)XL_>Q+(9#k#HnsNx;vx<zhzLH3{Ra+m
z!OA;$;DZDAfS%v0K-FPDxNm|E(-Jz*3N2032caHDS(d$3&@2c&ilTcQ$9L+%z~M^;
z&4TE{f^gph6E-DGp5>i^`wkeeE@AMj(2^v%5-EeHiadiL2+m;`o}~<KDk{sM1`Wb}
z3q~-8J`7?0JA-0r_^c-)Wpeq3A5<vab=|$^d3!07<2U>kg;LFgGbsKGZJ59kX1xFE
y?>+E+e@CR94=VC|VB5CkIF2Rlyj4-jJ@^0&o=tDjU66bL0000<MNUMnLSTZ{hI>;0
index d71dd27711f6e100a15309a5831e491bbace64d4..3a27f043939942d23aa6cb9992c35a6b526c449f
GIT binary patch
literal 211
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`vpiiKLn>}9y|j>vDNv;4;bmU4
z-%Yu!vp3|*ADX@)!bk1?!3?8Foih1%R?L&9HST<HNS^P$XLa7g=!J}L#dtS8*_yky
zHg*f&dgiwN?rRTC6DxLST-^Gh=;EU6hc6eER=hQ|i2=&;&bnB5QO7$j+hkGZMUU=v
z*7sw#yx8^mtZVnW{WYZ^#g7)bUO#jb$hV#!v*p46{mt@$v&77=+3mdzbR~nQtDnm{
Hr-UW|)xcdC
index 7991ee7a50703401c00aee71297564cd4755c481..810fbf9895d5b2de15177d60612d5fab2087010b
GIT binary patch
literal 143
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`VV*9IAr-gYUfRgXpvdD8$Zf5=
z=1uGCcWnh6*Nc?ePuKo-VA18ZxzrMWwDZI?X$#2&CN4W?#|upS)oW&Kk9v^$UG#Gp
qcS?wfv+Fe`Il+?x58o@x^8E4lp0QHyUg`s&4Gf;HelF{r5}E)Kcrc&<
--- a/browser/extensions/pdfjs/content/web/viewer.css
+++ b/browser/extensions/pdfjs/content/web/viewer.css
@@ -15,17 +15,17 @@
 
 * {
   padding: 0;
   margin: 0;
 }
 
 html {
   height: 100%;
-  /* Font size is needed to make the activity bar the correct size. */
+  /* Font size is needed to make the activity bar the corect size. */
   font-size: 10px;
 }
 
 body {
   height: 100%;
   background-color: #404040;
   background-image: url(images/texture.png);
 }
@@ -42,27 +42,29 @@ select {
 }
 [hidden] {
   display: none !important;
 }
 
 #viewerContainer:-moz-full-screen {
   top: 0px;
   border-top: 2px solid transparent;
-  background-color: #000;
+  background-color: #404040;
+  background-image: url(images/texture.png);
   width: 100%;
   height: 100%;
   overflow: hidden;
   cursor: none;
 }
 
 #viewerContainer:fullscreen {
   top: 0px;
   border-top: 2px solid transparent;
-  background-color: #000;
+  background-color: #404040;
+  background-image: url(images/texture.png);
   width: 100%;
   height: 100%;
   overflow: hidden;
   cursor: none;
 }
 
 :-moz-full-screen .page {
   margin-bottom: 100%;
@@ -175,42 +177,37 @@ html[dir='rtl'] #outerContainer.sidebarO
 }
 
 #sidebarContent {
   top: 32px;
   bottom: 0;
   overflow: auto;
   position: absolute;
   width: 200px;
+
   background-color: hsla(0,0%,0%,.1);
+  box-shadow: inset -1px 0 0 hsla(0,0%,0%,.25);
 }
 html[dir='ltr'] #sidebarContent {
   left: 0;
-  box-shadow: inset -1px 0 0 hsla(0,0%,0%,.25);
 }
 html[dir='rtl'] #sidebarContent {
   right: 0;
-  box-shadow: inset 1px 0 0 hsla(0,0%,0%,.25);
 }
 
 #viewerContainer {
   overflow: auto;
+  box-shadow: inset 1px 0 0 hsla(0,0%,100%,.05);
   position: absolute;
   top: 32px;
   right: 0;
   bottom: 0;
   left: 0;
   outline: none;
 }
-html[dir='ltr'] #viewerContainer {
-  box-shadow: inset 1px 0 0 hsla(0,0%,100%,.05);
-}
-html[dir='rtl'] #viewerContainer {
-  box-shadow: inset -1px 0 0 hsla(0,0%,100%,.05);
-}
 
 .toolbar {
   position: relative;
   left: 0;
   right: 0;
   z-index: 9999;
   cursor: default;
 }
@@ -220,51 +217,35 @@ html[dir='rtl'] #viewerContainer {
 }
 
 #toolbarSidebar {
   width: 200px;
   height: 32px;
   background-color: #424242; /* fallback */
   background-image: url(images/texture.png),
                     linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
-}
-html[dir='ltr'] #toolbarSidebar {
   box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.25),
+
               inset 0 -1px 0 hsla(0,0%,100%,.05),
               0 1px 0 hsla(0,0%,0%,.15),
               0 0 1px hsla(0,0%,0%,.1);
 }
-html[dir='rtl'] #toolbarSidebar {
-  box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.25),
-              inset 0 1px 0 hsla(0,0%,100%,.05),
-              0 1px 0 hsla(0,0%,0%,.15),
-              0 0 1px hsla(0,0%,0%,.1);
-}
 
 #toolbarContainer, .findbar, .secondaryToolbar {
   position: relative;
   height: 32px;
   background-color: #474747; /* fallback */
   background-image: url(images/texture.png),
                     linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
-}
-html[dir='ltr'] #toolbarContainer, .findbar, .secondaryToolbar {
   box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08),
               inset 0 1px 1px hsla(0,0%,0%,.15),
               inset 0 -1px 0 hsla(0,0%,100%,.05),
               0 1px 0 hsla(0,0%,0%,.15),
               0 1px 1px hsla(0,0%,0%,.1);
 }
-html[dir='rtl'] #toolbarContainer, .findbar, .secondaryToolbar {
-  box-shadow: inset -1px 0 0 hsla(0,0%,100%,.08),
-              inset 0 1px 1px hsla(0,0%,0%,.15),
-              inset 0 -1px 0 hsla(0,0%,100%,.05),
-              0 1px 0 hsla(0,0%,0%,.15),
-              0 1px 1px hsla(0,0%,0%,.1);
-}
 
 #toolbarViewer {
   height: 32px;
 }
 
 #loadingBar {
   position: relative;
   width: 100%;
@@ -516,17 +497,17 @@ html[dir='rtl'] .splitToolbarButton > .t
   transition-property: background-color, border-color, box-shadow;
   transition-duration: 150ms;
   transition-timing-function: ease;
 
 }
 .splitToolbarButton > .toolbarButton:hover,
 .splitToolbarButton > .toolbarButton:focus,
 .dropdownToolbarButton:hover,
-.overlayButton:hover,
+.promptButton:hover,
 .toolbarButton.textButton:hover,
 .toolbarButton.textButton:focus {
   background-color: hsla(0,0%,0%,.2);
   box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
               0 0 1px hsla(0,0%,100%,.15) inset,
               0 0 1px hsla(0,0%,0%,.05);
   z-index: 199;
 }
@@ -570,17 +551,17 @@ html[dir='rtl'] .splitToolbarButtonSepar
   box-shadow: 0 0 0 1px hsla(0,0%,100%,.03);
   transition-property: padding;
   transition-duration: 10ms;
   transition-timing-function: ease;
 }
 
 .toolbarButton,
 .dropdownToolbarButton,
-.overlayButton,
+.promptButton,
 .secondaryToolbarButton {
   min-width: 16px;
   padding: 2px 6px 0;
   border: 1px solid transparent;
   border-radius: 2px;
   color: hsla(0,0%,100%,.8);
   font-size: 12px;
   line-height: 14px;
@@ -588,44 +569,44 @@ html[dir='rtl'] .splitToolbarButtonSepar
   /* Opera does not support user-select, use <... unselectable="on"> instead */
   cursor: default;
   transition-property: background-color, border-color, box-shadow;
   transition-duration: 150ms;
   transition-timing-function: ease;
 }
 
 html[dir='ltr'] .toolbarButton,
-html[dir='ltr'] .overlayButton,
+html[dir='ltr'] .promptButton,
 html[dir='ltr'] .dropdownToolbarButton {
   margin: 3px 2px 4px 0;
 }
 html[dir='rtl'] .toolbarButton,
-html[dir='rtl'] .overlayButton,
+html[dir='rtl'] .promptButton,
 html[dir='rtl'] .dropdownToolbarButton {
   margin: 3px 0 4px 2px;
 }
 
 .toolbarButton:hover,
 .toolbarButton:focus,
 .dropdownToolbarButton,
-.overlayButton,
+.promptButton,
 .secondaryToolbarButton:hover,
 .secondaryToolbarButton:focus {
   background-color: hsla(0,0%,0%,.12);
   background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
   background-clip: padding-box;
   border: 1px solid hsla(0,0%,0%,.35);
   border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
   box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
               0 0 1px hsla(0,0%,100%,.15) inset,
               0 1px 0 hsla(0,0%,100%,.05);
 }
 
 .toolbarButton:hover:active,
-.overlayButton:hover:active,
+.promptButton:hover:active,
 .dropdownToolbarButton:hover:active,
 .secondaryToolbarButton:hover:active {
   background-color: hsla(0,0%,0%,.2);
   background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
   border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.4) hsla(0,0%,0%,.45);
   box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
               0 0 1px hsla(0,0%,0%,.2) inset,
               0 1px 0 hsla(0,0%,100%,.05);
@@ -682,17 +663,17 @@ html[dir='rtl'] .dropdownToolbarButton {
   border: none;
   background: rgba(0,0,0,0); /* Opera does not support 'transparent' <select> background */
 }
 
 .dropdownToolbarButton > select > option {
   background: hsl(0,0%,24%);
 }
 
-.overlayButton {
+.promptButton {
   margin: 3px 2px 4px 5px !important;
   line-height: 16px;
   padding: 2px 6px 3px 6px;
 }
 
 #customScaleOption {
   display: none;
 }
@@ -914,24 +895,16 @@ html[dir="rtl"] .secondaryToolbarButton 
 .secondaryToolbarButton.rotateCcw::before {
   content: url(images/secondaryToolbarButton-rotateCcw.png);
 }
 
 .secondaryToolbarButton.rotateCw::before {
   content: url(images/secondaryToolbarButton-rotateCw.png);
 }
 
-.secondaryToolbarButton.handTool::before {
-  content: url(images/secondaryToolbarButton-handTool.png);
-}
-
-.secondaryToolbarButton.documentProperties::before {
-  content: url(images/secondaryToolbarButton-documentProperties.png);
-}
-
 .verticalToolbarSeparator {
   display: block;
   padding: 8px 0;
   margin: 8px 4px;
   width: 1px;
   background-color: hsla(0,0%,0%,.5);
   box-shadow: 0 0 0 1px hsla(0,0%,100%,.08);
 }
@@ -1138,16 +1111,32 @@ html[dir='rtl'] .outlineItem > a {
 
 .noResults {
   font-size: 12px;
   color: hsla(0,0%,100%,.8);
   font-style: italic;
   cursor: default;
 }
 
+#findScrollView {
+  position: absolute;
+  top: 10px;
+  bottom: 10px;
+  left: 10px;
+  width: 280px;
+}
+
+#sidebarControls {
+  position:absolute;
+  width: 180px;
+  height: 32px;
+  left: 15px;
+  bottom: 35px;
+}
+
 .canvasWrapper {
   overflow: hidden;
 }
 
 canvas {
   margin: 0;
   display: block;
 }
@@ -1341,95 +1330,24 @@ canvas {
   width: 200px;
 }
 
 .prompt .toolbarField:hover,
 .prompt .toolbarField:focus {
   border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
 }
 
-#documentPropertiesContainer {
-  display: table-cell;
-  vertical-align: middle;
-  text-align: center;
-}
-
-#documentPropertiesContainer > * {
-  display: inline-block;
-  padding: 15px;
-  border-spacing: 4px;
-  max-width: 350px;
-  max-height: 350px;
-  color: hsl(0,0%,85%);
-  font-size: 12px;
-  line-height: 14px;
-  text-align: left;
-  cursor: default;
-  background-color: #474747; /* fallback */
-  background-image: url(images/texture.png),
-                    linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
-  box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08),
-              inset 0 1px 1px hsla(0,0%,0%,.15),
-              inset 0 -1px 0 hsla(0,0%,100%,.05),
-              0 1px 0 hsla(0,0%,0%,.15),
-              0 1px 1px hsla(0,0%,0%,.1);
-}
-
-#documentPropertiesContainer .separator {
-  display: block; 
-  margin: 4px 0 4px 0;
-  height: 1px;
-  width: 100%;
-  background-color: hsla(0,0%,0%,.5);
-  box-shadow: 0 0 0 1px hsla(0,0%,100%,.08);
-}
-
-#documentPropertiesContainer .row {
-  display: table-row;
-}
-
-html[dir='ltr'] #documentPropertiesContainer .row > * {
-  display: table-cell;
-  min-width: 100px;
-}
-
-html[dir='rtl'] #documentPropertiesContainer .row > * {
-  display: table-cell;
-  min-width: 100px;
-  text-align: right;
-}
-
-#documentPropertiesContainer .row span {
-  width: 125px;
-  word-wrap: break-word;
-}
-
-#documentPropertiesContainer .row p {
-  max-width: 225px;
-  word-wrap: break-word;
-}
-
-#documentPropertiesContainer .buttonRow {
-  margin-top: 10px;
-  text-align: center;
-  vertical-align: middle;
-}
-
 .clearBoth {
   clear: both;
 }
 
 .fileInput {
   background: white;
   color: black;
   margin-top: 5px;
-  visibility: hidden;
-  position: fixed;
-  right: 0;
-  top: 0;
 }
 
 #PDFBug {
   background: none repeat scroll 0 0 white;
   border: 1px solid #666666;
   position: fixed;
   top: 32px;
   right: 0;
@@ -1481,40 +1399,16 @@ html[dir='rtl'] #documentPropertiesConta
   color: black;
 }
 
 #viewer.textLayer-shadow .textLayer > div {
   background-color: rgba(255,255,255, .6);
   color: black;
 }
 
-.grab-to-pan-grab * {
-  cursor: url("images/grab.cur"), move !important;
-  cursor: -moz-grab !important;
-  cursor: grab !important;
-}
-.grab-to-pan-grabbing,
-.grab-to-pan-grabbing * {
-  cursor: url("images/grabbing.cur"), move !important;
-  cursor: -moz-grabbing !important;
-  cursor: grabbing !important;
-}
-.grab-to-pan-grab input,
-.grab-to-pan-grab textarea,
-.grab-to-pan-grab button,
-.grab-to-pan-grab button *,
-.grab-to-pan-grab select,
-.grab-to-pan-grab option {
-  cursor: auto !important;
-}
-.grab-to-pan-grab a[href],
-.grab-to-pan-grab a[href] * {
-  cursor: pointer !important;
-}
-
 @page {
   margin: 0;
 }
 
 #printContainer {
   display: none;
 }
 
--- a/browser/extensions/pdfjs/content/web/viewer.html
+++ b/browser/extensions/pdfjs/content/web/viewer.html
@@ -114,28 +114,16 @@ limitations under the License.
             <div class="horizontalToolbarSeparator"></div>
 
             <button id="pageRotateCw" class="secondaryToolbarButton rotateCw" title="Rotate Clockwise" tabindex="25" data-l10n-id="page_rotate_cw">
               <span data-l10n-id="page_rotate_cw_label">Rotate Clockwise</span>
             </button>
             <button id="pageRotateCcw" class="secondaryToolbarButton rotateCcw" title="Rotate Counterclockwise" tabindex="26" data-l10n-id="page_rotate_ccw">
               <span data-l10n-id="page_rotate_ccw_label">Rotate Counterclockwise</span>
             </button>
-
-            <div class="horizontalToolbarSeparator"></div>
-
-            <button id="toggleHandTool" class="secondaryToolbarButton handTool" title="Enable hand tool" tabindex="27" data-l10n-id="hand_tool_enable">
-              <span data-l10n-id="hand_tool_enable_label">Enable hand tool</span>
-            </button>
-            
-            <div class="horizontalToolbarSeparator"></div>
-
-            <button id="documentProperties" class="secondaryToolbarButton documentProperties" title="Document Properties…" tabindex="28" data-l10n-id="document_properties">
-              <span data-l10n-id="document_properties_label">Document Properties…</span>
-            </button>
           </div>
         </div>  <!-- secondaryToolbar -->
 
         <div class="toolbar">
           <div id="toolbarContainer">
             <div id="toolbarViewer">
               <div id="toolbarViewerLeft">
                 <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="4" data-l10n-id="toggle_sidebar">
@@ -254,74 +242,29 @@ limitations under the License.
             </button>
           </div>
           <div class="clearBoth"></div>
           <textarea id="errorMoreInfo" hidden='true' readonly="readonly"></textarea>
         </div>
       </div> <!-- mainContainer -->
 
       <div id="overlayContainer" class="hidden">
-        <div id="promptContainer" class="hidden">
+        <div id="promptContainer">
           <div id="passwordContainer" class="prompt doorHanger">
             <div class="row">
               <p id="passwordText" data-l10n-id="password_label">Enter the password to open this PDF file:</p>
             </div>
             <div class="row">
               <input type="password" id="password" class="toolbarField" />
             </div>
-            <div class="buttonRow">
-              <button id="passwordCancel" class="overlayButton"><span data-l10n-id="password_cancel">Cancel</span></button>
-              <button id="passwordSubmit" class="overlayButton"><span data-l10n-id="password_ok">OK</span></button>
+            <div class="row">
+              <button id="passwordCancel" class="promptButton"><span data-l10n-id="password_cancel">Cancel</span></button>
+              <button id="passwordSubmit" class="promptButton"><span data-l10n-id="password_ok">OK</span></button>
             </div>
           </div>
         </div>
-        <div id="documentPropertiesContainer" class="hidden">
-          <div class="doorHanger">
-            <div class="row">
-              <span data-l10n-id="document_properties_file_name">File name:</span> <p id="fileNameField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_file_size">File size:</span> <p id="fileSizeField">-</p>
-            </div>
-            <div class="separator"></div>
-            <div class="row">
-              <span data-l10n-id="document_properties_title">Title:</span> <p id="titleField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_author">Author:</span> <p id="authorField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_subject">Subject:</span> <p id="subjectField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_keywords">Keywords:</span> <p id="keywordsField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_creation_date">Creation Date:</span> <p id="creationDateField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_modification_date">Modification Date:</span> <p id="modificationDateField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_creator">Creator:</span> <p id="creatorField">-</p>
-            </div>
-            <div class="separator"></div>
-            <div class="row">
-              <span data-l10n-id="document_properties_producer">PDF Producer:</span> <p id="producerField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_version">PDF Version:</span> <p id="versionField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_page_count">Page Count:</span> <p id="pageCountField">-</p>
-            </div>
-            <div class="buttonRow">
-	          <button id="documentPropertiesClose" class="overlayButton"><span data-l10n-id="document_properties_close">Close</span></button>
-            </div>
-          </div>
-        </div>
-      </div>  <!-- overlayContainer -->
+      </div> 
 
     </div> <!-- outerContainer -->
     <div id="printContainer"></div>
   </body>
 </html>
 
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -12,40 +12,38 @@
  * 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 PDFJS, PDFBug, FirefoxCom, Stats, Cache, PDFFindBar, CustomStyle,
            PDFFindController, ProgressBar, TextLayerBuilder, DownloadManager,
            getFileName, scrollIntoView, getPDFFileNameFromURL, PDFHistory,
-           Preferences, ViewHistory, PageView, ThumbnailView,
-           noContextMenuHandler, SecondaryToolbar, PasswordPrompt,
-           PresentationMode, HandTool, Promise, DocumentProperties */
+           Preferences, Settings, PageView, ThumbnailView, noContextMenuHandler,
+           SecondaryToolbar, PasswordPrompt, PresentationMode */
 
 'use strict';
 
 var DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf';
 var DEFAULT_SCALE = 'auto';
 var DEFAULT_SCALE_DELTA = 1.1;
 var UNKNOWN_SCALE = 0;
 var CACHE_SIZE = 20;
 var CSS_UNITS = 96.0 / 72.0;
 var SCROLLBAR_PADDING = 40;
 var VERTICAL_PADDING = 5;
 var MAX_AUTO_SCALE = 1.25;
 var MIN_SCALE = 0.25;
 var MAX_SCALE = 4.0;
-var VIEW_HISTORY_MEMORY = 20;
+var SETTINGS_MEMORY = 20;
 var SCALE_SELECT_CONTAINER_PADDING = 8;
 var SCALE_SELECT_PADDING = 22;
 var THUMBNAIL_SCROLL_MARGIN = -19;
 var USE_ONLY_CSS_ZOOM = false;
 var CLEANUP_TIMEOUT = 30000;
-var IGNORE_CURRENT_POSITION_ON_ZOOM = false;
 var RenderingStates = {
   INITIAL: 0,
   RUNNING: 1,
   PAUSED: 2,
   FINISHED: 3
 };
 var FindStates = {
   FIND_FOUND: 0,
@@ -139,51 +137,39 @@ function getOutputScale(ctx) {
     sy: pixelRatio,
     scaled: pixelRatio != 1
   };
 }
 
 /**
  * Scrolls specified element into view of its parent.
  * element {Object} The element to be visible.
- * spot {Object} An object with optional top and left properties,
- *               specifying the offset from the top left edge.
+ * spot {Object} The object with the top property -- offset from the top edge.
  */
 function scrollIntoView(element, spot) {
   // Assuming offsetParent is available (it's not available when viewer is in
   // hidden iframe or object). We have to scroll: if the offsetParent is not set
   // producing the error. See also animationStartedClosure.
   var parent = element.offsetParent;
   var offsetY = element.offsetTop + element.clientTop;
-  var offsetX = element.offsetLeft + element.clientLeft;
   if (!parent) {
     console.error('offsetParent is not set -- cannot scroll');
     return;
   }
-  while (parent.clientHeight === parent.scrollHeight) {
+  while (parent.clientHeight == parent.scrollHeight) {
     if (parent.dataset._scaleY) {
       offsetY /= parent.dataset._scaleY;
-      offsetX /= parent.dataset._scaleX;
     }
     offsetY += parent.offsetTop;
-    offsetX += parent.offsetLeft;
     parent = parent.offsetParent;
-    if (!parent) {
+    if (!parent)
       return; // no need to scroll
-    }
   }
-  if (spot) {
-    if (spot.top !== undefined) {
-      offsetY += spot.top;
-    }
-    if (spot.left !== undefined) {
-      offsetX += spot.left;
-      parent.scrollLeft = offsetX;
-    }
-  }
+  if (spot)
+    offsetY += spot.top;
   parent.scrollTop = offsetY;
 }
 
 /**
  * Event handler to suppress context menu.
  */
 function noContextMenuHandler(e) {
   e.preventDefault();
@@ -309,44 +295,42 @@ var DEFAULT_PREFERENCES = {
   defaultZoomValue: '',
   ifAvailableShowOutlineOnLoad: false
 };
 
 
 var Preferences = (function PreferencesClosure() {
   function Preferences() {
     this.prefs = {};
-    this.isInitializedPromiseResolved = false;
     this.initializedPromise = this.readFromStorage().then(function(prefObj) {
-      this.isInitializedPromiseResolved = true;
       if (prefObj) {
         this.prefs = prefObj;
       }
     }.bind(this));
   }
 
   Preferences.prototype = {
     writeToStorage: function Preferences_writeToStorage(prefObj) {
       return;
     },
 
     readFromStorage: function Preferences_readFromStorage() {
-      var readFromStoragePromise = Promise.resolve();
+      var readFromStoragePromise = new PDFJS.Promise();
       return readFromStoragePromise;
     },
 
     reset: function Preferences_reset() {
-      if (this.isInitializedPromiseResolved) {
+      if (this.initializedPromise.isResolved) {
         this.prefs = {};
         this.writeToStorage(this.prefs);
       }
     },
 
     set: function Preferences_set(name, value) {
-      if (!this.isInitializedPromiseResolved) {
+      if (!this.initializedPromise.isResolved) {
         return;
       } else if (DEFAULT_PREFERENCES[name] === undefined) {
         console.error('Preferences_set: \'' + name + '\' is undefined.');
         return;
       } else if (value === undefined) {
         console.error('Preferences_set: no value is specified.');
         return;
       }
@@ -367,17 +351,17 @@ var Preferences = (function PreferencesC
     },
 
     get: function Preferences_get(name) {
       var defaultPref = DEFAULT_PREFERENCES[name];
 
       if (defaultPref === undefined) {
         console.error('Preferences_get: \'' + name + '\' is undefined.');
         return;
-      } else if (this.isInitializedPromiseResolved) {
+      } else if (this.initializedPromise.isResolved) {
         var pref = this.prefs[name];
 
         if (pref !== undefined) {
           return pref;
         }
       }
       return defaultPref;
     }
@@ -479,66 +463,59 @@ var DownloadManager = (function Download
   return DownloadManager;
 })();
 
 Preferences.prototype.writeToStorage = function(prefObj) {
   FirefoxCom.requestSync('setPreferences', prefObj);
 };
 
 Preferences.prototype.readFromStorage = function() {
-  var readFromStoragePromise = new Promise(function (resolve) {
-    var readPrefs = JSON.parse(FirefoxCom.requestSync('getPreferences'));
-    resolve(readPrefs);
-  });
+  var readFromStoragePromise = new PDFJS.Promise();
+  var readPrefs = JSON.parse(FirefoxCom.requestSync('getPreferences'));
+  readFromStoragePromise.resolve(readPrefs);
   return readFromStoragePromise;
 };
 
 
-
 var cache = new Cache(CACHE_SIZE);
 var currentPageNumber = 1;
 
 
 /**
- * View History - This is a utility for saving various view parameters for
- *                recently opened files.
+ * Settings Manager - This is a utility for saving settings.
  *
- * The way that the view parameters are stored depends on how PDF.js is built,
+ * The way that settings are stored depends on how PDF.js is built,
  * for 'node make <flag>' the following cases exist:
  *  - FIREFOX or MOZCENTRAL - uses about:config.
  *  - B2G                   - uses asyncStorage.
  *  - GENERIC or CHROME     - uses localStorage, if it is available.
  */
-var ViewHistory = (function ViewHistoryClosure() {
-  function ViewHistory(fingerprint) {
+var Settings = (function SettingsClosure() {
+
+  function Settings(fingerprint) {
     this.fingerprint = fingerprint;
-    var initializedPromiseResolve;
-    this.isInitializedPromiseResolved = false;
-    this.initializedPromise = new Promise(function (resolve) {
-      initializedPromiseResolve = resolve;
-    });
-
-    var resolvePromise = (function ViewHistoryResolvePromise(db) {
-      this.isInitializedPromiseResolved = true;
+    this.initializedPromise = new PDFJS.Promise();
+
+    var resolvePromise = (function settingsResolvePromise(db) {
       this.initialize(db || '{}');
-      initializedPromiseResolve();
+      this.initializedPromise.resolve();
     }).bind(this);
 
 
     resolvePromise(FirefoxCom.requestSync('getDatabase', null));
 
   }
 
-  ViewHistory.prototype = {
-    initialize: function ViewHistory_initialize(database) {
+  Settings.prototype = {
+    initialize: function settingsInitialize(database) {
       database = JSON.parse(database);
       if (!('files' in database)) {
         database.files = [];
       }
-      if (database.files.length >= VIEW_HISTORY_MEMORY) {
+      if (database.files.length >= SETTINGS_MEMORY) {
         database.files.shift();
       }
       var index;
       for (var i = 0, length = database.files.length; i < length; i++) {
         var branch = database.files[i];
         if (branch.fingerprint === this.fingerprint) {
           index = i;
           break;
@@ -546,38 +523,38 @@ var ViewHistory = (function ViewHistoryC
       }
       if (typeof index !== 'number') {
         index = database.files.push({fingerprint: this.fingerprint}) - 1;
       }
       this.file = database.files[index];
       this.database = database;
     },
 
-    set: function ViewHistory_set(name, val) {
-      if (!this.isInitializedPromiseResolved) {
+    set: function settingsSet(name, val) {
+      if (!this.initializedPromise.isResolved) {
         return;
       }
       var file = this.file;
       file[name] = val;
       var database = JSON.stringify(this.database);
 
 
       FirefoxCom.requestSync('setDatabase', database);
 
     },
 
-    get: function ViewHistory_get(name, defaultValue) {
-      if (!this.isInitializedPromiseResolved) {
+    get: function settingsGet(name, defaultValue) {
+      if (!this.initializedPromise.isResolved) {
         return defaultValue;
       }
       return this.file[name] || defaultValue;
     }
   };
 
-  return ViewHistory;
+  return Settings;
 })();
 
 
 /* globals PDFFindController, FindStates, mozL10n */
 
 /**
  * Creates a "search bar" given set of DOM elements
  * that act as controls for searching, or for setting
@@ -730,17 +707,17 @@ var PDFFindBar = {
     } else {
       this.open();
     }
   }
 };
 
 
 
-/* globals PDFFindBar, PDFJS, FindStates, FirefoxCom, Promise */
+/* globals PDFFindBar, PDFJS, FindStates, FirefoxCom */
 
 /**
  * Provides a "search" or "find" functionality for the PDF.
  * This object actually performs the search for a given string.
  */
 
 var PDFFindController = {
   startedTextExtraction: false,
@@ -778,35 +755,34 @@ var PDFFindController = {
   dirtyMatch: false,
 
   findTimeout: null,
 
   pdfPageSource: null,
 
   integratedFind: false,
 
+  firstPagePromise: new PDFJS.Promise(),
+
   initialize: function(options) {
     if(typeof PDFFindBar === 'undefined' || PDFFindBar === null) {
         throw 'PDFFindController cannot be initialized ' +
             'without a PDFFindController instance';
     }
 
     this.pdfPageSource = options.pdfPageSource;
     this.integratedFind = options.integratedFind;
 
     var events = [
       'find',
       'findagain',
       'findhighlightallchange',
       'findcasesensitivitychange'
     ];
 
-    this.firstPagePromise = new Promise(function (resolve) {
-      this.resolveFirstPage = resolve;
-    }.bind(this));
     this.handleEvent = this.handleEvent.bind(this);
 
     for (var i = 0; i < events.length; i++) {
       window.addEventListener(events[i], this.handleEvent);
     }
   },
 
   reset: function pdfFindControllerReset() {
@@ -854,37 +830,36 @@ var PDFFindController = {
 
   extractText: function() {
     if (this.startedTextExtraction) {
       return;
     }
     this.startedTextExtraction = true;
 
     this.pageContents = [];
-    var extractTextPromisesResolves = [];
     for (var i = 0, ii = this.pdfPageSource.pdfDocument.numPages; i < ii; i++) {
-      this.extractTextPromises.push(new Promise(function (resolve) {
-        extractTextPromisesResolves.push(resolve);
-      }));
+      this.extractTextPromises.push(new PDFJS.Promise());
     }
 
     var self = this;
     function extractPageText(pageIndex) {
       self.pdfPageSource.pages[pageIndex].getTextContent().then(
-        function textContentResolved(bidiTexts) {
+        function textContentResolved(data) {
+          // Build the find string.
+          var bidiTexts = data.bidiTexts;
           var str = '';
 
           for (var i = 0; i < bidiTexts.length; i++) {
             str += bidiTexts[i].str;
           }
 
           // Store the pageContent as a string.
           self.pageContents.push(str);
 
-          extractTextPromisesResolves[pageIndex](pageIndex);
+          self.extractTextPromises[pageIndex].resolve(pageIndex);
           if ((pageIndex + 1) < self.pdfPageSource.pages.length)
             extractPageText(pageIndex + 1);
         }
       );
     }
     extractPageText(0);
   },
 
@@ -1428,50 +1403,41 @@ var PDFHistory = {
 var SecondaryToolbar = {
   opened: false,
   previousContainerHeight: null,
   newContainerHeight: null,
 
   initialize: function secondaryToolbarInitialize(options) {
     this.toolbar = options.toolbar;
     this.presentationMode = options.presentationMode;
-    this.documentProperties = options.documentProperties;
     this.buttonContainer = this.toolbar.firstElementChild;
 
     // Define the toolbar buttons.
     this.toggleButton = options.toggleButton;
     this.presentationModeButton = options.presentationModeButton;
     this.openFile = options.openFile;
     this.print = options.print;
     this.download = options.download;
-    this.viewBookmark = options.viewBookmark;
     this.firstPage = options.firstPage;
     this.lastPage = options.lastPage;
     this.pageRotateCw = options.pageRotateCw;
     this.pageRotateCcw = options.pageRotateCcw;
-    this.documentPropertiesButton = options.documentPropertiesButton;
 
     // Attach the event listeners.
     var elements = [
-      // Button to toggle the visibility of the secondary toolbar:
       { element: this.toggleButton, handler: this.toggle },
-      // All items within the secondary toolbar
-      // (except for toggleHandTool, hand_tool.js is responsible for it):
       { element: this.presentationModeButton,
         handler: this.presentationModeClick },
       { element: this.openFile, handler: this.openFileClick },
       { element: this.print, handler: this.printClick },
       { element: this.download, handler: this.downloadClick },
-      { element: this.viewBookmark, handler: this.viewBookmarkClick },
       { element: this.firstPage, handler: this.firstPageClick },
       { element: this.lastPage, handler: this.lastPageClick },
       { element: this.pageRotateCw, handler: this.pageRotateCwClick },
-      { element: this.pageRotateCcw, handler: this.pageRotateCcwClick },
-      { element: this.documentPropertiesButton,
-        handler: this.documentPropertiesClick }
+      { element: this.pageRotateCcw, handler: this.pageRotateCcwClick }
     ];
 
     for (var item in elements) {
       var element = elements[item].element;
       if (element) {
         element.addEventListener('click', elements[item].handler.bind(this));
       }
     }
@@ -1480,56 +1446,45 @@ var SecondaryToolbar = {
   // Event handling functions.
   presentationModeClick: function secondaryToolbarPresentationModeClick(evt) {
     this.presentationMode.request();
     this.close();
   },
 
   openFileClick: function secondaryToolbarOpenFileClick(evt) {
     document.getElementById('fileInput').click();
-    this.close();
+    this.close(evt.target);
   },
 
   printClick: function secondaryToolbarPrintClick(evt) {
     window.print();
-    this.close();
+    this.close(evt.target);
   },
 
   downloadClick: function secondaryToolbarDownloadClick(evt) {
     PDFView.download();
-    this.close();
-  },
-
-  viewBookmarkClick: function secondaryToolbarViewBookmarkClick(evt) {
-    this.close();
+    this.close(evt.target);
   },
 
   firstPageClick: function secondaryToolbarFirstPageClick(evt) {
     PDFView.page = 1;
-    this.close();
   },
 
   lastPageClick: function secondaryToolbarLastPageClick(evt) {
     PDFView.page = PDFView.pdfDocument.numPages;
-    this.close();
   },
 
   pageRotateCwClick: function secondaryToolbarPageRotateCwClick(evt) {
     PDFView.rotatePages(90);
   },
 
   pageRotateCcwClick: function secondaryToolbarPageRotateCcwClick(evt) {
     PDFView.rotatePages(-90);
   },
 
-  documentPropertiesClick: function secondaryToolbarDocumentPropsClick(evt) {
-    this.documentProperties.show();
-    this.close();
-  },
-
   // Misc. functions for interacting with the toolbar.
   setMaxHeight: function secondaryToolbarSetMaxHeight(container) {
     if (!container || !this.buttonContainer) {
       return;
     }
     this.newContainerHeight = container.clientHeight;
     if (this.previousContainerHeight === this.newContainerHeight) {
       return;
@@ -1594,31 +1549,30 @@ var PasswordPrompt = {
 
     this.passwordField.addEventListener('keydown',
       function (e) {
         if (e.keyCode === 13) { // Enter key
           this.verifyPassword();
         }
       }.bind(this));
 
-    window.addEventListener('keydown',
+    this.overlayContainer.addEventListener('keydown',
       function (e) {
         if (e.keyCode === 27) { // Esc key
           this.hide();
         }
       }.bind(this));
   },
 
   show: function passwordPromptShow() {
     if (this.visible) {
       return;
     }
     this.visible = true;
     this.overlayContainer.classList.remove('hidden');
-    this.overlayContainer.firstElementChild.classList.remove('hidden');
     this.passwordField.focus();
 
     var promptString = mozL10n.get('password_label', null,
       'Enter the password to open this PDF file.');
 
     if (this.reason === PDFJS.PasswordResponses.INCORRECT_PASSWORD) {
       promptString = mozL10n.get('password_invalid', null,
         'Invalid password. Please try again.');
@@ -1629,32 +1583,30 @@ var PasswordPrompt = {
 
   hide: function passwordPromptClose() {
     if (!this.visible) {
       return;
     }
     this.visible = false;
     this.passwordField.value = '';
     this.overlayContainer.classList.add('hidden');
-    this.overlayContainer.firstElementChild.classList.add('hidden');
   },
 
   verifyPassword: function passwordPromptVerifyPassword() {
     var password = this.passwordField.value;
     if (password && password.length > 0) {
       this.hide();
       return this.updatePassword(password);
     }
   }
 };
 
 
 var DELAY_BEFORE_HIDING_CONTROLS = 3000; // in ms
 var SELECTOR = 'presentationControls';
-var DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS = 1000; // in ms
 
 var PresentationMode = {
   active: false,
   args: null,
   contextMenuOpen: false,
 
   initialize: function presentationModeInitialize(options) {
     this.container = options.container;
@@ -1688,48 +1640,21 @@ var PresentationMode = {
 
   get isFullscreen() {
     return (document.fullscreenElement ||
             document.mozFullScreen ||
             document.webkitIsFullScreen ||
             document.msFullscreenElement);
   },
 
-  /**
-   * Initialize a timeout that is used to reset PDFView.currentPosition when the
-   * browser transitions to fullscreen mode. Since resize events are triggered
-   * multiple times during the switch to fullscreen mode, this is necessary in
-   * order to prevent the page from being scrolled partially, or completely,
-   * out of view when Presentation Mode is enabled.
-   * Note: This is only an issue at certain zoom levels, e.g. 'page-width'.
-   */
-  _setSwitchInProgress: function presentationMode_setSwitchInProgress() {
-    if (this.switchInProgress) {
-      clearTimeout(this.switchInProgress);
-    }
-    this.switchInProgress = setTimeout(function switchInProgressTimeout() {
-      delete this.switchInProgress;
-    }.bind(this), DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS);
-
-    PDFView.currentPosition = null;
-  },
-
-  _resetSwitchInProgress: function presentationMode_resetSwitchInProgress() {
-    if (this.switchInProgress) {
-      clearTimeout(this.switchInProgress);
-      delete this.switchInProgress;
-    }
-  },
-
   request: function presentationModeRequest() {
     if (!PDFView.supportsFullscreen || this.isFullscreen ||
         !this.viewer.hasChildNodes()) {
       return false;
     }
-    this._setSwitchInProgress();
 
     if (this.container.requestFullscreen) {
       this.container.requestFullscreen();
     } else if (this.container.mozRequestFullScreen) {
       this.container.mozRequestFullScreen();
     } else if (this.container.webkitRequestFullScreen) {
       this.container.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
     } else if (this.container.msRequestFullscreen) {
@@ -1743,58 +1668,43 @@ var PresentationMode = {
       previousScale: PDFView.currentScaleValue
     };
 
     return true;
   },
 
   enter: function presentationModeEnter() {
     this.active = true;
-    this._resetSwitchInProgress();
-
-    // Ensure that the correct page is scrolled into view when entering
-    // Presentation Mode, by waiting until fullscreen mode in enabled.
-    // Note: This is only necessary in non-Mozilla browsers.
-    setTimeout(function enterPresentationModeTimeout() {
-      PDFView.page = this.args.page;
-      PDFView.setScale('page-fit', true);
-    }.bind(this), 0);
+
+    PDFView.page = this.args.page;
+    PDFView.setScale('page-fit', true);
 
     window.addEventListener('mousemove', this.mouseMove, false);
     window.addEventListener('mousedown', this.mouseDown, false);
     window.addEventListener('contextmenu', this.contextMenu, false);
 
     this.showControls();
-    HandTool.enterPresentationMode();
     this.contextMenuOpen = false;
     this.container.setAttribute('contextmenu', 'viewerContextMenu');
   },
 
   exit: function presentationModeExit() {
+    this.active = false;
+
     var page = PDFView.page;
-
-    // Ensure that the correct page is scrolled into view when exiting
-    // Presentation Mode, by waiting until fullscreen mode is disabled.
-    // Note: This is only necessary in non-Mozilla browsers.
-    setTimeout(function exitPresentationModeTimeout() {
-      PDFView.setScale(this.args.previousScale);
-      PDFView.page = page;
-      // Keep Presentation Mode active until the page is scrolled into view,
-      // to prevent issues in non-Mozilla browsers.
-      this.active = false;
-      this.args = null;
-    }.bind(this), 0);
+    PDFView.setScale(this.args.previousScale);
+    PDFView.page = page;
 
     window.removeEventListener('mousemove', this.mouseMove, false);
     window.removeEventListener('mousedown', this.mouseDown, false);
     window.removeEventListener('contextmenu', this.contextMenu, false);
 
     this.hideControls();
+    this.args = null;
     PDFView.clearMouseScrollState();
-    HandTool.exitPresentationMode();
     this.container.removeAttribute('contextmenu');
     this.contextMenuOpen = false;
 
     // Ensure that the thumbnail of the current page is visible
     // when exiting presentation mode.
     scrollIntoView(document.getElementById('thumbnailContainer' + page));
   },
 
@@ -1861,454 +1771,16 @@ var PresentationMode = {
   window.addEventListener('fullscreenchange', presentationModeChange, false);
   window.addEventListener('mozfullscreenchange', presentationModeChange, false);
   window.addEventListener('webkitfullscreenchange', presentationModeChange,
                           false);
   window.addEventListener('MSFullscreenChange', presentationModeChange, false);
 })();
 
 
-/* Copyright 2013 Rob Wu <gwnRob@gmail.com>
- * https://github.com/Rob--W/grab-to-pan.js
- *
- * 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.
- */
-
-'use strict';
-
-var GrabToPan = (function GrabToPanClosure() {
-  /**
-   * Construct a GrabToPan instance for a given HTML element.
-   * @param options.element {Element}
-   * @param options.ignoreTarget {function} optional. See `ignoreTarget(node)`
-   * @param options.onActiveChanged {function(boolean)} optional. Called
-   *  when grab-to-pan is (de)activated. The first argument is a boolean that
-   *  shows whether grab-to-pan is activated.
-   */
-  function GrabToPan(options) {
-    this.element = options.element;
-    this.document = options.element.ownerDocument;
-    if (typeof options.ignoreTarget === 'function') {
-      this.ignoreTarget = options.ignoreTarget;
-    }
-    this.onActiveChanged = options.onActiveChanged;
-
-    // Bind the contexts to ensure that `this` always points to
-    // the GrabToPan instance.
-    this.activate = this.activate.bind(this);
-    this.deactivate = this.deactivate.bind(this);
-    this.toggle = this.toggle.bind(this);
-    this._onmousedown = this._onmousedown.bind(this);
-    this._onmousemove = this._onmousemove.bind(this);
-    this._endPan = this._endPan.bind(this);
-  }
-  GrabToPan.prototype = {
-    /**
-     * Class name of element which can be grabbed
-     */
-    CSS_CLASS_GRAB: 'grab-to-pan-grab',
-    /**
-     * Class name of element which is being dragged & panned
-     */
-    CSS_CLASS_GRABBING: 'grab-to-pan-grabbing',
-
-    /**
-     * Bind a mousedown event to the element to enable grab-detection.
-     */
-    activate: function GrabToPan_activate() {
-      if (!this.active) {
-        this.active = true;
-        this.element.addEventListener('mousedown', this._onmousedown, true);
-        this.element.classList.add(this.CSS_CLASS_GRAB);
-        if (this.onActiveChanged) {
-          this.onActiveChanged(true);
-        }
-      }
-    },
-
-    /**
-     * Removes all events. Any pending pan session is immediately stopped.
-     */
-    deactivate: function GrabToPan_deactivate() {
-      if (this.active) {
-        this.active = false;
-        this.element.removeEventListener('mousedown', this._onmousedown, true);
-        this._endPan();
-        this.element.classList.remove(this.CSS_CLASS_GRAB);
-        if (this.onActiveChanged) {
-          this.onActiveChanged(false);
-        }
-      }
-    },
-
-    toggle: function GrabToPan_toggle() {
-      if (this.active) {
-        this.deactivate();
-      } else {
-        this.activate();
-      }
-    },
-
-    /**
-     * Whether to not pan if the target element is clicked.
-     * Override this method to change the default behaviour.
-     *
-     * @param node {Element} The target of the event
-     * @return {boolean} Whether to not react to the click event.
-     */
-    ignoreTarget: function GrabToPan_ignoreTarget(node) {
-      // Use matchesSelector to check whether the clicked element
-      // is (a child of) an input element / link
-      return node[matchesSelector](
-        'a[href], a[href] *, input, textarea, button, button *, select, option'
-      );
-    },
-
-    /**
-     * @private
-     */
-    _onmousedown: function GrabToPan__onmousedown(event) {
-      if (event.button !== 0 || this.ignoreTarget(event.target)) {
-        return;
-      }
-      if (event.originalTarget) {
-        try {
-          /* jshint expr:true */
-          event.originalTarget.tagName;
-        } catch (e) {
-          // Mozilla-specific: element is a scrollbar (XUL element)
-          return;
-        }
-      }
-
-      this.scrollLeftStart = this.element.scrollLeft;
-      this.scrollTopStart = this.element.scrollTop;
-      this.clientXStart = event.clientX;
-      this.clientYStart = event.clientY;
-      this.document.addEventListener('mousemove', this._onmousemove, true);
-      this.document.addEventListener('mouseup', this._endPan, true);
-      // When a scroll event occurs before a mousemove, assume that the user
-      // dragged a scrollbar (necessary for Opera Presto, Safari and IE)
-      // (not needed for Chrome/Firefox)
-      this.element.addEventListener('scroll', this._endPan, true);
-      event.preventDefault();
-      event.stopPropagation();
-      this.element.classList.remove(this.CSS_CLASS_GRAB);
-      this.document.documentElement.classList.add(this.CSS_CLASS_GRABBING);
-    },
-
-    /**
-     * @private
-     */
-    _onmousemove: function GrabToPan__onmousemove(event) {
-      this.element.removeEventListener('scroll', this._endPan, true);
-      if (isLeftMouseReleased(event)) {
-        this.document.removeEventListener('mousemove', this._onmousemove, true);
-        return;
-      }
-      var xDiff = event.clientX - this.clientXStart;
-      var yDiff = event.clientY - this.clientYStart;
-      this.element.scrollTop = this.scrollTopStart - yDiff;
-      this.element.scrollLeft = this.scrollLeftStart - xDiff;
-    },
-
-    /**
-     * @private
-     */
-    _endPan: function GrabToPan__endPan() {
-      this.element.removeEventListener('scroll', this._endPan, true);
-      this.document.removeEventListener('mousemove', this._onmousemove, true);
-      this.document.removeEventListener('mouseup', this._endPan, true);
-      this.document.documentElement.classList.remove(this.CSS_CLASS_GRABBING);
-      this.element.classList.add(this.CSS_CLASS_GRAB);
-    }
-  };
-
-  // Get the correct (vendor-prefixed) name of the matches method.
-  var matchesSelector;
-  ['webkitM', 'mozM', 'msM', 'oM', 'm'].some(function(prefix) {
-    var name = prefix + 'atches';
-    if (name in document.documentElement) {
-      matchesSelector = name;
-    }
-    name += 'Selector';
-    if (name in document.documentElement) {
-      matchesSelector = name;
-    }
-    return matchesSelector; // If found, then truthy, and [].some() ends.
-  });
-
-  // Browser sniffing because it's impossible to feature-detect
-  // whether event.which for onmousemove is reliable
-  var isNotIEorIsIE10plus = !document.documentMode || document.documentMode > 9;
-  var chrome = window.chrome;
-  var isChrome15OrOpera15plus = chrome && (chrome.webstore || chrome.app);
-  //                                       ^ Chrome 15+       ^ Opera 15+
-  var isSafari6plus = /Apple/.test(navigator.vendor) &&
-                      /Version\/([6-9]\d*|[1-5]\d+)/.test(navigator.userAgent);
-
-  /**
-   * Whether the left mouse is not pressed.
-   * @param event {MouseEvent}
-   * @return {boolean} True if the left mouse button is not pressed.
-   *                   False if unsure or if the left mouse button is pressed.
-   */
-  function isLeftMouseReleased(event) {
-    if ('buttons' in event && isNotIEorIsIE10plus) {
-      // http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-buttons
-      // Firefox 15+
-      // Internet Explorer 10+
-      return !(event.buttons | 1);
-    }
-    if (isChrome15OrOpera15plus || isSafari6plus) {
-      // Chrome 14+
-      // Opera 15+
-      // Safari 6.0+
-      return event.which === 0;
-    }
-  }
-
-  return GrabToPan;
-})();
-
-var HandTool = {
-  initialize: function handToolInitialize(options) {
-    var toggleHandTool = options.toggleHandTool;
-    this.handTool = new GrabToPan({
-      element: options.container,
-      onActiveChanged: function(isActive) {
-        if (!toggleHandTool) {
-          return;
-        }
-        if (isActive) {
-          toggleHandTool.title =
-            mozL10n.get('hand_tool_disable.title', null, 'Disable hand tool');
-          toggleHandTool.firstElementChild.textContent =
-            mozL10n.get('hand_tool_disable_label', null, 'Disable hand tool');
-        } else {
-          toggleHandTool.title =
-            mozL10n.get('hand_tool_enable.title', null, 'Enable hand tool');
-          toggleHandTool.firstElementChild.textContent =
-            mozL10n.get('hand_tool_enable_label', null, 'Enable hand tool');
-        }
-      }
-    });
-    if (toggleHandTool) {
-      toggleHandTool.addEventListener('click', this.toggle.bind(this), false);
-    }
-    // TODO: Read global prefs and call this.handTool.activate() if needed.
-  },
-
-  toggle: function handToolToggle() {
-    this.handTool.toggle();
-    SecondaryToolbar.close();
-  },
-
-  enterPresentationMode: function handToolEnterPresentationMode() {
-    if (this.handTool.active) {
-      this.wasActive = true;
-      this.handTool.deactivate();
-    }
-  },
-
-  exitPresentationMode: function handToolExitPresentationMode() {
-    if (this.wasActive) {
-      this.wasActive = null;
-      this.handTool.activate();
-    }
-  }
-};
-
-
-var DocumentProperties = {
-  overlayContainer: null,
-  fileName: '',
-  fileSize: '',
-  visible: false,
-
-  // Document property fields (in the viewer).
-  fileNameField: null,
-  fileSizeField: null,
-  titleField: null,
-  authorField: null,
-  subjectField: null,
-  keywordsField: null,
-  creationDateField: null,
-  modificationDateField: null,
-  creatorField: null,
-  producerField: null,
-  versionField: null,
-  pageCountField: null,
-
-  initialize: function documentPropertiesInitialize(options) {
-    this.overlayContainer = options.overlayContainer;
-
-    // Set the document property fields.
-    this.fileNameField = options.fileNameField;
-    this.fileSizeField = options.fileSizeField;
-    this.titleField = options.titleField;
-    this.authorField = options.authorField;
-    this.subjectField = options.subjectField;
-    this.keywordsField = options.keywordsField;
-    this.creationDateField = options.creationDateField;
-    this.modificationDateField = options.modificationDateField;
-    this.creatorField = options.creatorField;
-    this.producerField = options.producerField;
-    this.versionField = options.versionField;
-    this.pageCountField = options.pageCountField;
-
-    // Bind the event listener for the Close button.
-    if (options.closeButton) {
-      options.closeButton.addEventListener('click', this.hide.bind(this));
-    }
-
-    // Bind the event listener for the Esc key (to close the dialog).
-    window.addEventListener('keydown',
-      function (e) {
-        if (e.keyCode === 27) { // Esc key
-          this.hide();
-        }
-      }.bind(this));
-  },
-
-  getProperties: function documentPropertiesGetProperties() {
-    var self = this;
-
-    // Get the file name.
-    this.fileName = getPDFFileNameFromURL(PDFView.url);
-
-    // Get the file size.
-    PDFView.pdfDocument.dataLoaded().then(function(data) {
-      self.setFileSize(data.length);
-    });
-
-    // Get the other document properties.
-    PDFView.pdfDocument.getMetadata().then(function(data) {
-      var fields = [
-        { field: self.fileNameField, content: self.fileName },
-        { field: self.fileSizeField, content: self.fileSize },
-        { field: self.titleField, content: data.info.Title },
-        { field: self.authorField, content: data.info.Author },
-        { field: self.subjectField, content: data.info.Subject },
-        { field: self.keywordsField, content: data.info.Keywords },
-        { field: self.creationDateField,
-          content: self.parseDate(data.info.CreationDate) },
-        { field: self.modificationDateField,
-          content: self.parseDate(data.info.ModDate) },
-        { field: self.creatorField, content: data.info.Creator },
-        { field: self.producerField, content: data.info.Producer },
-        { field: self.versionField, content: data.info.PDFFormatVersion },
-        { field: self.pageCountField, content: PDFView.pdfDocument.numPages }
-      ];
-
-      // Show the properties in the dialog.
-      for (var item in fields) {
-        var element = fields[item];
-        if (element.field && element.content !== undefined &&
-            element.content !== '') {
-          element.field.textContent = element.content;
-        }
-      }
-    });
-  },
-
-  setFileSize: function documentPropertiesSetFileSize(fileSize) {
-    var kb = fileSize / 1024;
-    if (kb < 1024) {
-      this.fileSize = mozL10n.get('document_properties_kb', {
-        size_kb: (+kb.toPrecision(3)).toLocaleString(),
-        size_b: fileSize.toLocaleString()
-      }, '{{size_kb}} KB ({{size_b}} bytes)');
-    } else {
-      this.fileSize = mozL10n.get('document_properties_mb', {
-        size_mb: (+(kb / 1024).toPrecision(3)).toLocaleString(),
-        size_b: fileSize.toLocaleString()
-      }, '{{size_mb}} MB ({{size_b}} bytes)');
-    }
-  },
-
-  show: function documentPropertiesShow() {
-    if (this.visible) {
-      return;
-    }
-    this.visible = true;
-    this.overlayContainer.classList.remove('hidden');
-    this.overlayContainer.lastElementChild.classList.remove('hidden');
-    this.getProperties();
-  },
-
-  hide: function documentPropertiesClose() {
-    if (!this.visible) {
-      return;
-    }
-    this.visible = false;
-    this.overlayContainer.classList.add('hidden');
-    this.overlayContainer.lastElementChild.classList.add('hidden');
-  },
-
-  parseDate: function documentPropertiesParseDate(inputDate) {
-    // This is implemented according to the PDF specification (see
-    // http://www.gnupdf.org/Date for an overview), but note that 
-    // Adobe Reader doesn't handle changing the date to universal time
-    // and doesn't use the user's time zone (they're effectively ignoring
-    // the HH' and mm' parts of the date string).
-    var dateToParse = inputDate;
-    if (dateToParse === undefined) {
-      return '';
-    }
-
-    // Remove the D: prefix if it is available.
-    if (dateToParse.substring(0,2) === 'D:') {
-      dateToParse = dateToParse.substring(2);
-    }
-
-    // Get all elements from the PDF date string.
-    // JavaScript's Date object expects the month to be between
-    // 0 and 11 instead of 1 and 12, so we're correcting for this.
-    var year = parseInt(dateToParse.substring(0,4), 10);
-    var month = parseInt(dateToParse.substring(4,6), 10) - 1;
-    var day = parseInt(dateToParse.substring(6,8), 10);
-    var hours = parseInt(dateToParse.substring(8,10), 10);
-    var minutes = parseInt(dateToParse.substring(10,12), 10);
-    var seconds = parseInt(dateToParse.substring(12,14), 10);
-    var utRel = dateToParse.substring(14,15);
-    var offsetHours = parseInt(dateToParse.substring(15,17), 10);
-    var offsetMinutes = parseInt(dateToParse.substring(18,20), 10);
-
-    // As per spec, utRel = 'Z' means equal to universal time.
-    // The other cases ('-' and '+') have to be handled here.
-    if (utRel == '-') {
-      hours += offsetHours;
-      minutes += offsetMinutes;
-    } else if (utRel == '+') {
-      hours -= offsetHours;
-      minutes += offsetMinutes;
-    }
-
-    // Return the new date format from the user's locale.
-    var date = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
-    var dateString = date.toLocaleDateString();
-    var timeString = date.toLocaleTimeString();
-    return mozL10n.get('document_properties_date_string',
-                       {date: dateString, time: timeString},
-                       '{{date}}, {{time}}');
-  }
-};
-
-
 var PDFView = {
   pages: [],
   thumbnails: [],
   currentScale: UNKNOWN_SCALE,
   currentScaleValue: null,
   initialBookmark: document.location.hash.substring(1),
   container: null,
   thumbnailContainer: null,
@@ -2320,17 +1792,16 @@ var PDFView = {
   thumbnailViewScroll: null,
   pageRotation: 0,
   mouseScrollTimeStamp: 0,
   mouseScrollDelta: 0,
   lastScroll: 0,
   previousPageNumber: 1,
   isViewerEmbedded: (window.parent !== window),
   idleTimeout: null,
-  currentPosition: null,
 
   // called once when the document is loaded
   initialize: function pdfViewInitialize() {
     var self = this;
     var container = this.container = document.getElementById('viewerContainer');
     this.pageViewScroll = {};
     this.watchScroll(container, this.pageViewScroll, updateViewarea);
 
@@ -2352,37 +1823,29 @@ var PDFView = {
       findNextButton: document.getElementById('findNext')
     });
 
     PDFFindController.initialize({
       pdfPageSource: this,
       integratedFind: this.supportsIntegratedFind
     });
 
-    HandTool.initialize({
-      container: container,
-      toggleHandTool: document.getElementById('toggleHandTool')
-    });
-
     SecondaryToolbar.initialize({
       toolbar: document.getElementById('secondaryToolbar'),
       presentationMode: PresentationMode,
       toggleButton: document.getElementById('secondaryToolbarToggle'),
       presentationModeButton:
         document.getElementById('secondaryPresentationMode'),
       openFile: document.getElementById('secondaryOpenFile'),
       print: document.getElementById('secondaryPrint'),
       download: document.getElementById('secondaryDownload'),
-      viewBookmark: document.getElementById('secondaryViewBookmark'),
       firstPage: document.getElementById('firstPage'),
       lastPage: document.getElementById('lastPage'),
       pageRotateCw: document.getElementById('pageRotateCw'),
-      pageRotateCcw: document.getElementById('pageRotateCcw'),
-      documentProperties: DocumentProperties,
-      documentPropertiesButton: document.getElementById('documentProperties')
+      pageRotateCcw: document.getElementById('pageRotateCcw')
     });
 
     PasswordPrompt.initialize({
       overlayContainer: document.getElementById('overlayContainer'),
       passwordField: document.getElementById('password'),
       passwordText: document.getElementById('passwordText'),
       passwordSubmit: document.getElementById('passwordSubmit'),
       passwordCancel: document.getElementById('passwordCancel')
@@ -2392,33 +1855,16 @@ var PDFView = {
       container: container,
       secondaryToolbar: SecondaryToolbar,
       firstPage: document.getElementById('contextFirstPage'),
       lastPage: document.getElementById('contextLastPage'),
       pageRotateCw: document.getElementById('contextPageRotateCw'),
       pageRotateCcw: document.getElementById('contextPageRotateCcw')
     });
 
-    DocumentProperties.initialize({
-      overlayContainer: document.getElementById('overlayContainer'),
-      closeButton: document.getElementById('documentPropertiesClose'),
-      fileNameField: document.getElementById('fileNameField'),
-      fileSizeField: document.getElementById('fileSizeField'),
-      titleField: document.getElementById('titleField'),
-      authorField: document.getElementById('authorField'),
-      subjectField: document.getElementById('subjectField'),
-      keywordsField: document.getElementById('keywordsField'),
-      creationDateField: document.getElementById('creationDateField'),
-      modificationDateField: document.getElementById('modificationDateField'),
-      creatorField: document.getElementById('creatorField'),
-      producerField: document.getElementById('producerField'),
-      versionField: document.getElementById('versionField'),
-      pageCountField: document.getElementById('pageCountField')
-    });
-
     this.initialized = true;
     container.addEventListener('scroll', function() {
       self.lastScroll = Date.now();
     }, false);
   },
 
   getPage: function pdfViewGetPage(n) {
     return this.pdfDocument.getPage(n);
@@ -2437,53 +1883,29 @@ var PDFView = {
       else if (currentY < lastY)
         state.down = false;
       // else do nothing and use previous value
       state.lastY = currentY;
       callback();
     }, true);
   },
 
-  _setScaleUpdatePages: function pdfView_setScaleUpdatePages(
-      newScale, newValue, resetAutoSettings, noScroll) {
-    this.currentScaleValue = newValue;
-    if (newScale === this.currentScale) {
-      return;
-    }
-    for (var i = 0, ii = this.pages.length; i < ii; i++) {
-      this.pages[i].update(newScale);
-    }
-    this.currentScale = newScale;
-
-    if (!noScroll) {
-      var page = this.page, dest;
-      if (this.currentPosition && !IGNORE_CURRENT_POSITION_ON_ZOOM) {
-        page = this.currentPosition.page;
-        dest = [null, { name: 'XYZ' }, this.currentPosition.left,
-                this.currentPosition.top, null];
-      }
-      this.pages[page - 1].scrollIntoView(dest);
-    }
-    var event = document.createEvent('UIEvents');
-    event.initUIEvent('scalechange', false, false, window, 0);
-    event.scale = newScale;
-    event.resetAutoSettings = resetAutoSettings;
-    window.dispatchEvent(event);
-  },
-
   setScale: function pdfViewSetScale(value, resetAutoSettings, noScroll) {
     if (value === 'custom') {
       return;
     }
-    var scale = parseFloat(value);
-
-    if (scale > 0) {
-      this._setScaleUpdatePages(scale, value, true, noScroll);
+    var pages = this.pages;
+    var currentPage = pages[this.page - 1];
+    var number = parseFloat(value);
+    var scale;
+
+    if (number > 0) {
+      scale = number;
+      resetAutoSettings = true;
     } else {
-      var currentPage = this.pages[this.page - 1];
       if (!currentPage) {
         return;
       }
       var pageWidthScale = (this.container.clientWidth - SCROLLBAR_PADDING) /
                             currentPage.width * currentPage.scale;
       var pageHeightScale = (this.container.clientHeight - VERTICAL_PADDING) /
                              currentPage.height * currentPage.scale;
       switch (value) {
@@ -2502,18 +1924,38 @@ var PDFView = {
         case 'auto':
           scale = Math.min(MAX_AUTO_SCALE, pageWidthScale);
           break;
         default:
           console.error('pdfViewSetScale: \'' + value +
                         '\' is an unknown zoom value.');
           return;
       }
-      this._setScaleUpdatePages(scale, value, resetAutoSettings, noScroll);
-
+    }
+    this.currentScaleValue = value;
+
+    if (scale === this.currentScale) {
+      return;
+    }
+    for (var i = 0, ii = pages.length; i < ii; i++) {
+      pages[i].update(scale);
+    }
+    this.currentScale = scale;
+
+    if (!noScroll) {
+      currentPage.scrollIntoView();
+    }
+
+    var event = document.createEvent('UIEvents');
+    event.initUIEvent('scalechange', false, false, window, 0);
+    event.scale = scale;
+    event.resetAutoSettings = resetAutoSettings;
+    window.dispatchEvent(event);
+
+    if (!number) {
       selectScaleOption(value);
     }
   },
 
   zoomIn: function pdfViewZoomIn(ticks) {
     var newScale = this.currentScale;
     do {
       newScale = (newScale * DEFAULT_SCALE_DELTA).toFixed(2);
@@ -2530,16 +1972,17 @@ var PDFView = {
       newScale = Math.floor(newScale * 10) / 10;
       newScale = Math.max(MIN_SCALE, newScale);
     } while (--ticks && newScale > MIN_SCALE);
     this.setScale(newScale, true);
   },
 
   set page(val) {
     var pages = this.pages;
+    var input = document.getElementById('pageNumber');
     var event = document.createEvent('UIEvents');
     event.initUIEvent('pagechange', false, false, window, 0);
 
     if (!(0 < val && val <= pages.length)) {
       this.previousPageNumber = val;
       event.pageNumber = this.page;
       window.dispatchEvent(event);
       return;
@@ -2548,23 +1991,23 @@ var PDFView = {
     pages[val - 1].updateStats();
     this.previousPageNumber = currentPageNumber;
     currentPageNumber = val;
     event.pageNumber = val;
     window.dispatchEvent(event);
 
     // checking if the this.page was called from the updateViewarea function:
     // avoiding the creation of two "set page" method (internal and public)
-    if (updateViewarea.inProgress) {
+    if (updateViewarea.inProgress)
       return;
-    }
+
     // Avoid scrolling the first page during loading
-    if (this.loading && val === 1) {
+    if (this.loading && val == 1)
       return;
-    }
+
     pages[val - 1].scrollIntoView();
   },
 
   get page() {
     return currentPageNumber;
   },
 
   get supportsPrinting() {
@@ -2740,20 +2183,16 @@ var PDFView = {
       parameters.data = url;
     }
     if (args) {
       for (var prop in args) {
         parameters[prop] = args[prop];
       }
     }
 
-    // Terminate worker of the previous document if any.
-    if (this.pdfDocument) {
-      this.pdfDocument.destroy();
-    }
     this.pdfDocument = null;
     var self = this;
     self.loading = true;
     var passwordNeeded = function passwordNeeded(updatePassword, reason) {
       PasswordPrompt.updatePassword = updatePassword;
       PasswordPrompt.reason = reason;
       PasswordPrompt.show();
     };
@@ -2817,30 +2256,28 @@ var PDFView = {
       function getDataSuccess(data) {
         var blob = PDFJS.createBlob(data, 'application/pdf');
         downloadManager.download(blob, url, filename);
       },
       noData // Error occurred try downloading with just the url.
     ).then(null, noData);
   },
 
-  fallback: function pdfViewFallback(featureId) {
+  fallback: function pdfViewFallback() {
     // Only trigger the fallback once so we don't spam the user with messages
     // for one PDF.
     if (this.fellback)
       return;
     this.fellback = true;
     var url = this.url.split('#')[0];
-    FirefoxCom.request('fallback', { featureId: featureId, url: url },
-      function response(download) {
-        if (!download) {
-          return;
-        }
-        PDFView.download();
-      });
+    FirefoxCom.request('fallback', url, function response(download) {
+      if (!download)
+        return;
+      PDFView.download();
+    });
   },
 
   navigateTo: function pdfViewNavigateTo(dest) {
     var destString = '';
     var self = this;