plugins/pdfviewer

Thomas Brüderli bruederli at kolabsys.com
Mon Jan 20 16:41:52 CET 2014


 plugins/pdfviewer/README                                                     |    3 
 plugins/pdfviewer/pdfjs-viewer.diff                                          |  130 
 plugins/pdfviewer/viewer/compatibility.js                                    |   12 
 plugins/pdfviewer/viewer/debugger.js                                         |   10 
 plugins/pdfviewer/viewer/images/findbarButton-next-rtl.png                   |binary
 plugins/pdfviewer/viewer/images/findbarButton-next.png                       |binary
 plugins/pdfviewer/viewer/images/findbarButton-previous-rtl.png               |binary
 plugins/pdfviewer/viewer/images/findbarButton-previous.png                   |binary
 plugins/pdfviewer/viewer/images/loading-small.png                            |binary
 plugins/pdfviewer/viewer/images/secondaryToolbarButton-firstPage.png         |binary
 plugins/pdfviewer/viewer/images/secondaryToolbarButton-lastPage.png          |binary
 plugins/pdfviewer/viewer/images/secondaryToolbarButton-rotateCcw.png         |binary
 plugins/pdfviewer/viewer/images/secondaryToolbarButton-rotateCw.png          |binary
 plugins/pdfviewer/viewer/images/shadow.png                                   |binary
 plugins/pdfviewer/viewer/images/texture.png                                  |binary
 plugins/pdfviewer/viewer/images/toolbarButton-bookmark.png                   |binary
 plugins/pdfviewer/viewer/images/toolbarButton-download.png                   |binary
 plugins/pdfviewer/viewer/images/toolbarButton-menuArrows.png                 |binary
 plugins/pdfviewer/viewer/images/toolbarButton-openFile.png                   |binary
 plugins/pdfviewer/viewer/images/toolbarButton-pageDown-rtl.png               |binary
 plugins/pdfviewer/viewer/images/toolbarButton-pageDown.png                   |binary
 plugins/pdfviewer/viewer/images/toolbarButton-pageUp-rtl.png                 |binary
 plugins/pdfviewer/viewer/images/toolbarButton-pageUp.png                     |binary
 plugins/pdfviewer/viewer/images/toolbarButton-presentationMode.png           |binary
 plugins/pdfviewer/viewer/images/toolbarButton-print.png                      |binary
 plugins/pdfviewer/viewer/images/toolbarButton-search.png                     |binary
 plugins/pdfviewer/viewer/images/toolbarButton-secondaryToolbarToggle-rtl.png |binary
 plugins/pdfviewer/viewer/images/toolbarButton-secondaryToolbarToggle.png     |binary
 plugins/pdfviewer/viewer/images/toolbarButton-sidebarToggle-rtl.png          |binary
 plugins/pdfviewer/viewer/images/toolbarButton-sidebarToggle.png              |binary
 plugins/pdfviewer/viewer/images/toolbarButton-viewOutline-rtl.png            |binary
 plugins/pdfviewer/viewer/images/toolbarButton-viewOutline.png                |binary
 plugins/pdfviewer/viewer/images/toolbarButton-viewThumbnail.png              |binary
 plugins/pdfviewer/viewer/images/toolbarButton-zoomOut.png                    |binary
 plugins/pdfviewer/viewer/locale/de/viewer.properties                         |   31 
 plugins/pdfviewer/viewer/locale/en-US/viewer.properties                      |    5 
 plugins/pdfviewer/viewer/locale/es/viewer.properties                         |   18 
 plugins/pdfviewer/viewer/locale/ja/viewer.properties                         |   13 
 plugins/pdfviewer/viewer/locale/locale.properties                            |    4 
 plugins/pdfviewer/viewer/locale/nl/viewer.properties                         |    5 
 plugins/pdfviewer/viewer/locale/zh-CN/viewer.properties                      |   14 
 plugins/pdfviewer/viewer/locale/zh-TW/viewer.properties                      |   11 
 plugins/pdfviewer/viewer/pdf.js                                              | 7776 +++++++++-
 plugins/pdfviewer/viewer/pdf.min.js                                          |  178 
 plugins/pdfviewer/viewer/pdf.worker.js                                       | 5664 ++++---
 plugins/pdfviewer/viewer/viewer.css                                          |   93 
 plugins/pdfviewer/viewer/viewer.html                                         |  117 
 plugins/pdfviewer/viewer/viewer.js                                           | 5542 +++++++
 plugins/pdfviewer/viewer/viewer.min.js                                       |  164 
 49 files changed, 16952 insertions(+), 2838 deletions(-)

New commits:
commit dcac898f7d9a5551c18a7aa1a28821e7c45f0304
Author: Thomas Bruederli <thomas at roundcube.net>
Date:   Mon Jan 20 16:41:18 2014 +0100

    Updated pdfviewer plugin to latest version of pdf.js

diff --git a/plugins/pdfviewer/README b/plugins/pdfviewer/README
index 8949ac8..ecba65e 100644
--- a/plugins/pdfviewer/README
+++ b/plugins/pdfviewer/README
@@ -44,6 +44,9 @@ or the YUI Compressor [2].
 $ <roundcubedir>/bin/jsshrink.sh viewer/pdf.js ECMASCRIPT5
 $ <roundcubedir>/bin/jsshrink.sh viewer/viewer.js ECMASCRIPT5
 
+This will create minimized versions in viewer/*.min.js which are
+linked by the viewer.html template.
+
 [1] http://closure-compiler.googlecode.com/
 [2] http://developer.yahoo.com/yui/compressor/
 
diff --git a/plugins/pdfviewer/pdfjs-viewer.diff b/plugins/pdfviewer/pdfjs-viewer.diff
index 52a65c6..91bc469 100644
--- a/plugins/pdfviewer/pdfjs-viewer.diff
+++ b/plugins/pdfviewer/pdfjs-viewer.diff
@@ -1,57 +1,69 @@
---- viewer/viewer.html.orig	2013-10-03 14:06:24.000000000 +0200
-+++ viewer/viewer.html	2013-10-03 13:53:17.000000000 +0200
-@@ -31,7 +31,7 @@
+--- viewer/viewer.html.orig	2014-01-20 16:22:49.000000000 +0100
++++ viewer/viewer.html	2014-01-20 16:38:37.000000000 +0100
+@@ -31,12 +31,12 @@
  <!-- This snippet is used in production, see Makefile -->
  <link rel="resource" type="application/l10n" href="locale/locale.properties"/>
  <script type="text/javascript" src="l10n.js"></script>
 -<script type="text/javascript" src="../build/pdf.js"></script>
-+<script type="text/javascript" src="pdf.js"></script>
++<script type="text/javascript" src="pdf.min.js"></script>
  
  
  
-@@ -88,18 +88,10 @@
+     <script type="text/javascript" src="debugger.js"></script>
+-    <script type="text/javascript" src="viewer.js"></script>
++    <script type="text/javascript" src="viewer.min.js"></script>
+ 
+   </head>
+ 
+@@ -88,7 +88,7 @@
                <span data-l10n-id="presentation_mode_label">Presentation Mode</span>
              </button>
  
 -            <button id="secondaryOpenFile" class="secondaryToolbarButton openFile visibleLargeView" title="Open File" tabindex="19" data-l10n-id="open_file">
--              <span data-l10n-id="open_file_label">Open</span>
--            </button>
--
-             <button id="secondaryPrint" class="secondaryToolbarButton print visibleMediumView" title="Print" tabindex="20" data-l10n-id="print">
++            <button id="secondaryOpenFile" class="secondaryToolbarButton openFile hidden" title="Open File" tabindex="19" data-l10n-id="open_file">
+               <span data-l10n-id="open_file_label">Open</span>
+             </button>
+ 
+@@ -96,11 +96,11 @@
                <span data-l10n-id="print_label">Print</span>
              </button>
  
 -            <button id="secondaryDownload" class="secondaryToolbarButton download visibleMediumView" title="Download" tabindex="21" data-l10n-id="download">
--              <span data-l10n-id="download_label">Download</span>
--            </button>
--
-             <div class="horizontalToolbarSeparator visibleLargeView"></div>
++            <button id="secondaryDownload" class="secondaryToolbarButton download hidden" title="Download" tabindex="21" data-l10n-id="download">
+               <span data-l10n-id="download_label">Download</span>
+             </button>
+ 
+-            <a href="#" id="secondaryViewBookmark" class="secondaryToolbarButton bookmark visibleSmallView" title="Current view (copy or open in new window)" tabindex="22" data-l10n-id="bookmark">
++            <a href="#" id="secondaryViewBookmark" class="secondaryToolbarButton bookmark hidden" title="Current view (copy or open in new window)" tabindex="22" data-l10n-id="bookmark">
+               <span data-l10n-id="bookmark_label">Current View</span>
+             </a>
  
-             <button id="firstPage" class="secondaryToolbarButton firstPage" title="Go to First Page" tabindex="22" data-l10n-id="first_page">
-@@ -150,20 +142,10 @@
+@@ -159,7 +159,7 @@
                    <span data-l10n-id="presentation_mode_label">Presentation Mode</span>
                  </button>
  
 -                <button id="openFile" class="toolbarButton openFile hiddenLargeView" title="Open File" tabindex="13" data-l10n-id="open_file">
--                  <span data-l10n-id="open_file_label">Open</span>
--                </button>
--
-                 <button id="print" class="toolbarButton print hiddenMediumView" title="Print" tabindex="14" data-l10n-id="print">
++                <button id="openFile" class="toolbarButton openFile hidden" title="Open File" tabindex="13" data-l10n-id="open_file">
+                   <span data-l10n-id="open_file_label">Open</span>
+                 </button>
+ 
+@@ -167,11 +167,11 @@
                    <span data-l10n-id="print_label">Print</span>
                  </button>
  
 -                <button id="download" class="toolbarButton download hiddenMediumView" title="Download" tabindex="15" data-l10n-id="download">
--                  <span data-l10n-id="download_label">Download</span>
--                </button>
--                <!-- <div class="toolbarButtonSpacer"></div> -->
--                <a href="#" id="viewBookmark" class="toolbarButton bookmark hiddenSmallView" title="Current view (copy or open in new window)" tabindex="16" data-l10n-id="bookmark"><span data-l10n-id="bookmark_label">Current View</span></a>
--
-                 <div class="verticalToolbarSeparator hiddenSmallView"></div>
-                 
-                 <button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="17" data-l10n-id="tools">
---- viewer/viewer.js.orig	2013-10-03 14:06:30.000000000 +0200
-+++ viewer/viewer.js	2013-10-03 14:06:00.000000000 +0200
-@@ -22,7 +22,7 @@
++                <button id="download" class="toolbarButton download hidden" title="Download" tabindex="15" data-l10n-id="download">
+                   <span data-l10n-id="download_label">Download</span>
+                 </button>
+                 <!-- <div class="toolbarButtonSpacer"></div> -->
+-                <a href="#" id="viewBookmark" class="toolbarButton bookmark hiddenSmallView" title="Current view (copy or open in new window)" tabindex="16" data-l10n-id="bookmark">
++                <a href="#" id="viewBookmark" class="toolbarButton bookmark hidden" title="Current view (copy or open in new window)" tabindex="16" data-l10n-id="bookmark">
+                   <span data-l10n-id="bookmark_label">Current View</span>
+                 </a>
+ 
+--- viewer/viewer.js.orig	2014-01-20 16:22:49.000000000 +0100
++++ viewer/viewer.js	2014-01-20 16:32:24.000000000 +0100
+@@ -23,7 +23,7 @@
  
  'use strict';
  
@@ -60,7 +72,7 @@
  var DEFAULT_SCALE = 'auto';
  var DEFAULT_SCALE_DELTA = 1.1;
  var UNKNOWN_SCALE = 0;
-@@ -49,7 +49,7 @@
+@@ -55,7 +55,7 @@
  };
  
  PDFJS.imageResourcesPath = './images/';
@@ -69,19 +81,19 @@
  
  var mozL10n = document.mozL10n || document.webL10n;
  
-@@ -1313,9 +1313,9 @@
- 
-     this.presentationMode.addEventListener('click',
-       this.presentationModeClick.bind(this));
--    this.openFile.addEventListener('click', this.openFileClick.bind(this));
-+    //this.openFile.addEventListener('click', this.openFileClick.bind(this));
-     this.print.addEventListener('click', this.printClick.bind(this));
--    this.download.addEventListener('click', this.downloadClick.bind(this));
-+    //this.download.addEventListener('click', this.downloadClick.bind(this));
- 
-     this.firstPage.addEventListener('click', this.firstPageClick.bind(this));
-     this.lastPage.addEventListener('click', this.lastPageClick.bind(this));
-@@ -3991,8 +3991,8 @@
+@@ -1581,9 +1581,9 @@
+       // (except for toggleHandTool, hand_tool.js is responsible for it):
+       { element: this.presentationModeButton,
+         handler: this.presentationModeClick },
+-      { element: this.openFile, handler: this.openFileClick },
++      //{ element: this.openFile, handler: this.openFileClick },
+       { element: this.print, handler: this.printClick },
+-      { element: this.download, handler: this.downloadClick },
++      //{ element: this.download, handler: this.downloadClick },
+       { element: this.firstPage, handler: this.firstPageClick },
+       { element: this.lastPage, handler: this.lastPageClick },
+       { element: this.pageRotateCw, handler: this.pageRotateCwClick },
+@@ -4806,8 +4806,8 @@
    document.body.appendChild(fileInput);
  
    if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
@@ -92,7 +104,7 @@
    } else {
      document.getElementById('fileInput').value = null;
    }
-@@ -4147,14 +4147,14 @@
+@@ -4970,14 +4970,14 @@
    document.getElementById('presentationMode').addEventListener('click',
      SecondaryToolbar.presentationModeClick.bind(SecondaryToolbar));
  
@@ -109,29 +121,5 @@
 +//  document.getElementById('download').addEventListener('click',
 +//    SecondaryToolbar.downloadClick.bind(SecondaryToolbar));
  
-   document.getElementById('contextFirstPage').addEventListener('click',
-     SecondaryToolbar.firstPageClick.bind(SecondaryToolbar));
-@@ -4229,8 +4229,8 @@
-     store.set('scrollLeft', Math.round(topLeft[0]));
-     store.set('scrollTop', Math.round(topLeft[1]));
-   });
--  var href = PDFView.getAnchorUrl(pdfOpenParams);
--  document.getElementById('viewBookmark').href = href;
-+  //var href = PDFView.getAnchorUrl(pdfOpenParams);
-+  //document.getElementById('viewBookmark').href = href;
- 
-   // Update the current bookmark in the browsing history.
-   PDFHistory.updateCurrentBookmark(pdfOpenParams, pageNumber);
-@@ -4273,9 +4273,9 @@
-   PDFView.setTitleUsingUrl(file.name);
- 
-   // URL does not reflect proper document location - hiding some icons.
--  document.getElementById('viewBookmark').setAttribute('hidden', 'true');
--  document.getElementById('download').setAttribute('hidden', 'true');
--  document.getElementById('secondaryDownload').setAttribute('hidden', 'true');
-+  //document.getElementById('viewBookmark').setAttribute('hidden', 'true');
-+  //document.getElementById('download').setAttribute('hidden', 'true');
-+  //document.getElementById('secondaryDownload').setAttribute('hidden', 'true');
- }, true);
- 
- function selectScaleOption(value) {
+ 
+   PDFView.open(file, 0);
diff --git a/plugins/pdfviewer/viewer/compatibility.js b/plugins/pdfviewer/viewer/compatibility.js
index 23ca69e..433e617 100644
--- a/plugins/pdfviewer/viewer/compatibility.js
+++ b/plugins/pdfviewer/viewer/compatibility.js
@@ -361,12 +361,16 @@ if (typeof PDFJS === 'undefined') {
     if (index >= 0 && remove)
       list.splice(index, 1);
     element.className = list.join(' ');
+    return (index >= 0);
   }
 
   var classListPrototype = {
     add: function(name) {
       changeList(this.element, name, true, false);
     },
+    contains: function(name) {
+      return changeList(this.element, name, false, false);
+    },
     remove: function(name) {
       changeList(this.element, name, false, true);
     },
@@ -438,6 +442,14 @@ if (typeof PDFJS === 'undefined') {
   }
 })();
 
+// Checks if possible to use URL.createObjectURL()
+(function checkOnBlobSupport() {
+  // sometimes IE loosing the data created with createObjectURL(), see #3977
+  if (navigator.userAgent.indexOf('Trident') >= 0) {
+    PDFJS.disableCreateObjectURL = true;
+  }
+})();
+
 // Checks if navigator.language is supported
 (function checkNavigatorLanguage() {
   if ('language' in navigator)
diff --git a/plugins/pdfviewer/viewer/debugger.js b/plugins/pdfviewer/viewer/debugger.js
index da57fc3..a70ad0c 100644
--- a/plugins/pdfviewer/viewer/debugger.js
+++ b/plugins/pdfviewer/viewer/debugger.js
@@ -240,6 +240,8 @@ var Stepper = (function StepperClosure() {
     return out;
   }
 
+  var opMap = null;
+
   var glyphCommands = {
     'showText': 0,
     'showSpacedText': 0,
@@ -271,6 +273,12 @@ var Stepper = (function StepperClosure() {
       headerRow.appendChild(c('th', 'args'));
       panel.appendChild(content);
       this.table = table;
+      if (!opMap) {
+        opMap = Object.create(null);
+        for (var key in PDFJS.OPS) {
+          opMap[PDFJS.OPS[key]] = key;
+        }
+      }
     },
     updateOperatorList: function updateOperatorList(operatorList) {
       var self = this;
@@ -300,7 +308,7 @@ var Stepper = (function StepperClosure() {
         breakCell.appendChild(cbox);
         line.appendChild(breakCell);
         line.appendChild(c('td', i.toString()));
-        var fn = operatorList.fnArray[i];
+        var fn = opMap[operatorList.fnArray[i]];
         var decArgs = args;
         if (fn in glyphCommands) {
           var glyphIndex = glyphCommands[fn];
diff --git a/plugins/pdfviewer/viewer/images/findbarButton-next-rtl.png b/plugins/pdfviewer/viewer/images/findbarButton-next-rtl.png
index 08a2c25..4b5551e 100644
Binary files a/plugins/pdfviewer/viewer/images/findbarButton-next-rtl.png and b/plugins/pdfviewer/viewer/images/findbarButton-next-rtl.png differ
diff --git a/plugins/pdfviewer/viewer/images/findbarButton-next.png b/plugins/pdfviewer/viewer/images/findbarButton-next.png
index beef8cc..f681e4e 100644
Binary files a/plugins/pdfviewer/viewer/images/findbarButton-next.png and b/plugins/pdfviewer/viewer/images/findbarButton-next.png differ
diff --git a/plugins/pdfviewer/viewer/images/findbarButton-previous-rtl.png b/plugins/pdfviewer/viewer/images/findbarButton-previous-rtl.png
index beef8cc..f681e4e 100644
Binary files a/plugins/pdfviewer/viewer/images/findbarButton-previous-rtl.png and b/plugins/pdfviewer/viewer/images/findbarButton-previous-rtl.png differ
diff --git a/plugins/pdfviewer/viewer/images/findbarButton-previous.png b/plugins/pdfviewer/viewer/images/findbarButton-previous.png
index 08a2c25..4b5551e 100644
Binary files a/plugins/pdfviewer/viewer/images/findbarButton-previous.png and b/plugins/pdfviewer/viewer/images/findbarButton-previous.png differ
diff --git a/plugins/pdfviewer/viewer/images/loading-small.png b/plugins/pdfviewer/viewer/images/loading-small.png
index 1b2df80..51848a7 100644
Binary files a/plugins/pdfviewer/viewer/images/loading-small.png and b/plugins/pdfviewer/viewer/images/loading-small.png differ
diff --git a/plugins/pdfviewer/viewer/images/secondaryToolbarButton-firstPage.png b/plugins/pdfviewer/viewer/images/secondaryToolbarButton-firstPage.png
index 59b3d34..2c1076d 100644
Binary files a/plugins/pdfviewer/viewer/images/secondaryToolbarButton-firstPage.png and b/plugins/pdfviewer/viewer/images/secondaryToolbarButton-firstPage.png differ
diff --git a/plugins/pdfviewer/viewer/images/secondaryToolbarButton-lastPage.png b/plugins/pdfviewer/viewer/images/secondaryToolbarButton-lastPage.png
index 3967cc6..55a9efe 100644
Binary files a/plugins/pdfviewer/viewer/images/secondaryToolbarButton-lastPage.png and b/plugins/pdfviewer/viewer/images/secondaryToolbarButton-lastPage.png differ
diff --git a/plugins/pdfviewer/viewer/images/secondaryToolbarButton-rotateCcw.png b/plugins/pdfviewer/viewer/images/secondaryToolbarButton-rotateCcw.png
index ffe6293..d23d84a 100644
Binary files a/plugins/pdfviewer/viewer/images/secondaryToolbarButton-rotateCcw.png and b/plugins/pdfviewer/viewer/images/secondaryToolbarButton-rotateCcw.png differ
diff --git a/plugins/pdfviewer/viewer/images/secondaryToolbarButton-rotateCw.png b/plugins/pdfviewer/viewer/images/secondaryToolbarButton-rotateCw.png
index 1fe2a8f..f36bba8 100644
Binary files a/plugins/pdfviewer/viewer/images/secondaryToolbarButton-rotateCw.png and b/plugins/pdfviewer/viewer/images/secondaryToolbarButton-rotateCw.png differ
diff --git a/plugins/pdfviewer/viewer/images/shadow.png b/plugins/pdfviewer/viewer/images/shadow.png
index dd009dc..31d3bdb 100644
Binary files a/plugins/pdfviewer/viewer/images/shadow.png and b/plugins/pdfviewer/viewer/images/shadow.png differ
diff --git a/plugins/pdfviewer/viewer/images/texture.png b/plugins/pdfviewer/viewer/images/texture.png
index df00864..eb5ccb5 100644
Binary files a/plugins/pdfviewer/viewer/images/texture.png and b/plugins/pdfviewer/viewer/images/texture.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-bookmark.png b/plugins/pdfviewer/viewer/images/toolbarButton-bookmark.png
index 1e5259a..b27050e 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-bookmark.png and b/plugins/pdfviewer/viewer/images/toolbarButton-bookmark.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-download.png b/plugins/pdfviewer/viewer/images/toolbarButton-download.png
index 8676d8e..7755eee 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-download.png and b/plugins/pdfviewer/viewer/images/toolbarButton-download.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-menuArrows.png b/plugins/pdfviewer/viewer/images/toolbarButton-menuArrows.png
index 31b06b5..63a7c32 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-menuArrows.png and b/plugins/pdfviewer/viewer/images/toolbarButton-menuArrows.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-openFile.png b/plugins/pdfviewer/viewer/images/toolbarButton-openFile.png
index fc7023f..e139f30 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-openFile.png and b/plugins/pdfviewer/viewer/images/toolbarButton-openFile.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-pageDown-rtl.png b/plugins/pdfviewer/viewer/images/toolbarButton-pageDown-rtl.png
index c0051f8..9ba3667 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-pageDown-rtl.png and b/plugins/pdfviewer/viewer/images/toolbarButton-pageDown-rtl.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-pageDown.png b/plugins/pdfviewer/viewer/images/toolbarButton-pageDown.png
index 762ac43..272a3ca 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-pageDown.png and b/plugins/pdfviewer/viewer/images/toolbarButton-pageDown.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-pageUp-rtl.png b/plugins/pdfviewer/viewer/images/toolbarButton-pageUp-rtl.png
index 0d49d8e..da02bc6 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-pageUp-rtl.png and b/plugins/pdfviewer/viewer/images/toolbarButton-pageUp-rtl.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-pageUp.png b/plugins/pdfviewer/viewer/images/toolbarButton-pageUp.png
index 3155b8b..a4d6c8e 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-pageUp.png and b/plugins/pdfviewer/viewer/images/toolbarButton-pageUp.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-presentationMode.png b/plugins/pdfviewer/viewer/images/toolbarButton-presentationMode.png
index fa73095..2bd1c1d 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-presentationMode.png and b/plugins/pdfviewer/viewer/images/toolbarButton-presentationMode.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-print.png b/plugins/pdfviewer/viewer/images/toolbarButton-print.png
index fef84dd..ccc6208 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-print.png and b/plugins/pdfviewer/viewer/images/toolbarButton-print.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-search.png b/plugins/pdfviewer/viewer/images/toolbarButton-search.png
index 604e652..e52370e 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-search.png and b/plugins/pdfviewer/viewer/images/toolbarButton-search.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-secondaryToolbarToggle-rtl.png b/plugins/pdfviewer/viewer/images/toolbarButton-secondaryToolbarToggle-rtl.png
index 9793024..145316b 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-secondaryToolbarToggle-rtl.png and b/plugins/pdfviewer/viewer/images/toolbarButton-secondaryToolbarToggle-rtl.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-secondaryToolbarToggle.png b/plugins/pdfviewer/viewer/images/toolbarButton-secondaryToolbarToggle.png
index ddd8a87..02ed6c6 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-secondaryToolbarToggle.png and b/plugins/pdfviewer/viewer/images/toolbarButton-secondaryToolbarToggle.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-sidebarToggle-rtl.png b/plugins/pdfviewer/viewer/images/toolbarButton-sidebarToggle-rtl.png
index d9946fd..c308668 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-sidebarToggle-rtl.png and b/plugins/pdfviewer/viewer/images/toolbarButton-sidebarToggle-rtl.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-sidebarToggle.png b/plugins/pdfviewer/viewer/images/toolbarButton-sidebarToggle.png
index 5a937c7..be9eceb 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-sidebarToggle.png and b/plugins/pdfviewer/viewer/images/toolbarButton-sidebarToggle.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-viewOutline-rtl.png b/plugins/pdfviewer/viewer/images/toolbarButton-viewOutline-rtl.png
index d57a12c..21ceb3b 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-viewOutline-rtl.png and b/plugins/pdfviewer/viewer/images/toolbarButton-viewOutline-rtl.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-viewOutline.png b/plugins/pdfviewer/viewer/images/toolbarButton-viewOutline.png
index cb3967b..9b2e2f5 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-viewOutline.png and b/plugins/pdfviewer/viewer/images/toolbarButton-viewOutline.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-viewThumbnail.png b/plugins/pdfviewer/viewer/images/toolbarButton-viewThumbnail.png
index 3a27f04..d71dd27 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-viewThumbnail.png and b/plugins/pdfviewer/viewer/images/toolbarButton-viewThumbnail.png differ
diff --git a/plugins/pdfviewer/viewer/images/toolbarButton-zoomOut.png b/plugins/pdfviewer/viewer/images/toolbarButton-zoomOut.png
index 810fbf9..7991ee7 100644
Binary files a/plugins/pdfviewer/viewer/images/toolbarButton-zoomOut.png and b/plugins/pdfviewer/viewer/images/toolbarButton-zoomOut.png differ
diff --git a/plugins/pdfviewer/viewer/locale/de/viewer.properties b/plugins/pdfviewer/viewer/locale/de/viewer.properties
index 5988c82..c9908b5 100644
--- a/plugins/pdfviewer/viewer/locale/de/viewer.properties
+++ b/plugins/pdfviewer/viewer/locale/de/viewer.properties
@@ -42,6 +42,8 @@ bookmark.title=Aktuelle Ansicht (Kopieren oder in einem neuen Fenster öffnen)
 bookmark_label=Aktuelle Ansicht
 
 # Secondary toolbar and context menu
+tools.title=Werkzeuge
+tools_label=Werkzeuge
 first_page.title=Erste Seite
 first_page.label=Erste Seite
 first_page_label=Erste Seite
@@ -51,9 +53,14 @@ last_page_label=Letzte Seite
 page_rotate_cw.title=Im Uhrzeigersinn drehen
 page_rotate_cw.label=Im Uhrzeigersinn drehen
 page_rotate_cw_label=Im Uhrzeigersinn drehen
-page_rotate_ccw.title=Entgegen dem Uhrzeigersinn drehen
-page_rotate_ccw.label=Entgegen dem Uhrzeigersinn drehen
-page_rotate_ccw_label=Entgegen dem Uhrzeigersinn drehen
+page_rotate_ccw.title=Gegen den Uhrzeigersinn drehen
+page_rotate_ccw.label=Gegen den Uhrzeigersinn drehen
+page_rotate_ccw_label=Gegen den Uhrzeigersinn drehen
+
+hand_tool_enable.title=Hand-Werkzeug aktivieren
+hand_tool_enable_label=Hand-Werkzeug aktivieren
+hand_tool_disable.title=Hand-Werkzeug deaktivieren
+hand_tool_disable_label=Hand-Werkzeug deaktivieren
 
 # Tooltips and alt text for side panel toolbar buttons
 # (the _label strings are alt text for the buttons, the .title strings are
@@ -91,9 +98,9 @@ find_not_found=Ausdruck nicht gefunden
 error_more_info=Mehr Info
 error_less_info=Weniger Info
 error_close=Schließen
-# LOCALIZATION NOTE (error_build): "{{build}}" will be replaced by the PDF.JS
-# build ID.
-error_build=PDF.JS Build: {{build}}
+# LOCALIZATION NOTE (error_version_info): "{{version}}" and "{{build}}" will be
+# replaced by the PDF.JS version and build ID.
+error_version_info=PDF.js v{{version}} (build: {{build}})
 # LOCALIZATION NOTE (error_message): "{{message}}" will be replaced by an
 # english string describing the error.
 error_message=Nachricht: {{message}}
@@ -104,7 +111,7 @@ error_stack=Stack: {{stack}}
 error_file=Datei: {{file}}
 # LOCALIZATION NOTE (error_line): "{{line}}" will be replaced with a line number
 error_line=Zeile: {{line}}
-rendering_error=Das PDF konnte nicht angezeigt werden.
+rendering_error=Die PDF-Datei konnte nicht angezeigt werden.
 
 # Predefined zoom values
 page_scale_width=Seitenbreite
@@ -114,15 +121,21 @@ page_scale_actual=Originalgröße
 
 # Loading indicator messages
 loading_error_indicator=Fehler
-loading_error=Das PDF konnte nicht geladen werden.
+loading_error=Die PDF-Datei konnte nicht geladen werden.
 invalid_file_error=Ungültige oder beschädigte PDF-Datei.
+missing_file_error=Fehlende PDF-Datei.
 
 # LOCALIZATION NOTE (text_annotation_type.alt): This is used as a tooltip.
 # "{{type}}" will be replaced with an annotation type from a list defined in
 # the PDF spec (32000-1:2008 Table 169 – Annotation types).
 # Some common types are e.g.: "Check", "Text", "Comment", "Note"
 text_annotation_type.alt=[{{type}} Annotation]
-request_password=Das PDF ist passwortgeschützt:
+password_label=Geben Sie das Passwort ein, um diese Datei zu öffnen.
+password_invalid=Ungültiges Passwort. Versuchen Sie es erneut.
+password_ok=OK
+password_cancel=Abbrechen
 
 printing_not_supported=Warnung: Drucken wird durch diesen Browser nicht vollständig unterstützt.
+printing_not_ready=Warnung: Die PDF-Datei ist zum Drucken noch nicht vollständig geladen.
 web_fonts_disabled=Webfonts sind deaktiviert: Eingebundene PDF-Schriftarten können nicht verwendet werden.
+document_colors_disabled=PDF-Dateien können eigene Farben nicht verwenden: \'Seiten das Verwenden von eigenen Farben erlauben\' ist im Browser deaktiviert.
diff --git a/plugins/pdfviewer/viewer/locale/en-US/viewer.properties b/plugins/pdfviewer/viewer/locale/en-US/viewer.properties
index 629bfb2..2c893a4 100644
--- a/plugins/pdfviewer/viewer/locale/en-US/viewer.properties
+++ b/plugins/pdfviewer/viewer/locale/en-US/viewer.properties
@@ -57,6 +57,11 @@ page_rotate_ccw.title=Rotate Counterclockwise
 page_rotate_ccw.label=Rotate Counterclockwise
 page_rotate_ccw_label=Rotate Counterclockwise
 
+hand_tool_enable.title=Enable hand tool
+hand_tool_enable_label=Enable hand tool
+hand_tool_disable.title=Disable hand tool
+hand_tool_disable_label=Disable hand tool
+
 # Tooltips and alt text for side panel toolbar buttons
 # (the _label strings are alt text for the buttons, the .title strings are
 # tooltips)
diff --git a/plugins/pdfviewer/viewer/locale/es/viewer.properties b/plugins/pdfviewer/viewer/locale/es/viewer.properties
index 188cbed..fc8848f 100644
--- a/plugins/pdfviewer/viewer/locale/es/viewer.properties
+++ b/plugins/pdfviewer/viewer/locale/es/viewer.properties
@@ -38,10 +38,12 @@ print.title=Imprimir
 print_label=Imprimir
 download.title=Descargar
 download_label=Descargar
-bookmark.title=Vista actual (copie o abra en una ventana nueva)
+bookmark.title=Vista actual (para copiar o abrir en otra ventana)
 bookmark_label=Vista actual
 
 # Secondary toolbar and context menu
+tools.title=Herramientas
+tools_label=Herramientas
 first_page.title=Ir a la primera página
 first_page.label=Ir a la primera página
 first_page_label=Ir a la primera página
@@ -55,6 +57,11 @@ page_rotate_ccw.title=Girar a la izquierda
 page_rotate_ccw.label=Girar a la izquierda
 page_rotate_ccw_label=Girar a la izquierda
 
+hand_tool_enable.title=Activar la herramienta Mano
+hand_tool_enable_label=Activar la herramienta Mano
+hand_tool_disable.title=Desactivar la herramienta Mano
+hand_tool_disable_label=Desactivar la herramienta Mano
+
 # Tooltips and alt text for side panel toolbar buttons
 # (the _label strings are alt text for the buttons, the .title strings are
 # tooltips)
@@ -118,14 +125,17 @@ loading_error=Ocurrió un error al cargar el PDF.
 invalid_file_error=El archivo PDF no es válido o está dañado.
 missing_file_error=Falta el archivo PDF.
 
-# LOCALIZATION NOTE (text_annotation_type): This is used as a tooltip.
+# LOCALIZATION NOTE (text_annotation_type.alt): This is used as a tooltip.
 # "{{type}}" will be replaced with an annotation type from a list defined in
 # the PDF spec (32000-1:2008 Table 169 – Annotation types).
 # Some common types are e.g.: "Check", "Text", "Comment", "Note"
 text_annotation_type.alt=[Anotación {{type}}]
-request_password=El archivo PDF está protegido por una contraseña:
+password_label=Escriba la contraseña para abrir este archivo PDF.
+password_invalid=La contraseña no es válida. Inténtelo de nuevo.
+password_ok=Aceptar
+password_cancel=Cancelar
 
 printing_not_supported=Aviso: Este navegador no es compatible completamente con la impresión.
 printing_not_ready=Aviso: El PDF no se ha cargado completamente para su impresión.
 web_fonts_disabled=Se han desactivado los tipos de letra web: no se pueden usar los tipos de letra incrustados en el PDF.
-web_colors_disabled=Se han desactivado los colores web.
+document_colors_disabled=No se permite que los documentos PDF usen sus propios colores: la opción «Permitir que las páginas elijan sus propios colores» está desactivada en el navegador.
diff --git a/plugins/pdfviewer/viewer/locale/ja/viewer.properties b/plugins/pdfviewer/viewer/locale/ja/viewer.properties
index dd024ca..3b35bbd 100644
--- a/plugins/pdfviewer/viewer/locale/ja/viewer.properties
+++ b/plugins/pdfviewer/viewer/locale/ja/viewer.properties
@@ -23,7 +23,7 @@ next_label=次へ
 # Do not translate "{{pageCount}}", it will be substituted with a number
 # representing the total number of pages.
 page_label=ページ:
-page_of=of {{pageCount}}
+page_of=/ {{pageCount}}
 
 zoom_out.title=縮小
 zoom_out_label=縮小
@@ -57,6 +57,11 @@ page_rotate_ccw.title=左回転
 page_rotate_ccw.label=左回転
 page_rotate_ccw_label=左回転
 
+hand_tool_enable.title=手のひらツールを有効にする
+hand_tool_enable_label=手のひらツールを有効にする
+hand_tool_disable.title=手のひらツールを無効にする
+hand_tool_disable_label=手のひらツールを無効にする
+
 # Tooltips and alt text for side panel toolbar buttons
 # (the _label strings are alt text for the buttons, the .title strings are
 # tooltips)
@@ -125,8 +130,10 @@ missing_file_error=PDF ファイルが見つかりません。
 # the PDF spec (32000-1:2008 Table 169 – Annotation types).
 # Some common types are e.g.: "Check", "Text", "Comment", "Note"
 text_annotation_type.alt=[{{type}} 注釈]
-request_password=PDF はパスワードによって保護されています
-invalid_password=無効なパスワードです
+password_label=この PDF ファイルを開くためのパスワードを入力してください。
+password_invalid=無効なパスワードです。もう一度やり直してください。
+password_ok=OK
+password_cancel=キャンセル
 
 printing_not_supported=警告:このブラウザでは印刷が完全にサポートされていません
 printing_not_ready=警告:PDF を印刷するための読み込みが終了していません
diff --git a/plugins/pdfviewer/viewer/locale/locale.properties b/plugins/pdfviewer/viewer/locale/locale.properties
index d706328..7e94bc6 100644
--- a/plugins/pdfviewer/viewer/locale/locale.properties
+++ b/plugins/pdfviewer/viewer/locale/locale.properties
@@ -70,8 +70,8 @@
 [sr]
 @import url(sr/viewer.properties)
 
-[sv]
- at import url(sv/viewer.properties)
+[sv-SE]
+ at import url(sv-SE/viewer.properties)
 
 [tr]
 @import url(tr/viewer.properties)
diff --git a/plugins/pdfviewer/viewer/locale/nl/viewer.properties b/plugins/pdfviewer/viewer/locale/nl/viewer.properties
index 9288af8..38f266d 100644
--- a/plugins/pdfviewer/viewer/locale/nl/viewer.properties
+++ b/plugins/pdfviewer/viewer/locale/nl/viewer.properties
@@ -57,6 +57,11 @@ page_rotate_ccw.title=Tegen de klok in roteren
 page_rotate_ccw.label=Tegen de klok in roteren
 page_rotate_ccw_label=Tegen de klok in roteren
 
+hand_tool_enable.title=Handcursor inschakelen
+hand_tool_enable_label=Handcursor inschakelen
+hand_tool_disable.title=Handcursor uitschakelen
+hand_tool_disable_label=Handcursor uitschakelen
+
 # Tooltips and alt text for side panel toolbar buttons
 # (the _label strings are alt text for the buttons, the .title strings are
 # tooltips)
diff --git a/plugins/pdfviewer/viewer/locale/zh-CN/viewer.properties b/plugins/pdfviewer/viewer/locale/zh-CN/viewer.properties
index 28a9971..bbc77c2 100644
--- a/plugins/pdfviewer/viewer/locale/zh-CN/viewer.properties
+++ b/plugins/pdfviewer/viewer/locale/zh-CN/viewer.properties
@@ -42,6 +42,8 @@ bookmark.title=当前视图(复制或在新窗口中打开)
 bookmark_label=当前视图
 
 # Secondary toolbar and context menu
+tools.title=工具
+tools_label=工具
 first_page.title=转到第一页
 first_page.label=转到第一页
 first_page_label=转到第一页
@@ -55,6 +57,11 @@ page_rotate_ccw.title=逆时针旋转
 page_rotate_ccw.label=逆时针旋转
 page_rotate_ccw_label=逆时针旋转
 
+hand_tool_enable.title=启用掌型工具
+hand_tool_enable_label=启用掌型工具
+hand_tool_disable.title=禁用掌型工具
+hand_tool_disable_label=禁用掌型工具
+
 # Tooltips and alt text for side panel toolbar buttons
 # (the _label strings are alt text for the buttons, the .title strings are
 # tooltips)
@@ -123,7 +130,12 @@ missing_file_error=缺失 PDF 文件。
 # the PDF spec (32000-1:2008 Table 169 – Annotation types).
 # Some common types are e.g.: "Check", "Text", "Comment", "Note"
 text_annotation_type.alt=[{{type}} 注解]
-request_password=该 PDF 文档受密码保护:
+password_label=输入 PDF 文件的密码。
+password_invalid=密码无效,请重新输入。
+password_ok=确定
+password_cancel=取消
 
 printing_not_supported=警告:该浏览器不能完全支持打印。
+printing_not_ready=警告:此 PDF 没有完全被载入以供打印。
 web_fonts_disabled=Web 页面字体已被禁用,无法使用嵌入到 PDF 中的字体。
+document_colors_disabled=PDF 文件不被允许使用自己的颜色:\‘允许页面选择自己的颜色’\没有在该浏览器中被激活。
diff --git a/plugins/pdfviewer/viewer/locale/zh-TW/viewer.properties b/plugins/pdfviewer/viewer/locale/zh-TW/viewer.properties
index 766ff14..3456495 100644
--- a/plugins/pdfviewer/viewer/locale/zh-TW/viewer.properties
+++ b/plugins/pdfviewer/viewer/locale/zh-TW/viewer.properties
@@ -57,6 +57,11 @@ page_rotate_ccw.title=逆時針旋轉
 page_rotate_ccw.label=逆時針旋轉
 page_rotate_ccw_label=逆時針旋轉
 
+hand_tool_enable.title=啟用掌型工具
+hand_tool_enable_label=啟用掌型工具
+hand_tool_disable.title=停用掌型工具
+hand_tool_disable_label=停用掌型工具
+
 # Tooltips and alt text for side panel toolbar buttons
 # (the _label strings are alt text for the buttons, the .title strings are
 # tooltips)
@@ -125,8 +130,10 @@ missing_file_error=找不到 PDF 檔案。
 # the PDF spec (32000-1:2008 Table 169 – Annotation types).
 # Some common types are e.g.: "Check", "Text", "Comment", "Note"
 text_annotation_type.alt=[{{type}} 註解]
-request_password=PDF 已被密碼保護:
-invalid_password=密碼無效。
+password_label=請輸入用來開啟此 PDF 檔案的密碼。
+password_invalid=密碼不正確,請再試一次。
+password_ok=確定
+password_cancel=取消
 
 printing_not_supported=警告: 此瀏覽器未完整支援列印功能。
 printing_not_ready=警告: 此 PDF 未完成下載以供列印。
diff --git a/plugins/pdfviewer/viewer/pdf.js b/plugins/pdfviewer/viewer/pdf.js
index 0ff40a1..c3723f5 100644
--- a/plugins/pdfviewer/viewer/pdf.js
+++ b/plugins/pdfviewer/viewer/pdf.js
@@ -1,166 +1,7610 @@
-"undefined"===typeof PDFJS&&(("undefined"!==typeof window?window:this).PDFJS={});PDFJS.version="0.8.573";PDFJS.build="e97e003";
-(function(){var D,V;function S(b){ba>=na&&(J("Info: "+b),PDFJS.LogManager.notify("info",b))}function F(b){ba>=ca&&(J("Warning: "+b),PDFJS.LogManager.notify("warn",b))}function m(b){if(1<arguments.length){var a=["Error:"];a.push.apply(a,arguments);J.apply(null,a);b=[].join.call(arguments," ")}else J("Error: "+b);var a=J,c;try{throw Error();}catch(e){c=e.stack?e.stack.split("\n").slice(2).join("\n"):""}a(c);PDFJS.LogManager.notify("error",b);throw Error(b);}function K(b){F("TODO: "+b)}function oa(b,
-a){if(!a)return b;if(0<=a.indexOf(":"))return a;if("/"==a.charAt(0)){var c=b.indexOf("://"),c=b.indexOf("/",c+3);return b.substring(0,c)+a}var e=b.length,c=b.lastIndexOf("#"),e=0<=c?c:e,c=b.lastIndexOf("?",e),c=b.lastIndexOf("/",0<=c?c:e);return b.substring(0,c+1)+a}function Y(b,a){if(!b)return!1;var c=b.indexOf(":");if(0>c)return a;switch(b.substr(0,c)){case "http":case "https":case "ftp":case "mailto":return!0;default:return!1}}function W(b,a,c){Object.defineProperty(b,a,{value:c,enumerable:!0,
-configurable:!0,writable:!1});return c}function T(b){var a,c=b.length,e="";if("\u00fe"===b[0]&&"\u00ff"===b[1])for(a=2;a<c;a+=2)e+=String.fromCharCode(b.charCodeAt(a)<<8|b.charCodeAt(a+1));else for(a=0;a<c;++a)var d=pa[b.charCodeAt(a)],e=e+(d?String.fromCharCode(d):b.charAt(a));return e}function L(b){return"boolean"==typeof b}function M(b){return b instanceof Name}function O(b,a){if(!(b instanceof Dict))return!1;if(!a)return!0;var c=b.get("Type");return M(c)&&c.name==a}function B(b){return b instanceof
-Array}function X(b){return"object"==typeof b&&null!==b&&void 0!==b&&"getBytes"in b}function da(b){if("object"!=typeof b)return!1;if(!O(b))if(X(b))b=b.dict;else return!1;return b.has("FunctionType")}function Z(b,a){this.name=b;this.comObj=a;this.callbackIndex=1;var c=this.callbacks={},e=this.actionHandler={};e.console_log=[function(a){J.apply(null,a)}];e.console_error="console"in v?[function(a){v.console.error.apply(null,a)}]:[function(a){J.apply(null,a)}];e._warn=[function(a){F(a)}];a.onmessage=function(d){var b=
-d.data;if(b.isReply)if(d=b.callbackId,b.callbackId in c){var f=c[d];delete c[d];f(b.data)}else m("Cannot resolve callback "+d);else b.action in e?(d=e[b.action],b.callbackId?(f=new x,f.then(function(c){a.postMessage({isReply:!0,callbackId:b.callbackId,data:c})}),d[0].call(d[1],b.data,f)):d[0].call(d[1],b.data)):m("Unkown action from worker: "+b.action)}}function qa(b,a,c){var e=new Image;e.onload=function(){c.resolve(b,e)};e.src="data:image/jpeg;base64,"+window.btoa(a)}function ea(b,a){var c=document.createElement("canvas");
-c.width=b;c.height=a;return c}function fa(b){b.mozCurrentTransform||(b._scaleX=b._scaleX||1,b._scaleY=b._scaleY||1,b._originalSave=b.save,b._originalRestore=b.restore,b._originalRotate=b.rotate,b._originalScale=b.scale,b._originalTranslate=b.translate,b._originalTransform=b.transform,b._originalSetTransform=b.setTransform,b._transformMatrix=[b._scaleX,0,0,b._scaleY,0,0],b._transformStack=[],Object.defineProperty(b,"mozCurrentTransform",{get:function(){return this._transformMatrix}}),Object.defineProperty(b,
-"mozCurrentTransformInverse",{get:function(){var a=this._transformMatrix,c=a[0],e=a[1],d=a[2],b=a[3],f=a[4],a=a[5],k=c*b-e*d,h=e*d-c*b;return[b/k,e/h,d/h,c/k,(b*f-d*a)/h,(e*f-c*a)/k]}}),b.save=function(){var a=this._transformMatrix;this._transformStack.push(a);this._transformMatrix=a.slice(0,6);this._originalSave()},b.restore=function(){var a=this._transformStack.pop();a&&(this._transformMatrix=a,this._originalRestore())},b.translate=function(a,c){var e=this._transformMatrix;e[4]=e[0]*a+e[2]*c+e[4];
-e[5]=e[1]*a+e[3]*c+e[5];this._originalTranslate(a,c)},b.scale=function(a,c){var e=this._transformMatrix;e[0]*=a;e[1]*=a;e[2]*=c;e[3]*=c;this._originalScale(a,c)},b.transform=function(a,c,e,d,g,f){var k=this._transformMatrix;this._transformMatrix=[k[0]*a+k[2]*c,k[1]*a+k[3]*c,k[0]*e+k[2]*d,k[1]*e+k[3]*d,k[0]*g+k[2]*f+k[4],k[1]*g+k[3]*f+k[5]];b._originalTransform(a,c,e,d,g,f)},b.setTransform=function(a,c,e,d,g,f){this._transformMatrix=[a,c,e,d,g,f];b._originalSetTransform(a,c,e,d,g,f)},b.rotate=function(a){var c=
-Math.cos(a),e=Math.sin(a),d=this._transformMatrix;this._transformMatrix=[d[0]*c+d[2]*e,d[1]*c+d[3]*e,d[0]*-e+d[2]*c,d[1]*-e+d[3]*c,d[4],d[5]];this._originalRotate(a)})}function ra(b){var a=b.width,c=b.height,e,d,g=a+1,f=new Uint8Array(g*(c+1)),k=new Uint8Array([0,2,4,0,1,0,5,4,8,10,0,8,0,2,1,0]),h=3,l=b.data,n=4*a,t=0;0!==l[3]&&(f[0]=1,++t);for(e=1;e<a;e++)l[h]!==l[h+4]&&(f[e]=l[h]?2:1,++t),h+=4;0!==l[h]&&(f[e]=2,++t);h+=4;for(b=1;b<c;b++){d=b*g;l[h-n]!==l[h]&&(f[d]=l[h]?1:8,++t);var y=(l[h]?4:0)+
-(l[h-n]?8:0);for(e=1;e<a;e++)y=(y>>2)+(l[h+4]?4:0)+(l[h-n+4]?8:0),k[y]&&(f[d+e]=k[y],++t),h+=4;l[h-n]!==l[h]&&(f[d+e]=l[h]?2:4,++t);h+=4;if(1E3<t)return null}h-=n;d=b*g;0!==l[h]&&(f[d]=8,++t);for(e=1;e<a;e++)l[h]!==l[h+4]&&(f[d+e]=l[h]?4:8,++t),h+=4;0!==l[h]&&(f[d+e]=4,++t);if(1E3<t)return null;var k=new Int32Array([0,g,-1,0,-g,0,0,0,1]),q=[];for(b=0;t&&b<=c;b++){h=b*g;for(e=h+a;h<e&&!f[h];)h++;if(h!==e){e=[h%g,b];d=f[h];l=h;do{n=k[d];do h+=n;while(!f[h]);n=f[h];5!==n&&10!==n?(d=n,f[h]=0):(d=n&51*
-d>>4,f[h]&=d>>2|d<<2);e.push(h%g);e.push(h/g|0);--t}while(l!==h);q.push(e);--b}}return function(f){f.save();f.scale(1/a,-1/c);f.translate(0,-c);f.beginPath();for(var d=0,e=q.length;d<e;d++){var b=q[d];f.moveTo(b[0],b[1]);for(var k=2,h=b.length;k<h;k+=2)f.lineTo(b[k],b[k+1])}f.fill();f.beginPath();f.restore()}}var v="undefined"===typeof window?this:window,U="undefined"==typeof window,ca=1,na=5,ba=ca,$=[0.0010,0,0,0.0010,0,0];V=0;v.PDFJS||(v.PDFJS={});v.PDFJS.pdfBug=!1;var J=function(){return"console"in
-v&&"log"in v.console?v.console.log.bind(v.console):function(){}}();PDFJS.isValidUrl=Y;PDFJS.LogManager=function(){var b=[];return{addLogger:function(a){b.push(a)},notify:function(a,c){for(var e=0,d=b.length;e<d;e++){var g=b[e];if(g[a])g[a](c)}}}}();var ga=PDFJS.PasswordResponses={NEED_PASSWORD:1,INCORRECT_PASSWORD:2};(function(){function b(a,c){this.name="PasswordException";this.message=a;this.code=c}b.prototype=Error();return b.constructor=b})();(function(){function b(a,c){this.name="UnknownErrorException";
-this.message=a;this.details=c}b.prototype=Error();return b.constructor=b})();(function(){function b(a){this.name="InvalidPDFException";this.message=a}b.prototype=Error();return b.constructor=b})();(function(){function b(a){this.name="MissingPDFException";this.message=a}b.prototype=Error();return b.constructor=b})();var sa=function(){function b(a){this.message=a}b.prototype=Error();b.prototype.name="NotImplementedException";return b.constructor=b}();(function(){function b(a,c){this.begin=a;this.end=
-c;this.message="Missing data [begin, end)"}b.prototype=Error();b.prototype.name="MissingDataException";return b.constructor=b})();(function(){function b(a){this.message=a}b.prototype=Error();b.prototype.name="XRefParseException";return b.constructor=b})();var ha=[1,0,0,1,0,0],s=PDFJS.Util=function(){function b(){}b.makeCssRgb=function(a){return"rgb("+a[0]+","+a[1]+","+a[2]+")"};b.makeCssCmyk=function(a){a=p.singletons.cmyk.getRgb(a,0);return b.makeCssRgb(a)};b.transform=function(a,c){return[a[0]*
-c[0]+a[2]*c[1],a[1]*c[0]+a[3]*c[1],a[0]*c[2]+a[2]*c[3],a[1]*c[2]+a[3]*c[3],a[0]*c[4]+a[2]*c[5]+a[4],a[1]*c[4]+a[3]*c[5]+a[5]]};b.applyTransform=function(a,c){return[a[0]*c[0]+a[1]*c[2]+c[4],a[0]*c[1]+a[1]*c[3]+c[5]]};b.applyInverseTransform=function(a,c){var e=c[0]*c[3]-c[1]*c[2];return[(a[0]*c[3]-a[1]*c[2]+c[2]*c[5]-c[4]*c[3])/e,(-a[0]*c[1]+a[1]*c[0]+c[4]*c[1]-c[5]*c[0])/e]};b.getAxialAlignedBoundingBox=function(a,c){var e=b.applyTransform(a,c),d=b.applyTransform(a.slice(2,4),c),g=b.applyTransform([a[0],
-a[3]],c),f=b.applyTransform([a[2],a[1]],c);return[Math.min(e[0],d[0],g[0],f[0]),Math.min(e[1],d[1],g[1],f[1]),Math.max(e[0],d[0],g[0],f[0]),Math.max(e[1],d[1],g[1],f[1])]};b.inverseTransform=function(a){var c=a[0]*a[3]-a[1]*a[2];return[a[3]/c,-a[1]/c,-a[2]/c,a[0]/c,(a[2]*a[5]-a[4]*a[3])/c,(a[4]*a[1]-a[5]*a[0])/c]};b.apply3dTransform=function(a,c){return[a[0]*c[0]+a[1]*c[1]+a[2]*c[2],a[3]*c[0]+a[4]*c[1]+a[5]*c[2],a[6]*c[0]+a[7]*c[1]+a[8]*c[2]]};b.singularValueDecompose2dScale=function(a){var c=[a[0],
-a[2],a[1],a[3]],e=a[0]*c[0]+a[1]*c[2],d=a[2]*c[1]+a[3]*c[3],b=(e+d)/2;a=Math.sqrt((e+d)*(e+d)-4*(e*d-(a[2]*c[0]+a[3]*c[2])*(a[0]*c[1]+a[1]*c[3])))/2;c=b-a||1;return[Math.sqrt(b+a||1),Math.sqrt(c)]};b.normalizeRect=function(a){var c=a.slice(0);a[0]>a[2]&&(c[0]=a[2],c[2]=a[0]);a[1]>a[3]&&(c[1]=a[3],c[3]=a[1]);return c};b.intersect=function(a,c){function e(a,c){return a-c}var d=[a[0],a[2],c[0],c[2]].sort(e),g=[a[1],a[3],c[1],c[3]].sort(e),f=[];a=b.normalizeRect(a);c=b.normalizeRect(c);if(d[0]===a[0]&&
-d[1]===c[0]||d[0]===c[0]&&d[1]===a[0])f[0]=d[1],f[2]=d[2];else return!1;if(g[0]===a[1]&&g[1]===c[1]||g[0]===c[1]&&g[1]===a[1])f[1]=g[1],f[3]=g[2];else return!1;return f};b.sign=function(a){return 0>a?-1:1};b.concatenateToArray=function(a,c){Array.prototype.push.apply(a,c)};b.prependToArray=function(a,c){Array.prototype.unshift.apply(a,c)};b.extendObj=function(a,c){for(var e in c)a[e]=c[e]};b.getInheritableProperty=function(a,c){for(;a&&!a.has(c);)a=a.get("Parent");return a?a.get(c):null};b.inherit=
-function(a,c,e){a.prototype=Object.create(c.prototype);a.prototype.constructor=a;for(var d in e)a.prototype[d]=e[d]};b.loadScript=function(a,c){var e=document.createElement("script"),d=!1;e.setAttribute("src",a);c&&(e.onload=function(){d||c();d=!0});document.getElementsByTagName("head")[0].appendChild(e)};return b}();PDFJS.PageViewport=function(){function b(a,c,e,d,b,f){this.viewBox=a;this.scale=c;this.rotation=e;this.offsetX=d;this.offsetY=b;var k=(a[2]+a[0])/2,h=(a[3]+a[1])/2,l,n,t;e%=360;switch(0>
-e?e+360:e){case 180:e=-1;n=l=0;t=1;break;case 90:e=0;n=l=1;t=0;break;case 270:e=0;n=l=-1;t=0;break;default:e=1,n=l=0,t=-1}f&&(n=-n,t=-t);0===e?(d=Math.abs(h-a[1])*c+d,b=Math.abs(k-a[0])*c+b,f=Math.abs(a[3]-a[1])*c,a=Math.abs(a[2]-a[0])*c):(d=Math.abs(k-a[0])*c+d,b=Math.abs(h-a[1])*c+b,f=Math.abs(a[2]-a[0])*c,a=Math.abs(a[3]-a[1])*c);this.transform=[e*c,l*c,n*c,t*c,d-e*c*k-n*c*h,b-l*c*k-t*c*h];this.width=f;this.height=a;this.fontScale=c}b.prototype={clone:function(a){a=a||{};var c="scale"in a?a.scale:
-this.scale,e="rotation"in a?a.rotation:this.rotation;return new b(this.viewBox.slice(),c,e,this.offsetX,this.offsetY,a.dontFlip)},convertToViewportPoint:function(a,c){return s.applyTransform([a,c],this.transform)},convertToViewportRectangle:function(a){var c=s.applyTransform([a[0],a[1]],this.transform);a=s.applyTransform([a[2],a[3]],this.transform);return[c[0],c[1],a[0],a[1]]},convertToPdfPoint:function(a,c){return s.applyInverseTransform([a,c],this.transform)}};return b}();var pa=[0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,728,711,710,729,733,731,730,732,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8226,8224,8225,8230,8212,8211,402,8260,8249,8250,8722,8240,8222,8220,8221,8216,8217,8218,8482,64257,64258,321,338,352,376,381,305,322,339,353,382,0,8364],x=PDFJS.Promise=function(){function b(){this._status=a;this._handlers=[]}var a=0,c=2,e={handlers:[],
-running:!1,unhandledRejections:[],pendingRejectionCheck:!1,scheduleHandlers:function(c){c._status!=a&&(this.handlers=this.handlers.concat(c._handlers),c._handlers=[],this.running||(this.running=!0,setTimeout(this.runHandlers.bind(this),0)))},runHandlers:function(){for(;0<this.handlers.length;){var a=this.handlers.shift(),e=a.thisPromise._status,f=a.thisPromise._value;try{1===e?"function"==typeof a.onResolve&&(f=a.onResolve(f)):"function"===typeof a.onReject&&(f=a.onReject(f),e=1,a.thisPromise._unhandledRejection&&
-this.removeUnhandeledRejection(a.thisPromise))}catch(b){e=c,f=b}a.nextPromise._updateStatus(e,f)}this.running=!1},addUnhandledRejection:function(a){this.unhandledRejections.push({promise:a,time:Date.now()});this.scheduleRejectionCheck()},removeUnhandeledRejection:function(a){a._unhandledRejection=!1;for(var c=0;c<this.unhandledRejections.length;c++)this.unhandledRejections[c].promise===a&&(this.unhandledRejections.splice(c),c--)},scheduleRejectionCheck:function(){this.pendingRejectionCheck||(this.pendingRejectionCheck=
-!0,setTimeout(function(){this.pendingRejectionCheck=!1;for(var a=Date.now(),c=0;c<this.unhandledRejections.length;c++)if(500<a-this.unhandledRejections[c].time){var f=this.unhandledRejections[c].promise._value,e="Unhandled rejection: "+f;f.stack&&(e+="\n"+f.stack);F(e);this.unhandledRejections.splice(c);c--}this.unhandledRejections.length&&this.scheduleRejectionCheck()}.bind(this),500))}};b.all=function(a){function e(a){f._status!==c&&(h=[],f.reject(a))}var f=new b,k=a.length,h=[];if(0===k)return f.resolve(h),
-f;for(var l=0,n=a.length;l<n;++l)a[l].then(function(a){return function(e){f._status!==c&&(h[a]=e,k--,0===k&&f.resolve(h))}}(l),e);return f};b.prototype={_status:null,_value:null,_handlers:null,_unhandledRejection:null,_updateStatus:function(a,b){1!==this._status&&this._status!==c&&(1==a&&b&&"function"===typeof b.then?b.then(this._updateStatus.bind(this,1),this._updateStatus.bind(this,c)):(this._status=a,this._value=b,a===c&&0===this._handlers.length&&(this._unhandledRejection=!0,e.addUnhandledRejection(this)),
-e.scheduleHandlers(this)))},get isResolved(){return 1===this._status},get isRejected(){return this._status===c},resolve:function(a){this._updateStatus(1,a)},reject:function(a){this._updateStatus(c,a)},then:function(a,c){var f=new b;this._handlers.push({thisPromise:this,onResolve:a,onReject:c,nextPromise:f});e.scheduleHandlers(this);return f}};return b}(),ta=function(){function b(){this.started={};this.times=[];this.enabled=!0}b.prototype={time:function(a){this.enabled&&(a in this.started&&F("Timer is already running for "+
-a),this.started[a]=Date.now())},timeEnd:function(a){this.enabled&&(a in this.started||F("Timer has not been started for "+a),this.times.push({name:a,start:this.started[a],end:Date.now()}),delete this.started[a])},toString:function(){for(var a=this.times,c="",e=0,d=0,b=a.length;d<b;++d){var f=a[d].name;f.length>e&&(e=f.length)}d=0;for(b=a.length;d<b;++d){for(var k=a[d],f=k.end-k.start,k=k.name;k.length<e;)k+=" ";c+=k+" "+f+"ms\n"}return c}};return b}();PDFJS.createBlob=function(b,a){if("function"===
-typeof Blob)return new Blob([b],{type:a});var c=new MozBlobBuilder;c.append(b);return c.getBlob(a)};Z.prototype={on:function(b,a,c){var e=this.actionHandler;e[b]&&m('There is already an actionName called "'+b+'"');e[b]=[a,c]},send:function(b,a,c){b={action:b,data:a};c&&(a=this.callbackIndex++,this.callbacks[a]=c,b.callbackId=a);this.comObj.postMessage(b)}};var p=function(){function b(){m("should not call ColorSpace constructor")}b.prototype={getRgb:function(a,c){m("Should not call ColorSpace.getRgb")},
-getRgbItem:function(a,c,e,d){m("Should not call ColorSpace.getRgbItem")},getRgbBuffer:function(a,c,e,d,b,f){m("Should not call ColorSpace.getRgbBuffer")},getOutputLength:function(a){m("Should not call ColorSpace.getOutputLength")},isPassthrough:function(a){return!1},createRgbBuffer:function(a,c,e,d){if(this.isPassthrough(d))return a.subarray(c);var b=new Uint8Array(3*e),f=1<<d;if(1===this.numComps&&e>f&&"DeviceGray"!==this.name&&"DeviceRGB"!==this.name){for(var k=8>=d?new Uint8Array(f):new Uint16Array(f),
-h=0;h<f;h++)k[h]=h;var l=new Uint8Array(3*f);this.getRgbBuffer(k,0,f,l,0,d);for(h=d=0;h<e;++h)f=3*a[c++],b[d++]=l[f],b[d++]=l[f+1],b[d++]=l[f+2];return b}this.getRgbBuffer(a,c,e,b,0,d);return b},usesZeroToOneRange:!0};b.parse=function(a,c,e){a=b.parseToIR(a,c,e);return a instanceof ia?a:b.fromIR(a)};b.fromIR=function(a){var c=B(a)?a[0]:a;switch(c){case "DeviceGrayCS":return this.singletons.gray;case "DeviceRgbCS":return this.singletons.rgb;case "DeviceCmykCS":return this.singletons.cmyk;case "PatternCS":return(a=
-a[1])&&(a=b.fromIR(a)),new ua(a);case "IndexedCS":var c=a[2],e=a[3];return new va(b.fromIR(a[1]),c,e);case "AlternateCS":return c=a[3],new ia(a[1],b.fromIR(a[2]),P.fromIR(c));case "LabCS":return new wa(a[1].WhitePoint,a[1].BlackPoint,a[1].Range);default:m("Unkown name "+c)}return null};b.parseToIR=function(a,c,e){if(M(a)){var d=e.get("ColorSpace");O(d)&&(d=d.get(a.name))&&(a=d)}a=c.fetchIfRef(a);if(M(a))switch(this.mode=d=a.name,d){case "DeviceGray":case "G":return"DeviceGrayCS";case "DeviceRGB":case "RGB":return"DeviceRgbCS";
-case "DeviceCMYK":case "CMYK":return"DeviceCmykCS";case "Pattern":return["PatternCS",null];default:m("unrecognized colorspace "+d)}else if(B(a))switch(this.mode=d=a[0].name,d){case "DeviceGray":case "G":return"DeviceGrayCS";case "DeviceRGB":case "RGB":return"DeviceRgbCS";case "DeviceCMYK":case "CMYK":return"DeviceCmykCS";case "CalGray":return"DeviceGrayCS";case "CalRGB":return"DeviceRgbCS";case "ICCBased":d=c.fetchIfRef(a[1]).dict.get("N");if(1==d)return"DeviceGrayCS";if(3==d)return"DeviceRgbCS";
-if(4==d)return"DeviceCmykCS";break;case "Pattern":return(a=a[1])&&(a=b.parseToIR(a,c,e)),["PatternCS",a];case "Indexed":case "I":return e=b.parseToIR(a[1],c,e),d=a[2]+1,c=c.fetchIfRef(a[3]),X(c)&&(c=c.getBytes()),["IndexedCS",e,d,c];case "Separation":case "DeviceN":var g=a[1],d=1;M(g)?d=1:B(g)&&(d=g.length);e=b.parseToIR(a[2],c,e);c=P.getIR(c,c.fetchIfRef(a[3]));return["AlternateCS",d,e,c];case "Lab":return["LabCS",a[1].getAll()];default:m('unimplemented color space object "'+d+'"')}else m('unrecognized color space object: "'+
-a+'"');return null};b.isDefaultDecode=function(a,c){if(!a)return!0;if(2*c!==a.length)return F("The decode map is not the correct length"),!0;for(var e=0,d=a.length;e<d;e+=2)if(0!==a[e]||1!=a[e+1])return!1;return!0};b.singletons={get gray(){return W(this,"gray",new xa)},get rgb(){return W(this,"rgb",new ya)},get cmyk(){return W(this,"cmyk",new za)}};return b}(),ia=function(){function b(a,c,e){this.name="Alternate";this.numComps=a;this.defaultColor=new Float32Array(a);for(var d=0;d<a;++d)this.defaultColor[d]=
-1;this.base=c;this.tintFn=e}b.prototype={getRgb:function(a,c){var e=new Uint8Array(3);this.getRgbItem(a,c,e,0);return e},getRgbItem:function(a,c,e,d){a="subarray"in a?a.subarray(c,c+this.numComps):Array.prototype.slice.call(a,c,c+this.numComps);a=this.tintFn(a);this.base.getRgbItem(a,0,e,d)},getRgbBuffer:function(a,c,e,d,b,f){var k=this.tintFn,h=this.base;f=1/((1<<f)-1);for(var l=h.numComps,n=h.usesZeroToOneRange,t=h.isPassthrough(8)||!n,y=t?b:0,q=t?d:new Uint8Array(l*e),r=this.numComps,m=new Float32Array(r),
-u=0;u<e;u++){for(var w=0;w<r;w++)m[w]=a[c++]*f;var s=k(m);if(n)for(w=0;w<l;w++)q[y++]=255*s[w];else h.getRgbItem(s,0,q,y),y+=l}t||h.getRgbBuffer(q,0,e,d,b,8)},getOutputLength:function(a){return this.base.getOutputLength(a*this.base.numComps/this.numComps)},isPassthrough:p.prototype.isPassthrough,createRgbBuffer:p.prototype.createRgbBuffer,isDefaultDecode:function(a){return p.isDefaultDecode(a,this.numComps)},usesZeroToOneRange:!0};return b}(),ua=function(){function b(a){this.name="Pattern";this.base=
-a}b.prototype={};return b}(),va=function(){function b(a,c,e){this.name="Indexed";this.numComps=1;this.defaultColor=new Uint8Array([0]);this.base=a;this.highVal=c;a=a.numComps*c;var d;if(X(e))d=new Uint8Array(a),e=e.getBytes(a),d.set(e);else if("string"==typeof e)for(d=new Uint8Array(a),c=0;c<a;++c)d[c]=e.charCodeAt(c);else e instanceof Uint8Array||e instanceof Array?d=e:m("Unrecognized lookup table: "+e);this.lookup=d}b.prototype={getRgb:function(a,c){return this.base.getRgb(this.lookup,a[c]*this.base.numComps)},
-getRgbItem:function(a,c,e,d){this.base.getRgbItem(this.lookup,a[c]*this.base.numComps,e,d)},getRgbBuffer:function(a,c,e,d,b){for(var f=this.base,k=f.numComps,h=f.getOutputLength(k),l=this.lookup,n=0;n<e;++n){var t=a[c++]*k;f.getRgbBuffer(l,t,1,d,b,8);b+=h}},getOutputLength:function(a){return this.base.getOutputLength(a*this.base.numComps)},isPassthrough:p.prototype.isPassthrough,createRgbBuffer:p.prototype.createRgbBuffer,isDefaultDecode:function(a){return!0},usesZeroToOneRange:!0};return b}(),xa=
-function(){function b(){this.name="DeviceGray";this.numComps=1;this.defaultColor=new Float32Array([0])}b.prototype={getRgb:function(a,c){var e=new Uint8Array(3);this.getRgbItem(a,c,e,0);return e},getRgbItem:function(a,c,e,d){a=255*a[c]|0;e[d]=e[d+1]=e[d+2]=0>a?0:255<a?255:a},getRgbBuffer:function(a,c,e,d,b,f){f=255/((1<<f)-1);for(var k=0;k<e;++k){var h=f*a[c++]|0;d[b++]=h;d[b++]=h;d[b++]=h}},getOutputLength:function(a){return 3*a},isPassthrough:p.prototype.isPassthrough,createRgbBuffer:p.prototype.createRgbBuffer,
-isDefaultDecode:function(a){return p.isDefaultDecode(a,this.numComps)},usesZeroToOneRange:!0};return b}(),ya=function(){function b(){this.name="DeviceRGB";this.numComps=3;this.defaultColor=new Float32Array([0,0,0])}b.prototype={getRgb:function(a,c){var e=new Uint8Array(3);this.getRgbItem(a,c,e,0);return e},getRgbItem:function(a,c,e,d){var b=255*a[c]|0,f=255*a[c+1]|0;a=255*a[c+2]|0;e[d]=0>b?0:255<b?255:b;e[d+1]=0>f?0:255<f?255:f;e[d+2]=0>a?0:255<a?255:a},getRgbBuffer:function(a,c,e,d,b,f){e*=3;if(8==
-f)d.set(a.subarray(c,c+e),b);else{f=255/((1<<f)-1);for(var k=0;k<e;++k)d[b++]=f*a[c++]|0}},getOutputLength:function(a){return a},isPassthrough:function(a){return 8==a},createRgbBuffer:p.prototype.createRgbBuffer,isDefaultDecode:function(a){return p.isDefaultDecode(a,this.numComps)},usesZeroToOneRange:!0};return b}(),za=function(){function b(a,e,d,b,f){var k=a[e+0]*d,h=a[e+1]*d,l=a[e+2]*d;d*=a[e+3];a=k*(-4.387332384609988*k+54.48615194189176*h+18.82290502165302*l+212.25662451639585*d+-285.2331026137004)+
-h*(1.7149763477362134*h-5.6096736904047315*l+-17.873870861415444*d-5.497006427196366)+l*(-2.5217340131683033*l-21.248923337353073*d+17.5119270841813)+d*(-21.86122147463605*d-189.48180835922747)+255;e=k*(8.841041422036149*k+60.118027045597366*h+6.871425592049007*l+31.159100130055922*d+-79.2970844816548)+h*(-15.310361306967817*h+17.575251261109482*l+131.35250912493976*d-190.9453302588951)+l*(4.444339102852739*l+9.8632861493405*d-24.86741582555878)+d*(-20.737325471181034*d-187.80453709719578)+255;k=
-k*(0.8842522430003296*k+8.078677503112928*h+30.89978309703729*l-0.23883238689178934*d+-14.183576799673286)+h*(10.49593273432072*h+63.02378494754052*l+50.606957656360734*d-112.23884253719248)+l*(0.03296041114873217*l+115.60384449646641*d+-193.58209356861505)+d*(-22.33816807309886*d-180.12613974708367)+255;b[f]=255<a?255:0>a?0:a;b[f+1]=255<e?255:0>e?0:e;b[f+2]=255<k?255:0>k?0:k}function a(){this.name="DeviceCMYK";this.numComps=4;this.defaultColor=new Float32Array([0,0,0,1])}a.prototype={getRgb:function(a,
-e){var d=new Uint8Array(3);b(a,e,1,d,0);return d},getRgbItem:function(a,e,d,g){b(a,e,1,d,g)},getRgbBuffer:function(a,e,d,g,f,k){k=1/((1<<k)-1);for(var h=0;h<d;h++)b(a,e,k,g,f),e+=4,f+=3},getOutputLength:function(a){return 3*(a>>2)},isPassthrough:p.prototype.isPassthrough,createRgbBuffer:p.prototype.createRgbBuffer,isDefaultDecode:function(a){return p.isDefaultDecode(a,this.numComps)},usesZeroToOneRange:!0};return a}(),wa=function(){function b(a,c,b){this.name="Lab";this.numComps=3;this.defaultColor=
-new Float32Array([0,0,0]);a||m("WhitePoint missing - required for color space Lab");c=c||[0,0,0];b=b||[-100,100,-100,100];this.XW=a[0];this.YW=a[1];this.ZW=a[2];this.amin=b[0];this.amax=b[1];this.bmin=b[2];this.bmax=b[3];this.XB=c[0];this.YB=c[1];this.ZB=c[2];(0>this.XW||0>this.ZW||1!==this.YW)&&m("Invalid WhitePoint components, no fallback available");if(0>this.XB||0>this.YB||0>this.ZB)S("Invalid BlackPoint, falling back to default"),this.XB=this.YB=this.ZB=0;if(this.amin>this.amax||this.bmin>this.bmax)S("Invalid Range, falling back to defaults"),
-this.amin=-100,this.amax=100,this.bmin=-100,this.bmax=100}function a(a){return a>=6/29?a*a*a:108/841*(a-4/29)}function c(c,d,b,f,k,h){var l=d[b],n=d[b+1];d=d[b+2];!1!==f&&(l=0+100*l/f,n=c.amin+n*(c.amax-c.amin)/f,d=c.bmin+d*(c.bmax-c.bmin)/f);n=n>c.amax?c.amax:n<c.amin?c.amin:n;d=d>c.bmax?c.bmax:d<c.bmin?c.bmin:d;f=(l+16)/116;l=f-d/200;n=c.XW*a(f+n/500);f=c.YW*a(f);l=c.ZW*a(l);1>c.ZW?(c=3.1339*n+-1.617*f+-0.4906*l,d=-0.9785*n+1.916*f+0.0333*l,n=0.072*n+-0.229*f+1.4057*l):(c=3.2406*n+-1.5372*f+-0.4986*
-l,d=-0.9689*n+1.8758*f+0.0415*l,n=0.0557*n+-0.204*f+1.057*l);k[h]=255*Math.sqrt(0>c?0:1<c?1:c);k[h+1]=255*Math.sqrt(0>d?0:1<d?1:d);k[h+2]=255*Math.sqrt(0>n?0:1<n?1:n)}b.prototype={getRgb:function(a,d){var b=new Uint8Array(3);c(this,a,d,!1,b,0);return b},getRgbItem:function(a,b,g,f){c(this,a,b,!1,g,f)},getRgbBuffer:function(a,b,g,f,k,h){h=(1<<h)-1;for(var l=0;l<g;l++)c(this,a,b,h,f,k),b+=3,k+=3},getOutputLength:function(a){return a},isPassthrough:p.prototype.isPassthrough,isDefaultDecode:function(a){return!0},
-usesZeroToOneRange:!1};return b}();D=3;var ja=function(){function b(){m("should not call Pattern constructor")}b.prototype={getPattern:function(a){m("Should not call Pattern.getStyle: "+a)}};b.shadingFromIR=function(a){return N[a[0]].fromIR(a)};b.parseShading=function(a,c,b,d){a=X(a)?a.dict:a;var g=a.get("ShadingType");switch(g){case 2:case D:return new N.RadialAxial(a,c,b,d);default:return K("Unsupported shading type: "+g),new N.Dummy}};return b}(),N={SMALL_NUMBER:0.01};N.RadialAxial=function(){function b(a,
-c,b,d,g){this.matrix=c;this.coordsArr=a.get("Coords");this.shadingType=a.get("ShadingType");this.type="Pattern";this.ctx=g;c=a.get("ColorSpace","CS");this.cs=c=p.parse(c,b,d);d=0;var f=1;a.has("Domain")&&(g=a.get("Domain"),d=g[0],f=g[1]);var k=g=!1;a.has("Extend")&&(k=a.get("Extend"),g=k[0],k=k[1]);if(!(this.shadingType!==D||g&&k)){var h=this.coordsArr[0],l=this.coordsArr[1],n=this.coordsArr[2],t=this.coordsArr[3],y=this.coordsArr[4],q=this.coordsArr[5],h=Math.sqrt((h-t)*(h-t)+(l-y)*(l-y));n<=q+h&&
-q<=n+h&&F("Unsupported radial gradient.")}this.extendStart=g;this.extendEnd=k;n=a.get("Function");if(B(n)){for(var r=[],q=0,h=n.length;q<h;q++)l=b.fetchIfRef(n[q]),da(l)||m("Invalid function"),r.push(P.parse(b,l));n=function(a){for(var c=[],f=0,b=r.length;f<b;f++)c.push(r[f](a)[0]);return c}}else da(n)||m("Invalid function"),n=P.parse(b,n);q=f-d;h=q/10;b=this.colorStops=[];if(d>=f||0>=h)S("Bad shading domain.");else{for(l=d;l<=f;l+=h)t=c.getRgb(n([l]),0),t=s.makeCssRgb(t),b.push([(l-d)/q,t]);d="transparent";
-a.has("Background")&&(t=c.getRgb(a.get("Background"),0),d=s.makeCssRgb(t));g||(b.unshift([0,d]),b[1][0]+=N.SMALL_NUMBER);k||(b[b.length-1][0]-=N.SMALL_NUMBER,b.push([1,d]));this.colorStops=b}}b.fromIR=function(a){var c=a[1],b=a[2],d=a[3],g=a[4],f=a[5],k=a[6];return{type:"Pattern",getPattern:function(a){var l;2==c?l=a.createLinearGradient(d[0],d[1],g[0],g[1]):c==D&&(l=a.createRadialGradient(d[0],d[1],f,g[0],g[1],k));a=0;for(var n=b.length;a<n;++a){var t=b[a];l.addColorStop(t[0],t[1])}return l}}};b.prototype=
-{getIR:function(){var a=this.coordsArr,c=this.shadingType;if(2==c)var b=[a[0],a[1]],d=[a[2],a[3]],g=null,f=null;else c==D?(b=[a[0],a[1]],d=[a[3],a[4]],g=a[2],f=a[5]):m("getPattern type unknown: "+c);if(a=this.matrix)b=s.applyTransform(b,a),d=s.applyTransform(d,a);return["RadialAxial",c,this.colorStops,b,d,g,f]}};return b}();N.Dummy=function(){function b(){this.type="Pattern"}b.fromIR=function(){return{type:"Pattern",getPattern:function(){return"hotpink"}}};b.prototype={getIR:function(){return["Dummy"]}};
-return b}();var Aa=function(){function b(a,c,b,d,g,f){this.name=a[1][0].name;this.operatorList=a[2];this.matrix=a[3]||[1,0,0,1,0,0];this.bbox=a[4];this.xstep=a[5];this.ystep=a[6];this.paintType=a[7];this.tilingType=a[8];this.color=c;this.objs=d;this.commonObjs=g;this.baseTransform=f;this.type="Pattern";this.ctx=b}b.getIR=function(a,c,b){var d=c.get("Matrix"),g=c.get("BBox"),f=c.get("XStep"),k=c.get("YStep"),h=c.get("PaintType");c=c.get("TilingType");return["TilingPattern",b,a,d,g,f,k,h,c]};b.prototype=
-{createPatternCanvas:function(a){var c=this.operatorList,b=this.bbox,d=this.xstep,g=this.ystep,f=this.paintType,k=this.color,h=this.objs,l=this.commonObjs;K("TilingType: "+this.tilingType);var n=b[0],t=b[1],y=b[2],q=b[3],r=[n,t],m=[n+d,t+g],u=m[0]-r[0],m=m[1]-r[1],w=s.singularValueDecompose2dScale(this.matrix),p=s.singularValueDecompose2dScale(this.baseTransform),w=[w[0]*p[0],w[1]*p[1]],u=Math.min(Math.ceil(Math.abs(u*w[0])),3E3),m=Math.min(Math.ceil(Math.abs(m*w[1])),3E3),w=G.getCanvas("pattern",
-u,m,!0),p=w.context,h=new ka(p,l,h);h.groupLevel=a.groupLevel;this.setFillAndStrokeStyleToContext(p,f,k);this.setScale(u,m,d,g);this.transformToScale(h);h.transform.apply(h,[1,0,0,1,-r[0],-r[1]]);this.clipBbox(h,b,n,t,y,q);h.executeOperatorList(c);return w.canvas},setScale:function(a,c,b,d){this.scale=[a/b,c/d]},transformToScale:function(a){var c=this.scale;a.transform.apply(a,[c[0],0,0,c[1],0,0])},scaleToContext:function(){var a=this.scale;this.ctx.scale(1/a[0],1/a[1])},clipBbox:function(a,c,b,d,
-g,f){c&&B(c)&&4==c.length&&(a.rectangle(b,d,g-b,f-d),a.clip(),a.endPath())},setFillAndStrokeStyleToContext:function(a,c,b){switch(c){case 1:c=this.ctx;a.fillStyle=c.fillStyle;a.strokeStyle=c.strokeStyle;break;case 2:c=p.singletons.rgb.getRgb(b,0);c=s.makeCssRgb(c);a.fillStyle=c;a.strokeStyle=c;break;default:m("Unsupported paint type: "+c)}},getPattern:function(a,c){var b=this.createPatternCanvas(c);a=this.ctx;a.setTransform.apply(a,this.baseTransform);a.transform.apply(a,this.matrix);this.scaleToContext();
-return a.createPattern(b,"repeat")}};return b}(),P=function(){return{getSampleArray:function(b,a,c,e){for(var d=1,g=0,f=b.length;g<f;g++)d*=b[g];d*=a;b=[];var f=a=0,k=1/(Math.pow(2,c)-1);e=e.getBytes((d*c+7)/8);for(var h=0,g=0;g<d;g++){for(;a<c;)f<<=8,f|=e[h++],a+=8;a-=c;b.push((f>>a)*k);f&=(1<<a)-1}return b},getIR:function(b,a){var c=a.dict;c||(c=a);var e=[this.constructSampled,null,this.constructInterpolated,this.constructStiched,this.constructPostScript],d=c.get("FunctionType");(e=e[d])||m("Unknown type of function");
-return e.call(this,a,c,b)},fromIR:function(b){switch(b[0]){case 0:return this.constructSampledFromIR(b);case 2:return this.constructInterpolatedFromIR(b);case 3:return this.constructStichedFromIR(b);default:return this.constructPostScriptFromIR(b)}},parse:function(b,a){var c=this.getIR(b,a);return this.fromIR(c)},constructSampled:function(b,a){function c(a){for(var c=a.length,f=[],b=0,d=0;d<c;d+=2)f[b]=[a[d],a[d+1]],++b;return f}var e=a.get("Domain"),d=a.get("Range");e&&d||m("No domain or range");
-var g=e.length/2,f=d.length/2,e=c(e),d=c(d),k=a.get("Size"),h=a.get("BitsPerSample"),l=a.get("Order")||1;1!==l&&K("No support for cubic spline interpolation: "+l);l=a.get("Encode");if(!l)for(var l=[],n=0;n<g;++n)l.push(0),l.push(k[n]-1);var l=c(l),n=(n=a.get("Decode"))?c(n):d,t=this.getSampleArray(k,f,h,b);return[0,g,e,l,n,t,k,f,Math.pow(2,h)-1,d]},constructSampledFromIR:function(b){return function(a){var c=b[1],e=b[2],d=b[3],g=b[4],f=b[5],k=b[6],h=b[7],l=b[9];c!=a.length&&m("Incorrect number of arguments: "+
-c+" != "+a.length);for(var n=1<<c,t=new Float64Array(n),y=new Uint32Array(n),q=0;q<n;q++)t[q]=1;for(var r=h,s=1,u=0;u<c;++u){for(var q=e[u][0],w=e[u][1],p=Math.min(Math.max(a[u],q),w),E=d[u][0]+(p-q)*((d[u][1]-d[u][0])/(w-q)),w=k[u],E=Math.min(Math.max(E,0),w-1),q=E<w-1?Math.floor(E):E-1,p=q+1-E,E=E-q,z=q*r,v=z+r,q=0;q<n;q++)q&s?(t[q]*=E,y[q]+=v):(t[q]*=p,y[q]+=z);r*=w;s<<=1}a=new Float64Array(h);for(q=0;q<h;++q){for(u=c=0;u<n;u++)c+=f[y[u]+q]*t[u];c=g[q][0]+(c-0)*((g[q][1]-g[q][0])/1);a[q]=Math.min(Math.max(c,
-l[q][0]),l[q][1])}return a}},constructInterpolated:function(b,a){var c=a.get("C0")||[0],e=a.get("C1")||[1],d=a.get("N");B(c)&&B(e)||m("Illegal dictionary for interpolated function");for(var g=c.length,f=[],k=0;k<g;++k)f.push(e[k]-c[k]);return[2,c,f,d]},constructInterpolatedFromIR:function(b){var a=b[1],c=b[2],e=b[3],d=c.length;return function(b){b=1==e?b[0]:Math.pow(b[0],e);for(var f=[],k=0;k<d;++k)f.push(a[k]+b*c[k]);return f}},constructStiched:function(b,a,c){(b=a.get("Domain"))||m("No domain");
-1!=b.length/2&&m("Bad domain for stiched function");for(var e=a.get("Functions"),d=[],g=0,f=e.length;g<f;++g)d.push(P.getIR(c,c.fetchIfRef(e[g])));c=a.get("Bounds");a=a.get("Encode");return[3,b,c,a,d]},constructStichedFromIR:function(b){var a=b[1],c=b[2],e=b[3];b=b[4];for(var d=[],g=0,f=b.length;g<f;g++)d.push(P.fromIR(b[g]));return function(f){f=f[0];var b=a[0],l=a[1];f>l?f=l:f<b&&(f=b);b=0;for(l=c.length;b<l&&!(f<c[b]);++b);l=a[0];0<b&&(l=c[b-1]);var g=a[1];b<c.length&&(g=c[b]);var t=e[2*b];return d[b]([t+
-(f-l)*(e[2*b+1]-t)/(g-l)])}},constructPostScript:function(b,a,c){c=a.get("Domain");a=a.get("Range");c||m("No domain.");a||m("No range.");b=new Ba(b);b=(new Ca(b)).parse();return[4,c,a,b]},constructPostScriptFromIR:function(b){var a=b[1],c=b[2],e=c.length/2,d=new Da(b[3]),g=new Ea;return function(f){for(var b=[],h=0,l=a.length/2;h<l;++h)b.push(f[h]);f=b.join("_");if(g.has(f))return g.get(f);b=d.execute(b);l=[];for(h=e-1;0<=h;--h){var n=b.pop(),t=2*h;n<c[t]?n=c[t]:n>c[t+1]&&(n=c[t+1]);l[h]=n}g.set(f,
-l);return l}}}}(),Ea=function(){function b(){this.cache={};this.total=0}b.prototype={has:function(a){return a in this.cache},get:function(a){return this.cache[a]},set:function(a,c){1024>this.total&&(this.cache[a]=c,this.total++)}};return b}(),Fa=function(){function b(a){this.stack=a||[]}b.prototype={push:function(a){100<=this.stack.length&&m("PostScript function stack overflow.");this.stack.push(a)},pop:function(){0>=this.stack.length&&m("PostScript function stack underflow.");return this.stack.pop()},
-copy:function(a){100<=this.stack.length+a&&m("PostScript function stack overflow.");var c=this.stack,b=c.length-a;for(a-=1;0<=a;a--,b++)c.push(c[b])},index:function(a){this.push(this.stack[this.stack.length-a-1])},roll:function(a,c){var b=this.stack,d=b.length-a,g=b.length-1,f=d+(c-Math.floor(c/a)*a),k,h,l;k=d;for(h=g;k<h;k++,h--)l=b[k],b[k]=b[h],b[h]=l;k=d;for(h=f-1;k<h;k++,h--)l=b[k],b[k]=b[h],b[h]=l;k=f;for(h=g;k<h;k++,h--)l=b[k],b[k]=b[h],b[h]=l}};return b}(),Da=function(){function b(a,c){this.operators=
-a;this.operands=c}b.prototype={execute:function(a){a=new Fa(a);for(var c=0,b=this.operators,d=b.length,g,f;c<d;)if(g=b[c++],"number"==typeof g)a.push(g);else switch(g){case "jz":f=a.pop();(g=a.pop())||(c=f);break;case "j":c=g=a.pop();break;case "abs":g=a.pop();a.push(Math.abs(g));break;case "add":f=a.pop();g=a.pop();a.push(g+f);break;case "and":f=a.pop();g=a.pop();L(g)&&L(f)?a.push(g&&f):a.push(g&f);break;case "atan":g=a.pop();a.push(Math.atan(g));break;case "bitshift":f=a.pop();g=a.pop();0<g?a.push(g<<
-f):a.push(g>>f);break;case "ceiling":g=a.pop();a.push(Math.ceil(g));break;case "copy":g=a.pop();a.copy(g);break;case "cos":g=a.pop();a.push(Math.cos(g));break;case "cvi":g=a.pop()|0;a.push(g);break;case "cvr":break;case "div":f=a.pop();g=a.pop();a.push(g/f);break;case "dup":a.copy(1);break;case "eq":f=a.pop();g=a.pop();a.push(g==f);break;case "exch":a.roll(2,1);break;case "exp":f=a.pop();g=a.pop();a.push(Math.pow(g,f));break;case "false":a.push(!1);break;case "floor":g=a.pop();a.push(Math.floor(g));
-break;case "ge":f=a.pop();g=a.pop();a.push(g>=f);break;case "gt":f=a.pop();g=a.pop();a.push(g>f);break;case "idiv":f=a.pop();g=a.pop();a.push(g/f|0);break;case "index":g=a.pop();a.index(g);break;case "le":f=a.pop();g=a.pop();a.push(g<=f);break;case "ln":g=a.pop();a.push(Math.log(g));break;case "log":g=a.pop();a.push(Math.log(g)/Math.LN10);break;case "lt":f=a.pop();g=a.pop();a.push(g<f);break;case "mod":f=a.pop();g=a.pop();a.push(g%f);break;case "mul":f=a.pop();g=a.pop();a.push(g*f);break;case "ne":f=
-a.pop();g=a.pop();a.push(g!=f);break;case "neg":a.pop();a.push(-f);break;case "not":g=a.pop();L(g)&&L(f)?a.push(g&&f):a.push(g&f);break;case "or":f=a.pop();g=a.pop();L(g)&&L(f)?a.push(g||f):a.push(g|f);break;case "pop":a.pop();break;case "roll":f=a.pop();g=a.pop();a.roll(g,f);break;case "round":g=a.pop();a.push(Math.round(g));break;case "sin":g=a.pop();a.push(Math.sin(g));break;case "sqrt":g=a.pop();a.push(Math.sqrt(g));break;case "sub":f=a.pop();g=a.pop();a.push(g-f);break;case "true":a.push(!0);
-break;case "truncate":g=a.pop();g=0>g?Math.ceil(g):Math.floor(g);a.push(g);break;case "xor":f=a.pop();g=a.pop();L(g)&&L(f)?a.push(g!=f):a.push(g^f);break;default:m("Unknown operator "+g)}return a.stack}};return b}(),Ca=function(){function b(a){this.lexer=a;this.operators=[];this.prev=this.token=null}b.prototype={nextToken:function(){this.prev=this.token;this.token=this.lexer.getToken()},accept:function(a){return this.token.type==a?(this.nextToken(),!0):!1},expect:function(a){if(this.accept(a))return!0;
-m("Unexpected symbol: found "+this.token.type+" expected "+a+".")},parse:function(){this.nextToken();this.expect(A.LBRACE);this.parseBlock();this.expect(A.RBRACE);return this.operators},parseBlock:function(){for(;;)if(this.accept(A.NUMBER))this.operators.push(this.prev.value);else if(this.accept(A.OPERATOR))this.operators.push(this.prev.value);else if(this.accept(A.LBRACE))this.parseCondition();else break},parseCondition:function(){var a=this.operators.length;this.operators.push(null,null);this.parseBlock();
-this.expect(A.RBRACE);if(this.accept(A.IF))this.operators[a]=this.operators.length,this.operators[a+1]="jz";else if(this.accept(A.LBRACE)){var c=this.operators.length;this.operators.push(null,null);var b=this.operators.length;this.parseBlock();this.expect(A.RBRACE);this.expect(A.IFELSE);this.operators[c]=this.operators.length;this.operators[c+1]="j";this.operators[a]=b;this.operators[a+1]="jz"}else m("PS Function: error parsing conditional.")}};return b}(),A={LBRACE:0,RBRACE:1,NUMBER:2,OPERATOR:3,
-IF:4,IFELSE:5},Q=function(){function b(a,b){this.type=a;this.value=b}var a={};b.getOperator=function(c){var e=a[c];return e?e:a[c]=new b(A.OPERATOR,c)};b.LBRACE=new b(A.LBRACE,"{");b.RBRACE=new b(A.RBRACE,"}");b.IF=new b(A.IF,"IF");b.IFELSE=new b(A.IFELSE,"IFELSE");return b}(),Ba=function(){function b(a){this.stream=a;this.nextChar()}b.prototype={nextChar:function(){return this.currentChar=this.stream.getByte()},getToken:function(){for(var a=!1,c=this.currentChar;;){if(0>c)return EOF;if(a){if(10===
-c||13===c)a=!1}else if(37==c)a=!0;else if(!Lexer.isSpace(c))break;c=this.nextChar()}switch(c|0){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:case 43:case 45:case 46:return new Q(A.NUMBER,this.getNumber());case 123:return this.nextChar(),Q.LBRACE;case 125:return this.nextChar(),Q.RBRACE}for(a=String.fromCharCode(c);0<=(c=this.nextChar())&&(65<=c&&90>=c||97<=c&&122>=c);)a+=String.fromCharCode(c);switch(a.toLowerCase()){case "if":return Q.IF;case "ifelse":return Q.IFELSE;
-default:return Q.getOperator(a)}},getNumber:function(){for(var a=this.currentChar,c=String.fromCharCode(a);0<=(a=this.nextChar());)if(48<=a&&57>=a||45===a||46===a)c+=String.fromCharCode(a);else break;a=parseFloat(c);isNaN(a)&&m("Invalid floating point number: "+a);return a}};return b}(),H=function(){function b(a,b,d){var g=s.getAxialAlignedBoundingBox(b,d);b=g[0];d=g[1];var f=g[2],g=g[3];if(b===f||d===g)return[1,0,0,1,a[0],a[1]];f=(a[2]-a[0])/(f-b);g=(a[3]-a[1])/(g-d);return[f,0,0,g,a[0]-b*f,a[1]-
-d*g]}function a(a){if(a.data)this.data=a.data;else{var b=a.dict;a=this.data={};a.subtype=b.get("Subtype").name;var d=b.get("Rect");a.rect=s.normalizeRect(d);a.annotationFlags=b.get("F");d=b.get("C");B(d)&&3===d.length?a.color=d:a.color=[0,0,0];b.has("BS")?(d=b.get("BS"),a.borderWidth=d.has("W")?d.get("W"):1):(d=b.get("Border")||[0,0,1],a.borderWidth=d[2]||0);var g;d=b.get("AP");O(d)?(d=d.get("N"),O(d)?(b=b.get("AS"))&&d.has(b.name)&&(g=d.get(b.name)):g=d):g=void 0;this.appearance=g;a.hasAppearance=
-!!this.appearance}}a.prototype={getData:function(){return this.data},hasHtml:function(){return!1},getHtmlElement:function(a){throw new sa("getHtmlElement() should be implemented in subclass");},getEmptyContainer:function(a,b){U&&m("getEmptyContainer() should be called from main thread");b=b||this.data.rect;var d=document.createElement(a);d.style.width=Math.ceil(b[2]-b[0])+"px";d.style.height=Math.ceil(b[3]-b[1])+"px";return d},isViewable:function(){var a=this.data;return!(!a||a.annotationFlags&&a.annotationFlags&
-34||!a.rect)},loadResources:function(a){var b=new x;this.appearance.dict.getAsync("Resources").then(function(d){d?(new ObjectLoader(d.map,a,d.xref)).load().then(function(){b.resolve(d)}):b.resolve()}.bind(this));return b},getOperatorList:function(a){var e=new x;if(!this.appearance)return e.resolve(new OperatorList),e;var d=this.data,g=this.appearance.dict,f=this.loadResources("ExtGState ColorSpace Pattern Shading XObject Font".split(" ")),k=g.get("BBox")||[0,0,1,1],h=g.get("Matrix")||[1,0,0,1,0,0],
-l=b(d.rect,k,h);f.then(function(b){var f=new OperatorList;f.addOp("beginAnnotation",[d.rect,l,h]);a.getOperatorList(this.appearance,b,f);f.addOp("endAnnotation",[]);e.resolve(f)}.bind(this));return e}};a.getConstructor=function(c,b){if(c){if("Link"===c)return Ga;if("Text"===c)return Ha;if("Widget"===c){if(b)return"Tx"===b?Ia:aa}else return a}};a.fromData=function(c){var b=a.getConstructor(c.subtype,c.fieldType);if(b)return new b({data:c})};a.fromRef=function(c,b){var d=c.fetchIfRef(b);if(O(d)){var g=
-d.get("Subtype");if(g=M(g)?g.name:""){var f=s.getInheritableProperty(d,"FT"),f=M(f)?f.name:"";if(f=a.getConstructor(g,f)){d=new f({dict:d,ref:b});if(d.isViewable())return d;K("unimplemented annotation type: "+g)}}}};a.appendToOperatorList=function(a,b,d,g){var f=new x;d=[];for(var k=0,h=a.length;k<h;++k)d.push(a[k].getOperatorList(g));x.all(d).then(function(a){b.addOp("beginAnnotations",[]);for(var c=0,d=a.length;c<d;++c)b.addOpList(a[c]);b.addOp("endAnnotations",[]);f.resolve()},function(a){f.reject(a)});
-return f};return a}();PDFJS.Annotation=H;var aa=function(){function b(a){H.call(this,a);if(!a.data){var b=a.dict,d=this.data;d.fieldValue=T(s.getInheritableProperty(b,"V")||"");d.alternativeText=T(b.get("TU")||"");d.defaultAppearance=s.getInheritableProperty(b,"DA")||"";var g=s.getInheritableProperty(b,"FT");d.fieldType=M(g)?g.name:"";d.fieldFlags=s.getInheritableProperty(b,"Ff")||0;this.fieldResources=s.getInheritableProperty(b,"DR")||new Dict;var g=[],f=b;for(a=a.ref;f;){var b=f.get("Parent"),k=
-f.getRaw("Parent");if(f=f.get("T"))g.unshift(T(f));else{var f=b.get("Kids"),h,l;h=0;for(l=f.length;h<l;h++){var n=f[h];if(n.num==a.num&&n.gen==a.gen)break}g.unshift("`"+h)}f=b;a=k}d.fullName=g.join(".")}}var a=H.prototype;s.inherit(b,H,{isViewable:function(){return"Sig"===this.data.fieldType?(K("unimplemented annotation type: Widget signature"),!1):a.isViewable.call(this)}});return b}(),Ia=function(){function b(a){aa.call(this,a);a.data||(this.data.textAlignment=s.getInheritableProperty(a.dict,"Q"))}
-s.inherit(b,aa,{hasHtml:function(){return!this.data.hasAppearance&&!!this.data.fieldValue},getHtmlElement:function(a){U&&m("getHtmlElement() shall be called from main thread");var c=this.data,b=this.getEmptyContainer("div");b.style.display="table";var d=document.createElement("div");d.textContent=c.fieldValue;d.style.textAlign=["left","center","right"][c.textAlignment];d.style.verticalAlign="middle";d.style.display="table-cell";a=c.fontRefName?a.getData(c.fontRefName):null;var g=d.style;g.fontSize=
-c.fontSize+"px";g.direction=0>c.fontDirection?"rtl":"ltr";a&&(g.fontWeight=a.black?a.bold?"bolder":"bold":a.bold?"bold":"normal",g.fontStyle=a.italic?"italic":"normal",c=a.loadedName,g.fontFamily=(c?'"'+c+'", ':"")+(a.fallbackName||"Helvetica, sans-serif"));b.appendChild(d);return b},getOperatorList:function(a){if(this.appearance)return H.prototype.getOperatorList.call(this,a);var c=new x,b=new OperatorList,d=this.data,g=d.defaultAppearance;if(!g)return c.resolve(b),c;for(var f=Stream,k=g.length,
-h=new Uint8Array(k),l=0;l<k;++l)h[l]=g.charCodeAt(l)&255;g=new f(h);a.getOperatorList(g,this.fieldResources,b);a=b.fnArray;g=b.argsArray;d.rgb=[0,0,0];for(f=0;0>f;++f)k=a[f],h=g[f],"setFont"===k?(d.fontRefName=h[0],k=h[1],0>k?(d.fontDirection=-1,d.fontSize=-k):(d.fontDirection=1,d.fontSize=k)):"setFillRGBColor"===k?d.rgb=h:"setFillGray"===k&&(k=255*h[0],d.rgb=[k,k,k]);c.resolve(b);return c}});return b}(),Ha=function(){function b(a){H.call(this,a);if(!a.data){a=a.dict;var c=this.data,b=a.get("Contents"),
-d=a.get("T");c.content=T(b||"");c.title=T(d||"");c.name=a.has("Name")?a.get("Name").name:"Note"}}s.inherit(b,H,{getOperatorList:function(a){a=new x;a.resolve(new OperatorList);return a},hasHtml:function(){return!0},getHtmlElement:function(a){U&&m("getHtmlElement() shall be called from main thread");var c=this.data,b=c.rect;10>b[3]-b[1]&&(b[3]=b[1]+10);10>b[2]-b[0]&&(b[2]=b[0]+(b[3]-b[1]));var d=this.getEmptyContainer("section",b);d.className="annotText";a=document.createElement("img");a.style.height=
-d.style.height;var g=c.name;a.src=PDFJS.imageResourcesPath+"annotation-"+g.toLowerCase()+".svg";a.alt="[{{type}} Annotation]";a.dataset.l10nId="text_annotation_type";a.dataset.l10nArgs=JSON.stringify({type:g});var f=document.createElement("div");f.setAttribute("hidden",!0);var g=document.createElement("h1"),k=document.createElement("p");f.style.left=Math.floor(b[2]-b[0])+"px";f.style.top="0px";g.textContent=c.title;if(c.content||c.title){for(var b=document.createElement("span"),c=c.content.split(/(?:\r\n?|\n)/),
-h=0,l=c.length;h<l;++h)b.appendChild(document.createTextNode(c[h])),h<l-1&&b.appendChild(document.createElement("br"));k.appendChild(b);b=function(){d.style.zIndex+=1;f.removeAttribute("hidden")};c=function(a){if(a.toElement||a.relatedTarget)d.style.zIndex-=1,f.setAttribute("hidden",!0)};f.addEventListener("mouseover",b,!1);f.addEventListener("mouseout",c,!1);a.addEventListener("mouseover",b,!1);a.addEventListener("mouseout",c,!1)}else f.setAttribute("hidden",!0);f.appendChild(g);f.appendChild(k);
-d.appendChild(a);d.appendChild(f);return d}});return b}(),Ga=function(){function b(a){H.call(this,a);if(!a.data){var b=a.dict;a=this.data;var e=b.get("A");if(e)if(b=e.get("S").name,"URI"===b){var d=e.get("URI");Y(d,!1)||(d="");a.url=d}else"GoTo"===b?a.dest=e.get("D"):"GoToR"===b?(b=e.get("F"),O(b)&&(d=b.get("F")||""),Y(d,!1)||(d=""),a.url=d,a.dest=e.get("D")):"Named"===b?a.action=e.get("N").name:K("unrecognized link type: "+b);else b.has("Dest")&&(d=b.get("Dest"),a.dest=M(d)?d.name:d)}}s.inherit(b,
-H,{hasOperatorList:function(){return!1},hasHtml:function(){return!0},getHtmlElement:function(a){a=this.data.rect;var b=document.createElement("a"),e=this.data.borderWidth;b.style.borderWidth=e+"px";for(var d=this.data.color,g=[],f=0;3>f;++f)g[f]=Math.round(255*d[f]);b.style.borderColor=s.makeCssRgb(g);b.style.borderStyle="solid";d=a[3]-a[1]-2*e;b.style.width=a[2]-a[0]-2*e+"px";b.style.height=d+"px";b.href=this.data.url||"";return b}});return b}();PDFJS.maxImageSize=void 0===PDFJS.maxImageSize?-1:
-PDFJS.maxImageSize;PDFJS.disableFontFace=void 0===PDFJS.disableFontFace?!1:PDFJS.disableFontFace;PDFJS.getDocument=function(b,a,c,e){var d,g;"string"===typeof b?b={url:b}:"object"==typeof b&&null!==b&&void 0!==b&&"byteLength"in b?b={data:b}:"object"!==typeof b&&m("Invalid parameter in getDocument, need either Uint8Array, string or a parameter object");b.url||b.data||m("Invalid parameter array, need either .data or .url");var f={};for(d in b)f[d]="url"===d&&"undefined"!==typeof window?oa(window.location.href,
-b[d]):b[d];b=new PDFJS.Promise;d=new PDFJS.Promise;g=new Ja(b,d,a,e);b.then(function(){g.passwordCallback=c;g.fetchDocument(f)});return d};var Ka=function(){function b(a,b){this.pdfInfo=a;this.transport=b}b.prototype={get numPages(){return this.pdfInfo.numPages},get fingerprint(){return this.pdfInfo.fingerprint},get embeddedFontsUsed(){return this.transport.embeddedFontsUsed},getPage:function(a){return this.transport.getPage(a)},getDestinations:function(){return this.transport.getDestinations()},
-getJavaScript:function(){var a=new PDFJS.Promise;a.resolve(this.pdfInfo.javaScript);return a},getOutline:function(){var a=new PDFJS.Promise;a.resolve(this.pdfInfo.outline);return a},getMetadata:function(){var a=new PDFJS.Promise,b=this.pdfInfo.metadata;a.resolve({info:this.pdfInfo.info,metadata:b?new PDFJS.Metadata(b):null});return a},isEncrypted:function(){var a=new PDFJS.Promise;a.resolve(this.pdfInfo.encrypted);return a},getData:function(){var a=new PDFJS.Promise;this.transport.getData(a);return a},
-dataLoaded:function(){return this.transport.dataLoaded()},destroy:function(){this.transport.destroy()}};return b}(),Na=function(){function b(a,b){this.pageInfo=a;this.transport=b;this.stats=new ta;this.stats.enabled=!!v.PDFJS.enableStats;this.commonObjs=b.commonObjs;this.objs=new la;this.pendingDestroy=this.cleanupAfterRender=this.receivingOperatorList=!1;this.renderTasks=[]}b.prototype={get pageNumber(){return this.pageInfo.pageIndex+1},get rotate(){return this.pageInfo.rotate},get ref(){return this.pageInfo.ref},
-get view(){return this.pageInfo.view},getViewport:function(a,b){2>arguments.length&&(b=this.rotate);return new PDFJS.PageViewport(this.view,a,b,0,0)},getAnnotations:function(){if(this.annotationsPromise)return this.annotationsPromise;var a=new PDFJS.Promise;this.annotationsPromise=a;this.transport.getAnnotations(this.pageInfo.pageIndex);return a},render:function(a){function b(a){var c=f.renderTasks.indexOf(d);0<=c&&f.renderTasks.splice(c,1);f.cleanupAfterRender&&(f.pendingDestroy=!0);f._tryDestroy();
-a?g.reject(a):g.resolve();e.timeEnd("Rendering");e.timeEnd("Overall")}var e=this.stats;e.time("Overall");this.pendingDestroy=!1;this.displayReadyPromise||(this.receivingOperatorList=!0,this.displayReadyPromise=new x,this.operatorList={fnArray:[],argsArray:[],lastChunk:!1},this.stats.time("Page Request"),this.transport.messageHandler.send("RenderPageRequest",{pageIndex:this.pageNumber-1}));var d=new La(b,a,this.objs,this.commonObjs,this.operatorList,this.pageNumber);this.renderTasks.push(d);var g=
-new Ma(d),f=this;this.displayReadyPromise.then(function(a){f.pendingDestroy?b():(e.time("Rendering"),d.initalizeGraphics(a),d.operatorListChanged())},function(a){b(a)});return g},getTextContent:function(){var a=new PDFJS.Promise;this.transport.messageHandler.send("GetTextContent",{pageIndex:this.pageNumber-1},function(b){a.resolve(b)});return a},getOperationList:function(){var a=new PDFJS.Promise;a.resolve({dependencyFontsID:null,operatorList:null});return a},destroy:function(){this.pendingDestroy=
-!0;this._tryDestroy()},_tryDestroy:function(){this.pendingDestroy&&0===this.renderTasks.length&&!this.receivingOperatorList&&(delete this.operatorList,delete this.displayReadyPromise,this.objs.clear(),this.pendingDestroy=!1)},_startRenderPage:function(a){this.displayReadyPromise.resolve(a)},_renderPageChunk:function(a){s.concatenateToArray(this.operatorList.fnArray,a.fnArray);s.concatenateToArray(this.operatorList.argsArray,a.argsArray);this.operatorList.lastChunk=a.lastChunk;for(var b=0;b<this.renderTasks.length;b++)this.renderTasks[b].operatorListChanged();
-a.lastChunk&&(this.receivingOperatorList=!1,this._tryDestroy())}};return b}(),Ja=function(){function b(a,b,e,d){this.pdfDataRangeTransport=e;this.workerReadyPromise=b;this.progressCallback=d;this.commonObjs=new la;this.pageCache=[];this.pagePromises=[];this.embeddedFontsUsed=!1;this.passwordCallback=null;if(!v.PDFJS.disableWorker&&"undefined"!==typeof Worker){b=PDFJS.workerSrc;"undefined"===typeof b&&m("No PDFJS.workerSrc specified");try{var g=new Worker(b),f=new Z("main",g);this.messageHandler=f;
-f.on("test",function(b){b?(this.worker=g,this.setupMessageHandler(f)):(v.PDFJS.disableWorker=!0,this.setupFakeWorker());a.resolve()}.bind(this));var k=new Uint8Array(1);f.send("test",k);return}catch(h){S("The worker has been disabled.")}}v.PDFJS.disableWorker=!0;this.loadFakeWorkerFiles().then(function(){this.setupFakeWorker();a.resolve()}.bind(this))}b.prototype={destroy:function(){this.pageCache=[];this.pagePromises=[];var a=this;this.messageHandler.send("Terminate",null,function(){a.worker&&a.worker.terminate()})},
-loadFakeWorkerFiles:function(){PDFJS.fakeWorkerFilesLoadedPromise||(PDFJS.fakeWorkerFilesLoadedPromise=new x,s.loadScript(PDFJS.workerSrc,function(){PDFJS.fakeWorkerFilesLoadedPromise.resolve()}));return PDFJS.fakeWorkerFilesLoadedPromise},setupFakeWorker:function(){F("Setting up fake worker.");var a={postMessage:function(b){a.onmessage({data:b})},terminate:function(){}},b=new Z("main",a);this.setupMessageHandler(b);PDFJS.WorkerMessageHandler.setup(b)},setupMessageHandler:function(a){function b(c){a.send("UpdatePassword",
-c)}this.messageHandler=a;var e=this.pdfDataRangeTransport;e&&(e.addRangeListener(function(b,c){a.send("OnDataRange",{begin:b,chunk:c})}),e.addProgressListener(function(b){a.send("OnDataProgress",{loaded:b})}),a.on("RequestDataRange",function(a){e.requestDataRange(a.begin,a.end)},this));a.on("GetDoc",function(a){this.pdfDocument=a=new Ka(a.pdfInfo,this);this.workerReadyPromise.resolve(a)},this);a.on("NeedPassword",function(a){if(this.passwordCallback)return this.passwordCallback(b,ga.NEED_PASSWORD);
-this.workerReadyPromise.reject(a.exception.message,a.exception)},this);a.on("IncorrectPassword",function(a){if(this.passwordCallback)return this.passwordCallback(b,ga.INCORRECT_PASSWORD);this.workerReadyPromise.reject(a.exception.message,a.exception)},this);a.on("InvalidPDF",function(a){this.workerReadyPromise.reject(a.exception.name,a.exception)},this);a.on("MissingPDF",function(a){this.workerReadyPromise.reject(a.exception.message,a.exception)},this);a.on("UnknownError",function(a){this.workerReadyPromise.reject(a.exception.message,
-a.exception)},this);a.on("GetPage",function(a){a=a.pageInfo;var b=new Na(a,this);this.pageCache[a.pageIndex]=b;this.pagePromises[a.pageIndex].resolve(b)},this);a.on("GetAnnotations",function(a){this.pageCache[a.pageIndex].annotationsPromise.resolve(a.annotations)},this);a.on("StartRenderPage",function(a){var b=this.pageCache[a.pageIndex];b.stats.timeEnd("Page Request");b._startRenderPage(a.transparency)},this);a.on("RenderPageChunk",function(a){this.pageCache[a.pageIndex]._renderPageChunk(a.operatorList)},
-this);a.on("commonobj",function(a){var b=a[0],c=a[1];if(!this.commonObjs.hasData(b))switch(c){case "Font":a=a[2];var k;if("error"in a){var h=a.error;F("Error during font loading: "+h);this.commonObjs.resolve(b,h);break}else k=new Oa(a);R.bind([k],function(a){this.commonObjs.resolve(b,k)}.bind(this));break;case "FontPath":this.commonObjs.resolve(b,a[2]);break;default:h("Got unknown common object type "+c)}},this);a.on("obj",function(a){var b=a[0],c=a[2],k=this.pageCache[a[1]];if(!k.objs.hasData(b))switch(c){case "JpegStream":a=
-a[3];qa(b,a,k.objs);break;case "Image":a=a[3];k.objs.resolve(b,a);"data"in a&&8E6<a.data.length&&(k.cleanupAfterRender=!0);break;default:m("Got unknown object type "+c)}},this);a.on("DocProgress",function(a){this.progressCallback&&this.progressCallback({loaded:a.loaded,total:a.total})},this);a.on("DocError",function(a){this.workerReadyPromise.reject(a)},this);a.on("PageError",function(a){var b=this.pageCache[a.pageNum-1];b.displayReadyPromise?b.displayReadyPromise.reject(a.error):m(a.error)},this);
-a.on("JpegDecode",function(a,b){var c=a[0],k=a[1];3!=k&&1!=k&&m("Only 3 component or 1 component can be returned");var h=new Image;h.onload=function(){var a=h.width,c=h.height,f=a*c,d=4*f,f=new Uint8Array(f*k),e=ea(a,c).getContext("2d");e.drawImage(h,0,0);e=e.getImageData(0,0,a,c).data;if(3==k)for(var r=0,m=0;r<d;r+=4,m+=3)f[m]=e[r],f[m+1]=e[r+1],f[m+2]=e[r+2];else if(1==k)for(m=r=0;r<d;r+=4,m++)f[m]=e[r];b.resolve({data:f,width:a,height:c})}.bind(this);c="data:image/jpeg;base64,"+window.btoa(c);
-h.src=c})},fetchDocument:function(a){a.disableAutoFetch=PDFJS.disableAutoFetch;a.chunkedViewerLoading=!!this.pdfDataRangeTransport;this.messageHandler.send("GetDocRequest",{source:a,disableRange:PDFJS.disableRange,maxImageSize:PDFJS.maxImageSize,disableFontFace:PDFJS.disableFontFace})},getData:function(a){this.messageHandler.send("GetData",null,function(b){a.resolve(b)})},dataLoaded:function(){var a=new PDFJS.Promise;this.messageHandler.send("DataLoaded",null,function(b){a.resolve(b)});return a},
-getPage:function(a,b){var e=a-1;if(e in this.pagePromises)return this.pagePromises[e];b=new PDFJS.Promise("Page "+a);this.pagePromises[e]=b;this.messageHandler.send("GetPageRequest",{pageIndex:e});return b},getAnnotations:function(a){this.messageHandler.send("GetAnnotationsRequest",{pageIndex:a})},getDestinations:function(){var a=new PDFJS.Promise;this.messageHandler.send("GetDestinations",null,function(b){a.resolve(b)});return a}};return b}(),la=function(){function b(){this.objs={}}b.prototype={ensureObj:function(a){if(this.objs[a])return this.objs[a];
-var b={promise:new x(a),data:null,resolved:!1};return this.objs[a]=b},get:function(a,b){if(b)return this.ensureObj(a).promise.then(b),null;var e=this.objs[a];e&&e.resolved||m("Requesting object that isn't resolved yet "+a);return e.data},resolve:function(a,b){var e=this.ensureObj(a);e.resolved=!0;e.data=b;e.promise.resolve(b)},isResolved:function(a){var b=this.objs;return b[a]?b[a].resolved:!1},hasData:function(a){return this.isResolved(a)},getData:function(a){var b=this.objs;return b[a]&&b[a].resolved?
-b[a].data:null},clear:function(){this.objs={}}};return b}(),Ma=function(){function b(a){this.internalRenderTask=a;x.call(this)}b.prototype=Object.create(x.prototype);b.prototype.cancel=function(){this.internalRenderTask.cancel()};return b}(),La=function(){function b(a,b,e,d,g,f){this.callback=a;this.params=b;this.objs=e;this.commonObjs=d;this.operatorListIdx=null;this.operatorList=g;this.pageNumber=f;this.running=!1;this.graphicsReadyCallback=null;this.cancelled=this.graphicsReady=!1}b.prototype=
-{initalizeGraphics:function(a){if(!this.cancelled){PDFJS.pdfBug&&"StepperManager"in v&&v.StepperManager.enabled&&(this.stepper=v.StepperManager.create(this.pageNumber-1),this.stepper.init(this.operatorList),this.stepper.nextBreakPoint=this.stepper.getNextBreakPoint());var b=this.params;this.gfx=new ka(b.canvasContext,this.commonObjs,this.objs,b.textLayer,b.imageLayer);this.gfx.beginDrawing(b.viewport,a);this.operatorListIdx=0;this.graphicsReady=!0;this.graphicsReadyCallback&&this.graphicsReadyCallback()}},
-cancel:function(){this.running=!1;this.cancelled=!0;this.callback("cancelled")},operatorListChanged:function(){this.graphicsReady?(this.stepper&&this.stepper.updateOperatorList(this.operatorList),this.running||this._continue()):this.graphicsReadyCallback||(this.graphicsReadyCallback=this._continue.bind(this))},_continue:function(){this.running=!0;this.cancelled||(this.params.continueCallback?this.params.continueCallback(this._next.bind(this)):this._next())},_next:function(){this.cancelled||(this.operatorListIdx=
-this.gfx.executeOperatorList(this.operatorList,this.operatorListIdx,this._continue.bind(this),this.stepper),this.operatorListIdx===this.operatorList.fnArray.length&&(this.running=!1,this.operatorList.lastChunk&&(this.gfx.endDrawing(),this.callback())))}};return b}();PDFJS.Metadata=function(){function b(a){return a.replace(/>\\376\\377([^<]+)/g,function(a,b){for(var c=b.replace(/\\([0-3])([0-7])([0-7])/g,function(a,b,c,f){return String.fromCharCode(64*b+8*c+1*f)}),f="",k=0;k<c.length;k+=2)var h=256*
-c.charCodeAt(k)+c.charCodeAt(k+1),f=f+("&#x"+(65536+h).toString(16).substring(1)+";");return">"+f})}function a(a){"string"===typeof a?(a=b(a),a=(new DOMParser).parseFromString(a,"application/xml")):a instanceof Document||m("Metadata: Invalid metadata object");this.metaDocument=a;this.metadata={};this.parse()}a.prototype={parse:function(){var a=this.metaDocument.documentElement;if("rdf:rdf"!==a.nodeName.toLowerCase())for(a=a.firstChild;a&&"rdf:rdf"!==a.nodeName.toLowerCase();)a=a.nextSibling;var b=
-a?a.nodeName.toLowerCase():null;if(a&&"rdf:rdf"===b&&a.hasChildNodes()){var a=a.childNodes,d,g,f,k,h,l;f=0;for(h=a.length;f<h;f++)if(b=a[f],"rdf:description"===b.nodeName.toLowerCase())for(k=0,l=b.childNodes.length;k<l;k++)"#text"!==b.childNodes[k].nodeName.toLowerCase()&&(d=b.childNodes[k],g=d.nodeName.toLowerCase(),this.metadata[g]=d.textContent.trim())}},get:function(a){return this.metadata[a]||null},has:function(a){return"undefined"!==typeof this.metadata[a]}};return a}();var G=function(){var b=
-{};return{getCanvas:function(a,c,e,d){a in b?(a=b[a],a.canvas.width=c,a.canvas.height=e,a.context.setTransform(1,0,0,1,0,0)):(c=ea(c,e),e=c.getContext("2d"),d&&fa(e),b[a]=a={canvas:c,context:e});return a},clear:function(){b={}}}}(),ma=function(){function b(a){this.alphaIsShape=!1;this.fontSize=0;this.fontSizeScale=1;this.textMatrix=ha;this.fontMatrix=$;this.wordSpacing=this.charSpacing=this.lineY=this.lineX=this.y=this.x=this.leading=0;this.textHScale=1;this.textRenderingMode=V;this.textRise=0;this.fillColorSpace=
-p.singletons.gray;this.fillColorSpaceObj=null;this.strokeColorSpace=p.singletons.gray;this.strokeColorObj=this.fillColorObj=this.strokeColorSpaceObj=null;this.strokeColor=this.fillColor="#000000";this.lineWidth=this.strokeAlpha=this.fillAlpha=1;this.paintFormXObjectDepth=0;this.old=a}b.prototype={clone:function(){return Object.create(this)},setCurrentPoint:function(a,b){this.x=a;this.y=b}};return b}(),ka=function(){function b(a,b,c,d,e){this.ctx=a;this.current=new ma;this.stateStack=[];this.pendingClip=
-null;this.pendingEOFill=!1;this.xobjs=this.res=null;this.commonObjs=b;this.objs=c;this.textLayer=d;this.imageLayer=e;this.groupStack=[];this.baseTransform=this.processingType3=null;this.baseTransformStack=[];this.groupLevel=0;a&&fa(a)}function a(a,b){if("undefined"!==typeof ImageData&&b instanceof ImageData)a.putImageData(b,0,0);else{var c=a.createImageData(b.width,b.height),d=b.data,e=c.data;if("set"in e)e.set(d);else for(var g=0,y=e.length;g<y;g++)e[g]=d[g];a.putImageData(c,0,0)}}var c=["butt",
-"round","square"],e=["miter","round","bevel"],d={},g={};b.prototype={slowCommands:{stroke:!0,closeStroke:!0,fill:!0,eoFill:!0,fillStroke:!0,eoFillStroke:!0,closeFillStroke:!0,closeEOFillStroke:!0,showText:!0,showSpacedText:!0,setStrokeColorSpace:!0,setFillColorSpace:!0,setStrokeColor:!0,setStrokeColorN:!0,setFillColor:!0,setFillColorN:!0,setStrokeGray:!0,setFillGray:!0,setStrokeRGBColor:!0,setFillRGBColor:!0,setStrokeCMYKColor:!0,setFillCMYKColor:!0,paintJpegXObject:!0,paintImageXObject:!0,paintInlineImageXObject:!0,
-paintInlineImageXObjectGroup:!0,paintImageMaskXObject:!0,paintImageMaskXObjectGroup:!0,shadingFill:!0},beginDrawing:function(a,b){var c=this.ctx.canvas.width,d=this.ctx.canvas.height;b?this.ctx.clearRect(0,0,c,d):(this.ctx.mozOpaque=!0,this.ctx.save(),this.ctx.fillStyle="rgb(255, 255, 255)",this.ctx.fillRect(0,0,c,d),this.ctx.restore());c=a.transform;this.baseTransform=c.slice();this.ctx.save();this.ctx.transform.apply(this.ctx,c);this.textLayer&&this.textLayer.beginLayout();this.imageLayer&&this.imageLayer.beginLayout()},
-executeOperatorList:function(a,b,c,d){var e=a.argsArray;a=a.fnArray;b=b||0;var g=e.length;if(g==b)return b;for(var y=Date.now()+15,q=this.commonObjs,r=this.objs,m,u=this.slowCommands;;){if(d&&b===d.nextBreakPoint)return d.breakIt(b,c),b;m=a[b];if("dependency"!==m)this[m].apply(this,e[b]);else for(var s=e[b],p=0,E=s.length;p<E;p++){var z=s[p],v="g_"==z.substring(0,2);if(!v&&!r.isResolved(z))return r.get(z,c),b;if(v&&!q.isResolved(z))return q.get(z,c),b}b++;if(b==g)return b;if(c&&u[m]&&Date.now()>y)return setTimeout(c,
-0),b}},endDrawing:function(){this.ctx.restore();G.clear();this.textLayer&&this.textLayer.endLayout();this.imageLayer&&this.imageLayer.endLayout()},setLineWidth:function(a){this.current.lineWidth=a;this.ctx.lineWidth=a},setLineCap:function(a){this.ctx.lineCap=c[a]},setLineJoin:function(a){this.ctx.lineJoin=e[a]},setMiterLimit:function(a){this.ctx.miterLimit=a},setDash:function(a,b){var c=this.ctx;"setLineDash"in c?(c.setLineDash(a),c.lineDashOffset=b):(c.mozDash=a,c.mozDashOffset=b)},setRenderingIntent:function(a){},
-setFlatness:function(a){},setGState:function(a){for(var b=0,c=a.length;b<c;b++){var d=a[b],e=d[1];switch(d[0]){case "LW":this.setLineWidth(e);break;case "LC":this.setLineCap(e);break;case "LJ":this.setLineJoin(e);break;case "ML":this.setMiterLimit(e);break;case "D":this.setDash(e[0],e[1]);break;case "RI":this.setRenderingIntent(e);break;case "FL":this.setFlatness(e);break;case "Font":this.setFont(e[0],e[1]);break;case "CA":this.current.strokeAlpha=d[1];break;case "ca":this.current.fillAlpha=d[1];
-this.ctx.globalAlpha=d[1];break;case "BM":e&&e.name&&"Normal"!==e.name?(d=e.name.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()}).substring(1),this.ctx.globalCompositeOperation=d,this.ctx.globalCompositeOperation!==d&&F('globalCompositeOperation "'+d+'" is not supported')):this.ctx.globalCompositeOperation="source-over"}}},save:function(){this.ctx.save();var a=this.current;this.stateStack.push(a);this.current=a.clone()},restore:function(){var a=this.stateStack.pop();a&&(this.current=a,this.ctx.restore())},
-transform:function(a,b,c,d,e,g){this.ctx.transform(a,b,c,d,e,g)},moveTo:function(a,b){this.ctx.moveTo(a,b);this.current.setCurrentPoint(a,b)},lineTo:function(a,b){this.ctx.lineTo(a,b);this.current.setCurrentPoint(a,b)},curveTo:function(a,b,c,d,e,g){this.ctx.bezierCurveTo(a,b,c,d,e,g);this.current.setCurrentPoint(e,g)},curveTo2:function(a,b,c,d){var e=this.current;this.ctx.bezierCurveTo(e.x,e.y,a,b,c,d);e.setCurrentPoint(c,d)},curveTo3:function(a,b,c,d){this.curveTo(a,b,c,d,c,d);this.current.setCurrentPoint(c,
-d)},closePath:function(){this.ctx.closePath()},rectangle:function(a,b,c,d){this.ctx.rect(a,b,c,d)},stroke:function(a){a="undefined"!==typeof a?a:!0;var b=this.ctx,c=this.current.strokeColor;0===this.current.lineWidth&&(b.lineWidth=this.getSinglePixelWidth());b.globalAlpha=this.current.strokeAlpha;c&&c.hasOwnProperty("type")&&"Pattern"===c.type?(b.save(),b.strokeStyle=c.getPattern(b,this),b.stroke(),b.restore()):b.stroke();a&&this.consumePath();b.globalAlpha=this.current.fillAlpha},closeStroke:function(){this.closePath();
-this.stroke()},fill:function(a){a="undefined"!==typeof a?a:!0;var b=this.ctx,c=this.current.fillColor,d=!1;c&&c.hasOwnProperty("type")&&"Pattern"===c.type&&(b.save(),b.fillStyle=c.getPattern(b,this),d=!0);if(this.pendingEOFill){if("mozFillRule"in this.ctx)this.ctx.mozFillRule="evenodd",this.ctx.fill(),this.ctx.mozFillRule="nonzero";else try{this.ctx.fill("evenodd")}catch(e){this.ctx.fill()}this.pendingEOFill=!1}else this.ctx.fill();d&&b.restore();a&&this.consumePath()},eoFill:function(){this.pendingEOFill=
-!0;this.fill()},fillStroke:function(){this.fill(!1);this.stroke(!1);this.consumePath()},eoFillStroke:function(){this.pendingEOFill=!0;this.fillStroke()},closeFillStroke:function(){this.closePath();this.fillStroke()},closeEOFillStroke:function(){this.pendingEOFill=!0;this.closePath();this.fillStroke()},endPath:function(){this.consumePath()},clip:function(){this.pendingClip=d},eoClip:function(){this.pendingClip=g},beginText:function(){this.current.textMatrix=ha;this.current.x=this.current.lineX=0;this.current.y=
-this.current.lineY=0},endText:function(){if("pendingTextPaths"in this){var a=this.pendingTextPaths,b=this.ctx;b.save();b.beginPath();for(var c=0;c<a.length;c++){var d=a[c];b.setTransform.apply(b,d.transform);b.translate(d.x,d.y);d.addToPath(b,d.fontSize)}b.restore();b.clip();b.beginPath();delete this.pendingTextPaths}else this.ctx.beginPath()},setCharSpacing:function(a){this.current.charSpacing=a},setWordSpacing:function(a){this.current.wordSpacing=a},setHScale:function(a){this.current.textHScale=
-a/100},setLeading:function(a){this.current.leading=-a},setFont:function(a,b){var c=this.commonObjs.get(a),d=this.current;c||m("Can't find font for "+a);d.fontMatrix=c.fontMatrix?c.fontMatrix:$;0!==d.fontMatrix[0]&&0!==d.fontMatrix[3]||F("Invalid font matrix for font "+a);0>b?(b=-b,d.fontDirection=-1):d.fontDirection=1;this.current.font=c;this.current.fontSize=b;if(!c.coded){var d=c.black?c.bold?"bolder":"bold":c.bold?"bold":"normal",e=c.italic?"italic":"normal",c='"'+(c.loadedName||"sans-serif")+
-'", '+c.fallbackName,g=16<=b?b:16;this.current.fontSizeScale=16!=g?1:b/16;this.ctx.font=e+" "+d+" "+g+"px "+c}},setTextRenderingMode:function(a){this.current.textRenderingMode=a},setTextRise:function(a){this.current.textRise=a},moveText:function(a,b){this.current.x=this.current.lineX+=a;this.current.y=this.current.lineY+=b},setLeadingMoveText:function(a,b){this.setLeading(-b);this.moveText(a,b)},setTextMatrix:function(a,b,c,d,e,g){this.current.textMatrix=[a,b,c,d,e,g];this.current.x=this.current.lineX=
-0;this.current.y=this.current.lineY=0},nextLine:function(){this.moveText(0,this.current.leading)},applyTextTransforms:function(){var a=this.ctx,b=this.current;a.transform.apply(a,b.textMatrix);a.translate(b.x,b.y+b.textRise);0<b.fontDirection?a.scale(b.textHScale,-1):a.scale(-b.textHScale,1)},createTextGeometry:function(){var a={},b=this.current.font,c=this.ctx.mozCurrentTransform,d=c[0],e=c[1],g=c[2],m=c[3],q=c[4],c=c[5],r=0<=d?Math.sqrt(d*d+e*e):-Math.sqrt(d*d+e*e),g=0<=m?Math.sqrt(g*g+m*m):-Math.sqrt(g*
-g+m*m),d=Math.atan2(e,d);a.x=q;a.y=c;a.hScale=r;a.vScale=g;a.angle=d;a.spaceWidth=b.spaceWidth;a.fontName=b.loadedName;a.fontFamily=b.fallbackName;a.fontSize=this.current.fontSize;return a},paintChar:function(a,b,c){var d=this.ctx,e=this.current,g=e.font,m=e.fontSize/e.fontSizeScale,q=e.textRenderingMode,e=q&3,q=!!(q&4),r;if(g.disableFontFace||q)r=g.getPathGenerator(this.commonObjs,a);g.disableFontFace?(d.save(),d.translate(b,c),d.beginPath(),r(d,m),e!==V&&2!==e||d.fill(),1!==e&&2!==e||d.stroke(),
-d.restore()):(e!==V&&2!==e||d.fillText(a,b,c),1!==e&&2!==e||d.strokeText(a,b,c));q&&(this.pendingTextPaths||(this.pendingTextPaths=[])).push({transform:d.mozCurrentTransform,x:b,y:c,fontSize:m,addToPath:r})},showText:function(a,b){var c=this.ctx,d=this.current,e=d.font,g=d.fontSize,m=d.fontSizeScale,q=d.charSpacing,r=d.wordSpacing,p=d.textHScale*d.fontDirection,u=d.fontMatrix||$,w=a.length,v,E=this.textLayer&&!b?!0:!1,z=0,A=e.vertical,F=e.defaultVMetrics;if(e.coded){c.save();c.transform.apply(c,d.textMatrix);
-c.translate(d.x,d.y);c.scale(p,1);E&&(this.save(),c.scale(1,-1),v=this.createTextGeometry(),this.restore());for(var I=0;I<w;++I){var C=a[I];if(null===C)this.ctx.translate(r,0),d.x+=r*p;else{this.processingType3=C;this.save();c.scale(g,g);c.transform.apply(c,u);this.executeOperatorList(C.operatorList);this.restore();var x=(s.applyTransform([C.width,0],u)[0]*g+q)*d.fontDirection;c.translate(x,0);d.x+=x*p;z+=x}}c.restore();this.processingType3=null}else{c.save();this.applyTextTransforms();var I=d.lineWidth,
-u=d.textMatrix[0],B=d.textMatrix[1],u=Math.sqrt(u*u+B*B),I=0===u||0===I?this.getSinglePixelWidth():I/u;E&&(v=this.createTextGeometry());1!=m&&(c.scale(m,m),I/=m);c.lineWidth=I;for(I=u=0;I<w;++I)if(C=a[I],null===C)u+=d.fontDirection*r;else{var B=!1,H=C.fontChar,D=C.vmetric||F;if(A)var L=C.vmetric?D[1]:0.5*C.width,L=-L*g*d.fontMatrix[0],M=D[2]*g*d.fontMatrix[0];var x=D?-D[0]:C.width,D=x*g*d.fontMatrix[0]+q*d.fontDirection,G=C.accent,J,K;C.disabled||(A?(C=L/m,J=(u+M)/m):(C=u/m,J=0),e.remeasure&&0<x&&
-(B=1E3*c.measureText(H).width/d.fontSize*d.fontSizeScale,x/=B,B=!0,c.save(),c.scale(x,1),C/=x,G&&(K/=x)),this.paintChar(H,C,J),G&&(K=C+G.offset.x/m,H=J-G.offset.y/m,this.paintChar(G.fontChar,K,H)));u+=D;z+=D;B&&c.restore()}A?d.y-=u*p:d.x+=u*p;c.restore()}E&&(v.canvasWidth=z,A&&(v.angle+=Math.PI/2),this.textLayer.appendText(v));return z},showSpacedText:function(a){var b=this.ctx,c=this.current,d=c.fontSize,e=0.0010*c.textHScale*c.fontDirection,g=a.length,m,q=0,r=this.textLayer?!0:!1,s=c.font.vertical,
-u=0;r&&(b.save(),this.applyTextTransforms(),m=this.createTextGeometry(),b.restore());for(b=0;b<g;++b){var p=a[b];"number"==typeof p?(p=-p*d*e,s?c.y+=p:c.x+=p,r&&(u+=p)):(p=this.showText(p,!0),r&&(q+=u+p,u=0))}r&&(m.canvasWidth=q,s&&(m.angle+=Math.PI/2),this.textLayer.appendText(m))},nextLineShowText:function(a){this.nextLine();this.showText(a)},nextLineSetSpacingShowText:function(a,b,c){this.setWordSpacing(a);this.setCharSpacing(b);this.nextLineShowText(c)},setCharWidth:function(a,b){},setCharWidthAndBounds:function(a,
-b,c,d,e,g){this.rectangle(c,d,e-c,g-d);this.clip();this.endPath()},setStrokeColorSpace:function(a){this.current.strokeColorSpace=p.fromIR(a)},setFillColorSpace:function(a){this.current.fillColorSpace=p.fromIR(a)},setStrokeColor:function(){var a=this.current.strokeColorSpace.getRgb(arguments,0),a=s.makeCssRgb(a);this.ctx.strokeStyle=a;this.current.strokeColor=a},getColorN_Pattern:function(a,b){if("TilingPattern"==a[0]){var c=a[1],d=b.base,e;d&&(e=d.getRgb(c,0));c=new Aa(a,e,this.ctx,this.objs,this.commonObjs,
-this.baseTransform)}else"RadialAxial"==a[0]||"Dummy"==a[0]?c=ja.shadingFromIR(a):m("Unkown IR type "+a[0]);return c},setStrokeColorN:function(){var a=this.current.strokeColorSpace;"Pattern"==a.name?this.current.strokeColor=this.getColorN_Pattern(arguments,a):this.setStrokeColor.apply(this,arguments)},setFillColor:function(){var a=this.current.fillColorSpace.getRgb(arguments,0),a=s.makeCssRgb(a);this.ctx.fillStyle=a;this.current.fillColor=a},setFillColorN:function(){var a=this.current.fillColorSpace;
-"Pattern"==a.name?this.current.fillColor=this.getColorN_Pattern(arguments,a):this.setFillColor.apply(this,arguments)},setStrokeGray:function(a){this.current.strokeColorSpace=p.singletons.gray;var b=this.current.strokeColorSpace.getRgb(arguments,0),b=s.makeCssRgb(b);this.ctx.strokeStyle=b;this.current.strokeColor=b},setFillGray:function(a){this.current.fillColorSpace=p.singletons.gray;var b=this.current.fillColorSpace.getRgb(arguments,0),b=s.makeCssRgb(b);this.ctx.fillStyle=b;this.current.fillColor=
-b},setStrokeRGBColor:function(a,b,c){this.current.strokeColorSpace=p.singletons.rgb;var d=this.current.strokeColorSpace.getRgb(arguments,0),d=s.makeCssRgb(d);this.ctx.strokeStyle=d;this.current.strokeColor=d},setFillRGBColor:function(a,b,c){this.current.fillColorSpace=p.singletons.rgb;var d=this.current.fillColorSpace.getRgb(arguments,0),d=s.makeCssRgb(d);this.ctx.fillStyle=d;this.current.fillColor=d},setStrokeCMYKColor:function(a,b,c,d){this.current.strokeColorSpace=p.singletons.cmyk;var e=s.makeCssCmyk(arguments);
-this.ctx.strokeStyle=e;this.current.strokeColor=e},setFillCMYKColor:function(a,b,c,d){this.current.fillColorSpace=p.singletons.cmyk;var e=s.makeCssCmyk(arguments);this.ctx.fillStyle=e;this.current.fillColor=e},shadingFill:function(a){var b=this.ctx;this.save();a=ja.shadingFromIR(a);b.fillStyle=a.getPattern(b,this);var c=b.mozCurrentTransformInverse;if(c){var b=b.canvas,d=b.width,e=b.height,b=s.applyTransform([0,0],c);a=s.applyTransform([0,e],c);var g=s.applyTransform([d,0],c),m=s.applyTransform([d,
-e],c),c=Math.min(b[0],a[0],g[0],m[0]),d=Math.min(b[1],a[1],g[1],m[1]),e=Math.max(b[0],a[0],g[0],m[0]),b=Math.max(b[1],a[1],g[1],m[1]);this.ctx.fillRect(c,d,e-c,b-d)}else this.ctx.fillRect(-1E10,-1E10,2E10,2E10);this.restore()},beginInlineImage:function(){m("Should not call beginInlineImage")},beginImageData:function(){m("Should not call beginImageData")},paintFormXObjectBegin:function(a,b){this.save();this.current.paintFormXObjectDepth++;this.baseTransformStack.push(this.baseTransform);a&&B(a)&&6==
-a.length&&this.transform.apply(this,a);this.baseTransform=this.ctx.mozCurrentTransform;b&&B(b)&&4==b.length&&(this.rectangle(b[0],b[1],b[2]-b[0],b[3]-b[1]),this.clip(),this.endPath())},paintFormXObjectEnd:function(){var a=this.current.paintFormXObjectDepth;do this.restore();while(this.current.paintFormXObjectDepth>=a);this.baseTransform=this.baseTransformStack.pop()},beginGroup:function(a){this.save();var b=this.ctx;a.isolated||S("TODO: Support non-isolated groups.");a.knockout&&K("Support knockout groups.");
-var c=b.mozCurrentTransform;a.matrix&&b.transform.apply(b,a.matrix);a.bbox||m("Bounding box is required.");var d=s.getAxialAlignedBoundingBox(a.bbox,b.mozCurrentTransform);a=Math.max(Math.ceil(d[2]-d[0]),1);var e=Math.max(Math.ceil(d[3]-d[1]),1);a=G.getCanvas("groupAt"+this.groupLevel,a,e,!0).context;e=d[0];d=d[1];a.translate(-e,-d);a.transform.apply(a,c);b.setTransform(1,0,0,1,0,0);b.translate(e,d);c="strokeStyle fillStyle fillRule globalAlpha lineWidth lineCap lineJoin miterLimit globalCompositeOperation font".split(" ");
-d=0;for(e=c.length;d<e;d++){var g=c[d];g in b&&(a[g]=b[g])}"setLineDash"in b?(a.setLineDash(b.getLineDash()),a.lineDashOffset=b.lineDashOffset):"mozDash"in b&&(a.mozDash=b.mozDash,a.mozDashOffset=b.mozDashOffset);this.ctx=a;this.setGState([["SMask","None"],["BM","Normal"],["ca",1],["CA",1]]);this.groupStack.push(b);this.groupLevel++},endGroup:function(a){this.groupLevel--;a=this.ctx;this.ctx=this.groupStack.pop();"imageSmoothingEnabled"in this.ctx?this.ctx.imageSmoothingEnabled=!1:this.ctx.mozImageSmoothingEnabled=
-!1;this.ctx.drawImage(a.canvas,0,0);this.restore()},beginAnnotations:function(){this.save();this.current=new ma},endAnnotations:function(){this.restore()},beginAnnotation:function(a,b,c){this.save();a&&B(a)&&4==a.length&&(this.rectangle(a[0],a[1],a[2]-a[0],a[3]-a[1]),this.clip(),this.endPath());this.transform.apply(this,b);this.transform.apply(this,c)},endAnnotation:function(){this.restore()},paintJpegXObject:function(a,b,c){var d=this.objs.get(a);d||m("Dependent image isn't ready yet");this.save();
-var e=this.ctx;e.scale(1/b,-1/c);e.drawImage(d,0,0,d.width,d.height,0,-c,b,c);this.imageLayer&&(d=e.mozCurrentTransformInverse,e=this.getCanvasPosition(0,0),this.imageLayer.appendImage({objId:a,left:e[0],top:e[1],width:b/d[0],height:c/d[3]}));this.restore()},paintImageMaskXObject:function(b){var c=this.ctx,d=b.width,e=b.height,g=this.processingType3;!g||"compiled"in g||(g.compiled=1E3>=d&&1E3>=e?ra({data:b.data,width:d,height:e}):null);g&&g.compiled?g.compiled(c):(c=G.getCanvas("maskCanvas",d,e),
-g=c.context,g.save(),a(g,b),g.globalCompositeOperation="source-in",b=this.current.fillColor,g.fillStyle=b&&b.hasOwnProperty("type")&&"Pattern"===b.type?b.getPattern(g,this):b,g.fillRect(0,0,d,e),g.restore(),this.paintInlineImageXObject(c.canvas))},paintImageMaskXObjectGroup:function(b){for(var c=this.ctx,d=0,e=b.length;d<e;d++){var g=b[d],m=g.width,p=g.height,q=G.getCanvas("maskCanvas",m,p),r=q.context;r.save();a(r,g);r.globalCompositeOperation="source-in";var s=this.current.fillColor;r.fillStyle=
-s&&s.hasOwnProperty("type")&&"Pattern"===s.type?s.getPattern(r,this):s;r.fillRect(0,0,m,p);r.restore();c.save();c.transform.apply(c,g.transform);c.scale(1,-1);c.drawImage(q.canvas,0,0,m,p,0,-1,1,1);c.restore()}},paintImageXObject:function(a){(a=this.objs.get(a))||m("Dependent image isn't ready yet");this.paintInlineImageXObject(a)},paintInlineImageXObject:function(b){var c=b.width,d=b.height,e=this.ctx;this.save();e.scale(1/c,-1/d);var g=e.mozCurrentTransformInverse,m=g[0],p=g[1],m=Math.max(Math.sqrt(m*
-m+p*p),1),p=g[2],q=g[3],p=Math.max(Math.sqrt(p*p+q*q),1);if(b instanceof HTMLElement)q=b;else{var r=G.getCanvas("inlineImage",c,d),s=r.context;a(s,b);q=r.canvas}for(var u=c,w=d,v="prescale1";2<m&&1<u||2<p&&1<w;){var x=u,z=w;2<m&&1<u&&(x=Math.ceil(u/2),m/=u/x);2<p&&1<w&&(z=Math.ceil(w/2),p/=w/z);r=G.getCanvas(v,x,z);s=r.context;s.clearRect(0,0,x,z);s.drawImage(q,0,0,u,w,0,0,x,z);q=r.canvas;u=x;w=z;v="prescale1"===v?"prescale2":"prescale1"}e.drawImage(q,0,0,u,w,0,-d,c,d);this.imageLayer&&(e=this.getCanvasPosition(0,
--d),this.imageLayer.appendImage({imgData:b,left:e[0],top:e[1],width:c/g[0],height:d/g[3]}));this.restore()},paintInlineImageXObjectGroup:function(b,c){var d=this.ctx,e=b.width,g=b.height,m=G.getCanvas("inlineImage",e,g);a(m.context,b);for(var p=0,q=c.length;p<q;p++){var r=c[p];d.save();d.transform.apply(d,r.transform);d.scale(1,-1);d.drawImage(m.canvas,r.x,r.y,r.w,r.h,0,-1,1,1);this.imageLayer&&(r=this.getCanvasPosition(r.x,r.y),this.imageLayer.appendImage({imgData:b,left:r[0],top:r[1],width:e,height:g}));
-d.restore()}},markPoint:function(a){},markPointProps:function(a,b){},beginMarkedContent:function(a){},beginMarkedContentProps:function(a,b){},endMarkedContent:function(){},beginCompat:function(){},endCompat:function(){},consumePath:function(){if(this.pendingClip){if(this.pendingClip==g)if("mozFillRule"in this.ctx)this.ctx.mozFillRule="evenodd",this.ctx.clip(),this.ctx.mozFillRule="nonzero";else try{this.ctx.clip("evenodd")}catch(a){this.ctx.clip()}else this.ctx.clip();this.pendingClip=null}this.ctx.beginPath()},
-getSinglePixelWidth:function(a){a=this.ctx.mozCurrentTransformInverse;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1],a[2]*a[2]+a[3]*a[3]))},getCanvasPosition:function(a,b){var c=this.ctx.mozCurrentTransform;return[c[0]*a+c[2]*b+c[4],c[1]*a+c[3]*b+c[5]]}};return b}();PDFJS.disableFontFace=!1;var R={insertRule:function(b){var a=document.getElementById("PDFJS_FONT_STYLE_TAG");a||(a=document.createElement("style"),a.id="PDFJS_FONT_STYLE_TAG",document.documentElement.getElementsByTagName("head")[0].appendChild(a));
-a=a.sheet;a.insertRule(b,a.cssRules.length)},get loadTestFont(){return W(this,"loadTestFont",atob("T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA=="))},
-loadTestFontId:0,loadingContext:{requests:[],nextRequestId:0},isSyncFontLoadingSupported:function(){if(U)return!1;var b=/Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(window.navigator.userAgent);return b&&14<=b[1]?!0:!1}(),bind:function(b,a){U&&m("bind() shall be called from main thread");for(var c=[],e=[],d=0,g=b.length;d<g;d++){var f=b[d];if(!f.attached&&!1!==f.loading){f.attached=!0;var k=f.bindDOM();k&&(c.push(k),e.push(f))}}d=R.queueLoadingCallback(a);0<c.length&&!this.isSyncFontLoadingSupported?R.prepareFontLoadEvent(c,
-e,d):d.complete()},queueLoadingCallback:function(b){var a=R.loadingContext,c={id:"pdfjs-font-loading-"+a.nextRequestId++,complete:function(){c.end&&m("completeRequest() cannot be called twice");for(c.end=Date.now();0<a.requests.length&&a.requests[0].end;){var b=a.requests.shift();setTimeout(b.callback,0)}},callback:b,started:Date.now()};a.requests.push(c);return c},prepareFontLoadEvent:function(b,a,c){function e(a,b){return a.charCodeAt(b)<<24|a.charCodeAt(b+1)<<16|a.charCodeAt(b+2)<<8|a.charCodeAt(b+
-3)&255}function d(a,b,c,d){a=m.substr(0,b);b=m.substr(b+c);return a+d+b}function g(a,b){l++;30<l?(F("Load test font never loaded."),b()):(h.font="30px "+a,h.fillText(".",0,20),0<h.getImageData(0,0,1,1).data[3]?b():setTimeout(g.bind(null,a,b)))}var f,k;b=document.createElement("canvas");b.width=1;b.height=1;var h=b.getContext("2d"),l=0;b="lt"+Date.now()+this.loadTestFontId++;var m=this.loadTestFont,m=d(m,976,b.length,b),p=e(m,16);f=0;for(k=b.length-3;f<k;f+=4)p=p-1482184792+e(b,f)|0;f<b.length&&(p=
-p-1482184792+e(b+"XXX",f)|0);m=d(m,16,4,String.fromCharCode(p>>24&255)+String.fromCharCode(p>>16&255)+String.fromCharCode(p>>8&255)+String.fromCharCode(p&255));f="url(data:font/opentype;base64,"+btoa(m)+");";R.insertRule('@font-face { font-family:"'+b+'";src:'+f+"}");p=[];f=0;for(k=a.length;f<k;f++)p.push(a[f].loadedName);p.push(b);var s=document.createElement("div");s.setAttribute("style","visibility: hidden;width: 10px; height: 10px;position: absolute; top: 0px; left: 0px;");f=0;for(k=p.length;f<
-k;++f)a=document.createElement("span"),a.textContent="Hi",a.style.fontFamily=p[f],s.appendChild(a);document.body.appendChild(s);g(b,function(){document.body.removeChild(s);c.complete()})}},Oa=function(){function b(a,b,e){this.compiledGlyphs={};if(1===arguments.length){var d=arguments[0],g;for(g in d)this[g]=d[g]}}b.prototype={bindDOM:function(){if(!this.data)return null;if(PDFJS.disableFontFace)return this.disableFontFace=!0,null;for(var a=this.data,b="",e=a.length,d=0;d<e;++d)b+=String.fromCharCode(a[d]);
-a=this.loadedName;b="url(data:"+this.mimetype+";base64,"+window.btoa(b)+");";a='@font-face { font-family:"'+a+'";src:'+b+"}";R.insertRule(a);PDFJS.pdfBug&&"FontInspector"in v&&v.FontInspector.enabled&&v.FontInspector.fontAdded(this,b);return a},getPathGenerator:function(a,b){if(!(b in this.compiledGlyphs)){var e=a.get(this.loadedName+"_path_"+b);this.compiledGlyphs[b]=new Function("c","size",e)}return this.compiledGlyphs[b]}};return b}()}).call("undefined"===typeof window?this:window);
-PDFJS.workerSrc||"undefined"===typeof document||(PDFJS.workerSrc=function(){var D=(document.body||document.getElementsByTagName("head")[0]).lastChild.src;return D&&D.replace(/\.js$/i,".worker.js")}());
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* Copyright 2012 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Initializing PDFJS global object (if still undefined)
+if (typeof PDFJS === 'undefined') {
+  (typeof window !== 'undefined' ? window : this).PDFJS = {};
+}
+
+PDFJS.version = '0.8.894';
+PDFJS.build = 'ac91047';
+
+(function pdfjsWrapper() {
+  // Use strict in our context only - users might not want it
+  'use strict';
+
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* Copyright 2012 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL,
+           Promise */
+
+'use strict';
+
+var globalScope = (typeof window === 'undefined') ? this : window;
+
+var isWorker = (typeof window == 'undefined');
+
+var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
+
+var TextRenderingMode = {
+  FILL: 0,
+  STROKE: 1,
+  FILL_STROKE: 2,
+  INVISIBLE: 3,
+  FILL_ADD_TO_PATH: 4,
+  STROKE_ADD_TO_PATH: 5,
+  FILL_STROKE_ADD_TO_PATH: 6,
+  ADD_TO_PATH: 7,
+  FILL_STROKE_MASK: 3,
+  ADD_TO_PATH_FLAG: 4
+};
+
+// The global PDFJS object exposes the API
+// In production, it will be declared outside a global wrapper
+// In development, it will be declared here
+if (!globalScope.PDFJS) {
+  globalScope.PDFJS = {};
+}
+
+globalScope.PDFJS.pdfBug = false;
+
+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,
+  setMiterLimit: 5,
+  setDash: 6,
+  setRenderingIntent: 7,
+  setFlatness: 8,
+  setGState: 9,
+  save: 10,
+  restore: 11,
+  transform: 12,
+  moveTo: 13,
+  lineTo: 14,
+  curveTo: 15,
+  curveTo2: 16,
+  curveTo3: 17,
+  closePath: 18,
+  rectangle: 19,
+  stroke: 20,
+  closeStroke: 21,
+  fill: 22,
+  eoFill: 23,
+  fillStroke: 24,
+  eoFillStroke: 25,
+  closeFillStroke: 26,
+  closeEOFillStroke: 27,
+  endPath: 28,
+  clip: 29,
+  eoClip: 30,
+  beginText: 31,
+  endText: 32,
+  setCharSpacing: 33,
+  setWordSpacing: 34,
+  setHScale: 35,
+  setLeading: 36,
+  setFont: 37,
+  setTextRenderingMode: 38,
+  setTextRise: 39,
+  moveText: 40,
+  setLeadingMoveText: 41,
+  setTextMatrix: 42,
+  nextLine: 43,
+  showText: 44,
+  showSpacedText: 45,
+  nextLineShowText: 46,
+  nextLineSetSpacingShowText: 47,
+  setCharWidth: 48,
+  setCharWidthAndBounds: 49,
+  setStrokeColorSpace: 50,
+  setFillColorSpace: 51,
+  setStrokeColor: 52,
+  setStrokeColorN: 53,
+  setFillColor: 54,
+  setFillColorN: 55,
+  setStrokeGray: 56,
+  setFillGray: 57,
+  setStrokeRGBColor: 58,
+  setFillRGBColor: 59,
+  setStrokeCMYKColor: 60,
+  setFillCMYKColor: 61,
+  shadingFill: 62,
+  beginInlineImage: 63,
+  beginImageData: 64,
+  endInlineImage: 65,
+  paintXObject: 66,
+  markPoint: 67,
+  markPointProps: 68,
+  beginMarkedContent: 69,
+  beginMarkedContentProps: 70,
+  endMarkedContent: 71,
+  beginCompat: 72,
+  endCompat: 73,
+  paintFormXObjectBegin: 74,
+  paintFormXObjectEnd: 75,
+  beginGroup: 76,
+  endGroup: 77,
+  beginAnnotations: 78,
+  endAnnotations: 79,
+  beginAnnotation: 80,
+  endAnnotation: 81,
+  paintJpegXObject: 82,
+  paintImageMaskXObject: 83,
+  paintImageMaskXObjectGroup: 84,
+  paintImageXObject: 85,
+  paintInlineImageXObject: 86,
+  paintInlineImageXObjectGroup: 87
+};
+
+// 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.
+function info(msg) {
+  if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) {
+    console.log('Info: ' + msg);
+  }
+}
+
+// Non-fatal warnings.
+function warn(msg) {
+  if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) {
+    console.log('Warning: ' + 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);
+    // 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);
+  throw new Error(msg);
+}
+
+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 (url.indexOf(':') >= 0)
+    return url;
+  if (url.charAt(0) == '/') {
+    // absolute path
+    var i = baseUrl.indexOf('://');
+    i = baseUrl.indexOf('/', i + 3);
+    return baseUrl.substring(0, i) + url;
+  } else {
+    // relative path
+    var pathLength = baseUrl.length, i;
+    i = baseUrl.lastIndexOf('#');
+    pathLength = i >= 0 ? i : pathLength;
+    i = baseUrl.lastIndexOf('?', pathLength);
+    pathLength = i >= 0 ? i : pathLength;
+    var prefixLength = baseUrl.lastIndexOf('/', pathLength);
+    return baseUrl.substring(0, prefixLength + 1) + url;
+  }
+}
+
+// Validates if URL is safe and allowed, e.g. to avoid XSS.
+function isValidUrl(url, allowRelative) {
+  if (!url) {
+    return false;
+  }
+  var colon = url.indexOf(':');
+  if (colon < 0) {
+    return allowRelative;
+  }
+  var protocol = url.substr(0, colon);
+  switch (protocol) {
+    case 'http':
+    case 'https':
+    case 'ftp':
+    case 'mailto':
+      return true;
+    default:
+      return false;
+  }
+}
+PDFJS.isValidUrl = isValidUrl;
+
+// In a well-formed PDF, |cond| holds.  If it doesn't, subsequent
+// behavior is undefined.
+function assertWellFormed(cond, msg) {
+  if (!cond)
+    error(msg);
+}
+
+function shadow(obj, prop, value) {
+  Object.defineProperty(obj, prop, { value: value,
+                                     enumerable: true,
+                                     configurable: true,
+                                     writable: false });
+  return value;
+}
+
+var PasswordResponses = PDFJS.PasswordResponses = {
+  NEED_PASSWORD: 1,
+  INCORRECT_PASSWORD: 2
+};
+
+var PasswordException = (function PasswordExceptionClosure() {
+  function PasswordException(msg, code) {
+    this.name = 'PasswordException';
+    this.message = msg;
+    this.code = code;
+  }
+
+  PasswordException.prototype = new Error();
+  PasswordException.constructor = PasswordException;
+
+  return PasswordException;
+})();
+
+var UnknownErrorException = (function UnknownErrorExceptionClosure() {
+  function UnknownErrorException(msg, details) {
+    this.name = 'UnknownErrorException';
+    this.message = msg;
+    this.details = details;
+  }
+
+  UnknownErrorException.prototype = new Error();
+  UnknownErrorException.constructor = UnknownErrorException;
+
+  return UnknownErrorException;
+})();
+
+var InvalidPDFException = (function InvalidPDFExceptionClosure() {
+  function InvalidPDFException(msg) {
+    this.name = 'InvalidPDFException';
+    this.message = msg;
+  }
+
+  InvalidPDFException.prototype = new Error();
+  InvalidPDFException.constructor = InvalidPDFException;
+
+  return InvalidPDFException;
+})();
+
+var MissingPDFException = (function MissingPDFExceptionClosure() {
+  function MissingPDFException(msg) {
+    this.name = 'MissingPDFException';
+    this.message = msg;
+  }
+
+  MissingPDFException.prototype = new Error();
+  MissingPDFException.constructor = MissingPDFException;
+
+  return MissingPDFException;
+})();
+
+var NotImplementedException = (function NotImplementedExceptionClosure() {
+  function NotImplementedException(msg) {
+    this.message = msg;
+  }
+
+  NotImplementedException.prototype = new Error();
+  NotImplementedException.prototype.name = 'NotImplementedException';
+  NotImplementedException.constructor = NotImplementedException;
+
+  return NotImplementedException;
+})();
+
+var MissingDataException = (function MissingDataExceptionClosure() {
+  function MissingDataException(begin, end) {
+    this.begin = begin;
+    this.end = end;
+    this.message = 'Missing data [' + begin + ', ' + end + ')';
+  }
+
+  MissingDataException.prototype = new Error();
+  MissingDataException.prototype.name = 'MissingDataException';
+  MissingDataException.constructor = MissingDataException;
+
+  return MissingDataException;
+})();
+
+var XRefParseException = (function XRefParseExceptionClosure() {
+  function XRefParseException(msg) {
+    this.message = msg;
+  }
+
+  XRefParseException.prototype = new Error();
+  XRefParseException.prototype.name = 'XRefParseException';
+  XRefParseException.constructor = XRefParseException;
+
+  return XRefParseException;
+})();
+
+
+function bytesToString(bytes) {
+  var str = '';
+  var length = bytes.length;
+  for (var n = 0; n < length; ++n)
+    str += String.fromCharCode(bytes[n]);
+  return str;
+}
+
+function stringToBytes(str) {
+  var length = str.length;
+  var bytes = new Uint8Array(length);
+  for (var n = 0; n < length; ++n)
+    bytes[n] = str.charCodeAt(n) & 0xFF;
+  return bytes;
+}
+
+var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
+
+var Util = PDFJS.Util = (function UtilClosure() {
+  function Util() {}
+
+  Util.makeCssRgb = function Util_makeCssRgb(rgb) {
+    return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
+  };
+
+  Util.makeCssCmyk = function Util_makeCssCmyk(cmyk) {
+    var rgb = ColorSpace.singletons.cmyk.getRgb(cmyk, 0);
+    return Util.makeCssRgb(rgb);
+  };
+
+  // Concatenates two transformation matrices together and returns the result.
+  Util.transform = function Util_transform(m1, m2) {
+    return [
+      m1[0] * m2[0] + m1[2] * m2[1],
+      m1[1] * m2[0] + m1[3] * m2[1],
+      m1[0] * m2[2] + m1[2] * m2[3],
+      m1[1] * m2[2] + m1[3] * m2[3],
+      m1[0] * m2[4] + m1[2] * m2[5] + m1[4],
+      m1[1] * m2[4] + m1[3] * m2[5] + m1[5]
+    ];
+  };
+
+  // For 2d affine transforms
+  Util.applyTransform = function Util_applyTransform(p, m) {
+    var xt = p[0] * m[0] + p[1] * m[2] + m[4];
+    var yt = p[0] * m[1] + p[1] * m[3] + m[5];
+    return [xt, yt];
+  };
+
+  Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
+    var d = m[0] * m[3] - m[1] * m[2];
+    var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
+    var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
+    return [xt, yt];
+  };
+
+  // Applies the transform to the rectangle and finds the minimum axially
+  // aligned bounding box.
+  Util.getAxialAlignedBoundingBox =
+    function Util_getAxialAlignedBoundingBox(r, m) {
+
+    var p1 = Util.applyTransform(r, m);
+    var p2 = Util.applyTransform(r.slice(2, 4), m);
+    var p3 = Util.applyTransform([r[0], r[3]], m);
+    var p4 = Util.applyTransform([r[2], r[1]], m);
+    return [
+      Math.min(p1[0], p2[0], p3[0], p4[0]),
+      Math.min(p1[1], p2[1], p3[1], p4[1]),
+      Math.max(p1[0], p2[0], p3[0], p4[0]),
+      Math.max(p1[1], p2[1], p3[1], p4[1])
+    ];
+  };
+
+  Util.inverseTransform = function Util_inverseTransform(m) {
+    var d = m[0] * m[3] - m[1] * m[2];
+    return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d,
+      (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
+  };
+
+  // Apply a generic 3d matrix M on a 3-vector v:
+  //   | a b c |   | X |
+  //   | d e f | x | Y |
+  //   | g h i |   | Z |
+  // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
+  // with v as [X,Y,Z]
+  Util.apply3dTransform = function Util_apply3dTransform(m, v) {
+    return [
+      m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
+      m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
+      m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
+    ];
+  };
+
+  // This calculation uses Singular Value Decomposition.
+  // The SVD can be represented with formula A = USV. We are interested in the
+  // matrix S here because it represents the scale values.
+  Util.singularValueDecompose2dScale =
+    function Util_singularValueDecompose2dScale(m) {
+
+    var transpose = [m[0], m[2], m[1], m[3]];
+
+    // Multiply matrix m with its transpose.
+    var a = m[0] * transpose[0] + m[1] * transpose[2];
+    var b = m[0] * transpose[1] + m[1] * transpose[3];
+    var c = m[2] * transpose[0] + m[3] * transpose[2];
+    var d = m[2] * transpose[1] + m[3] * transpose[3];
+
+    // Solve the second degree polynomial to get roots.
+    var first = (a + d) / 2;
+    var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
+    var sx = first + second || 1;
+    var sy = first - second || 1;
+
+    // Scale values are the square roots of the eigenvalues.
+    return [Math.sqrt(sx), Math.sqrt(sy)];
+  };
+
+  // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
+  // For coordinate systems whose origin lies in the bottom-left, this
+  // means normalization to (BL,TR) ordering. For systems with origin in the
+  // top-left, this means (TL,BR) ordering.
+  Util.normalizeRect = function Util_normalizeRect(rect) {
+    var r = rect.slice(0); // clone rect
+    if (rect[0] > rect[2]) {
+      r[0] = rect[2];
+      r[2] = rect[0];
+    }
+    if (rect[1] > rect[3]) {
+      r[1] = rect[3];
+      r[3] = rect[1];
+    }
+    return r;
+  };
+
+  // Returns a rectangle [x1, y1, x2, y2] corresponding to the
+  // intersection of rect1 and rect2. If no intersection, returns 'false'
+  // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
+  Util.intersect = function Util_intersect(rect1, rect2) {
+    function compare(a, b) {
+      return a - b;
+    }
+
+    // Order points along the axes
+    var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
+        orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
+        result = [];
+
+    rect1 = Util.normalizeRect(rect1);
+    rect2 = Util.normalizeRect(rect2);
+
+    // X: first and second points belong to different rectangles?
+    if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) ||
+        (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) {
+      // Intersection must be between second and third points
+      result[0] = orderedX[1];
+      result[2] = orderedX[2];
+    } else {
+      return false;
+    }
+
+    // Y: first and second points belong to different rectangles?
+    if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) ||
+        (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) {
+      // Intersection must be between second and third points
+      result[1] = orderedY[1];
+      result[3] = orderedY[2];
+    } else {
+      return false;
+    }
+
+    return result;
+  };
+
+  Util.sign = function Util_sign(num) {
+    return num < 0 ? -1 : 1;
+  };
+
+  // TODO(mack): Rename appendToArray
+  Util.concatenateToArray = function concatenateToArray(arr1, arr2) {
+    Array.prototype.push.apply(arr1, arr2);
+  };
+
+  Util.prependToArray = function concatenateToArray(arr1, arr2) {
+    Array.prototype.unshift.apply(arr1, arr2);
+  };
+
+  Util.extendObj = function extendObj(obj1, obj2) {
+    for (var key in obj2) {
+      obj1[key] = obj2[key];
+    }
+  };
+
+  Util.getInheritableProperty = function Util_getInheritableProperty(dict,
+                                                                     name) {
+    while (dict && !dict.has(name)) {
+      dict = dict.get('Parent');
+    }
+    if (!dict) {
+      return null;
+    }
+    return dict.get(name);
+  };
+
+  Util.inherit = function Util_inherit(sub, base, prototype) {
+    sub.prototype = Object.create(base.prototype);
+    sub.prototype.constructor = sub;
+    for (var prop in prototype) {
+      sub.prototype[prop] = prototype[prop];
+    }
+  };
+
+  Util.loadScript = function Util_loadScript(src, callback) {
+    var script = document.createElement('script');
+    var loaded = false;
+    script.setAttribute('src', src);
+    if (callback) {
+      script.onload = function() {
+        if (!loaded) {
+          callback();
+        }
+        loaded = true;
+      };
+    }
+    document.getElementsByTagName('head')[0].appendChild(script);
+  };
+
+  return Util;
+})();
+
+var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
+  function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) {
+    this.viewBox = viewBox;
+    this.scale = scale;
+    this.rotation = rotation;
+    this.offsetX = offsetX;
+    this.offsetY = offsetY;
+
+    // creating transform to convert pdf coordinate system to the normal
+    // canvas like coordinates taking in account scale and rotation
+    var centerX = (viewBox[2] + viewBox[0]) / 2;
+    var centerY = (viewBox[3] + viewBox[1]) / 2;
+    var rotateA, rotateB, rotateC, rotateD;
+    rotation = rotation % 360;
+    rotation = rotation < 0 ? rotation + 360 : rotation;
+    switch (rotation) {
+      case 180:
+        rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
+        break;
+      case 90:
+        rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
+        break;
+      case 270:
+        rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
+        break;
+      //case 0:
+      default:
+        rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
+        break;
+    }
+
+    if (dontFlip) {
+      rotateC = -rotateC; rotateD = -rotateD;
+    }
+
+    var offsetCanvasX, offsetCanvasY;
+    var width, height;
+    if (rotateA === 0) {
+      offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
+      offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
+      width = Math.abs(viewBox[3] - viewBox[1]) * scale;
+      height = Math.abs(viewBox[2] - viewBox[0]) * scale;
+    } else {
+      offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
+      offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
+      width = Math.abs(viewBox[2] - viewBox[0]) * scale;
+      height = Math.abs(viewBox[3] - viewBox[1]) * scale;
+    }
+    // creating transform for the following operations:
+    // translate(-centerX, -centerY), rotate and flip vertically,
+    // scale, and translate(offsetCanvasX, offsetCanvasY)
+    this.transform = [
+      rotateA * scale,
+      rotateB * scale,
+      rotateC * scale,
+      rotateD * scale,
+      offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
+      offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
+    ];
+
+    this.width = width;
+    this.height = height;
+    this.fontScale = scale;
+  }
+  PageViewport.prototype = {
+    clone: function PageViewPort_clone(args) {
+      args = args || {};
+      var scale = 'scale' in args ? args.scale : this.scale;
+      var rotation = 'rotation' in args ? args.rotation : this.rotation;
+      return new PageViewport(this.viewBox.slice(), scale, rotation,
+                              this.offsetX, this.offsetY, args.dontFlip);
+    },
+    convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
+      return Util.applyTransform([x, y], this.transform);
+    },
+    convertToViewportRectangle:
+      function PageViewport_convertToViewportRectangle(rect) {
+      var tl = Util.applyTransform([rect[0], rect[1]], this.transform);
+      var br = Util.applyTransform([rect[2], rect[3]], this.transform);
+      return [tl[0], tl[1], br[0], br[1]];
+    },
+    convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
+      return Util.applyInverseTransform([x, y], this.transform);
+    }
+  };
+  return PageViewport;
+})();
+
+var PDFStringTranslateTable = [
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014,
+  0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C,
+  0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160,
+  0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC
+];
+
+function stringToPDFString(str) {
+  var i, n = str.length, str2 = '';
+  if (str[0] === '\xFE' && str[1] === '\xFF') {
+    // UTF16BE BOM
+    for (i = 2; i < n; i += 2)
+      str2 += String.fromCharCode(
+        (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1));
+  } else {
+    for (i = 0; i < n; ++i) {
+      var code = PDFStringTranslateTable[str.charCodeAt(i)];
+      str2 += code ? String.fromCharCode(code) : str.charAt(i);
+    }
+  }
+  return str2;
+}
+
+function stringToUTF8String(str) {
+  return decodeURIComponent(escape(str));
+}
+
+function isEmptyObj(obj) {
+  for (var key in obj) {
+    return false;
+  }
+  return true;
+}
+
+function isBool(v) {
+  return typeof v == 'boolean';
+}
+
+function isInt(v) {
+  return typeof v == 'number' && ((v | 0) == v);
+}
+
+function isNum(v) {
+  return typeof v == 'number';
+}
+
+function isString(v) {
+  return typeof v == 'string';
+}
+
+function isNull(v) {
+  return v === null;
+}
+
+function isName(v) {
+  return v instanceof Name;
+}
+
+function isCmd(v, cmd) {
+  return v instanceof Cmd && (!cmd || v.cmd == cmd);
+}
+
+function isDict(v, type) {
+  if (!(v instanceof Dict)) {
+    return false;
+  }
+  if (!type) {
+    return true;
+  }
+  var dictType = v.get('Type');
+  return isName(dictType) && dictType.name == type;
+}
+
+function isArray(v) {
+  return v instanceof Array;
+}
+
+function isStream(v) {
+  return typeof v == 'object' && v !== null && v !== undefined &&
+         ('getBytes' in v);
+}
+
+function isArrayBuffer(v) {
+  return typeof v == 'object' && v !== null && v !== undefined &&
+         ('byteLength' in v);
+}
+
+function isRef(v) {
+  return v instanceof Ref;
+}
+
+function isPDFFunction(v) {
+  var fnDict;
+  if (typeof v != 'object')
+    return false;
+  else if (isDict(v))
+    fnDict = v;
+  else if (isStream(v))
+    fnDict = v.dict;
+  else
+    return false;
+  return fnDict.has('FunctionType');
+}
+
+/**
+ * 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;
+  }
+  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() {
+      var RUN_TIMEOUT = 1; // ms
+      var timeoutAt = Date.now() + RUN_TIMEOUT;
+      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);
+        if (Date.now() >= timeoutAt) {
+          break;
+        }
+      }
+
+      if (this.handlers.length > 0) {
+        setTimeout(this.runHandlers.bind(this), 0);
+        return;
+      }
+
+      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(resolver) {
+    this._status = STATUS_PENDING;
+    this._handlers = [];
+    resolver.call(this, this._resolve.bind(this), this._reject.bind(this));
+  }
+  /**
+   * 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 resolveAll, rejectAll;
+    var deferred = new Promise(function (resolve, reject) {
+      resolveAll = resolve;
+      rejectAll = reject;
+    });
+    var unresolved = promises.length;
+    var results = [];
+    if (unresolved === 0) {
+      resolveAll(results);
+      return deferred;
+    }
+    function reject(reason) {
+      if (deferred._status === STATUS_REJECTED) {
+        return;
+      }
+      results = [];
+      rejectAll(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)
+            resolveAll(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';
+  };
+  /**
+   * Creates resolved promise
+   * @param x resolve value
+   * @returns {Promise}
+   */
+  Promise.resolve = function Promise_resolve(x) {
+    return new Promise(function (resolve) { resolve(x); });
+  };
+
+  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);
+    },
+
+    _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(function (resolve, reject) {
+        this.resolve = reject;
+        this.reject = reject;
+      });
+      this._handlers.push({
+        thisPromise: this,
+        onResolve: onResolve,
+        onReject: onReject,
+        nextPromise: nextPromise
+      });
+      HandlerManager.scheduleHandlers(this);
+      return nextPromise;
+    }
+  };
+
+  globalScope.Promise = Promise;
+})();
+
+var StatTimer = (function StatTimerClosure() {
+  function rpad(str, pad, length) {
+    while (str.length < length)
+      str += pad;
+    return str;
+  }
+  function StatTimer() {
+    this.started = {};
+    this.times = [];
+    this.enabled = true;
+  }
+  StatTimer.prototype = {
+    time: function StatTimer_time(name) {
+      if (!this.enabled)
+        return;
+      if (name in this.started)
+        warn('Timer is already running for ' + name);
+      this.started[name] = Date.now();
+    },
+    timeEnd: function StatTimer_timeEnd(name) {
+      if (!this.enabled)
+        return;
+      if (!(name in this.started))
+        warn('Timer has not been started for ' + name);
+      this.times.push({
+        'name': name,
+        'start': this.started[name],
+        'end': Date.now()
+      });
+      // Remove timer from started so it can be called again.
+      delete this.started[name];
+    },
+    toString: function StatTimer_toString() {
+      var times = this.times;
+      var out = '';
+      // Find the longest name for padding purposes.
+      var longest = 0;
+      for (var i = 0, ii = times.length; i < ii; ++i) {
+        var name = times[i]['name'];
+        if (name.length > longest)
+          longest = name.length;
+      }
+      for (var i = 0, ii = times.length; i < ii; ++i) {
+        var span = times[i];
+        var duration = span.end - span.start;
+        out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
+      }
+      return out;
+    }
+  };
+  return StatTimer;
+})();
+
+PDFJS.createBlob = function createBlob(data, contentType) {
+  if (typeof Blob !== 'undefined')
+    return new Blob([data], { type: contentType });
+  // Blob builder is deprecated in FF14 and removed in FF18.
+  var bb = new MozBlobBuilder();
+  bb.append(data);
+  return bb.getBlob(contentType);
+};
+
+PDFJS.createObjectURL = (function createObjectURLClosure() {
+  // 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;
+      buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
+    }
+    return buffer;
+  };
+})();
+
+function MessageHandler(name, comObj) {
+  this.name = name;
+  this.comObj = comObj;
+  this.callbackIndex = 1;
+  this.postMessageTransfers = true;
+  var callbacks = this.callbacks = {};
+  var ah = this.actionHandler = {};
+
+  ah['console_log'] = [function ahConsoleLog(data) {
+    console.log.apply(console, data);
+  }];
+  ah['console_error'] = [function ahConsoleError(data) {
+    console.error.apply(console, data);
+  }];
+  ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) {
+    UnsupportedManager.notify(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;
+        promise.then(function(resolvedData) {
+          comObj.postMessage({
+            isReply: true,
+            callbackId: data.callbackId,
+            data: resolvedData
+          });
+        });
+        action[0].call(action[1], data.data, deferred);
+      } else {
+        action[0].call(action[1], data.data);
+      }
+    } else {
+      error('Unkown action from worker: ' + data.action);
+    }
+  };
+}
+
+MessageHandler.prototype = {
+  on: function messageHandlerOn(actionName, handler, scope) {
+    var ah = this.actionHandler;
+    if (ah[actionName]) {
+      error('There is already an actionName called "' + actionName + '"');
+    }
+    ah[actionName] = [handler, scope];
+  },
+  /**
+   * Sends a message to the comObj to invoke the action with the supplied data.
+   * @param {String} actionName Action to call.
+   * @param {JSON} data JSON data to send.
+   * @param {function} [callback] Optional callback that will handle a reply.
+   * @param {Array} [transfers] Optional list of transfers/ArrayBuffers
+   */
+  send: function messageHandlerSend(actionName, data, callback, transfers) {
+    var message = {
+      action: actionName,
+      data: data
+    };
+    if (callback) {
+      var callbackId = this.callbackIndex++;
+      this.callbacks[callbackId] = callback;
+      message.callbackId = callbackId;
+    }
+    if (transfers && this.postMessageTransfers) {
+      this.comObj.postMessage(message, transfers);
+    } else {
+      this.comObj.postMessage(message);
+    }
+  }
+};
+
+function loadJpegStream(id, imageUrl, objs) {
+  var img = new Image();
+  img.onload = (function loadJpegStream_onloadClosure() {
+    objs.resolve(id, img);
+  });
+  img.src = imageUrl;
+}
+
+
+var ColorSpace = (function ColorSpaceClosure() {
+  // Constructor should define this.numComps, this.defaultColor, this.name
+  function ColorSpace() {
+    error('should not call ColorSpace constructor');
+  }
+
+  ColorSpace.prototype = {
+    /**
+     * Converts the color value to the RGB color. The color components are
+     * located in the src array starting from the srcOffset. Returns the array
+     * of the rgb components, each value ranging from [0,255].
+     */
+    getRgb: function ColorSpace_getRgb(src, srcOffset) {
+      error('Should not call ColorSpace.getRgb');
+    },
+    /**
+     * Converts the color value to the RGB color, similar to the getRgb method.
+     * The result placed into the dest array starting from the destOffset.
+     */
+    getRgbItem: function ColorSpace_getRgb(src, srcOffset, dest, destOffset) {
+      error('Should not call ColorSpace.getRgbItem');
+    },
+    /**
+     * Converts the specified number of the color values to the RGB colors.
+     * The colors are located in the src array starting from the srcOffset.
+     * The result is placed into the dest array starting from the destOffset.
+     * The src array items shall be in [0,2^bits) range, the dest array items
+     * will be in [0,255] range.
+     */
+    getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count,
+                                                   dest, destOffset, bits) {
+      error('Should not call ColorSpace.getRgbBuffer');
+    },
+    /**
+     * Determines amount of the bytes is required to store the reslut of the
+     * conversion that done by the getRgbBuffer method.
+     */
+    getOutputLength: function ColorSpace_getOutputLength(inputLength) {
+      error('Should not call ColorSpace.getOutputLength');
+    },
+    /**
+     * Returns true if source data will be equal the result/output data.
+     */
+    isPassthrough: function ColorSpace_isPassthrough(bits) {
+      return false;
+    },
+    /**
+     * Creates the output buffer and converts the specified number of the color
+     * values to the RGB colors, similar to the getRgbBuffer.
+     */
+    createRgbBuffer: function ColorSpace_createRgbBuffer(src, srcOffset,
+                                                         count, bits) {
+      if (this.isPassthrough(bits)) {
+        return src.subarray(srcOffset);
+      }
+      var dest = new Uint8Array(count * 3);
+      var numComponentColors = 1 << bits;
+      // Optimization: create a color map when there is just one component and
+      // we are converting more colors than the size of the color map. We
+      // don't build the map if the colorspace is gray or rgb since those
+      // methods are faster than building a map. This mainly offers big speed
+      // ups for indexed and alternate colorspaces.
+      if (this.numComps === 1 && count > numComponentColors &&
+          this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') {
+        // TODO it may be worth while to cache the color map. While running
+        // testing I never hit a cache so I will leave that out for now (perhaps
+        // we are reparsing colorspaces too much?).
+        var allColors = bits <= 8 ? new Uint8Array(numComponentColors) :
+                                    new Uint16Array(numComponentColors);
+        for (var i = 0; i < numComponentColors; i++) {
+          allColors[i] = i;
+        }
+        var colorMap = new Uint8Array(numComponentColors * 3);
+        this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bits);
+
+        var destOffset = 0;
+        for (var i = 0; i < count; ++i) {
+          var key = src[srcOffset++] * 3;
+          dest[destOffset++] = colorMap[key];
+          dest[destOffset++] = colorMap[key + 1];
+          dest[destOffset++] = colorMap[key + 2];
+        }
+        return dest;
+      }
+      this.getRgbBuffer(src, srcOffset, count, dest, 0, bits);
+      return dest;
+    },
+    /**
+     * True if the colorspace has components in the default range of [0, 1].
+     * This should be true for all colorspaces except for lab color spaces
+     * which are [0,100], [-128, 127], [-128, 127].
+     */
+    usesZeroToOneRange: true
+  };
+
+  ColorSpace.parse = function ColorSpace_parse(cs, xref, res) {
+    var IR = ColorSpace.parseToIR(cs, xref, res);
+    if (IR instanceof AlternateCS)
+      return IR;
+
+    return ColorSpace.fromIR(IR);
+  };
+
+  ColorSpace.fromIR = function ColorSpace_fromIR(IR) {
+    var name = isArray(IR) ? IR[0] : IR;
+
+    switch (name) {
+      case 'DeviceGrayCS':
+        return this.singletons.gray;
+      case 'DeviceRgbCS':
+        return this.singletons.rgb;
+      case 'DeviceCmykCS':
+        return this.singletons.cmyk;
+      case 'CalGrayCS':
+        var whitePoint = IR[1].WhitePoint;
+        var blackPoint = IR[1].BlackPoint;
+        var gamma = IR[1].Gamma;
+        return new CalGrayCS(whitePoint, blackPoint, gamma);
+      case 'PatternCS':
+        var basePatternCS = IR[1];
+        if (basePatternCS)
+          basePatternCS = ColorSpace.fromIR(basePatternCS);
+        return new PatternCS(basePatternCS);
+      case 'IndexedCS':
+        var baseIndexedCS = IR[1];
+        var hiVal = IR[2];
+        var lookup = IR[3];
+        return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup);
+      case 'AlternateCS':
+        var numComps = IR[1];
+        var alt = IR[2];
+        var tintFnIR = IR[3];
+
+        return new AlternateCS(numComps, ColorSpace.fromIR(alt),
+                                PDFFunction.fromIR(tintFnIR));
+      case 'LabCS':
+        var whitePoint = IR[1].WhitePoint;
+        var blackPoint = IR[1].BlackPoint;
+        var range = IR[1].Range;
+        return new LabCS(whitePoint, blackPoint, range);
+      default:
+        error('Unkown name ' + name);
+    }
+    return null;
+  };
+
+  ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) {
+    if (isName(cs)) {
+      var colorSpaces = res.get('ColorSpace');
+      if (isDict(colorSpaces)) {
+        var refcs = colorSpaces.get(cs.name);
+        if (refcs)
+          cs = refcs;
+      }
+    }
+
+    cs = xref.fetchIfRef(cs);
+    var mode;
+
+    if (isName(cs)) {
+      mode = cs.name;
+      this.mode = mode;
+
+      switch (mode) {
+        case 'DeviceGray':
+        case 'G':
+          return 'DeviceGrayCS';
+        case 'DeviceRGB':
+        case 'RGB':
+          return 'DeviceRgbCS';
+        case 'DeviceCMYK':
+        case 'CMYK':
+          return 'DeviceCmykCS';
+        case 'Pattern':
+          return ['PatternCS', null];
+        default:
+          error('unrecognized colorspace ' + mode);
+      }
+    } else if (isArray(cs)) {
+      mode = cs[0].name;
+      this.mode = mode;
+
+      switch (mode) {
+        case 'DeviceGray':
+        case 'G':
+          return 'DeviceGrayCS';
+        case 'DeviceRGB':
+        case 'RGB':
+          return 'DeviceRgbCS';
+        case 'DeviceCMYK':
+        case 'CMYK':
+          return 'DeviceCmykCS';
+        case 'CalGray':
+          var params = cs[1].getAll();
+          return ['CalGrayCS', params];
+        case 'CalRGB':
+          return 'DeviceRgbCS';
+        case 'ICCBased':
+          var stream = xref.fetchIfRef(cs[1]);
+          var dict = stream.dict;
+          var numComps = dict.get('N');
+          if (numComps == 1)
+            return 'DeviceGrayCS';
+          if (numComps == 3)
+            return 'DeviceRgbCS';
+          if (numComps == 4)
+            return 'DeviceCmykCS';
+          break;
+        case 'Pattern':
+          var basePatternCS = cs[1];
+          if (basePatternCS)
+            basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
+          return ['PatternCS', basePatternCS];
+        case 'Indexed':
+        case 'I':
+          var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
+          var hiVal = cs[2] + 1;
+          var lookup = xref.fetchIfRef(cs[3]);
+          if (isStream(lookup)) {
+            lookup = lookup.getBytes();
+          }
+          return ['IndexedCS', baseIndexedCS, hiVal, lookup];
+        case 'Separation':
+        case 'DeviceN':
+          var name = cs[1];
+          var numComps = 1;
+          if (isName(name))
+            numComps = 1;
+          else if (isArray(name))
+            numComps = name.length;
+          var alt = ColorSpace.parseToIR(cs[2], xref, res);
+          var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3]));
+          return ['AlternateCS', numComps, alt, tintFnIR];
+        case 'Lab':
+          var params = cs[1].getAll();
+          return ['LabCS', params];
+        default:
+          error('unimplemented color space object "' + mode + '"');
+      }
+    } else {
+      error('unrecognized color space object: "' + cs + '"');
+    }
+    return null;
+  };
+  /**
+   * Checks if a decode map matches the default decode map for a color space.
+   * This handles the general decode maps where there are two values per
+   * component. e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
+   * This does not handle Lab, Indexed, or Pattern decode maps since they are
+   * slightly different.
+   * @param {Array} decode Decode map (usually from an image).
+   * @param {Number} n Number of components the color space has.
+   */
+  ColorSpace.isDefaultDecode = function ColorSpace_isDefaultDecode(decode, n) {
+    if (!decode)
+      return true;
+
+    if (n * 2 !== decode.length) {
+      warn('The decode map is not the correct length');
+      return true;
+    }
+    for (var i = 0, ii = decode.length; i < ii; i += 2) {
+      if (decode[i] !== 0 || decode[i + 1] != 1)
+        return false;
+    }
+    return true;
+  };
+
+  ColorSpace.singletons = {
+    get gray() {
+      return shadow(this, 'gray', new DeviceGrayCS());
+    },
+    get rgb() {
+      return shadow(this, 'rgb', new DeviceRgbCS());
+    },
+    get cmyk() {
+      return shadow(this, 'cmyk', new DeviceCmykCS());
+    }
+  };
+
+  return ColorSpace;
+})();
+
+/**
+ * Alternate color space handles both Separation and DeviceN color spaces.  A
+ * Separation color space is actually just a DeviceN with one color component.
+ * Both color spaces use a tinting function to convert colors to a base color
+ * space.
+ */
+var AlternateCS = (function AlternateCSClosure() {
+  function AlternateCS(numComps, base, tintFn) {
+    this.name = 'Alternate';
+    this.numComps = numComps;
+    this.defaultColor = new Float32Array(numComps);
+    for (var i = 0; i < numComps; ++i) {
+      this.defaultColor[i] = 1;
+    }
+    this.base = base;
+    this.tintFn = tintFn;
+  }
+
+  AlternateCS.prototype = {
+    getRgb: function AlternateCS_getRgb(src, srcOffset) {
+      var rgb = new Uint8Array(3);
+      this.getRgbItem(src, srcOffset, rgb, 0);
+      return rgb;
+    },
+    getRgbItem: function AlternateCS_getRgbItem(src, srcOffset,
+                                                dest, destOffset) {
+      var baseNumComps = this.base.numComps;
+      var input = 'subarray' in src ?
+        src.subarray(srcOffset, srcOffset + this.numComps) :
+        Array.prototype.slice.call(src, srcOffset, srcOffset + this.numComps);
+      var tinted = this.tintFn(input);
+      this.base.getRgbItem(tinted, 0, dest, destOffset);
+    },
+    getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count,
+                                                    dest, destOffset, bits) {
+      var tintFn = this.tintFn;
+      var base = this.base;
+      var scale = 1 / ((1 << bits) - 1);
+      var baseNumComps = base.numComps;
+      var usesZeroToOneRange = base.usesZeroToOneRange;
+      var isPassthrough = base.isPassthrough(8) || !usesZeroToOneRange;
+      var pos = isPassthrough ? destOffset : 0;
+      var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count);
+      var numComps = this.numComps;
+
+      var scaled = new Float32Array(numComps);
+      for (var i = 0; i < count; i++) {
+        for (var j = 0; j < numComps; j++) {
+          scaled[j] = src[srcOffset++] * scale;
+        }
+        var tinted = tintFn(scaled);
+        if (usesZeroToOneRange) {
+          for (var j = 0; j < baseNumComps; j++) {
+            baseBuf[pos++] = tinted[j] * 255;
+          }
+        } else {
+          base.getRgbItem(tinted, 0, baseBuf, pos);
+          pos += baseNumComps;
+        }
+      }
+      if (!isPassthrough) {
+        base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8);
+      }
+    },
+    getOutputLength: function AlternateCS_getOutputLength(inputLength) {
+      return this.base.getOutputLength(inputLength *
+                                       this.base.numComps / this.numComps);
+    },
+    isPassthrough: ColorSpace.prototype.isPassthrough,
+    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
+    isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
+    },
+    usesZeroToOneRange: true
+  };
+
+  return AlternateCS;
+})();
+
+var PatternCS = (function PatternCSClosure() {
+  function PatternCS(baseCS) {
+    this.name = 'Pattern';
+    this.base = baseCS;
+  }
+  PatternCS.prototype = {};
+
+  return PatternCS;
+})();
+
+var IndexedCS = (function IndexedCSClosure() {
+  function IndexedCS(base, highVal, lookup) {
+    this.name = 'Indexed';
+    this.numComps = 1;
+    this.defaultColor = new Uint8Array([0]);
+    this.base = base;
+    this.highVal = highVal;
+
+    var baseNumComps = base.numComps;
+    var length = baseNumComps * highVal;
+    var lookupArray;
+
+    if (isStream(lookup)) {
+      lookupArray = new Uint8Array(length);
+      var bytes = lookup.getBytes(length);
+      lookupArray.set(bytes);
+    } else if (isString(lookup)) {
+      lookupArray = new Uint8Array(length);
+      for (var i = 0; i < length; ++i)
+        lookupArray[i] = lookup.charCodeAt(i);
+    } else if (lookup instanceof Uint8Array || lookup instanceof Array) {
+      lookupArray = lookup;
+    } else {
+      error('Unrecognized lookup table: ' + lookup);
+    }
+    this.lookup = lookupArray;
+  }
+
+  IndexedCS.prototype = {
+    getRgb: function IndexedCS_getRgb(src, srcOffset) {
+      var numComps = this.base.numComps;
+      var start = src[srcOffset] * numComps;
+      return this.base.getRgb(this.lookup, start);
+    },
+    getRgbItem: function IndexedCS_getRgbItem(src, srcOffset,
+                                              dest, destOffset) {
+      var numComps = this.base.numComps;
+      var start = src[srcOffset] * numComps;
+      this.base.getRgbItem(this.lookup, start, dest, destOffset);
+    },
+    getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count,
+                                                  dest, destOffset) {
+      var base = this.base;
+      var numComps = base.numComps;
+      var outputDelta = base.getOutputLength(numComps);
+      var lookup = this.lookup;
+
+      for (var i = 0; i < count; ++i) {
+        var lookupPos = src[srcOffset++] * numComps;
+        base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8);
+        destOffset += outputDelta;
+      }
+    },
+    getOutputLength: function IndexedCS_getOutputLength(inputLength) {
+      return this.base.getOutputLength(inputLength * this.base.numComps);
+    },
+    isPassthrough: ColorSpace.prototype.isPassthrough,
+    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
+    isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) {
+      // indexed color maps shouldn't be changed
+      return true;
+    },
+    usesZeroToOneRange: true
+  };
+  return IndexedCS;
+})();
+
+var DeviceGrayCS = (function DeviceGrayCSClosure() {
+  function DeviceGrayCS() {
+    this.name = 'DeviceGray';
+    this.numComps = 1;
+    this.defaultColor = new Float32Array([0]);
+  }
+
+  DeviceGrayCS.prototype = {
+    getRgb: function DeviceGrayCS_getRgb(src, srcOffset) {
+      var rgb = new Uint8Array(3);
+      this.getRgbItem(src, srcOffset, rgb, 0);
+      return rgb;
+    },
+    getRgbItem: function DeviceGrayCS_getRgbItem(src, srcOffset,
+                                                 dest, destOffset) {
+      var c = (src[srcOffset] * 255) | 0;
+      c = c < 0 ? 0 : c > 255 ? 255 : c;
+      dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c;
+    },
+    getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count,
+                                                     dest, destOffset, bits) {
+      var scale = 255 / ((1 << bits) - 1);
+      var j = srcOffset, q = destOffset;
+      for (var i = 0; i < count; ++i) {
+        var c = (scale * src[j++]) | 0;
+        dest[q++] = c;
+        dest[q++] = c;
+        dest[q++] = c;
+      }
+    },
+    getOutputLength: function DeviceGrayCS_getOutputLength(inputLength) {
+      return inputLength * 3;
+    },
+    isPassthrough: ColorSpace.prototype.isPassthrough,
+    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
+    isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
+    },
+    usesZeroToOneRange: true
+  };
+  return DeviceGrayCS;
+})();
+
+var DeviceRgbCS = (function DeviceRgbCSClosure() {
+  function DeviceRgbCS() {
+    this.name = 'DeviceRGB';
+    this.numComps = 3;
+    this.defaultColor = new Float32Array([0, 0, 0]);
+  }
+  DeviceRgbCS.prototype = {
+    getRgb: function DeviceRgbCS_getRgb(src, srcOffset) {
+      var rgb = new Uint8Array(3);
+      this.getRgbItem(src, srcOffset, rgb, 0);
+      return rgb;
+    },
+    getRgbItem: function DeviceRgbCS_getRgbItem(src, srcOffset,
+                                                dest, destOffset) {
+      var r = (src[srcOffset] * 255) | 0;
+      var g = (src[srcOffset + 1] * 255) | 0;
+      var b = (src[srcOffset + 2] * 255) | 0;
+      dest[destOffset] = r < 0 ? 0 : r > 255 ? 255 : r;
+      dest[destOffset + 1] = g < 0 ? 0 : g > 255 ? 255 : g;
+      dest[destOffset + 2] = b < 0 ? 0 : b > 255 ? 255 : b;
+    },
+    getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count,
+                                                    dest, destOffset, bits) {
+      var length = count * 3;
+      if (bits == 8) {
+        dest.set(src.subarray(srcOffset, srcOffset + length), destOffset);
+        return;
+      }
+      var scale = 255 / ((1 << bits) - 1);
+      var j = srcOffset, q = destOffset;
+      for (var i = 0; i < length; ++i) {
+        dest[q++] = (scale * src[j++]) | 0;
+      }
+    },
+    getOutputLength: function DeviceRgbCS_getOutputLength(inputLength) {
+      return inputLength;
+    },
+    isPassthrough: function DeviceRgbCS_isPassthrough(bits) {
+      return bits == 8;
+    },
+    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
+    isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
+    },
+    usesZeroToOneRange: true
+  };
+  return DeviceRgbCS;
+})();
+
+var DeviceCmykCS = (function DeviceCmykCSClosure() {
+  // The coefficients below was found using numerical analysis: the method of
+  // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
+  // where color_value is the tabular value from the table of sampled RGB colors
+  // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
+  // CMYK color conversion using the estimation below:
+  //   f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
+  function convertToRgb(src, srcOffset, srcScale, dest, destOffset) {
+    var c = src[srcOffset + 0] * srcScale;
+    var m = src[srcOffset + 1] * srcScale;
+    var y = src[srcOffset + 2] * srcScale;
+    var k = src[srcOffset + 3] * srcScale;
+
+    var r =
+      c * (-4.387332384609988 * c + 54.48615194189176 * m +
+           18.82290502165302 * y + 212.25662451639585 * k +
+           -285.2331026137004) +
+      m * (1.7149763477362134 * m - 5.6096736904047315 * y +
+           -17.873870861415444 * k - 5.497006427196366) +
+      y * (-2.5217340131683033 * y - 21.248923337353073 * k +
+           17.5119270841813) +
+      k * (-21.86122147463605 * k - 189.48180835922747) + 255;
+    var g =
+      c * (8.841041422036149 * c + 60.118027045597366 * m +
+           6.871425592049007 * y + 31.159100130055922 * k +
+           -79.2970844816548) +
+      m * (-15.310361306967817 * m + 17.575251261109482 * y +
+           131.35250912493976 * k - 190.9453302588951) +
+      y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) +
+      k * (-20.737325471181034 * k - 187.80453709719578) + 255;
+    var b =
+      c * (0.8842522430003296 * c + 8.078677503112928 * m +
+           30.89978309703729 * y - 0.23883238689178934 * k +
+           -14.183576799673286) +
+      m * (10.49593273432072 * m + 63.02378494754052 * y +
+           50.606957656360734 * k - 112.23884253719248) +
+      y * (0.03296041114873217 * y + 115.60384449646641 * k +
+           -193.58209356861505) +
+      k * (-22.33816807309886 * k - 180.12613974708367) + 255;
+
+    dest[destOffset] = r > 255 ? 255 : r < 0 ? 0 : r;
+    dest[destOffset + 1] = g > 255 ? 255 : g < 0 ? 0 : g;
+    dest[destOffset + 2] = b > 255 ? 255 : b < 0 ? 0 : b;
+  }
+
+  function DeviceCmykCS() {
+    this.name = 'DeviceCMYK';
+    this.numComps = 4;
+    this.defaultColor = new Float32Array([0, 0, 0, 1]);
+  }
+  DeviceCmykCS.prototype = {
+    getRgb: function DeviceCmykCS_getRgb(src, srcOffset) {
+      var rgb = new Uint8Array(3);
+      convertToRgb(src, srcOffset, 1, rgb, 0);
+      return rgb;
+    },
+    getRgbItem: function DeviceCmykCS_getRgbItem(src, srcOffset,
+                                                 dest, destOffset) {
+      convertToRgb(src, srcOffset, 1, dest, destOffset);
+    },
+    getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count,
+                                                     dest, destOffset, bits) {
+      var scale = 1 / ((1 << bits) - 1);
+      for (var i = 0; i < count; i++) {
+        convertToRgb(src, srcOffset, scale, dest, destOffset);
+        srcOffset += 4;
+        destOffset += 3;
+      }
+    },
+    getOutputLength: function DeviceCmykCS_getOutputLength(inputLength) {
+      return (inputLength >> 2) * 3;
+    },
+    isPassthrough: ColorSpace.prototype.isPassthrough,
+    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
+    isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
+    },
+    usesZeroToOneRange: true
+  };
+
+  return DeviceCmykCS;
+})();
+
+//
+// CalGrayCS: Based on "PDF Reference, Sixth Ed", p.245
+//
+var CalGrayCS = (function CalGrayCSClosure() {
+  function CalGrayCS(whitePoint, blackPoint, gamma) {
+    this.name = 'CalGray';
+    this.numComps = 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) {
+      var scale = 1 / ((1 << bits) - 1);
+
+      for (var i = 0; i < count; ++i) {
+        convertToRgb(this, src, srcOffset, dest, destOffset, scale);
+        srcOffset += 1;
+        destOffset += 3;
+      }
+    },
+    getOutputLength: function CalGrayCS_getOutputLength(inputLength) {
+      return inputLength * 3;
+    },
+    isPassthrough: ColorSpace.prototype.isPassthrough,
+    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
+    isDefaultDecode: function CalGrayCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
+    },
+    usesZeroToOneRange: true
+  };
+  return CalGrayCS;
+})();
+
+//
+// LabCS: Based on "PDF Reference, Sixth Ed", p.250
+//
+var LabCS = (function LabCSClosure() {
+  function LabCS(whitePoint, blackPoint, range) {
+    this.name = 'Lab';
+    this.numComps = 3;
+    this.defaultColor = new Float32Array([0, 0, 0]);
+
+    if (!whitePoint)
+      error('WhitePoint missing - required for color space Lab');
+    blackPoint = blackPoint || [0, 0, 0];
+    range = range || [-100, 100, -100, 100];
+
+    // Translate args to spec variables
+    this.XW = whitePoint[0];
+    this.YW = whitePoint[1];
+    this.ZW = whitePoint[2];
+    this.amin = range[0];
+    this.amax = range[1];
+    this.bmin = range[2];
+    this.bmax = range[3];
+
+    // These are here just for completeness - the spec doesn't offer any
+    // formulas that use BlackPoint in Lab
+    this.XB = blackPoint[0];
+    this.YB = blackPoint[1];
+    this.ZB = blackPoint[2];
+
+    // Validate vars as per spec
+    if (this.XW < 0 || this.ZW < 0 || this.YW !== 1)
+      error('Invalid WhitePoint components, no fallback available');
+
+    if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
+      info('Invalid BlackPoint, falling back to default');
+      this.XB = this.YB = this.ZB = 0;
+    }
+
+    if (this.amin > this.amax || this.bmin > this.bmax) {
+      info('Invalid Range, falling back to defaults');
+      this.amin = -100;
+      this.amax = 100;
+      this.bmin = -100;
+      this.bmax = 100;
+    }
+  }
+
+  // Function g(x) from spec
+  function fn_g(x) {
+    if (x >= 6 / 29)
+      return x * x * x;
+    else
+      return (108 / 841) * (x - 4 / 29);
+  }
+
+  function decode(value, high1, low2, high2) {
+    return low2 + (value) * (high2 - low2) / (high1);
+  }
+
+  // If decoding is needed maxVal should be 2^bits per component - 1.
+  function convertToRgb(cs, src, srcOffset, maxVal, dest, destOffset) {
+    // XXX: Lab input is in the range of [0, 100], [amin, amax], [bmin, bmax]
+    // not the usual [0, 1]. If a command like setFillColor is used the src
+    // values will already be within the correct range. However, if we are
+    // converting an image we have to map the values to the correct range given
+    // above.
+    // Ls,as,bs <---> L*,a*,b* in the spec
+    var Ls = src[srcOffset];
+    var as = src[srcOffset + 1];
+    var bs = src[srcOffset + 2];
+    if (maxVal !== false) {
+      Ls = decode(Ls, maxVal, 0, 100);
+      as = decode(as, maxVal, cs.amin, cs.amax);
+      bs = decode(bs, maxVal, cs.bmin, cs.bmax);
+    }
+
+    // Adjust limits of 'as' and 'bs'
+    as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as;
+    bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs;
+
+    // Computes intermediate variables X,Y,Z as per spec
+    var M = (Ls + 16) / 116;
+    var L = M + (as / 500);
+    var N = M - (bs / 200);
+
+    var X = cs.XW * fn_g(L);
+    var Y = cs.YW * fn_g(M);
+    var Z = cs.ZW * fn_g(N);
+
+    var r, g, b;
+    // Using different conversions for D50 and D65 white points,
+    // per http://www.color.org/srgb.pdf
+    if (cs.ZW < 1) {
+      // Assuming D50 (X=0.9642, Y=1.00, Z=0.8249)
+      r = X * 3.1339 + Y * -1.6170 + Z * -0.4906;
+      g = X * -0.9785 + Y * 1.9160 + Z * 0.0333;
+      b = X * 0.0720 + Y * -0.2290 + Z * 1.4057;
+    } else {
+      // Assuming D65 (X=0.9505, Y=1.00, Z=1.0888)
+      r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
+      g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
+      b = X * 0.0557 + Y * -0.2040 + Z * 1.0570;
+    }
+    // clamp color values to [0,1] range then convert to [0,255] range.
+    dest[destOffset] = Math.sqrt(r < 0 ? 0 : r > 1 ? 1 : r) * 255;
+    dest[destOffset + 1] = Math.sqrt(g < 0 ? 0 : g > 1 ? 1 : g) * 255;
+    dest[destOffset + 2] = Math.sqrt(b < 0 ? 0 : b > 1 ? 1 : b) * 255;
+  }
+
+  LabCS.prototype = {
+    getRgb: function LabCS_getRgb(src, srcOffset) {
+      var rgb = new Uint8Array(3);
+      convertToRgb(this, src, srcOffset, false, rgb, 0);
+      return rgb;
+    },
+    getRgbItem: function LabCS_getRgbItem(src, srcOffset, dest, destOffset) {
+      convertToRgb(this, src, srcOffset, false, dest, destOffset);
+    },
+    getRgbBuffer: function LabCS_getRgbBuffer(src, srcOffset, count,
+                                              dest, destOffset, bits) {
+      var maxVal = (1 << bits) - 1;
+      for (var i = 0; i < count; i++) {
+        convertToRgb(this, src, srcOffset, maxVal, dest, destOffset);
+        srcOffset += 3;
+        destOffset += 3;
+      }
+    },
+    getOutputLength: function LabCS_getOutputLength(inputLength) {
+      return inputLength;
+    },
+    isPassthrough: ColorSpace.prototype.isPassthrough,
+    isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) {
+      // XXX: Decoding is handled with the lab conversion because of the strange
+      // ranges that are used.
+      return true;
+    },
+    usesZeroToOneRange: false
+  };
+  return LabCS;
+})();
+
+
+
+var PatternType = {
+  AXIAL: 2,
+  RADIAL: 3
+};
+
+var Pattern = (function PatternClosure() {
+  // Constructor should define this.getPattern
+  function Pattern() {
+    error('should not call Pattern constructor');
+  }
+
+  Pattern.prototype = {
+    // Input: current Canvas context
+    // Output: the appropriate fillStyle or strokeStyle
+    getPattern: function Pattern_getPattern(ctx) {
+      error('Should not call Pattern.getStyle: ' + ctx);
+    }
+  };
+
+  Pattern.shadingFromIR = function Pattern_shadingFromIR(raw) {
+    return Shadings[raw[0]].fromIR(raw);
+  };
+
+  Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref,
+                                                       res) {
+
+    var dict = isStream(shading) ? shading.dict : shading;
+    var type = dict.get('ShadingType');
+
+    switch (type) {
+      case PatternType.AXIAL:
+      case PatternType.RADIAL:
+        // Both radial and axial shadings are handled by RadialAxial shading.
+        return new Shadings.RadialAxial(dict, matrix, xref, res);
+      default:
+        UnsupportedManager.notify(UNSUPPORTED_FEATURES.shadingPattern);
+        return new Shadings.Dummy();
+    }
+  };
+  return Pattern;
+})();
+
+var Shadings = {};
+
+// A small number to offset the first/last color stops so we can insert ones to
+// support extend.  Number.MIN_VALUE appears to be too small and breaks the
+// extend. 1e-7 works in FF but chrome seems to use an even smaller sized number
+// internally so we have to go bigger.
+Shadings.SMALL_NUMBER = 1e-2;
+
+// Radial and axial shading have very similar implementations
+// If needed, the implementations can be broken into two classes
+Shadings.RadialAxial = (function RadialAxialClosure() {
+  function RadialAxial(dict, matrix, xref, res, ctx) {
+    this.matrix = matrix;
+    this.coordsArr = dict.get('Coords');
+    this.shadingType = dict.get('ShadingType');
+    this.type = 'Pattern';
+    this.ctx = ctx;
+    var cs = dict.get('ColorSpace', 'CS');
+    cs = ColorSpace.parse(cs, xref, res);
+    this.cs = cs;
+
+    var t0 = 0.0, t1 = 1.0;
+    if (dict.has('Domain')) {
+      var domainArr = dict.get('Domain');
+      t0 = domainArr[0];
+      t1 = domainArr[1];
+    }
+
+    var extendStart = false, extendEnd = false;
+    if (dict.has('Extend')) {
+      var extendArr = dict.get('Extend');
+      extendStart = extendArr[0];
+      extendEnd = extendArr[1];
+    }
+
+    if (this.shadingType === PatternType.RADIAL &&
+       (!extendStart || !extendEnd)) {
+      // Radial gradient only currently works if either circle is fully within
+      // the other circle.
+      var x1 = this.coordsArr[0];
+      var y1 = this.coordsArr[1];
+      var r1 = this.coordsArr[2];
+      var x2 = this.coordsArr[3];
+      var y2 = this.coordsArr[4];
+      var r2 = this.coordsArr[5];
+      var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
+      if (r1 <= r2 + distance &&
+          r2 <= r1 + distance) {
+        warn('Unsupported radial gradient.');
+      }
+    }
+
+    this.extendStart = extendStart;
+    this.extendEnd = extendEnd;
+
+    var fnObj = dict.get('Function');
+    var fn;
+    if (isArray(fnObj)) {
+      var fnArray = [];
+      for (var j = 0, jj = fnObj.length; j < jj; j++) {
+        var obj = xref.fetchIfRef(fnObj[j]);
+        if (!isPDFFunction(obj)) {
+          error('Invalid function');
+        }
+        fnArray.push(PDFFunction.parse(xref, obj));
+      }
+      fn = function radialAxialColorFunction(arg) {
+        var out = [];
+        for (var i = 0, ii = fnArray.length; i < ii; i++) {
+          out.push(fnArray[i](arg)[0]);
+        }
+        return out;
+      };
+    } else {
+      if (!isPDFFunction(fnObj)) {
+        error('Invalid function');
+      }
+      fn = PDFFunction.parse(xref, fnObj);
+    }
+
+    // 10 samples seems good enough for now, but probably won't work
+    // if there are sharp color changes. Ideally, we would implement
+    // the spec faithfully and add lossless optimizations.
+    var diff = t1 - t0;
+    var step = diff / 10;
+
+    var colorStops = this.colorStops = [];
+
+    // Protect against bad domains so we don't end up in an infinte loop below.
+    if (t0 >= t1 || step <= 0) {
+      // Acrobat doesn't seem to handle these cases so we'll ignore for
+      // now.
+      info('Bad shading domain.');
+      return;
+    }
+
+    for (var i = t0; i <= t1; i += step) {
+      var rgbColor = cs.getRgb(fn([i]), 0);
+      var cssColor = Util.makeCssRgb(rgbColor);
+      colorStops.push([(i - t0) / diff, cssColor]);
+    }
+
+    var background = 'transparent';
+    if (dict.has('Background')) {
+      var rgbColor = cs.getRgb(dict.get('Background'), 0);
+      background = Util.makeCssRgb(rgbColor);
+    }
+
+    if (!extendStart) {
+      // Insert a color stop at the front and offset the first real color stop
+      // so it doesn't conflict with the one we insert.
+      colorStops.unshift([0, background]);
+      colorStops[1][0] += Shadings.SMALL_NUMBER;
+    }
+    if (!extendEnd) {
+      // Same idea as above in extendStart but for the end.
+      colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER;
+      colorStops.push([1, background]);
+    }
+
+    this.colorStops = colorStops;
+  }
+
+  RadialAxial.fromIR = function RadialAxial_fromIR(raw) {
+    var type = raw[1];
+    var colorStops = raw[2];
+    var p0 = raw[3];
+    var p1 = raw[4];
+    var r0 = raw[5];
+    var r1 = raw[6];
+    return {
+      type: 'Pattern',
+      getPattern: function RadialAxial_getPattern(ctx) {
+        var grad;
+        if (type == PatternType.AXIAL)
+          grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
+        else if (type == PatternType.RADIAL)
+          grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
+
+        for (var i = 0, ii = colorStops.length; i < ii; ++i) {
+          var c = colorStops[i];
+          grad.addColorStop(c[0], c[1]);
+        }
+        return grad;
+      }
+    };
+  };
+
+  RadialAxial.prototype = {
+    getIR: function RadialAxial_getIR() {
+      var coordsArr = this.coordsArr;
+      var type = this.shadingType;
+      if (type == PatternType.AXIAL) {
+        var p0 = [coordsArr[0], coordsArr[1]];
+        var p1 = [coordsArr[2], coordsArr[3]];
+        var r0 = null;
+        var r1 = null;
+      } else if (type == PatternType.RADIAL) {
+        var p0 = [coordsArr[0], coordsArr[1]];
+        var p1 = [coordsArr[3], coordsArr[4]];
+        var r0 = coordsArr[2];
+        var r1 = coordsArr[5];
+      } else {
+        error('getPattern type unknown: ' + type);
+      }
+
+      var matrix = this.matrix;
+      if (matrix) {
+        p0 = Util.applyTransform(p0, matrix);
+        p1 = Util.applyTransform(p1, matrix);
+      }
+
+      return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1];
+    }
+  };
+
+  return RadialAxial;
+})();
+
+Shadings.Dummy = (function DummyClosure() {
+  function Dummy() {
+    this.type = 'Pattern';
+  }
+
+  Dummy.fromIR = function Dummy_fromIR() {
+    return {
+      type: 'Pattern',
+      getPattern: function Dummy_fromIR_getPattern() {
+        return 'hotpink';
+      }
+    };
+  };
+
+  Dummy.prototype = {
+    getIR: function Dummy_getIR() {
+      return ['Dummy'];
+    }
+  };
+  return Dummy;
+})();
+
+var TilingPattern = (function TilingPatternClosure() {
+  var PaintType = {
+    COLORED: 1,
+    UNCOLORED: 2
+  };
+
+  var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough
+
+  function TilingPattern(IR, color, ctx, objs, commonObjs, baseTransform) {
+    this.name = IR[1][0].name;
+    this.operatorList = IR[2];
+    this.matrix = IR[3] || [1, 0, 0, 1, 0, 0];
+    this.bbox = IR[4];
+    this.xstep = IR[5];
+    this.ystep = IR[6];
+    this.paintType = IR[7];
+    this.tilingType = IR[8];
+    this.color = color;
+    this.objs = objs;
+    this.commonObjs = commonObjs;
+    this.baseTransform = baseTransform;
+    this.type = 'Pattern';
+    this.ctx = ctx;
+  }
+
+  TilingPattern.getIR = function TilingPattern_getIR(operatorList, dict, args) {
+    var matrix = dict.get('Matrix');
+    var bbox = dict.get('BBox');
+    var xstep = dict.get('XStep');
+    var ystep = dict.get('YStep');
+    var paintType = dict.get('PaintType');
+    var tilingType = dict.get('TilingType');
+
+    return [
+      'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep,
+      paintType, tilingType
+    ];
+  };
+
+  TilingPattern.prototype = {
+    createPatternCanvas: function TilinPattern_createPatternCanvas(owner) {
+      var operatorList = this.operatorList;
+      var bbox = this.bbox;
+      var xstep = this.xstep;
+      var ystep = this.ystep;
+      var paintType = this.paintType;
+      var tilingType = this.tilingType;
+      var color = this.color;
+      var objs = this.objs;
+      var commonObjs = this.commonObjs;
+      var ctx = this.ctx;
+
+      info('TilingType: ' + tilingType);
+
+      var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3];
+
+      var topLeft = [x0, y0];
+      // we want the canvas to be as large as the step size
+      var botRight = [x0 + xstep, y0 + ystep];
+
+      var width = botRight[0] - topLeft[0];
+      var height = botRight[1] - topLeft[1];
+
+      // Obtain scale from matrix and current transformation matrix.
+      var matrixScale = Util.singularValueDecompose2dScale(this.matrix);
+      var curMatrixScale = Util.singularValueDecompose2dScale(
+                             this.baseTransform);
+      var combinedScale = [matrixScale[0] * curMatrixScale[0],
+                           matrixScale[1] * curMatrixScale[1]];
+
+      // MAX_PATTERN_SIZE is used to avoid OOM situation.
+      // Use width and height values that are as close as possible to the end
+      // result when the pattern is used. Too low value makes the pattern look
+      // blurry. Too large value makes it look too crispy.
+      width = Math.min(Math.ceil(Math.abs(width * combinedScale[0])),
+                       MAX_PATTERN_SIZE);
+
+      height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])),
+                        MAX_PATTERN_SIZE);
+
+      var tmpCanvas = CachedCanvases.getCanvas('pattern', width, height, true);
+      var tmpCtx = tmpCanvas.context;
+      var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs);
+      graphics.groupLevel = owner.groupLevel;
+
+      this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color);
+
+      this.setScale(width, height, xstep, ystep);
+      this.transformToScale(graphics);
+
+      // transform coordinates to pattern space
+      var tmpTranslate = [1, 0, 0, 1, -topLeft[0], -topLeft[1]];
+      graphics.transform.apply(graphics, tmpTranslate);
+
+      this.clipBbox(graphics, bbox, x0, y0, x1, y1);
+
+      graphics.executeOperatorList(operatorList);
+      return tmpCanvas.canvas;
+    },
+
+    setScale: function TilingPattern_setScale(width, height, xstep, ystep) {
+      this.scale = [width / xstep, height / ystep];
+    },
+
+    transformToScale: function TilingPattern_transformToScale(graphics) {
+      var scale = this.scale;
+      var tmpScale = [scale[0], 0, 0, scale[1], 0, 0];
+      graphics.transform.apply(graphics, tmpScale);
+    },
+
+    scaleToContext: function TilingPattern_scaleToContext() {
+      var scale = this.scale;
+      this.ctx.scale(1 / scale[0], 1 / scale[1]);
+    },
+
+    clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
+      if (bbox && isArray(bbox) && 4 == bbox.length) {
+        var bboxWidth = x1 - x0;
+        var bboxHeight = y1 - y0;
+        graphics.rectangle(x0, y0, bboxWidth, bboxHeight);
+        graphics.clip();
+        graphics.endPath();
+      }
+    },
+
+    setFillAndStrokeStyleToContext:
+      function setFillAndStrokeStyleToContext(context, paintType, color) {
+      switch (paintType) {
+        case PaintType.COLORED:
+          var ctx = this.ctx;
+          context.fillStyle = ctx.fillStyle;
+          context.strokeStyle = ctx.strokeStyle;
+          break;
+        case PaintType.UNCOLORED:
+          var rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0);
+          var cssColor = Util.makeCssRgb(rgbColor);
+          context.fillStyle = cssColor;
+          context.strokeStyle = cssColor;
+          break;
+        default:
+          error('Unsupported paint type: ' + paintType);
+      }
+    },
+
+    getPattern: function TilingPattern_getPattern(ctx, owner) {
+      var temporaryPatternCanvas = this.createPatternCanvas(owner);
+
+      var ctx = this.ctx;
+      ctx.setTransform.apply(ctx, this.baseTransform);
+      ctx.transform.apply(ctx, this.matrix);
+      this.scaleToContext();
+
+      return ctx.createPattern(temporaryPatternCanvas, 'repeat');
+    }
+  };
+
+  return TilingPattern;
+})();
+
+
+
+var PDFFunction = (function PDFFunctionClosure() {
+  var CONSTRUCT_SAMPLED = 0;
+  var CONSTRUCT_INTERPOLATED = 2;
+  var CONSTRUCT_STICHED = 3;
+  var CONSTRUCT_POSTSCRIPT = 4;
+
+  return {
+    getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps,
+                                                       str) {
+      var length = 1;
+      for (var i = 0, ii = size.length; i < ii; i++)
+        length *= size[i];
+      length *= outputSize;
+
+      var array = [];
+      var codeSize = 0;
+      var codeBuf = 0;
+      // 32 is a valid bps so shifting won't work
+      var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1);
+
+      var strBytes = str.getBytes((length * bps + 7) / 8);
+      var strIdx = 0;
+      for (var i = 0; i < length; i++) {
+        while (codeSize < bps) {
+          codeBuf <<= 8;
+          codeBuf |= strBytes[strIdx++];
+          codeSize += 8;
+        }
+        codeSize -= bps;
+        array.push((codeBuf >> codeSize) * sampleMul);
+        codeBuf &= (1 << codeSize) - 1;
+      }
+      return array;
+    },
+
+    getIR: function PDFFunction_getIR(xref, fn) {
+      var dict = fn.dict;
+      if (!dict)
+        dict = fn;
+
+      var types = [this.constructSampled,
+                   null,
+                   this.constructInterpolated,
+                   this.constructStiched,
+                   this.constructPostScript];
+
+      var typeNum = dict.get('FunctionType');
+      var typeFn = types[typeNum];
+      if (!typeFn)
+        error('Unknown type of function');
+
+      return typeFn.call(this, fn, dict, xref);
+    },
+
+    fromIR: function PDFFunction_fromIR(IR) {
+      var type = IR[0];
+      switch (type) {
+        case CONSTRUCT_SAMPLED:
+          return this.constructSampledFromIR(IR);
+        case CONSTRUCT_INTERPOLATED:
+          return this.constructInterpolatedFromIR(IR);
+        case CONSTRUCT_STICHED:
+          return this.constructStichedFromIR(IR);
+        //case CONSTRUCT_POSTSCRIPT:
+        default:
+          return this.constructPostScriptFromIR(IR);
+      }
+    },
+
+    parse: function PDFFunction_parse(xref, fn) {
+      var IR = this.getIR(xref, fn);
+      return this.fromIR(IR);
+    },
+
+    constructSampled: function PDFFunction_constructSampled(str, dict) {
+      function toMultiArray(arr) {
+        var inputLength = arr.length;
+        var outputLength = arr.length / 2;
+        var out = [];
+        var index = 0;
+        for (var i = 0; i < inputLength; i += 2) {
+          out[index] = [arr[i], arr[i + 1]];
+          ++index;
+        }
+        return out;
+      }
+      var domain = dict.get('Domain');
+      var range = dict.get('Range');
+
+      if (!domain || !range)
+        error('No domain or range');
+
+      var inputSize = domain.length / 2;
+      var outputSize = range.length / 2;
+
+      domain = toMultiArray(domain);
+      range = toMultiArray(range);
+
+      var size = dict.get('Size');
+      var bps = dict.get('BitsPerSample');
+      var order = dict.get('Order') || 1;
+      if (order !== 1) {
+        // No description how cubic spline interpolation works in PDF32000:2008
+        // As in poppler, ignoring order, linear interpolation may work as good
+        info('No support for cubic spline interpolation: ' + order);
+      }
+
+      var encode = dict.get('Encode');
+      if (!encode) {
+        encode = [];
+        for (var i = 0; i < inputSize; ++i) {
+          encode.push(0);
+          encode.push(size[i] - 1);
+        }
+      }
+      encode = toMultiArray(encode);
+
+      var decode = dict.get('Decode');
+      if (!decode)
+        decode = range;
+      else
+        decode = toMultiArray(decode);
+
+      var samples = this.getSampleArray(size, outputSize, bps, str);
+
+      return [
+        CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size,
+        outputSize, Math.pow(2, bps) - 1, range
+      ];
+    },
+
+    constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) {
+      // See chapter 3, page 109 of the PDF reference
+      function interpolate(x, xmin, xmax, ymin, ymax) {
+        return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin)));
+      }
+
+      return function constructSampledFromIRResult(args) {
+        // See chapter 3, page 110 of the PDF reference.
+        var m = IR[1];
+        var domain = IR[2];
+        var encode = IR[3];
+        var decode = IR[4];
+        var samples = IR[5];
+        var size = IR[6];
+        var n = IR[7];
+        var mask = IR[8];
+        var range = IR[9];
+
+        if (m != args.length)
+          error('Incorrect number of arguments: ' + m + ' != ' +
+                args.length);
+
+        var x = args;
+
+        // Building the cube vertices: its part and sample index
+        // http://rjwagner49.com/Mathematics/Interpolation.pdf
+        var cubeVertices = 1 << m;
+        var cubeN = new Float64Array(cubeVertices);
+        var cubeVertex = new Uint32Array(cubeVertices);
+        for (var j = 0; j < cubeVertices; j++)
+          cubeN[j] = 1;
+
+        var k = n, pos = 1;
+        // Map x_i to y_j for 0 <= i < m using the sampled function.
+        for (var i = 0; i < m; ++i) {
+          // x_i' = min(max(x_i, Domain_2i), Domain_2i+1)
+          var domain_2i = domain[i][0];
+          var domain_2i_1 = domain[i][1];
+          var xi = Math.min(Math.max(x[i], domain_2i), domain_2i_1);
+
+          // e_i = Interpolate(x_i', Domain_2i, Domain_2i+1,
+          //                   Encode_2i, Encode_2i+1)
+          var e = interpolate(xi, domain_2i, domain_2i_1,
+                              encode[i][0], encode[i][1]);
+
+          // e_i' = min(max(e_i, 0), Size_i - 1)
+          var size_i = size[i];
+          e = Math.min(Math.max(e, 0), size_i - 1);
+
+          // Adjusting the cube: N and vertex sample index
+          var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; // e1 = e0 + 1;
+          var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
+          var n1 = e - e0; // (e - e0) / (e1 - e0);
+          var offset0 = e0 * k;
+          var offset1 = offset0 + k; // e1 * k
+          for (var j = 0; j < cubeVertices; j++) {
+            if (j & pos) {
+              cubeN[j] *= n1;
+              cubeVertex[j] += offset1;
+            } else {
+              cubeN[j] *= n0;
+              cubeVertex[j] += offset0;
+            }
+          }
+
+          k *= size_i;
+          pos <<= 1;
+        }
+
+        var y = new Float64Array(n);
+        for (var j = 0; j < n; ++j) {
+          // Sum all cube vertices' samples portions
+          var rj = 0;
+          for (var i = 0; i < cubeVertices; i++)
+            rj += samples[cubeVertex[i] + j] * cubeN[i];
+
+          // r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1,
+          //                    Decode_2j, Decode_2j+1)
+          rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
+
+          // y_j = min(max(r_j, range_2j), range_2j+1)
+          y[j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
+        }
+
+        return y;
+      };
+    },
+
+    constructInterpolated: function PDFFunction_constructInterpolated(str,
+                                                                      dict) {
+      var c0 = dict.get('C0') || [0];
+      var c1 = dict.get('C1') || [1];
+      var n = dict.get('N');
+
+      if (!isArray(c0) || !isArray(c1))
+        error('Illegal dictionary for interpolated function');
+
+      var length = c0.length;
+      var diff = [];
+      for (var i = 0; i < length; ++i)
+        diff.push(c1[i] - c0[i]);
+
+      return [CONSTRUCT_INTERPOLATED, c0, diff, n];
+    },
+
+    constructInterpolatedFromIR:
+      function PDFFunction_constructInterpolatedFromIR(IR) {
+      var c0 = IR[1];
+      var diff = IR[2];
+      var n = IR[3];
+
+      var length = diff.length;
+
+      return function constructInterpolatedFromIRResult(args) {
+        var x = n == 1 ? args[0] : Math.pow(args[0], n);
+
+        var out = [];
+        for (var j = 0; j < length; ++j)
+          out.push(c0[j] + (x * diff[j]));
+
+        return out;
+
+      };
+    },
+
+    constructStiched: function PDFFunction_constructStiched(fn, dict, xref) {
+      var domain = dict.get('Domain');
+
+      if (!domain)
+        error('No domain');
+
+      var inputSize = domain.length / 2;
+      if (inputSize != 1)
+        error('Bad domain for stiched function');
+
+      var fnRefs = dict.get('Functions');
+      var fns = [];
+      for (var i = 0, ii = fnRefs.length; i < ii; ++i)
+        fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i])));
+
+      var bounds = dict.get('Bounds');
+      var encode = dict.get('Encode');
+
+      return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
+    },
+
+    constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) {
+      var domain = IR[1];
+      var bounds = IR[2];
+      var encode = IR[3];
+      var fnsIR = IR[4];
+      var fns = [];
+
+      for (var i = 0, ii = fnsIR.length; i < ii; i++) {
+        fns.push(PDFFunction.fromIR(fnsIR[i]));
+      }
+
+      return function constructStichedFromIRResult(args) {
+        var clip = function constructStichedFromIRClip(v, min, max) {
+          if (v > max)
+            v = max;
+          else if (v < min)
+            v = min;
+          return v;
+        };
+
+        // clip to domain
+        var v = clip(args[0], domain[0], domain[1]);
+        // calulate which bound the value is in
+        for (var i = 0, ii = bounds.length; i < ii; ++i) {
+          if (v < bounds[i])
+            break;
+        }
+
+        // encode value into domain of function
+        var dmin = domain[0];
+        if (i > 0)
+          dmin = bounds[i - 1];
+        var dmax = domain[1];
+        if (i < bounds.length)
+          dmax = bounds[i];
+
+        var rmin = encode[2 * i];
+        var rmax = encode[2 * i + 1];
+
+        var v2 = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
+
+        // call the appropropriate function
+        return fns[i]([v2]);
+      };
+    },
+
+    constructPostScript: function PDFFunction_constructPostScript(fn, dict,
+                                                                  xref) {
+      var domain = dict.get('Domain');
+      var range = dict.get('Range');
+
+      if (!domain)
+        error('No domain.');
+
+      if (!range)
+        error('No range.');
+
+      var lexer = new PostScriptLexer(fn);
+      var parser = new PostScriptParser(lexer);
+      var code = parser.parse();
+
+      return [CONSTRUCT_POSTSCRIPT, domain, range, code];
+    },
+
+    constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR(
+                                          IR) {
+      var domain = IR[1];
+      var range = IR[2];
+      var code = IR[3];
+      var numOutputs = range.length / 2;
+      var evaluator = new PostScriptEvaluator(code);
+      // Cache the values for a big speed up, the cache size is limited though
+      // since the number of possible values can be huge from a PS function.
+      var cache = new FunctionCache();
+      return function constructPostScriptFromIRResult(args) {
+        var initialStack = [];
+        for (var i = 0, ii = (domain.length / 2); i < ii; ++i) {
+          initialStack.push(args[i]);
+        }
+
+        var key = initialStack.join('_');
+        if (cache.has(key))
+          return cache.get(key);
+
+        var stack = evaluator.execute(initialStack);
+        var transformed = [];
+        for (i = numOutputs - 1; i >= 0; --i) {
+          var out = stack.pop();
+          var rangeIndex = 2 * i;
+          if (out < range[rangeIndex])
+            out = range[rangeIndex];
+          else if (out > range[rangeIndex + 1])
+            out = range[rangeIndex + 1];
+          transformed[i] = out;
+        }
+        cache.set(key, transformed);
+        return transformed;
+      };
+    }
+  };
+})();
+
+var FunctionCache = (function FunctionCacheClosure() {
+  // Of 10 PDF's with type4 functions the maxium number of distinct values seen
+  // was 256. This still may need some tweaking in the future though.
+  var MAX_CACHE_SIZE = 1024;
+  function FunctionCache() {
+    this.cache = {};
+    this.total = 0;
+  }
+  FunctionCache.prototype = {
+    has: function FunctionCache_has(key) {
+      return key in this.cache;
+    },
+    get: function FunctionCache_get(key) {
+      return this.cache[key];
+    },
+    set: function FunctionCache_set(key, value) {
+      if (this.total < MAX_CACHE_SIZE) {
+        this.cache[key] = value;
+        this.total++;
+      }
+    }
+  };
+  return FunctionCache;
+})();
+
+var PostScriptStack = (function PostScriptStackClosure() {
+  var MAX_STACK_SIZE = 100;
+  function PostScriptStack(initialStack) {
+    this.stack = initialStack || [];
+  }
+
+  PostScriptStack.prototype = {
+    push: function PostScriptStack_push(value) {
+      if (this.stack.length >= MAX_STACK_SIZE)
+        error('PostScript function stack overflow.');
+      this.stack.push(value);
+    },
+    pop: function PostScriptStack_pop() {
+      if (this.stack.length <= 0)
+        error('PostScript function stack underflow.');
+      return this.stack.pop();
+    },
+    copy: function PostScriptStack_copy(n) {
+      if (this.stack.length + n >= MAX_STACK_SIZE)
+        error('PostScript function stack overflow.');
+      var stack = this.stack;
+      for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++)
+        stack.push(stack[i]);
+    },
+    index: function PostScriptStack_index(n) {
+      this.push(this.stack[this.stack.length - n - 1]);
+    },
+    // rotate the last n stack elements p times
+    roll: function PostScriptStack_roll(n, p) {
+      var stack = this.stack;
+      var l = stack.length - n;
+      var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t;
+      for (i = l, j = r; i < j; i++, j--) {
+        t = stack[i]; stack[i] = stack[j]; stack[j] = t;
+      }
+      for (i = l, j = c - 1; i < j; i++, j--) {
+        t = stack[i]; stack[i] = stack[j]; stack[j] = t;
+      }
+      for (i = c, j = r; i < j; i++, j--) {
+        t = stack[i]; stack[i] = stack[j]; stack[j] = t;
+      }
+    }
+  };
+  return PostScriptStack;
+})();
+var PostScriptEvaluator = (function PostScriptEvaluatorClosure() {
+  function PostScriptEvaluator(operators, operands) {
+    this.operators = operators;
+    this.operands = operands;
+  }
+  PostScriptEvaluator.prototype = {
+    execute: function PostScriptEvaluator_execute(initialStack) {
+      var stack = new PostScriptStack(initialStack);
+      var counter = 0;
+      var operators = this.operators;
+      var length = operators.length;
+      var operator, a, b;
+      while (counter < length) {
+        operator = operators[counter++];
+        if (typeof operator == 'number') {
+          // Operator is really an operand and should be pushed to the stack.
+          stack.push(operator);
+          continue;
+        }
+        switch (operator) {
+          // non standard ps operators
+          case 'jz': // jump if false
+            b = stack.pop();
+            a = stack.pop();
+            if (!a)
+              counter = b;
+            break;
+          case 'j': // jump
+            a = stack.pop();
+            counter = a;
+            break;
+
+          // all ps operators in alphabetical order (excluding if/ifelse)
+          case 'abs':
+            a = stack.pop();
+            stack.push(Math.abs(a));
+            break;
+          case 'add':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a + b);
+            break;
+          case 'and':
+            b = stack.pop();
+            a = stack.pop();
+            if (isBool(a) && isBool(b))
+              stack.push(a && b);
+            else
+              stack.push(a & b);
+            break;
+          case 'atan':
+            a = stack.pop();
+            stack.push(Math.atan(a));
+            break;
+          case 'bitshift':
+            b = stack.pop();
+            a = stack.pop();
+            if (a > 0)
+              stack.push(a << b);
+            else
+              stack.push(a >> b);
+            break;
+          case 'ceiling':
+            a = stack.pop();
+            stack.push(Math.ceil(a));
+            break;
+          case 'copy':
+            a = stack.pop();
+            stack.copy(a);
+            break;
+          case 'cos':
+            a = stack.pop();
+            stack.push(Math.cos(a));
+            break;
+          case 'cvi':
+            a = stack.pop() | 0;
+            stack.push(a);
+            break;
+          case 'cvr':
+            // noop
+            break;
+          case 'div':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a / b);
+            break;
+          case 'dup':
+            stack.copy(1);
+            break;
+          case 'eq':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a == b);
+            break;
+          case 'exch':
+            stack.roll(2, 1);
+            break;
+          case 'exp':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(Math.pow(a, b));
+            break;
+          case 'false':
+            stack.push(false);
+            break;
+          case 'floor':
+            a = stack.pop();
+            stack.push(Math.floor(a));
+            break;
+          case 'ge':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a >= b);
+            break;
+          case 'gt':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a > b);
+            break;
+          case 'idiv':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push((a / b) | 0);
+            break;
+          case 'index':
+            a = stack.pop();
+            stack.index(a);
+            break;
+          case 'le':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a <= b);
+            break;
+          case 'ln':
+            a = stack.pop();
+            stack.push(Math.log(a));
+            break;
+          case 'log':
+            a = stack.pop();
+            stack.push(Math.log(a) / Math.LN10);
+            break;
+          case 'lt':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a < b);
+            break;
+          case 'mod':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a % b);
+            break;
+          case 'mul':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a * b);
+            break;
+          case 'ne':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a != b);
+            break;
+          case 'neg':
+            a = stack.pop();
+            stack.push(-b);
+            break;
+          case 'not':
+            a = stack.pop();
+            if (isBool(a) && isBool(b))
+              stack.push(a && b);
+            else
+              stack.push(a & b);
+            break;
+          case 'or':
+            b = stack.pop();
+            a = stack.pop();
+            if (isBool(a) && isBool(b))
+              stack.push(a || b);
+            else
+              stack.push(a | b);
+            break;
+          case 'pop':
+            stack.pop();
+            break;
+          case 'roll':
+            b = stack.pop();
+            a = stack.pop();
+            stack.roll(a, b);
+            break;
+          case 'round':
+            a = stack.pop();
+            stack.push(Math.round(a));
+            break;
+          case 'sin':
+            a = stack.pop();
+            stack.push(Math.sin(a));
+            break;
+          case 'sqrt':
+            a = stack.pop();
+            stack.push(Math.sqrt(a));
+            break;
+          case 'sub':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a - b);
+            break;
+          case 'true':
+            stack.push(true);
+            break;
+          case 'truncate':
+            a = stack.pop();
+            a = a < 0 ? Math.ceil(a) : Math.floor(a);
+            stack.push(a);
+            break;
+          case 'xor':
+            b = stack.pop();
+            a = stack.pop();
+            if (isBool(a) && isBool(b))
+              stack.push(a != b);
+            else
+              stack.push(a ^ b);
+            break;
+          default:
+            error('Unknown operator ' + operator);
+            break;
+        }
+      }
+      return stack.stack;
+    }
+  };
+  return PostScriptEvaluator;
+})();
+
+var PostScriptParser = (function PostScriptParserClosure() {
+  function PostScriptParser(lexer) {
+    this.lexer = lexer;
+    this.operators = [];
+    this.token = null;
+    this.prev = null;
+  }
+  PostScriptParser.prototype = {
+    nextToken: function PostScriptParser_nextToken() {
+      this.prev = this.token;
+      this.token = this.lexer.getToken();
+    },
+    accept: function PostScriptParser_accept(type) {
+      if (this.token.type == type) {
+        this.nextToken();
+        return true;
+      }
+      return false;
+    },
+    expect: function PostScriptParser_expect(type) {
+      if (this.accept(type))
+        return true;
+      error('Unexpected symbol: found ' + this.token.type + ' expected ' +
+            type + '.');
+    },
+    parse: function PostScriptParser_parse() {
+      this.nextToken();
+      this.expect(PostScriptTokenTypes.LBRACE);
+      this.parseBlock();
+      this.expect(PostScriptTokenTypes.RBRACE);
+      return this.operators;
+    },
+    parseBlock: function PostScriptParser_parseBlock() {
+      while (true) {
+        if (this.accept(PostScriptTokenTypes.NUMBER)) {
+          this.operators.push(this.prev.value);
+        } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
+          this.operators.push(this.prev.value);
+        } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
+          this.parseCondition();
+        } else {
+          return;
+        }
+      }
+    },
+    parseCondition: function PostScriptParser_parseCondition() {
+      // Add two place holders that will be updated later
+      var conditionLocation = this.operators.length;
+      this.operators.push(null, null);
+
+      this.parseBlock();
+      this.expect(PostScriptTokenTypes.RBRACE);
+      if (this.accept(PostScriptTokenTypes.IF)) {
+        // The true block is right after the 'if' so it just falls through on
+        // true else it jumps and skips the true block.
+        this.operators[conditionLocation] = this.operators.length;
+        this.operators[conditionLocation + 1] = 'jz';
+      } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
+        var jumpLocation = this.operators.length;
+        this.operators.push(null, null);
+        var endOfTrue = this.operators.length;
+        this.parseBlock();
+        this.expect(PostScriptTokenTypes.RBRACE);
+        this.expect(PostScriptTokenTypes.IFELSE);
+        // The jump is added at the end of the true block to skip the false
+        // block.
+        this.operators[jumpLocation] = this.operators.length;
+        this.operators[jumpLocation + 1] = 'j';
+
+        this.operators[conditionLocation] = endOfTrue;
+        this.operators[conditionLocation + 1] = 'jz';
+      } else {
+        error('PS Function: error parsing conditional.');
+      }
+    }
+  };
+  return PostScriptParser;
+})();
+
+var PostScriptTokenTypes = {
+  LBRACE: 0,
+  RBRACE: 1,
+  NUMBER: 2,
+  OPERATOR: 3,
+  IF: 4,
+  IFELSE: 5
+};
+
+var PostScriptToken = (function PostScriptTokenClosure() {
+  function PostScriptToken(type, value) {
+    this.type = type;
+    this.value = value;
+  }
+
+  var opCache = {};
+
+  PostScriptToken.getOperator = function PostScriptToken_getOperator(op) {
+    var opValue = opCache[op];
+    if (opValue)
+      return opValue;
+
+    return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
+  };
+
+  PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE,
+                                                '{');
+  PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE,
+                                                '}');
+  PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF');
+  PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE,
+                                                'IFELSE');
+  return PostScriptToken;
+})();
+
+var PostScriptLexer = (function PostScriptLexerClosure() {
+  function PostScriptLexer(stream) {
+    this.stream = stream;
+    this.nextChar();
+  }
+  PostScriptLexer.prototype = {
+    nextChar: function PostScriptLexer_nextChar() {
+      return (this.currentChar = this.stream.getByte());
+    },
+    getToken: function PostScriptLexer_getToken() {
+      var s = '';
+      var comment = false;
+      var ch = this.currentChar;
+
+      // skip comments
+      while (true) {
+        if (ch < 0) {
+          return EOF;
+        }
+
+        if (comment) {
+          if (ch === 0x0A || ch === 0x0D) {
+            comment = false;
+          }
+        } else if (ch == 0x25) { // '%'
+          comment = true;
+        } else if (!Lexer.isSpace(ch)) {
+          break;
+        }
+        ch = this.nextChar();
+      }
+      switch (ch | 0) {
+        case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4'
+        case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9'
+        case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.'
+          return new PostScriptToken(PostScriptTokenTypes.NUMBER,
+                                      this.getNumber());
+        case 0x7B: // '{'
+          this.nextChar();
+          return PostScriptToken.LBRACE;
+        case 0x7D: // '}'
+          this.nextChar();
+          return PostScriptToken.RBRACE;
+      }
+      // operator
+      var str = String.fromCharCode(ch);
+      while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
+             ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) {
+        str += String.fromCharCode(ch);
+      }
+      switch (str.toLowerCase()) {
+        case 'if':
+          return PostScriptToken.IF;
+        case 'ifelse':
+          return PostScriptToken.IFELSE;
+        default:
+          return PostScriptToken.getOperator(str);
+      }
+    },
+    getNumber: function PostScriptLexer_getNumber() {
+      var ch = this.currentChar;
+      var str = String.fromCharCode(ch);
+      while ((ch = this.nextChar()) >= 0) {
+        if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9'
+             ch === 0x2D || ch === 0x2E) { // '-', '.'
+          str += String.fromCharCode(ch);
+        } else {
+          break;
+        }
+      }
+      var value = parseFloat(str);
+      if (isNaN(value))
+        error('Invalid floating point number: ' + value);
+      return value;
+    }
+  };
+  return PostScriptLexer;
+})();
+
+
+
+var Annotation = (function AnnotationClosure() {
+  // 12.5.5: Algorithm: Appearance streams
+  function getTransformMatrix(rect, bbox, matrix) {
+    var bounds = Util.getAxialAlignedBoundingBox(bbox, matrix);
+    var minX = bounds[0];
+    var minY = bounds[1];
+    var maxX = bounds[2];
+    var maxY = bounds[3];
+
+    if (minX === maxX || minY === maxY) {
+      // From real-life file, bbox was [0, 0, 0, 0]. In this case,
+      // just apply the transform for rect
+      return [1, 0, 0, 1, rect[0], rect[1]];
+    }
+
+    var xRatio = (rect[2] - rect[0]) / (maxX - minX);
+    var yRatio = (rect[3] - rect[1]) / (maxY - minY);
+    return [
+      xRatio,
+      0,
+      0,
+      yRatio,
+      rect[0] - minX * xRatio,
+      rect[1] - minY * yRatio
+    ];
+  }
+
+  function getDefaultAppearance(dict) {
+    var appearanceState = dict.get('AP');
+    if (!isDict(appearanceState)) {
+      return;
+    }
+
+    var appearance;
+    var appearances = appearanceState.get('N');
+    if (isDict(appearances)) {
+      var as = dict.get('AS');
+      if (as && appearances.has(as.name)) {
+        appearance = appearances.get(as.name);
+      }
+    } else {
+      appearance = appearances;
+    }
+    return appearance;
+  }
+
+  function Annotation(params) {
+    if (params.data) {
+      this.data = params.data;
+      return;
+    }
+
+    var dict = params.dict;
+    var data = this.data = {};
+
+    data.subtype = dict.get('Subtype').name;
+    var rect = dict.get('Rect');
+    data.rect = Util.normalizeRect(rect);
+    data.annotationFlags = dict.get('F');
+
+    var color = dict.get('C');
+    if (isArray(color) && color.length === 3) {
+      // TODO(mack): currently only supporting rgb; need support different
+      // colorspaces
+      data.color = color;
+    } else {
+      data.color = [0, 0, 0];
+    }
+
+    // Some types of annotations have border style dict which has more
+    // info than the border array
+    if (dict.has('BS')) {
+      var borderStyle = dict.get('BS');
+      data.borderWidth = borderStyle.has('W') ? borderStyle.get('W') : 1;
+    } else {
+      var borderArray = dict.get('Border') || [0, 0, 1];
+      data.borderWidth = borderArray[2] || 0;
+
+      // TODO: implement proper support for annotations with line dash patterns.
+      var dashArray = borderArray[3];
+      if (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 = {
+
+    getData: function Annotation_getData() {
+      return this.data;
+    },
+
+    hasHtml: function Annotation_hasHtml() {
+      return false;
+    },
+
+    getHtmlElement: function Annotation_getHtmlElement(commonObjs) {
+      throw new NotImplementedException(
+        'getHtmlElement() should be implemented in subclass');
+    },
+
+    // TODO(mack): Remove this, it's not really that helpful.
+    getEmptyContainer: function Annotation_getEmptyContainer(tagName, rect) {
+      assert(!isWorker,
+        'getEmptyContainer() should be called from main thread');
+
+      rect = rect || this.data.rect;
+      var element = document.createElement(tagName);
+      element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
+      element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
+      return element;
+    },
+
+    isViewable: function Annotation_isViewable() {
+      var data = this.data;
+      return !!(
+        data &&
+        (!data.annotationFlags ||
+         !(data.annotationFlags & 0x22)) && // Hidden or NoView
+        data.rect                            // rectangle is nessessary
+      );
+    },
+
+    loadResources: function(keys) {
+      var promise = new LegacyPromise();
+      this.appearance.dict.getAsync('Resources').then(function(resources) {
+        if (!resources) {
+          promise.resolve();
+          return;
+        }
+        var objectLoader = new ObjectLoader(resources.map,
+                                            keys,
+                                            resources.xref);
+        objectLoader.load().then(function() {
+          promise.resolve(resources);
+        });
+      }.bind(this));
+
+      return promise;
+    },
+
+    getOperatorList: function Annotation_getToOperatorList(evaluator) {
+
+      var promise = new LegacyPromise();
+
+      if (!this.appearance) {
+        promise.resolve(new OperatorList());
+        return promise;
+      }
+
+      var data = this.data;
+
+      var appearanceDict = this.appearance.dict;
+      var resourcesPromise = this.loadResources([
+        'ExtGState',
+        'ColorSpace',
+        'Pattern',
+        'Shading',
+        'XObject',
+        'Font'
+        // ProcSet
+        // Properties
+      ]);
+      var bbox = appearanceDict.get('BBox') || [0, 0, 1, 1];
+      var matrix = appearanceDict.get('Matrix') || [1, 0, 0, 1, 0 ,0];
+      var transform = getTransformMatrix(data.rect, bbox, matrix);
+
+      var border = data.border;
+
+      resourcesPromise.then(function(resources) {
+        var opList = new OperatorList();
+        opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
+        evaluator.getOperatorList(this.appearance, resources, opList);
+        opList.addOp(OPS.endAnnotation, []);
+        promise.resolve(opList);
+      }.bind(this));
+
+      return promise;
+    }
+  };
+
+  Annotation.getConstructor =
+      function Annotation_getConstructor(subtype, fieldType) {
+
+    if (!subtype) {
+      return;
+    }
+
+    // TODO(mack): Implement FreeText annotations
+    if (subtype === 'Link') {
+      return LinkAnnotation;
+    } else if (subtype === 'Text') {
+      return TextAnnotation;
+    } else if (subtype === 'Widget') {
+      if (!fieldType) {
+        return;
+      }
+
+      if (fieldType === 'Tx') {
+        return TextWidgetAnnotation;
+      } else {
+        return WidgetAnnotation;
+      }
+    } else {
+      return Annotation;
+    }
+  };
+
+  // TODO(mack): Support loading annotation from data
+  Annotation.fromData = function Annotation_fromData(data) {
+    var subtype = data.subtype;
+    var fieldType = data.fieldType;
+    var Constructor = Annotation.getConstructor(subtype, fieldType);
+    if (Constructor) {
+      return new Constructor({ data: data });
+    }
+  };
+
+  Annotation.fromRef = function Annotation_fromRef(xref, ref) {
+
+    var dict = xref.fetchIfRef(ref);
+    if (!isDict(dict)) {
+      return;
+    }
+
+    var subtype = dict.get('Subtype');
+    subtype = isName(subtype) ? subtype.name : '';
+    if (!subtype) {
+      return;
+    }
+
+    var fieldType = Util.getInheritableProperty(dict, 'FT');
+    fieldType = isName(fieldType) ? fieldType.name : '';
+
+    var Constructor = Annotation.getConstructor(subtype, fieldType);
+    if (!Constructor) {
+      return;
+    }
+
+    var params = {
+      dict: dict,
+      ref: ref,
+    };
+
+    var annotation = new Constructor(params);
+
+    if (annotation.isViewable()) {
+      return annotation;
+    } else {
+      warn('unimplemented annotation type: ' + subtype);
+    }
+  };
+
+  Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
+      annotations, opList, pdfManager, partialEvaluator) {
+
+    function reject(e) {
+      annotationsReadyPromise.reject(e);
+    }
+
+    var annotationsReadyPromise = new LegacyPromise();
+
+    var annotationPromises = [];
+    for (var i = 0, n = annotations.length; i < n; ++i) {
+      annotationPromises.push(annotations[i].getOperatorList(partialEvaluator));
+    }
+    Promise.all(annotationPromises).then(function(datas) {
+      opList.addOp(OPS.beginAnnotations, []);
+      for (var i = 0, n = datas.length; i < n; ++i) {
+        var annotOpList = datas[i];
+        opList.addOpList(annotOpList);
+      }
+      opList.addOp(OPS.endAnnotations, []);
+      annotationsReadyPromise.resolve();
+    }, reject);
+
+    return annotationsReadyPromise;
+  };
+
+  return Annotation;
+})();
+PDFJS.Annotation = Annotation;
+
+
+var WidgetAnnotation = (function WidgetAnnotationClosure() {
+
+  function WidgetAnnotation(params) {
+    Annotation.call(this, params);
+
+    if (params.data) {
+      return;
+    }
+
+    var dict = params.dict;
+    var data = this.data;
+
+    data.fieldValue = stringToPDFString(
+      Util.getInheritableProperty(dict, 'V') || '');
+    data.alternativeText = stringToPDFString(dict.get('TU') || '');
+    data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || '';
+    var fieldType = Util.getInheritableProperty(dict, 'FT');
+    data.fieldType = isName(fieldType) ? fieldType.name : '';
+    data.fieldFlags = Util.getInheritableProperty(dict, 'Ff') || 0;
+    this.fieldResources = Util.getInheritableProperty(dict, 'DR') || new Dict();
+
+    // Building the full field name by collecting the field and
+    // its ancestors 'T' data and joining them using '.'.
+    var fieldName = [];
+    var namedItem = dict;
+    var ref = params.ref;
+    while (namedItem) {
+      var parent = namedItem.get('Parent');
+      var parentRef = namedItem.getRaw('Parent');
+      var name = namedItem.get('T');
+      if (name) {
+        fieldName.unshift(stringToPDFString(name));
+      } else {
+        // The field name is absent, that means more than one field
+        // with the same name may exist. Replacing the empty name
+        // with the '`' plus index in the parent's 'Kids' array.
+        // This is not in the PDF spec but necessary to id the
+        // the input controls.
+        var kids = parent.get('Kids');
+        var j, jj;
+        for (j = 0, jj = kids.length; j < jj; j++) {
+          var kidRef = kids[j];
+          if (kidRef.num == ref.num && kidRef.gen == ref.gen)
+            break;
+        }
+        fieldName.unshift('`' + j);
+      }
+      namedItem = parent;
+      ref = parentRef;
+    }
+    data.fullName = fieldName.join('.');
+  }
+
+  var parent = Annotation.prototype;
+  Util.inherit(WidgetAnnotation, Annotation, {
+    isViewable: function WidgetAnnotation_isViewable() {
+      if (this.data.fieldType === 'Sig') {
+        warn('unimplemented annotation type: Widget signature');
+        return false;
+      }
+
+      return parent.isViewable.call(this);
+    }
+  });
+
+  return WidgetAnnotation;
+})();
+
+var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
+  function TextWidgetAnnotation(params) {
+    WidgetAnnotation.call(this, params);
+
+    if (params.data) {
+      return;
+    }
+
+    this.data.textAlignment = Util.getInheritableProperty(params.dict, 'Q');
+  }
+
+  // TODO(mack): This dupes some of the logic in CanvasGraphics.setFont()
+  function setTextStyles(element, item, fontObj) {
+
+    var style = element.style;
+    style.fontSize = item.fontSize + 'px';
+    style.direction = item.fontDirection < 0 ? 'rtl': 'ltr';
+
+    if (!fontObj) {
+      return;
+    }
+
+    style.fontWeight = fontObj.black ?
+                            (fontObj.bold ? 'bolder' : 'bold') :
+                            (fontObj.bold ? 'bold' : 'normal');
+    style.fontStyle = fontObj.italic ? 'italic' : 'normal';
+
+    var fontName = fontObj.loadedName;
+    var fontFamily = fontName ? '"' + fontName + '", ' : '';
+    // Use a reasonable default font if the font doesn't specify a fallback
+    var fallbackName = fontObj.fallbackName || 'Helvetica, sans-serif';
+    style.fontFamily = fontFamily + fallbackName;
+  }
+
+
+  var parent = WidgetAnnotation.prototype;
+  Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {
+    hasHtml: function TextWidgetAnnotation_hasHtml() {
+      return !this.data.hasAppearance && !!this.data.fieldValue;
+    },
+
+    getHtmlElement: function TextWidgetAnnotation_getHtmlElement(commonObjs) {
+      assert(!isWorker, 'getHtmlElement() shall be called from main thread');
+
+      var item = this.data;
+
+      var element = this.getEmptyContainer('div');
+      element.style.display = 'table';
+
+      var content = document.createElement('div');
+      content.textContent = item.fieldValue;
+      var textAlignment = item.textAlignment;
+      content.style.textAlign = ['left', 'center', 'right'][textAlignment];
+      content.style.verticalAlign = 'middle';
+      content.style.display = 'table-cell';
+
+      var fontObj = item.fontRefName ?
+                    commonObjs.getData(item.fontRefName) : null;
+      var cssRules = setTextStyles(content, item, fontObj);
+
+      element.appendChild(content);
+
+      return element;
+    },
+
+    getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) {
+      if (this.appearance) {
+        return Annotation.prototype.getOperatorList.call(this, evaluator);
+      }
+
+      var promise = new LegacyPromise();
+      var opList = new OperatorList();
+      var data = this.data;
+
+      // Even if there is an appearance stream, ignore it. This is the
+      // behaviour used by Adobe Reader.
+
+      var defaultAppearance = data.defaultAppearance;
+      if (!defaultAppearance) {
+        promise.resolve(opList);
+        return promise;
+      }
+
+      // Include any font resources found in the default appearance
+
+      var stream = new Stream(stringToBytes(defaultAppearance));
+      evaluator.getOperatorList(stream, this.fieldResources, opList);
+      var appearanceFnArray = opList.fnArray;
+      var appearanceArgsArray = opList.argsArray;
+      var fnArray = [];
+      var argsArray = [];
+
+      // TODO(mack): Add support for stroke color
+      data.rgb = [0, 0, 0];
+      // TODO THIS DOESN'T MAKE ANY SENSE SINCE THE fnArray IS EMPTY!
+      for (var i = 0, n = fnArray.length; i < n; ++i) {
+        var fnId = appearanceFnArray[i];
+        var args = appearanceArgsArray[i];
+
+        if (fnId === OPS.setFont) {
+          data.fontRefName = args[0];
+          var size = args[1];
+          if (size < 0) {
+            data.fontDirection = -1;
+            data.fontSize = -size;
+          } else {
+            data.fontDirection = 1;
+            data.fontSize = size;
+          }
+        } else if (fnId === OPS.setFillRGBColor) {
+          data.rgb = args;
+        } else if (fnId === OPS.setFillGray) {
+          var rgbValue = args[0] * 255;
+          data.rgb = [rgbValue, rgbValue, rgbValue];
+        }
+      }
+      promise.resolve(opList);
+      return promise;
+    }
+  });
+
+  return TextWidgetAnnotation;
+})();
+
+var TextAnnotation = (function TextAnnotationClosure() {
+  function TextAnnotation(params) {
+    Annotation.call(this, params);
+
+    if (params.data) {
+      return;
+    }
+
+    var dict = params.dict;
+    var data = this.data;
+
+    var content = dict.get('Contents');
+    var title = dict.get('T');
+    data.content = stringToPDFString(content || '');
+    data.title = stringToPDFString(title || '');
+    data.name = !dict.has('Name') ? 'Note' : dict.get('Name').name;
+  }
+
+  var ANNOT_MIN_SIZE = 10;
+
+  Util.inherit(TextAnnotation, Annotation, {
+
+    getOperatorList: function TextAnnotation_getOperatorList(evaluator) {
+      var promise = new LegacyPromise();
+      promise.resolve(new OperatorList());
+      return promise;
+    },
+
+    hasHtml: function TextAnnotation_hasHtml() {
+      return true;
+    },
+
+    getHtmlElement: function TextAnnotation_getHtmlElement(commonObjs) {
+      assert(!isWorker, 'getHtmlElement() shall be called from main thread');
+
+      var item = this.data;
+      var rect = item.rect;
+
+      // sanity check because of OOo-generated PDFs
+      if ((rect[3] - rect[1]) < ANNOT_MIN_SIZE) {
+        rect[3] = rect[1] + ANNOT_MIN_SIZE;
+      }
+      if ((rect[2] - rect[0]) < ANNOT_MIN_SIZE) {
+        rect[2] = rect[0] + (rect[3] - rect[1]); // make it square
+      }
+
+      var container = this.getEmptyContainer('section', rect);
+      container.className = 'annotText';
+
+      var image = document.createElement('img');
+      image.style.height = container.style.height;
+      var iconName = item.name;
+      image.src = PDFJS.imageResourcesPath + 'annotation-' +
+        iconName.toLowerCase() + '.svg';
+      image.alt = '[{{type}} Annotation]';
+      image.dataset.l10nId = 'text_annotation_type';
+      image.dataset.l10nArgs = JSON.stringify({type: iconName});
+      var content = document.createElement('div');
+      content.setAttribute('hidden', true);
+      var title = document.createElement('h1');
+      var text = document.createElement('p');
+      content.style.left = Math.floor(rect[2] - rect[0]) + 'px';
+      content.style.top = '0px';
+      title.textContent = item.title;
+
+      if (!item.content && !item.title) {
+        content.setAttribute('hidden', true);
+      } else {
+        var e = document.createElement('span');
+        var lines = item.content.split(/(?:\r\n?|\n)/);
+        for (var i = 0, ii = lines.length; i < ii; ++i) {
+          var line = lines[i];
+          e.appendChild(document.createTextNode(line));
+          if (i < (ii - 1))
+            e.appendChild(document.createElement('br'));
+        }
+        text.appendChild(e);
+
+        var showAnnotation = function showAnnotation() {
+          container.style.zIndex += 1;
+          content.removeAttribute('hidden');
+        };
+
+        var hideAnnotation = function hideAnnotation(e) {
+          if (e.toElement || e.relatedTarget) { // No context menu is used
+            container.style.zIndex -= 1;
+            content.setAttribute('hidden', true);
+          }
+        };
+
+        content.addEventListener('mouseover', showAnnotation, false);
+        content.addEventListener('mouseout', hideAnnotation, false);
+        image.addEventListener('mouseover', showAnnotation, false);
+        image.addEventListener('mouseout', hideAnnotation, false);
+      }
+
+      content.appendChild(title);
+      content.appendChild(text);
+      container.appendChild(image);
+      container.appendChild(content);
+
+      return container;
+    }
+  });
+
+  return TextAnnotation;
+})();
+
+var LinkAnnotation = (function LinkAnnotationClosure() {
+  function LinkAnnotation(params) {
+    Annotation.call(this, params);
+
+    if (params.data) {
+      return;
+    }
+
+    var dict = params.dict;
+    var data = this.data;
+
+    var action = dict.get('A');
+    if (action) {
+      var linkType = action.get('S').name;
+      if (linkType === 'URI') {
+        var url = addDefaultProtocolToUrl(action.get('URI'));
+        // TODO: pdf spec mentions urls can be relative to a Base
+        // entry in the dictionary.
+        if (!isValidUrl(url, false)) {
+          url = '';
+        }
+        data.url = url;
+      } else if (linkType === 'GoTo') {
+        data.dest = action.get('D');
+      } else if (linkType === 'GoToR') {
+        var urlDict = action.get('F');
+        if (isDict(urlDict)) {
+          // We assume that the 'url' is a Filspec dictionary
+          // and fetch the url without checking any further
+          url = urlDict.get('F') || '';
+        }
+
+        // TODO: pdf reference says that GoToR
+        // can also have 'NewWindow' attribute
+        if (!isValidUrl(url, false)) {
+          url = '';
+        }
+        data.url = url;
+        data.dest = action.get('D');
+      } else if (linkType === 'Named') {
+        data.action = action.get('N').name;
+      } else {
+        warn('unrecognized link type: ' + linkType);
+      }
+    } else if (dict.has('Dest')) {
+      // simple destination link
+      var dest = dict.get('Dest');
+      data.dest = isName(dest) ? dest.name : dest;
+    }
+  }
+
+  // Lets URLs beginning with 'www.' default to using the 'http://' protocol.
+  function addDefaultProtocolToUrl(url) {
+    if (url.indexOf('www.') === 0) {
+      return ('http://' + url);
+    }
+    return url;
+  }
+
+  Util.inherit(LinkAnnotation, Annotation, {
+    hasOperatorList: function LinkAnnotation_hasOperatorList() {
+      return false;
+    },
+
+    hasHtml: function LinkAnnotation_hasHtml() {
+      return true;
+    },
+
+    getHtmlElement: function LinkAnnotation_getHtmlElement(commonObjs) {
+      var rect = this.data.rect;
+      var element = document.createElement('a');
+      var borderWidth = this.data.borderWidth;
+
+      element.style.borderWidth = borderWidth + 'px';
+      var color = this.data.color;
+      var rgb = [];
+      for (var i = 0; i < 3; ++i) {
+        rgb[i] = Math.round(color[i] * 255);
+      }
+      element.style.borderColor = Util.makeCssRgb(rgb);
+      element.style.borderStyle = 'solid';
+
+      var width = rect[2] - rect[0] - 2 * borderWidth;
+      var height = rect[3] - rect[1] - 2 * borderWidth;
+      element.style.width = width + 'px';
+      element.style.height = height + 'px';
+
+      element.href = this.data.url || '';
+      return element;
+    }
+  });
+
+  return LinkAnnotation;
+})();
+
+
+/**
+ * The maximum allowed image size in total pixels e.g. width * height. Images
+ * above this value will not be drawn. Use -1 for no limit.
+ * @var {Number}
+ */
+PDFJS.maxImageSize = PDFJS.maxImageSize === undefined ? -1 : PDFJS.maxImageSize;
+
+/**
+ * By default fonts are converted to OpenType fonts and loaded via font face
+ * rules. If disabled, the font will be rendered using a built in font renderer
+ * that constructs the glyphs with primitive path commands.
+ * @var {Boolean}
+ */
+PDFJS.disableFontFace = PDFJS.disableFontFace === undefined ?
+                        false : PDFJS.disableFontFace;
+
+/**
+ * Path for image resources, mainly for annotation icons. Include trailing
+ * slash.
+ * @var {String}
+ */
+PDFJS.imageResourcesPath = PDFJS.imageResourcesPath === undefined ?
+                           '' : PDFJS.imageResourcesPath;
+
+/**
+ * Disable the web worker and run all code on the main thread. This will happen
+ * automatically if the browser doesn't support workers or sending typed arrays
+ * to workers.
+ * @var {Boolean}
+ */
+PDFJS.disableWorker = PDFJS.disableWorker === undefined ?
+                      false : PDFJS.disableWorker;
+
+/**
+ * Path and filename of the worker file. Required when the worker is enabled in
+ * development mode. If unspecified in the production build, the worker will be
+ * loaded based on the location of the pdf.js file.
+ * @var {String}
+ */
+PDFJS.workerSrc = PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc;
+
+/**
+ * Disable range request loading of PDF files. When enabled and if the server
+ * supports partial content requests then the PDF will be fetched in chunks.
+ * Enabled (false) by default.
+ * @var {Boolean}
+ */
+PDFJS.disableRange = PDFJS.disableRange === undefined ?
+                     false : PDFJS.disableRange;
+
+/**
+ * Disable pre-fetching of PDF file data. When range requests are enabled PDF.js
+ * will automatically keep fetching more data even if it isn't needed to display
+ * the current page. This default behavior can be disabled.
+ * @var {Boolean}
+ */
+PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ?
+                         false : PDFJS.disableAutoFetch;
+
+/**
+ * Enables special hooks for debugging PDF.js.
+ * @var {Boolean}
+ */
+PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug;
+
+/**
+ * Enables transfer usage in postMessage for ArrayBuffers.
+ * @var {boolean}
+ */
+PDFJS.postMessageTransfers = PDFJS.postMessageTransfers === undefined ?
+                             true : PDFJS.postMessageTransfers;
+
+/**
+ * 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;
+
+/**
+ * This is the main entry point for loading a PDF and interacting with it.
+ * NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR)
+ * is used, which means it must follow the same origin rules that any XHR does
+ * e.g. No cross domain requests without CORS.
+ *
+ * @param {string|TypedAray|object} source Can be an url to where a PDF is
+ * located, a typed array (Uint8Array) already populated with data or
+ * and parameter object with the following possible fields:
+ *  - url   - The URL of the PDF.
+ *  - data  - A typed array with PDF data.
+ *  - httpHeaders - Basic authentication headers.
+ *  - 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.
+ *  - password - For decrypting password-protected PDFs.
+ *  - initialData - A typed array with the first portion or all of the pdf data.
+ *                  Used by the extension since some data is already loaded
+ *                  before the switch to range requests. 
+ *
+ * @param {object} pdfDataRangeTransport is optional. It is used if you want
+ * to manually serve range requests for data in the PDF. See viewer.js for
+ * an example of pdfDataRangeTransport's interface.
+ *
+ * @param {function} passwordCallback is optional. It is used to request a
+ * password if wrong or no password was provided. The callback receives two
+ * parameters: function that needs to be called with new password and reason
+ * (see {PasswordResponses}).
+ *
+ * @return {Promise} A promise that is resolved with {PDFDocumentProxy} object.
+ */
+PDFJS.getDocument = function getDocument(source,
+                                         pdfDataRangeTransport,
+                                         passwordCallback,
+                                         progressCallback) {
+  var workerInitializedPromise, workerReadyPromise, transport;
+
+  if (typeof source === 'string') {
+    source = { url: source };
+  } else if (isArrayBuffer(source)) {
+    source = { data: source };
+  } else if (typeof source !== 'object') {
+    error('Invalid parameter in getDocument, need either Uint8Array, ' +
+          'string or a parameter object');
+  }
+
+  if (!source.url && !source.data)
+    error('Invalid parameter array, need either .data or .url');
+
+  // copy/use all keys as is except 'url' -- full path is required
+  var params = {};
+  for (var key in source) {
+    if (key === 'url' && typeof window !== 'undefined') {
+      params[key] = combineUrl(window.location.href, source[key]);
+      continue;
+    }
+    params[key] = source[key];
+  }
+
+  workerInitializedPromise = new PDFJS.LegacyPromise();
+  workerReadyPromise = new PDFJS.LegacyPromise();
+  transport = new WorkerTransport(workerInitializedPromise,
+      workerReadyPromise, pdfDataRangeTransport, progressCallback);
+  workerInitializedPromise.then(function transportInitialized() {
+    transport.passwordCallback = passwordCallback;
+    transport.fetchDocument(params);
+  });
+  return workerReadyPromise;
+};
+
+/**
+ * Proxy to a PDFDocument in the worker thread. Also, contains commonly used
+ * properties that can be read synchronously.
+ */
+var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
+  function PDFDocumentProxy(pdfInfo, transport) {
+    this.pdfInfo = pdfInfo;
+    this.transport = transport;
+  }
+  PDFDocumentProxy.prototype = {
+    /**
+     * @return {number} Total number of pages the PDF contains.
+     */
+    get numPages() {
+      return this.pdfInfo.numPages;
+    },
+    /**
+     * @return {string} A unique ID to identify a PDF. Not guaranteed to be
+     * unique.
+     */
+    get fingerprint() {
+      return this.pdfInfo.fingerprint;
+    },
+    /**
+     * @return {boolean} true if embedded document fonts are in use. Will be
+     * set during rendering of the pages.
+     */
+    get embeddedFontsUsed() {
+      return this.transport.embeddedFontsUsed;
+    },
+    /**
+     * @param {number} The page number to get. The first page is 1.
+     * @return {Promise} A promise that is resolved with a {PDFPageProxy}
+     * object.
+     */
+    getPage: function PDFDocumentProxy_getPage(number) {
+      return this.transport.getPage(number);
+    },
+    /**
+     * @param {object} Must have 'num' and 'gen' properties.
+     * @return {Promise} A promise that is resolved with the page index that is
+     * associated with the reference.
+     */
+    getPageIndex: function PDFDocumentProxy_getPageIndex(ref) {
+      return this.transport.getPageIndex(ref);
+    },
+    /**
+     * @return {Promise} A promise that is resolved with a lookup table for
+     * mapping named destinations to reference numbers.
+     */
+    getDestinations: function PDFDocumentProxy_getDestinations() {
+      return this.transport.getDestinations();
+    },
+    /**
+     * @return {Promise} A promise that is resolved with an array of all the
+     * JavaScript strings in the name tree.
+     */
+    getJavaScript: function PDFDocumentProxy_getJavaScript() {
+      var promise = new PDFJS.LegacyPromise();
+      var js = this.pdfInfo.javaScript;
+      promise.resolve(js);
+      return promise;
+    },
+    /**
+     * @return {Promise} A promise that is resolved with an {array} that is a
+     * tree outline (if it has one) of the PDF. The tree is in the format of:
+     * [
+     *  {
+     *   title: string,
+     *   bold: boolean,
+     *   italic: boolean,
+     *   color: rgb array,
+     *   dest: dest obj,
+     *   items: array of more items like this
+     *  },
+     *  ...
+     * ].
+     */
+    getOutline: function PDFDocumentProxy_getOutline() {
+      var promise = new PDFJS.LegacyPromise();
+      var outline = this.pdfInfo.outline;
+      promise.resolve(outline);
+      return promise;
+    },
+    /**
+     * @return {Promise} A promise that is resolved with an {object} that has
+     * info and metadata properties.  Info is an {object} filled with anything
+     * available in the information dictionary and similarly metadata is a
+     * {Metadata} object with information from the metadata section of the PDF.
+     */
+    getMetadata: function PDFDocumentProxy_getMetadata() {
+      var promise = new PDFJS.LegacyPromise();
+      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.LegacyPromise();
+      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();
+      this.transport.getData(promise);
+      return promise;
+    },
+    /**
+     * @return {Promise} A promise that is resolved when the document's data
+     * is loaded
+     */
+    dataLoaded: function PDFDocumentProxy_dataLoaded() {
+      return this.transport.dataLoaded();
+    },
+    cleanup: function PDFDocumentProxy_cleanup() {
+      this.transport.startCleanup();
+    },
+    destroy: function PDFDocumentProxy_destroy() {
+      this.transport.destroy();
+    }
+  };
+  return PDFDocumentProxy;
+})();
+
+var PDFPageProxy = (function PDFPageProxyClosure() {
+  function PDFPageProxy(pageInfo, transport) {
+    this.pageInfo = pageInfo;
+    this.transport = transport;
+    this.stats = new StatTimer();
+    this.stats.enabled = !!globalScope.PDFJS.enableStats;
+    this.commonObjs = transport.commonObjs;
+    this.objs = new PDFObjects();
+    this.receivingOperatorList  = false;
+    this.cleanupAfterRender = false;
+    this.pendingDestroy = false;
+    this.renderTasks = [];
+  }
+  PDFPageProxy.prototype = {
+    /**
+     * @return {number} Page number of the page. First page is 1.
+     */
+    get pageNumber() {
+      return this.pageInfo.pageIndex + 1;
+    },
+    /**
+     * @return {number} The number of degrees the page is rotated clockwise.
+     */
+    get rotate() {
+      return this.pageInfo.rotate;
+    },
+    /**
+     * @return {object} The reference that points to this page. It has 'num' and
+     * 'gen' properties.
+     */
+    get ref() {
+      return this.pageInfo.ref;
+    },
+    /**
+     * @return {array} An array of the visible portion of the PDF page in the
+     * user space units - [x1, y1, x2, y2].
+     */
+    get view() {
+      return this.pageInfo.view;
+    },
+    /**
+     * @param {number} scale The desired scale of the viewport.
+     * @param {number} rotate Degrees to rotate the viewport. If omitted this
+     * defaults to the page rotation.
+     * @return {PageViewport} Contains 'width' and 'height' properties along
+     * with transforms required for rendering.
+     */
+    getViewport: function PDFPageProxy_getViewport(scale, rotate) {
+      if (arguments.length < 2)
+        rotate = this.rotate;
+      return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
+    },
+    /**
+     * @return {Promise} A promise that is resolved with an {array} of the
+     * annotation objects.
+     */
+    getAnnotations: function PDFPageProxy_getAnnotations() {
+      if (this.annotationsPromise)
+        return this.annotationsPromise;
+
+      var promise = new PDFJS.LegacyPromise();
+      this.annotationsPromise = promise;
+      this.transport.getAnnotations(this.pageInfo.pageIndex);
+      return promise;
+    },
+    /**
+     * Begins the process of rendering a page to the desired context.
+     * @param {object} params A parameter object that supports:
+     * {
+     *   canvasContext(required): A 2D context of a DOM Canvas object.,
+     *   textLayer(optional): An object that has beginLayout, endLayout, and
+     *                        appendText functions.,
+     *   imageLayer(optional): An object that has beginLayout, endLayout and
+     *                         appendImage functions.,
+     *   continueCallback(optional): A function that will be called each time
+     *                               the rendering is paused.  To continue
+     *                               rendering call the function that is the
+     *                               first argument to the callback.
+     * }.
+     * @return {RenderTask} An extended promise that is resolved when the page
+     * finishes rendering (see RenderTask).
+     */
+    render: function PDFPageProxy_render(params) {
+      var stats = this.stats;
+      stats.time('Overall');
+
+      // If there was a pending destroy cancel it so no cleanup happens during
+      // this call to render.
+      this.pendingDestroy = false;
+
+      // If there is no displayReadyPromise yet, then the operatorList was never
+      // requested before. Make the request and create the promise.
+      if (!this.displayReadyPromise) {
+        this.receivingOperatorList = true;
+        this.displayReadyPromise = new LegacyPromise();
+        this.operatorList = {
+          fnArray: [],
+          argsArray: [],
+          lastChunk: false
+        };
+
+        this.stats.time('Page Request');
+        this.transport.messageHandler.send('RenderPageRequest', {
+          pageIndex: this.pageNumber - 1
+        });
+      }
+
+      var internalRenderTask = new InternalRenderTask(complete, params,
+                                       this.objs, this.commonObjs,
+                                       this.operatorList, this.pageNumber);
+      this.renderTasks.push(internalRenderTask);
+      var renderTask = new RenderTask(internalRenderTask);
+
+      var self = this;
+      this.displayReadyPromise.then(
+        function pageDisplayReadyPromise(transparency) {
+          if (self.pendingDestroy) {
+            complete();
+            return;
+          }
+          stats.time('Rendering');
+          internalRenderTask.initalizeGraphics(transparency);
+          internalRenderTask.operatorListChanged();
+        },
+        function pageDisplayReadPromiseError(reason) {
+          complete(reason);
+        }
+      );
+
+      function complete(error) {
+        var i = self.renderTasks.indexOf(internalRenderTask);
+        if (i >= 0) {
+          self.renderTasks.splice(i, 1);
+        }
+
+        if (self.cleanupAfterRender) {
+          self.pendingDestroy = true;
+        }
+        self._tryDestroy();
+
+        if (error) {
+          renderTask.promise.reject(error);
+        } else {
+          renderTask.promise.resolve();
+        }
+        stats.timeEnd('Rendering');
+        stats.timeEnd('Overall');
+      }
+
+      return renderTask;
+    },
+    /**
+     * @return {Promise} That is resolved with the a {string} that is the text
+     * content from the page.
+     */
+    getTextContent: function PDFPageProxy_getTextContent() {
+      var promise = new PDFJS.LegacyPromise();
+      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.LegacyPromise();
+      var operationList = { // not implemented
+        dependencyFontsID: null,
+        operatorList: null
+      };
+      promise.resolve(operationList);
+      return promise;
+    },
+    /**
+     * Destroys resources allocated by the page.
+     */
+    destroy: function PDFPageProxy_destroy() {
+      this.pendingDestroy = true;
+      this._tryDestroy();
+    },
+    /**
+     * For internal use only. Attempts to clean up if rendering is in a state
+     * where that's possible.
+     */
+    _tryDestroy: function PDFPageProxy__destroy() {
+      if (!this.pendingDestroy ||
+          this.renderTasks.length !== 0 ||
+          this.receivingOperatorList) {
+        return;
+      }
+
+      delete this.operatorList;
+      delete this.displayReadyPromise;
+      this.objs.clear();
+      this.pendingDestroy = false;
+    },
+    /**
+     * For internal use only.
+     */
+    _startRenderPage: function PDFPageProxy_startRenderPage(transparency) {
+      this.displayReadyPromise.resolve(transparency);
+    },
+    /**
+     * For internal use only.
+     */
+    _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk) {
+      // Add the new chunk to the current operator list.
+      for (var i = 0, ii = operatorListChunk.length; i < ii; i++) {
+        this.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
+        this.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
+      }
+      this.operatorList.lastChunk = operatorListChunk.lastChunk;
+
+      // Notify all the rendering tasks there are more operators to be consumed.
+      for (var i = 0; i < this.renderTasks.length; i++) {
+        this.renderTasks[i].operatorListChanged();
+      }
+
+      if (operatorListChunk.lastChunk) {
+        this.receivingOperatorList = false;
+        this._tryDestroy();
+      }
+    }
+  };
+  return PDFPageProxy;
+})();
+/**
+ * For internal use only.
+ */
+var WorkerTransport = (function WorkerTransportClosure() {
+  function WorkerTransport(workerInitializedPromise, workerReadyPromise,
+      pdfDataRangeTransport, progressCallback) {
+    this.pdfDataRangeTransport = pdfDataRangeTransport;
+
+    this.workerReadyPromise = workerReadyPromise;
+    this.progressCallback = progressCallback;
+    this.commonObjs = new PDFObjects();
+
+    this.pageCache = [];
+    this.pagePromises = [];
+    this.embeddedFontsUsed = false;
+
+    this.passwordCallback = null;
+
+    // If worker support isn't disabled explicit and the browser has worker
+    // support, create a new web worker and test if it/the browser fullfills
+    // all requirements to run parts of pdf.js in a web worker.
+    // Right now, the requirement is, that an Uint8Array is still an Uint8Array
+    // as it arrives on the worker. Chrome added this with version 15.
+    if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
+      var workerSrc = PDFJS.workerSrc;
+      if (!workerSrc) {
+        error('No PDFJS.workerSrc specified');
+      }
+
+      try {
+        // Some versions of FF can't create a worker on localhost, see:
+        // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
+        var worker = new Worker(workerSrc);
+        var messageHandler = new MessageHandler('main', worker);
+        this.messageHandler = messageHandler;
+
+        messageHandler.on('test', function transportTest(data) {
+          var supportTypedArray = data && data.supportTypedArray;
+          if (supportTypedArray) {
+            this.worker = worker;
+            if (!data.supportTransfers) {
+              PDFJS.postMessageTransfers = false;
+            }
+            this.setupMessageHandler(messageHandler);
+            workerInitializedPromise.resolve();
+          } else {
+            globalScope.PDFJS.disableWorker = true;
+            this.loadFakeWorkerFiles().then(function() {
+              this.setupFakeWorker();
+              workerInitializedPromise.resolve();
+            }.bind(this));
+          }
+        }.bind(this));
+
+        var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]);
+        // Some versions of Opera throw a DATA_CLONE_ERR on serializing the
+        // typed array. Also, checking if we can use transfers.
+        try {
+          messageHandler.send('test', testObj, null, [testObj.buffer]);
+        } catch (ex) {
+          info('Cannot use postMessage transfers');
+          testObj[0] = 0;
+          messageHandler.send('test', testObj);
+        }
+        return;
+      } catch (e) {
+        info('The worker has been disabled.');
+      }
+    }
+    // Either workers are disabled, not supported or have thrown an exception.
+    // Thus, we fallback to a faked worker.
+    globalScope.PDFJS.disableWorker = true;
+    this.loadFakeWorkerFiles().then(function() {
+      this.setupFakeWorker();
+      workerInitializedPromise.resolve();
+    }.bind(this));
+  }
+  WorkerTransport.prototype = {
+    destroy: function WorkerTransport_destroy() {
+      this.pageCache = [];
+      this.pagePromises = [];
+      var self = this;
+      this.messageHandler.send('Terminate', null, function () {
+        if (self.worker) {
+          self.worker.terminate();
+        }
+      });
+    },
+
+    loadFakeWorkerFiles: function WorkerTransport_loadFakeWorkerFiles() {
+      if (!PDFJS.fakeWorkerFilesLoadedPromise) {
+        PDFJS.fakeWorkerFilesLoadedPromise = new LegacyPromise();
+        // In the developer build load worker_loader which in turn loads all the
+        // other files and resolves the promise. In production only the
+        // pdf.worker.js file is needed.
+        Util.loadScript(PDFJS.workerSrc, function() {
+          PDFJS.fakeWorkerFilesLoadedPromise.resolve();
+        });
+      }
+      return PDFJS.fakeWorkerFilesLoadedPromise;
+    },
+
+    setupFakeWorker: function WorkerTransport_setupFakeWorker() {
+      warn('Setting up fake worker.');
+      // If we don't use a worker, just post/sendMessage to the main thread.
+      var fakeWorker = {
+        postMessage: function WorkerTransport_postMessage(obj) {
+          fakeWorker.onmessage({data: obj});
+        },
+        terminate: function WorkerTransport_terminate() {}
+      };
+
+      var messageHandler = new MessageHandler('main', fakeWorker);
+      this.setupMessageHandler(messageHandler);
+
+      // If the main thread is our worker, setup the handling for the messages
+      // the main thread sends to it self.
+      PDFJS.WorkerMessageHandler.setup(messageHandler);
+    },
+
+    setupMessageHandler:
+      function WorkerTransport_setupMessageHandler(messageHandler) {
+      this.messageHandler = messageHandler;
+
+      function updatePassword(password) {
+        messageHandler.send('UpdatePassword', password);
+      }
+
+      var pdfDataRangeTransport = this.pdfDataRangeTransport;
+      if (pdfDataRangeTransport) {
+        pdfDataRangeTransport.addRangeListener(function(begin, chunk) {
+          messageHandler.send('OnDataRange', {
+            begin: begin,
+            chunk: chunk
+          });
+        });
+
+        pdfDataRangeTransport.addProgressListener(function(loaded) {
+          messageHandler.send('OnDataProgress', {
+            loaded: loaded
+          });
+        });
+
+        messageHandler.on('RequestDataRange',
+          function transportDataRange(data) {
+            pdfDataRangeTransport.requestDataRange(data.begin, data.end);
+          }, this);
+      }
+
+      messageHandler.on('GetDoc', function transportDoc(data) {
+        var pdfInfo = data.pdfInfo;
+        var pdfDocument = new PDFDocumentProxy(pdfInfo, this);
+        this.pdfDocument = pdfDocument;
+        this.workerReadyPromise.resolve(pdfDocument);
+      }, this);
+
+      messageHandler.on('NeedPassword', function transportPassword(data) {
+        if (this.passwordCallback) {
+          return this.passwordCallback(updatePassword,
+                                       PasswordResponses.NEED_PASSWORD);
+        }
+        this.workerReadyPromise.reject(data.exception.message, data.exception);
+      }, this);
+
+      messageHandler.on('IncorrectPassword', function transportBadPass(data) {
+        if (this.passwordCallback) {
+          return this.passwordCallback(updatePassword,
+                                       PasswordResponses.INCORRECT_PASSWORD);
+        }
+        this.workerReadyPromise.reject(data.exception.message, data.exception);
+      }, this);
+
+      messageHandler.on('InvalidPDF', function transportInvalidPDF(data) {
+        this.workerReadyPromise.reject(data.exception.name, data.exception);
+      }, this);
+
+      messageHandler.on('MissingPDF', function transportMissingPDF(data) {
+        this.workerReadyPromise.reject(data.exception.message, data.exception);
+      }, this);
+
+      messageHandler.on('UnknownError', function transportUnknownError(data) {
+        this.workerReadyPromise.reject(data.exception.message, data.exception);
+      }, this);
+
+      messageHandler.on('GetPage', function transportPage(data) {
+        var pageInfo = data.pageInfo;
+        var page = new PDFPageProxy(pageInfo, this);
+        this.pageCache[pageInfo.pageIndex] = page;
+        var promise = this.pagePromises[pageInfo.pageIndex];
+        promise.resolve(page);
+      }, this);
+
+      messageHandler.on('GetAnnotations', function transportAnnotations(data) {
+        var annotations = data.annotations;
+        var promise = this.pageCache[data.pageIndex].annotationsPromise;
+        promise.resolve(annotations);
+      }, this);
+
+      messageHandler.on('StartRenderPage', function transportRender(data) {
+        var page = this.pageCache[data.pageIndex];
+
+        page.stats.timeEnd('Page Request');
+        page._startRenderPage(data.transparency);
+      }, this);
+
+      messageHandler.on('RenderPageChunk', function transportRender(data) {
+        var page = this.pageCache[data.pageIndex];
+
+        page._renderPageChunk(data.operatorList);
+      }, this);
+
+      messageHandler.on('commonobj', function transportObj(data) {
+        var id = data[0];
+        var type = data[1];
+        if (this.commonObjs.hasData(id))
+          return;
+
+        switch (type) {
+          case 'Font':
+            var exportedData = data[2];
+
+            var font;
+            if ('error' in exportedData) {
+              var error = exportedData.error;
+              warn('Error during font loading: ' + error);
+              this.commonObjs.resolve(id, error);
+              break;
+            } else {
+              font = new FontFace(exportedData);
+            }
+
+            FontLoader.bind(
+              [font],
+              function fontReady(fontObjs) {
+                this.commonObjs.resolve(id, font);
+              }.bind(this)
+            );
+            break;
+          case 'FontPath':
+            this.commonObjs.resolve(id, data[2]);
+            break;
+          default:
+            error('Got unknown common object type ' + type);
+        }
+      }, this);
+
+      messageHandler.on('obj', function transportObj(data) {
+        var id = data[0];
+        var pageIndex = data[1];
+        var type = data[2];
+        var pageProxy = this.pageCache[pageIndex];
+        if (pageProxy.objs.hasData(id))
+          return;
+
+        switch (type) {
+          case 'JpegStream':
+            var imageData = data[3];
+            loadJpegStream(id, imageData, pageProxy.objs);
+            break;
+          case 'Image':
+            var imageData = data[3];
+            pageProxy.objs.resolve(id, imageData);
+
+            // heuristics that will allow not to store large data
+            var MAX_IMAGE_SIZE_TO_STORE = 8000000;
+            if ('data' in imageData &&
+                imageData.data.length > MAX_IMAGE_SIZE_TO_STORE) {
+              pageProxy.cleanupAfterRender = true;
+            }
+            break;
+          default:
+            error('Got unknown object type ' + type);
+        }
+      }, this);
+
+      messageHandler.on('DocProgress', function transportDocProgress(data) {
+        if (this.progressCallback) {
+          this.progressCallback({
+            loaded: data.loaded,
+            total: data.total
+          });
+        }
+      }, this);
+
+      messageHandler.on('DocError', function transportDocError(data) {
+        this.workerReadyPromise.reject(data);
+      }, this);
+
+      messageHandler.on('PageError', function transportError(data) {
+        var page = this.pageCache[data.pageNum - 1];
+        if (page.displayReadyPromise)
+          page.displayReadyPromise.reject(data.error);
+        else
+          error(data.error);
+      }, this);
+
+      messageHandler.on('JpegDecode', function(data, deferred) {
+        var imageUrl = data[0];
+        var components = data[1];
+        if (components != 3 && components != 1)
+          error('Only 3 component or 1 component can be returned');
+
+        var img = new Image();
+        img.onload = (function messageHandler_onloadClosure() {
+          var width = img.width;
+          var height = img.height;
+          var size = width * height;
+          var rgbaLength = size * 4;
+          var buf = new Uint8Array(size * components);
+          var tmpCanvas = createScratchCanvas(width, height);
+          var tmpCtx = tmpCanvas.getContext('2d');
+          tmpCtx.drawImage(img, 0, 0);
+          var data = tmpCtx.getImageData(0, 0, width, height).data;
+
+          if (components == 3) {
+            for (var i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
+              buf[j] = data[i];
+              buf[j + 1] = data[i + 1];
+              buf[j + 2] = data[i + 2];
+            }
+          } else if (components == 1) {
+            for (var i = 0, j = 0; i < rgbaLength; i += 4, j++) {
+              buf[j] = data[i];
+            }
+          }
+          deferred.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
+      });
+    },
+
+    getData: function WorkerTransport_getData(promise) {
+      this.messageHandler.send('GetData', null, function(data) {
+        promise.resolve(data);
+      });
+    },
+
+    dataLoaded: function WorkerTransport_dataLoaded() {
+      var promise = new PDFJS.LegacyPromise();
+      this.messageHandler.send('DataLoaded', null, function(args) {
+        promise.resolve(args);
+      });
+      return promise;
+    },
+
+    getPage: function WorkerTransport_getPage(pageNumber, promise) {
+      var pageIndex = pageNumber - 1;
+      if (pageIndex in this.pagePromises)
+        return this.pagePromises[pageIndex];
+      var promise = new PDFJS.LegacyPromise();
+      this.pagePromises[pageIndex] = promise;
+      this.messageHandler.send('GetPageRequest', { pageIndex: pageIndex });
+      return promise;
+    },
+
+    getPageIndex: function WorkerTransport_getPageIndexByRef(ref) {
+      var promise = new PDFJS.LegacyPromise();
+      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();
+      this.messageHandler.send('GetDestinations', null,
+        function transportDestinations(destinations) {
+          promise.resolve(destinations);
+        }
+      );
+      return promise;
+    },
+
+    startCleanup: function WorkerTransport_startCleanup() {
+      this.messageHandler.send('Cleanup', null,
+        function endCleanup() {
+          for (var i = 0, ii = this.pageCache.length; i < ii; i++) {
+            var page = this.pageCache[i];
+            if (page) {
+              page.destroy();
+            }
+          }
+          this.commonObjs.clear();
+          FontLoader.clear();
+        }.bind(this)
+      );
+    }
+  };
+  return WorkerTransport;
+
+})();
+
+/**
+ * A PDF document and page is built of many objects. E.g. there are objects
+ * for fonts, images, rendering code and such. These objects might get processed
+ * inside of a worker. The `PDFObjects` implements some basic functions to
+ * manage these objects.
+ */
+var PDFObjects = (function PDFObjectsClosure() {
+  function PDFObjects() {
+    this.objs = {};
+  }
+
+  PDFObjects.prototype = {
+    /**
+     * Internal function.
+     * Ensures there is an object defined for `objId`.
+     */
+    ensureObj: function PDFObjects_ensureObj(objId) {
+      if (this.objs[objId])
+        return this.objs[objId];
+
+      var obj = {
+        promise: new LegacyPromise(),
+        data: null,
+        resolved: false
+      };
+      this.objs[objId] = obj;
+
+      return obj;
+    },
+
+    /**
+     * If called *without* callback, this returns the data of `objId` but the
+     * object needs to be resolved. If it isn't, this function throws.
+     *
+     * If called *with* a callback, the callback is called with the data of the
+     * object once the object is resolved. That means, if you call this
+     * function and the object is already resolved, the callback gets called
+     * right away.
+     */
+    get: function PDFObjects_get(objId, callback) {
+      // If there is a callback, then the get can be async and the object is
+      // not required to be resolved right now
+      if (callback) {
+        this.ensureObj(objId).promise.then(callback);
+        return null;
+      }
+
+      // If there isn't a callback, the user expects to get the resolved data
+      // directly.
+      var obj = this.objs[objId];
+
+      // If there isn't an object yet or the object isn't resolved, then the
+      // data isn't ready yet!
+      if (!obj || !obj.resolved)
+        error('Requesting object that isn\'t resolved yet ' + objId);
+
+      return obj.data;
+    },
+
+    /**
+     * Resolves the object `objId` with optional `data`.
+     */
+    resolve: function PDFObjects_resolve(objId, data) {
+      var obj = this.ensureObj(objId);
+
+      obj.resolved = true;
+      obj.data = data;
+      obj.promise.resolve(data);
+    },
+
+    isResolved: function PDFObjects_isResolved(objId) {
+      var objs = this.objs;
+
+      if (!objs[objId]) {
+        return false;
+      } else {
+        return objs[objId].resolved;
+      }
+    },
+
+    hasData: function PDFObjects_hasData(objId) {
+      return this.isResolved(objId);
+    },
+
+    /**
+     * Returns the data of `objId` if object exists, null otherwise.
+     */
+    getData: function PDFObjects_getData(objId) {
+      var objs = this.objs;
+      if (!objs[objId] || !objs[objId].resolved) {
+        return null;
+      } else {
+        return objs[objId].data;
+      }
+    },
+
+    clear: function PDFObjects_clear() {
+      this.objs = {};
+    }
+  };
+  return PDFObjects;
+})();
+
+var RenderTask = (function RenderTaskClosure() {
+  function RenderTask(internalRenderTask) {
+    this.internalRenderTask = internalRenderTask;
+    this.promise = new PDFJS.LegacyPromise();
+  }
+
+  /**
+   * Cancel the rendering task. If the task is curently rendering it will not be
+   * cancelled until graphics pauses with a timeout. The promise that this
+   * object extends will resolved when cancelled.
+   */
+  RenderTask.prototype.cancel = function RenderTask_cancel() {
+    this.internalRenderTask.cancel();
+  };
+
+  return RenderTask;
+})();
+
+var InternalRenderTask = (function InternalRenderTaskClosure() {
+
+  function InternalRenderTask(callback, params, objs, commonObjs, operatorList,
+                              pageNumber) {
+    this.callback = callback;
+    this.params = params;
+    this.objs = objs;
+    this.commonObjs = commonObjs;
+    this.operatorListIdx = null;
+    this.operatorList = operatorList;
+    this.pageNumber = pageNumber;
+    this.running = false;
+    this.graphicsReadyCallback = null;
+    this.graphicsReady = false;
+    this.cancelled = false;
+  }
+
+  InternalRenderTask.prototype = {
+
+    initalizeGraphics:
+        function InternalRenderTask_initalizeGraphics(transparency) {
+
+      if (this.cancelled) {
+        return;
+      }
+      if (PDFJS.pdfBug && 'StepperManager' in globalScope &&
+          globalScope.StepperManager.enabled) {
+        this.stepper = globalScope.StepperManager.create(this.pageNumber - 1);
+        this.stepper.init(this.operatorList);
+        this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
+      }
+
+      var params = this.params;
+      this.gfx = new CanvasGraphics(params.canvasContext, this.commonObjs,
+                                    this.objs, params.textLayer,
+                                    params.imageLayer);
+
+      this.gfx.beginDrawing(params.viewport, transparency);
+      this.operatorListIdx = 0;
+      this.graphicsReady = true;
+      if (this.graphicsReadyCallback) {
+        this.graphicsReadyCallback();
+      }
+    },
+
+    cancel: function InternalRenderTask_cancel() {
+      this.running = false;
+      this.cancelled = true;
+      this.callback('cancelled');
+    },
+
+    operatorListChanged: function InternalRenderTask_operatorListChanged() {
+      if (!this.graphicsReady) {
+        if (!this.graphicsReadyCallback) {
+          this.graphicsReadyCallback = this._continue.bind(this);
+        }
+        return;
+      }
+
+      if (this.stepper) {
+        this.stepper.updateOperatorList(this.operatorList);
+      }
+
+      if (this.running) {
+        return;
+      }
+      this._continue();
+    },
+
+    _continue: function InternalRenderTask__continue() {
+      this.running = true;
+      if (this.cancelled) {
+        return;
+      }
+      if (this.params.continueCallback) {
+        this.params.continueCallback(this._next.bind(this));
+      } else {
+        this._next();
+      }
+    },
+
+    _next: function InternalRenderTask__next() {
+      if (this.cancelled) {
+        return;
+      }
+      this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList,
+                                        this.operatorListIdx,
+                                        this._continue.bind(this),
+                                        this.stepper);
+      if (this.operatorListIdx === this.operatorList.argsArray.length) {
+        this.running = false;
+        if (this.operatorList.lastChunk) {
+          this.gfx.endDrawing();
+          this.callback();
+        }
+      }
+    }
+
+  };
+
+  return InternalRenderTask;
+})();
+
+
+var Metadata = PDFJS.Metadata = (function MetadataClosure() {
+  function fixMetadata(meta) {
+    return meta.replace(/>\\376\\377([^<]+)/g, function(all, codes) {
+      var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g,
+                                function(code, d1, d2, d3) {
+        return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
+      });
+      var chars = '';
+      for (var i = 0; i < bytes.length; i += 2) {
+        var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
+        chars += code >= 32 && code < 127 && code != 60 && code != 62 &&
+          code != 38 && false ? String.fromCharCode(code) :
+          '&#x' + (0x10000 + code).toString(16).substring(1) + ';';
+      }
+      return '>' + chars;
+    });
+  }
+
+  function Metadata(meta) {
+    if (typeof meta === 'string') {
+      // Ghostscript produces invalid metadata
+      meta = fixMetadata(meta);
+
+      var parser = new DOMParser();
+      meta = parser.parseFromString(meta, 'application/xml');
+    } else if (!(meta instanceof Document)) {
+      error('Metadata: Invalid metadata object');
+    }
+
+    this.metaDocument = meta;
+    this.metadata = {};
+    this.parse();
+  }
+
+  Metadata.prototype = {
+    parse: function Metadata_parse() {
+      var doc = this.metaDocument;
+      var rdf = doc.documentElement;
+
+      if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in <xmpmeta>
+        rdf = rdf.firstChild;
+        while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf')
+          rdf = rdf.nextSibling;
+      }
+
+      var nodeName = (rdf) ? rdf.nodeName.toLowerCase() : null;
+      if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes())
+        return;
+
+      var children = rdf.childNodes, desc, entry, name, i, ii, length, iLength;
+
+      for (i = 0, length = children.length; i < length; i++) {
+        desc = children[i];
+        if (desc.nodeName.toLowerCase() !== 'rdf:description')
+          continue;
+
+        for (ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) {
+          if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text') {
+            entry = desc.childNodes[ii];
+            name = entry.nodeName.toLowerCase();
+            this.metadata[name] = entry.textContent.trim();
+          }
+        }
+      }
+    },
+
+    get: function Metadata_get(name) {
+      return this.metadata[name] || null;
+    },
+
+    has: function Metadata_has(name) {
+      return typeof this.metadata[name] !== 'undefined';
+    }
+  };
+
+  return Metadata;
+})();
+
+
+// <canvas> contexts store most of the state we need natively.
+// However, PDF needs a bit more state, which we store here.
+
+// Minimal font size that would be used during canvas fillText operations.
+var MIN_FONT_SIZE = 16;
+
+var COMPILE_TYPE3_GLYPHS = true;
+
+function createScratchCanvas(width, height) {
+  var canvas = document.createElement('canvas');
+  canvas.width = width;
+  canvas.height = height;
+  return canvas;
+}
+
+function addContextCurrentTransform(ctx) {
+  // If the context doesn't expose a `mozCurrentTransform`, add a JS based on.
+  if (!ctx.mozCurrentTransform) {
+    // Store the original context
+    ctx._scaleX = ctx._scaleX || 1.0;
+    ctx._scaleY = ctx._scaleY || 1.0;
+    ctx._originalSave = ctx.save;
+    ctx._originalRestore = ctx.restore;
+    ctx._originalRotate = ctx.rotate;
+    ctx._originalScale = ctx.scale;
+    ctx._originalTranslate = ctx.translate;
+    ctx._originalTransform = ctx.transform;
+    ctx._originalSetTransform = ctx.setTransform;
+
+    ctx._transformMatrix = [ctx._scaleX, 0, 0, ctx._scaleY, 0, 0];
+    ctx._transformStack = [];
+
+    Object.defineProperty(ctx, 'mozCurrentTransform', {
+      get: function getCurrentTransform() {
+        return this._transformMatrix;
+      }
+    });
+
+    Object.defineProperty(ctx, 'mozCurrentTransformInverse', {
+      get: function getCurrentTransformInverse() {
+        // Calculation done using WolframAlpha:
+        // http://www.wolframalpha.com/input/?
+        //   i=Inverse+{{a%2C+c%2C+e}%2C+{b%2C+d%2C+f}%2C+{0%2C+0%2C+1}}
+
+        var m = this._transformMatrix;
+        var a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5];
+
+        var ad_bc = a * d - b * c;
+        var bc_ad = b * c - a * d;
+
+        return [
+          d / ad_bc,
+          b / bc_ad,
+          c / bc_ad,
+          a / ad_bc,
+          (d * e - c * f) / bc_ad,
+          (b * e - a * f) / ad_bc
+        ];
+      }
+    });
+
+    ctx.save = function ctxSave() {
+      var old = this._transformMatrix;
+      this._transformStack.push(old);
+      this._transformMatrix = old.slice(0, 6);
+
+      this._originalSave();
+    };
+
+    ctx.restore = function ctxRestore() {
+      var prev = this._transformStack.pop();
+      if (prev) {
+        this._transformMatrix = prev;
+        this._originalRestore();
+      }
+    };
+
+    ctx.translate = function ctxTranslate(x, y) {
+      var m = this._transformMatrix;
+      m[4] = m[0] * x + m[2] * y + m[4];
+      m[5] = m[1] * x + m[3] * y + m[5];
+
+      this._originalTranslate(x, y);
+    };
+
+    ctx.scale = function ctxScale(x, y) {
+      var m = this._transformMatrix;
+      m[0] = m[0] * x;
+      m[1] = m[1] * x;
+      m[2] = m[2] * y;
+      m[3] = m[3] * y;
+
+      this._originalScale(x, y);
+    };
+
+    ctx.transform = function ctxTransform(a, b, c, d, e, f) {
+      var m = this._transformMatrix;
+      this._transformMatrix = [
+        m[0] * a + m[2] * b,
+        m[1] * a + m[3] * b,
+        m[0] * c + m[2] * d,
+        m[1] * c + m[3] * d,
+        m[0] * e + m[2] * f + m[4],
+        m[1] * e + m[3] * f + m[5]
+      ];
+
+      ctx._originalTransform(a, b, c, d, e, f);
+    };
+
+    ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) {
+      this._transformMatrix = [a, b, c, d, e, f];
+
+      ctx._originalSetTransform(a, b, c, d, e, f);
+    };
+
+    ctx.rotate = function ctxRotate(angle) {
+      var cosValue = Math.cos(angle);
+      var sinValue = Math.sin(angle);
+
+      var m = this._transformMatrix;
+      this._transformMatrix = [
+        m[0] * cosValue + m[2] * sinValue,
+        m[1] * cosValue + m[3] * sinValue,
+        m[0] * (-sinValue) + m[2] * cosValue,
+        m[1] * (-sinValue) + m[3] * cosValue,
+        m[4],
+        m[5]
+      ];
+
+      this._originalRotate(angle);
+    };
+  }
+}
+
+var CachedCanvases = (function CachedCanvasesClosure() {
+  var cache = {};
+  return {
+    getCanvas: function CachedCanvases_getCanvas(id, width, height,
+                                                 trackTransform) {
+      var canvasEntry;
+      if (id in cache) {
+        canvasEntry = cache[id];
+        canvasEntry.canvas.width = width;
+        canvasEntry.canvas.height = height;
+        // reset canvas transform for emulated mozCurrentTransform, if needed
+        canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0);
+      } else {
+        var canvas = createScratchCanvas(width, height);
+        var ctx = canvas.getContext('2d');
+        if (trackTransform) {
+          addContextCurrentTransform(ctx);
+        }
+        cache[id] = canvasEntry = {canvas: canvas, context: ctx};
+      }
+      return canvasEntry;
+    },
+    clear: function () {
+      cache = {};
+    }
+  };
+})();
+
+function compileType3Glyph(imgData) {
+  var POINT_TO_PROCESS_LIMIT = 1000;
+
+  var width = imgData.width, height = imgData.height;
+  var i, j, j0, width1 = width + 1;
+  var points = new Uint8Array(width1 * (height + 1));
+  var POINT_TYPES =
+      new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]);
+
+  // 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) {
+    points[0] = 1;
+    ++count;
+  }
+  for (j = 1; j < width; j++) {
+    if (data[pos] !== data[pos + 1]) {
+      points[j] = data[pos] ? 2 : 1;
+      ++count;
+    }
+    pos++;
+  }
+  if (data[pos] !== 0) {
+    points[j] = 2;
+    ++count;
+  }
+  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);
+      if (POINT_TYPES[sum]) {
+        points[j0 + j] = POINT_TYPES[sum];
+        ++count;
+      }
+      pos++;
+    }
+    if (data[pos - lineSize] !== data[pos]) {
+      points[j0 + j] = data[pos] ? 2 : 4;
+      ++count;
+    }
+
+    if (count > POINT_TO_PROCESS_LIMIT) {
+      return null;
+    }
+  }
+
+  pos = lineSize * (height - 1);
+  j0 = i * width1;
+  if (data[pos] !== 0) {
+    points[j0] = 8;
+    ++count;
+  }
+  for (j = 1; j < width; j++) {
+    if (data[pos] !== data[pos + 1]) {
+      points[j0 + j] = data[pos] ? 4 : 8;
+      ++count;
+    }
+    pos++;
+  }
+  if (data[pos] !== 0) {
+    points[j0 + j] = 4;
+    ++count;
+  }
+  if (count > POINT_TO_PROCESS_LIMIT) {
+    return null;
+  }
+
+  // building outlines
+  var steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]);
+  var outlines = [];
+  for (i = 0; count && i <= height; i++) {
+    var p = i * width1;
+    var end = p + width;
+    while (p < end && !points[p]) {
+      p++;
+    }
+    if (p === end) {
+      continue;
+    }
+    var coords = [p % width1, i];
+
+    var type = points[p], p0 = p, pp;
+    do {
+      var step = steps[type];
+      do { p += step; } while (!points[p]);
+
+      pp = points[p];
+      if (pp !== 5 && pp !== 10) {
+        // set new direction
+        type = pp;
+        // delete mark
+        points[p] = 0;
+      } else { // type is 5 or 10, ie, a crossing
+        // set new direction
+        type = pp & ((0x33 * type) >> 4);
+        // set new type for "future hit"
+        points[p] &= (type >> 2 | type << 2);
+      }
+
+      coords.push(p % width1);
+      coords.push((p / width1) | 0);
+      --count;
+    } while (p0 !== p);
+    outlines.push(coords);
+    --i;
+  }
+
+  var drawOutline = function(c) {
+    c.save();
+    // the path shall be painted in [0..1]x[0..1] space
+    c.scale(1 / width, -1 / height);
+    c.translate(0, -height);
+    c.beginPath();
+    for (var i = 0, ii = outlines.length; i < ii; i++) {
+      var o = outlines[i];
+      c.moveTo(o[0], o[1]);
+      for (var j = 2, jj = o.length; j < jj; j += 2) {
+        c.lineTo(o[j], o[j+1]);
+      }
+    }
+    c.fill();
+    c.beginPath();
+    c.restore();
+  };
+
+  return drawOutline;
+}
+
+var CanvasExtraState = (function CanvasExtraStateClosure() {
+  function CanvasExtraState(old) {
+    // Are soft masks and alpha values shapes or opacities?
+    this.alphaIsShape = false;
+    this.fontSize = 0;
+    this.fontSizeScale = 1;
+    this.textMatrix = IDENTITY_MATRIX;
+    this.fontMatrix = FONT_IDENTITY_MATRIX;
+    this.leading = 0;
+    // Current point (in user coordinates)
+    this.x = 0;
+    this.y = 0;
+    // Start of text line (in text coordinates)
+    this.lineX = 0;
+    this.lineY = 0;
+    // Character and word spacing
+    this.charSpacing = 0;
+    this.wordSpacing = 0;
+    this.textHScale = 1;
+    this.textRenderingMode = TextRenderingMode.FILL;
+    this.textRise = 0;
+    // Color spaces
+    this.fillColorSpace = ColorSpace.singletons.gray;
+    this.fillColorSpaceObj = null;
+    this.strokeColorSpace = ColorSpace.singletons.gray;
+    this.strokeColorSpaceObj = null;
+    this.fillColorObj = null;
+    this.strokeColorObj = null;
+    // Default fore and background colors
+    this.fillColor = '#000000';
+    this.strokeColor = '#000000';
+    // Note: fill alpha applies to all non-stroking operations
+    this.fillAlpha = 1;
+    this.strokeAlpha = 1;
+    this.lineWidth = 1;
+
+    this.old = old;
+  }
+
+  CanvasExtraState.prototype = {
+    clone: function CanvasExtraState_clone() {
+      return Object.create(this);
+    },
+    setCurrentPoint: function CanvasExtraState_setCurrentPoint(x, y) {
+      this.x = x;
+      this.y = y;
+    }
+  };
+  return CanvasExtraState;
+})();
+
+var CanvasGraphics = (function CanvasGraphicsClosure() {
+  // Defines the time the executeOperatorList is going to be executing
+  // before it stops and shedules a continue of execution.
+  var EXECUTION_TIME = 15;
+
+  function CanvasGraphics(canvasCtx, commonObjs, objs, textLayer, imageLayer) {
+    this.ctx = canvasCtx;
+    this.current = new CanvasExtraState();
+    this.stateStack = [];
+    this.pendingClip = null;
+    this.pendingEOFill = false;
+    this.res = null;
+    this.xobjs = null;
+    this.commonObjs = commonObjs;
+    this.objs = objs;
+    this.textLayer = textLayer;
+    this.imageLayer = imageLayer;
+    this.groupStack = [];
+    this.processingType3 = null;
+    // Patterns are painted relative to the initial page/form transform, see pdf
+    // spec 8.7.2 NOTE 1.
+    this.baseTransform = null;
+    this.baseTransformStack = [];
+    this.groupLevel = 0;
+    if (canvasCtx) {
+      addContextCurrentTransform(canvasCtx);
+    }
+  }
+
+  function putBinaryImageData(ctx, imgData) {
+    if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) {
+      ctx.putImageData(imgData, 0, 0);
+      return;
+    }
+
+    // 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 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;
+      }
+    }
+
+    ctx.putImageData(tmpImgData, 0, 0);
+  }
+
+  function copyCtxState(sourceCtx, destCtx) {
+    var properties = ['strokeStyle', 'fillStyle', 'fillRule', 'globalAlpha',
+                      'lineWidth', 'lineCap', 'lineJoin', 'miterLimit',
+                      'globalCompositeOperation', 'font'];
+    for (var i = 0, ii = properties.length; i < ii; i++) {
+      var property = properties[i];
+      if (property in sourceCtx) {
+        destCtx[property] = sourceCtx[property];
+      }
+    }
+    if ('setLineDash' in sourceCtx) {
+      destCtx.setLineDash(sourceCtx.getLineDash());
+      destCtx.lineDashOffset =  sourceCtx.lineDashOffset;
+    } else if ('mozDash' in sourceCtx) {
+      destCtx.mozDash = sourceCtx.mozDash;
+      destCtx.mozDashOffset = sourceCtx.mozDashOffset;
+    }
+  }
+
+  var LINE_CAP_STYLES = ['butt', 'round', 'square'];
+  var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
+  var NORMAL_CLIP = {};
+  var EO_CLIP = {};
+
+  CanvasGraphics.prototype = {
+
+    beginDrawing: function CanvasGraphics_beginDrawing(viewport, transparency) {
+      // For pdfs that use blend modes we have to clear the canvas else certain
+      // blend modes can look wrong since we'd be blending with a white
+      // backdrop. The problem with a transparent backdrop though is we then
+      // don't get sub pixel anti aliasing on text, so we fill with white if
+      // we can.
+      var width = this.ctx.canvas.width;
+      var height = this.ctx.canvas.height;
+      if (transparency) {
+        this.ctx.clearRect(0, 0, width, height);
+      } else {
+        this.ctx.mozOpaque = true;
+        this.ctx.save();
+        this.ctx.fillStyle = 'rgb(255, 255, 255)';
+        this.ctx.fillRect(0, 0, width, height);
+        this.ctx.restore();
+      }
+
+      var transform = viewport.transform;
+      this.baseTransform = transform.slice();
+      this.ctx.save();
+      this.ctx.transform.apply(this.ctx, transform);
+
+      if (this.textLayer) {
+        this.textLayer.beginLayout();
+      }
+      if (this.imageLayer) {
+        this.imageLayer.beginLayout();
+      }
+    },
+
+    executeOperatorList: function CanvasGraphics_executeOperatorList(
+                                    operatorList,
+                                    executionStartIdx, continueCallback,
+                                    stepper) {
+      var argsArray = operatorList.argsArray;
+      var fnArray = operatorList.fnArray;
+      var i = executionStartIdx || 0;
+      var argsArrayLen = argsArray.length;
+
+      // Sometimes the OperatorList to execute is empty.
+      if (argsArrayLen == i) {
+        return i;
+      }
+
+      var executionEndIdx;
+      var endTime = Date.now() + EXECUTION_TIME;
+
+      var commonObjs = this.commonObjs;
+      var objs = this.objs;
+      var fnId;
+      var deferred = Promise.resolve();
+
+      while (true) {
+        if (stepper && i === stepper.nextBreakPoint) {
+          stepper.breakIt(i, continueCallback);
+          return i;
+        }
+
+        fnId = fnArray[i];
+
+        if (fnId !== OPS.dependency) {
+          this[fnId].apply(this, argsArray[i]);
+        } else {
+          var deps = argsArray[i];
+          for (var n = 0, nn = deps.length; n < nn; n++) {
+            var depObjId = deps[n];
+            var common = depObjId.substring(0, 2) == 'g_';
+
+            // If the promise isn't resolved yet, add the continueCallback
+            // to the promise and bail out.
+            if (!common && !objs.isResolved(depObjId)) {
+              objs.get(depObjId, continueCallback);
+              return i;
+            }
+            if (common && !commonObjs.isResolved(depObjId)) {
+              commonObjs.get(depObjId, continueCallback);
+              return i;
+            }
+          }
+        }
+
+        i++;
+
+        // If the entire operatorList was executed, stop as were done.
+        if (i == argsArrayLen) {
+          return i;
+        }
+
+        // If the execution took longer then a certain amount of time, schedule
+        // to continue exeution after a short delay.
+        // However, this is only possible if a 'continueCallback' is passed in.
+        if (continueCallback && Date.now() > endTime) {
+          deferred.then(continueCallback);
+          return i;
+        }
+
+        // If the operatorList isn't executed completely yet OR the execution
+        // time was short enough, do another execution round.
+      }
+    },
+
+    endDrawing: function CanvasGraphics_endDrawing() {
+      this.ctx.restore();
+      CachedCanvases.clear();
+
+      if (this.textLayer) {
+        this.textLayer.endLayout();
+      }
+      if (this.imageLayer) {
+        this.imageLayer.endLayout();
+      }
+    },
+
+    // Graphics state
+    setLineWidth: function CanvasGraphics_setLineWidth(width) {
+      this.current.lineWidth = width;
+      this.ctx.lineWidth = width;
+    },
+    setLineCap: function CanvasGraphics_setLineCap(style) {
+      this.ctx.lineCap = LINE_CAP_STYLES[style];
+    },
+    setLineJoin: function CanvasGraphics_setLineJoin(style) {
+      this.ctx.lineJoin = LINE_JOIN_STYLES[style];
+    },
+    setMiterLimit: function CanvasGraphics_setMiterLimit(limit) {
+      this.ctx.miterLimit = limit;
+    },
+    setDash: function CanvasGraphics_setDash(dashArray, dashPhase) {
+      var ctx = this.ctx;
+      if ('setLineDash' in ctx) {
+        ctx.setLineDash(dashArray);
+        ctx.lineDashOffset = dashPhase;
+      } else {
+        ctx.mozDash = dashArray;
+        ctx.mozDashOffset = dashPhase;
+      }
+    },
+    setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) {
+      // Maybe if we one day fully support color spaces this will be important
+      // for now we can ignore.
+      // TODO set rendering intent?
+    },
+    setFlatness: function CanvasGraphics_setFlatness(flatness) {
+      // There's no way to control this with canvas, but we can safely ignore.
+      // TODO set flatness?
+    },
+    setGState: function CanvasGraphics_setGState(states) {
+      for (var i = 0, ii = states.length; i < ii; i++) {
+        var state = states[i];
+        var key = state[0];
+        var value = state[1];
+
+        switch (key) {
+          case 'LW':
+            this.setLineWidth(value);
+            break;
+          case 'LC':
+            this.setLineCap(value);
+            break;
+          case 'LJ':
+            this.setLineJoin(value);
+            break;
+          case 'ML':
+            this.setMiterLimit(value);
+            break;
+          case 'D':
+            this.setDash(value[0], value[1]);
+            break;
+          case 'RI':
+            this.setRenderingIntent(value);
+            break;
+          case 'FL':
+            this.setFlatness(value);
+            break;
+          case 'Font':
+            this.setFont(value[0], value[1]);
+            break;
+          case 'CA':
+            this.current.strokeAlpha = state[1];
+            break;
+          case 'ca':
+            this.current.fillAlpha = state[1];
+            this.ctx.globalAlpha = state[1];
+            break;
+          case 'BM':
+            if (value && value.name && (value.name !== 'Normal')) {
+              var mode = value.name.replace(/([A-Z])/g,
+                function(c) {
+                  return '-' + c.toLowerCase();
+                }
+              ).substring(1);
+              this.ctx.globalCompositeOperation = mode;
+              if (this.ctx.globalCompositeOperation !== mode) {
+                warn('globalCompositeOperation "' + mode +
+                     '" is not supported');
+              }
+            } else {
+              this.ctx.globalCompositeOperation = 'source-over';
+            }
+            break;
+        }
+      }
+    },
+    save: function CanvasGraphics_save() {
+      this.ctx.save();
+      var old = this.current;
+      this.stateStack.push(old);
+      this.current = old.clone();
+    },
+    restore: function CanvasGraphics_restore() {
+      var prev = this.stateStack.pop();
+      if (prev) {
+        this.current = prev;
+        this.ctx.restore();
+      }
+    },
+    transform: function CanvasGraphics_transform(a, b, c, d, e, f) {
+      this.ctx.transform(a, b, c, d, e, f);
+    },
+
+    // Path
+    moveTo: function CanvasGraphics_moveTo(x, y) {
+      this.ctx.moveTo(x, y);
+      this.current.setCurrentPoint(x, y);
+    },
+    lineTo: function CanvasGraphics_lineTo(x, y) {
+      this.ctx.lineTo(x, y);
+      this.current.setCurrentPoint(x, y);
+    },
+    curveTo: function CanvasGraphics_curveTo(x1, y1, x2, y2, x3, y3) {
+      this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
+      this.current.setCurrentPoint(x3, y3);
+    },
+    curveTo2: function CanvasGraphics_curveTo2(x2, y2, x3, y3) {
+      var current = this.current;
+      this.ctx.bezierCurveTo(current.x, current.y, x2, y2, x3, y3);
+      current.setCurrentPoint(x3, y3);
+    },
+    curveTo3: function CanvasGraphics_curveTo3(x1, y1, x3, y3) {
+      this.curveTo(x1, y1, x3, y3, x3, y3);
+      this.current.setCurrentPoint(x3, y3);
+    },
+    closePath: function CanvasGraphics_closePath() {
+      this.ctx.closePath();
+    },
+    rectangle: function CanvasGraphics_rectangle(x, y, width, height) {
+      this.ctx.rect(x, y, width, height);
+    },
+    stroke: function CanvasGraphics_stroke(consumePath) {
+      consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
+      var ctx = this.ctx;
+      var strokeColor = this.current.strokeColor;
+      if (this.current.lineWidth === 0)
+        ctx.lineWidth = this.getSinglePixelWidth();
+      // For stroke we want to temporarily change the global alpha to the
+      // stroking alpha.
+      ctx.globalAlpha = this.current.strokeAlpha;
+      if (strokeColor && strokeColor.hasOwnProperty('type') &&
+          strokeColor.type === 'Pattern') {
+        // for patterns, we transform to pattern space, calculate
+        // the pattern, call stroke, and restore to user space
+        ctx.save();
+        ctx.strokeStyle = strokeColor.getPattern(ctx, this);
+        ctx.stroke();
+        ctx.restore();
+      } else {
+        ctx.stroke();
+      }
+      if (consumePath)
+        this.consumePath();
+      // Restore the global alpha to the fill alpha
+      ctx.globalAlpha = this.current.fillAlpha;
+    },
+    closeStroke: function CanvasGraphics_closeStroke() {
+      this.closePath();
+      this.stroke();
+    },
+    fill: function CanvasGraphics_fill(consumePath) {
+      consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
+      var ctx = this.ctx;
+      var fillColor = this.current.fillColor;
+      var needRestore = false;
+
+      if (fillColor && fillColor.hasOwnProperty('type') &&
+          fillColor.type === 'Pattern') {
+        ctx.save();
+        ctx.fillStyle = fillColor.getPattern(ctx, this);
+        needRestore = true;
+      }
+
+      if (this.pendingEOFill) {
+        if ('mozFillRule' in this.ctx) {
+          this.ctx.mozFillRule = 'evenodd';
+          this.ctx.fill();
+          this.ctx.mozFillRule = 'nonzero';
+        } else {
+          try {
+            this.ctx.fill('evenodd');
+          } catch (ex) {
+            // shouldn't really happen, but browsers might think differently
+            this.ctx.fill();
+          }
+        }
+        this.pendingEOFill = false;
+      } else {
+        this.ctx.fill();
+      }
+
+      if (needRestore) {
+        ctx.restore();
+      }
+      if (consumePath) {
+        this.consumePath();
+      }
+    },
+    eoFill: function CanvasGraphics_eoFill() {
+      this.pendingEOFill = true;
+      this.fill();
+    },
+    fillStroke: function CanvasGraphics_fillStroke() {
+      this.fill(false);
+      this.stroke(false);
+
+      this.consumePath();
+    },
+    eoFillStroke: function CanvasGraphics_eoFillStroke() {
+      this.pendingEOFill = true;
+      this.fillStroke();
+    },
+    closeFillStroke: function CanvasGraphics_closeFillStroke() {
+      this.closePath();
+      this.fillStroke();
+    },
+    closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() {
+      this.pendingEOFill = true;
+      this.closePath();
+      this.fillStroke();
+    },
+    endPath: function CanvasGraphics_endPath() {
+      this.consumePath();
+    },
+
+    // Clipping
+    clip: function CanvasGraphics_clip() {
+      this.pendingClip = NORMAL_CLIP;
+    },
+    eoClip: function CanvasGraphics_eoClip() {
+      this.pendingClip = EO_CLIP;
+    },
+
+    // Text
+    beginText: function CanvasGraphics_beginText() {
+      this.current.textMatrix = IDENTITY_MATRIX;
+      this.current.x = this.current.lineX = 0;
+      this.current.y = this.current.lineY = 0;
+    },
+    endText: function CanvasGraphics_endText() {
+      if (!('pendingTextPaths' in this)) {
+        this.ctx.beginPath();
+        return;
+      }
+      var paths = this.pendingTextPaths;
+      var ctx = this.ctx;
+
+      ctx.save();
+      ctx.beginPath();
+      for (var i = 0; i < paths.length; i++) {
+        var path = paths[i];
+        ctx.setTransform.apply(ctx, path.transform);
+        ctx.translate(path.x, path.y);
+        path.addToPath(ctx, path.fontSize);
+      }
+      ctx.restore();
+      ctx.clip();
+      ctx.beginPath();
+      delete this.pendingTextPaths;
+    },
+    setCharSpacing: function CanvasGraphics_setCharSpacing(spacing) {
+      this.current.charSpacing = spacing;
+    },
+    setWordSpacing: function CanvasGraphics_setWordSpacing(spacing) {
+      this.current.wordSpacing = spacing;
+    },
+    setHScale: function CanvasGraphics_setHScale(scale) {
+      this.current.textHScale = scale / 100;
+    },
+    setLeading: function CanvasGraphics_setLeading(leading) {
+      this.current.leading = -leading;
+    },
+    setFont: function CanvasGraphics_setFont(fontRefName, size) {
+      var fontObj = this.commonObjs.get(fontRefName);
+      var current = this.current;
+
+      if (!fontObj)
+        error('Can\'t find font for ' + fontRefName);
+
+      current.fontMatrix = fontObj.fontMatrix ? fontObj.fontMatrix :
+                                                FONT_IDENTITY_MATRIX;
+
+      // A valid matrix needs all main diagonal elements to be non-zero
+      // This also ensures we bypass FF bugzilla bug #719844.
+      if (current.fontMatrix[0] === 0 ||
+          current.fontMatrix[3] === 0) {
+        warn('Invalid font matrix for font ' + fontRefName);
+      }
+
+      // The spec for Tf (setFont) says that 'size' specifies the font 'scale',
+      // and in some docs this can be negative (inverted x-y axes).
+      if (size < 0) {
+        size = -size;
+        current.fontDirection = -1;
+      } else {
+        current.fontDirection = 1;
+      }
+
+      this.current.font = fontObj;
+      this.current.fontSize = size;
+
+      if (fontObj.coded)
+        return; // we don't need ctx.font for Type3 fonts
+
+      var name = fontObj.loadedName || 'sans-serif';
+      var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') :
+                                 (fontObj.bold ? 'bold' : 'normal');
+
+      var italic = fontObj.italic ? 'italic' : 'normal';
+      var typeface = '"' + name + '", ' + fontObj.fallbackName;
+
+      // Some font backends cannot handle fonts below certain size.
+      // Keeping the font at minimal size and using the fontSizeScale to change
+      // the current transformation matrix before the fillText/strokeText.
+      // See https://bugzilla.mozilla.org/show_bug.cgi?id=726227
+      var browserFontSize = size >= MIN_FONT_SIZE ? size : MIN_FONT_SIZE;
+      this.current.fontSizeScale = browserFontSize != MIN_FONT_SIZE ? 1.0 :
+                                   size / MIN_FONT_SIZE;
+
+      var rule = italic + ' ' + bold + ' ' + browserFontSize + 'px ' + typeface;
+      this.ctx.font = rule;
+    },
+    setTextRenderingMode: function CanvasGraphics_setTextRenderingMode(mode) {
+      this.current.textRenderingMode = mode;
+    },
+    setTextRise: function CanvasGraphics_setTextRise(rise) {
+      this.current.textRise = rise;
+    },
+    moveText: function CanvasGraphics_moveText(x, y) {
+      this.current.x = this.current.lineX += x;
+      this.current.y = this.current.lineY += y;
+    },
+    setLeadingMoveText: function CanvasGraphics_setLeadingMoveText(x, y) {
+      this.setLeading(-y);
+      this.moveText(x, y);
+    },
+    setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) {
+      this.current.textMatrix = [a, b, c, d, e, f];
+
+      this.current.x = this.current.lineX = 0;
+      this.current.y = this.current.lineY = 0;
+    },
+    nextLine: function CanvasGraphics_nextLine() {
+      this.moveText(0, this.current.leading);
+    },
+    applyTextTransforms: function CanvasGraphics_applyTextTransforms() {
+      var ctx = this.ctx;
+      var current = this.current;
+      ctx.transform.apply(ctx, current.textMatrix);
+      ctx.translate(current.x, current.y + current.textRise);
+      if (current.fontDirection > 0) {
+        ctx.scale(current.textHScale, -1);
+      } else {
+        ctx.scale(-current.textHScale, 1);
+      }
+    },
+    createTextGeometry: function CanvasGraphics_createTextGeometry() {
+      var geometry = {};
+      var ctx = this.ctx;
+      var font = this.current.font;
+      var ctxMatrix = ctx.mozCurrentTransform;
+      var a = ctxMatrix[0], b = ctxMatrix[1], c = ctxMatrix[2];
+      var d = ctxMatrix[3], e = ctxMatrix[4], f = ctxMatrix[5];
+      var sx = (a >= 0) ?
+          Math.sqrt((a * a) + (b * b)) : -Math.sqrt((a * a) + (b * b));
+      var sy = (d >= 0) ?
+          Math.sqrt((c * c) + (d * d)) : -Math.sqrt((c * c) + (d * d));
+      var angle = Math.atan2(b, a);
+      var x = e;
+      var y = f;
+      geometry.x = x;
+      geometry.y = y;
+      geometry.hScale = sx;
+      geometry.vScale = sy;
+      geometry.angle = angle;
+      geometry.spaceWidth = font.spaceWidth;
+      geometry.fontName = font.loadedName;
+      geometry.fontFamily = font.fallbackName;
+      geometry.fontSize = this.current.fontSize;
+      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;
+      var textRenderingMode = current.textRenderingMode;
+      var fillStrokeMode = textRenderingMode &
+        TextRenderingMode.FILL_STROKE_MASK;
+      var isAddToPathSet = !!(textRenderingMode &
+        TextRenderingMode.ADD_TO_PATH_FLAG);
+
+      var addToPath;
+      if (font.disableFontFace || isAddToPathSet) {
+        addToPath = font.getPathGenerator(this.commonObjs, character);
+      }
+
+      if (font.disableFontFace) {
+        ctx.save();
+        ctx.translate(x, y);
+        ctx.beginPath();
+        addToPath(ctx, fontSize);
+        if (fillStrokeMode === TextRenderingMode.FILL ||
+            fillStrokeMode === TextRenderingMode.FILL_STROKE) {
+          ctx.fill();
+        }
+        if (fillStrokeMode === TextRenderingMode.STROKE ||
+            fillStrokeMode === TextRenderingMode.FILL_STROKE) {
+          ctx.stroke();
+        }
+        ctx.restore();
+      } else {
+        if (fillStrokeMode === TextRenderingMode.FILL ||
+            fillStrokeMode === TextRenderingMode.FILL_STROKE) {
+          ctx.fillText(character, x, y);
+        }
+        if (fillStrokeMode === TextRenderingMode.STROKE ||
+            fillStrokeMode === TextRenderingMode.FILL_STROKE) {
+          ctx.strokeText(character, x, y);
+        }
+      }
+
+      if (isAddToPathSet) {
+        var paths = this.pendingTextPaths || (this.pendingTextPaths = []);
+        paths.push({
+          transform: ctx.mozCurrentTransform,
+          x: x,
+          y: y,
+          fontSize: fontSize,
+          addToPath: addToPath
+        });
+      }
+    },
+
+    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;
+      var textHScale = current.textHScale * current.fontDirection;
+      var fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX;
+      var glyphsLength = glyphs.length;
+      var textLayer = this.textLayer;
+      var geom;
+      var textSelection = textLayer && !skipTextSelection ? true : false;
+      var canvasWidth = 0.0;
+      var vertical = font.vertical;
+      var defaultVMetrics = font.defaultVMetrics;
+
+      // Type3 fonts - each glyph is a "mini-PDF"
+      if (font.coded) {
+        ctx.save();
+        ctx.transform.apply(ctx, current.textMatrix);
+        ctx.translate(current.x, current.y);
+
+        ctx.scale(textHScale, 1);
+
+        if (textSelection) {
+          this.save();
+          ctx.scale(1, -1);
+          geom = this.createTextGeometry();
+          this.restore();
+        }
+        for (var i = 0; i < glyphsLength; ++i) {
+
+          var glyph = glyphs[i];
+          if (glyph === null) {
+            // word break
+            this.ctx.translate(wordSpacing, 0);
+            current.x += wordSpacing * textHScale;
+            continue;
+          }
+
+          this.processingType3 = glyph;
+          this.save();
+          ctx.scale(fontSize, fontSize);
+          ctx.transform.apply(ctx, fontMatrix);
+          this.executeOperatorList(glyph.operatorList);
+          this.restore();
+
+          var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
+          var width = (transformed[0] * fontSize + charSpacing) *
+                      current.fontDirection;
+
+          ctx.translate(width, 0);
+          current.x += width * textHScale;
+
+          canvasWidth += width;
+        }
+        ctx.restore();
+        this.processingType3 = null;
+      } else {
+        ctx.save();
+        this.applyTextTransforms();
+
+        var lineWidth = current.lineWidth;
+        var a1 = current.textMatrix[0], b1 = current.textMatrix[1];
+        var scale = Math.sqrt(a1 * a1 + b1 * b1);
+        if (scale === 0 || lineWidth === 0)
+          lineWidth = this.getSinglePixelWidth();
+        else
+          lineWidth /= scale;
+
+        if (textSelection)
+          geom = this.createTextGeometry();
+
+        if (fontSizeScale != 1.0) {
+          ctx.scale(fontSizeScale, fontSizeScale);
+          lineWidth /= fontSizeScale;
+        }
+
+        ctx.lineWidth = lineWidth;
+
+        var x = 0;
+        for (var i = 0; i < glyphsLength; ++i) {
+          var glyph = glyphs[i];
+          if (glyph === null) {
+            // word break
+            x += current.fontDirection * wordSpacing;
+            continue;
+          }
+
+          var restoreNeeded = false;
+          var character = glyph.fontChar;
+          var vmetric = glyph.vmetric || defaultVMetrics;
+          if (vertical) {
+            var vx = glyph.vmetric ? vmetric[1] : glyph.width * 0.5;
+            vx = -vx * fontSize * current.fontMatrix[0];
+            var vy = vmetric[2] * fontSize * current.fontMatrix[0];
+          }
+          var width = vmetric ? -vmetric[0] : glyph.width;
+          var charWidth = width * fontSize * current.fontMatrix[0] +
+                          charSpacing * current.fontDirection;
+          var accent = glyph.accent;
+
+          var scaledX, scaledY, scaledAccentX, scaledAccentY;
+          if (!glyph.disabled) {
+            if (vertical) {
+              scaledX = vx / fontSizeScale;
+              scaledY = (x + vy) / fontSizeScale;
+            } else {
+              scaledX = x / fontSizeScale;
+              scaledY = 0;
+            }
+
+            if (font.remeasure && width > 0 && this.isFontSubpixelAAEnabled) {
+              // some standard fonts may not have the exact width, trying to
+              // rescale per character
+              var measuredWidth = ctx.measureText(character).width * 1000 /
+                current.fontSize * current.fontSizeScale;
+              var characterScaleX = width / measuredWidth;
+              restoreNeeded = true;
+              ctx.save();
+              ctx.scale(characterScaleX, 1);
+              scaledX /= characterScaleX;
+              if (accent) {
+                scaledAccentX /= characterScaleX;
+              }
+            }
+
+            this.paintChar(character, scaledX, scaledY);
+            if (accent) {
+              scaledAccentX = scaledX + accent.offset.x / fontSizeScale;
+              scaledAccentY = scaledY - accent.offset.y / fontSizeScale;
+              this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY);
+            }
+          }
+
+          x += charWidth;
+
+          canvasWidth += charWidth;
+
+          if (restoreNeeded) {
+            ctx.restore();
+          }
+        }
+        if (vertical) {
+          current.y -= x * textHScale;
+        } else {
+          current.x += x * textHScale;
+        }
+        ctx.restore();
+      }
+
+      if (textSelection) {
+        geom.canvasWidth = canvasWidth;
+        if (vertical) {
+          var VERTICAL_TEXT_ROTATION = Math.PI / 2;
+          geom.angle += VERTICAL_TEXT_ROTATION;
+        }
+        this.textLayer.appendText(geom);
+      }
+
+      return canvasWidth;
+    },
+    showSpacedText: function CanvasGraphics_showSpacedText(arr) {
+      var ctx = this.ctx;
+      var current = this.current;
+      var font = current.font;
+      var fontSize = current.fontSize;
+      // TJ array's number is independent from fontMatrix
+      var textHScale = current.textHScale * 0.001 * current.fontDirection;
+      var arrLength = arr.length;
+      var textLayer = this.textLayer;
+      var geom;
+      var canvasWidth = 0.0;
+      var textSelection = textLayer ? true : false;
+      var vertical = font.vertical;
+      var spacingAccumulator = 0;
+
+      if (textSelection) {
+        ctx.save();
+        this.applyTextTransforms();
+        geom = this.createTextGeometry();
+        ctx.restore();
+      }
+
+      for (var i = 0; i < arrLength; ++i) {
+        var e = arr[i];
+        if (isNum(e)) {
+          var spacingLength = -e * fontSize * textHScale;
+          if (vertical) {
+            current.y += spacingLength;
+          } else {
+            current.x += spacingLength;
+          }
+
+          if (textSelection)
+            spacingAccumulator += spacingLength;
+        } else {
+          var shownCanvasWidth = this.showText(e, true);
+
+          if (textSelection) {
+            canvasWidth += spacingAccumulator + shownCanvasWidth;
+            spacingAccumulator = 0;
+          }
+        }
+      }
+
+      if (textSelection) {
+        geom.canvasWidth = canvasWidth;
+        if (vertical) {
+          var VERTICAL_TEXT_ROTATION = Math.PI / 2;
+          geom.angle += VERTICAL_TEXT_ROTATION;
+        }
+        this.textLayer.appendText(geom);
+      }
+    },
+    nextLineShowText: function CanvasGraphics_nextLineShowText(text) {
+      this.nextLine();
+      this.showText(text);
+    },
+    nextLineSetSpacingShowText:
+      function CanvasGraphics_nextLineSetSpacingShowText(wordSpacing,
+                                                         charSpacing,
+                                                         text) {
+      this.setWordSpacing(wordSpacing);
+      this.setCharSpacing(charSpacing);
+      this.nextLineShowText(text);
+    },
+
+    // Type3 fonts
+    setCharWidth: function CanvasGraphics_setCharWidth(xWidth, yWidth) {
+      // We can safely ignore this since the width should be the same
+      // as the width in the Widths array.
+    },
+    setCharWidthAndBounds: function CanvasGraphics_setCharWidthAndBounds(xWidth,
+                                                                        yWidth,
+                                                                        llx,
+                                                                        lly,
+                                                                        urx,
+                                                                        ury) {
+      // TODO According to the spec we're also suppose to ignore any operators
+      // that set color or include images while processing this type3 font.
+      this.rectangle(llx, lly, urx - llx, ury - lly);
+      this.clip();
+      this.endPath();
+    },
+
+    // Color
+    setStrokeColorSpace: function CanvasGraphics_setStrokeColorSpace(raw) {
+      this.current.strokeColorSpace = ColorSpace.fromIR(raw);
+    },
+    setFillColorSpace: function CanvasGraphics_setFillColorSpace(raw) {
+      this.current.fillColorSpace = ColorSpace.fromIR(raw);
+    },
+    setStrokeColor: function CanvasGraphics_setStrokeColor(/*...*/) {
+      var cs = this.current.strokeColorSpace;
+      var rgbColor = cs.getRgb(arguments, 0);
+      var color = Util.makeCssRgb(rgbColor);
+      this.ctx.strokeStyle = color;
+      this.current.strokeColor = color;
+    },
+    getColorN_Pattern: function CanvasGraphics_getColorN_Pattern(IR, cs) {
+      if (IR[0] == 'TilingPattern') {
+        var args = IR[1];
+        var base = cs.base;
+        var color;
+        if (base) {
+          var baseComps = base.numComps;
+
+          color = base.getRgb(args, 0);
+        }
+        var pattern = new TilingPattern(IR, color, this.ctx, this.objs,
+                                        this.commonObjs, this.baseTransform);
+      } else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') {
+        var pattern = Pattern.shadingFromIR(IR);
+      } else {
+        error('Unkown IR type ' + IR[0]);
+      }
+      return pattern;
+    },
+    setStrokeColorN: function CanvasGraphics_setStrokeColorN(/*...*/) {
+      var cs = this.current.strokeColorSpace;
+
+      if (cs.name == 'Pattern') {
+        this.current.strokeColor = this.getColorN_Pattern(arguments, cs);
+      } else {
+        this.setStrokeColor.apply(this, arguments);
+      }
+    },
+    setFillColor: function CanvasGraphics_setFillColor(/*...*/) {
+      var cs = this.current.fillColorSpace;
+      var rgbColor = cs.getRgb(arguments, 0);
+      var color = Util.makeCssRgb(rgbColor);
+      this.ctx.fillStyle = color;
+      this.current.fillColor = color;
+    },
+    setFillColorN: function CanvasGraphics_setFillColorN(/*...*/) {
+      var cs = this.current.fillColorSpace;
+
+      if (cs.name == 'Pattern') {
+        this.current.fillColor = this.getColorN_Pattern(arguments, cs);
+      } else {
+        this.setFillColor.apply(this, arguments);
+      }
+    },
+    setStrokeGray: function CanvasGraphics_setStrokeGray(gray) {
+      this.current.strokeColorSpace = ColorSpace.singletons.gray;
+
+      var rgbColor = this.current.strokeColorSpace.getRgb(arguments, 0);
+      var color = Util.makeCssRgb(rgbColor);
+      this.ctx.strokeStyle = color;
+      this.current.strokeColor = color;
+    },
+    setFillGray: function CanvasGraphics_setFillGray(gray) {
+      this.current.fillColorSpace = ColorSpace.singletons.gray;
+
+      var rgbColor = this.current.fillColorSpace.getRgb(arguments, 0);
+      var color = Util.makeCssRgb(rgbColor);
+      this.ctx.fillStyle = color;
+      this.current.fillColor = color;
+    },
+    setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) {
+      this.current.strokeColorSpace = ColorSpace.singletons.rgb;
+
+      var rgbColor = this.current.strokeColorSpace.getRgb(arguments, 0);
+      var color = Util.makeCssRgb(rgbColor);
+      this.ctx.strokeStyle = color;
+      this.current.strokeColor = color;
+    },
+    setFillRGBColor: function CanvasGraphics_setFillRGBColor(r, g, b) {
+      this.current.fillColorSpace = ColorSpace.singletons.rgb;
+
+      var rgbColor = this.current.fillColorSpace.getRgb(arguments, 0);
+      var color = Util.makeCssRgb(rgbColor);
+      this.ctx.fillStyle = color;
+      this.current.fillColor = color;
+    },
+    setStrokeCMYKColor: function CanvasGraphics_setStrokeCMYKColor(c, m, y, k) {
+      this.current.strokeColorSpace = ColorSpace.singletons.cmyk;
+
+      var color = Util.makeCssCmyk(arguments);
+      this.ctx.strokeStyle = color;
+      this.current.strokeColor = color;
+    },
+    setFillCMYKColor: function CanvasGraphics_setFillCMYKColor(c, m, y, k) {
+      this.current.fillColorSpace = ColorSpace.singletons.cmyk;
+
+      var color = Util.makeCssCmyk(arguments);
+      this.ctx.fillStyle = color;
+      this.current.fillColor = color;
+    },
+
+    shadingFill: function CanvasGraphics_shadingFill(patternIR) {
+      var ctx = this.ctx;
+
+      this.save();
+      var pattern = Pattern.shadingFromIR(patternIR);
+      ctx.fillStyle = pattern.getPattern(ctx, this);
+
+      var inv = ctx.mozCurrentTransformInverse;
+      if (inv) {
+        var canvas = ctx.canvas;
+        var width = canvas.width;
+        var height = canvas.height;
+
+        var bl = Util.applyTransform([0, 0], inv);
+        var br = Util.applyTransform([0, height], inv);
+        var ul = Util.applyTransform([width, 0], inv);
+        var ur = Util.applyTransform([width, height], inv);
+
+        var x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
+        var y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
+        var x1 = Math.max(bl[0], br[0], ul[0], ur[0]);
+        var y1 = Math.max(bl[1], br[1], ul[1], ur[1]);
+
+        this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0);
+      } else {
+        // HACK to draw the gradient onto an infinite rectangle.
+        // PDF gradients are drawn across the entire image while
+        // Canvas only allows gradients to be drawn in a rectangle
+        // The following bug should allow us to remove this.
+        // https://bugzilla.mozilla.org/show_bug.cgi?id=664884
+
+        this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
+      }
+
+      this.restore();
+    },
+
+    // Images
+    beginInlineImage: function CanvasGraphics_beginInlineImage() {
+      error('Should not call beginInlineImage');
+    },
+    beginImageData: function CanvasGraphics_beginImageData() {
+      error('Should not call beginImageData');
+    },
+
+    paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix,
+                                                                        bbox) {
+      this.save();
+      this.baseTransformStack.push(this.baseTransform);
+
+      if (matrix && isArray(matrix) && 6 == matrix.length)
+        this.transform.apply(this, matrix);
+
+      this.baseTransform = this.ctx.mozCurrentTransform;
+
+      if (bbox && isArray(bbox) && 4 == bbox.length) {
+        var width = bbox[2] - bbox[0];
+        var height = bbox[3] - bbox[1];
+        this.rectangle(bbox[0], bbox[1], width, height);
+        this.clip();
+        this.endPath();
+      }
+    },
+
+    paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() {
+      this.restore();
+      this.baseTransform = this.baseTransformStack.pop();
+    },
+
+    beginGroup: function CanvasGraphics_beginGroup(group) {
+      this.save();
+      var currentCtx = this.ctx;
+      // TODO non-isolated groups - according to Rik at adobe non-isolated
+      // group results aren't usually that different and they even have tools
+      // that ignore this setting. Notes from Rik on implmenting:
+      // - When you encounter an transparency group, create a new canvas with
+      // the dimensions of the bbox
+      // - copy the content from the previous canvas to the new canvas
+      // - draw as usual
+      // - remove the backdrop alpha:
+      // alphaNew = 1 - (1 - alpha)/(1 - alphaBackdrop) with 'alpha' the alpha
+      // value of your transparency group and 'alphaBackdrop' the alpha of the
+      // backdrop
+      // - remove background color:
+      // colorNew = color - alphaNew *colorBackdrop /(1 - alphaNew)
+      if (!group.isolated) {
+        info('TODO: Support non-isolated groups.');
+      }
+
+      // TODO knockout - supposedly possible with the clever use of compositing
+      // modes.
+      if (group.knockout) {
+        warn('Knockout groups not supported.');
+      }
+
+      var currentTransform = currentCtx.mozCurrentTransform;
+      if (group.matrix) {
+        currentCtx.transform.apply(currentCtx, group.matrix);
+      }
+      assert(group.bbox, 'Bounding box is required.');
+
+      // Based on the current transform figure out how big the bounding box
+      // will actually be.
+      var bounds = Util.getAxialAlignedBoundingBox(
+                    group.bbox,
+                    currentCtx.mozCurrentTransform);
+      // Clip the bounding box to the current canvas.
+      var canvasBounds = [0,
+                          0,
+                          currentCtx.canvas.width,
+                          currentCtx.canvas.height];
+      bounds = Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0];
+      // Use ceil in case we're between sizes so we don't create canvas that is
+      // too small and make the canvas at least 1x1 pixels.
+      var drawnWidth = Math.max(Math.ceil(bounds[2] - bounds[0]), 1);
+      var drawnHeight = Math.max(Math.ceil(bounds[3] - bounds[1]), 1);
+
+      var scratchCanvas = CachedCanvases.getCanvas(
+        'groupAt' + this.groupLevel, drawnWidth, drawnHeight, true);
+      var groupCtx = scratchCanvas.context;
+      // Since we created a new canvas that is just the size of the bounding box
+      // we have to translate the group ctx.
+      var offsetX = bounds[0];
+      var offsetY = bounds[1];
+      groupCtx.translate(-offsetX, -offsetY);
+      groupCtx.transform.apply(groupCtx, currentTransform);
+
+      // Setup the current ctx so when the group is popped we draw it the right
+      // location.
+      currentCtx.setTransform(1, 0, 0, 1, 0, 0);
+      currentCtx.translate(offsetX, offsetY);
+      // The transparency group inherits all off the current graphics state
+      // except the blend mode, soft mask, and alpha constants.
+      copyCtxState(currentCtx, groupCtx);
+      this.ctx = groupCtx;
+      this.setGState([
+        ['SMask', 'None'],
+        ['BM', 'Normal'],
+        ['ca', 1],
+        ['CA', 1]
+      ]);
+      this.groupStack.push(currentCtx);
+      this.groupLevel++;
+    },
+
+    endGroup: function CanvasGraphics_endGroup(group) {
+      this.groupLevel--;
+      var groupCtx = this.ctx;
+      this.ctx = this.groupStack.pop();
+      // Turn off image smoothing to avoid sub pixel interpolation which can
+      // look kind of blurry for some pdfs.
+      if ('imageSmoothingEnabled' in this.ctx) {
+        this.ctx.imageSmoothingEnabled = false;
+      } else {
+        this.ctx.mozImageSmoothingEnabled = false;
+      }
+      this.ctx.drawImage(groupCtx.canvas, 0, 0);
+      this.restore();
+    },
+
+    beginAnnotations: function CanvasGraphics_beginAnnotations() {
+      this.save();
+      this.current = new CanvasExtraState();
+    },
+
+    endAnnotations: function CanvasGraphics_endAnnotations() {
+      this.restore();
+    },
+
+    beginAnnotation: function CanvasGraphics_beginAnnotation(rect, transform,
+                                                             matrix) {
+      this.save();
+
+      if (rect && isArray(rect) && 4 == rect.length) {
+        var width = rect[2] - rect[0];
+        var height = rect[3] - rect[1];
+        this.rectangle(rect[0], rect[1], width, height);
+        this.clip();
+        this.endPath();
+      }
+
+      this.transform.apply(this, transform);
+      this.transform.apply(this, matrix);
+    },
+
+    endAnnotation: function CanvasGraphics_endAnnotation() {
+      this.restore();
+    },
+
+    paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
+      var domImage = this.objs.get(objId);
+      if (!domImage) {
+        error('Dependent image isn\'t ready yet');
+      }
+
+      this.save();
+
+      var ctx = this.ctx;
+      // scale the image to the unit square
+      ctx.scale(1 / w, -1 / h);
+
+      ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
+                    0, -h, w, h);
+      if (this.imageLayer) {
+        var currentTransform = ctx.mozCurrentTransformInverse;
+        var position = this.getCanvasPosition(0, 0);
+        this.imageLayer.appendImage({
+          objId: objId,
+          left: position[0],
+          top: position[1],
+          width: w / currentTransform[0],
+          height: h / currentTransform[3]
+        });
+      }
+      this.restore();
+    },
+
+    paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(img) {
+      var ctx = this.ctx;
+      var width = img.width, height = img.height;
+
+      var glyph = this.processingType3;
+
+      if (COMPILE_TYPE3_GLYPHS && glyph && !('compiled' in glyph)) {
+        var MAX_SIZE_TO_COMPILE = 1000;
+        if (width <= MAX_SIZE_TO_COMPILE && height <= MAX_SIZE_TO_COMPILE) {
+          glyph.compiled =
+            compileType3Glyph({data: img.data, width: width, height: height});
+        } else {
+          glyph.compiled = null;
+        }
+      }
+
+      if (glyph && glyph.compiled) {
+        glyph.compiled(ctx);
+        return;
+      }
+
+      var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
+      var maskCtx = maskCanvas.context;
+      maskCtx.save();
+
+      putBinaryImageMask(maskCtx, img);
+
+      maskCtx.globalCompositeOperation = 'source-in';
+
+      var fillColor = this.current.fillColor;
+      maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
+                          fillColor.type === 'Pattern') ?
+                          fillColor.getPattern(maskCtx, this) : fillColor;
+      maskCtx.fillRect(0, 0, width, height);
+
+      maskCtx.restore();
+
+      this.paintInlineImageXObject(maskCanvas.canvas);
+    },
+
+    paintImageMaskXObjectGroup:
+      function CanvasGraphics_paintImageMaskXObjectGroup(images) {
+      var ctx = this.ctx;
+
+      for (var i = 0, ii = images.length; i < ii; i++) {
+        var image = images[i];
+        var width = image.width, height = image.height;
+
+        var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
+        var maskCtx = maskCanvas.context;
+        maskCtx.save();
+
+        putBinaryImageMask(maskCtx, image);
+
+        maskCtx.globalCompositeOperation = 'source-in';
+
+        var fillColor = this.current.fillColor;
+        maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
+                            fillColor.type === 'Pattern') ?
+                            fillColor.getPattern(maskCtx, this) : fillColor;
+        maskCtx.fillRect(0, 0, width, height);
+
+        maskCtx.restore();
+
+        ctx.save();
+        ctx.transform.apply(ctx, image.transform);
+        ctx.scale(1, -1);
+        ctx.drawImage(maskCanvas.canvas, 0, 0, width, height,
+                      0, -1, 1, 1);
+        ctx.restore();
+      }
+    },
+
+    paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
+      var imgData = this.objs.get(objId);
+      if (!imgData)
+        error('Dependent image isn\'t ready yet');
+
+      this.paintInlineImageXObject(imgData);
+    },
+
+    paintInlineImageXObject:
+      function CanvasGraphics_paintInlineImageXObject(imgData) {
+      var width = imgData.width;
+      var height = imgData.height;
+      var ctx = this.ctx;
+
+      this.save();
+      // scale the image to the unit square
+      ctx.scale(1 / width, -1 / height);
+
+      var currentTransform = ctx.mozCurrentTransformInverse;
+      var a = currentTransform[0], b = currentTransform[1];
+      var widthScale = Math.max(Math.sqrt(a * a + b * b), 1);
+      var c = currentTransform[2], d = currentTransform[3];
+      var heightScale = Math.max(Math.sqrt(c * c + d * d), 1);
+
+      var imgToPaint;
+      // instanceof HTMLElement does not work in jsdom node.js module
+      if (imgData instanceof HTMLElement || !imgData.data) {
+        imgToPaint = imgData;
+      } else {
+        var tmpCanvas = CachedCanvases.getCanvas('inlineImage', width, height);
+        var tmpCtx = tmpCanvas.context;
+        putBinaryImageData(tmpCtx, imgData);
+        imgToPaint = tmpCanvas.canvas;
+      }
+
+      var paintWidth = width, paintHeight = height;
+      var tmpCanvasId = 'prescale1';
+      // Vertial or horizontal scaling shall not be more than 2 to not loose the
+      // pixels during drawImage operation, painting on the temporary canvas(es)
+      // that are twice smaller in size
+      while ((widthScale > 2 && paintWidth > 1) ||
+             (heightScale > 2 && paintHeight > 1)) {
+        var newWidth = paintWidth, newHeight = paintHeight;
+        if (widthScale > 2 && paintWidth > 1) {
+          newWidth = Math.ceil(paintWidth / 2);
+          widthScale /= paintWidth / newWidth;
+        }
+        if (heightScale > 2 && paintHeight > 1) {
+          newHeight = Math.ceil(paintHeight / 2);
+          heightScale /= paintHeight / newHeight;
+        }
+        var tmpCanvas = CachedCanvases.getCanvas(tmpCanvasId,
+                                                 newWidth, newHeight);
+        tmpCtx = tmpCanvas.context;
+        tmpCtx.clearRect(0, 0, newWidth, newHeight);
+        tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight,
+                                     0, 0, newWidth, newHeight);
+        imgToPaint = tmpCanvas.canvas;
+        paintWidth = newWidth;
+        paintHeight = newHeight;
+        tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1';
+      }
+      ctx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight,
+                                0, -height, width, height);
+
+      if (this.imageLayer) {
+        var position = this.getCanvasPosition(0, -height);
+        this.imageLayer.appendImage({
+          imgData: imgData,
+          left: position[0],
+          top: position[1],
+          width: width / currentTransform[0],
+          height: height / currentTransform[3]
+        });
+      }
+      this.restore();
+    },
+
+    paintInlineImageXObjectGroup:
+      function CanvasGraphics_paintInlineImageXObjectGroup(imgData, map) {
+      var ctx = this.ctx;
+      var w = imgData.width;
+      var h = imgData.height;
+
+      var tmpCanvas = CachedCanvases.getCanvas('inlineImage', w, h);
+      var tmpCtx = tmpCanvas.context;
+      putBinaryImageData(tmpCtx, imgData);
+
+      for (var i = 0, ii = map.length; i < ii; i++) {
+        var entry = map[i];
+        ctx.save();
+        ctx.transform.apply(ctx, entry.transform);
+        ctx.scale(1, -1);
+        ctx.drawImage(tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h,
+                      0, -1, 1, 1);
+        if (this.imageLayer) {
+          var position = this.getCanvasPosition(entry.x, entry.y);
+          this.imageLayer.appendImage({
+            imgData: imgData,
+            left: position[0],
+            top: position[1],
+            width: w,
+            height: h
+          });
+        }
+        ctx.restore();
+      }
+    },
+
+    // Marked content
+
+    markPoint: function CanvasGraphics_markPoint(tag) {
+      // TODO Marked content.
+    },
+    markPointProps: function CanvasGraphics_markPointProps(tag, properties) {
+      // TODO Marked content.
+    },
+    beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) {
+      // TODO Marked content.
+    },
+    beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps(
+                                        tag, properties) {
+      // TODO Marked content.
+    },
+    endMarkedContent: function CanvasGraphics_endMarkedContent() {
+      // TODO Marked content.
+    },
+
+    // Compatibility
+
+    beginCompat: function CanvasGraphics_beginCompat() {
+      // TODO ignore undefined operators (should we do that anyway?)
+    },
+    endCompat: function CanvasGraphics_endCompat() {
+      // TODO stop ignoring undefined operators
+    },
+
+    // Helper functions
+
+    consumePath: function CanvasGraphics_consumePath() {
+      if (this.pendingClip) {
+        if (this.pendingClip == EO_CLIP) {
+          if ('mozFillRule' in this.ctx) {
+            this.ctx.mozFillRule = 'evenodd';
+            this.ctx.clip();
+            this.ctx.mozFillRule = 'nonzero';
+          } else {
+            try {
+              this.ctx.clip('evenodd');
+            } catch (ex) {
+              // shouldn't really happen, but browsers might think differently
+              this.ctx.clip();
+            }
+          }
+        } else {
+          this.ctx.clip();
+        }
+        this.pendingClip = null;
+      }
+      this.ctx.beginPath();
+    },
+    getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) {
+      var inverse = this.ctx.mozCurrentTransformInverse;
+      // max of the current horizontal and vertical scale
+      return Math.sqrt(Math.max(
+        (inverse[0] * inverse[0] + inverse[1] * inverse[1]),
+        (inverse[2] * inverse[2] + inverse[3] * inverse[3])));
+    },
+    getCanvasPosition: function CanvasGraphics_getCanvasPosition(x, y) {
+        var transform = this.ctx.mozCurrentTransform;
+        return [
+          transform[0] * x + transform[2] * y + transform[4],
+          transform[1] * x + transform[3] * y + transform[5]
+        ];
+    }
+  };
+
+  for (var op in OPS) {
+    CanvasGraphics.prototype[OPS[op]] = CanvasGraphics.prototype[op];
+  }
+
+  return CanvasGraphics;
+})();
+
+
+
+PDFJS.disableFontFace = false;
+
+var FontLoader = {
+  insertRule: function fontLoaderInsertRule(rule) {
+    var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
+    if (!styleElement) {
+        styleElement = document.createElement('style');
+        styleElement.id = 'PDFJS_FONT_STYLE_TAG';
+        document.documentElement.getElementsByTagName('head')[0].appendChild(
+          styleElement);
+    }
+
+    var styleSheet = styleElement.sheet;
+    styleSheet.insertRule(rule, styleSheet.cssRules.length);
+  },
+  clear: function fontLoaderClear() {
+    var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
+    if (styleElement) {
+      styleElement.parentNode.removeChild(styleElement);
+    }
+  },
+  get loadTestFont() {
+    // This is a CFF font with 1 glyph for '.' that fills its entire width and
+    // height.
+    return shadow(this, 'loadTestFont', atob(
+      'T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQ' +
+      'AABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwA' +
+      'AAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbm' +
+      'FtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAA' +
+      'AADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6A' +
+      'ABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAA' +
+      'MQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAA' +
+      'AAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAA' +
+      'AAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQ' +
+      'AAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMA' +
+      'AQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAA' +
+      'EAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAA' +
+      'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAA' +
+      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA' +
+      'AAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgc' +
+      'A/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF' +
+      'hYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQA' +
+      'AAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAg' +
+      'ABAAAAAAAAAAAD6AAAAAAAAA=='
+    ));
+  },
+
+  loadTestFontId: 0,
+
+  loadingContext: {
+    requests: [],
+    nextRequestId: 0
+  },
+
+  isSyncFontLoadingSupported: (function detectSyncFontLoadingSupport() {
+    if (isWorker)
+      return false;
+
+    // User agent string sniffing is bad, but there is no reliable way to tell
+    // if font is fully loaded and ready to be used with canvas.
+    var userAgent = window.navigator.userAgent;
+    var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent);
+    if (m && m[1] >= 14)
+      return true;
+    // TODO other browsers
+    return false;
+  })(),
+
+  bind: function fontLoaderBind(fonts, callback) {
+    assert(!isWorker, 'bind() shall be called from main thread');
+
+    var rules = [], fontsToLoad = [];
+    for (var i = 0, ii = fonts.length; i < ii; i++) {
+      var font = fonts[i];
+
+      // Add the font to the DOM only once or skip if the font
+      // is already loaded.
+      if (font.attached || font.loading === false) {
+        continue;
+      }
+      font.attached = true;
+
+      var rule = font.bindDOM();
+      if (rule) {
+        rules.push(rule);
+        fontsToLoad.push(font);
+      }
+    }
+
+    var request = FontLoader.queueLoadingCallback(callback);
+    if (rules.length > 0 && !this.isSyncFontLoadingSupported) {
+      FontLoader.prepareFontLoadEvent(rules, fontsToLoad, request);
+    } else {
+      request.complete();
+    }
+  },
+
+  queueLoadingCallback: function FontLoader_queueLoadingCallback(callback) {
+    function LoadLoader_completeRequest() {
+      assert(!request.end, 'completeRequest() cannot be called twice');
+      request.end = Date.now();
+
+      // sending all completed requests in order how they were queued
+      while (context.requests.length > 0 && context.requests[0].end) {
+        var otherRequest = context.requests.shift();
+        setTimeout(otherRequest.callback, 0);
+      }
+    }
+
+    var context = FontLoader.loadingContext;
+    var requestId = 'pdfjs-font-loading-' + (context.nextRequestId++);
+    var request = {
+      id: requestId,
+      complete: LoadLoader_completeRequest,
+      callback: callback,
+      started: Date.now()
+    };
+    context.requests.push(request);
+    return request;
+  },
+
+  prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules,
+                                                                fonts,
+                                                                request) {
+      /** Hack begin */
+      // There's currently no event when a font has finished downloading so the
+      // following code is a dirty hack to 'guess' when a font is
+      // ready. It's assumed fonts are loaded in order, so add a known test
+      // font after the desired fonts and then test for the loading of that
+      // test font.
+
+      function int32(data, offset) {
+        return (data.charCodeAt(offset) << 24) |
+               (data.charCodeAt(offset + 1) << 16) |
+               (data.charCodeAt(offset + 2) << 8) |
+               (data.charCodeAt(offset + 3) & 0xff);
+      }
+
+      function string32(value) {
+        return String.fromCharCode((value >> 24) & 0xff) +
+               String.fromCharCode((value >> 16) & 0xff) +
+               String.fromCharCode((value >> 8) & 0xff) +
+               String.fromCharCode(value & 0xff);
+      }
+
+      function spliceString(s, offset, remove, insert) {
+        var chunk1 = data.substr(0, offset);
+        var chunk2 = data.substr(offset + remove);
+        return chunk1 + insert + chunk2;
+      }
+
+      var i, ii;
+
+      var canvas = document.createElement('canvas');
+      canvas.width = 1;
+      canvas.height = 1;
+      var ctx = canvas.getContext('2d');
+
+      var called = 0;
+      function isFontReady(name, callback) {
+        called++;
+        // With setTimeout clamping this gives the font ~100ms to load.
+        if(called > 30) {
+          warn('Load test font never loaded.');
+          callback();
+          return;
+        }
+        ctx.font = '30px ' + name;
+        ctx.fillText('.', 0, 20);
+        var imageData = ctx.getImageData(0, 0, 1, 1);
+        if (imageData.data[3] > 0) {
+          callback();
+          return;
+        }
+        setTimeout(isFontReady.bind(null, name, callback));
+      }
+
+      var loadTestFontId = 'lt' + Date.now() + this.loadTestFontId++;
+      // Chromium seems to cache fonts based on a hash of the actual font data,
+      // so the font must be modified for each load test else it will appear to
+      // be loaded already.
+      // TODO: This could maybe be made faster by avoiding the btoa of the full
+      // font by splitting it in chunks before hand and padding the font id.
+      var data = this.loadTestFont;
+      var COMMENT_OFFSET = 976; // has to be on 4 byte boundary (for checksum)
+      data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length,
+                          loadTestFontId);
+      // CFF checksum is important for IE, adjusting it
+      var CFF_CHECKSUM_OFFSET = 16;
+      var XXXX_VALUE = 0x58585858; // the "comment" filled with 'X'
+      var checksum = int32(data, CFF_CHECKSUM_OFFSET);
+      for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) {
+        checksum = (checksum - XXXX_VALUE + int32(loadTestFontId, i)) | 0;
+      }
+      if (i < loadTestFontId.length) { // align to 4 bytes boundary
+        checksum = (checksum - XXXX_VALUE +
+                    int32(loadTestFontId + 'XXX', i)) | 0;
+      }
+      data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum));
+
+      var url = 'url(data:font/opentype;base64,' + btoa(data) + ');';
+      var rule = '@font-face { font-family:"' + loadTestFontId + '";src:' +
+                 url + '}';
+      FontLoader.insertRule(rule);
+
+      var names = [];
+      for (i = 0, ii = fonts.length; i < ii; i++) {
+        names.push(fonts[i].loadedName);
+      }
+      names.push(loadTestFontId);
+
+      var div = document.createElement('div');
+      div.setAttribute('style',
+                       'visibility: hidden;' +
+                       'width: 10px; height: 10px;' +
+                       'position: absolute; top: 0px; left: 0px;');
+      for (i = 0, ii = names.length; i < ii; ++i) {
+        var span = document.createElement('span');
+        span.textContent = 'Hi';
+        span.style.fontFamily = names[i];
+        div.appendChild(span);
+      }
+      document.body.appendChild(div);
+
+      isFontReady(loadTestFontId, function() {
+        document.body.removeChild(div);
+        request.complete();
+      });
+      /** Hack end */
+  }
+};
+
+var FontFace = (function FontFaceClosure() {
+  function FontFace(name, file, properties) {
+    this.compiledGlyphs = {};
+    if (arguments.length === 1) {
+      // importing translated data
+      var data = arguments[0];
+      for (var i in data) {
+        this[i] = data[i];
+      }
+      return;
+    }
+  }
+  FontFace.prototype = {
+    bindDOM: function FontFace_bindDOM() {
+      if (!this.data)
+        return null;
+
+      if (PDFJS.disableFontFace) {
+        this.disableFontFace = true;
+        return null;
+      }
+
+      var data = bytesToString(this.data);
+      var fontName = this.loadedName;
+
+      // Add the font-face rule to the document
+      var url = ('url(data:' + this.mimetype + ';base64,' +
+                 window.btoa(data) + ');');
+      var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}';
+
+      FontLoader.insertRule(rule);
+
+      if (PDFJS.pdfBug && 'FontInspector' in globalScope &&
+          globalScope['FontInspector'].enabled)
+        globalScope['FontInspector'].fontAdded(this, url);
+
+      return rule;
+    },
+    getPathGenerator: function (objs, character) {
+      if (!(character in this.compiledGlyphs)) {
+        var js = objs.get(this.loadedName + '_path_' + character);
+        /*jshint -W054 */
+        this.compiledGlyphs[character] = new Function('c', 'size', js);
+      }
+      return this.compiledGlyphs[character];
+    }
+  };
+  return FontFace;
+})();
+
+
+}).call((typeof window === 'undefined') ? this : window);
+
+if (!PDFJS.workerSrc && typeof document !== 'undefined') {
+  // workerSrc is not set -- using last script url to define default location
+  PDFJS.workerSrc = (function () {
+    'use strict';
+    var scriptTagContainer = document.body ||
+                             document.getElementsByTagName('head')[0];
+    var pdfjsSrc = scriptTagContainer.lastChild.src;
+    return pdfjsSrc && pdfjsSrc.replace(/\.js$/i, '.worker.js');
+  })();
+}
+
+
diff --git a/plugins/pdfviewer/viewer/pdf.min.js b/plugins/pdfviewer/viewer/pdf.min.js
new file mode 100644
index 0000000..5688c2e
--- /dev/null
+++ b/plugins/pdfviewer/viewer/pdf.min.js
@@ -0,0 +1,178 @@
+"undefined"===typeof PDFJS&&(("undefined"!==typeof window?window:this).PDFJS={});PDFJS.version="0.8.894";PDFJS.build="ac91047";
+(function(){var E,X;function K(b){PDFJS.verbosity>=PDFJS.VERBOSITY_LEVELS.infos&&console.log("Info: "+b)}function x(b){PDFJS.verbosity>=PDFJS.VERBOSITY_LEVELS.warnings&&console.log("Warning: "+b)}function m(b){if(1<arguments.length){var a=["Error:"];a.push.apply(a,arguments);console.log.apply(console,a);b=[].join.call(arguments," ")}else console.log("Error: "+b);console.log(oa());Z.notify(da.unknown);throw Error(b);}function oa(){try{throw Error();}catch(b){return b.stack?b.stack.split("\n").slice(2).join("\n"):
+""}}function pa(b,a){if(!a)return b;if(0<=a.indexOf(":"))return a;if("/"==a.charAt(0)){var c=b.indexOf("://"),c=b.indexOf("/",c+3);return b.substring(0,c)+a}var e=b.length,c=b.lastIndexOf("#"),e=0<=c?c:e,c=b.lastIndexOf("?",e),c=b.lastIndexOf("/",0<=c?c:e);return b.substring(0,c+1)+a}function $(b,a){if(!b)return!1;var c=b.indexOf(":");if(0>c)return a;switch(b.substr(0,c)){case "http":case "https":case "ftp":case "mailto":return!0;default:return!1}}function U(b,a,c){Object.defineProperty(b,a,{value:c,
+enumerable:!0,configurable:!0,writable:!1});return c}function V(b){var a,c=b.length,e="";if("\u00fe"===b[0]&&"\u00ff"===b[1])for(a=2;a<c;a+=2)e+=String.fromCharCode(b.charCodeAt(a)<<8|b.charCodeAt(a+1));else for(a=0;a<c;++a)var d=qa[b.charCodeAt(a)],e=e+(d?String.fromCharCode(d):b.charAt(a));return e}function L(b){return"boolean"==typeof b}function P(b){return b instanceof Name}function R(b,a){if(!(b instanceof Dict))return!1;if(!a)return!0;var c=b.get("Type");return P(c)&&c.name==a}function D(b){return b instanceof
+Array}function Y(b){return"object"==typeof b&&null!==b&&void 0!==b&&"getBytes"in b}function ea(b){if("object"!=typeof b)return!1;if(!R(b))if(Y(b))b=b.dict;else return!1;return b.has("FunctionType")}function aa(b,a){this.name=b;this.comObj=a;this.callbackIndex=1;this.postMessageTransfers=!0;var c=this.callbacks={},e=this.actionHandler={};e.console_log=[function(a){console.log.apply(console,a)}];e.console_error=[function(a){console.error.apply(console,a)}];e._unsupported_feature=[function(a){Z.notify(a)}];
+a.onmessage=function(d){var b=d.data;if(b.isReply)if(d=b.callbackId,b.callbackId in c){var f=c[d];delete c[d];f(b.data)}else m("Cannot resolve callback "+d);else if(b.action in e)if(d=e[b.action],b.callbackId){var h={},f=new Promise(function(a,c){h.resolve=a;h.reject=c});h.promise=f;f.then(function(c){a.postMessage({isReply:!0,callbackId:b.callbackId,data:c})});d[0].call(d[1],b.data,h)}else d[0].call(d[1],b.data);else m("Unkown action from worker: "+b.action)}}function ra(b,a,c){var e=new Image;e.onload=
+function(){c.resolve(b,e)};e.src=a}function fa(b,a){var c=document.createElement("canvas");c.width=b;c.height=a;return c}function ga(b){b.mozCurrentTransform||(b._scaleX=b._scaleX||1,b._scaleY=b._scaleY||1,b._originalSave=b.save,b._originalRestore=b.restore,b._originalRotate=b.rotate,b._originalScale=b.scale,b._originalTranslate=b.translate,b._originalTransform=b.transform,b._originalSetTransform=b.setTransform,b._transformMatrix=[b._scaleX,0,0,b._scaleY,0,0],b._transformStack=[],Object.defineProperty(b,
+"mozCurrentTransform",{get:function(){return this._transformMatrix}}),Object.defineProperty(b,"mozCurrentTransformInverse",{get:function(){var a=this._transformMatrix,c=a[0],e=a[1],d=a[2],b=a[3],f=a[4],a=a[5],h=c*b-e*d,k=e*d-c*b;return[b/h,e/k,d/k,c/h,(b*f-d*a)/k,(e*f-c*a)/h]}}),b.save=function(){var a=this._transformMatrix;this._transformStack.push(a);this._transformMatrix=a.slice(0,6);this._originalSave()},b.restore=function(){var a=this._transformStack.pop();a&&(this._transformMatrix=a,this._originalRestore())},
+b.translate=function(a,c){var e=this._transformMatrix;e[4]=e[0]*a+e[2]*c+e[4];e[5]=e[1]*a+e[3]*c+e[5];this._originalTranslate(a,c)},b.scale=function(a,c){var e=this._transformMatrix;e[0]*=a;e[1]*=a;e[2]*=c;e[3]*=c;this._originalScale(a,c)},b.transform=function(a,c,e,d,g,f){var h=this._transformMatrix;this._transformMatrix=[h[0]*a+h[2]*c,h[1]*a+h[3]*c,h[0]*e+h[2]*d,h[1]*e+h[3]*d,h[0]*g+h[2]*f+h[4],h[1]*g+h[3]*f+h[5]];b._originalTransform(a,c,e,d,g,f)},b.setTransform=function(a,c,e,d,g,f){this._transformMatrix=
+[a,c,e,d,g,f];b._originalSetTransform(a,c,e,d,g,f)},b.rotate=function(a){var c=Math.cos(a),e=Math.sin(a),d=this._transformMatrix;this._transformMatrix=[d[0]*c+d[2]*e,d[1]*c+d[3]*e,d[0]*-e+d[2]*c,d[1]*-e+d[3]*c,d[4],d[5]];this._originalRotate(a)})}function sa(b){var a=b.width,c=b.height,e,d,g=a+1,f=new Uint8Array(g*(c+1)),h=new Uint8Array([0,2,4,0,1,0,5,4,8,10,0,8,0,2,1,0]),k=a+7&-8,l=b.data,n=new Uint8Array(k*c),p=0;b=0;for(e=l.length;b<e;b++){d=128;for(var z=l[b];0<d;)n[p++]=z&d?0:255,d>>=1}p=l=
+0;0!==n[p]&&(f[0]=1,++l);for(e=1;e<a;e++)n[p]!==n[p+1]&&(f[e]=n[p]?2:1,++l),p++;0!==n[p]&&(f[e]=2,++l);for(b=1;b<c;b++){p=b*k;d=b*g;n[p-k]!==n[p]&&(f[d]=n[p]?1:8,++l);z=(n[p]?4:0)+(n[p-k]?8:0);for(e=1;e<a;e++)z=(z>>2)+(n[p+1]?4:0)+(n[p-k+1]?8:0),h[z]&&(f[d+e]=h[z],++l),p++;n[p-k]!==n[p]&&(f[d+e]=n[p]?2:4,++l);if(1E3<l)return null}p=k*(c-1);d=b*g;0!==n[p]&&(f[d]=8,++l);for(e=1;e<a;e++)n[p]!==n[p+1]&&(f[d+e]=n[p]?4:8,++l),p++;0!==n[p]&&(f[d+e]=4,++l);if(1E3<l)return null;var h=new Int32Array([0,g,-1,
+0,-g,0,0,0,1]),s=[];for(b=0;l&&b<=c;b++){k=b*g;for(n=k+a;k<n&&!f[k];)k++;if(k!==n){n=[k%g,b];p=f[k];e=k;do{d=h[p];do k+=d;while(!f[k]);d=f[k];5!==d&&10!==d?(p=d,f[k]=0):(p=d&51*p>>4,f[k]&=p>>2|p<<2);n.push(k%g);n.push(k/g|0);--l}while(e!==k);s.push(n);--b}}return function(d){d.save();d.scale(1/a,-1/c);d.translate(0,-c);d.beginPath();for(var e=0,k=s.length;e<k;e++){var b=s[e];d.moveTo(b[0],b[1]);for(var g=2,l=b.length;g<l;g+=2)d.lineTo(b[g],b[g+1])}d.fill();d.beginPath();d.restore()}}var t="undefined"===
+typeof window?this:window,W="undefined"==typeof window,ba=[0.0010,0,0,0.0010,0,0];X=0;t.PDFJS||(t.PDFJS={});t.PDFJS.pdfBug=!1;PDFJS.VERBOSITY_LEVELS={errors:0,warnings:1,infos:5};var y=PDFJS.OPS={dependency:1,setLineWidth:2,setLineCap:3,setLineJoin:4,setMiterLimit:5,setDash:6,setRenderingIntent:7,setFlatness:8,setGState:9,save:10,restore:11,transform:12,moveTo:13,lineTo:14,curveTo:15,curveTo2:16,curveTo3:17,closePath:18,rectangle:19,stroke:20,closeStroke:21,fill:22,eoFill:23,fillStroke:24,eoFillStroke:25,
+closeFillStroke:26,closeEOFillStroke:27,endPath:28,clip:29,eoClip:30,beginText:31,endText:32,setCharSpacing:33,setWordSpacing:34,setHScale:35,setLeading:36,setFont:37,setTextRenderingMode:38,setTextRise:39,moveText:40,setLeadingMoveText:41,setTextMatrix:42,nextLine:43,showText:44,showSpacedText:45,nextLineShowText:46,nextLineSetSpacingShowText:47,setCharWidth:48,setCharWidthAndBounds:49,setStrokeColorSpace:50,setFillColorSpace:51,setStrokeColor:52,setStrokeColorN:53,setFillColor:54,setFillColorN:55,
+setStrokeGray:56,setFillGray:57,setStrokeRGBColor:58,setFillRGBColor:59,setStrokeCMYKColor:60,setFillCMYKColor:61,shadingFill:62,beginInlineImage:63,beginImageData:64,endInlineImage:65,paintXObject:66,markPoint:67,markPointProps:68,beginMarkedContent:69,beginMarkedContentProps:70,endMarkedContent:71,beginCompat:72,endCompat:73,paintFormXObjectBegin:74,paintFormXObjectEnd:75,beginGroup:76,endGroup:77,beginAnnotations:78,endAnnotations:79,beginAnnotation:80,endAnnotation:81,paintJpegXObject:82,paintImageMaskXObject:83,
+paintImageMaskXObjectGroup:84,paintImageXObject:85,paintInlineImageXObject:86,paintInlineImageXObjectGroup:87},da=PDFJS.UNSUPPORTED_FEATURES={unknown:"unknown",forms:"forms",javaScript:"javaScript",smask:"smask",shadingPattern:"shadingPattern",font:"font"},Z=PDFJS.UnsupportedManager=function(){var b=[];return{listen:function(a){b.push(a)},notify:function(a){x('Unsupported feature "'+a+'"');for(var c=0,e=b.length;c<e;c++)b[c](a)}}}();PDFJS.isValidUrl=$;var ha=PDFJS.PasswordResponses={NEED_PASSWORD:1,
+INCORRECT_PASSWORD:2};(function(){function b(a,c){this.name="PasswordException";this.message=a;this.code=c}b.prototype=Error();return b.constructor=b})();(function(){function b(a,c){this.name="UnknownErrorException";this.message=a;this.details=c}b.prototype=Error();return b.constructor=b})();(function(){function b(a){this.name="InvalidPDFException";this.message=a}b.prototype=Error();return b.constructor=b})();(function(){function b(a){this.name="MissingPDFException";this.message=a}b.prototype=Error();
+return b.constructor=b})();var ta=function(){function b(a){this.message=a}b.prototype=Error();b.prototype.name="NotImplementedException";return b.constructor=b}();(function(){function b(a,c){this.begin=a;this.end=c;this.message="Missing data ["+a+", "+c+")"}b.prototype=Error();b.prototype.name="MissingDataException";return b.constructor=b})();(function(){function b(a){this.message=a}b.prototype=Error();b.prototype.name="XRefParseException";return b.constructor=b})();var ia=[1,0,0,1,0,0],q=PDFJS.Util=
+function(){function b(){}b.makeCssRgb=function(a){return"rgb("+a[0]+","+a[1]+","+a[2]+")"};b.makeCssCmyk=function(a){a=r.singletons.cmyk.getRgb(a,0);return b.makeCssRgb(a)};b.transform=function(a,c){return[a[0]*c[0]+a[2]*c[1],a[1]*c[0]+a[3]*c[1],a[0]*c[2]+a[2]*c[3],a[1]*c[2]+a[3]*c[3],a[0]*c[4]+a[2]*c[5]+a[4],a[1]*c[4]+a[3]*c[5]+a[5]]};b.applyTransform=function(a,c){return[a[0]*c[0]+a[1]*c[2]+c[4],a[0]*c[1]+a[1]*c[3]+c[5]]};b.applyInverseTransform=function(a,c){var e=c[0]*c[3]-c[1]*c[2];return[(a[0]*
+c[3]-a[1]*c[2]+c[2]*c[5]-c[4]*c[3])/e,(-a[0]*c[1]+a[1]*c[0]+c[4]*c[1]-c[5]*c[0])/e]};b.getAxialAlignedBoundingBox=function(a,c){var e=b.applyTransform(a,c),d=b.applyTransform(a.slice(2,4),c),g=b.applyTransform([a[0],a[3]],c),f=b.applyTransform([a[2],a[1]],c);return[Math.min(e[0],d[0],g[0],f[0]),Math.min(e[1],d[1],g[1],f[1]),Math.max(e[0],d[0],g[0],f[0]),Math.max(e[1],d[1],g[1],f[1])]};b.inverseTransform=function(a){var c=a[0]*a[3]-a[1]*a[2];return[a[3]/c,-a[1]/c,-a[2]/c,a[0]/c,(a[2]*a[5]-a[4]*a[3])/
+c,(a[4]*a[1]-a[5]*a[0])/c]};b.apply3dTransform=function(a,c){return[a[0]*c[0]+a[1]*c[1]+a[2]*c[2],a[3]*c[0]+a[4]*c[1]+a[5]*c[2],a[6]*c[0]+a[7]*c[1]+a[8]*c[2]]};b.singularValueDecompose2dScale=function(a){var c=[a[0],a[2],a[1],a[3]],e=a[0]*c[0]+a[1]*c[2],d=a[2]*c[1]+a[3]*c[3],b=(e+d)/2;a=Math.sqrt((e+d)*(e+d)-4*(e*d-(a[2]*c[0]+a[3]*c[2])*(a[0]*c[1]+a[1]*c[3])))/2;c=b-a||1;return[Math.sqrt(b+a||1),Math.sqrt(c)]};b.normalizeRect=function(a){var c=a.slice(0);a[0]>a[2]&&(c[0]=a[2],c[2]=a[0]);a[1]>a[3]&&
+(c[1]=a[3],c[3]=a[1]);return c};b.intersect=function(a,c){function e(a,c){return a-c}var d=[a[0],a[2],c[0],c[2]].sort(e),g=[a[1],a[3],c[1],c[3]].sort(e),f=[];a=b.normalizeRect(a);c=b.normalizeRect(c);if(d[0]===a[0]&&d[1]===c[0]||d[0]===c[0]&&d[1]===a[0])f[0]=d[1],f[2]=d[2];else return!1;if(g[0]===a[1]&&g[1]===c[1]||g[0]===c[1]&&g[1]===a[1])f[1]=g[1],f[3]=g[2];else return!1;return f};b.sign=function(a){return 0>a?-1:1};b.concatenateToArray=function(a,c){Array.prototype.push.apply(a,c)};b.prependToArray=
+function(a,c){Array.prototype.unshift.apply(a,c)};b.extendObj=function(a,c){for(var e in c)a[e]=c[e]};b.getInheritableProperty=function(a,c){for(;a&&!a.has(c);)a=a.get("Parent");return a?a.get(c):null};b.inherit=function(a,c,e){a.prototype=Object.create(c.prototype);a.prototype.constructor=a;for(var d in e)a.prototype[d]=e[d]};b.loadScript=function(a,c){var e=document.createElement("script"),d=!1;e.setAttribute("src",a);c&&(e.onload=function(){d||c();d=!0});document.getElementsByTagName("head")[0].appendChild(e)};
+return b}();PDFJS.PageViewport=function(){function b(a,c,e,d,b,f){this.viewBox=a;this.scale=c;this.rotation=e;this.offsetX=d;this.offsetY=b;var h=(a[2]+a[0])/2,k=(a[3]+a[1])/2,l,n,p;e%=360;switch(0>e?e+360:e){case 180:e=-1;n=l=0;p=1;break;case 90:e=0;n=l=1;p=0;break;case 270:e=0;n=l=-1;p=0;break;default:e=1,n=l=0,p=-1}f&&(n=-n,p=-p);0===e?(d=Math.abs(k-a[1])*c+d,b=Math.abs(h-a[0])*c+b,f=Math.abs(a[3]-a[1])*c,a=Math.abs(a[2]-a[0])*c):(d=Math.abs(h-a[0])*c+d,b=Math.abs(k-a[1])*c+b,f=Math.abs(a[2]-a[0])*
+c,a=Math.abs(a[3]-a[1])*c);this.transform=[e*c,l*c,n*c,p*c,d-e*c*h-n*c*k,b-l*c*h-p*c*k];this.width=f;this.height=a;this.fontScale=c}b.prototype={clone:function(a){a=a||{};var c="scale"in a?a.scale:this.scale,e="rotation"in a?a.rotation:this.rotation;return new b(this.viewBox.slice(),c,e,this.offsetX,this.offsetY,a.dontFlip)},convertToViewportPoint:function(a,c){return q.applyTransform([a,c],this.transform)},convertToViewportRectangle:function(a){var c=q.applyTransform([a[0],a[1]],this.transform);
+a=q.applyTransform([a[2],a[3]],this.transform);return[c[0],c[1],a[0],a[1]]},convertToPdfPoint:function(a,c){return q.applyInverseTransform([a,c],this.transform)}};return b}();var qa=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,728,711,710,729,733,731,730,732,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8226,8224,8225,8230,8212,8211,402,8260,8249,8250,
+8722,8240,8222,8220,8221,8216,8217,8218,8482,64257,64258,321,338,352,376,381,305,322,339,353,382,0,8364],G=PDFJS.LegacyPromise=function(){return function(){var b,a,c=new Promise(function(c,d){b=c;a=d});c.resolve=b;c.reject=a;return c}}();(function(){function b(c){this._status=a;this._handlers=[];c.call(this,this._resolve.bind(this),this._reject.bind(this))}if(t.Promise)"function"!==typeof t.Promise.all&&(t.Promise.all=function(a){var c=0,e=[],b,k,l=new t.Promise(function(a,c){b=a;k=c});a.forEach(function(a,
+d){c++;a.then(function(a){e[d]=a;c--;0===c&&b(e)},k)});0===c&&b(e);return l}),"function"!==typeof t.Promise.resolve&&(t.Promise.resolve=function(a){return new t.Promise(function(c){c(a)})});else{var a=0,c=2,e={handlers:[],running:!1,unhandledRejections:[],pendingRejectionCheck:!1,scheduleHandlers:function(c){c._status!=a&&(this.handlers=this.handlers.concat(c._handlers),c._handlers=[],this.running||(this.running=!0,setTimeout(this.runHandlers.bind(this),0)))},runHandlers:function(){for(var a=Date.now()+
+1;0<this.handlers.length;){var e=this.handlers.shift(),b=e.thisPromise._status,h=e.thisPromise._value;try{1===b?"function"==typeof e.onResolve&&(h=e.onResolve(h)):"function"===typeof e.onReject&&(h=e.onReject(h),b=1,e.thisPromise._unhandledRejection&&this.removeUnhandeledRejection(e.thisPromise))}catch(k){b=c,h=k}e.nextPromise._updateStatus(b,h);if(Date.now()>=a)break}0<this.handlers.length?setTimeout(this.runHandlers.bind(this),0):this.running=!1},addUnhandledRejection:function(a){this.unhandledRejections.push({promise:a,
+time:Date.now()});this.scheduleRejectionCheck()},removeUnhandeledRejection:function(a){a._unhandledRejection=!1;for(var c=0;c<this.unhandledRejections.length;c++)this.unhandledRejections[c].promise===a&&(this.unhandledRejections.splice(c),c--)},scheduleRejectionCheck:function(){this.pendingRejectionCheck||(this.pendingRejectionCheck=!0,setTimeout(function(){this.pendingRejectionCheck=!1;for(var a=Date.now(),c=0;c<this.unhandledRejections.length;c++)if(500<a-this.unhandledRejections[c].time){var e=
+this.unhandledRejections[c].promise._value,b="Unhandled rejection: "+e;e.stack&&(b+="\n"+e.stack);x(b);this.unhandledRejections.splice(c);c--}this.unhandledRejections.length&&this.scheduleRejectionCheck()}.bind(this),500))}};b.all=function(a){function e(a){k._status!==c&&(n=[],h(a))}var f,h,k=new b(function(a,c){f=a;h=c}),l=a.length,n=[];if(0===l)return f(n),k;for(var p=0,z=a.length;p<z;++p){var s=a[p],w=function(a){return function(e){k._status!==c&&(n[a]=e,l--,0===l&&f(n))}}(p);b.isPromise(s)?s.then(w,
+e):w(s)}return k};b.isPromise=function(a){return a&&"function"===typeof a.then};b.resolve=function(a){return new b(function(c){c(a)})};b.prototype={_status:null,_value:null,_handlers:null,_unhandledRejection:null,_updateStatus:function(a,g){1!==this._status&&this._status!==c&&(1==a&&b.isPromise(g)?g.then(this._updateStatus.bind(this,1),this._updateStatus.bind(this,c)):(this._status=a,this._value=g,a===c&&0===this._handlers.length&&(this._unhandledRejection=!0,e.addUnhandledRejection(this)),e.scheduleHandlers(this)))},
+_resolve:function(a){this._updateStatus(1,a)},_reject:function(a){this._updateStatus(c,a)},then:function(a,c){var f=new b(function(a,c){this.reject=this.resolve=c});this._handlers.push({thisPromise:this,onResolve:a,onReject:c,nextPromise:f});e.scheduleHandlers(this);return f}};t.Promise=b}})();var ua=function(){function b(){this.started={};this.times=[];this.enabled=!0}b.prototype={time:function(a){this.enabled&&(a in this.started&&x("Timer is already running for "+a),this.started[a]=Date.now())},
+timeEnd:function(a){this.enabled&&(a in this.started||x("Timer has not been started for "+a),this.times.push({name:a,start:this.started[a],end:Date.now()}),delete this.started[a])},toString:function(){for(var a=this.times,c="",e=0,d=0,b=a.length;d<b;++d){var f=a[d].name;f.length>e&&(e=f.length)}d=0;for(b=a.length;d<b;++d){for(var h=a[d],f=h.end-h.start,h=h.name;h.length<e;)h+=" ";c+=h+" "+f+"ms\n"}return c}};return b}();PDFJS.createBlob=function(b,a){if("undefined"!==typeof Blob)return new Blob([b],
+{type:a});var c=new MozBlobBuilder;c.append(b);return c.getBlob(a)};PDFJS.createObjectURL=function(){return function(b,a){if(!PDFJS.disableCreateObjectURL&&"undefined"!==typeof URL&&URL.createObjectURL){var c=PDFJS.createBlob(b,a);return URL.createObjectURL(c)}for(var c="data:"+a+";base64,",e=0,d=b.length;e<d;e+=3)var g=b[e]&255,f=b[e+1]&255,h=b[e+2]&255,c=c+("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[g>>2]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[(g&
+3)<<4|f>>4]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[e+1<d?(f&15)<<2|h>>6:64]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[e+2<d?h&63:64]);return c}}();aa.prototype={on:function(b,a,c){var e=this.actionHandler;e[b]&&m('There is already an actionName called "'+b+'"');e[b]=[a,c]},send:function(b,a,c,e){b={action:b,data:a};c&&(a=this.callbackIndex++,this.callbacks[a]=c,b.callbackId=a);e&&this.postMessageTransfers?this.comObj.postMessage(b,e):this.comObj.postMessage(b)}};
+var r=function(){function b(){m("should not call ColorSpace constructor")}b.prototype={getRgb:function(a,c){m("Should not call ColorSpace.getRgb")},getRgbItem:function(a,c,e,d){m("Should not call ColorSpace.getRgbItem")},getRgbBuffer:function(a,c,e,d,b,f){m("Should not call ColorSpace.getRgbBuffer")},getOutputLength:function(a){m("Should not call ColorSpace.getOutputLength")},isPassthrough:function(a){return!1},createRgbBuffer:function(a,c,e,d){if(this.isPassthrough(d))return a.subarray(c);var b=
+new Uint8Array(3*e),f=1<<d;if(1===this.numComps&&e>f&&"DeviceGray"!==this.name&&"DeviceRGB"!==this.name){for(var h=8>=d?new Uint8Array(f):new Uint16Array(f),k=0;k<f;k++)h[k]=k;var l=new Uint8Array(3*f);this.getRgbBuffer(h,0,f,l,0,d);for(k=d=0;k<e;++k)f=3*a[c++],b[d++]=l[f],b[d++]=l[f+1],b[d++]=l[f+2];return b}this.getRgbBuffer(a,c,e,b,0,d);return b},usesZeroToOneRange:!0};b.parse=function(a,c,e){a=b.parseToIR(a,c,e);return a instanceof ja?a:b.fromIR(a)};b.fromIR=function(a){var c=D(a)?a[0]:a;switch(c){case "DeviceGrayCS":return this.singletons.gray;
+case "DeviceRgbCS":return this.singletons.rgb;case "DeviceCmykCS":return this.singletons.cmyk;case "CalGrayCS":var c=a[1].WhitePoint,e=a[1].BlackPoint;return new va(c,e,a[1].Gamma);case "PatternCS":return(a=a[1])&&(a=b.fromIR(a)),new wa(a);case "IndexedCS":return c=a[2],e=a[3],new xa(b.fromIR(a[1]),c,e);case "AlternateCS":return c=a[3],new ja(a[1],b.fromIR(a[2]),S.fromIR(c));case "LabCS":return c=a[1].WhitePoint,e=a[1].BlackPoint,new ya(c,e,a[1].Range);default:m("Unkown name "+c)}return null};b.parseToIR=
+function(a,c,e){if(P(a)){var d=e.get("ColorSpace");R(d)&&(d=d.get(a.name))&&(a=d)}a=c.fetchIfRef(a);if(P(a))switch(this.mode=d=a.name,d){case "DeviceGray":case "G":return"DeviceGrayCS";case "DeviceRGB":case "RGB":return"DeviceRgbCS";case "DeviceCMYK":case "CMYK":return"DeviceCmykCS";case "Pattern":return["PatternCS",null];default:m("unrecognized colorspace "+d)}else if(D(a))switch(this.mode=d=a[0].name,d){case "DeviceGray":case "G":return"DeviceGrayCS";case "DeviceRGB":case "RGB":return"DeviceRgbCS";
+case "DeviceCMYK":case "CMYK":return"DeviceCmykCS";case "CalGray":return c=a[1].getAll(),["CalGrayCS",c];case "CalRGB":return"DeviceRgbCS";case "ICCBased":d=c.fetchIfRef(a[1]).dict.get("N");if(1==d)return"DeviceGrayCS";if(3==d)return"DeviceRgbCS";if(4==d)return"DeviceCmykCS";break;case "Pattern":return(a=a[1])&&(a=b.parseToIR(a,c,e)),["PatternCS",a];case "Indexed":case "I":return e=b.parseToIR(a[1],c,e),d=a[2]+1,c=c.fetchIfRef(a[3]),Y(c)&&(c=c.getBytes()),["IndexedCS",e,d,c];case "Separation":case "DeviceN":var g=
+a[1],d=1;P(g)?d=1:D(g)&&(d=g.length);e=b.parseToIR(a[2],c,e);c=S.getIR(c,c.fetchIfRef(a[3]));return["AlternateCS",d,e,c];case "Lab":return c=a[1].getAll(),["LabCS",c];default:m('unimplemented color space object "'+d+'"')}else m('unrecognized color space object: "'+a+'"');return null};b.isDefaultDecode=function(a,c){if(!a)return!0;if(2*c!==a.length)return x("The decode map is not the correct length"),!0;for(var e=0,d=a.length;e<d;e+=2)if(0!==a[e]||1!=a[e+1])return!1;return!0};b.singletons={get gray(){return U(this,
+"gray",new za)},get rgb(){return U(this,"rgb",new Aa)},get cmyk(){return U(this,"cmyk",new Ba)}};return b}(),ja=function(){function b(a,c,e){this.name="Alternate";this.numComps=a;this.defaultColor=new Float32Array(a);for(var d=0;d<a;++d)this.defaultColor[d]=1;this.base=c;this.tintFn=e}b.prototype={getRgb:function(a,c){var e=new Uint8Array(3);this.getRgbItem(a,c,e,0);return e},getRgbItem:function(a,c,e,d){a="subarray"in a?a.subarray(c,c+this.numComps):Array.prototype.slice.call(a,c,c+this.numComps);
+a=this.tintFn(a);this.base.getRgbItem(a,0,e,d)},getRgbBuffer:function(a,c,e,d,b,f){var h=this.tintFn,k=this.base;f=1/((1<<f)-1);for(var l=k.numComps,n=k.usesZeroToOneRange,p=k.isPassthrough(8)||!n,z=p?b:0,s=p?d:new Uint8Array(l*e),w=this.numComps,F=new Float32Array(w),A=0;A<e;A++){for(var C=0;C<w;C++)F[C]=a[c++]*f;var m=h(F);if(n)for(C=0;C<l;C++)s[z++]=255*m[C];else k.getRgbItem(m,0,s,z),z+=l}p||k.getRgbBuffer(s,0,e,d,b,8)},getOutputLength:function(a){return this.base.getOutputLength(a*this.base.numComps/
+this.numComps)},isPassthrough:r.prototype.isPassthrough,createRgbBuffer:r.prototype.createRgbBuffer,isDefaultDecode:function(a){return r.isDefaultDecode(a,this.numComps)},usesZeroToOneRange:!0};return b}(),wa=function(){function b(a){this.name="Pattern";this.base=a}b.prototype={};return b}(),xa=function(){function b(a,c,e){this.name="Indexed";this.numComps=1;this.defaultColor=new Uint8Array([0]);this.base=a;this.highVal=c;a=a.numComps*c;var d;if(Y(e))d=new Uint8Array(a),e=e.getBytes(a),d.set(e);else if("string"==
+typeof e)for(d=new Uint8Array(a),c=0;c<a;++c)d[c]=e.charCodeAt(c);else e instanceof Uint8Array||e instanceof Array?d=e:m("Unrecognized lookup table: "+e);this.lookup=d}b.prototype={getRgb:function(a,c){return this.base.getRgb(this.lookup,a[c]*this.base.numComps)},getRgbItem:function(a,c,e,d){this.base.getRgbItem(this.lookup,a[c]*this.base.numComps,e,d)},getRgbBuffer:function(a,c,e,d,b){for(var f=this.base,h=f.numComps,k=f.getOutputLength(h),l=this.lookup,n=0;n<e;++n){var p=a[c++]*h;f.getRgbBuffer(l,
+p,1,d,b,8);b+=k}},getOutputLength:function(a){return this.base.getOutputLength(a*this.base.numComps)},isPassthrough:r.prototype.isPassthrough,createRgbBuffer:r.prototype.createRgbBuffer,isDefaultDecode:function(a){return!0},usesZeroToOneRange:!0};return b}(),za=function(){function b(){this.name="DeviceGray";this.numComps=1;this.defaultColor=new Float32Array([0])}b.prototype={getRgb:function(a,c){var e=new Uint8Array(3);this.getRgbItem(a,c,e,0);return e},getRgbItem:function(a,c,e,d){a=255*a[c]|0;e[d]=
+e[d+1]=e[d+2]=0>a?0:255<a?255:a},getRgbBuffer:function(a,c,e,d,b,f){f=255/((1<<f)-1);for(var h=0;h<e;++h){var k=f*a[c++]|0;d[b++]=k;d[b++]=k;d[b++]=k}},getOutputLength:function(a){return 3*a},isPassthrough:r.prototype.isPassthrough,createRgbBuffer:r.prototype.createRgbBuffer,isDefaultDecode:function(a){return r.isDefaultDecode(a,this.numComps)},usesZeroToOneRange:!0};return b}(),Aa=function(){function b(){this.name="DeviceRGB";this.numComps=3;this.defaultColor=new Float32Array([0,0,0])}b.prototype=
+{getRgb:function(a,c){var e=new Uint8Array(3);this.getRgbItem(a,c,e,0);return e},getRgbItem:function(a,c,e,d){var b=255*a[c]|0,f=255*a[c+1]|0;a=255*a[c+2]|0;e[d]=0>b?0:255<b?255:b;e[d+1]=0>f?0:255<f?255:f;e[d+2]=0>a?0:255<a?255:a},getRgbBuffer:function(a,c,e,d,b,f){e*=3;if(8==f)d.set(a.subarray(c,c+e),b);else{f=255/((1<<f)-1);for(var h=0;h<e;++h)d[b++]=f*a[c++]|0}},getOutputLength:function(a){return a},isPassthrough:function(a){return 8==a},createRgbBuffer:r.prototype.createRgbBuffer,isDefaultDecode:function(a){return r.isDefaultDecode(a,
+this.numComps)},usesZeroToOneRange:!0};return b}(),Ba=function(){function b(a,e,d,b,f){var h=a[e+0]*d,k=a[e+1]*d,l=a[e+2]*d;d*=a[e+3];a=h*(-4.387332384609988*h+54.48615194189176*k+18.82290502165302*l+212.25662451639585*d+-285.2331026137004)+k*(1.7149763477362134*k-5.6096736904047315*l+-17.873870861415444*d-5.497006427196366)+l*(-2.5217340131683033*l-21.248923337353073*d+17.5119270841813)+d*(-21.86122147463605*d-189.48180835922747)+255;e=h*(8.841041422036149*h+60.118027045597366*k+6.871425592049007*
+l+31.159100130055922*d+-79.2970844816548)+k*(-15.310361306967817*k+17.575251261109482*l+131.35250912493976*d-190.9453302588951)+l*(4.444339102852739*l+9.8632861493405*d-24.86741582555878)+d*(-20.737325471181034*d-187.80453709719578)+255;h=h*(0.8842522430003296*h+8.078677503112928*k+30.89978309703729*l-0.23883238689178934*d+-14.183576799673286)+k*(10.49593273432072*k+63.02378494754052*l+50.606957656360734*d-112.23884253719248)+l*(0.03296041114873217*l+115.60384449646641*d+-193.58209356861505)+d*(-22.33816807309886*
+d-180.12613974708367)+255;b[f]=255<a?255:0>a?0:a;b[f+1]=255<e?255:0>e?0:e;b[f+2]=255<h?255:0>h?0:h}function a(){this.name="DeviceCMYK";this.numComps=4;this.defaultColor=new Float32Array([0,0,0,1])}a.prototype={getRgb:function(a,e){var d=new Uint8Array(3);b(a,e,1,d,0);return d},getRgbItem:function(a,e,d,g){b(a,e,1,d,g)},getRgbBuffer:function(a,e,d,g,f,h){h=1/((1<<h)-1);for(var k=0;k<d;k++)b(a,e,h,g,f),e+=4,f+=3},getOutputLength:function(a){return 3*(a>>2)},isPassthrough:r.prototype.isPassthrough,createRgbBuffer:r.prototype.createRgbBuffer,
+isDefaultDecode:function(a){return r.isDefaultDecode(a,this.numComps)},usesZeroToOneRange:!0};return a}(),va=function(){function b(a,e,d){this.name="CalGray";this.numComps=1;this.defaultColor=new Float32Array([0]);a||m("WhitePoint missing - required for color space CalGray");e=e||[0,0,0];this.XW=a[0];this.YW=a[1];this.ZW=a[2];this.XB=e[0];this.YB=e[1];this.ZB=e[2];this.G=d||1;(0>this.XW||0>this.ZW||1!==this.YW)&&m("Invalid WhitePoint components for "+this.name+", no fallback available");if(0>this.XB||
+0>this.YB||0>this.ZB)K("Invalid BlackPoint for "+this.name+", falling back to default"),this.XB=this.YB=this.ZB=0;0===this.XB&&0===this.YB&&0===this.ZB||x(this.name+", BlackPoint: XB: "+this.XB+", YB: "+this.YB+", ZB: "+this.ZB+", only default values are supported.");1>this.G&&(K("Invalid Gamma: "+this.G+" for "+this.name+", falling back to default"),this.G=1)}function a(a,e,d,b,f,h){e=Math.pow(e[d]*h,a.G);a=Math.max(116*Math.pow(a.YW*e,1/3)-16,0);b[f]=255*a/100;b[f+1]=255*a/100;b[f+2]=255*a/100}
+b.prototype={getRgb:function(a,e){var d=new Uint8Array(3);this.getRgbItem(a,e,d,0);return d},getRgbItem:function(c,e,d,b){a(this,c,e,d,b,1)},getRgbBuffer:function(c,e,d,b,f,h){h=1/((1<<h)-1);for(var k=0;k<d;++k)a(this,c,e,b,f,h),e+=1,f+=3},getOutputLength:function(a){return 3*a},isPassthrough:r.prototype.isPassthrough,createRgbBuffer:r.prototype.createRgbBuffer,isDefaultDecode:function(a){return r.isDefaultDecode(a,this.numComps)},usesZeroToOneRange:!0};return b}(),ya=function(){function b(a,c,b){this.name=
+"Lab";this.numComps=3;this.defaultColor=new Float32Array([0,0,0]);a||m("WhitePoint missing - required for color space Lab");c=c||[0,0,0];b=b||[-100,100,-100,100];this.XW=a[0];this.YW=a[1];this.ZW=a[2];this.amin=b[0];this.amax=b[1];this.bmin=b[2];this.bmax=b[3];this.XB=c[0];this.YB=c[1];this.ZB=c[2];(0>this.XW||0>this.ZW||1!==this.YW)&&m("Invalid WhitePoint components, no fallback available");if(0>this.XB||0>this.YB||0>this.ZB)K("Invalid BlackPoint, falling back to default"),this.XB=this.YB=this.ZB=
+0;if(this.amin>this.amax||this.bmin>this.bmax)K("Invalid Range, falling back to defaults"),this.amin=-100,this.amax=100,this.bmin=-100,this.bmax=100}function a(a){return a>=6/29?a*a*a:108/841*(a-4/29)}function c(c,d,b,f,h,k){var l=d[b],n=d[b+1];d=d[b+2];!1!==f&&(l=0+100*l/f,n=c.amin+n*(c.amax-c.amin)/f,d=c.bmin+d*(c.bmax-c.bmin)/f);n=n>c.amax?c.amax:n<c.amin?c.amin:n;d=d>c.bmax?c.bmax:d<c.bmin?c.bmin:d;f=(l+16)/116;l=f-d/200;n=c.XW*a(f+n/500);f=c.YW*a(f);l=c.ZW*a(l);1>c.ZW?(c=3.1339*n+-1.617*f+-0.4906*
+l,d=-0.9785*n+1.916*f+0.0333*l,n=0.072*n+-0.229*f+1.4057*l):(c=3.2406*n+-1.5372*f+-0.4986*l,d=-0.9689*n+1.8758*f+0.0415*l,n=0.0557*n+-0.204*f+1.057*l);h[k]=255*Math.sqrt(0>c?0:1<c?1:c);h[k+1]=255*Math.sqrt(0>d?0:1<d?1:d);h[k+2]=255*Math.sqrt(0>n?0:1<n?1:n)}b.prototype={getRgb:function(a,d){var b=new Uint8Array(3);c(this,a,d,!1,b,0);return b},getRgbItem:function(a,b,g,f){c(this,a,b,!1,g,f)},getRgbBuffer:function(a,b,g,f,h,k){k=(1<<k)-1;for(var l=0;l<g;l++)c(this,a,b,k,f,h),b+=3,h+=3},getOutputLength:function(a){return a},
+isPassthrough:r.prototype.isPassthrough,isDefaultDecode:function(a){return!0},usesZeroToOneRange:!1};return b}();E=3;var ka=function(){function b(){m("should not call Pattern constructor")}b.prototype={getPattern:function(a){m("Should not call Pattern.getStyle: "+a)}};b.shadingFromIR=function(a){return N[a[0]].fromIR(a)};b.parseShading=function(a,c,b,d){a=Y(a)?a.dict:a;switch(a.get("ShadingType")){case 2:case E:return new N.RadialAxial(a,c,b,d);default:return Z.notify(da.shadingPattern),new N.Dummy}};
+return b}(),N={SMALL_NUMBER:0.01};N.RadialAxial=function(){function b(a,c,b,d,g){this.matrix=c;this.coordsArr=a.get("Coords");this.shadingType=a.get("ShadingType");this.type="Pattern";this.ctx=g;c=a.get("ColorSpace","CS");this.cs=c=r.parse(c,b,d);d=0;var f=1;a.has("Domain")&&(g=a.get("Domain"),d=g[0],f=g[1]);var h=g=!1;a.has("Extend")&&(h=a.get("Extend"),g=h[0],h=h[1]);if(!(this.shadingType!==E||g&&h)){var k=this.coordsArr[0],l=this.coordsArr[1],n=this.coordsArr[2],p=this.coordsArr[3],z=this.coordsArr[4],
+s=this.coordsArr[5],k=Math.sqrt((k-p)*(k-p)+(l-z)*(l-z));n<=s+k&&s<=n+k&&x("Unsupported radial gradient.")}this.extendStart=g;this.extendEnd=h;n=a.get("Function");if(D(n)){for(var w=[],s=0,k=n.length;s<k;s++)l=b.fetchIfRef(n[s]),ea(l)||m("Invalid function"),w.push(S.parse(b,l));n=function(a){for(var c=[],b=0,d=w.length;b<d;b++)c.push(w[b](a)[0]);return c}}else ea(n)||m("Invalid function"),n=S.parse(b,n);s=f-d;k=s/10;b=this.colorStops=[];if(d>=f||0>=k)K("Bad shading domain.");else{for(l=d;l<=f;l+=
+k)p=c.getRgb(n([l]),0),p=q.makeCssRgb(p),b.push([(l-d)/s,p]);d="transparent";a.has("Background")&&(p=c.getRgb(a.get("Background"),0),d=q.makeCssRgb(p));g||(b.unshift([0,d]),b[1][0]+=N.SMALL_NUMBER);h||(b[b.length-1][0]-=N.SMALL_NUMBER,b.push([1,d]));this.colorStops=b}}b.fromIR=function(a){var c=a[1],b=a[2],d=a[3],g=a[4],f=a[5],h=a[6];return{type:"Pattern",getPattern:function(a){var l;2==c?l=a.createLinearGradient(d[0],d[1],g[0],g[1]):c==E&&(l=a.createRadialGradient(d[0],d[1],f,g[0],g[1],h));a=0;for(var n=
+b.length;a<n;++a){var p=b[a];l.addColorStop(p[0],p[1])}return l}}};b.prototype={getIR:function(){var a=this.coordsArr,c=this.shadingType;if(2==c)var b=[a[0],a[1]],d=[a[2],a[3]],g=null,f=null;else c==E?(b=[a[0],a[1]],d=[a[3],a[4]],g=a[2],f=a[5]):m("getPattern type unknown: "+c);if(a=this.matrix)b=q.applyTransform(b,a),d=q.applyTransform(d,a);return["RadialAxial",c,this.colorStops,b,d,g,f]}};return b}();N.Dummy=function(){function b(){this.type="Pattern"}b.fromIR=function(){return{type:"Pattern",getPattern:function(){return"hotpink"}}};
+b.prototype={getIR:function(){return["Dummy"]}};return b}();var Ca=function(){function b(a,c,b,d,g,f){this.name=a[1][0].name;this.operatorList=a[2];this.matrix=a[3]||[1,0,0,1,0,0];this.bbox=a[4];this.xstep=a[5];this.ystep=a[6];this.paintType=a[7];this.tilingType=a[8];this.color=c;this.objs=d;this.commonObjs=g;this.baseTransform=f;this.type="Pattern";this.ctx=b}b.getIR=function(a,c,b){var d=c.get("Matrix"),g=c.get("BBox"),f=c.get("XStep"),h=c.get("YStep"),k=c.get("PaintType");c=c.get("TilingType");
+return["TilingPattern",b,a,d,g,f,h,k,c]};b.prototype={createPatternCanvas:function(a){var c=this.operatorList,b=this.bbox,d=this.xstep,g=this.ystep,f=this.paintType,h=this.color,k=this.objs,l=this.commonObjs;K("TilingType: "+this.tilingType);var n=b[0],p=b[1],z=b[2],s=b[3],w=[n,p],F=[n+d,p+g],A=F[0]-w[0],F=F[1]-w[1],m=q.singularValueDecompose2dScale(this.matrix),u=q.singularValueDecompose2dScale(this.baseTransform),m=[m[0]*u[0],m[1]*u[1]],A=Math.min(Math.ceil(Math.abs(A*m[0])),3E3),F=Math.min(Math.ceil(Math.abs(F*
+m[1])),3E3),m=J.getCanvas("pattern",A,F,!0),u=m.context,k=new la(u,l,k);k.groupLevel=a.groupLevel;this.setFillAndStrokeStyleToContext(u,f,h);this.setScale(A,F,d,g);this.transformToScale(k);k.transform.apply(k,[1,0,0,1,-w[0],-w[1]]);this.clipBbox(k,b,n,p,z,s);k.executeOperatorList(c);return m.canvas},setScale:function(a,c,b,d){this.scale=[a/b,c/d]},transformToScale:function(a){var c=this.scale;a.transform.apply(a,[c[0],0,0,c[1],0,0])},scaleToContext:function(){var a=this.scale;this.ctx.scale(1/a[0],
+1/a[1])},clipBbox:function(a,c,b,d,g,f){c&&D(c)&&4==c.length&&(a.rectangle(b,d,g-b,f-d),a.clip(),a.endPath())},setFillAndStrokeStyleToContext:function(a,c,b){switch(c){case 1:c=this.ctx;a.fillStyle=c.fillStyle;a.strokeStyle=c.strokeStyle;break;case 2:c=r.singletons.rgb.getRgb(b,0);c=q.makeCssRgb(c);a.fillStyle=c;a.strokeStyle=c;break;default:m("Unsupported paint type: "+c)}},getPattern:function(a,c){var b=this.createPatternCanvas(c);a=this.ctx;a.setTransform.apply(a,this.baseTransform);a.transform.apply(a,
+this.matrix);this.scaleToContext();return a.createPattern(b,"repeat")}};return b}(),S=function(){return{getSampleArray:function(b,a,c,e){for(var d=1,g=0,f=b.length;g<f;g++)d*=b[g];d*=a;b=[];var f=a=0,h=1/(Math.pow(2,c)-1);e=e.getBytes((d*c+7)/8);for(var k=0,g=0;g<d;g++){for(;a<c;)f<<=8,f|=e[k++],a+=8;a-=c;b.push((f>>a)*h);f&=(1<<a)-1}return b},getIR:function(b,a){var c=a.dict;c||(c=a);var e=[this.constructSampled,null,this.constructInterpolated,this.constructStiched,this.constructPostScript],d=c.get("FunctionType");
+(e=e[d])||m("Unknown type of function");return e.call(this,a,c,b)},fromIR:function(b){switch(b[0]){case 0:return this.constructSampledFromIR(b);case 2:return this.constructInterpolatedFromIR(b);case 3:return this.constructStichedFromIR(b);default:return this.constructPostScriptFromIR(b)}},parse:function(b,a){var c=this.getIR(b,a);return this.fromIR(c)},constructSampled:function(b,a){function c(a){for(var c=a.length,b=[],d=0,e=0;e<c;e+=2)b[d]=[a[e],a[e+1]],++d;return b}var e=a.get("Domain"),d=a.get("Range");
+e&&d||m("No domain or range");var g=e.length/2,f=d.length/2,e=c(e),d=c(d),h=a.get("Size"),k=a.get("BitsPerSample"),l=a.get("Order")||1;1!==l&&K("No support for cubic spline interpolation: "+l);l=a.get("Encode");if(!l)for(var l=[],n=0;n<g;++n)l.push(0),l.push(h[n]-1);var l=c(l),n=(n=a.get("Decode"))?c(n):d,p=this.getSampleArray(h,f,k,b);return[0,g,e,l,n,p,h,f,Math.pow(2,k)-1,d]},constructSampledFromIR:function(b){return function(a){var c=b[1],e=b[2],d=b[3],g=b[4],f=b[5],h=b[6],k=b[7],l=b[9];c!=a.length&&
+m("Incorrect number of arguments: "+c+" != "+a.length);for(var n=1<<c,p=new Float64Array(n),z=new Uint32Array(n),s=0;s<n;s++)p[s]=1;for(var w=k,F=1,A=0;A<c;++A){for(var s=e[A][0],C=e[A][1],u=Math.min(Math.max(a[A],s),C),M=d[A][0]+(d[A][1]-d[A][0])/(C-s)*(u-s),C=h[A],M=Math.min(Math.max(M,0),C-1),s=M<C-1?Math.floor(M):M-1,u=s+1-M,M=M-s,q=s*w,r=q+w,s=0;s<n;s++)s&F?(p[s]*=M,z[s]+=r):(p[s]*=u,z[s]+=q);w*=C;F<<=1}a=new Float64Array(k);for(s=0;s<k;++s){for(A=c=0;A<n;A++)c+=f[z[A]+s]*p[A];c=g[s][0]+(g[s][1]-
+g[s][0])/1*(c-0);a[s]=Math.min(Math.max(c,l[s][0]),l[s][1])}return a}},constructInterpolated:function(b,a){var c=a.get("C0")||[0],e=a.get("C1")||[1],d=a.get("N");D(c)&&D(e)||m("Illegal dictionary for interpolated function");for(var g=c.length,f=[],h=0;h<g;++h)f.push(e[h]-c[h]);return[2,c,f,d]},constructInterpolatedFromIR:function(b){var a=b[1],c=b[2],e=b[3],d=c.length;return function(b){b=1==e?b[0]:Math.pow(b[0],e);for(var f=[],h=0;h<d;++h)f.push(a[h]+b*c[h]);return f}},constructStiched:function(b,
+a,c){(b=a.get("Domain"))||m("No domain");1!=b.length/2&&m("Bad domain for stiched function");for(var e=a.get("Functions"),d=[],g=0,f=e.length;g<f;++g)d.push(S.getIR(c,c.fetchIfRef(e[g])));c=a.get("Bounds");a=a.get("Encode");return[3,b,c,a,d]},constructStichedFromIR:function(b){var a=b[1],c=b[2],e=b[3];b=b[4];for(var d=[],g=0,f=b.length;g<f;g++)d.push(S.fromIR(b[g]));return function(b){b=b[0];var k=a[0],l=a[1];b>l?b=l:b<k&&(b=k);k=0;for(l=c.length;k<l&&!(b<c[k]);++k);l=a[0];0<k&&(l=c[k-1]);var f=a[1];
+k<c.length&&(f=c[k]);var g=e[2*k];return d[k]([g+(b-l)*(e[2*k+1]-g)/(f-l)])}},constructPostScript:function(b,a,c){c=a.get("Domain");a=a.get("Range");c||m("No domain.");a||m("No range.");b=new Da(b);b=(new Ea(b)).parse();return[4,c,a,b]},constructPostScriptFromIR:function(b){var a=b[1],c=b[2],e=c.length/2,d=new Fa(b[3]),g=new Ga;return function(b){for(var h=[],k=0,l=a.length/2;k<l;++k)h.push(b[k]);b=h.join("_");if(g.has(b))return g.get(b);h=d.execute(h);l=[];for(k=e-1;0<=k;--k){var n=h.pop(),p=2*k;
+n<c[p]?n=c[p]:n>c[p+1]&&(n=c[p+1]);l[k]=n}g.set(b,l);return l}}}}(),Ga=function(){function b(){this.cache={};this.total=0}b.prototype={has:function(a){return a in this.cache},get:function(a){return this.cache[a]},set:function(a,c){1024>this.total&&(this.cache[a]=c,this.total++)}};return b}(),Ha=function(){function b(a){this.stack=a||[]}b.prototype={push:function(a){100<=this.stack.length&&m("PostScript function stack overflow.");this.stack.push(a)},pop:function(){0>=this.stack.length&&m("PostScript function stack underflow.");
+return this.stack.pop()},copy:function(a){100<=this.stack.length+a&&m("PostScript function stack overflow.");var c=this.stack,b=c.length-a;for(a-=1;0<=a;a--,b++)c.push(c[b])},index:function(a){this.push(this.stack[this.stack.length-a-1])},roll:function(a,c){var b=this.stack,d=b.length-a,g=b.length-1,f=d+(c-Math.floor(c/a)*a),h,k,l;h=d;for(k=g;h<k;h++,k--)l=b[h],b[h]=b[k],b[k]=l;h=d;for(k=f-1;h<k;h++,k--)l=b[h],b[h]=b[k],b[k]=l;h=f;for(k=g;h<k;h++,k--)l=b[h],b[h]=b[k],b[k]=l}};return b}(),Fa=function(){function b(a,
+c){this.operators=a;this.operands=c}b.prototype={execute:function(a){a=new Ha(a);for(var c=0,b=this.operators,d=b.length,g,f;c<d;)if(g=b[c++],"number"==typeof g)a.push(g);else switch(g){case "jz":f=a.pop();(g=a.pop())||(c=f);break;case "j":c=g=a.pop();break;case "abs":g=a.pop();a.push(Math.abs(g));break;case "add":f=a.pop();g=a.pop();a.push(g+f);break;case "and":f=a.pop();g=a.pop();L(g)&&L(f)?a.push(g&&f):a.push(g&f);break;case "atan":g=a.pop();a.push(Math.atan(g));break;case "bitshift":f=a.pop();
+g=a.pop();0<g?a.push(g<<f):a.push(g>>f);break;case "ceiling":g=a.pop();a.push(Math.ceil(g));break;case "copy":g=a.pop();a.copy(g);break;case "cos":g=a.pop();a.push(Math.cos(g));break;case "cvi":g=a.pop()|0;a.push(g);break;case "cvr":break;case "div":f=a.pop();g=a.pop();a.push(g/f);break;case "dup":a.copy(1);break;case "eq":f=a.pop();g=a.pop();a.push(g==f);break;case "exch":a.roll(2,1);break;case "exp":f=a.pop();g=a.pop();a.push(Math.pow(g,f));break;case "false":a.push(!1);break;case "floor":g=a.pop();
+a.push(Math.floor(g));break;case "ge":f=a.pop();g=a.pop();a.push(g>=f);break;case "gt":f=a.pop();g=a.pop();a.push(g>f);break;case "idiv":f=a.pop();g=a.pop();a.push(g/f|0);break;case "index":g=a.pop();a.index(g);break;case "le":f=a.pop();g=a.pop();a.push(g<=f);break;case "ln":g=a.pop();a.push(Math.log(g));break;case "log":g=a.pop();a.push(Math.log(g)/Math.LN10);break;case "lt":f=a.pop();g=a.pop();a.push(g<f);break;case "mod":f=a.pop();g=a.pop();a.push(g%f);break;case "mul":f=a.pop();g=a.pop();a.push(g*
+f);break;case "ne":f=a.pop();g=a.pop();a.push(g!=f);break;case "neg":a.pop();a.push(-f);break;case "not":g=a.pop();L(g)&&L(f)?a.push(g&&f):a.push(g&f);break;case "or":f=a.pop();g=a.pop();L(g)&&L(f)?a.push(g||f):a.push(g|f);break;case "pop":a.pop();break;case "roll":f=a.pop();g=a.pop();a.roll(g,f);break;case "round":g=a.pop();a.push(Math.round(g));break;case "sin":g=a.pop();a.push(Math.sin(g));break;case "sqrt":g=a.pop();a.push(Math.sqrt(g));break;case "sub":f=a.pop();g=a.pop();a.push(g-f);break;case "true":a.push(!0);
+break;case "truncate":g=a.pop();g=0>g?Math.ceil(g):Math.floor(g);a.push(g);break;case "xor":f=a.pop();g=a.pop();L(g)&&L(f)?a.push(g!=f):a.push(g^f);break;default:m("Unknown operator "+g)}return a.stack}};return b}(),Ea=function(){function b(a){this.lexer=a;this.operators=[];this.prev=this.token=null}b.prototype={nextToken:function(){this.prev=this.token;this.token=this.lexer.getToken()},accept:function(a){return this.token.type==a?(this.nextToken(),!0):!1},expect:function(a){if(this.accept(a))return!0;
+m("Unexpected symbol: found "+this.token.type+" expected "+a+".")},parse:function(){this.nextToken();this.expect(v.LBRACE);this.parseBlock();this.expect(v.RBRACE);return this.operators},parseBlock:function(){for(;;)if(this.accept(v.NUMBER))this.operators.push(this.prev.value);else if(this.accept(v.OPERATOR))this.operators.push(this.prev.value);else if(this.accept(v.LBRACE))this.parseCondition();else break},parseCondition:function(){var a=this.operators.length;this.operators.push(null,null);this.parseBlock();
+this.expect(v.RBRACE);if(this.accept(v.IF))this.operators[a]=this.operators.length,this.operators[a+1]="jz";else if(this.accept(v.LBRACE)){var c=this.operators.length;this.operators.push(null,null);var b=this.operators.length;this.parseBlock();this.expect(v.RBRACE);this.expect(v.IFELSE);this.operators[c]=this.operators.length;this.operators[c+1]="j";this.operators[a]=b;this.operators[a+1]="jz"}else m("PS Function: error parsing conditional.")}};return b}(),v={LBRACE:0,RBRACE:1,NUMBER:2,OPERATOR:3,
+IF:4,IFELSE:5},T=function(){function b(a,b){this.type=a;this.value=b}var a={};b.getOperator=function(c){var e=a[c];return e?e:a[c]=new b(v.OPERATOR,c)};b.LBRACE=new b(v.LBRACE,"{");b.RBRACE=new b(v.RBRACE,"}");b.IF=new b(v.IF,"IF");b.IFELSE=new b(v.IFELSE,"IFELSE");return b}(),Da=function(){function b(a){this.stream=a;this.nextChar()}b.prototype={nextChar:function(){return this.currentChar=this.stream.getByte()},getToken:function(){for(var a=!1,c=this.currentChar;;){if(0>c)return EOF;if(a){if(10===
+c||13===c)a=!1}else if(37==c)a=!0;else if(!Lexer.isSpace(c))break;c=this.nextChar()}switch(c|0){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:case 43:case 45:case 46:return new T(v.NUMBER,this.getNumber());case 123:return this.nextChar(),T.LBRACE;case 125:return this.nextChar(),T.RBRACE}for(a=String.fromCharCode(c);0<=(c=this.nextChar())&&(65<=c&&90>=c||97<=c&&122>=c);)a+=String.fromCharCode(c);switch(a.toLowerCase()){case "if":return T.IF;case "ifelse":return T.IFELSE;
+default:return T.getOperator(a)}},getNumber:function(){for(var a=this.currentChar,c=String.fromCharCode(a);0<=(a=this.nextChar());)if(48<=a&&57>=a||45===a||46===a)c+=String.fromCharCode(a);else break;a=parseFloat(c);isNaN(a)&&m("Invalid floating point number: "+a);return a}};return b}(),H=function(){function b(a,b,d){var g=q.getAxialAlignedBoundingBox(b,d);b=g[0];d=g[1];var f=g[2],g=g[3];if(b===f||d===g)return[1,0,0,1,a[0],a[1]];f=(a[2]-a[0])/(f-b);g=(a[3]-a[1])/(g-d);return[f,0,0,g,a[0]-b*f,a[1]-
+d*g]}function a(a){if(a.data)this.data=a.data;else{var b=a.dict;a=this.data={};a.subtype=b.get("Subtype").name;var d=b.get("Rect");a.rect=q.normalizeRect(d);a.annotationFlags=b.get("F");d=b.get("C");D(d)&&3===d.length?a.color=d:a.color=[0,0,0];if(b.has("BS"))d=b.get("BS"),a.borderWidth=d.has("W")?d.get("W"):1;else if(d=b.get("Border")||[0,0,1],a.borderWidth=d[2]||0,(d=d[3])&&D(d)){var g=d.length;if(0<g){for(var f=!1,h=0,k=0;k<g;k++)if(0<=+d[k])0<d[k]&&h++;else{f=!0;break}if(f||0===h)a.borderWidth=
+0}}var l;d=b.get("AP");R(d)?(d=d.get("N"),R(d)?(b=b.get("AS"))&&d.has(b.name)&&(l=d.get(b.name)):l=d):l=void 0;this.appearance=l;a.hasAppearance=!!this.appearance}}a.prototype={getData:function(){return this.data},hasHtml:function(){return!1},getHtmlElement:function(a){throw new ta("getHtmlElement() should be implemented in subclass");},getEmptyContainer:function(a,b){W&&m("getEmptyContainer() should be called from main thread");b=b||this.data.rect;var d=document.createElement(a);d.style.width=Math.ceil(b[2]-
+b[0])+"px";d.style.height=Math.ceil(b[3]-b[1])+"px";return d},isViewable:function(){var a=this.data;return!(!a||a.annotationFlags&&a.annotationFlags&34||!a.rect)},loadResources:function(a){var b=new G;this.appearance.dict.getAsync("Resources").then(function(d){d?(new ObjectLoader(d.map,a,d.xref)).load().then(function(){b.resolve(d)}):b.resolve()}.bind(this));return b},getOperatorList:function(a){var e=new G;if(!this.appearance)return e.resolve(new OperatorList),e;var d=this.data,g=this.appearance.dict,
+f=this.loadResources("ExtGState ColorSpace Pattern Shading XObject Font".split(" ")),h=g.get("BBox")||[0,0,1,1],k=g.get("Matrix")||[1,0,0,1,0,0],l=b(d.rect,h,k);f.then(function(b){var f=new OperatorList;f.addOp(y.beginAnnotation,[d.rect,l,k]);a.getOperatorList(this.appearance,b,f);f.addOp(y.endAnnotation,[]);e.resolve(f)}.bind(this));return e}};a.getConstructor=function(c,b){if(c){if("Link"===c)return Ia;if("Text"===c)return Ja;if("Widget"===c){if(b)return"Tx"===b?Ka:ca}else return a}};a.fromData=
+function(c){var b=a.getConstructor(c.subtype,c.fieldType);if(b)return new b({data:c})};a.fromRef=function(c,b){var d=c.fetchIfRef(b);if(R(d)){var g=d.get("Subtype");if(g=P(g)?g.name:""){var f=q.getInheritableProperty(d,"FT"),f=P(f)?f.name:"";if(f=a.getConstructor(g,f)){d=new f({dict:d,ref:b});if(d.isViewable())return d;x("unimplemented annotation type: "+g)}}}};a.appendToOperatorList=function(a,b,d,g){var f=new G;d=[];for(var h=0,k=a.length;h<k;++h)d.push(a[h].getOperatorList(g));Promise.all(d).then(function(a){b.addOp(y.beginAnnotations,
+[]);for(var c=0,d=a.length;c<d;++c)b.addOpList(a[c]);b.addOp(y.endAnnotations,[]);f.resolve()},function(a){f.reject(a)});return f};return a}();PDFJS.Annotation=H;var ca=function(){function b(a){H.call(this,a);if(!a.data){var b=a.dict,d=this.data;d.fieldValue=V(q.getInheritableProperty(b,"V")||"");d.alternativeText=V(b.get("TU")||"");d.defaultAppearance=q.getInheritableProperty(b,"DA")||"";var g=q.getInheritableProperty(b,"FT");d.fieldType=P(g)?g.name:"";d.fieldFlags=q.getInheritableProperty(b,"Ff")||
+0;this.fieldResources=q.getInheritableProperty(b,"DR")||new Dict;var g=[],f=b;for(a=a.ref;f;){var b=f.get("Parent"),h=f.getRaw("Parent");if(f=f.get("T"))g.unshift(V(f));else{var f=b.get("Kids"),k,l;k=0;for(l=f.length;k<l;k++){var n=f[k];if(n.num==a.num&&n.gen==a.gen)break}g.unshift("`"+k)}f=b;a=h}d.fullName=g.join(".")}}var a=H.prototype;q.inherit(b,H,{isViewable:function(){return"Sig"===this.data.fieldType?(x("unimplemented annotation type: Widget signature"),!1):a.isViewable.call(this)}});return b}(),
+Ka=function(){function b(a){ca.call(this,a);a.data||(this.data.textAlignment=q.getInheritableProperty(a.dict,"Q"))}q.inherit(b,ca,{hasHtml:function(){return!this.data.hasAppearance&&!!this.data.fieldValue},getHtmlElement:function(a){W&&m("getHtmlElement() shall be called from main thread");var c=this.data,b=this.getEmptyContainer("div");b.style.display="table";var d=document.createElement("div");d.textContent=c.fieldValue;d.style.textAlign=["left","center","right"][c.textAlignment];d.style.verticalAlign=
+"middle";d.style.display="table-cell";a=c.fontRefName?a.getData(c.fontRefName):null;var g=d.style;g.fontSize=c.fontSize+"px";g.direction=0>c.fontDirection?"rtl":"ltr";a&&(g.fontWeight=a.black?a.bold?"bolder":"bold":a.bold?"bold":"normal",g.fontStyle=a.italic?"italic":"normal",c=a.loadedName,g.fontFamily=(c?'"'+c+'", ':"")+(a.fallbackName||"Helvetica, sans-serif"));b.appendChild(d);return b},getOperatorList:function(a){if(this.appearance)return H.prototype.getOperatorList.call(this,a);var c=new G,
+b=new OperatorList,d=this.data,g=d.defaultAppearance;if(!g)return c.resolve(b),c;for(var f=Stream,h=g.length,k=new Uint8Array(h),l=0;l<h;++l)k[l]=g.charCodeAt(l)&255;g=new f(k);a.getOperatorList(g,this.fieldResources,b);a=b.fnArray;g=b.argsArray;d.rgb=[0,0,0];for(f=0;0>f;++f)h=a[f],k=g[f],h===y.setFont?(d.fontRefName=k[0],h=k[1],0>h?(d.fontDirection=-1,d.fontSize=-h):(d.fontDirection=1,d.fontSize=h)):h===y.setFillRGBColor?d.rgb=k:h===y.setFillGray&&(h=255*k[0],d.rgb=[h,h,h]);c.resolve(b);return c}});
+return b}(),Ja=function(){function b(a){H.call(this,a);if(!a.data){a=a.dict;var c=this.data,b=a.get("Contents"),d=a.get("T");c.content=V(b||"");c.title=V(d||"");c.name=a.has("Name")?a.get("Name").name:"Note"}}q.inherit(b,H,{getOperatorList:function(a){a=new G;a.resolve(new OperatorList);return a},hasHtml:function(){return!0},getHtmlElement:function(a){W&&m("getHtmlElement() shall be called from main thread");var c=this.data,b=c.rect;10>b[3]-b[1]&&(b[3]=b[1]+10);10>b[2]-b[0]&&(b[2]=b[0]+(b[3]-b[1]));
+var d=this.getEmptyContainer("section",b);d.className="annotText";a=document.createElement("img");a.style.height=d.style.height;var g=c.name;a.src=PDFJS.imageResourcesPath+"annotation-"+g.toLowerCase()+".svg";a.alt="[{{type}} Annotation]";a.dataset.l10nId="text_annotation_type";a.dataset.l10nArgs=JSON.stringify({type:g});var f=document.createElement("div");f.setAttribute("hidden",!0);var g=document.createElement("h1"),h=document.createElement("p");f.style.left=Math.floor(b[2]-b[0])+"px";f.style.top=
+"0px";g.textContent=c.title;if(c.content||c.title){for(var b=document.createElement("span"),c=c.content.split(/(?:\r\n?|\n)/),k=0,l=c.length;k<l;++k)b.appendChild(document.createTextNode(c[k])),k<l-1&&b.appendChild(document.createElement("br"));h.appendChild(b);b=function(){d.style.zIndex+=1;f.removeAttribute("hidden")};c=function(a){if(a.toElement||a.relatedTarget)d.style.zIndex-=1,f.setAttribute("hidden",!0)};f.addEventListener("mouseover",b,!1);f.addEventListener("mouseout",c,!1);a.addEventListener("mouseover",
+b,!1);a.addEventListener("mouseout",c,!1)}else f.setAttribute("hidden",!0);f.appendChild(g);f.appendChild(h);d.appendChild(a);d.appendChild(f);return d}});return b}(),Ia=function(){function b(a){H.call(this,a);if(!a.data){var c=a.dict;a=this.data;var b=c.get("A");if(b)if(c=b.get("S").name,"URI"===c){var d;d=b.get("URI");d=0===d.indexOf("www.")?"http://"+d:d;$(d,!1)||(d="");a.url=d}else"GoTo"===c?a.dest=b.get("D"):"GoToR"===c?(c=b.get("F"),R(c)&&(d=c.get("F")||""),$(d,!1)||(d=""),a.url=d,a.dest=b.get("D")):
+"Named"===c?a.action=b.get("N").name:x("unrecognized link type: "+c);else c.has("Dest")&&(d=c.get("Dest"),a.dest=P(d)?d.name:d)}}q.inherit(b,H,{hasOperatorList:function(){return!1},hasHtml:function(){return!0},getHtmlElement:function(a){a=this.data.rect;var c=document.createElement("a"),b=this.data.borderWidth;c.style.borderWidth=b+"px";for(var d=this.data.color,g=[],f=0;3>f;++f)g[f]=Math.round(255*d[f]);c.style.borderColor=q.makeCssRgb(g);c.style.borderStyle="solid";d=a[3]-a[1]-2*b;c.style.width=
+a[2]-a[0]-2*b+"px";c.style.height=d+"px";c.href=this.data.url||"";return c}});return b}();PDFJS.maxImageSize=void 0===PDFJS.maxImageSize?-1:PDFJS.maxImageSize;PDFJS.disableFontFace=void 0===PDFJS.disableFontFace?!1:PDFJS.disableFontFace;PDFJS.imageResourcesPath=void 0===PDFJS.imageResourcesPath?"":PDFJS.imageResourcesPath;PDFJS.disableWorker=void 0===PDFJS.disableWorker?!1:PDFJS.disableWorker;PDFJS.workerSrc=void 0===PDFJS.workerSrc?null:PDFJS.workerSrc;PDFJS.disableRange=void 0===PDFJS.disableRange?
+!1:PDFJS.disableRange;PDFJS.disableAutoFetch=void 0===PDFJS.disableAutoFetch?!1:PDFJS.disableAutoFetch;PDFJS.pdfBug=void 0===PDFJS.pdfBug?!1:PDFJS.pdfBug;PDFJS.postMessageTransfers=void 0===PDFJS.postMessageTransfers?!0:PDFJS.postMessageTransfers;PDFJS.disableCreateObjectURL=void 0===PDFJS.disableCreateObjectURL?!1:PDFJS.disableCreateObjectURL;PDFJS.verbosity=void 0===PDFJS.verbosity?PDFJS.VERBOSITY_LEVELS.warnings:PDFJS.verbosity;PDFJS.getDocument=function(b,a,c,e){var d,g;"string"===typeof b?b=
+{url:b}:"object"==typeof b&&null!==b&&void 0!==b&&"byteLength"in b?b={data:b}:"object"!==typeof b&&m("Invalid parameter in getDocument, need either Uint8Array, string or a parameter object");b.url||b.data||m("Invalid parameter array, need either .data or .url");var f={};for(d in b)f[d]="url"===d&&"undefined"!==typeof window?pa(window.location.href,b[d]):b[d];b=new PDFJS.LegacyPromise;d=new PDFJS.LegacyPromise;g=new La(b,d,a,e);b.then(function(){g.passwordCallback=c;g.fetchDocument(f)});return d};
+var Ma=function(){function b(a,c){this.pdfInfo=a;this.transport=c}b.prototype={get numPages(){return this.pdfInfo.numPages},get fingerprint(){return this.pdfInfo.fingerprint},get embeddedFontsUsed(){return this.transport.embeddedFontsUsed},getPage:function(a){return this.transport.getPage(a)},getPageIndex:function(a){return this.transport.getPageIndex(a)},getDestinations:function(){return this.transport.getDestinations()},getJavaScript:function(){var a=new PDFJS.LegacyPromise;a.resolve(this.pdfInfo.javaScript);
+return a},getOutline:function(){var a=new PDFJS.LegacyPromise;a.resolve(this.pdfInfo.outline);return a},getMetadata:function(){var a=new PDFJS.LegacyPromise,c=this.pdfInfo.metadata;a.resolve({info:this.pdfInfo.info,metadata:c?new PDFJS.Metadata(c):null});return a},isEncrypted:function(){var a=new PDFJS.LegacyPromise;a.resolve(this.pdfInfo.encrypted);return a},getData:function(){var a=new PDFJS.LegacyPromise;this.transport.getData(a);return a},dataLoaded:function(){return this.transport.dataLoaded()},
+cleanup:function(){this.transport.startCleanup()},destroy:function(){this.transport.destroy()}};return b}(),Pa=function(){function b(a,c){this.pageInfo=a;this.transport=c;this.stats=new ua;this.stats.enabled=!!t.PDFJS.enableStats;this.commonObjs=c.commonObjs;this.objs=new ma;this.pendingDestroy=this.cleanupAfterRender=this.receivingOperatorList=!1;this.renderTasks=[]}b.prototype={get pageNumber(){return this.pageInfo.pageIndex+1},get rotate(){return this.pageInfo.rotate},get ref(){return this.pageInfo.ref},
+get view(){return this.pageInfo.view},getViewport:function(a,c){2>arguments.length&&(c=this.rotate);return new PDFJS.PageViewport(this.view,a,c,0,0)},getAnnotations:function(){if(this.annotationsPromise)return this.annotationsPromise;var a=new PDFJS.LegacyPromise;this.annotationsPromise=a;this.transport.getAnnotations(this.pageInfo.pageIndex);return a},render:function(a){function c(a){var c=f.renderTasks.indexOf(d);0<=c&&f.renderTasks.splice(c,1);f.cleanupAfterRender&&(f.pendingDestroy=!0);f._tryDestroy();
+a?g.promise.reject(a):g.promise.resolve();b.timeEnd("Rendering");b.timeEnd("Overall")}var b=this.stats;b.time("Overall");this.pendingDestroy=!1;this.displayReadyPromise||(this.receivingOperatorList=!0,this.displayReadyPromise=new G,this.operatorList={fnArray:[],argsArray:[],lastChunk:!1},this.stats.time("Page Request"),this.transport.messageHandler.send("RenderPageRequest",{pageIndex:this.pageNumber-1}));var d=new Na(c,a,this.objs,this.commonObjs,this.operatorList,this.pageNumber);this.renderTasks.push(d);
+var g=new Oa(d),f=this;this.displayReadyPromise.then(function(a){f.pendingDestroy?c():(b.time("Rendering"),d.initalizeGraphics(a),d.operatorListChanged())},function(a){c(a)});return g},getTextContent:function(){var a=new PDFJS.LegacyPromise;this.transport.messageHandler.send("GetTextContent",{pageIndex:this.pageNumber-1},function(c){a.resolve(c)});return a},getOperationList:function(){var a=new PDFJS.LegacyPromise;a.resolve({dependencyFontsID:null,operatorList:null});return a},destroy:function(){this.pendingDestroy=
+!0;this._tryDestroy()},_tryDestroy:function(){this.pendingDestroy&&0===this.renderTasks.length&&!this.receivingOperatorList&&(delete this.operatorList,delete this.displayReadyPromise,this.objs.clear(),this.pendingDestroy=!1)},_startRenderPage:function(a){this.displayReadyPromise.resolve(a)},_renderPageChunk:function(a){for(var c=0,b=a.length;c<b;c++)this.operatorList.fnArray.push(a.fnArray[c]),this.operatorList.argsArray.push(a.argsArray[c]);this.operatorList.lastChunk=a.lastChunk;for(c=0;c<this.renderTasks.length;c++)this.renderTasks[c].operatorListChanged();
+a.lastChunk&&(this.receivingOperatorList=!1,this._tryDestroy())}};return b}(),La=function(){function b(a,c,b,d){this.pdfDataRangeTransport=b;this.workerReadyPromise=c;this.progressCallback=d;this.commonObjs=new ma;this.pageCache=[];this.pagePromises=[];this.embeddedFontsUsed=!1;this.passwordCallback=null;if(!t.PDFJS.disableWorker&&"undefined"!==typeof Worker){(c=PDFJS.workerSrc)||m("No PDFJS.workerSrc specified");try{var g=new Worker(c),f=new aa("main",g);this.messageHandler=f;f.on("test",function(b){b&&
+b.supportTypedArray?(this.worker=g,b.supportTransfers||(PDFJS.postMessageTransfers=!1),this.setupMessageHandler(f),a.resolve()):(t.PDFJS.disableWorker=!0,this.loadFakeWorkerFiles().then(function(){this.setupFakeWorker();a.resolve()}.bind(this)))}.bind(this));var h=new Uint8Array([PDFJS.postMessageTransfers?255:0]);try{f.send("test",h,null,[h.buffer])}catch(k){K("Cannot use postMessage transfers"),h[0]=0,f.send("test",h)}return}catch(l){K("The worker has been disabled.")}}t.PDFJS.disableWorker=!0;
+this.loadFakeWorkerFiles().then(function(){this.setupFakeWorker();a.resolve()}.bind(this))}b.prototype={destroy:function(){this.pageCache=[];this.pagePromises=[];var a=this;this.messageHandler.send("Terminate",null,function(){a.worker&&a.worker.terminate()})},loadFakeWorkerFiles:function(){PDFJS.fakeWorkerFilesLoadedPromise||(PDFJS.fakeWorkerFilesLoadedPromise=new G,q.loadScript(PDFJS.workerSrc,function(){PDFJS.fakeWorkerFilesLoadedPromise.resolve()}));return PDFJS.fakeWorkerFilesLoadedPromise},setupFakeWorker:function(){x("Setting up fake worker.");
+var a={postMessage:function(b){a.onmessage({data:b})},terminate:function(){}},b=new aa("main",a);this.setupMessageHandler(b);PDFJS.WorkerMessageHandler.setup(b)},setupMessageHandler:function(a){function b(c){a.send("UpdatePassword",c)}this.messageHandler=a;var e=this.pdfDataRangeTransport;e&&(e.addRangeListener(function(b,c){a.send("OnDataRange",{begin:b,chunk:c})}),e.addProgressListener(function(b){a.send("OnDataProgress",{loaded:b})}),a.on("RequestDataRange",function(a){e.requestDataRange(a.begin,
+a.end)},this));a.on("GetDoc",function(a){this.pdfDocument=a=new Ma(a.pdfInfo,this);this.workerReadyPromise.resolve(a)},this);a.on("NeedPassword",function(a){if(this.passwordCallback)return this.passwordCallback(b,ha.NEED_PASSWORD);this.workerReadyPromise.reject(a.exception.message,a.exception)},this);a.on("IncorrectPassword",function(a){if(this.passwordCallback)return this.passwordCallback(b,ha.INCORRECT_PASSWORD);this.workerReadyPromise.reject(a.exception.message,a.exception)},this);a.on("InvalidPDF",
+function(a){this.workerReadyPromise.reject(a.exception.name,a.exception)},this);a.on("MissingPDF",function(a){this.workerReadyPromise.reject(a.exception.message,a.exception)},this);a.on("UnknownError",function(a){this.workerReadyPromise.reject(a.exception.message,a.exception)},this);a.on("GetPage",function(a){a=a.pageInfo;var b=new Pa(a,this);this.pageCache[a.pageIndex]=b;this.pagePromises[a.pageIndex].resolve(b)},this);a.on("GetAnnotations",function(a){this.pageCache[a.pageIndex].annotationsPromise.resolve(a.annotations)},
+this);a.on("StartRenderPage",function(a){var b=this.pageCache[a.pageIndex];b.stats.timeEnd("Page Request");b._startRenderPage(a.transparency)},this);a.on("RenderPageChunk",function(a){this.pageCache[a.pageIndex]._renderPageChunk(a.operatorList)},this);a.on("commonobj",function(a){var b=a[0],c=a[1];if(!this.commonObjs.hasData(b))switch(c){case "Font":a=a[2];var e;if("error"in a){var k=a.error;x("Error during font loading: "+k);this.commonObjs.resolve(b,k);break}else e=new Qa(a);Q.bind([e],function(a){this.commonObjs.resolve(b,
+e)}.bind(this));break;case "FontPath":this.commonObjs.resolve(b,a[2]);break;default:k("Got unknown common object type "+c)}},this);a.on("obj",function(a){var b=a[0],c=a[2],e=this.pageCache[a[1]];if(!e.objs.hasData(b))switch(c){case "JpegStream":a=a[3];ra(b,a,e.objs);break;case "Image":a=a[3];e.objs.resolve(b,a);"data"in a&&8E6<a.data.length&&(e.cleanupAfterRender=!0);break;default:m("Got unknown object type "+c)}},this);a.on("DocProgress",function(a){this.progressCallback&&this.progressCallback({loaded:a.loaded,
+total:a.total})},this);a.on("DocError",function(a){this.workerReadyPromise.reject(a)},this);a.on("PageError",function(a){var b=this.pageCache[a.pageNum-1];b.displayReadyPromise?b.displayReadyPromise.reject(a.error):m(a.error)},this);a.on("JpegDecode",function(a,b){var c=a[0],e=a[1];3!=e&&1!=e&&m("Only 3 component or 1 component can be returned");var k=new Image;k.onload=function(){var a=k.width,c=k.height,d=a*c,f=4*d,d=new Uint8Array(d*e),s=fa(a,c).getContext("2d");s.drawImage(k,0,0);s=s.getImageData(0,
+0,a,c).data;if(3==e)for(var w=0,m=0;w<f;w+=4,m+=3)d[m]=s[w],d[m+1]=s[w+1],d[m+2]=s[w+2];else if(1==e)for(m=w=0;w<f;w+=4,m++)d[m]=s[w];b.resolve({data:d,width:a,height:c})}.bind(this);k.src=c})},fetchDocument:function(a){a.disableAutoFetch=PDFJS.disableAutoFetch;a.chunkedViewerLoading=!!this.pdfDataRangeTransport;this.messageHandler.send("GetDocRequest",{source:a,disableRange:PDFJS.disableRange,maxImageSize:PDFJS.maxImageSize,disableFontFace:PDFJS.disableFontFace,disableCreateObjectURL:PDFJS.disableCreateObjectURL,
+verbosity:PDFJS.verbosity})},getData:function(a){this.messageHandler.send("GetData",null,function(b){a.resolve(b)})},dataLoaded:function(){var a=new PDFJS.LegacyPromise;this.messageHandler.send("DataLoaded",null,function(b){a.resolve(b)});return a},getPage:function(a,b){var e=a-1;if(e in this.pagePromises)return this.pagePromises[e];b=new PDFJS.LegacyPromise;this.pagePromises[e]=b;this.messageHandler.send("GetPageRequest",{pageIndex:e});return b},getPageIndex:function(a){var b=new PDFJS.LegacyPromise;
+this.messageHandler.send("GetPageIndex",{ref:a},function(a){b.resolve(a)});return b},getAnnotations:function(a){this.messageHandler.send("GetAnnotationsRequest",{pageIndex:a})},getDestinations:function(){var a=new PDFJS.LegacyPromise;this.messageHandler.send("GetDestinations",null,function(b){a.resolve(b)});return a},startCleanup:function(){this.messageHandler.send("Cleanup",null,function(){for(var a=0,b=this.pageCache.length;a<b;a++){var e=this.pageCache[a];e&&e.destroy()}this.commonObjs.clear();
+Q.clear()}.bind(this))}};return b}(),ma=function(){function b(){this.objs={}}b.prototype={ensureObj:function(a){if(this.objs[a])return this.objs[a];var b={promise:new G,data:null,resolved:!1};return this.objs[a]=b},get:function(a,b){if(b)return this.ensureObj(a).promise.then(b),null;var e=this.objs[a];e&&e.resolved||m("Requesting object that isn't resolved yet "+a);return e.data},resolve:function(a,b){var e=this.ensureObj(a);e.resolved=!0;e.data=b;e.promise.resolve(b)},isResolved:function(a){var b=
+this.objs;return b[a]?b[a].resolved:!1},hasData:function(a){return this.isResolved(a)},getData:function(a){var b=this.objs;return b[a]&&b[a].resolved?b[a].data:null},clear:function(){this.objs={}}};return b}(),Oa=function(){function b(a){this.internalRenderTask=a;this.promise=new PDFJS.LegacyPromise}b.prototype.cancel=function(){this.internalRenderTask.cancel()};return b}(),Na=function(){function b(a,b,e,d,g,f){this.callback=a;this.params=b;this.objs=e;this.commonObjs=d;this.operatorListIdx=null;
+this.operatorList=g;this.pageNumber=f;this.running=!1;this.graphicsReadyCallback=null;this.cancelled=this.graphicsReady=!1}b.prototype={initalizeGraphics:function(a){if(!this.cancelled){PDFJS.pdfBug&&"StepperManager"in t&&t.StepperManager.enabled&&(this.stepper=t.StepperManager.create(this.pageNumber-1),this.stepper.init(this.operatorList),this.stepper.nextBreakPoint=this.stepper.getNextBreakPoint());var b=this.params;this.gfx=new la(b.canvasContext,this.commonObjs,this.objs,b.textLayer,b.imageLayer);
+this.gfx.beginDrawing(b.viewport,a);this.operatorListIdx=0;this.graphicsReady=!0;this.graphicsReadyCallback&&this.graphicsReadyCallback()}},cancel:function(){this.running=!1;this.cancelled=!0;this.callback("cancelled")},operatorListChanged:function(){this.graphicsReady?(this.stepper&&this.stepper.updateOperatorList(this.operatorList),this.running||this._continue()):this.graphicsReadyCallback||(this.graphicsReadyCallback=this._continue.bind(this))},_continue:function(){this.running=!0;this.cancelled||
+(this.params.continueCallback?this.params.continueCallback(this._next.bind(this)):this._next())},_next:function(){this.cancelled||(this.operatorListIdx=this.gfx.executeOperatorList(this.operatorList,this.operatorListIdx,this._continue.bind(this),this.stepper),this.operatorListIdx===this.operatorList.argsArray.length&&(this.running=!1,this.operatorList.lastChunk&&(this.gfx.endDrawing(),this.callback())))}};return b}();PDFJS.Metadata=function(){function b(a){return a.replace(/>\\376\\377([^<]+)/g,function(a,
+b){for(var c=b.replace(/\\([0-3])([0-7])([0-7])/g,function(a,b,c,d){return String.fromCharCode(64*b+8*c+1*d)}),f="",h=0;h<c.length;h+=2)var k=256*c.charCodeAt(h)+c.charCodeAt(h+1),f=f+("&#x"+(65536+k).toString(16).substring(1)+";");return">"+f})}function a(a){"string"===typeof a?(a=b(a),a=(new DOMParser).parseFromString(a,"application/xml")):a instanceof Document||m("Metadata: Invalid metadata object");this.metaDocument=a;this.metadata={};this.parse()}a.prototype={parse:function(){var a=this.metaDocument.documentElement;
+if("rdf:rdf"!==a.nodeName.toLowerCase())for(a=a.firstChild;a&&"rdf:rdf"!==a.nodeName.toLowerCase();)a=a.nextSibling;var b=a?a.nodeName.toLowerCase():null;if(a&&"rdf:rdf"===b&&a.hasChildNodes()){var a=a.childNodes,d,g,f,h,k,l;f=0;for(k=a.length;f<k;f++)if(b=a[f],"rdf:description"===b.nodeName.toLowerCase())for(h=0,l=b.childNodes.length;h<l;h++)"#text"!==b.childNodes[h].nodeName.toLowerCase()&&(d=b.childNodes[h],g=d.nodeName.toLowerCase(),this.metadata[g]=d.textContent.trim())}},get:function(a){return this.metadata[a]||
+null},has:function(a){return"undefined"!==typeof this.metadata[a]}};return a}();var J=function(){var b={};return{getCanvas:function(a,c,e,d){a in b?(a=b[a],a.canvas.width=c,a.canvas.height=e,a.context.setTransform(1,0,0,1,0,0)):(c=fa(c,e),e=c.getContext("2d"),d&&ga(e),b[a]=a={canvas:c,context:e});return a},clear:function(){b={}}}}(),na=function(){function b(a){this.alphaIsShape=!1;this.fontSize=0;this.fontSizeScale=1;this.textMatrix=ia;this.fontMatrix=ba;this.wordSpacing=this.charSpacing=this.lineY=
+this.lineX=this.y=this.x=this.leading=0;this.textHScale=1;this.textRenderingMode=X;this.textRise=0;this.fillColorSpace=r.singletons.gray;this.fillColorSpaceObj=null;this.strokeColorSpace=r.singletons.gray;this.strokeColorObj=this.fillColorObj=this.strokeColorSpaceObj=null;this.strokeColor=this.fillColor="#000000";this.lineWidth=this.strokeAlpha=this.fillAlpha=1;this.old=a}b.prototype={clone:function(){return Object.create(this)},setCurrentPoint:function(a,b){this.x=a;this.y=b}};return b}(),la=function(){function b(a,
+b,c,d,e){this.ctx=a;this.current=new na;this.stateStack=[];this.pendingClip=null;this.pendingEOFill=!1;this.xobjs=this.res=null;this.commonObjs=b;this.objs=c;this.textLayer=d;this.imageLayer=e;this.groupStack=[];this.baseTransform=this.processingType3=null;this.baseTransformStack=[];this.groupLevel=0;a&&ga(a)}function a(a,b){if("undefined"!==typeof ImageData&&b instanceof ImageData)a.putImageData(b,0,0);else{var c=b.height/16|0,d=b.height-16*c,e=64*b.width,f=b.width*d*4,g=a.createImageData(b.width,
+16),h=0,m=b.data,C=g.data,u="set"in C&&"subarray"in m,q=0;for(;q<c;q++){if(u)C.set(m.subarray(h,h+e)),h+=e;else for(var r=0;r<e;r++)g.data[r]=b.data[h++];a.putImageData(g,0,16*q)}if(0!==d){if(u)C.set(m.subarray(h,h+f));else for(r=0;r<f;r++)g.data[r]=b.data[h++];a.putImageData(g,0,16*c)}}}function c(a,b){for(var c=b.width,d=b.height,e=a.createImageData(c,d),f=b.data,g=e.data,h=0,m=3,q=0;q<d;q++)for(var u=0,r=0;r<c;r++){if(!u)var t=f[h++],u=128;t&u||(g[m]=255);m+=4;u>>=1}a.putImageData(e,0,0)}var e=
+["butt","round","square"],d=["miter","round","bevel"],g={},f={};b.prototype={beginDrawing:function(a,b){var c=this.ctx.canvas.width,d=this.ctx.canvas.height;b?this.ctx.clearRect(0,0,c,d):(this.ctx.mozOpaque=!0,this.ctx.save(),this.ctx.fillStyle="rgb(255, 255, 255)",this.ctx.fillRect(0,0,c,d),this.ctx.restore());c=a.transform;this.baseTransform=c.slice();this.ctx.save();this.ctx.transform.apply(this.ctx,c);this.textLayer&&this.textLayer.beginLayout();this.imageLayer&&this.imageLayer.beginLayout()},
+executeOperatorList:function(a,b,c,d){var e=a.argsArray;a=a.fnArray;b=b||0;var f=e.length;if(f==b)return b;for(var g=Date.now()+15,h=this.commonObjs,m=this.objs,q,u=Promise.resolve();;){if(d&&b===d.nextBreakPoint)return d.breakIt(b,c),b;q=a[b];if(q!==y.dependency)this[q].apply(this,e[b]);else{q=e[b];for(var r=0,t=q.length;r<t;r++){var x=q[r],v="g_"==x.substring(0,2);if(!v&&!m.isResolved(x))return m.get(x,c),b;if(v&&!h.isResolved(x))return h.get(x,c),b}}b++;if(b==f)return b;if(c&&Date.now()>g)return u.then(c),
+b}},endDrawing:function(){this.ctx.restore();J.clear();this.textLayer&&this.textLayer.endLayout();this.imageLayer&&this.imageLayer.endLayout()},setLineWidth:function(a){this.current.lineWidth=a;this.ctx.lineWidth=a},setLineCap:function(a){this.ctx.lineCap=e[a]},setLineJoin:function(a){this.ctx.lineJoin=d[a]},setMiterLimit:function(a){this.ctx.miterLimit=a},setDash:function(a,b){var c=this.ctx;"setLineDash"in c?(c.setLineDash(a),c.lineDashOffset=b):(c.mozDash=a,c.mozDashOffset=b)},setRenderingIntent:function(a){},
+setFlatness:function(a){},setGState:function(a){for(var b=0,c=a.length;b<c;b++){var d=a[b],e=d[1];switch(d[0]){case "LW":this.setLineWidth(e);break;case "LC":this.setLineCap(e);break;case "LJ":this.setLineJoin(e);break;case "ML":this.setMiterLimit(e);break;case "D":this.setDash(e[0],e[1]);break;case "RI":this.setRenderingIntent(e);break;case "FL":this.setFlatness(e);break;case "Font":this.setFont(e[0],e[1]);break;case "CA":this.current.strokeAlpha=d[1];break;case "ca":this.current.fillAlpha=d[1];
+this.ctx.globalAlpha=d[1];break;case "BM":e&&e.name&&"Normal"!==e.name?(d=e.name.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()}).substring(1),this.ctx.globalCompositeOperation=d,this.ctx.globalCompositeOperation!==d&&x('globalCompositeOperation "'+d+'" is not supported')):this.ctx.globalCompositeOperation="source-over"}}},save:function(){this.ctx.save();var a=this.current;this.stateStack.push(a);this.current=a.clone()},restore:function(){var a=this.stateStack.pop();a&&(this.current=a,this.ctx.restore())},
+transform:function(a,b,c,d,e,f){this.ctx.transform(a,b,c,d,e,f)},moveTo:function(a,b){this.ctx.moveTo(a,b);this.current.setCurrentPoint(a,b)},lineTo:function(a,b){this.ctx.lineTo(a,b);this.current.setCurrentPoint(a,b)},curveTo:function(a,b,c,d,e,f){this.ctx.bezierCurveTo(a,b,c,d,e,f);this.current.setCurrentPoint(e,f)},curveTo2:function(a,b,c,d){var e=this.current;this.ctx.bezierCurveTo(e.x,e.y,a,b,c,d);e.setCurrentPoint(c,d)},curveTo3:function(a,b,c,d){this.curveTo(a,b,c,d,c,d);this.current.setCurrentPoint(c,
+d)},closePath:function(){this.ctx.closePath()},rectangle:function(a,b,c,d){this.ctx.rect(a,b,c,d)},stroke:function(a){a="undefined"!==typeof a?a:!0;var b=this.ctx,c=this.current.strokeColor;0===this.current.lineWidth&&(b.lineWidth=this.getSinglePixelWidth());b.globalAlpha=this.current.strokeAlpha;c&&c.hasOwnProperty("type")&&"Pattern"===c.type?(b.save(),b.strokeStyle=c.getPattern(b,this),b.stroke(),b.restore()):b.stroke();a&&this.consumePath();b.globalAlpha=this.current.fillAlpha},closeStroke:function(){this.closePath();
+this.stroke()},fill:function(a){a="undefined"!==typeof a?a:!0;var b=this.ctx,c=this.current.fillColor,d=!1;c&&c.hasOwnProperty("type")&&"Pattern"===c.type&&(b.save(),b.fillStyle=c.getPattern(b,this),d=!0);if(this.pendingEOFill){if("mozFillRule"in this.ctx)this.ctx.mozFillRule="evenodd",this.ctx.fill(),this.ctx.mozFillRule="nonzero";else try{this.ctx.fill("evenodd")}catch(e){this.ctx.fill()}this.pendingEOFill=!1}else this.ctx.fill();d&&b.restore();a&&this.consumePath()},eoFill:function(){this.pendingEOFill=
+!0;this.fill()},fillStroke:function(){this.fill(!1);this.stroke(!1);this.consumePath()},eoFillStroke:function(){this.pendingEOFill=!0;this.fillStroke()},closeFillStroke:function(){this.closePath();this.fillStroke()},closeEOFillStroke:function(){this.pendingEOFill=!0;this.closePath();this.fillStroke()},endPath:function(){this.consumePath()},clip:function(){this.pendingClip=g},eoClip:function(){this.pendingClip=f},beginText:function(){this.current.textMatrix=ia;this.current.x=this.current.lineX=0;this.current.y=
+this.current.lineY=0},endText:function(){if("pendingTextPaths"in this){var a=this.pendingTextPaths,b=this.ctx;b.save();b.beginPath();for(var c=0;c<a.length;c++){var d=a[c];b.setTransform.apply(b,d.transform);b.translate(d.x,d.y);d.addToPath(b,d.fontSize)}b.restore();b.clip();b.beginPath();delete this.pendingTextPaths}else this.ctx.beginPath()},setCharSpacing:function(a){this.current.charSpacing=a},setWordSpacing:function(a){this.current.wordSpacing=a},setHScale:function(a){this.current.textHScale=
+a/100},setLeading:function(a){this.current.leading=-a},setFont:function(a,b){var c=this.commonObjs.get(a),d=this.current;c||m("Can't find font for "+a);d.fontMatrix=c.fontMatrix?c.fontMatrix:ba;0!==d.fontMatrix[0]&&0!==d.fontMatrix[3]||x("Invalid font matrix for font "+a);0>b?(b=-b,d.fontDirection=-1):d.fontDirection=1;this.current.font=c;this.current.fontSize=b;if(!c.coded){var d=c.black?c.bold?"bolder":"bold":c.bold?"bold":"normal",e=c.italic?"italic":"normal",c='"'+(c.loadedName||"sans-serif")+
+'", '+c.fallbackName,f=16<=b?b:16;this.current.fontSizeScale=16!=f?1:b/16;this.ctx.font=e+" "+d+" "+f+"px "+c}},setTextRenderingMode:function(a){this.current.textRenderingMode=a},setTextRise:function(a){this.current.textRise=a},moveText:function(a,b){this.current.x=this.current.lineX+=a;this.current.y=this.current.lineY+=b},setLeadingMoveText:function(a,b){this.setLeading(-b);this.moveText(a,b)},setTextMatrix:function(a,b,c,d,e,f){this.current.textMatrix=[a,b,c,d,e,f];this.current.x=this.current.lineX=
+0;this.current.y=this.current.lineY=0},nextLine:function(){this.moveText(0,this.current.leading)},applyTextTransforms:function(){var a=this.ctx,b=this.current;a.transform.apply(a,b.textMatrix);a.translate(b.x,b.y+b.textRise);0<b.fontDirection?a.scale(b.textHScale,-1):a.scale(-b.textHScale,1)},createTextGeometry:function(){var a={},b=this.current.font,c=this.ctx.mozCurrentTransform,d=c[0],e=c[1],f=c[2],g=c[3],h=c[4],c=c[5],m=0<=d?Math.sqrt(d*d+e*e):-Math.sqrt(d*d+e*e),f=0<=g?Math.sqrt(f*f+g*g):-Math.sqrt(f*
+f+g*g),d=Math.atan2(e,d);a.x=h;a.y=c;a.hScale=m;a.vScale=f;a.angle=d;a.spaceWidth=b.spaceWidth;a.fontName=b.loadedName;a.fontFamily=b.fallbackName;a.fontSize=this.current.fontSize;a.ascent=b.ascent;a.descent=b.descent;return a},paintChar:function(a,b,c){var d=this.ctx,e=this.current,f=e.font,g=e.fontSize/e.fontSizeScale,h=e.textRenderingMode,e=h&3,h=!!(h&4),m;if(f.disableFontFace||h)m=f.getPathGenerator(this.commonObjs,a);f.disableFontFace?(d.save(),d.translate(b,c),d.beginPath(),m(d,g),e!==X&&2!==
+e||d.fill(),1!==e&&2!==e||d.stroke(),d.restore()):(e!==X&&2!==e||d.fillText(a,b,c),1!==e&&2!==e||d.strokeText(a,b,c));h&&(this.pendingTextPaths||(this.pendingTextPaths=[])).push({transform:d.mozCurrentTransform,x:b,y:c,fontSize:g,addToPath:m})},get isFontSubpixelAAEnabled(){var a=document.createElement("canvas").getContext("2d");a.scale(1.5,1);a.fillText("I",0,10);for(var a=a.getImageData(0,0,10,10).data,b=!1,c=3;c<a.length;c+=4)if(0<a[c]&&255>a[c]){b=!0;break}return U(this,"isFontSubpixelAAEnabled",
+b)},showText:function(a,b){var c=this.ctx,d=this.current,e=d.font,f=d.fontSize,g=d.fontSizeScale,h=d.charSpacing,m=d.wordSpacing,r=d.textHScale*d.fontDirection,u=d.fontMatrix||ba,M=a.length,t,x=this.textLayer&&!b?!0:!1,v=0,D=e.vertical,K=e.defaultVMetrics;if(e.coded){c.save();c.transform.apply(c,d.textMatrix);c.translate(d.x,d.y);c.scale(r,1);x&&(this.save(),c.scale(1,-1),t=this.createTextGeometry(),this.restore());for(var I=0;I<M;++I){var B=a[I];if(null===B)this.ctx.translate(m,0),d.x+=m*r;else{this.processingType3=
+B;this.save();c.scale(f,f);c.transform.apply(c,u);this.executeOperatorList(B.operatorList);this.restore();var O=(q.applyTransform([B.width,0],u)[0]*f+h)*d.fontDirection;c.translate(O,0);d.x+=O*r;v+=O}}c.restore();this.processingType3=null}else{c.save();this.applyTextTransforms();var I=d.lineWidth,u=d.textMatrix[0],y=d.textMatrix[1],u=Math.sqrt(u*u+y*y),I=0===u||0===I?this.getSinglePixelWidth():I/u;x&&(t=this.createTextGeometry());1!=g&&(c.scale(g,g),I/=g);c.lineWidth=I;for(I=u=0;I<M;++I)if(B=a[I],
+null===B)u+=d.fontDirection*m;else{var y=!1,H=B.fontChar,E=B.vmetric||K;if(D)var L=B.vmetric?E[1]:0.5*B.width,L=-L*f*d.fontMatrix[0],P=E[2]*f*d.fontMatrix[0];var O=E?-E[0]:B.width,E=O*f*d.fontMatrix[0]+h*d.fontDirection,G=B.accent,J,N;B.disabled||(D?(B=L/g,J=(u+P)/g):(B=u/g,J=0),e.remeasure&&0<O&&this.isFontSubpixelAAEnabled&&(y=1E3*c.measureText(H).width/d.fontSize*d.fontSizeScale,O/=y,y=!0,c.save(),c.scale(O,1),B/=O,G&&(N/=O)),this.paintChar(H,B,J),G&&(N=B+G.offset.x/g,H=J-G.offset.y/g,this.paintChar(G.fontChar,
+N,H)));u+=E;v+=E;y&&c.restore()}D?d.y-=u*r:d.x+=u*r;c.restore()}x&&(t.canvasWidth=v,D&&(t.angle+=Math.PI/2),this.textLayer.appendText(t));return v},showSpacedText:function(a){var b=this.ctx,c=this.current,d=c.fontSize,e=0.0010*c.textHScale*c.fontDirection,f=a.length,g,h=0,m=this.textLayer?!0:!1,q=c.font.vertical,r=0;m&&(b.save(),this.applyTextTransforms(),g=this.createTextGeometry(),b.restore());for(b=0;b<f;++b){var t=a[b];"number"==typeof t?(t=-t*d*e,q?c.y+=t:c.x+=t,m&&(r+=t)):(t=this.showText(t,
+!0),m&&(h+=r+t,r=0))}m&&(g.canvasWidth=h,q&&(g.angle+=Math.PI/2),this.textLayer.appendText(g))},nextLineShowText:function(a){this.nextLine();this.showText(a)},nextLineSetSpacingShowText:function(a,b,c){this.setWordSpacing(a);this.setCharSpacing(b);this.nextLineShowText(c)},setCharWidth:function(a,b){},setCharWidthAndBounds:function(a,b,c,d,e,f){this.rectangle(c,d,e-c,f-d);this.clip();this.endPath()},setStrokeColorSpace:function(a){this.current.strokeColorSpace=r.fromIR(a)},setFillColorSpace:function(a){this.current.fillColorSpace=
+r.fromIR(a)},setStrokeColor:function(){var a=this.current.strokeColorSpace.getRgb(arguments,0),a=q.makeCssRgb(a);this.ctx.strokeStyle=a;this.current.strokeColor=a},getColorN_Pattern:function(a,b){if("TilingPattern"==a[0]){var c=a[1],d=b.base,e;d&&(e=d.getRgb(c,0));c=new Ca(a,e,this.ctx,this.objs,this.commonObjs,this.baseTransform)}else"RadialAxial"==a[0]||"Dummy"==a[0]?c=ka.shadingFromIR(a):m("Unkown IR type "+a[0]);return c},setStrokeColorN:function(){var a=this.current.strokeColorSpace;"Pattern"==
+a.name?this.current.strokeColor=this.getColorN_Pattern(arguments,a):this.setStrokeColor.apply(this,arguments)},setFillColor:function(){var a=this.current.fillColorSpace.getRgb(arguments,0),a=q.makeCssRgb(a);this.ctx.fillStyle=a;this.current.fillColor=a},setFillColorN:function(){var a=this.current.fillColorSpace;"Pattern"==a.name?this.current.fillColor=this.getColorN_Pattern(arguments,a):this.setFillColor.apply(this,arguments)},setStrokeGray:function(a){this.current.strokeColorSpace=r.singletons.gray;
+var b=this.current.strokeColorSpace.getRgb(arguments,0),b=q.makeCssRgb(b);this.ctx.strokeStyle=b;this.current.strokeColor=b},setFillGray:function(a){this.current.fillColorSpace=r.singletons.gray;var b=this.current.fillColorSpace.getRgb(arguments,0),b=q.makeCssRgb(b);this.ctx.fillStyle=b;this.current.fillColor=b},setStrokeRGBColor:function(a,b,c){this.current.strokeColorSpace=r.singletons.rgb;var d=this.current.strokeColorSpace.getRgb(arguments,0),d=q.makeCssRgb(d);this.ctx.strokeStyle=d;this.current.strokeColor=
+d},setFillRGBColor:function(a,b,c){this.current.fillColorSpace=r.singletons.rgb;var d=this.current.fillColorSpace.getRgb(arguments,0),d=q.makeCssRgb(d);this.ctx.fillStyle=d;this.current.fillColor=d},setStrokeCMYKColor:function(a,b,c,d){this.current.strokeColorSpace=r.singletons.cmyk;var e=q.makeCssCmyk(arguments);this.ctx.strokeStyle=e;this.current.strokeColor=e},setFillCMYKColor:function(a,b,c,d){this.current.fillColorSpace=r.singletons.cmyk;var e=q.makeCssCmyk(arguments);this.ctx.fillStyle=e;this.current.fillColor=
+e},shadingFill:function(a){var b=this.ctx;this.save();a=ka.shadingFromIR(a);b.fillStyle=a.getPattern(b,this);var c=b.mozCurrentTransformInverse;if(c){var b=b.canvas,d=b.width,e=b.height,b=q.applyTransform([0,0],c);a=q.applyTransform([0,e],c);var f=q.applyTransform([d,0],c),g=q.applyTransform([d,e],c),c=Math.min(b[0],a[0],f[0],g[0]),d=Math.min(b[1],a[1],f[1],g[1]),e=Math.max(b[0],a[0],f[0],g[0]),b=Math.max(b[1],a[1],f[1],g[1]);this.ctx.fillRect(c,d,e-c,b-d)}else this.ctx.fillRect(-1E10,-1E10,2E10,
+2E10);this.restore()},beginInlineImage:function(){m("Should not call beginInlineImage")},beginImageData:function(){m("Should not call beginImageData")},paintFormXObjectBegin:function(a,b){this.save();this.baseTransformStack.push(this.baseTransform);a&&D(a)&&6==a.length&&this.transform.apply(this,a);this.baseTransform=this.ctx.mozCurrentTransform;b&&D(b)&&4==b.length&&(this.rectangle(b[0],b[1],b[2]-b[0],b[3]-b[1]),this.clip(),this.endPath())},paintFormXObjectEnd:function(){this.restore();this.baseTransform=
+this.baseTransformStack.pop()},beginGroup:function(a){this.save();var b=this.ctx;a.isolated||K("TODO: Support non-isolated groups.");a.knockout&&x("Knockout groups not supported.");var c=b.mozCurrentTransform;a.matrix&&b.transform.apply(b,a.matrix);a.bbox||m("Bounding box is required.");var d=q.getAxialAlignedBoundingBox(a.bbox,b.mozCurrentTransform),d=q.intersect(d,[0,0,b.canvas.width,b.canvas.height])||[0,0,0,0];a=Math.max(Math.ceil(d[2]-d[0]),1);var e=Math.max(Math.ceil(d[3]-d[1]),1);a=J.getCanvas("groupAt"+
+this.groupLevel,a,e,!0).context;e=d[0];d=d[1];a.translate(-e,-d);a.transform.apply(a,c);b.setTransform(1,0,0,1,0,0);b.translate(e,d);c="strokeStyle fillStyle fillRule globalAlpha lineWidth lineCap lineJoin miterLimit globalCompositeOperation font".split(" ");d=0;for(e=c.length;d<e;d++){var f=c[d];f in b&&(a[f]=b[f])}"setLineDash"in b?(a.setLineDash(b.getLineDash()),a.lineDashOffset=b.lineDashOffset):"mozDash"in b&&(a.mozDash=b.mozDash,a.mozDashOffset=b.mozDashOffset);this.ctx=a;this.setGState([["SMask",
+"None"],["BM","Normal"],["ca",1],["CA",1]]);this.groupStack.push(b);this.groupLevel++},endGroup:function(a){this.groupLevel--;a=this.ctx;this.ctx=this.groupStack.pop();"imageSmoothingEnabled"in this.ctx?this.ctx.imageSmoothingEnabled=!1:this.ctx.mozImageSmoothingEnabled=!1;this.ctx.drawImage(a.canvas,0,0);this.restore()},beginAnnotations:function(){this.save();this.current=new na},endAnnotations:function(){this.restore()},beginAnnotation:function(a,b,c){this.save();a&&D(a)&&4==a.length&&(this.rectangle(a[0],
+a[1],a[2]-a[0],a[3]-a[1]),this.clip(),this.endPath());this.transform.apply(this,b);this.transform.apply(this,c)},endAnnotation:function(){this.restore()},paintJpegXObject:function(a,b,c){var d=this.objs.get(a);d||m("Dependent image isn't ready yet");this.save();var e=this.ctx;e.scale(1/b,-1/c);e.drawImage(d,0,0,d.width,d.height,0,-c,b,c);this.imageLayer&&(d=e.mozCurrentTransformInverse,e=this.getCanvasPosition(0,0),this.imageLayer.appendImage({objId:a,left:e[0],top:e[1],width:b/d[0],height:c/d[3]}));
+this.restore()},paintImageMaskXObject:function(a){var b=this.ctx,d=a.width,e=a.height,f=this.processingType3;!f||"compiled"in f||(f.compiled=1E3>=d&&1E3>=e?sa({data:a.data,width:d,height:e}):null);f&&f.compiled?f.compiled(b):(b=J.getCanvas("maskCanvas",d,e),f=b.context,f.save(),c(f,a),f.globalCompositeOperation="source-in",a=this.current.fillColor,f.fillStyle=a&&a.hasOwnProperty("type")&&"Pattern"===a.type?a.getPattern(f,this):a,f.fillRect(0,0,d,e),f.restore(),this.paintInlineImageXObject(b.canvas))},
+paintImageMaskXObjectGroup:function(a){for(var b=this.ctx,d=0,e=a.length;d<e;d++){var f=a[d],g=f.width,h=f.height,m=J.getCanvas("maskCanvas",g,h),q=m.context;q.save();c(q,f);q.globalCompositeOperation="source-in";var r=this.current.fillColor;q.fillStyle=r&&r.hasOwnProperty("type")&&"Pattern"===r.type?r.getPattern(q,this):r;q.fillRect(0,0,g,h);q.restore();b.save();b.transform.apply(b,f.transform);b.scale(1,-1);b.drawImage(m.canvas,0,0,g,h,0,-1,1,1);b.restore()}},paintImageXObject:function(a){(a=this.objs.get(a))||
+m("Dependent image isn't ready yet");this.paintInlineImageXObject(a)},paintInlineImageXObject:function(b){var c=b.width,d=b.height,e=this.ctx;this.save();e.scale(1/c,-1/d);var f=e.mozCurrentTransformInverse,g=f[0],h=f[1],g=Math.max(Math.sqrt(g*g+h*h),1),h=f[2],m=f[3],h=Math.max(Math.sqrt(h*h+m*m),1);if(b instanceof HTMLElement||!b.data)m=b;else{var q=J.getCanvas("inlineImage",c,d),r=q.context;a(r,b);m=q.canvas}for(var u=c,t=d,x="prescale1";2<g&&1<u||2<h&&1<t;){var v=u,y=t;2<g&&1<u&&(v=Math.ceil(u/
+2),g/=u/v);2<h&&1<t&&(y=Math.ceil(t/2),h/=t/y);q=J.getCanvas(x,v,y);r=q.context;r.clearRect(0,0,v,y);r.drawImage(m,0,0,u,t,0,0,v,y);m=q.canvas;u=v;t=y;x="prescale1"===x?"prescale2":"prescale1"}e.drawImage(m,0,0,u,t,0,-d,c,d);this.imageLayer&&(e=this.getCanvasPosition(0,-d),this.imageLayer.appendImage({imgData:b,left:e[0],top:e[1],width:c/f[0],height:d/f[3]}));this.restore()},paintInlineImageXObjectGroup:function(b,c){var d=this.ctx,e=b.width,f=b.height,g=J.getCanvas("inlineImage",e,f);a(g.context,
+b);for(var h=0,m=c.length;h<m;h++){var q=c[h];d.save();d.transform.apply(d,q.transform);d.scale(1,-1);d.drawImage(g.canvas,q.x,q.y,q.w,q.h,0,-1,1,1);this.imageLayer&&(q=this.getCanvasPosition(q.x,q.y),this.imageLayer.appendImage({imgData:b,left:q[0],top:q[1],width:e,height:f}));d.restore()}},markPoint:function(a){},markPointProps:function(a,b){},beginMarkedContent:function(a){},beginMarkedContentProps:function(a,b){},endMarkedContent:function(){},beginCompat:function(){},endCompat:function(){},consumePath:function(){if(this.pendingClip){if(this.pendingClip==
+f)if("mozFillRule"in this.ctx)this.ctx.mozFillRule="evenodd",this.ctx.clip(),this.ctx.mozFillRule="nonzero";else try{this.ctx.clip("evenodd")}catch(a){this.ctx.clip()}else this.ctx.clip();this.pendingClip=null}this.ctx.beginPath()},getSinglePixelWidth:function(a){a=this.ctx.mozCurrentTransformInverse;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1],a[2]*a[2]+a[3]*a[3]))},getCanvasPosition:function(a,b){var c=this.ctx.mozCurrentTransform;return[c[0]*a+c[2]*b+c[4],c[1]*a+c[3]*b+c[5]]}};for(var h in y)b.prototype[y[h]]=
+b.prototype[h];return b}();PDFJS.disableFontFace=!1;var Q={insertRule:function(b){var a=document.getElementById("PDFJS_FONT_STYLE_TAG");a||(a=document.createElement("style"),a.id="PDFJS_FONT_STYLE_TAG",document.documentElement.getElementsByTagName("head")[0].appendChild(a));a=a.sheet;a.insertRule(b,a.cssRules.length)},clear:function(){var b=document.getElementById("PDFJS_FONT_STYLE_TAG");b&&b.parentNode.removeChild(b)},get loadTestFont(){return U(this,"loadTestFont",atob("T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAAB
 AAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA=="))},
+loadTestFontId:0,loadingContext:{requests:[],nextRequestId:0},isSyncFontLoadingSupported:function(){if(W)return!1;var b=/Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(window.navigator.userAgent);return b&&14<=b[1]?!0:!1}(),bind:function(b,a){W&&m("bind() shall be called from main thread");for(var c=[],e=[],d=0,g=b.length;d<g;d++){var f=b[d];if(!f.attached&&!1!==f.loading){f.attached=!0;var h=f.bindDOM();h&&(c.push(h),e.push(f))}}d=Q.queueLoadingCallback(a);0<c.length&&!this.isSyncFontLoadingSupported?Q.prepareFontLoadEvent(c,
+e,d):d.complete()},queueLoadingCallback:function(b){var a=Q.loadingContext,c={id:"pdfjs-font-loading-"+a.nextRequestId++,complete:function(){c.end&&m("completeRequest() cannot be called twice");for(c.end=Date.now();0<a.requests.length&&a.requests[0].end;){var b=a.requests.shift();setTimeout(b.callback,0)}},callback:b,started:Date.now()};a.requests.push(c);return c},prepareFontLoadEvent:function(b,a,c){function e(a,b){return a.charCodeAt(b)<<24|a.charCodeAt(b+1)<<16|a.charCodeAt(b+2)<<8|a.charCodeAt(b+
+3)&255}function d(a,b,c,d){a=m.substr(0,b);b=m.substr(b+c);return a+d+b}function g(a,b){l++;30<l?(x("Load test font never loaded."),b()):(k.font="30px "+a,k.fillText(".",0,20),0<k.getImageData(0,0,1,1).data[3]?b():setTimeout(g.bind(null,a,b)))}var f,h;b=document.createElement("canvas");b.width=1;b.height=1;var k=b.getContext("2d"),l=0;b="lt"+Date.now()+this.loadTestFontId++;var m=this.loadTestFont,m=d(m,976,b.length,b),p=e(m,16);f=0;for(h=b.length-3;f<h;f+=4)p=p-1482184792+e(b,f)|0;f<b.length&&(p=
+p-1482184792+e(b+"XXX",f)|0);m=d(m,16,4,String.fromCharCode(p>>24&255)+String.fromCharCode(p>>16&255)+String.fromCharCode(p>>8&255)+String.fromCharCode(p&255));f="url(data:font/opentype;base64,"+btoa(m)+");";Q.insertRule('@font-face { font-family:"'+b+'";src:'+f+"}");p=[];f=0;for(h=a.length;f<h;f++)p.push(a[f].loadedName);p.push(b);var q=document.createElement("div");q.setAttribute("style","visibility: hidden;width: 10px; height: 10px;position: absolute; top: 0px; left: 0px;");f=0;for(h=p.length;f<
+h;++f)a=document.createElement("span"),a.textContent="Hi",a.style.fontFamily=p[f],q.appendChild(a);document.body.appendChild(q);g(b,function(){document.body.removeChild(q);c.complete()})}},Qa=function(){function b(a,b,e){this.compiledGlyphs={};if(1===arguments.length){var d=arguments[0],g;for(g in d)this[g]=d[g]}}b.prototype={bindDOM:function(){if(!this.data)return null;if(PDFJS.disableFontFace)return this.disableFontFace=!0,null;for(var a=this.data,b="",e=a.length,d=0;d<e;++d)b+=String.fromCharCode(a[d]);
+a=this.loadedName;b="url(data:"+this.mimetype+";base64,"+window.btoa(b)+");";a='@font-face { font-family:"'+a+'";src:'+b+"}";Q.insertRule(a);PDFJS.pdfBug&&"FontInspector"in t&&t.FontInspector.enabled&&t.FontInspector.fontAdded(this,b);return a},getPathGenerator:function(a,b){if(!(b in this.compiledGlyphs)){var e=a.get(this.loadedName+"_path_"+b);this.compiledGlyphs[b]=new Function("c","size",e)}return this.compiledGlyphs[b]}};return b}()}).call("undefined"===typeof window?this:window);
+PDFJS.workerSrc||"undefined"===typeof document||(PDFJS.workerSrc=function(){var E=(document.body||document.getElementsByTagName("head")[0]).lastChild.src;return E&&E.replace(/\.js$/i,".worker.js")}());
diff --git a/plugins/pdfviewer/viewer/pdf.worker.js b/plugins/pdfviewer/viewer/pdf.worker.js
index 0f954c3..13debfc 100644
--- a/plugins/pdfviewer/viewer/pdf.worker.js
+++ b/plugins/pdfviewer/viewer/pdf.worker.js
@@ -20,8 +20,8 @@ if (typeof PDFJS === 'undefined') {
   (typeof window !== 'undefined' ? window : this).PDFJS = {};
 }
 
-PDFJS.version = '0.8.573';
-PDFJS.build = 'e97e003';
+PDFJS.version = '0.8.894';
+PDFJS.build = 'ac91047';
 
 (function pdfjsWrapper() {
   // Use strict in our context only - users might not want it
@@ -43,7 +43,8 @@ PDFJS.build = 'e97e003';
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref */
+/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL,
+           Promise */
 
 'use strict';
 
@@ -51,9 +52,6 @@ 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 = {
@@ -78,33 +76,118 @@ if (!globalScope.PDFJS) {
 
 globalScope.PDFJS.pdfBug = false;
 
+PDFJS.VERBOSITY_LEVELS = {
+  errors: 0,
+  warnings: 1,
+  infos: 5
+};
 
-// 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() {
-    };
-  }
-})();
+// All the possible operations for an operator list.
+var OPS = PDFJS.OPS = {
+  // Intentionally start from 1 so it is easy to spot bad operators that will be
+  // 0's.
+  dependency: 1,
+  setLineWidth: 2,
+  setLineCap: 3,
+  setLineJoin: 4,
+  setMiterLimit: 5,
+  setDash: 6,
+  setRenderingIntent: 7,
+  setFlatness: 8,
+  setGState: 9,
+  save: 10,
+  restore: 11,
+  transform: 12,
+  moveTo: 13,
+  lineTo: 14,
+  curveTo: 15,
+  curveTo2: 16,
+  curveTo3: 17,
+  closePath: 18,
+  rectangle: 19,
+  stroke: 20,
+  closeStroke: 21,
+  fill: 22,
+  eoFill: 23,
+  fillStroke: 24,
+  eoFillStroke: 25,
+  closeFillStroke: 26,
+  closeEOFillStroke: 27,
+  endPath: 28,
+  clip: 29,
+  eoClip: 30,
+  beginText: 31,
+  endText: 32,
+  setCharSpacing: 33,
+  setWordSpacing: 34,
+  setHScale: 35,
+  setLeading: 36,
+  setFont: 37,
+  setTextRenderingMode: 38,
+  setTextRise: 39,
+  moveText: 40,
+  setLeadingMoveText: 41,
+  setTextMatrix: 42,
+  nextLine: 43,
+  showText: 44,
+  showSpacedText: 45,
+  nextLineShowText: 46,
+  nextLineSetSpacingShowText: 47,
+  setCharWidth: 48,
+  setCharWidthAndBounds: 49,
+  setStrokeColorSpace: 50,
+  setFillColorSpace: 51,
+  setStrokeColor: 52,
+  setStrokeColorN: 53,
+  setFillColor: 54,
+  setFillColorN: 55,
+  setStrokeGray: 56,
+  setFillGray: 57,
+  setStrokeRGBColor: 58,
+  setFillRGBColor: 59,
+  setStrokeCMYKColor: 60,
+  setFillCMYKColor: 61,
+  shadingFill: 62,
+  beginInlineImage: 63,
+  beginImageData: 64,
+  endInlineImage: 65,
+  paintXObject: 66,
+  markPoint: 67,
+  markPointProps: 68,
+  beginMarkedContent: 69,
+  beginMarkedContentProps: 70,
+  endMarkedContent: 71,
+  beginCompat: 72,
+  endCompat: 73,
+  paintFormXObjectBegin: 74,
+  paintFormXObjectEnd: 75,
+  beginGroup: 76,
+  endGroup: 77,
+  beginAnnotations: 78,
+  endAnnotations: 79,
+  beginAnnotation: 80,
+  endAnnotation: 81,
+  paintJpegXObject: 82,
+  paintImageMaskXObject: 83,
+  paintImageMaskXObjectGroup: 84,
+  paintImageXObject: 85,
+  paintInlineImageXObject: 86,
+  paintInlineImageXObjectGroup: 87
+};
 
-// 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.
+// 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.
 function info(msg) {
-  if (verbosity >= INFOS) {
-    log('Info: ' + msg);
-    PDFJS.LogManager.notify('info', msg);
+  if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) {
+    console.log('Info: ' + msg);
   }
 }
 
-// Non-fatal warnings that should trigger the fallback UI.
+// Non-fatal warnings.
 function warn(msg) {
-  if (verbosity >= WARNINGS) {
-    log('Warning: ' + msg);
-    PDFJS.LogManager.notify('warn', msg);
+  if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) {
+    console.log('Warning: ' + msg);
   }
 }
 
@@ -115,22 +198,17 @@ function error(msg) {
   if (arguments.length > 1) {
     var logArguments = ['Error:'];
     logArguments.push.apply(logArguments, arguments);
-    log.apply(null, logArguments);
+    console.log.apply(console, logArguments);
     // Join the arguments into a single string for the lines below.
     msg = [].join.call(arguments, ' ');
   } else {
-    log('Error: ' + msg);
+    console.log('Error: ' + msg);
   }
-  log(backtrace());
-  PDFJS.LogManager.notify('error', msg);
+  console.log(backtrace());
+  UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown);
   throw new Error(msg);
 }
 
-// Missing features that should trigger the fallback UI.
-function TODO(what) {
-  warn('TODO: ' + what);
-}
-
 function backtrace() {
   try {
     throw new Error();
@@ -144,6 +222,31 @@ function assert(cond, msg) {
     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) {
@@ -197,22 +300,6 @@ function assertWellFormed(cond, msg) {
     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,
@@ -292,7 +379,7 @@ var MissingDataException = (function MissingDataExceptionClosure() {
   function MissingDataException(begin, end) {
     this.begin = begin;
     this.end = end;
-    this.message = 'Missing data [begin, end)';
+    this.message = 'Missing data [' + begin + ', ' + end + ')';
   }
 
   MissingDataException.prototype = new Error();
@@ -742,6 +829,24 @@ function isPDFFunction(v) {
 }
 
 /**
+ * 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.
@@ -750,7 +855,39 @@ function isPDFFunction(v) {
  * Based off of the work in:
  * https://bugzilla.mozilla.org/show_bug.cgi?id=810490
  */
-var Promise = PDFJS.Promise = (function PromiseClosure() {
+(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;
+  }
   var STATUS_PENDING = 0;
   var STATUS_RESOLVED = 1;
   var STATUS_REJECTED = 2;
@@ -783,6 +920,8 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
     },
 
     runHandlers: function runHandlers() {
+      var RUN_TIMEOUT = 1; // ms
+      var timeoutAt = Date.now() + RUN_TIMEOUT;
       while (this.handlers.length > 0) {
         var handler = this.handlers.shift();
 
@@ -808,6 +947,14 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
         }
 
         handler.nextPromise._updateStatus(nextStatus, nextValue);
+        if (Date.now() >= timeoutAt) {
+          break;
+        }
+      }
+
+      if (this.handlers.length > 0) {
+        setTimeout(this.runHandlers.bind(this), 0);
+        return;
       }
 
       this.running = false;
@@ -858,22 +1005,27 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
     }
   };
 
-  function Promise() {
+  function Promise(resolver) {
     this._status = STATUS_PENDING;
     this._handlers = [];
+    resolver.call(this, this._resolve.bind(this), this._reject.bind(this));
   }
   /**
    * Builds a promise that is resolved when all the passed in promises are
    * resolved.
-   * @param {Promise[]} promises Array of promises to wait for.
+   * @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 resolveAll, rejectAll;
+    var deferred = new Promise(function (resolve, reject) {
+      resolveAll = resolve;
+      rejectAll = reject;
+    });
     var unresolved = promises.length;
     var results = [];
     if (unresolved === 0) {
-      deferred.resolve(results);
+      resolveAll(results);
       return deferred;
     }
     function reject(reason) {
@@ -881,11 +1033,11 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
         return;
       }
       results = [];
-      deferred.reject(reason);
+      rejectAll(reason);
     }
     for (var i = 0, ii = promises.length; i < ii; ++i) {
       var promise = promises[i];
-      promise.then((function(i) {
+      var resolve = (function(i) {
         return function(value) {
           if (deferred._status === STATUS_REJECTED) {
             return;
@@ -893,13 +1045,34 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
           results[i] = value;
           unresolved--;
           if (unresolved === 0)
-            deferred.resolve(results);
+            resolveAll(results);
         };
-      })(i), reject);
+      })(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';
+  };
+  /**
+   * Creates resolved promise
+   * @param x resolve value
+   * @returns {Promise}
+   */
+  Promise.resolve = function Promise_resolve(x) {
+    return new Promise(function (resolve) { resolve(x); });
+  };
+
   Promise.prototype = {
     _status: null,
     _value: null,
@@ -913,7 +1086,7 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
       }
 
       if (status == STATUS_RESOLVED &&
-          value && typeof(value.then) === 'function') {
+          Promise.isPromise(value)) {
         value.then(this._updateStatus.bind(this, STATUS_RESOLVED),
                    this._updateStatus.bind(this, STATUS_REJECTED));
         return;
@@ -930,24 +1103,19 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
       HandlerManager.scheduleHandlers(this);
     },
 
-    get isResolved() {
-      return this._status === STATUS_RESOLVED;
-    },
-
-    get isRejected() {
-      return this._status === STATUS_REJECTED;
-    },
-
-    resolve: function Promise_resolve(value) {
+    _resolve: function Promise_resolve(value) {
       this._updateStatus(STATUS_RESOLVED, value);
     },
 
-    reject: function Promise_reject(reason) {
+    _reject: function Promise_reject(reason) {
       this._updateStatus(STATUS_REJECTED, reason);
     },
 
     then: function Promise_then(onResolve, onReject) {
-      var nextPromise = new Promise();
+      var nextPromise = new Promise(function (resolve, reject) {
+        this.resolve = reject;
+        this.reject = reject;
+      });
       this._handlers.push({
         thisPromise: this,
         onResolve: onResolve,
@@ -959,7 +1127,7 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
     }
   };
 
-  return Promise;
+  globalScope.Promise = Promise;
 })();
 
 var StatTimer = (function StatTimerClosure() {
@@ -1016,7 +1184,7 @@ var StatTimer = (function StatTimerClosure() {
 })();
 
 PDFJS.createBlob = function createBlob(data, contentType) {
-  if (typeof Blob === 'function')
+  if (typeof Blob !== 'undefined')
     return new Blob([data], { type: contentType });
   // Blob builder is deprecated in FF14 and removed in FF18.
   var bb = new MozBlobBuilder();
@@ -1024,29 +1192,48 @@ PDFJS.createBlob = function createBlob(data, contentType) {
   return bb.getBlob(contentType);
 };
 
+PDFJS.createObjectURL = (function createObjectURLClosure() {
+  // 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;
+      buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
+    }
+    return buffer;
+  };
+})();
+
 function MessageHandler(name, comObj) {
   this.name = name;
   this.comObj = comObj;
   this.callbackIndex = 1;
+  this.postMessageTransfers = true;
   var callbacks = this.callbacks = {};
   var ah = this.actionHandler = {};
 
   ah['console_log'] = [function ahConsoleLog(data) {
-    log.apply(null, data);
+    console.log.apply(console, 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);
+  ah['console_error'] = [function ahConsoleError(data) {
+    console.error.apply(console, data);
+  }];
+  ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) {
+    UnsupportedManager.notify(data);
   }];
 
   comObj.onmessage = function messageHandlerComObjOnMessage(event) {
@@ -1063,7 +1250,12 @@ function MessageHandler(name, comObj) {
     } else if (data.action in ah) {
       var action = ah[data.action];
       if (data.callbackId) {
-        var promise = new Promise();
+        var deferred = {};
+        var promise = new Promise(function (resolve, reject) {
+          deferred.resolve = resolve;
+          deferred.reject = reject;
+        });
+        deferred.promise = promise;
         promise.then(function(resolvedData) {
           comObj.postMessage({
             isReply: true,
@@ -1071,7 +1263,7 @@ function MessageHandler(name, comObj) {
             data: resolvedData
           });
         });
-        action[0].call(action[1], data.data, promise);
+        action[0].call(action[1], data.data, deferred);
       } else {
         action[0].call(action[1], data.data);
       }
@@ -1094,8 +1286,9 @@ MessageHandler.prototype = {
    * @param {String} actionName Action to call.
    * @param {JSON} data JSON data to send.
    * @param {function} [callback] Optional callback that will handle a reply.
+   * @param {Array} [transfers] Optional list of transfers/ArrayBuffers
    */
-  send: function messageHandlerSend(actionName, data, callback) {
+  send: function messageHandlerSend(actionName, data, callback, transfers) {
     var message = {
       action: actionName,
       data: data
@@ -1105,693 +1298,1563 @@ MessageHandler.prototype = {
       this.callbacks[callbackId] = callback;
       message.callbackId = callbackId;
     }
-    this.comObj.postMessage(message);
+    if (transfers && this.postMessageTransfers) {
+      this.comObj.postMessage(message, transfers);
+    } else {
+      this.comObj.postMessage(message);
+    }
   }
 };
 
-function loadJpegStream(id, imageData, objs) {
+function loadJpegStream(id, imageUrl, objs) {
   var img = new Image();
   img.onload = (function loadJpegStream_onloadClosure() {
     objs.resolve(id, img);
   });
-  img.src = 'data:image/jpeg;base64,' + window.btoa(imageData);
+  img.src = imageUrl;
 }
 
 
-var PatternType = {
-  AXIAL: 2,
-  RADIAL: 3
-};
-
-var Pattern = (function PatternClosure() {
-  // Constructor should define this.getPattern
-  function Pattern() {
-    error('should not call Pattern constructor');
+var ColorSpace = (function ColorSpaceClosure() {
+  // Constructor should define this.numComps, this.defaultColor, this.name
+  function ColorSpace() {
+    error('should not call ColorSpace constructor');
   }
 
-  Pattern.prototype = {
-    // Input: current Canvas context
-    // Output: the appropriate fillStyle or strokeStyle
-    getPattern: function Pattern_getPattern(ctx) {
-      error('Should not call Pattern.getStyle: ' + ctx);
-    }
+  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
   };
 
-  Pattern.shadingFromIR = function Pattern_shadingFromIR(raw) {
-    return Shadings[raw[0]].fromIR(raw);
+  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);
   };
 
-  Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref,
-                                                       res) {
+  ColorSpace.fromIR = function ColorSpace_fromIR(IR) {
+    var name = isArray(IR) ? IR[0] : IR;
 
-    var dict = isStream(shading) ? shading.dict : shading;
-    var type = dict.get('ShadingType');
+    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];
 
-    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);
+        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:
-        TODO('Unsupported shading type: ' + type);
-        return new Shadings.Dummy();
+        error('Unkown name ' + name);
     }
+    return null;
   };
-  return Pattern;
-})();
-
-var Shadings = {};
-
-// A small number to offset the first/last color stops so we can insert ones to
-// support extend.  Number.MIN_VALUE appears to be too small and breaks the
-// extend. 1e-7 works in FF but chrome seems to use an even smaller sized number
-// internally so we have to go bigger.
-Shadings.SMALL_NUMBER = 1e-2;
-
-// Radial and axial shading have very similar implementations
-// If needed, the implementations can be broken into two classes
-Shadings.RadialAxial = (function RadialAxialClosure() {
-  function RadialAxial(dict, matrix, xref, res, ctx) {
-    this.matrix = matrix;
-    this.coordsArr = dict.get('Coords');
-    this.shadingType = dict.get('ShadingType');
-    this.type = 'Pattern';
-    this.ctx = ctx;
-    var cs = dict.get('ColorSpace', 'CS');
-    cs = ColorSpace.parse(cs, xref, res);
-    this.cs = cs;
 
-    var t0 = 0.0, t1 = 1.0;
-    if (dict.has('Domain')) {
-      var domainArr = dict.get('Domain');
-      t0 = domainArr[0];
-      t1 = domainArr[1];
+  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;
+      }
     }
 
-    var extendStart = false, extendEnd = false;
-    if (dict.has('Extend')) {
-      var extendArr = dict.get('Extend');
-      extendStart = extendArr[0];
-      extendEnd = extendArr[1];
-    }
+    cs = xref.fetchIfRef(cs);
+    var mode;
 
-    if (this.shadingType === PatternType.RADIAL &&
-       (!extendStart || !extendEnd)) {
-      // Radial gradient only currently works if either circle is fully within
-      // the other circle.
-      var x1 = this.coordsArr[0];
-      var y1 = this.coordsArr[1];
-      var r1 = this.coordsArr[2];
-      var x2 = this.coordsArr[3];
-      var y2 = this.coordsArr[4];
-      var r2 = this.coordsArr[5];
-      var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
-      if (r1 <= r2 + distance &&
-          r2 <= r1 + distance) {
-        warn('Unsupported radial gradient.');
-      }
-    }
+    if (isName(cs)) {
+      mode = cs.name;
+      this.mode = mode;
 
-    this.extendStart = extendStart;
-    this.extendEnd = extendEnd;
+      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;
 
-    var fnObj = dict.get('Function');
-    var fn;
-    if (isArray(fnObj)) {
-      var fnArray = [];
-      for (var j = 0, jj = fnObj.length; j < jj; j++) {
-        var obj = xref.fetchIfRef(fnObj[j]);
-        if (!isPDFFunction(obj)) {
-          error('Invalid function');
-        }
-        fnArray.push(PDFFunction.parse(xref, obj));
+      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 + '"');
       }
-      fn = function radialAxialColorFunction(arg) {
-        var out = [];
-        for (var i = 0, ii = fnArray.length; i < ii; i++) {
-          out.push(fnArray[i](arg)[0]);
-        }
-        return out;
-      };
     } else {
-      if (!isPDFFunction(fnObj)) {
-        error('Invalid function');
-      }
-      fn = PDFFunction.parse(xref, fnObj);
+      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;
 
-    // 10 samples seems good enough for now, but probably won't work
-    // if there are sharp color changes. Ideally, we would implement
-    // the spec faithfully and add lossless optimizations.
-    var diff = t1 - t0;
-    var step = diff / 10;
-
-    var colorStops = this.colorStops = [];
-
-    // Protect against bad domains so we don't end up in an infinte loop below.
-    if (t0 >= t1 || step <= 0) {
-      // Acrobat doesn't seem to handle these cases so we'll ignore for
-      // now.
-      info('Bad shading domain.');
-      return;
+    if (n * 2 !== decode.length) {
+      warn('The decode map is not the correct length');
+      return true;
     }
-
-    for (var i = t0; i <= t1; i += step) {
-      var rgbColor = cs.getRgb(fn([i]), 0);
-      var cssColor = Util.makeCssRgb(rgbColor);
-      colorStops.push([(i - t0) / diff, cssColor]);
+    for (var i = 0, ii = decode.length; i < ii; i += 2) {
+      if (decode[i] !== 0 || decode[i + 1] != 1)
+        return false;
     }
+    return true;
+  };
 
-    var background = 'transparent';
-    if (dict.has('Background')) {
-      var rgbColor = cs.getRgb(dict.get('Background'), 0);
-      background = Util.makeCssRgb(rgbColor);
+  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());
     }
+  };
 
-    if (!extendStart) {
-      // Insert a color stop at the front and offset the first real color stop
-      // so it doesn't conflict with the one we insert.
-      colorStops.unshift([0, background]);
-      colorStops[1][0] += Shadings.SMALL_NUMBER;
-    }
-    if (!extendEnd) {
-      // Same idea as above in extendStart but for the end.
-      colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER;
-      colorStops.push([1, background]);
-    }
+  return ColorSpace;
+})();
 
-    this.colorStops = colorStops;
+/**
+ * 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;
   }
 
-  RadialAxial.fromIR = function RadialAxial_fromIR(raw) {
-    var type = raw[1];
-    var colorStops = raw[2];
-    var p0 = raw[3];
-    var p1 = raw[4];
-    var r0 = raw[5];
-    var r1 = raw[6];
-    return {
-      type: 'Pattern',
-      getPattern: function RadialAxial_getPattern(ctx) {
-        var grad;
-        if (type == PatternType.AXIAL)
-          grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
-        else if (type == PatternType.RADIAL)
-          grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
-
-        for (var i = 0, ii = colorStops.length; i < ii; ++i) {
-          var c = colorStops[i];
-          grad.addColorStop(c[0], c[1]);
-        }
-        return grad;
-      }
-    };
-  };
-
-  RadialAxial.prototype = {
-    getIR: function RadialAxial_getIR() {
-      var coordsArr = this.coordsArr;
-      var type = this.shadingType;
-      if (type == PatternType.AXIAL) {
-        var p0 = [coordsArr[0], coordsArr[1]];
-        var p1 = [coordsArr[2], coordsArr[3]];
-        var r0 = null;
-        var r1 = null;
-      } else if (type == PatternType.RADIAL) {
-        var p0 = [coordsArr[0], coordsArr[1]];
-        var p1 = [coordsArr[3], coordsArr[4]];
-        var r0 = coordsArr[2];
-        var r1 = coordsArr[5];
-      } else {
-        error('getPattern type unknown: ' + type);
-      }
+  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 matrix = this.matrix;
-      if (matrix) {
-        p0 = Util.applyTransform(p0, matrix);
-        p1 = Util.applyTransform(p1, matrix);
+      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;
+        }
       }
-
-      return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1];
-    }
+      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 RadialAxial;
+  return AlternateCS;
 })();
 
-Shadings.Dummy = (function DummyClosure() {
-  function Dummy() {
-    this.type = 'Pattern';
+var PatternCS = (function PatternCSClosure() {
+  function PatternCS(baseCS) {
+    this.name = 'Pattern';
+    this.base = baseCS;
   }
+  PatternCS.prototype = {};
 
-  Dummy.fromIR = function Dummy_fromIR() {
-    return {
-      type: 'Pattern',
-      getPattern: function Dummy_fromIR_getPattern() {
-        return 'hotpink';
-      }
-    };
-  };
+  return PatternCS;
+})();
 
-  Dummy.prototype = {
-    getIR: function Dummy_getIR() {
-      return ['Dummy'];
+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);
     }
-  };
-  return Dummy;
-})();
+    this.lookup = lookupArray;
+  }
 
-var TilingPattern = (function TilingPatternClosure() {
-  var PaintType = {
-    COLORED: 1,
-    UNCOLORED: 2
-  };
+  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;
 
-  var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough
+      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;
+})();
 
-  function TilingPattern(IR, color, ctx, objs, commonObjs, baseTransform) {
-    this.name = IR[1][0].name;
-    this.operatorList = IR[2];
-    this.matrix = IR[3] || [1, 0, 0, 1, 0, 0];
-    this.bbox = IR[4];
-    this.xstep = IR[5];
-    this.ystep = IR[6];
-    this.paintType = IR[7];
-    this.tilingType = IR[8];
-    this.color = color;
-    this.objs = objs;
-    this.commonObjs = commonObjs;
-    this.baseTransform = baseTransform;
-    this.type = 'Pattern';
-    this.ctx = ctx;
+var DeviceGrayCS = (function DeviceGrayCSClosure() {
+  function DeviceGrayCS() {
+    this.name = 'DeviceGray';
+    this.numComps = 1;
+    this.defaultColor = new Float32Array([0]);
   }
 
-  TilingPattern.getIR = function TilingPattern_getIR(operatorList, dict, args) {
-    var matrix = dict.get('Matrix');
-    var bbox = dict.get('BBox');
-    var xstep = dict.get('XStep');
-    var ystep = dict.get('YStep');
-    var paintType = dict.get('PaintType');
-    var tilingType = dict.get('TilingType');
+  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;
+})();
 
-    return [
-      'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep,
-      paintType, tilingType
-    ];
+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;
+})();
 
-  TilingPattern.prototype = {
-    createPatternCanvas: function TilinPattern_createPatternCanvas(owner) {
-      var operatorList = this.operatorList;
-      var bbox = this.bbox;
-      var xstep = this.xstep;
-      var ystep = this.ystep;
-      var paintType = this.paintType;
-      var tilingType = this.tilingType;
-      var color = this.color;
-      var objs = this.objs;
-      var commonObjs = this.commonObjs;
-      var ctx = this.ctx;
+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;
 
-      TODO('TilingType: ' + tilingType);
+    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;
 
-      var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3];
+    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;
+  }
 
-      var topLeft = [x0, y0];
-      // we want the canvas to be as large as the step size
-      var botRight = [x0 + xstep, y0 + ystep];
+  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
+  };
 
-      var width = botRight[0] - topLeft[0];
-      var height = botRight[1] - topLeft[1];
+  return DeviceCmykCS;
+})();
 
-      // Obtain scale from matrix and current transformation matrix.
-      var matrixScale = Util.singularValueDecompose2dScale(this.matrix);
-      var curMatrixScale = Util.singularValueDecompose2dScale(
-                             this.baseTransform);
-      var combinedScale = [matrixScale[0] * curMatrixScale[0],
-                           matrixScale[1] * curMatrixScale[1]];
+//
+// 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]);
 
-      // MAX_PATTERN_SIZE is used to avoid OOM situation.
-      // Use width and height values that are as close as possible to the end
-      // result when the pattern is used. Too low value makes the pattern look
-      // blurry. Too large value makes it look too crispy.
-      width = Math.min(Math.ceil(Math.abs(width * combinedScale[0])),
-                       MAX_PATTERN_SIZE);
+    if (!whitePoint) {
+      error('WhitePoint missing - required for color space CalGray');
+    }
+    blackPoint = blackPoint || [0, 0, 0];
+    gamma = gamma || 1;
 
-      height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])),
-                        MAX_PATTERN_SIZE);
+    // Translate arguments to spec variables.
+    this.XW = whitePoint[0];
+    this.YW = whitePoint[1];
+    this.ZW = whitePoint[2];
 
-      var tmpCanvas = CachedCanvases.getCanvas('pattern', width, height, true);
-      var tmpCtx = tmpCanvas.context;
-      var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs);
-      graphics.groupLevel = owner.groupLevel;
+    this.XB = blackPoint[0];
+    this.YB = blackPoint[1];
+    this.ZB = blackPoint[2];
 
-      this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color);
+    this.G = gamma;
 
-      this.setScale(width, height, xstep, ystep);
-      this.transformToScale(graphics);
+    // 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');
+    }
 
-      // transform coordinates to pattern space
-      var tmpTranslate = [1, 0, 0, 1, -topLeft[0], -topLeft[1]];
-      graphics.transform.apply(graphics, tmpTranslate);
+    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;
+    }
 
-      this.clipBbox(graphics, bbox, x0, y0, x1, y1);
+    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.');
+    }
 
-      graphics.executeOperatorList(operatorList);
-      return tmpCanvas.canvas;
-    },
+    if (this.G < 1) {
+      info('Invalid Gamma: ' + this.G + ' for ' + this.name +
+           ', falling back to default');
+      this.G = 1;
+    }
+  }
 
-    setScale: function TilingPattern_setScale(width, height, xstep, ystep) {
-      this.scale = [width / xstep, height / ystep];
-    },
+  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;
+  }
 
-    transformToScale: function TilingPattern_transformToScale(graphics) {
-      var scale = this.scale;
-      var tmpScale = [scale[0], 0, 0, scale[1], 0, 0];
-      graphics.transform.apply(graphics, tmpScale);
+  CalGrayCS.prototype = {
+    getRgb: function CalGrayCS_getRgb(src, srcOffset) {
+      var rgb = new Uint8Array(3);
+      this.getRgbItem(src, srcOffset, rgb, 0);
+      return rgb;
     },
-
-    scaleToContext: function TilingPattern_scaleToContext() {
-      var scale = this.scale;
-      this.ctx.scale(1 / scale[0], 1 / scale[1]);
+    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) {
+      var scale = 1 / ((1 << bits) - 1);
 
-    clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
-      if (bbox && isArray(bbox) && 4 == bbox.length) {
-        var bboxWidth = x1 - x0;
-        var bboxHeight = y1 - y0;
-        graphics.rectangle(x0, y0, bboxWidth, bboxHeight);
-        graphics.clip();
-        graphics.endPath();
+      for (var i = 0; i < count; ++i) {
+        convertToRgb(this, src, srcOffset, dest, destOffset, scale);
+        srcOffset += 1;
+        destOffset += 3;
       }
     },
-
-    setFillAndStrokeStyleToContext:
-      function setFillAndStrokeStyleToContext(context, paintType, color) {
-      switch (paintType) {
-        case PaintType.COLORED:
-          var ctx = this.ctx;
-          context.fillStyle = ctx.fillStyle;
-          context.strokeStyle = ctx.strokeStyle;
-          break;
-        case PaintType.UNCOLORED:
-          var rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0);
-          var cssColor = Util.makeCssRgb(rgbColor);
-          context.fillStyle = cssColor;
-          context.strokeStyle = cssColor;
-          break;
-        default:
-          error('Unsupported paint type: ' + paintType);
-      }
+    getOutputLength: function CalGrayCS_getOutputLength(inputLength) {
+      return inputLength * 3;
     },
-
-    getPattern: function TilingPattern_getPattern(ctx, owner) {
-      var temporaryPatternCanvas = this.createPatternCanvas(owner);
-
-      var ctx = this.ctx;
-      ctx.setTransform.apply(ctx, this.baseTransform);
-      ctx.transform.apply(ctx, this.matrix);
-      this.scaleToContext();
-
-      return ctx.createPattern(temporaryPatternCanvas, 'repeat');
-    }
+    isPassthrough: ColorSpace.prototype.isPassthrough,
+    createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
+    isDefaultDecode: function CalGrayCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
+    },
+    usesZeroToOneRange: true
   };
-
-  return TilingPattern;
+  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];
 
-var PDFFunction = (function PDFFunctionClosure() {
-  var CONSTRUCT_SAMPLED = 0;
-  var CONSTRUCT_INTERPOLATED = 2;
-  var CONSTRUCT_STICHED = 3;
-  var CONSTRUCT_POSTSCRIPT = 4;
+    // 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];
 
-  return {
-    getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps,
-                                                       str) {
-      var length = 1;
-      for (var i = 0, ii = size.length; i < ii; i++)
-        length *= size[i];
-      length *= outputSize;
-
-      var array = [];
-      var codeSize = 0;
-      var codeBuf = 0;
-      // 32 is a valid bps so shifting won't work
-      var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1);
-
-      var strBytes = str.getBytes((length * bps + 7) / 8);
-      var strIdx = 0;
-      for (var i = 0; i < length; i++) {
-        while (codeSize < bps) {
-          codeBuf <<= 8;
-          codeBuf |= strBytes[strIdx++];
-          codeSize += 8;
-        }
-        codeSize -= bps;
-        array.push((codeBuf >> codeSize) * sampleMul);
-        codeBuf &= (1 << codeSize) - 1;
-      }
-      return array;
-    },
+    // 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];
 
-    getIR: function PDFFunction_getIR(xref, fn) {
-      var dict = fn.dict;
-      if (!dict)
-        dict = fn;
+    // Validate vars as per spec
+    if (this.XW < 0 || this.ZW < 0 || this.YW !== 1)
+      error('Invalid WhitePoint components, no fallback available');
 
-      var types = [this.constructSampled,
-                   null,
-                   this.constructInterpolated,
-                   this.constructStiched,
-                   this.constructPostScript];
+    if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
+      info('Invalid BlackPoint, falling back to default');
+      this.XB = this.YB = this.ZB = 0;
+    }
 
-      var typeNum = dict.get('FunctionType');
-      var typeFn = types[typeNum];
-      if (!typeFn)
-        error('Unknown type of function');
+    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;
+    }
+  }
 
-      return typeFn.call(this, fn, dict, xref);
-    },
+  // Function g(x) from spec
+  function fn_g(x) {
+    if (x >= 6 / 29)
+      return x * x * x;
+    else
+      return (108 / 841) * (x - 4 / 29);
+  }
 
-    fromIR: function PDFFunction_fromIR(IR) {
-      var type = IR[0];
-      switch (type) {
-        case CONSTRUCT_SAMPLED:
-          return this.constructSampledFromIR(IR);
-        case CONSTRUCT_INTERPOLATED:
-          return this.constructInterpolatedFromIR(IR);
-        case CONSTRUCT_STICHED:
-          return this.constructStichedFromIR(IR);
-        //case CONSTRUCT_POSTSCRIPT:
-        default:
-          return this.constructPostScriptFromIR(IR);
-      }
-    },
+  function decode(value, high1, low2, high2) {
+    return low2 + (value) * (high2 - low2) / (high1);
+  }
 
-    parse: function PDFFunction_parse(xref, fn) {
-      var IR = this.getIR(xref, fn);
-      return this.fromIR(IR);
-    },
+  // 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);
+    }
 
-    constructSampled: function PDFFunction_constructSampled(str, dict) {
-      function toMultiArray(arr) {
-        var inputLength = arr.length;
-        var outputLength = arr.length / 2;
-        var out = [];
-        var index = 0;
-        for (var i = 0; i < inputLength; i += 2) {
-          out[index] = [arr[i], arr[i + 1]];
-          ++index;
-        }
-        return out;
-      }
-      var domain = dict.get('Domain');
-      var range = dict.get('Range');
+    // 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;
 
-      if (!domain || !range)
-        error('No domain or range');
+    // 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 inputSize = domain.length / 2;
-      var outputSize = range.length / 2;
+    var X = cs.XW * fn_g(L);
+    var Y = cs.YW * fn_g(M);
+    var Z = cs.ZW * fn_g(N);
 
-      domain = toMultiArray(domain);
-      range = toMultiArray(range);
+    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;
+  }
 
-      var size = dict.get('Size');
-      var bps = dict.get('BitsPerSample');
-      var order = dict.get('Order') || 1;
-      if (order !== 1) {
-        // No description how cubic spline interpolation works in PDF32000:2008
-        // As in poppler, ignoring order, linear interpolation may work as good
-        TODO('No support for cubic spline interpolation: ' + order);
+  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 encode = dict.get('Encode');
-      if (!encode) {
-        encode = [];
-        for (var i = 0; i < inputSize; ++i) {
-          encode.push(0);
-          encode.push(size[i] - 1);
-        }
-      }
-      encode = toMultiArray(encode);
 
-      var decode = dict.get('Decode');
-      if (!decode)
-        decode = range;
-      else
-        decode = toMultiArray(decode);
 
-      var samples = this.getSampleArray(size, outputSize, bps, str);
+var PatternType = {
+  AXIAL: 2,
+  RADIAL: 3
+};
 
-      return [
-        CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size,
-        outputSize, Math.pow(2, bps) - 1, range
-      ];
-    },
+var Pattern = (function PatternClosure() {
+  // Constructor should define this.getPattern
+  function Pattern() {
+    error('should not call Pattern constructor');
+  }
 
-    constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) {
-      // See chapter 3, page 109 of the PDF reference
-      function interpolate(x, xmin, xmax, ymin, ymax) {
-        return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin)));
-      }
+  Pattern.prototype = {
+    // Input: current Canvas context
+    // Output: the appropriate fillStyle or strokeStyle
+    getPattern: function Pattern_getPattern(ctx) {
+      error('Should not call Pattern.getStyle: ' + ctx);
+    }
+  };
 
-      return function constructSampledFromIRResult(args) {
-        // See chapter 3, page 110 of the PDF reference.
-        var m = IR[1];
-        var domain = IR[2];
-        var encode = IR[3];
-        var decode = IR[4];
-        var samples = IR[5];
-        var size = IR[6];
-        var n = IR[7];
-        var mask = IR[8];
-        var range = IR[9];
+  Pattern.shadingFromIR = function Pattern_shadingFromIR(raw) {
+    return Shadings[raw[0]].fromIR(raw);
+  };
 
-        if (m != args.length)
-          error('Incorrect number of arguments: ' + m + ' != ' +
-                args.length);
+  Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref,
+                                                       res) {
 
-        var x = args;
+    var dict = isStream(shading) ? shading.dict : shading;
+    var type = dict.get('ShadingType');
 
-        // Building the cube vertices: its part and sample index
-        // http://rjwagner49.com/Mathematics/Interpolation.pdf
-        var cubeVertices = 1 << m;
-        var cubeN = new Float64Array(cubeVertices);
-        var cubeVertex = new Uint32Array(cubeVertices);
-        for (var j = 0; j < cubeVertices; j++)
-          cubeN[j] = 1;
+    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);
+        return new Shadings.Dummy();
+    }
+  };
+  return Pattern;
+})();
 
-        var k = n, pos = 1;
-        // Map x_i to y_j for 0 <= i < m using the sampled function.
-        for (var i = 0; i < m; ++i) {
-          // x_i' = min(max(x_i, Domain_2i), Domain_2i+1)
-          var domain_2i = domain[i][0];
-          var domain_2i_1 = domain[i][1];
-          var xi = Math.min(Math.max(x[i], domain_2i), domain_2i_1);
+var Shadings = {};
 
-          // e_i = Interpolate(x_i', Domain_2i, Domain_2i+1,
-          //                   Encode_2i, Encode_2i+1)
-          var e = interpolate(xi, domain_2i, domain_2i_1,
-                              encode[i][0], encode[i][1]);
+// A small number to offset the first/last color stops so we can insert ones to
+// support extend.  Number.MIN_VALUE appears to be too small and breaks the
+// extend. 1e-7 works in FF but chrome seems to use an even smaller sized number
+// internally so we have to go bigger.
+Shadings.SMALL_NUMBER = 1e-2;
 
-          // e_i' = min(max(e_i, 0), Size_i - 1)
-          var size_i = size[i];
-          e = Math.min(Math.max(e, 0), size_i - 1);
+// Radial and axial shading have very similar implementations
+// If needed, the implementations can be broken into two classes
+Shadings.RadialAxial = (function RadialAxialClosure() {
+  function RadialAxial(dict, matrix, xref, res, ctx) {
+    this.matrix = matrix;
+    this.coordsArr = dict.get('Coords');
+    this.shadingType = dict.get('ShadingType');
+    this.type = 'Pattern';
+    this.ctx = ctx;
+    var cs = dict.get('ColorSpace', 'CS');
+    cs = ColorSpace.parse(cs, xref, res);
+    this.cs = cs;
 
-          // Adjusting the cube: N and vertex sample index
-          var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; // e1 = e0 + 1;
-          var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
-          var n1 = e - e0; // (e - e0) / (e1 - e0);
-          var offset0 = e0 * k;
-          var offset1 = offset0 + k; // e1 * k
-          for (var j = 0; j < cubeVertices; j++) {
-            if (j & pos) {
-              cubeN[j] *= n1;
-              cubeVertex[j] += offset1;
-            } else {
-              cubeN[j] *= n0;
-              cubeVertex[j] += offset0;
-            }
-          }
+    var t0 = 0.0, t1 = 1.0;
+    if (dict.has('Domain')) {
+      var domainArr = dict.get('Domain');
+      t0 = domainArr[0];
+      t1 = domainArr[1];
+    }
 
-          k *= size_i;
-          pos <<= 1;
-        }
+    var extendStart = false, extendEnd = false;
+    if (dict.has('Extend')) {
+      var extendArr = dict.get('Extend');
+      extendStart = extendArr[0];
+      extendEnd = extendArr[1];
+    }
 
-        var y = new Float64Array(n);
-        for (var j = 0; j < n; ++j) {
-          // Sum all cube vertices' samples portions
-          var rj = 0;
-          for (var i = 0; i < cubeVertices; i++)
-            rj += samples[cubeVertex[i] + j] * cubeN[i];
+    if (this.shadingType === PatternType.RADIAL &&
+       (!extendStart || !extendEnd)) {
+      // Radial gradient only currently works if either circle is fully within
+      // the other circle.
+      var x1 = this.coordsArr[0];
+      var y1 = this.coordsArr[1];
+      var r1 = this.coordsArr[2];
+      var x2 = this.coordsArr[3];
+      var y2 = this.coordsArr[4];
+      var r2 = this.coordsArr[5];
+      var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
+      if (r1 <= r2 + distance &&
+          r2 <= r1 + distance) {
+        warn('Unsupported radial gradient.');
+      }
+    }
 
-          // r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1,
-          //                    Decode_2j, Decode_2j+1)
-          rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
+    this.extendStart = extendStart;
+    this.extendEnd = extendEnd;
 
-          // y_j = min(max(r_j, range_2j), range_2j+1)
-          y[j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
+    var fnObj = dict.get('Function');
+    var fn;
+    if (isArray(fnObj)) {
+      var fnArray = [];
+      for (var j = 0, jj = fnObj.length; j < jj; j++) {
+        var obj = xref.fetchIfRef(fnObj[j]);
+        if (!isPDFFunction(obj)) {
+          error('Invalid function');
         }
-
-        return y;
+        fnArray.push(PDFFunction.parse(xref, obj));
+      }
+      fn = function radialAxialColorFunction(arg) {
+        var out = [];
+        for (var i = 0, ii = fnArray.length; i < ii; i++) {
+          out.push(fnArray[i](arg)[0]);
+        }
+        return out;
       };
-    },
-
-    constructInterpolated: function PDFFunction_constructInterpolated(str,
-                                                                      dict) {
-      var c0 = dict.get('C0') || [0];
-      var c1 = dict.get('C1') || [1];
-      var n = dict.get('N');
+    } else {
+      if (!isPDFFunction(fnObj)) {
+        error('Invalid function');
+      }
+      fn = PDFFunction.parse(xref, fnObj);
+    }
 
-      if (!isArray(c0) || !isArray(c1))
-        error('Illegal dictionary for interpolated function');
+    // 10 samples seems good enough for now, but probably won't work
+    // if there are sharp color changes. Ideally, we would implement
+    // the spec faithfully and add lossless optimizations.
+    var diff = t1 - t0;
+    var step = diff / 10;
 
-      var length = c0.length;
-      var diff = [];
-      for (var i = 0; i < length; ++i)
-        diff.push(c1[i] - c0[i]);
+    var colorStops = this.colorStops = [];
 
-      return [CONSTRUCT_INTERPOLATED, c0, diff, n];
-    },
+    // Protect against bad domains so we don't end up in an infinte loop below.
+    if (t0 >= t1 || step <= 0) {
+      // Acrobat doesn't seem to handle these cases so we'll ignore for
+      // now.
+      info('Bad shading domain.');
+      return;
+    }
 
-    constructInterpolatedFromIR:
-      function PDFFunction_constructInterpolatedFromIR(IR) {
-      var c0 = IR[1];
-      var diff = IR[2];
-      var n = IR[3];
+    for (var i = t0; i <= t1; i += step) {
+      var rgbColor = cs.getRgb(fn([i]), 0);
+      var cssColor = Util.makeCssRgb(rgbColor);
+      colorStops.push([(i - t0) / diff, cssColor]);
+    }
 
-      var length = diff.length;
+    var background = 'transparent';
+    if (dict.has('Background')) {
+      var rgbColor = cs.getRgb(dict.get('Background'), 0);
+      background = Util.makeCssRgb(rgbColor);
+    }
 
-      return function constructInterpolatedFromIRResult(args) {
-        var x = n == 1 ? args[0] : Math.pow(args[0], n);
+    if (!extendStart) {
+      // Insert a color stop at the front and offset the first real color stop
+      // so it doesn't conflict with the one we insert.
+      colorStops.unshift([0, background]);
+      colorStops[1][0] += Shadings.SMALL_NUMBER;
+    }
+    if (!extendEnd) {
+      // Same idea as above in extendStart but for the end.
+      colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER;
+      colorStops.push([1, background]);
+    }
 
-        var out = [];
-        for (var j = 0; j < length; ++j)
-          out.push(c0[j] + (x * diff[j]));
+    this.colorStops = colorStops;
+  }
 
-        return out;
+  RadialAxial.fromIR = function RadialAxial_fromIR(raw) {
+    var type = raw[1];
+    var colorStops = raw[2];
+    var p0 = raw[3];
+    var p1 = raw[4];
+    var r0 = raw[5];
+    var r1 = raw[6];
+    return {
+      type: 'Pattern',
+      getPattern: function RadialAxial_getPattern(ctx) {
+        var grad;
+        if (type == PatternType.AXIAL)
+          grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
+        else if (type == PatternType.RADIAL)
+          grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
 
-      };
-    },
+        for (var i = 0, ii = colorStops.length; i < ii; ++i) {
+          var c = colorStops[i];
+          grad.addColorStop(c[0], c[1]);
+        }
+        return grad;
+      }
+    };
+  };
 
-    constructStiched: function PDFFunction_constructStiched(fn, dict, xref) {
-      var domain = dict.get('Domain');
+  RadialAxial.prototype = {
+    getIR: function RadialAxial_getIR() {
+      var coordsArr = this.coordsArr;
+      var type = this.shadingType;
+      if (type == PatternType.AXIAL) {
+        var p0 = [coordsArr[0], coordsArr[1]];
+        var p1 = [coordsArr[2], coordsArr[3]];
+        var r0 = null;
+        var r1 = null;
+      } else if (type == PatternType.RADIAL) {
+        var p0 = [coordsArr[0], coordsArr[1]];
+        var p1 = [coordsArr[3], coordsArr[4]];
+        var r0 = coordsArr[2];
+        var r1 = coordsArr[5];
+      } else {
+        error('getPattern type unknown: ' + type);
+      }
 
-      if (!domain)
-        error('No domain');
+      var matrix = this.matrix;
+      if (matrix) {
+        p0 = Util.applyTransform(p0, matrix);
+        p1 = Util.applyTransform(p1, matrix);
+      }
 
-      var inputSize = domain.length / 2;
-      if (inputSize != 1)
-        error('Bad domain for stiched function');
+      return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1];
+    }
+  };
 
-      var fnRefs = dict.get('Functions');
-      var fns = [];
-      for (var i = 0, ii = fnRefs.length; i < ii; ++i)
-        fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i])));
+  return RadialAxial;
+})();
+
+Shadings.Dummy = (function DummyClosure() {
+  function Dummy() {
+    this.type = 'Pattern';
+  }
+
+  Dummy.fromIR = function Dummy_fromIR() {
+    return {
+      type: 'Pattern',
+      getPattern: function Dummy_fromIR_getPattern() {
+        return 'hotpink';
+      }
+    };
+  };
+
+  Dummy.prototype = {
+    getIR: function Dummy_getIR() {
+      return ['Dummy'];
+    }
+  };
+  return Dummy;
+})();
+
+var TilingPattern = (function TilingPatternClosure() {
+  var PaintType = {
+    COLORED: 1,
+    UNCOLORED: 2
+  };
+
+  var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough
+
+  function TilingPattern(IR, color, ctx, objs, commonObjs, baseTransform) {
+    this.name = IR[1][0].name;
+    this.operatorList = IR[2];
+    this.matrix = IR[3] || [1, 0, 0, 1, 0, 0];
+    this.bbox = IR[4];
+    this.xstep = IR[5];
+    this.ystep = IR[6];
+    this.paintType = IR[7];
+    this.tilingType = IR[8];
+    this.color = color;
+    this.objs = objs;
+    this.commonObjs = commonObjs;
+    this.baseTransform = baseTransform;
+    this.type = 'Pattern';
+    this.ctx = ctx;
+  }
+
+  TilingPattern.getIR = function TilingPattern_getIR(operatorList, dict, args) {
+    var matrix = dict.get('Matrix');
+    var bbox = dict.get('BBox');
+    var xstep = dict.get('XStep');
+    var ystep = dict.get('YStep');
+    var paintType = dict.get('PaintType');
+    var tilingType = dict.get('TilingType');
+
+    return [
+      'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep,
+      paintType, tilingType
+    ];
+  };
+
+  TilingPattern.prototype = {
+    createPatternCanvas: function TilinPattern_createPatternCanvas(owner) {
+      var operatorList = this.operatorList;
+      var bbox = this.bbox;
+      var xstep = this.xstep;
+      var ystep = this.ystep;
+      var paintType = this.paintType;
+      var tilingType = this.tilingType;
+      var color = this.color;
+      var objs = this.objs;
+      var commonObjs = this.commonObjs;
+      var ctx = this.ctx;
+
+      info('TilingType: ' + tilingType);
+
+      var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3];
+
+      var topLeft = [x0, y0];
+      // we want the canvas to be as large as the step size
+      var botRight = [x0 + xstep, y0 + ystep];
+
+      var width = botRight[0] - topLeft[0];
+      var height = botRight[1] - topLeft[1];
+
+      // Obtain scale from matrix and current transformation matrix.
+      var matrixScale = Util.singularValueDecompose2dScale(this.matrix);
+      var curMatrixScale = Util.singularValueDecompose2dScale(
+                             this.baseTransform);
+      var combinedScale = [matrixScale[0] * curMatrixScale[0],
+                           matrixScale[1] * curMatrixScale[1]];
+
+      // MAX_PATTERN_SIZE is used to avoid OOM situation.
+      // Use width and height values that are as close as possible to the end
+      // result when the pattern is used. Too low value makes the pattern look
+      // blurry. Too large value makes it look too crispy.
+      width = Math.min(Math.ceil(Math.abs(width * combinedScale[0])),
+                       MAX_PATTERN_SIZE);
+
+      height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])),
+                        MAX_PATTERN_SIZE);
+
+      var tmpCanvas = CachedCanvases.getCanvas('pattern', width, height, true);
+      var tmpCtx = tmpCanvas.context;
+      var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs);
+      graphics.groupLevel = owner.groupLevel;
+
+      this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color);
+
+      this.setScale(width, height, xstep, ystep);
+      this.transformToScale(graphics);
+
+      // transform coordinates to pattern space
+      var tmpTranslate = [1, 0, 0, 1, -topLeft[0], -topLeft[1]];
+      graphics.transform.apply(graphics, tmpTranslate);
+
+      this.clipBbox(graphics, bbox, x0, y0, x1, y1);
+
+      graphics.executeOperatorList(operatorList);
+      return tmpCanvas.canvas;
+    },
+
+    setScale: function TilingPattern_setScale(width, height, xstep, ystep) {
+      this.scale = [width / xstep, height / ystep];
+    },
+
+    transformToScale: function TilingPattern_transformToScale(graphics) {
+      var scale = this.scale;
+      var tmpScale = [scale[0], 0, 0, scale[1], 0, 0];
+      graphics.transform.apply(graphics, tmpScale);
+    },
+
+    scaleToContext: function TilingPattern_scaleToContext() {
+      var scale = this.scale;
+      this.ctx.scale(1 / scale[0], 1 / scale[1]);
+    },
+
+    clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
+      if (bbox && isArray(bbox) && 4 == bbox.length) {
+        var bboxWidth = x1 - x0;
+        var bboxHeight = y1 - y0;
+        graphics.rectangle(x0, y0, bboxWidth, bboxHeight);
+        graphics.clip();
+        graphics.endPath();
+      }
+    },
+
+    setFillAndStrokeStyleToContext:
+      function setFillAndStrokeStyleToContext(context, paintType, color) {
+      switch (paintType) {
+        case PaintType.COLORED:
+          var ctx = this.ctx;
+          context.fillStyle = ctx.fillStyle;
+          context.strokeStyle = ctx.strokeStyle;
+          break;
+        case PaintType.UNCOLORED:
+          var rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0);
+          var cssColor = Util.makeCssRgb(rgbColor);
+          context.fillStyle = cssColor;
+          context.strokeStyle = cssColor;
+          break;
+        default:
+          error('Unsupported paint type: ' + paintType);
+      }
+    },
+
+    getPattern: function TilingPattern_getPattern(ctx, owner) {
+      var temporaryPatternCanvas = this.createPatternCanvas(owner);
+
+      var ctx = this.ctx;
+      ctx.setTransform.apply(ctx, this.baseTransform);
+      ctx.transform.apply(ctx, this.matrix);
+      this.scaleToContext();
+
+      return ctx.createPattern(temporaryPatternCanvas, 'repeat');
+    }
+  };
+
+  return TilingPattern;
+})();
+
+
+
+var PDFFunction = (function PDFFunctionClosure() {
+  var CONSTRUCT_SAMPLED = 0;
+  var CONSTRUCT_INTERPOLATED = 2;
+  var CONSTRUCT_STICHED = 3;
+  var CONSTRUCT_POSTSCRIPT = 4;
+
+  return {
+    getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps,
+                                                       str) {
+      var length = 1;
+      for (var i = 0, ii = size.length; i < ii; i++)
+        length *= size[i];
+      length *= outputSize;
+
+      var array = [];
+      var codeSize = 0;
+      var codeBuf = 0;
+      // 32 is a valid bps so shifting won't work
+      var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1);
+
+      var strBytes = str.getBytes((length * bps + 7) / 8);
+      var strIdx = 0;
+      for (var i = 0; i < length; i++) {
+        while (codeSize < bps) {
+          codeBuf <<= 8;
+          codeBuf |= strBytes[strIdx++];
+          codeSize += 8;
+        }
+        codeSize -= bps;
+        array.push((codeBuf >> codeSize) * sampleMul);
+        codeBuf &= (1 << codeSize) - 1;
+      }
+      return array;
+    },
+
+    getIR: function PDFFunction_getIR(xref, fn) {
+      var dict = fn.dict;
+      if (!dict)
+        dict = fn;
+
+      var types = [this.constructSampled,
+                   null,
+                   this.constructInterpolated,
+                   this.constructStiched,
+                   this.constructPostScript];
+
+      var typeNum = dict.get('FunctionType');
+      var typeFn = types[typeNum];
+      if (!typeFn)
+        error('Unknown type of function');
+
+      return typeFn.call(this, fn, dict, xref);
+    },
+
+    fromIR: function PDFFunction_fromIR(IR) {
+      var type = IR[0];
+      switch (type) {
+        case CONSTRUCT_SAMPLED:
+          return this.constructSampledFromIR(IR);
+        case CONSTRUCT_INTERPOLATED:
+          return this.constructInterpolatedFromIR(IR);
+        case CONSTRUCT_STICHED:
+          return this.constructStichedFromIR(IR);
+        //case CONSTRUCT_POSTSCRIPT:
+        default:
+          return this.constructPostScriptFromIR(IR);
+      }
+    },
+
+    parse: function PDFFunction_parse(xref, fn) {
+      var IR = this.getIR(xref, fn);
+      return this.fromIR(IR);
+    },
+
+    constructSampled: function PDFFunction_constructSampled(str, dict) {
+      function toMultiArray(arr) {
+        var inputLength = arr.length;
+        var outputLength = arr.length / 2;
+        var out = [];
+        var index = 0;
+        for (var i = 0; i < inputLength; i += 2) {
+          out[index] = [arr[i], arr[i + 1]];
+          ++index;
+        }
+        return out;
+      }
+      var domain = dict.get('Domain');
+      var range = dict.get('Range');
+
+      if (!domain || !range)
+        error('No domain or range');
+
+      var inputSize = domain.length / 2;
+      var outputSize = range.length / 2;
+
+      domain = toMultiArray(domain);
+      range = toMultiArray(range);
+
+      var size = dict.get('Size');
+      var bps = dict.get('BitsPerSample');
+      var order = dict.get('Order') || 1;
+      if (order !== 1) {
+        // No description how cubic spline interpolation works in PDF32000:2008
+        // As in poppler, ignoring order, linear interpolation may work as good
+        info('No support for cubic spline interpolation: ' + order);
+      }
+
+      var encode = dict.get('Encode');
+      if (!encode) {
+        encode = [];
+        for (var i = 0; i < inputSize; ++i) {
+          encode.push(0);
+          encode.push(size[i] - 1);
+        }
+      }
+      encode = toMultiArray(encode);
+
+      var decode = dict.get('Decode');
+      if (!decode)
+        decode = range;
+      else
+        decode = toMultiArray(decode);
+
+      var samples = this.getSampleArray(size, outputSize, bps, str);
+
+      return [
+        CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size,
+        outputSize, Math.pow(2, bps) - 1, range
+      ];
+    },
+
+    constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) {
+      // See chapter 3, page 109 of the PDF reference
+      function interpolate(x, xmin, xmax, ymin, ymax) {
+        return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin)));
+      }
+
+      return function constructSampledFromIRResult(args) {
+        // See chapter 3, page 110 of the PDF reference.
+        var m = IR[1];
+        var domain = IR[2];
+        var encode = IR[3];
+        var decode = IR[4];
+        var samples = IR[5];
+        var size = IR[6];
+        var n = IR[7];
+        var mask = IR[8];
+        var range = IR[9];
+
+        if (m != args.length)
+          error('Incorrect number of arguments: ' + m + ' != ' +
+                args.length);
+
+        var x = args;
+
+        // Building the cube vertices: its part and sample index
+        // http://rjwagner49.com/Mathematics/Interpolation.pdf
+        var cubeVertices = 1 << m;
+        var cubeN = new Float64Array(cubeVertices);
+        var cubeVertex = new Uint32Array(cubeVertices);
+        for (var j = 0; j < cubeVertices; j++)
+          cubeN[j] = 1;
+
+        var k = n, pos = 1;
+        // Map x_i to y_j for 0 <= i < m using the sampled function.
+        for (var i = 0; i < m; ++i) {
+          // x_i' = min(max(x_i, Domain_2i), Domain_2i+1)
+          var domain_2i = domain[i][0];
+          var domain_2i_1 = domain[i][1];
+          var xi = Math.min(Math.max(x[i], domain_2i), domain_2i_1);
+
+          // e_i = Interpolate(x_i', Domain_2i, Domain_2i+1,
+          //                   Encode_2i, Encode_2i+1)
+          var e = interpolate(xi, domain_2i, domain_2i_1,
+                              encode[i][0], encode[i][1]);
+
+          // e_i' = min(max(e_i, 0), Size_i - 1)
+          var size_i = size[i];
+          e = Math.min(Math.max(e, 0), size_i - 1);
+
+          // Adjusting the cube: N and vertex sample index
+          var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; // e1 = e0 + 1;
+          var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
+          var n1 = e - e0; // (e - e0) / (e1 - e0);
+          var offset0 = e0 * k;
+          var offset1 = offset0 + k; // e1 * k
+          for (var j = 0; j < cubeVertices; j++) {
+            if (j & pos) {
+              cubeN[j] *= n1;
+              cubeVertex[j] += offset1;
+            } else {
+              cubeN[j] *= n0;
+              cubeVertex[j] += offset0;
+            }
+          }
+
+          k *= size_i;
+          pos <<= 1;
+        }
+
+        var y = new Float64Array(n);
+        for (var j = 0; j < n; ++j) {
+          // Sum all cube vertices' samples portions
+          var rj = 0;
+          for (var i = 0; i < cubeVertices; i++)
+            rj += samples[cubeVertex[i] + j] * cubeN[i];
+
+          // r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1,
+          //                    Decode_2j, Decode_2j+1)
+          rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
+
+          // y_j = min(max(r_j, range_2j), range_2j+1)
+          y[j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
+        }
+
+        return y;
+      };
+    },
+
+    constructInterpolated: function PDFFunction_constructInterpolated(str,
+                                                                      dict) {
+      var c0 = dict.get('C0') || [0];
+      var c1 = dict.get('C1') || [1];
+      var n = dict.get('N');
+
+      if (!isArray(c0) || !isArray(c1))
+        error('Illegal dictionary for interpolated function');
+
+      var length = c0.length;
+      var diff = [];
+      for (var i = 0; i < length; ++i)
+        diff.push(c1[i] - c0[i]);
+
+      return [CONSTRUCT_INTERPOLATED, c0, diff, n];
+    },
+
+    constructInterpolatedFromIR:
+      function PDFFunction_constructInterpolatedFromIR(IR) {
+      var c0 = IR[1];
+      var diff = IR[2];
+      var n = IR[3];
+
+      var length = diff.length;
+
+      return function constructInterpolatedFromIRResult(args) {
+        var x = n == 1 ? args[0] : Math.pow(args[0], n);
+
+        var out = [];
+        for (var j = 0; j < length; ++j)
+          out.push(c0[j] + (x * diff[j]));
+
+        return out;
+
+      };
+    },
+
+    constructStiched: function PDFFunction_constructStiched(fn, dict, xref) {
+      var domain = dict.get('Domain');
+
+      if (!domain)
+        error('No domain');
+
+      var inputSize = domain.length / 2;
+      if (inputSize != 1)
+        error('Bad domain for stiched function');
+
+      var fnRefs = dict.get('Functions');
+      var fns = [];
+      for (var i = 0, ii = fnRefs.length; i < ii; ++i)
+        fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i])));
 
       var bounds = dict.get('Bounds');
       var encode = dict.get('Encode');
@@ -2475,6 +3538,29 @@ var Annotation = (function AnnotationClosure() {
     } 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 (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);
@@ -2519,7 +3605,7 @@ var Annotation = (function AnnotationClosure() {
     },
 
     loadResources: function(keys) {
-      var promise = new Promise();
+      var promise = new LegacyPromise();
       this.appearance.dict.getAsync('Resources').then(function(resources) {
         if (!resources) {
           promise.resolve();
@@ -2538,7 +3624,7 @@ var Annotation = (function AnnotationClosure() {
 
     getOperatorList: function Annotation_getToOperatorList(evaluator) {
 
-      var promise = new Promise();
+      var promise = new LegacyPromise();
 
       if (!this.appearance) {
         promise.resolve(new OperatorList());
@@ -2566,9 +3652,9 @@ var Annotation = (function AnnotationClosure() {
 
       resourcesPromise.then(function(resources) {
         var opList = new OperatorList();
-        opList.addOp('beginAnnotation', [data.rect, transform, matrix]);
+        opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
         evaluator.getOperatorList(this.appearance, resources, opList);
-        opList.addOp('endAnnotation', []);
+        opList.addOp(OPS.endAnnotation, []);
         promise.resolve(opList);
       }.bind(this));
 
@@ -2644,7 +3730,7 @@ var Annotation = (function AnnotationClosure() {
     if (annotation.isViewable()) {
       return annotation;
     } else {
-      TODO('unimplemented annotation type: ' + subtype);
+      warn('unimplemented annotation type: ' + subtype);
     }
   };
 
@@ -2655,19 +3741,19 @@ var Annotation = (function AnnotationClosure() {
       annotationsReadyPromise.reject(e);
     }
 
-    var annotationsReadyPromise = new Promise();
+    var annotationsReadyPromise = new LegacyPromise();
 
     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('beginAnnotations', []);
+      opList.addOp(OPS.beginAnnotations, []);
       for (var i = 0, n = datas.length; i < n; ++i) {
         var annotOpList = datas[i];
         opList.addOpList(annotOpList);
       }
-      opList.addOp('endAnnotations', []);
+      opList.addOp(OPS.endAnnotations, []);
       annotationsReadyPromise.resolve();
     }, reject);
 
@@ -2736,7 +3822,7 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() {
   Util.inherit(WidgetAnnotation, Annotation, {
     isViewable: function WidgetAnnotation_isViewable() {
       if (this.data.fieldType === 'Sig') {
-        TODO('unimplemented annotation type: Widget signature');
+        warn('unimplemented annotation type: Widget signature');
         return false;
       }
 
@@ -2817,7 +3903,7 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
         return Annotation.prototype.getOperatorList.call(this, evaluator);
       }
 
-      var promise = new Promise();
+      var promise = new LegacyPromise();
       var opList = new OperatorList();
       var data = this.data;
 
@@ -2843,10 +3929,10 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
       data.rgb = [0, 0, 0];
       // TODO THIS DOESN'T MAKE ANY SENSE SINCE THE fnArray IS EMPTY!
       for (var i = 0, n = fnArray.length; i < n; ++i) {
-        var fnName = appearanceFnArray[i];
+        var fnId = appearanceFnArray[i];
         var args = appearanceArgsArray[i];
 
-        if (fnName === 'setFont') {
+        if (fnId === OPS.setFont) {
           data.fontRefName = args[0];
           var size = args[1];
           if (size < 0) {
@@ -2856,9 +3942,9 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
             data.fontDirection = 1;
             data.fontSize = size;
           }
-        } else if (fnName === 'setFillRGBColor') {
+        } else if (fnId === OPS.setFillRGBColor) {
           data.rgb = args;
-        } else if (fnName === 'setFillGray') {
+        } else if (fnId === OPS.setFillGray) {
           var rgbValue = args[0] * 255;
           data.rgb = [rgbValue, rgbValue, rgbValue];
         }
@@ -2894,7 +3980,7 @@ var TextAnnotation = (function TextAnnotationClosure() {
   Util.inherit(TextAnnotation, Annotation, {
 
     getOperatorList: function TextAnnotation_getOperatorList(evaluator) {
-      var promise = new Promise();
+      var promise = new LegacyPromise();
       promise.resolve(new OperatorList());
       return promise;
     },
@@ -2994,7 +4080,7 @@ var LinkAnnotation = (function LinkAnnotationClosure() {
     if (action) {
       var linkType = action.get('S').name;
       if (linkType === 'URI') {
-        var url = action.get('URI');
+        var url = addDefaultProtocolToUrl(action.get('URI'));
         // TODO: pdf spec mentions urls can be relative to a Base
         // entry in the dictionary.
         if (!isValidUrl(url, false)) {
@@ -3021,7 +4107,7 @@ var LinkAnnotation = (function LinkAnnotationClosure() {
       } else if (linkType === 'Named') {
         data.action = action.get('N').name;
       } else {
-        TODO('unrecognized link type: ' + linkType);
+        warn('unrecognized link type: ' + linkType);
       }
     } else if (dict.has('Dest')) {
       // simple destination link
@@ -3030,6 +4116,14 @@ var LinkAnnotation = (function LinkAnnotationClosure() {
     }
   }
 
+  // Lets URLs beginning with 'www.' default to using the 'http://' protocol.
+  function addDefaultProtocolToUrl(url) {
+    if (url.indexOf('www.') === 0) {
+      return ('http://' + url);
+    }
+    return url;
+  }
+
   Util.inherit(LinkAnnotation, Annotation, {
     hasOperatorList: function LinkAnnotation_hasOperatorList() {
       return false;
@@ -3078,6 +4172,7 @@ var NetworkManager = (function NetworkManagerClosure() {
     this.url = url;
     args = args || {};
     this.httpHeaders = args.httpHeaders || {};
+    this.withCredentials = args.withCredentials || false;
     this.getXhr = args.getXhr ||
       function NetworkManager_getXhr() {
         return new XMLHttpRequest();
@@ -3126,6 +4221,7 @@ var NetworkManager = (function NetworkManagerClosure() {
       };
 
       xhr.open('GET', this.url);
+      xhr.withCredentials = this.withCredentials;
       for (var property in this.httpHeaders) {
         var value = this.httpHeaders[property];
         if (typeof value === 'undefined') {
@@ -3278,6 +4374,7 @@ var ChunkedStream = (function ChunkedStreamClosure() {
     this.numChunksLoaded = 0;
     this.numChunks = Math.ceil(length / chunkSize);
     this.manager = manager;
+    this.initialDataLength = 0;
   }
 
   // required methods for a stream. if a particular stream does not
@@ -3325,11 +4422,26 @@ var ChunkedStream = (function ChunkedStreamClosure() {
       }
     },
 
+    onReceiveInitialData: function (data) {
+      this.bytes.set(data);
+      this.initialDataLength = data.length;
+      var endChunk = this.end === data.length ?
+                     this.numChunks : Math.floor(data.length / this.chunkSize);
+      for (var i = 0; i < endChunk; i++) {
+        this.loadedChunks[i] = true;
+        ++this.numChunksLoaded;
+      }
+    },
+
     ensureRange: function ChunkedStream_ensureRange(begin, end) {
       if (begin >= end) {
         return;
       }
 
+      if (end <= this.initialDataLength) {
+        return;
+      }
+
       var chunkSize = this.chunkSize;
       var beginChunk = Math.floor(begin / chunkSize);
       var endChunk = Math.floor((end - 1) / chunkSize) + 1;
@@ -3470,7 +4582,8 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
       };
       this.networkManager = new NetworkManager(this.url, {
         getXhr: getXhr,
-        httpHeaders: args.httpHeaders
+        httpHeaders: args.httpHeaders,
+        withCredentials: args.withCredentials
       });
       this.sendRequest = function ChunkedStreamManager_sendRequest(begin, end) {
         this.networkManager.requestRange(begin, end, {
@@ -3486,11 +4599,26 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
     this.requestsByChunk = {};
     this.callbacksByRequest = {};
 
-    this.loadedStream = new Promise();
+    this.loadedStream = new LegacyPromise();
+    if (args.initialData) {
+      this.setInitialData(args.initialData);
+    }
   }
 
   ChunkedStreamManager.prototype = {
 
+    setInitialData: function ChunkedStreamManager_setInitialData(data) {
+      this.stream.onReceiveInitialData(data);
+      if (this.stream.allChunksLoaded()) {
+        this.loadedStream.resolve(this.stream);
+      } else if (this.msgHandler) {
+        this.msgHandler.send('DocProgress', {
+          loaded: data.length,
+          total: this.length
+        });
+      }
+    },
+
     onLoadedStream: function ChunkedStreamManager_getLoadedStream() {
       return this.loadedStream;
     },
@@ -3592,16 +4720,16 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
     // chunks as possible
     groupChunks: function ChunkedStreamManager_groupChunks(chunks) {
       var groupedChunks = [];
-      var beginChunk;
-      var prevChunk;
+      var beginChunk = -1;
+      var prevChunk = -1;
       for (var i = 0; i < chunks.length; ++i) {
         var chunk = chunks[i];
 
-        if (!beginChunk) {
+        if (beginChunk < 0) {
           beginChunk = chunk;
         }
 
-        if (prevChunk && prevChunk + 1 !== chunk) {
+        if (prevChunk >= 0 && prevChunk + 1 !== chunk) {
           groupedChunks.push({
             beginChunk: beginChunk, endChunk: prevChunk + 1});
           beginChunk = chunk;
@@ -3747,6 +4875,10 @@ var BasePdfManager = (function BasePdfManagerClosure() {
       return this.pdfModel.getPage(pageIndex);
     },
 
+    cleanup: function BasePdfManager_cleanup() {
+      return this.pdfModel.cleanup();
+    },
+
     ensure: function BasePdfManager_ensure(obj, prop, args) {
       return new NotImplementedException();
     },
@@ -3778,7 +4910,7 @@ var LocalPdfManager = (function LocalPdfManagerClosure() {
   function LocalPdfManager(data, password) {
     var stream = new Stream(data);
     this.pdfModel = new PDFDocument(this, stream, password);
-    this.loadedStream = new Promise();
+    this.loadedStream = new LegacyPromise();
     this.loadedStream.resolve(stream);
   }
 
@@ -3787,7 +4919,7 @@ var LocalPdfManager = (function LocalPdfManagerClosure() {
 
   LocalPdfManager.prototype.ensure =
       function LocalPdfManager_ensure(obj, prop, args) {
-    var promise = new Promise();
+    var promise = new LegacyPromise();
     try {
       var value = obj[prop];
       var result;
@@ -3806,7 +4938,7 @@ var LocalPdfManager = (function LocalPdfManagerClosure() {
 
   LocalPdfManager.prototype.requestRange =
       function LocalPdfManager_requestRange(begin, end) {
-    var promise = new Promise();
+    var promise = new LegacyPromise();
     promise.resolve();
     return promise;
   };
@@ -3839,8 +4971,10 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
     var params = {
       msgHandler: msgHandler,
       httpHeaders: args.httpHeaders,
+      withCredentials: args.withCredentials,
       chunkedViewerLoading: args.chunkedViewerLoading,
-      disableAutoFetch: args.disableAutoFetch
+      disableAutoFetch: args.disableAutoFetch,
+      initialData: args.initialData
     };
     this.streamManager = new ChunkedStreamManager(args.length, CHUNK_SIZE,
                                                   args.url, params);
@@ -3854,7 +4988,7 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
 
   NetworkPdfManager.prototype.ensure =
       function NetworkPdfManager_ensure(obj, prop, args) {
-    var promise = new Promise();
+    var promise = new LegacyPromise();
     this.ensureHelper(promise, obj, prop, args);
     return promise;
   };
@@ -3885,7 +5019,7 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
 
   NetworkPdfManager.prototype.requestRange =
       function NetworkPdfManager_requestRange(begin, end) {
-    var promise = new Promise();
+    var promise = new LegacyPromise();
     this.streamManager.requestRange(begin, end, function() {
       promise.resolve();
     });
@@ -3914,12 +5048,13 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
 
 var Page = (function PageClosure() {
 
-  function Page(pdfManager, xref, pageIndex, pageDict, ref) {
+  function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache) {
     this.pdfManager = pdfManager;
     this.pageIndex = pageIndex;
     this.pageDict = pageDict;
     this.xref = xref;
     this.ref = ref;
+    this.fontCache = fontCache;
     this.idCounters = {
       obj: 0
     };
@@ -4011,7 +5146,7 @@ var Page = (function PageClosure() {
         // TODO: add async inheritPageProp and remove this.
         this.resourcesPromise = this.pdfManager.ensure(this, 'resources');
       }
-      var promise = new Promise();
+      var promise = new LegacyPromise();
       this.resourcesPromise.then(function resourceSuccess() {
         var objectLoader = new ObjectLoader(this.resources.map,
                                             keys,
@@ -4024,13 +5159,13 @@ var Page = (function PageClosure() {
     },
     getOperatorList: function Page_getOperatorList(handler) {
       var self = this;
-      var promise = new Promise();
+      var promise = new LegacyPromise();
 
       function reject(e) {
         promise.reject(e);
       }
 
-      var pageListPromise = new Promise();
+      var pageListPromise = new LegacyPromise();
 
       var pdfManager = this.pdfManager;
       var contentStreamPromise = pdfManager.ensure(this, 'getContentStream',
@@ -4049,7 +5184,7 @@ var Page = (function PageClosure() {
       var partialEvaluator = new PartialEvaluator(
             pdfManager, this.xref, handler,
             this.pageIndex, 'p' + this.pageIndex + '_',
-            this.idCounters);
+            this.idCounters, this.fontCache);
 
       var dataPromises = Promise.all(
           [contentStreamPromise, resourcesPromise], reject);
@@ -4073,7 +5208,6 @@ var Page = (function PageClosure() {
         var annotations = datas[1];
 
         if (annotations.length === 0) {
-          PartialEvaluator.optimizeQueue(pageOpList);
           pageOpList.flush(true);
           promise.resolve(pageOpList);
           return;
@@ -4082,7 +5216,6 @@ var Page = (function PageClosure() {
         var annotationsReadyPromise = Annotation.appendToOperatorList(
           annotations, pageOpList, pdfManager, partialEvaluator);
         annotationsReadyPromise.then(function () {
-          PartialEvaluator.optimizeQueue(pageOpList);
           pageOpList.flush(true);
           promise.resolve(pageOpList);
         }, reject);
@@ -4098,7 +5231,7 @@ var Page = (function PageClosure() {
 
       var self = this;
 
-      var textContentPromise = new Promise();
+      var textContentPromise = new LegacyPromise();
 
       var pdfManager = this.pdfManager;
       var contentStreamPromise = pdfManager.ensure(this, 'getContentStream',
@@ -4117,7 +5250,7 @@ var Page = (function PageClosure() {
         var partialEvaluator = new PartialEvaluator(
               pdfManager, self.xref, handler,
               self.pageIndex, 'p' + self.pageIndex + '_',
-              self.idCounters);
+              self.idCounters, self.fontCache);
 
         var bidiTexts = partialEvaluator.getTextContent(contentStream,
                                                         self.resources);
@@ -4370,33 +5503,27 @@ var PDFDocument = (function PDFDocumentClosure() {
       return shadow(this, 'documentInfo', docInfo);
     },
     get fingerprint() {
-      var xref = this.xref, fileID;
+      var xref = this.xref, hash, fileID = '';
+
       if (xref.trailer.has('ID')) {
-        fileID = '';
-        var id = xref.trailer.get('ID')[0];
-        id.split('').forEach(function(el) {
-          fileID += Number(el.charCodeAt(0)).toString(16);
-        });
+        hash = stringToBytes(xref.trailer.get('ID')[0]);
       } else {
-        // If we got no fileID, then we generate one,
-        // from the first 100 bytes of PDF
-        var data = this.stream.bytes.subarray(0, 100);
-        var hash = calculateMD5(data, 0, data.length);
-        fileID = '';
-        for (var i = 0, length = hash.length; i < length; i++) {
-          fileID += Number(hash[i]).toString(16);
-        }
+        hash = calculateMD5(this.stream.bytes.subarray(0, 100), 0, 100);
       }
 
-      return shadow(this, 'fingerprint', fileID);
-    },
+      for (var i = 0, n = hash.length; i < n; i++) {
+        fileID += hash[i].toString(16);
+      }
 
-    traversePages: function PDFDocument_traversePages() {
-      this.catalog.traversePages();
+      return shadow(this, 'fingerprint', fileID);
     },
 
     getPage: function PDFDocument_getPage(pageIndex) {
       return this.catalog.getPage(pageIndex);
+    },
+
+    cleanup: function PDFDocument_cleanup() {
+      return this.catalog.cleanup();
     }
   };
 
@@ -4479,7 +5606,7 @@ var Dict = (function DictClosure() {
         if (xref) {
           return xref.fetchIfRefAsync(value);
         }
-        promise = new Promise();
+        promise = new LegacyPromise();
         promise.resolve(value);
         return promise;
       }
@@ -4488,7 +5615,7 @@ var Dict = (function DictClosure() {
         if (xref) {
           return xref.fetchIfRefAsync(value);
         }
-        promise = new Promise();
+        promise = new LegacyPromise();
         promise.resolve(value);
         return promise;
       }
@@ -4496,7 +5623,7 @@ var Dict = (function DictClosure() {
       if (xref) {
         return xref.fetchIfRefAsync(value);
       }
-      promise = new Promise();
+      promise = new LegacyPromise();
       promise.resolve(value);
       return promise;
     },
@@ -4571,7 +5698,7 @@ var RefSet = (function RefSetClosure() {
 
 var RefSetCache = (function RefSetCacheClosure() {
   function RefSetCache() {
-    this.dict = {};
+    this.dict = Object.create(null);
   }
 
   RefSetCache.prototype = {
@@ -4585,6 +5712,16 @@ var RefSetCache = (function RefSetCacheClosure() {
 
     put: function RefSetCache_put(ref, obj) {
       this.dict['R' + ref.num + '.' + ref.gen] = obj;
+    },
+
+    forEach: function RefSetCache_forEach(fn, thisArg) {
+      for (var i in this.dict) {
+        fn.call(thisArg, this.dict[i]);
+      }
+    },
+
+    clear: function RefSetCache_clear() {
+      this.dict = Object.create(null);
     }
   };
 
@@ -4596,17 +5733,11 @@ var Catalog = (function CatalogClosure() {
     this.pdfManager = pdfManager;
     this.xref = xref;
     this.catDict = xref.getCatalogObj();
+    this.fontCache = new RefSetCache();
     assertWellFormed(isDict(this.catDict),
       'catalog object is not a dictionary');
 
-    // Stores state as we traverse the pages catalog so that we can resume
-    // parsing if an exception is thrown
-    this.traversePagesQueue = [{
-      pagesDict: this.toplevelPagesDict,
-      posInKids: 0
-    }];
     this.pagePromises = [];
-    this.currPageIndex = 0;
   }
 
   Catalog.prototype = {
@@ -4789,59 +5920,156 @@ var Catalog = (function CatalogClosure() {
       return shadow(this, 'javaScript', javaScript);
     },
 
+    cleanup: function Catalog_cleanup() {
+      this.fontCache.forEach(function (font) {
+        delete font.sent;
+        delete font.translated;
+      });
+      this.fontCache.clear();
+    },
+
     getPage: function Catalog_getPage(pageIndex) {
-      if (pageIndex < 0 || pageIndex >= this.numPages ||
-          (pageIndex|0) !== pageIndex) {
-        var pagePromise = new Promise();
-        pagePromise.reject(new Error('Invalid page index'));
-        return pagePromise;
-      }
       if (!(pageIndex in this.pagePromises)) {
-        this.pagePromises[pageIndex] = new Promise();
+        this.pagePromises[pageIndex] = this.getPageDict(pageIndex).then(
+          function (a) {
+            var dict = a[0];
+            var ref = a[1];
+            return new Page(this.pdfManager, this.xref, pageIndex, dict, ref,
+                            this.fontCache);
+          }.bind(this)
+        );
       }
       return this.pagePromises[pageIndex];
     },
 
-    // Traverses pages in DFS order so that pages are processed in increasing
-    // order
-    traversePages: function Catalog_traversePages() {
-      var queue = this.traversePagesQueue;
-      while (queue.length) {
-        var queueItem = queue[queue.length - 1];
-        var pagesDict = queueItem.pagesDict;
+    getPageDict: function Catalog_getPageDict(pageIndex) {
+      var promise = new LegacyPromise();
+      var nodesToVisit = [this.catDict.getRaw('Pages')];
+      var currentPageIndex = 0;
+      var xref = this.xref;
 
-        var kids = pagesDict.get('Kids');
-        assert(isArray(kids), 'page dictionary kids object is not an array');
-        if (queueItem.posInKids >= kids.length) {
-          queue.pop();
-          continue;
-        }
-        var kidRef = kids[queueItem.posInKids];
-        assert(isRef(kidRef), 'page dictionary kid is not a reference');
+      function next() {
+        while (nodesToVisit.length) {
+          var currentNode = nodesToVisit.pop();
 
-        var kid = this.xref.fetch(kidRef);
-        if (isDict(kid, 'Page') || (isDict(kid) && !kid.has('Kids'))) {
-          var pageIndex = this.currPageIndex++;
-          var page = new Page(this.pdfManager, this.xref, pageIndex, kid,
-                              kidRef);
-          if (!(pageIndex in this.pagePromises)) {
-            this.pagePromises[pageIndex] = new Promise();
+          if (isRef(currentNode)) {
+            xref.fetchAsync(currentNode).then(function (obj) {
+              if ((isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids')))) {
+                if (pageIndex === currentPageIndex) {
+                  promise.resolve([obj, currentNode]);
+                } else {
+                  currentPageIndex++;
+                  next();
+                }
+                return;
+              }
+              nodesToVisit.push(obj);
+              next();
+            }.bind(this), promise.reject.bind(promise));
+            return;
           }
-          this.pagePromises[pageIndex].resolve(page);
 
-        } else { // must be a child page dictionary
+          // must be a child page dictionary
           assert(
-            isDict(kid),
+            isDict(currentNode),
             'page dictionary kid reference points to wrong type of object'
           );
+          var count = currentNode.get('Count');
+          // Skip nodes where the page can't be.
+          if (currentPageIndex + count <= pageIndex) {
+            currentPageIndex += count;
+            continue;
+          }
 
-          queue.push({
-            pagesDict: kid,
-            posInKids: 0
-          });
+          var kids = currentNode.get('Kids');
+          assert(isArray(kids), 'page dictionary kids object is not an array');
+          if (count === kids.length) {
+            // Nodes that don't have the page have been skipped and this is the
+            // bottom of the tree which means the page requested must be a
+            // descendant of this pages node. Ideally we would just resolve the
+            // promise with the page ref here, but there is the case where more
+            // pages nodes could link to single a page (see issue 3666 pdf). To
+            // handle this push it back on the queue so if it is a pages node it
+            // will be descended into.
+            nodesToVisit = [kids[pageIndex - currentPageIndex]];
+            currentPageIndex = pageIndex;
+            continue;
+          } else {
+            for (var last = kids.length - 1; last >= 0; last--) {
+              nodesToVisit.push(kids[last]);
+            }
+          }
         }
-        ++queueItem.posInKids;
+        promise.reject('Page index ' + pageIndex + ' not found.');
+      }
+      next();
+      return promise;
+    },
+
+    getPageIndex: function Catalog_getPageIndex(ref) {
+      // The page tree nodes have the count of all the leaves below them. To get
+      // how many pages are before we just have to walk up the tree and keep
+      // adding the count of siblings to the left of the node.
+      var xref = this.xref;
+      function pagesBeforeRef(kidRef) {
+        var total = 0;
+        var parentRef;
+        return xref.fetchAsync(kidRef).then(function (node) {
+          if (!node) {
+            return null;
+          }
+          parentRef = node.getRaw('Parent');
+          return node.getAsync('Parent');
+        }).then(function (parent) {
+          if (!parent) {
+            return null;
+          }
+          return parent.getAsync('Kids');
+        }).then(function (kids) {
+          if (!kids) {
+            return null;
+          }
+          var kidPromises = [];
+          var found = false;
+          for (var i = 0; i < kids.length; i++) {
+            var kid = kids[i];
+            assert(isRef(kid), 'kids must be an ref');
+            if (kid.num == kidRef.num) {
+              found = true;
+              break;
+            }
+            kidPromises.push(xref.fetchAsync(kid).then(function (kid) {
+              if (kid.has('Count')) {
+                var count = kid.get('Count');
+                total += count;
+              } else { // page leaf node
+                total++;
+              }
+            }));
+          }
+          if (!found) {
+            error('kid ref not found in parents kids');
+          }
+          return Promise.all(kidPromises).then(function () {
+            return [total, parentRef];
+          });
+        });
+      }
+
+      var total = 0;
+      function next(ref) {
+        return pagesBeforeRef(ref).then(function (args) {
+          if (!args) {
+            return total;
+          }
+          var count = args[0];
+          var parentRef = args[1];
+          total += count;
+          return next(parentRef);
+        });
       }
+
+      return next(ref);
     }
   };
 
@@ -5258,6 +6486,8 @@ var XRef = (function XRefClosure() {
 
             if (!dict)
               error('Failed to read XRef stream');
+          } else {
+            error('Invalid XRef stream header');
           }
 
           // Recursively get previous dictionary, if any
@@ -5278,7 +6508,7 @@ var XRef = (function XRefClosure() {
         if (e instanceof MissingDataException) {
           throw e;
         }
-        log('(while reading XRef): ' + e);
+        info('(while reading XRef): ' + e);
       }
 
       if (recoveryMode)
@@ -5399,14 +6629,14 @@ var XRef = (function XRefClosure() {
     },
     fetchIfRefAsync: function XRef_fetchIfRefAsync(obj) {
       if (!isRef(obj)) {
-        var promise = new Promise();
+        var promise = new LegacyPromise();
         promise.resolve(obj);
         return promise;
       }
       return this.fetchAsync(obj);
     },
     fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) {
-      var promise = new Promise();
+      var promise = new LegacyPromise();
       var tryFetch = function (promise) {
         try {
           promise.resolve(this.fetch(ref, suppressEncryption));
@@ -5533,7 +6763,7 @@ var ObjectLoader = (function() {
 
     load: function ObjectLoader_load() {
       var keys = this.keys;
-      this.promise = new Promise();
+      this.promise = new LegacyPromise();
       // Don't walk the graph if all the data is already loaded.
       if (!(this.xref.stream instanceof ChunkedStream) ||
           this.xref.stream.getMissingChunks().length === 0) {
@@ -12218,1196 +13448,446 @@ var CIDToUnicodeMaps = {
     {f: 2, c: 31026}, {f: 5, c: 31029}, 31037, 31039, {f: 4, c: 31042}, 31047,
     {f: 9, c: 31050}, {f: 2, c: 31060}, {f: 2, c: 31064}, 31073,
     {f: 2, c: 31075}, 31078, {f: 4, c: 31081}, 31086, {f: 7, c: 31088}, 31097,
-    {f: 5, c: 31099}, {f: 2, c: 31106}, {f: 4, c: 31110}, {f: 2, c: 31115},
-    {f: 10, c: 31120}, {f: 11, c: 31131}, {f: 2, c: 31144}, {f: 3, c: 31147},
-    31151, 31154, {f: 4, c: 31156}, [12145, 31160], 31164, 31167, 31170,
-    {f: 2, c: 31172}, {f: 2, c: 31175}, 31178, 31180, {f: 3, c: 31182},
-    {f: 2, c: 31187}, {f: 2, c: 31190}, {f: 6, c: 31193}, {f: 3, c: 31200},
-    31205, 31208, 31210, 31212, 31214, {f: 7, c: 31217}, {f: 2, c: 31225},
-    31228, {f: 2, c: 31230}, 31233, {f: 2, c: 31236}, {f: 4, c: 31239}, 31244,
-    {f: 5, c: 31247}, {f: 2, c: 31253}, {f: 2, c: 31256}, {f: 3, c: 31259},
-    31263, {f: 2, c: 31265}, {f: 10, c: 31268}, {f: 2, c: 31279}, 31282,
-    {f: 3, c: 31284}, 31288, 31290, 31294, {f: 5, c: 31297}, {f: 5, c: 31303},
-    {f: 2, c: 31311}, {f: 5, c: 31314}, {f: 9, c: 31320}, {f: 6, c: 31331},
-    31338, {f: 4, c: 31340}, {f: 3, c: 31345}, 31349, {f: 4, c: 31355}, 31362,
-    31365, 31367, {f: 4, c: 31369}, {f: 3, c: 31374}, {f: 2, c: 31379},
-    {f: 3, c: 31385}, 31390, {f: 4, c: 31393}, 31399, 31403, {f: 4, c: 31407},
-    {f: 2, c: 31412}, {f: 3, c: 31415}, {f: 4, c: 31419}, {f: 4, c: 31424},
-    31430, 31433, {f: 10, c: 31436}, {f: 2, c: 31447}, {f: 4, c: 31450},
-    {f: 2, c: 31457}, 31460, {f: 3, c: 31463}, {f: 2, c: 31467}, 31470,
-    {f: 6, c: 31472}, {f: 2, c: 31479}, {f: 2, c: 31483}, 31486,
-    {f: 3, c: 31488}, 31493, 31495, 31497, {f: 3, c: 31500}, 31504,
-    {f: 2, c: 31506}, {f: 3, c: 31510}, 31514, {f: 2, c: 31516}, 31519,
-    {f: 3, c: 31521}, 31527, 31529, 31533, {f: 2, c: 31535}, 31538,
-    {f: 4, c: 31540}, 31545, 31547, 31549, {f: 6, c: 31551}, 31560, 31562,
-    {f: 2, c: 31565}, 31571, 31573, 31575, 31577, 31580, {f: 2, c: 31582},
-    31585, {f: 4, c: 31587}, {f: 6, c: 31592}, {f: 2, c: 31599},
-    {f: 2, c: 31603}, 31606, 31608, 31610, {f: 2, c: 31612}, 31615,
-    {f: 4, c: 31617}, {f: 5, c: 31622}, 31628, {f: 2, c: 31630},
-    {f: 3, c: 31633}, 31638, {f: 4, c: 31640}, {f: 3, c: 31646},
-    {f: 3, c: 31651}, {f: 3, c: 31662}, {f: 2, c: 31666}, {f: 3, c: 31669},
-    {f: 7, c: 31673}, {f: 2, c: 31682}, 31685, 31688, 31690, {f: 4, c: 31693},
-    31698, {f: 5, c: 31700}, {f: 2, c: 31707}, {f: 3, c: 31710},
-    {f: 2, c: 31714}, {f: 2, c: 31719}, {f: 3, c: 31723}, {f: 2, c: 31727},
-    31730, {f: 3, c: 31732}, {f: 4, c: 31736}, 31741, 31743, {f: 6, c: 31745},
-    {f: 3, c: 31752}, 31758, {f: 6, c: 31760}, {f: 7, c: 31767}, 31776, 31778,
-    {f: 2, c: 31780}, {f: 2, c: 31784}, {f: 12, c: 31788}, {f: 4, c: 31801},
-    31810, {f: 8, c: 31812}, {f: 14, c: 31822}, {f: 2, c: 31837},
-    {f: 3, c: 31841}, {f: 4, c: 31845}, 31851, 31853, {f: 3, c: 31855},
-    {f: 6, c: 31861}, {f: 11, c: 31870}, {f: 7, c: 31882}, {f: 2, c: 31891},
-    31894, {f: 3, c: 31897}, {f: 2, c: 31904}, 31907, {f: 4, c: 31910},
-    {f: 3, c: 31915}, {f: 2, c: 31919}, {f: 5, c: 31924}, {f: 2, c: 31930},
-    {f: 2, c: 31935}, {f: 3, c: 31938}, 31942, 31945, 31947, {f: 7, c: 31950},
-    31960, {f: 2, c: 31962}, {f: 6, c: 31969}, {f: 6, c: 31977}, 31985, 31987,
-    31989, 31991, 31994, {f: 2, c: 31996}, 31999, 32001, 32003, 32012,
-    {f: 2, c: 32014}, {f: 2, c: 32017}, 32022, 32024, {f: 3, c: 32029},
-    {f: 4, c: 32035}, {f: 3, c: 32040}, {f: 3, c: 32044}, {f: 5, c: 32052},
-    32059, {f: 2, c: 32061}, 32065, 32067, 32069, {f: 7, c: 32071}, 32079,
-    {f: 12, c: 32081}, {f: 2, c: 32095}, {f: 3, c: 32099}, 32103,
-    {f: 5, c: 32105}, {f: 2, c: 32111}, {f: 2, c: 32116}, 32120,
-    {f: 7, c: 32122}, 32130, {f: 2, c: 32132}, 32135, {f: 5, c: 32138},
-    {f: 3, c: 32144}, {f: 8, c: 32148}, 32157, {f: 3, c: 32159},
-    {f: 2, c: 32164}, {f: 4, c: 32167}, 32175, {f: 3, c: 32181}, 32188,
-    {f: 4, c: 32192}, {f: 2, c: 32197}, {f: 2, c: 32200}, {f: 5, c: 32204},
-    32211, {f: 2, c: 32213}, {f: 3, c: 32218}, 32223, 32226, {f: 2, c: 32228},
-    32231, {f: 2, c: 32234}, {f: 2, c: 32237}, 32240, 32243, 32245,
-    {f: 2, c: 32247}, 32250, {f: 12, c: 32252}, {f: 4, c: 32268},
-    {f: 9, c: 32274}, 32284, {f: 3, c: 32288}, {f: 3, c: 32292},
-    {f: 3, c: 32296}, 32300, {f: 2, c: 32303}, 32307, 32312, 32314, 32316,
-    {f: 2, c: 32319}, {f: 3, c: 32322}, {f: 10, c: 32328}, 32339,
-    {f: 4, c: 32342}, {f: 3, c: 32347}, {f: 3, c: 32351}, {f: 6, c: 32355},
-    32364, {f: 2, c: 32369}, {f: 5, c: 32372}, {f: 2, c: 32378},
-    {f: 3, c: 32383}, {f: 5, c: 32387}, 32393, 32395, 32398, {f: 3, c: 32400},
-    32405, 32407, {f: 2, c: 32409}, {f: 2, c: 32413}, 32430, 32436,
-    {f: 2, c: 32443}, 32470, 32484, 32492, 32505, 32522, 32528, 32542, 32567,
-    32569, {f: 7, c: 32571}, 32579, {f: 6, c: 32582}, 32589, 32591,
-    {f: 2, c: 32594}, 32598, 32601, {f: 4, c: 32603}, 32608, {f: 5, c: 32611},
-    {f: 3, c: 32619}, 32623, 32627, {f: 2, c: 32629}, 32632, {f: 4, c: 32634},
-    {f: 2, c: 32639}, {f: 3, c: 32642}, 32647, 32649, 32651, 32653,
-    {f: 5, c: 32655}, {f: 5, c: 32661}, {f: 2, c: 32667}, 32672,
-    {f: 2, c: 32674}, 32678, 32680, {f: 5, c: 32682}, 32689, {f: 5, c: 32691},
-    {f: 2, c: 32698}, 32702, 32704, {f: 3, c: 32706}, {f: 4, c: 32710}, 32715,
-    32717, {f: 3, c: 32719}, 32723, {f: 2, c: 32726}, {f: 6, c: 32729},
-    {f: 3, c: 32738}, {f: 2, c: 32743}, {f: 4, c: 32746}, 32751, 32754,
-    {f: 5, c: 32756}, 32762, {f: 3, c: 32765}, 32770, {f: 4, c: 32775},
-    {f: 2, c: 32782}, 32785, 32787, {f: 2, c: 32794}, {f: 3, c: 32797}, 32801,
-    {f: 2, c: 32803}, 32811, 32813, {f: 2, c: 32815}, 32818, 32820,
-    {f: 2, c: 32825}, 32828, 32830, {f: 2, c: 32832}, {f: 2, c: 32836},
-    {f: 3, c: 32839}, {f: 4, c: 32846}, 32851, 32853, 32855, 32857,
-    {f: 3, c: 32859}, {f: 10, c: 32863}, {f: 4, c: 32875}, 32884, 32888,
-    {f: 3, c: 32890}, {f: 2, c: 32897}, 32904, 32906, {f: 6, c: 32909},
-    {f: 2, c: 32916}, 32919, 32921, 32926, 32931, {f: 3, c: 32934}, 32940,
-    32944, 32947, {f: 2, c: 32949}, {f: 2, c: 32952}, 32955, 32965,
-    {f: 5, c: 32967}, {f: 7, c: 32975}, 32984, {f: 2, c: 32991},
-    {f: 2, c: 32994}, 32998, 33006, 33013, 33015, 33017, 33019,
-    {f: 4, c: 33022}, {f: 2, c: 33027}, {f: 2, c: 33031}, {f: 2, c: 33035},
-    33045, 33047, 33049, {f: 2, c: 33052}, {f: 13, c: 33055}, {f: 2, c: 33069},
-    33072, {f: 3, c: 33075}, 33079, {f: 4, c: 33082}, {f: 7, c: 33087}, 33095,
-    33097, 33101, 33103, 33106, {f: 2, c: 33111}, {f: 5, c: 33115},
-    {f: 3, c: 33122}, 33128, 33130, 33132, 33135, {f: 2, c: 33138},
-    {f: 3, c: 33141}, 33153, {f: 5, c: 33155}, 33161, {f: 4, c: 33163}, 33168,
-    {f: 6, c: 33170}, 33177, {f: 2, c: 33182}, {f: 2, c: 33185},
-    {f: 2, c: 33188}, 33191, {f: 8, c: 33195}, {f: 6, c: 33204}, 33212,
-    {f: 2, c: 33220}, {f: 2, c: 33223}, 33227, 33230, {f: 8, c: 33232}, 33241,
-    {f: 4, c: 33243}, {f: 2, c: 33249}, {f: 3, c: 33252}, 33257, 33259,
-    {f: 5, c: 33262}, {f: 5, c: 33269}, 33277, 33279, 33283, 33291,
-    {f: 2, c: 33294}, 33297, 33299, {f: 6, c: 33301}, 33309, 33312,
-    {f: 4, c: 33316}, 33321, 33326, 33330, 33338, {f: 2, c: 33340},
-    {f: 5, c: 33343}, {f: 2, c: 33349}, 33352, 33354, {f: 3, c: 33356},
-    {f: 8, c: 33360}, {f: 4, c: 33371}, {f: 4, c: 33376}, 33381, 33383,
-    {f: 2, c: 33385}, {f: 2, c: 33388}, {f: 2, c: 33397}, [12171, 33400],
-    {f: 2, c: 33403}, {f: 2, c: 33408}, 33411, {f: 3, c: 33413}, 33417, 33420,
-    33424, {f: 4, c: 33427}, {f: 2, c: 33434}, 33438, 33440, {f: 2, c: 33442},
-    33447, 33458, {f: 2, c: 33461}, 33466, 33468, {f: 2, c: 33471},
-    {f: 2, c: 33474}, {f: 2, c: 33477}, 33481, 33488, 33494, {f: 2, c: 33497},
-    33501, 33506, {f: 3, c: 33512}, {f: 3, c: 33516}, 33520, {f: 2, c: 33522},
-    {f: 2, c: 33525}, 33528, 33530, {f: 5, c: 33532}, {f: 2, c: 33546}, 33549,
-    33552, {f: 2, c: 33554}, 33558, {f: 2, c: 33560}, {f: 10, c: 33565},
-    {f: 2, c: 33577}, 33582, 33584, 33586, 33591, 33595, {f: 3, c: 33597},
-    {f: 2, c: 33601}, {f: 2, c: 33604}, 33608, {f: 5, c: 33610}, 33619,
-    {f: 5, c: 33621}, 33629, 33634, {f: 7, c: 33648}, {f: 2, c: 33657},
-    {f: 7, c: 33662}, {f: 2, c: 33671}, {f: 3, c: 33675}, {f: 3, c: 33679},
-    {f: 2, c: 33684}, 33687, {f: 2, c: 33689}, 33693, 33695, 33697,
-    {f: 4, c: 33699}, {f: 4, c: 33708}, 33717, 33723, {f: 2, c: 33726},
-    {f: 3, c: 33730}, 33734, {f: 2, c: 33736}, 33739, {f: 2, c: 33741},
-    {f: 4, c: 33744}, 33749, 33751, {f: 3, c: 33753}, 33758, {f: 3, c: 33762},
-    {f: 3, c: 33766}, {f: 4, c: 33771}, {f: 5, c: 33779}, {f: 3, c: 33786},
-    {f: 3, c: 33790}, 33794, 33797, {f: 2, c: 33800}, 33808, {f: 6, c: 33810},
-    {f: 3, c: 33817}, {f: 6, c: 33822}, {f: 3, c: 33833}, {f: 4, c: 33837},
-    {f: 3, c: 33842}, {f: 2, c: 33846}, {f: 3, c: 33849}, {f: 8, c: 33854},
-    {f: 2, c: 33863}, {f: 7, c: 33866}, {f: 4, c: 33875}, 33880,
-    {f: 4, c: 33885}, 33890, 33893, {f: 2, c: 33895}, 33898, 33902, 33904,
-    33906, 33908, 33913, {f: 7, c: 33915}, {f: 4, c: 33923}, 33930, 33933,
-    {f: 4, c: 33935}, {f: 2, c: 33941}, 33944, {f: 2, c: 33946},
-    {f: 4, c: 33949}, {f: 13, c: 33954}, {f: 2, c: 33968}, 33971,
-    {f: 3, c: 33973}, 33979, 33982, {f: 2, c: 33986}, {f: 4, c: 33989}, 33996,
-    {f: 2, c: 33998}, 34002, {f: 2, c: 34004}, {f: 6, c: 34007}, 34014,
-    {f: 2, c: 34017}, 34020, {f: 5, c: 34023}, 34029, {f: 11, c: 34033}, 34046,
-    {f: 12, c: 34048}, {f: 4, c: 34061}, 34066, {f: 2, c: 34069},
-    {f: 2, c: 34072}, {f: 3, c: 34075}, 34080, 34082, {f: 2, c: 34084},
-    {f: 4, c: 34087}, {f: 9, c: 34094}, {f: 3, c: 34110}, 34114,
-    {f: 2, c: 34116}, 34119, {f: 3, c: 34123}, {f: 3, c: 34127}, 34132, 34135,
-    {f: 4, c: 34138}, {f: 3, c: 34143}, 34147, {f: 3, c: 34149},
-    {f: 2, c: 34155}, {f: 4, c: 34158}, 34163, {f: 2, c: 34165}, 34168,
-    {f: 2, c: 34172}, {f: 5, c: 34175}, 34182, 34185, 34187, {f: 2, c: 34189},
-    34192, {f: 2, c: 34194}, {f: 6, c: 34197}, {f: 2, c: 34205},
-    {f: 4, c: 34208}, 34213, 34215, {f: 3, c: 34219}, {f: 6, c: 34225}, 34232,
-    {f: 6, c: 34235}, {f: 7, c: 34242}, {f: 3, c: 34250}, {f: 2, c: 34257},
-    34260, {f: 6, c: 34262}, {f: 6, c: 34270}, {f: 3, c: 34278},
-    {f: 9, c: 34283}, 34293, {f: 2, c: 34295}, {f: 3, c: 34300},
-    {f: 4, c: 34304}, {f: 3, c: 34312}, {f: 5, c: 34316}, {f: 4, c: 34322},
-    {f: 3, c: 34327}, {f: 3, c: 34331}, {f: 3, c: 34335}, {f: 4, c: 34339},
-    34344, {f: 3, c: 34346}, {f: 10, c: 34350}, 34361, 34363, {f: 2, c: 34365},
-    {f: 13, c: 34368}, {f: 2, c: 34386}, {f: 4, c: 34390}, 34395, 34397,
-    {f: 2, c: 34400}, {f: 4, c: 34403}, {f: 3, c: 34408}, 34413,
-    {f: 2, c: 34415}, {f: 7, c: 34418}, {f: 7, c: 34435}, {f: 5, c: 34446},
-    34452, {f: 6, c: 34454}, {f: 5, c: 34462}, {f: 2, c: 34469}, 34475,
-    {f: 2, c: 34477}, {f: 2, c: 34482}, {f: 3, c: 34487}, {f: 5, c: 34491},
-    {f: 3, c: 34497}, 34501, 34504, {f: 2, c: 34508}, {f: 2, c: 34514},
-    {f: 3, c: 34517}, 34522, {f: 2, c: 34524}, {f: 4, c: 34528},
-    {f: 4, c: 34533}, {f: 3, c: 34538}, 34543, {f: 3, c: 34549},
-    {f: 3, c: 34555}, 34559, 34561, {f: 2, c: 34564}, {f: 2, c: 34571},
-    {f: 4, c: 34574}, 34580, 34582, 34585, 34587, 34589, {f: 2, c: 34591},
-    34596, {f: 3, c: 34598}, {f: 4, c: 34602}, {f: 2, c: 34607},
-    {f: 2, c: 34610}, {f: 2, c: 34613}, {f: 3, c: 34616}, {f: 2, c: 34620},
-    {f: 7, c: 34624}, {f: 2, c: 34634}, 34637, {f: 4, c: 34639}, 34644, 34646,
-    34648, {f: 6, c: 34650}, {f: 2, c: 34657}, {f: 7, c: 34663}, 34671,
-    {f: 3, c: 34673}, 34677, 34679, {f: 2, c: 34681}, {f: 3, c: 34687},
-    {f: 2, c: 34694}, {f: 2, c: 34697}, 34700, {f: 5, c: 34702},
-    {f: 3, c: 34708}, {f: 6, c: 34712}, {f: 2, c: 34720}, {f: 5, c: 34723},
-    {f: 2, c: 34729}, 34734, {f: 3, c: 34736}, 34740, {f: 4, c: 34742}, 34748,
-    {f: 2, c: 34750}, {f: 3, c: 34753}, 34757, 34759, 34761, {f: 2, c: 34764},
-    {f: 2, c: 34767}, {f: 7, c: 34772}, {f: 4, c: 34780}, {f: 2, c: 34785},
-    34788, {f: 4, c: 34790}, 34795, 34797, {f: 2, c: 34800}, {f: 3, c: 34803},
-    {f: 2, c: 34807}, 34810, {f: 2, c: 34812}, {f: 4, c: 34815}, 34820,
-    {f: 3, c: 34823}, {f: 5, c: 34827}, 34834, 34836, {f: 4, c: 34839},
-    {f: 3, c: 34844}, 34848, {f: 13, c: 34852}, {f: 3, c: 34867},
-    {f: 2, c: 34871}, 34874, {f: 3, c: 34877}, {f: 3, c: 34881},
-    {f: 3, c: 34887}, 34891, {f: 5, c: 34894}, {f: 2, c: 34901}, 34904, 34906,
-    34908, {f: 3, c: 34910}, {f: 2, c: 34918}, 34922, 34925, 34927, 34929,
-    {f: 4, c: 34931}, 34936, {f: 3, c: 34938}, 34944, 34947, {f: 2, c: 34950},
-    {f: 2, c: 34953}, 34956, {f: 4, c: 34958}, {f: 3, c: 34963},
-    {f: 5, c: 34967}, {f: 5, c: 34973}, 34979, {f: 6, c: 34981}, 34988,
-    {f: 3, c: 34990}, {f: 5, c: 34994}, {f: 4, c: 35000}, {f: 4, c: 35005},
-    {f: 2, c: 35011}, {f: 2, c: 35015}, {f: 3, c: 35019}, {f: 2, c: 35024},
-    35027, {f: 2, c: 35030}, {f: 2, c: 35034}, 35038, {f: 2, c: 35040},
-    {f: 2, c: 35046}, {f: 7, c: 35049}, 35058, {f: 3, c: 35061},
-    {f: 2, c: 35066}, {f: 3, c: 35071}, {f: 4, c: 35075}, {f: 2, c: 35080},
-    {f: 5, c: 35083}, 35089, {f: 5, c: 35092}, {f: 5, c: 35100},
-    {f: 3, c: 35106}, {f: 4, c: 35110}, {f: 4, c: 35116}, 35121, 35125, 35127,
-    {f: 2, c: 35129}, {f: 5, c: 35132}, {f: 2, c: 35138}, {f: 2, c: 35141},
-    {f: 14, c: 35144}, {f: 6, c: 35159}, {f: 3, c: 35169}, 35173,
-    {f: 3, c: 35175}, 35179, {f: 2, c: 35181}, {f: 2, c: 35184},
-    {f: 8, c: 35187}, {f: 2, c: 35196}, [12177, 35198], 35200, 35202,
-    {f: 2, c: 35204}, {f: 4, c: 35207}, {f: 3, c: 35212}, {f: 3, c: 35216},
-    {f: 2, c: 35220}, 35223, {f: 8, c: 35225}, {f: 4, c: 35234},
-    {f: 3, c: 35239}, 35243, {f: 2, c: 35245}, {f: 2, c: 35248},
-    {f: 4, c: 35251}, {f: 2, c: 35256}, {f: 2, c: 35259}, 35262, 35267, 35277,
-    {f: 3, c: 35283}, {f: 3, c: 35287}, 35291, 35293, {f: 4, c: 35295}, 35300,
-    {f: 4, c: 35303}, {f: 3, c: 35308}, {f: 3, c: 35312}, 35317, 35319,
-    {f: 7, c: 35321}, {f: 3, c: 35332}, 35337, 35339, 35341, 35343,
-    {f: 2, c: 35345}, 35348, 35351, {f: 2, c: 35353}, 35356, 35358,
-    {f: 3, c: 35360}, 35364, {f: 4, c: 35366}, {f: 2, c: 35371},
-    {f: 3, c: 35374}, {f: 2, c: 35378}, 35381, {f: 3, c: 35383},
-    {f: 3, c: 35387}, {f: 2, c: 35391}, {f: 4, c: 35394}, 35399,
-    {f: 5, c: 35401}, 35407, 35409, 35411, {f: 2, c: 35414}, {f: 2, c: 35417},
-    {f: 2, c: 35420}, {f: 2, c: 35423}, {f: 2, c: 35428}, {f: 2, c: 35431},
-    35434, 35439, 35444, {f: 3, c: 35446}, {f: 2, c: 35450}, {f: 2, c: 35453},
-    {f: 4, c: 35456}, 35464, {f: 2, c: 35467}, {f: 3, c: 35470}, 35476,
-    {f: 2, c: 35478}, 35481, {f: 3, c: 35483}, 35487, 35490, 35495,
-    {f: 3, c: 35497}, {f: 3, c: 35501}, 35505, {f: 3, c: 35507},
-    {f: 2, c: 35511}, {f: 2, c: 35514}, {f: 2, c: 35517}, {f: 2, c: 35520},
-    35523, {f: 2, c: 35525}, 35528, 35530, 35532, 35534, 35536,
-    {f: 3, c: 35539}, {f: 3, c: 35544}, 35549, {f: 3, c: 35551}, 35555, 35557,
-    {f: 3, c: 35560}, 35564, {f: 2, c: 35567}, 35570, {f: 2, c: 35572}, 35577,
-    35579, 35581, 35583, 35587, 35590, {f: 2, c: 35592}, {f: 3, c: 35595},
-    35599, {f: 3, c: 35601}, 35605, 35608, 35612, {f: 3, c: 35614},
-    {f: 4, c: 35618}, 35623, {f: 2, c: 35625}, {f: 5, c: 35630},
-    {f: 5, c: 35636}, {f: 4, c: 35642}, {f: 10, c: 35647}, {f: 4, c: 35658},
-    {f: 6, c: 35664}, 35671, 35675, {f: 9, c: 35677}, {f: 4, c: 35687},
-    {f: 2, c: 35693}, {f: 3, c: 35697}, {f: 2, c: 35701}, {f: 5, c: 35704},
-    {f: 2, c: 35710}, {f: 9, c: 35713}, {f: 3, c: 35723}, {f: 3, c: 35727},
-    35732, {f: 5, c: 35735}, 35741, 35743, 35756, 35761, 35771, 35783, 35792,
-    35818, 35849, 35870, {f: 9, c: 35896}, {f: 4, c: 35906}, {f: 2, c: 35914},
-    {f: 3, c: 35917}, {f: 4, c: 35921}, {f: 4, c: 35926}, {f: 6, c: 35931},
-    {f: 7, c: 35939}, {f: 7, c: 35948}, {f: 4, c: 35956}, {f: 7, c: 35963},
-    {f: 2, c: 35971}, {f: 3, c: 35974}, 35979, {f: 7, c: 35981},
-    {f: 3, c: 35989}, {f: 4, c: 35993}, 35999, {f: 4, c: 36003},
-    {f: 2, c: 36013}, 36017, 36021, 36025, 36030, 36038, 36041,
-    {f: 6, c: 36043}, 36052, {f: 4, c: 36054}, 36059, 36061, 36063, 36069,
-    {f: 2, c: 36072}, {f: 6, c: 36078}, {f: 5, c: 36085}, {f: 5, c: 36095},
-    {f: 2, c: 36102}, 36105, 36108, 36110, {f: 5, c: 36113}, {f: 4, c: 36119},
-    36128, {f: 2, c: 36177}, 36183, 36191, 36197, {f: 3, c: 36200}, 36204,
-    {f: 2, c: 36206}, {f: 2, c: 36209}, {f: 9, c: 36216}, {f: 2, c: 36226},
-    {f: 4, c: 36230}, {f: 5, c: 36236}, {f: 2, c: 36242}, {f: 3, c: 36246},
-    {f: 5, c: 36250}, {f: 3, c: 36256}, {f: 4, c: 36260}, {f: 8, c: 36265},
-    {f: 2, c: 36278}, 36281, 36283, 36285, {f: 3, c: 36288}, 36293,
-    {f: 4, c: 36295}, 36301, 36304, {f: 4, c: 36306}, {f: 2, c: 36312}, 36316,
-    {f: 3, c: 36320}, {f: 3, c: 36325}, 36329, {f: 2, c: 36333},
-    {f: 3, c: 36336}, 36340, 36342, 36348, {f: 7, c: 36350}, {f: 3, c: 36358},
-    36363, {f: 2, c: 36365}, {f: 3, c: 36369}, {f: 8, c: 36373},
-    {f: 2, c: 36384}, {f: 5, c: 36388}, 36395, 36397, 36400, {f: 2, c: 36402},
-    {f: 3, c: 36406}, {f: 2, c: 36411}, {f: 2, c: 36414}, 36419,
-    {f: 2, c: 36421}, {f: 4, c: 36429}, {f: 2, c: 36435}, {f: 3, c: 36438},
-    {f: 9, c: 36442}, {f: 2, c: 36452}, {f: 2, c: 36455}, {f: 2, c: 36458},
-    36462, 36465, 36467, 36469, {f: 3, c: 36471}, 36475, {f: 2, c: 36477},
-    36480, {f: 3, c: 36482}, 36486, 36488, 36492, 36494, {f: 5, c: 36501},
-    36507, 36509, {f: 2, c: 36511}, {f: 3, c: 36514}, {f: 3, c: 36519},
-    {f: 2, c: 36525}, {f: 2, c: 36528}, {f: 7, c: 36531}, {f: 5, c: 36539},
-    {f: 9, c: 36545}, {f: 3, c: 36559}, 36563, {f: 6, c: 36565},
-    {f: 3, c: 36572}, {f: 4, c: 36576}, {f: 6, c: 36581}, {f: 6, c: 36588},
-    {f: 5, c: 36595}, 36605, {f: 4, c: 36607}, 36612, 36614, 36616,
-    {f: 7, c: 36619}, 36627, {f: 5, c: 36630}, {f: 5, c: 36640},
-    {f: 2, c: 36647}, {f: 4, c: 36651}, {f: 3, c: 36656}, {f: 4, c: 36660},
-    {f: 2, c: 36665}, {f: 2, c: 36668}, {f: 2, c: 36672}, 36675,
-    {f: 2, c: 36679}, {f: 3, c: 36682}, {f: 5, c: 36687}, {f: 10, c: 36693},
-    36704, 36707, 36709, 36714, 36736, 36748, 36754, 36765, {f: 3, c: 36768},
-    {f: 2, c: 36772}, 36775, 36778, 36780, {f: 2, c: 36787}, [12193, 36789],
-    {f: 2, c: 36791}, {f: 3, c: 36794}, {f: 2, c: 36799}, 36803, 36806,
-    {f: 5, c: 36809}, 36815, 36818, {f: 2, c: 36822}, 36826, {f: 2, c: 36832},
-    36835, 36839, 36844, 36847, {f: 2, c: 36849}, {f: 2, c: 36853},
-    {f: 3, c: 36858}, {f: 2, c: 36862}, {f: 2, c: 36871}, 36876, 36878, 36883,
-    36888, 36892, {f: 2, c: 36900}, {f: 6, c: 36903}, {f: 2, c: 36912},
-    {f: 2, c: 36915}, 36919, {f: 2, c: 36921}, 36925, {f: 2, c: 36927}, 36931,
-    {f: 2, c: 36933}, {f: 3, c: 36936}, 36940, 36950, {f: 2, c: 36953}, 36957,
-    36959, 36961, 36964, {f: 2, c: 36966}, {f: 3, c: 36970}, {f: 3, c: 36975},
-    36979, 36982, 36985, 36987, 36990, {f: 2, c: 36997}, 37001,
-    {f: 3, c: 37004}, 37010, 37012, 37014, 37016, 37018, 37020,
-    {f: 3, c: 37022}, {f: 2, c: 37028}, {f: 3, c: 37031}, 37035, 37037, 37042,
-    37047, {f: 2, c: 37052}, {f: 2, c: 37055}, {f: 2, c: 37058}, 37062,
-    {f: 2, c: 37064}, {f: 3, c: 37067}, 37074, {f: 3, c: 37076},
-    {f: 3, c: 37080}, 37086, 37088, {f: 3, c: 37091}, {f: 2, c: 37097}, 37100,
-    37102, {f: 4, c: 37104}, {f: 2, c: 37110}, {f: 4, c: 37113},
-    {f: 3, c: 37119}, 37123, 37125, {f: 2, c: 37127}, {f: 8, c: 37130}, 37139,
-    37141, {f: 2, c: 37143}, {f: 4, c: 37146}, {f: 3, c: 37151},
-    {f: 3, c: 37156}, {f: 5, c: 37160}, 37166, 37171, 37173, {f: 2, c: 37175},
-    {f: 8, c: 37179}, {f: 2, c: 37188}, 37191, 37201, {f: 4, c: 37203},
-    {f: 2, c: 37208}, {f: 2, c: 37211}, {f: 2, c: 37215}, {f: 3, c: 37222},
-    37227, 37229, 37235, {f: 3, c: 37242}, {f: 5, c: 37248}, 37254, 37256,
-    37258, {f: 2, c: 37262}, {f: 3, c: 37267}, {f: 3, c: 37271},
-    {f: 5, c: 37277}, {f: 6, c: 37284}, {f: 4, c: 37296}, {f: 4, c: 37302},
-    {f: 5, c: 37307}, 37314, 37316, [12196, 37318], 37320, 37328, 37334,
-    {f: 2, c: 37338}, {f: 5, c: 37342}, {f: 2, c: 37349}, 37352,
-    {f: 11, c: 37354}, 37366, 37368, {f: 5, c: 37371}, {f: 2, c: 37378},
-    {f: 3, c: 37381}, {f: 3, c: 37386}, 37391, {f: 2, c: 37394},
-    {f: 8, c: 37398}, {f: 4, c: 37407}, 37412, {f: 6, c: 37416}, 37423,
-    {f: 2, c: 37425}, {f: 2, c: 37429}, {f: 2, c: 37435}, {f: 4, c: 37441},
-    {f: 2, c: 37446}, {f: 3, c: 37450}, {f: 3, c: 37454}, {f: 3, c: 37458},
-    37462, {f: 2, c: 37464}, {f: 2, c: 37468}, {f: 3, c: 37471},
-    {f: 3, c: 37475}, {f: 5, c: 37479}, {f: 6, c: 37486}, {f: 3, c: 37493},
-    37497, {f: 3, c: 37500}, {f: 2, c: 37505}, 37508, {f: 8, c: 37510},
-    {f: 2, c: 37519}, 37522, {f: 2, c: 37524}, 37527, 37529, 37531,
-    {f: 3, c: 37533}, {f: 2, c: 37537}, 37540, 37543, 37549, {f: 2, c: 37551},
-    {f: 5, c: 37554}, 37560, 37562, {f: 4, c: 37565}, 37570, 37572, 37574,
-    {f: 3, c: 37577}, {f: 2, c: 37581}, {f: 2, c: 37584}, {f: 10, c: 37587},
-    37598, {f: 3, c: 37600}, 37607, 37609, {f: 2, c: 37611}, {f: 4, c: 37618},
-    37623, {f: 3, c: 37625}, {f: 4, c: 37629}, {f: 4, c: 37634},
-    {f: 7, c: 37641}, 37649, {f: 2, c: 37651}, {f: 2, c: 37654},
-    {f: 3, c: 37660}, 37665, {f: 3, c: 37667}, 37671, {f: 2, c: 37673},
-    {f: 2, c: 37676}, {f: 2, c: 37680}, {f: 2, c: 37684}, 37687,
-    {f: 5, c: 37689}, 37695, 37698, {f: 2, c: 37700}, {f: 3, c: 37704}, 37708,
-    {f: 6, c: 37710}, {f: 3, c: 37717}, {f: 2, c: 37721}, {f: 8, c: 37724},
-    {f: 3, c: 37734}, 37739, {f: 3, c: 37741}, {f: 4, c: 37745},
-    {f: 3, c: 37751}, {f: 3, c: 37755}, {f: 3, c: 37759}, 37763,
-    {f: 2, c: 37765}, {f: 2, c: 37768}, {f: 4, c: 37771}, {f: 6, c: 37776},
-    37783, {f: 9, c: 37785}, {f: 2, c: 37796}, 37800, 37803, 37805, 37807,
-    {f: 2, c: 37809}, 37812, {f: 2, c: 37814}, {f: 6, c: 37817},
-    {f: 3, c: 37824}, {f: 3, c: 37828}, 37833, 37835, {f: 3, c: 37838},
-    {f: 4, c: 37842}, {f: 3, c: 37849}, 37856, 37859, {f: 3, c: 37861},
-    {f: 12, c: 37865}, 37878, 37880, {f: 9, c: 37882}, {f: 7, c: 37892},
-    {f: 4, c: 37900}, 37905, {f: 3, c: 37909}, {f: 3, c: 37914},
-    {f: 2, c: 37918}, {f: 5, c: 37921}, {f: 5, c: 37929}, {f: 3, c: 37935},
-    37940, {f: 2, c: 37942}, 37945, {f: 3, c: 37947}, {f: 4, c: 37952},
-    {f: 5, c: 37957}, 37963, {f: 5, c: 37965}, 37971, {f: 11, c: 37973},
-    {f: 2, c: 37985}, 37988, {f: 5, c: 37990}, 37996, {f: 2, c: 37998}, 38001,
-    {f: 4, c: 38003}, 38008, {f: 2, c: 38010}, {f: 5, c: 38016}, 38033, 38038,
-    38040, 38087, 38095, {f: 2, c: 38099}, 38106, 38118, 38139, 38172, 38176,
-    38183, 38195, 38205, 38211, 38216, 38219, 38229, 38234, 38240, 38254,
-    {f: 2, c: 38260}, {f: 7, c: 38264}, 38273, {f: 2, c: 38276},
-    {f: 2, c: 38279}, 38282, 38285, 38288, 38290, {f: 3, c: 38293},
-    {f: 8, c: 38297}, 38306, {f: 2, c: 38310}, 38314, {f: 4, c: 38318},
-    {f: 3, c: 38323}, {f: 2, c: 38327}, 38330, {f: 3, c: 38336},
-    {f: 2, c: 38340}, 38343, 38345, {f: 3, c: 38349}, {f: 3, c: 38353},
-    {f: 5, c: 38359}, 38365, {f: 2, c: 38367}, {f: 2, c: 38371},
-    {f: 2, c: 38374}, 38380, 38399, 38407, 38419, 38424, 38427, 38430, 38432,
-    {f: 7, c: 38435}, {f: 3, c: 38443}, {f: 2, c: 38447}, {f: 4, c: 38455},
-    38462, 38465, 38467, 38474, {f: 2, c: 38478}, {f: 3, c: 38481},
-    {f: 2, c: 38486}, {f: 2, c: 38489}, 38492, 38494, 38496, {f: 2, c: 38501},
-    38507, {f: 3, c: 38509}, 38513, {f: 4, c: 38521}, {f: 7, c: 38526}, 38535,
-    38537, 38540, {f: 3, c: 38545}, 38550, 38554, {f: 10, c: 38557}, 38569,
-    {f: 5, c: 38571}, 38578, 38581, 38583, 38586, 38591, {f: 2, c: 38594},
-    38600, {f: 2, c: 38602}, {f: 2, c: 38608}, {f: 2, c: 38611},
-    {f: 2, c: 38615}, 38618, {f: 3, c: 38621}, 38625, {f: 4, c: 38628},
-    {f: 4, c: 38635}, {f: 2, c: 38640}, {f: 2, c: 38644}, 38648, 38650,
-    {f: 2, c: 38652}, 38655, {f: 2, c: 38658}, 38661, {f: 3, c: 38666},
-    {f: 3, c: 38672}, {f: 2, c: 38676}, {f: 5, c: 38679}, 38685,
-    {f: 8, c: 38687}, {f: 2, c: 38696}, {f: 2, c: 38699}, {f: 2, c: 38702},
-    38705, {f: 5, c: 38707}, {f: 3, c: 38714}, {f: 3, c: 38719}, 38723,
-    {f: 3, c: 38725}, {f: 8, c: 38729}, [12205, 38737], {f: 2, c: 38740},
-    {f: 2, c: 38743}, {f: 2, c: 38748}, 38751, {f: 2, c: 38755},
-    {f: 2, c: 38758}, {f: 9, c: 38762}, 38773, {f: 5, c: 38775},
-    {f: 8, c: 38781}, {f: 5, c: 38790}, 38796, 38798, 38800, 38803,
-    {f: 3, c: 38805}, {f: 7, c: 38809}, {f: 2, c: 38817}, {f: 2, c: 38820},
-    {f: 4, c: 38823}, 38828, 38830, {f: 2, c: 38832}, 38835, {f: 8, c: 38837},
-    {f: 5, c: 38846}, {f: 2, c: 38852}, {f: 2, c: 38855}, 38858,
-    {f: 6, c: 38861}, {f: 5, c: 38868}, {f: 2, c: 38874}, 38877,
-    {f: 7, c: 38879}, 38888, {f: 5, c: 38894}, 38900, {f: 8, c: 38903}, 38912,
-    38916, 38921, 38923, 38925, {f: 3, c: 38932}, {f: 3, c: 38937},
-    {f: 4, c: 38941}, {f: 2, c: 38946}, 38949, {f: 6, c: 38951},
-    {f: 2, c: 38958}, {f: 6, c: 38961}, {f: 2, c: 38969}, 38972,
-    {f: 8, c: 38974}, {f: 5, c: 38983}, {f: 4, c: 38991}, {f: 3, c: 38997},
-    39002, {f: 2, c: 39004}, {f: 3, c: 39007}, {f: 2, c: 39011}, 39014,
-    {f: 3, c: 39016}, {f: 2, c: 39021}, 39026, 39051, 39054, 39058, 39061,
-    39065, 39075, {f: 5, c: 39081}, 39088, 39090, {f: 2, c: 39092},
-    {f: 5, c: 39095}, {f: 7, c: 39101}, 39109, 39111, {f: 5, c: 39113},
-    {f: 2, c: 39119}, 39124, {f: 2, c: 39126}, {f: 2, c: 39132}, 39137,
-    {f: 4, c: 39139}, 39148, 39150, {f: 2, c: 39152}, 39155, {f: 7, c: 39157},
-    {f: 4, c: 39167}, 39172, {f: 3, c: 39174}, 39179, {f: 2, c: 39182},
-    {f: 4, c: 39188}, {f: 2, c: 39193}, {f: 2, c: 39196}, {f: 2, c: 39199},
-    {f: 6, c: 39202}, {f: 5, c: 39209}, {f: 4, c: 39215}, {f: 3, c: 39220},
-    {f: 4, c: 39224}, 39229, {f: 3, c: 39232}, 39236, {f: 2, c: 39238},
-    {f: 4, c: 39245}, 39251, 39254, {f: 4, c: 39256}, 39261, {f: 3, c: 39263},
-    39268, 39270, 39283, {f: 2, c: 39288}, 39291, 39294, {f: 2, c: 39298},
-    39305, 39308, 39310, {f: 11, c: 39322}, {f: 2, c: 39334}, {f: 3, c: 39337},
-    {f: 2, c: 39343}, 39346, {f: 12, c: 39349}, {f: 14, c: 39362}, 39379,
-    {f: 2, c: 39382}, 39386, 39388, 39390, 39392, {f: 10, c: 39395},
-    {f: 3, c: 39406}, {f: 13, c: 39410}, 39424, {f: 3, c: 39426},
-    {f: 7, c: 39430}, {f: 6, c: 39440}, {f: 2, c: 39447}, {f: 17, c: 39450},
-    39468, 39471, {f: 5, c: 39473}, {f: 5, c: 39481}, 39487, {f: 4, c: 39494},
-    {f: 2, c: 39499}, 39502, {f: 5, c: 39504}, 39510, {f: 2, c: 39512},
-    {f: 3, c: 39516}, {f: 2, c: 39520}, 39523, {f: 4, c: 39526}, 39531, 39538,
-    39555, 39561, {f: 2, c: 39565}, {f: 2, c: 39572}, 39577, 39590,
-    {f: 6, c: 39593}, {f: 4, c: 39602}, 39609, 39611, {f: 3, c: 39613},
-    {f: 2, c: 39619}, {f: 5, c: 39622}, {f: 2, c: 39629}, 39632, 39639,
-    {f: 6, c: 39641}, 39648, {f: 4, c: 39650}, {f: 4, c: 39655}, 39660,
-    {f: 9, c: 39664}, 39674, {f: 7, c: 39676}, {f: 2, c: 39684}, 39687,
-    {f: 4, c: 39689}, 39694, {f: 3, c: 39696}, {f: 6, c: 39700},
-    {f: 4, c: 39707}, {f: 2, c: 39712}, 39716, 39718, 39720, {f: 4, c: 39722},
-    39728, {f: 8, c: 39731}, {f: 4, c: 39741}, 39750, {f: 3, c: 39754}, 39760,
-    {f: 2, c: 39762}, {f: 3, c: 39765}, 39769, {f: 20, c: 39771},
-    {f: 4, c: 39792}, {f: 2, c: 39797}, {f: 9, c: 39800}, 39810,
-    {f: 10, c: 39812}, 39823, {f: 7, c: 39827}, {f: 2, c: 39835},
-    {f: 11, c: 39839}, 39852, {f: 17, c: 39855}, {f: 5, c: 39874}, 39880,
-    {f: 9, c: 39883}, 39893, {f: 4, c: 39895}, 39900, {f: 3, c: 39902}, 39907,
-    {f: 2, c: 39909}, 39913, {f: 4, c: 39916}, {f: 3, c: 39921},
-    {f: 8, c: 39925}, 39934, {f: 8, c: 39936}, {f: 3, c: 39946},
-    {f: 2, c: 39950}, 39953, {f: 12, c: 39956}, {f: 2, c: 39969}, 39972,
-    {f: 2, c: 39974}, {f: 3, c: 39978}, {f: 3, c: 39982}, 39988, 39990, 39992,
-    39994, {f: 2, c: 39996}, {f: 6, c: 39999}, {f: 2, c: 40006},
-    {f: 8, c: 40010}, 40019, 40021, {f: 4, c: 40025}, 40030, {f: 7, c: 40032},
-    {f: 5, c: 40040}, {f: 10, c: 40046}, 40057, 40059, {f: 2, c: 40061}, 40064,
-    {f: 2, c: 40067}, {f: 2, c: 40073}, 40076, 40079, 40083, {f: 4, c: 40086},
-    40093, 40106, 40108, 40111, 40121, {f: 5, c: 40126}, {f: 2, c: 40136},
-    {f: 2, c: 40145}, {f: 2, c: 40154}, {f: 2, c: 40160}, {f: 2, c: 40163},
-    {f: 3, c: 40166}, {f: 2, c: 40170}, {f: 6, c: 40173}, 40181,
-    {f: 15, c: 40183}, 40200, {f: 11, c: 40202}, {f: 5, c: 40214}, 40220,
-    40222, {f: 3, c: 40224}, {f: 2, c: 40228}, 40231, {f: 6, c: 40233},
-    {f: 10, c: 40241}, {f: 3, c: 40252}, {f: 2, c: 40256}, {f: 14, c: 40259},
-    {f: 8, c: 40276}, {f: 2, c: 40286}, {f: 8, c: 40290}, 40299,
-    {f: 2, c: 40301}, {f: 2, c: 40304}, {f: 20, c: 40307}, 40328,
-    {f: 9, c: 40330}, {f: 4, c: 40340}, 40345, {f: 10, c: 40347},
-    {f: 3, c: 40358}, {f: 5, c: 40362}, {f: 4, c: 40368}, {f: 6, c: 40373},
-    {f: 3, c: 40381}, 40385, 40387, {f: 14, c: 40389}, {f: 3, c: 40404}, 40408,
-    {f: 10, c: 40411}, {f: 8, c: 40423}, {f: 2, c: 40432}, {f: 4, c: 40436},
-    {f: 17, c: 40443}, {f: 8, c: 40461}, {f: 4, c: 40470}, 40476, 40484, 40487,
-    40494, 40496, 40500, {f: 2, c: 40507}, 40512, 40525, 40528,
-    {f: 3, c: 40530}, 40534, 40537, 40541, {f: 4, c: 40543}, 40549,
-    {f: 2, c: 40558}, 40562, 40564, {f: 3, c: 40566}, 40571, {f: 2, c: 40576},
-    {f: 4, c: 40579}, {f: 2, c: 40585}, {f: 6, c: 40588}, {f: 3, c: 40596},
-    {f: 5, c: 40600}, 40606, {f: 5, c: 40608}, {f: 2, c: 40615},
-    {f: 5, c: 40618}, {f: 4, c: 40624}, {f: 2, c: 40630}, {f: 2, c: 40633},
-    40636, {f: 4, c: 40639}, [12232, 40643], {f: 4, c: 40645},
-    {f: 2, c: 40650}, 40656, {f: 2, c: 40658}, {f: 3, c: 40661},
-    {f: 2, c: 40665}, 40673, {f: 2, c: 40675}, 40678, {f: 4, c: 40683},
-    {f: 2, c: 40688}, 40691, {f: 2, c: 40693}, 40696, 40698, {f: 9, c: 40704},
-    40714, 40716, 40719, {f: 2, c: 40721}, 40724, 40726, 40728,
-    {f: 6, c: 40730}, 40737, {f: 9, c: 40739}, {f: 2, c: 40749},
-    {f: 7, c: 40752}, 40760, 40762, 40764, {f: 5, c: 40767}, {f: 5, c: 40773},
-    {f: 3, c: 40780}, 40787, {f: 4, c: 40789}, {f: 2, c: 40794},
-    {f: 2, c: 40797}, 40802, {f: 2, c: 40804}, {f: 3, c: 40807}, 40811,
-    {f: 5, c: 40813}, {f: 4, c: 40819}, {f: 7, c: 40824}, {f: 2, c: 40833},
-    {f: 2, c: 40846}, {f: 3, c: 40849}, {f: 3, c: 40854}, {f: 2, c: 40861},
-    {f: 5, c: 40865}, 63788, {f: 3, c: 64013}, 64017, {f: 2, c: 64019}, 64024,
-    {f: 3, c: 64031}, {f: 2, c: 64035}, {f: 3, c: 64039}, 11905,
-    [59414, 131207], [59415, 131209], [59416, 131276], 11908, 13427, 13383,
-    11912, 11915, 59422, 13726, 13850, 13838, 11916, 11927, 14702, 14616,
-    59430, 14799, 14815, 14963, 14800, {f: 2, c: 59435}, 15182, 15470, 15584,
-    11943, [59441, 136663], 59442, 11946, 16470, 16735, 11950, 17207, 11955,
-    {f: 2, c: 11958}, [59451, 141711], 17329, 17324, 11963, 17373, 17622,
-    18017, 17996, [59459, 132361], 18211, 18217, 18300, 18317, 11978, 18759,
-    18810, 18813, {f: 2, c: 18818}, {f: 2, c: 18821}, 18847, 18843, 18871,
-    18870, [59476, 133533], [59477, 147966], 19619, {f: 3, c: 19615}, 19575,
-    19618, {f: 7, c: 19731}, 19886, 59492, {s: 226}, 8364, 165, 0, 0, 12351,
-    {s: 17}, 12436, {s: 14}, 12535, 12537, 12536, 12538, 0, {f: 3, c: 12339},
-    {f: 3, c: 12344}, {f: 3, c: 12586}, {f: 24, c: 12704}, 11904,
-    {f: 2, c: 11906}, {f: 3, c: 11909}, {f: 2, c: 11913}, {f: 10, c: 11917},
-    {f: 2, c: 11928}, {f: 12, c: 11931}, {f: 2, c: 11944}, {f: 3, c: 11947},
-    {f: 4, c: 11951}, {f: 2, c: 11956}, {f: 3, c: 11960}, {f: 14, c: 11964},
-    {f: 41, c: 11979}, {f: 71, c: 13312}, {f: 43, c: 13384},
-    {f: 298, c: 13428}, {f: 111, c: 13727}, {f: 11, c: 13839},
-    {f: 765, c: 13851}, {f: 85, c: 14617}, {f: 96, c: 14703},
-    {f: 14, c: 14801}, {f: 147, c: 14816}, {f: 218, c: 14964},
-    {f: 287, c: 15183}, {f: 113, c: 15471}, {f: 885, c: 15585},
-    {f: 264, c: 16471}, {f: 471, c: 16736}, {f: 116, c: 17208},
-    {f: 4, c: 17325}, {f: 43, c: 17330}, {f: 248, c: 17374},
-    {f: 373, c: 17623}, {f: 20, c: 17997}, {f: 193, c: 18018},
-    {f: 5, c: 18212}, {f: 82, c: 18218}, {f: 16, c: 18301}, {f: 441, c: 18318},
-    {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 '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':
-          return 'DeviceGrayCS';
-        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;
-})();
-
-//
-// 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;
-  }
+    {f: 5, c: 31099}, {f: 2, c: 31106}, {f: 4, c: 31110}, {f: 2, c: 31115},
+    {f: 10, c: 31120}, {f: 11, c: 31131}, {f: 2, c: 31144}, {f: 3, c: 31147},
+    31151, 31154, {f: 4, c: 31156}, [12145, 31160], 31164, 31167, 31170,
+    {f: 2, c: 31172}, {f: 2, c: 31175}, 31178, 31180, {f: 3, c: 31182},
+    {f: 2, c: 31187}, {f: 2, c: 31190}, {f: 6, c: 31193}, {f: 3, c: 31200},
+    31205, 31208, 31210, 31212, 31214, {f: 7, c: 31217}, {f: 2, c: 31225},
+    31228, {f: 2, c: 31230}, 31233, {f: 2, c: 31236}, {f: 4, c: 31239}, 31244,
+    {f: 5, c: 31247}, {f: 2, c: 31253}, {f: 2, c: 31256}, {f: 3, c: 31259},
+    31263, {f: 2, c: 31265}, {f: 10, c: 31268}, {f: 2, c: 31279}, 31282,
+    {f: 3, c: 31284}, 31288, 31290, 31294, {f: 5, c: 31297}, {f: 5, c: 31303},
+    {f: 2, c: 31311}, {f: 5, c: 31314}, {f: 9, c: 31320}, {f: 6, c: 31331},
+    31338, {f: 4, c: 31340}, {f: 3, c: 31345}, 31349, {f: 4, c: 31355}, 31362,
+    31365, 31367, {f: 4, c: 31369}, {f: 3, c: 31374}, {f: 2, c: 31379},
+    {f: 3, c: 31385}, 31390, {f: 4, c: 31393}, 31399, 31403, {f: 4, c: 31407},
+    {f: 2, c: 31412}, {f: 3, c: 31415}, {f: 4, c: 31419}, {f: 4, c: 31424},
+    31430, 31433, {f: 10, c: 31436}, {f: 2, c: 31447}, {f: 4, c: 31450},
+    {f: 2, c: 31457}, 31460, {f: 3, c: 31463}, {f: 2, c: 31467}, 31470,
+    {f: 6, c: 31472}, {f: 2, c: 31479}, {f: 2, c: 31483}, 31486,
+    {f: 3, c: 31488}, 31493, 31495, 31497, {f: 3, c: 31500}, 31504,
+    {f: 2, c: 31506}, {f: 3, c: 31510}, 31514, {f: 2, c: 31516}, 31519,
+    {f: 3, c: 31521}, 31527, 31529, 31533, {f: 2, c: 31535}, 31538,
+    {f: 4, c: 31540}, 31545, 31547, 31549, {f: 6, c: 31551}, 31560, 31562,
+    {f: 2, c: 31565}, 31571, 31573, 31575, 31577, 31580, {f: 2, c: 31582},
+    31585, {f: 4, c: 31587}, {f: 6, c: 31592}, {f: 2, c: 31599},
+    {f: 2, c: 31603}, 31606, 31608, 31610, {f: 2, c: 31612}, 31615,
+    {f: 4, c: 31617}, {f: 5, c: 31622}, 31628, {f: 2, c: 31630},
+    {f: 3, c: 31633}, 31638, {f: 4, c: 31640}, {f: 3, c: 31646},
+    {f: 3, c: 31651}, {f: 3, c: 31662}, {f: 2, c: 31666}, {f: 3, c: 31669},
+    {f: 7, c: 31673}, {f: 2, c: 31682}, 31685, 31688, 31690, {f: 4, c: 31693},
+    31698, {f: 5, c: 31700}, {f: 2, c: 31707}, {f: 3, c: 31710},
+    {f: 2, c: 31714}, {f: 2, c: 31719}, {f: 3, c: 31723}, {f: 2, c: 31727},
+    31730, {f: 3, c: 31732}, {f: 4, c: 31736}, 31741, 31743, {f: 6, c: 31745},
+    {f: 3, c: 31752}, 31758, {f: 6, c: 31760}, {f: 7, c: 31767}, 31776, 31778,
+    {f: 2, c: 31780}, {f: 2, c: 31784}, {f: 12, c: 31788}, {f: 4, c: 31801},
+    31810, {f: 8, c: 31812}, {f: 14, c: 31822}, {f: 2, c: 31837},
+    {f: 3, c: 31841}, {f: 4, c: 31845}, 31851, 31853, {f: 3, c: 31855},
+    {f: 6, c: 31861}, {f: 11, c: 31870}, {f: 7, c: 31882}, {f: 2, c: 31891},
+    31894, {f: 3, c: 31897}, {f: 2, c: 31904}, 31907, {f: 4, c: 31910},
+    {f: 3, c: 31915}, {f: 2, c: 31919}, {f: 5, c: 31924}, {f: 2, c: 31930},
+    {f: 2, c: 31935}, {f: 3, c: 31938}, 31942, 31945, 31947, {f: 7, c: 31950},
+    31960, {f: 2, c: 31962}, {f: 6, c: 31969}, {f: 6, c: 31977}, 31985, 31987,
+    31989, 31991, 31994, {f: 2, c: 31996}, 31999, 32001, 32003, 32012,
+    {f: 2, c: 32014}, {f: 2, c: 32017}, 32022, 32024, {f: 3, c: 32029},
+    {f: 4, c: 32035}, {f: 3, c: 32040}, {f: 3, c: 32044}, {f: 5, c: 32052},
+    32059, {f: 2, c: 32061}, 32065, 32067, 32069, {f: 7, c: 32071}, 32079,
+    {f: 12, c: 32081}, {f: 2, c: 32095}, {f: 3, c: 32099}, 32103,
+    {f: 5, c: 32105}, {f: 2, c: 32111}, {f: 2, c: 32116}, 32120,
+    {f: 7, c: 32122}, 32130, {f: 2, c: 32132}, 32135, {f: 5, c: 32138},
+    {f: 3, c: 32144}, {f: 8, c: 32148}, 32157, {f: 3, c: 32159},
+    {f: 2, c: 32164}, {f: 4, c: 32167}, 32175, {f: 3, c: 32181}, 32188,
+    {f: 4, c: 32192}, {f: 2, c: 32197}, {f: 2, c: 32200}, {f: 5, c: 32204},
+    32211, {f: 2, c: 32213}, {f: 3, c: 32218}, 32223, 32226, {f: 2, c: 32228},
+    32231, {f: 2, c: 32234}, {f: 2, c: 32237}, 32240, 32243, 32245,
+    {f: 2, c: 32247}, 32250, {f: 12, c: 32252}, {f: 4, c: 32268},
+    {f: 9, c: 32274}, 32284, {f: 3, c: 32288}, {f: 3, c: 32292},
+    {f: 3, c: 32296}, 32300, {f: 2, c: 32303}, 32307, 32312, 32314, 32316,
+    {f: 2, c: 32319}, {f: 3, c: 32322}, {f: 10, c: 32328}, 32339,
+    {f: 4, c: 32342}, {f: 3, c: 32347}, {f: 3, c: 32351}, {f: 6, c: 32355},
+    32364, {f: 2, c: 32369}, {f: 5, c: 32372}, {f: 2, c: 32378},
+    {f: 3, c: 32383}, {f: 5, c: 32387}, 32393, 32395, 32398, {f: 3, c: 32400},
+    32405, 32407, {f: 2, c: 32409}, {f: 2, c: 32413}, 32430, 32436,
+    {f: 2, c: 32443}, 32470, 32484, 32492, 32505, 32522, 32528, 32542, 32567,
+    32569, {f: 7, c: 32571}, 32579, {f: 6, c: 32582}, 32589, 32591,
+    {f: 2, c: 32594}, 32598, 32601, {f: 4, c: 32603}, 32608, {f: 5, c: 32611},
+    {f: 3, c: 32619}, 32623, 32627, {f: 2, c: 32629}, 32632, {f: 4, c: 32634},
+    {f: 2, c: 32639}, {f: 3, c: 32642}, 32647, 32649, 32651, 32653,
+    {f: 5, c: 32655}, {f: 5, c: 32661}, {f: 2, c: 32667}, 32672,
+    {f: 2, c: 32674}, 32678, 32680, {f: 5, c: 32682}, 32689, {f: 5, c: 32691},
+    {f: 2, c: 32698}, 32702, 32704, {f: 3, c: 32706}, {f: 4, c: 32710}, 32715,
+    32717, {f: 3, c: 32719}, 32723, {f: 2, c: 32726}, {f: 6, c: 32729},
+    {f: 3, c: 32738}, {f: 2, c: 32743}, {f: 4, c: 32746}, 32751, 32754,
+    {f: 5, c: 32756}, 32762, {f: 3, c: 32765}, 32770, {f: 4, c: 32775},
+    {f: 2, c: 32782}, 32785, 32787, {f: 2, c: 32794}, {f: 3, c: 32797}, 32801,
+    {f: 2, c: 32803}, 32811, 32813, {f: 2, c: 32815}, 32818, 32820,
+    {f: 2, c: 32825}, 32828, 32830, {f: 2, c: 32832}, {f: 2, c: 32836},
+    {f: 3, c: 32839}, {f: 4, c: 32846}, 32851, 32853, 32855, 32857,
+    {f: 3, c: 32859}, {f: 10, c: 32863}, {f: 4, c: 32875}, 32884, 32888,
+    {f: 3, c: 32890}, {f: 2, c: 32897}, 32904, 32906, {f: 6, c: 32909},
+    {f: 2, c: 32916}, 32919, 32921, 32926, 32931, {f: 3, c: 32934}, 32940,
+    32944, 32947, {f: 2, c: 32949}, {f: 2, c: 32952}, 32955, 32965,
+    {f: 5, c: 32967}, {f: 7, c: 32975}, 32984, {f: 2, c: 32991},
+    {f: 2, c: 32994}, 32998, 33006, 33013, 33015, 33017, 33019,
+    {f: 4, c: 33022}, {f: 2, c: 33027}, {f: 2, c: 33031}, {f: 2, c: 33035},
+    33045, 33047, 33049, {f: 2, c: 33052}, {f: 13, c: 33055}, {f: 2, c: 33069},
+    33072, {f: 3, c: 33075}, 33079, {f: 4, c: 33082}, {f: 7, c: 33087}, 33095,
+    33097, 33101, 33103, 33106, {f: 2, c: 33111}, {f: 5, c: 33115},
+    {f: 3, c: 33122}, 33128, 33130, 33132, 33135, {f: 2, c: 33138},
+    {f: 3, c: 33141}, 33153, {f: 5, c: 33155}, 33161, {f: 4, c: 33163}, 33168,
+    {f: 6, c: 33170}, 33177, {f: 2, c: 33182}, {f: 2, c: 33185},
+    {f: 2, c: 33188}, 33191, {f: 8, c: 33195}, {f: 6, c: 33204}, 33212,
+    {f: 2, c: 33220}, {f: 2, c: 33223}, 33227, 33230, {f: 8, c: 33232}, 33241,
+    {f: 4, c: 33243}, {f: 2, c: 33249}, {f: 3, c: 33252}, 33257, 33259,
+    {f: 5, c: 33262}, {f: 5, c: 33269}, 33277, 33279, 33283, 33291,
+    {f: 2, c: 33294}, 33297, 33299, {f: 6, c: 33301}, 33309, 33312,
+    {f: 4, c: 33316}, 33321, 33326, 33330, 33338, {f: 2, c: 33340},
+    {f: 5, c: 33343}, {f: 2, c: 33349}, 33352, 33354, {f: 3, c: 33356},
+    {f: 8, c: 33360}, {f: 4, c: 33371}, {f: 4, c: 33376}, 33381, 33383,
+    {f: 2, c: 33385}, {f: 2, c: 33388}, {f: 2, c: 33397}, [12171, 33400],
+    {f: 2, c: 33403}, {f: 2, c: 33408}, 33411, {f: 3, c: 33413}, 33417, 33420,
+    33424, {f: 4, c: 33427}, {f: 2, c: 33434}, 33438, 33440, {f: 2, c: 33442},
+    33447, 33458, {f: 2, c: 33461}, 33466, 33468, {f: 2, c: 33471},
+    {f: 2, c: 33474}, {f: 2, c: 33477}, 33481, 33488, 33494, {f: 2, c: 33497},
+    33501, 33506, {f: 3, c: 33512}, {f: 3, c: 33516}, 33520, {f: 2, c: 33522},
+    {f: 2, c: 33525}, 33528, 33530, {f: 5, c: 33532}, {f: 2, c: 33546}, 33549,
+    33552, {f: 2, c: 33554}, 33558, {f: 2, c: 33560}, {f: 10, c: 33565},
+    {f: 2, c: 33577}, 33582, 33584, 33586, 33591, 33595, {f: 3, c: 33597},
+    {f: 2, c: 33601}, {f: 2, c: 33604}, 33608, {f: 5, c: 33610}, 33619,
+    {f: 5, c: 33621}, 33629, 33634, {f: 7, c: 33648}, {f: 2, c: 33657},
+    {f: 7, c: 33662}, {f: 2, c: 33671}, {f: 3, c: 33675}, {f: 3, c: 33679},
+    {f: 2, c: 33684}, 33687, {f: 2, c: 33689}, 33693, 33695, 33697,
+    {f: 4, c: 33699}, {f: 4, c: 33708}, 33717, 33723, {f: 2, c: 33726},
+    {f: 3, c: 33730}, 33734, {f: 2, c: 33736}, 33739, {f: 2, c: 33741},
+    {f: 4, c: 33744}, 33749, 33751, {f: 3, c: 33753}, 33758, {f: 3, c: 33762},
+    {f: 3, c: 33766}, {f: 4, c: 33771}, {f: 5, c: 33779}, {f: 3, c: 33786},
+    {f: 3, c: 33790}, 33794, 33797, {f: 2, c: 33800}, 33808, {f: 6, c: 33810},
+    {f: 3, c: 33817}, {f: 6, c: 33822}, {f: 3, c: 33833}, {f: 4, c: 33837},
+    {f: 3, c: 33842}, {f: 2, c: 33846}, {f: 3, c: 33849}, {f: 8, c: 33854},
+    {f: 2, c: 33863}, {f: 7, c: 33866}, {f: 4, c: 33875}, 33880,
+    {f: 4, c: 33885}, 33890, 33893, {f: 2, c: 33895}, 33898, 33902, 33904,
+    33906, 33908, 33913, {f: 7, c: 33915}, {f: 4, c: 33923}, 33930, 33933,
+    {f: 4, c: 33935}, {f: 2, c: 33941}, 33944, {f: 2, c: 33946},
+    {f: 4, c: 33949}, {f: 13, c: 33954}, {f: 2, c: 33968}, 33971,
+    {f: 3, c: 33973}, 33979, 33982, {f: 2, c: 33986}, {f: 4, c: 33989}, 33996,
+    {f: 2, c: 33998}, 34002, {f: 2, c: 34004}, {f: 6, c: 34007}, 34014,
+    {f: 2, c: 34017}, 34020, {f: 5, c: 34023}, 34029, {f: 11, c: 34033}, 34046,
+    {f: 12, c: 34048}, {f: 4, c: 34061}, 34066, {f: 2, c: 34069},
+    {f: 2, c: 34072}, {f: 3, c: 34075}, 34080, 34082, {f: 2, c: 34084},
+    {f: 4, c: 34087}, {f: 9, c: 34094}, {f: 3, c: 34110}, 34114,
+    {f: 2, c: 34116}, 34119, {f: 3, c: 34123}, {f: 3, c: 34127}, 34132, 34135,
+    {f: 4, c: 34138}, {f: 3, c: 34143}, 34147, {f: 3, c: 34149},
+    {f: 2, c: 34155}, {f: 4, c: 34158}, 34163, {f: 2, c: 34165}, 34168,
+    {f: 2, c: 34172}, {f: 5, c: 34175}, 34182, 34185, 34187, {f: 2, c: 34189},
+    34192, {f: 2, c: 34194}, {f: 6, c: 34197}, {f: 2, c: 34205},
+    {f: 4, c: 34208}, 34213, 34215, {f: 3, c: 34219}, {f: 6, c: 34225}, 34232,
+    {f: 6, c: 34235}, {f: 7, c: 34242}, {f: 3, c: 34250}, {f: 2, c: 34257},
+    34260, {f: 6, c: 34262}, {f: 6, c: 34270}, {f: 3, c: 34278},
+    {f: 9, c: 34283}, 34293, {f: 2, c: 34295}, {f: 3, c: 34300},
+    {f: 4, c: 34304}, {f: 3, c: 34312}, {f: 5, c: 34316}, {f: 4, c: 34322},
+    {f: 3, c: 34327}, {f: 3, c: 34331}, {f: 3, c: 34335}, {f: 4, c: 34339},
+    34344, {f: 3, c: 34346}, {f: 10, c: 34350}, 34361, 34363, {f: 2, c: 34365},
+    {f: 13, c: 34368}, {f: 2, c: 34386}, {f: 4, c: 34390}, 34395, 34397,
+    {f: 2, c: 34400}, {f: 4, c: 34403}, {f: 3, c: 34408}, 34413,
+    {f: 2, c: 34415}, {f: 7, c: 34418}, {f: 7, c: 34435}, {f: 5, c: 34446},
+    34452, {f: 6, c: 34454}, {f: 5, c: 34462}, {f: 2, c: 34469}, 34475,
+    {f: 2, c: 34477}, {f: 2, c: 34482}, {f: 3, c: 34487}, {f: 5, c: 34491},
+    {f: 3, c: 34497}, 34501, 34504, {f: 2, c: 34508}, {f: 2, c: 34514},
+    {f: 3, c: 34517}, 34522, {f: 2, c: 34524}, {f: 4, c: 34528},
+    {f: 4, c: 34533}, {f: 3, c: 34538}, 34543, {f: 3, c: 34549},
+    {f: 3, c: 34555}, 34559, 34561, {f: 2, c: 34564}, {f: 2, c: 34571},
+    {f: 4, c: 34574}, 34580, 34582, 34585, 34587, 34589, {f: 2, c: 34591},
+    34596, {f: 3, c: 34598}, {f: 4, c: 34602}, {f: 2, c: 34607},
+    {f: 2, c: 34610}, {f: 2, c: 34613}, {f: 3, c: 34616}, {f: 2, c: 34620},
+    {f: 7, c: 34624}, {f: 2, c: 34634}, 34637, {f: 4, c: 34639}, 34644, 34646,
+    34648, {f: 6, c: 34650}, {f: 2, c: 34657}, {f: 7, c: 34663}, 34671,
+    {f: 3, c: 34673}, 34677, 34679, {f: 2, c: 34681}, {f: 3, c: 34687},
+    {f: 2, c: 34694}, {f: 2, c: 34697}, 34700, {f: 5, c: 34702},
+    {f: 3, c: 34708}, {f: 6, c: 34712}, {f: 2, c: 34720}, {f: 5, c: 34723},
+    {f: 2, c: 34729}, 34734, {f: 3, c: 34736}, 34740, {f: 4, c: 34742}, 34748,
+    {f: 2, c: 34750}, {f: 3, c: 34753}, 34757, 34759, 34761, {f: 2, c: 34764},
+    {f: 2, c: 34767}, {f: 7, c: 34772}, {f: 4, c: 34780}, {f: 2, c: 34785},
+    34788, {f: 4, c: 34790}, 34795, 34797, {f: 2, c: 34800}, {f: 3, c: 34803},
+    {f: 2, c: 34807}, 34810, {f: 2, c: 34812}, {f: 4, c: 34815}, 34820,
+    {f: 3, c: 34823}, {f: 5, c: 34827}, 34834, 34836, {f: 4, c: 34839},
+    {f: 3, c: 34844}, 34848, {f: 13, c: 34852}, {f: 3, c: 34867},
+    {f: 2, c: 34871}, 34874, {f: 3, c: 34877}, {f: 3, c: 34881},
+    {f: 3, c: 34887}, 34891, {f: 5, c: 34894}, {f: 2, c: 34901}, 34904, 34906,
+    34908, {f: 3, c: 34910}, {f: 2, c: 34918}, 34922, 34925, 34927, 34929,
+    {f: 4, c: 34931}, 34936, {f: 3, c: 34938}, 34944, 34947, {f: 2, c: 34950},
+    {f: 2, c: 34953}, 34956, {f: 4, c: 34958}, {f: 3, c: 34963},
+    {f: 5, c: 34967}, {f: 5, c: 34973}, 34979, {f: 6, c: 34981}, 34988,
+    {f: 3, c: 34990}, {f: 5, c: 34994}, {f: 4, c: 35000}, {f: 4, c: 35005},
+    {f: 2, c: 35011}, {f: 2, c: 35015}, {f: 3, c: 35019}, {f: 2, c: 35024},
+    35027, {f: 2, c: 35030}, {f: 2, c: 35034}, 35038, {f: 2, c: 35040},
+    {f: 2, c: 35046}, {f: 7, c: 35049}, 35058, {f: 3, c: 35061},
+    {f: 2, c: 35066}, {f: 3, c: 35071}, {f: 4, c: 35075}, {f: 2, c: 35080},
+    {f: 5, c: 35083}, 35089, {f: 5, c: 35092}, {f: 5, c: 35100},
+    {f: 3, c: 35106}, {f: 4, c: 35110}, {f: 4, c: 35116}, 35121, 35125, 35127,
+    {f: 2, c: 35129}, {f: 5, c: 35132}, {f: 2, c: 35138}, {f: 2, c: 35141},
+    {f: 14, c: 35144}, {f: 6, c: 35159}, {f: 3, c: 35169}, 35173,
+    {f: 3, c: 35175}, 35179, {f: 2, c: 35181}, {f: 2, c: 35184},
+    {f: 8, c: 35187}, {f: 2, c: 35196}, [12177, 35198], 35200, 35202,
+    {f: 2, c: 35204}, {f: 4, c: 35207}, {f: 3, c: 35212}, {f: 3, c: 35216},
+    {f: 2, c: 35220}, 35223, {f: 8, c: 35225}, {f: 4, c: 35234},
+    {f: 3, c: 35239}, 35243, {f: 2, c: 35245}, {f: 2, c: 35248},
+    {f: 4, c: 35251}, {f: 2, c: 35256}, {f: 2, c: 35259}, 35262, 35267, 35277,
+    {f: 3, c: 35283}, {f: 3, c: 35287}, 35291, 35293, {f: 4, c: 35295}, 35300,
+    {f: 4, c: 35303}, {f: 3, c: 35308}, {f: 3, c: 35312}, 35317, 35319,
+    {f: 7, c: 35321}, {f: 3, c: 35332}, 35337, 35339, 35341, 35343,
+    {f: 2, c: 35345}, 35348, 35351, {f: 2, c: 35353}, 35356, 35358,
+    {f: 3, c: 35360}, 35364, {f: 4, c: 35366}, {f: 2, c: 35371},
+    {f: 3, c: 35374}, {f: 2, c: 35378}, 35381, {f: 3, c: 35383},
+    {f: 3, c: 35387}, {f: 2, c: 35391}, {f: 4, c: 35394}, 35399,
+    {f: 5, c: 35401}, 35407, 35409, 35411, {f: 2, c: 35414}, {f: 2, c: 35417},
+    {f: 2, c: 35420}, {f: 2, c: 35423}, {f: 2, c: 35428}, {f: 2, c: 35431},
+    35434, 35439, 35444, {f: 3, c: 35446}, {f: 2, c: 35450}, {f: 2, c: 35453},
+    {f: 4, c: 35456}, 35464, {f: 2, c: 35467}, {f: 3, c: 35470}, 35476,
+    {f: 2, c: 35478}, 35481, {f: 3, c: 35483}, 35487, 35490, 35495,
+    {f: 3, c: 35497}, {f: 3, c: 35501}, 35505, {f: 3, c: 35507},
+    {f: 2, c: 35511}, {f: 2, c: 35514}, {f: 2, c: 35517}, {f: 2, c: 35520},
+    35523, {f: 2, c: 35525}, 35528, 35530, 35532, 35534, 35536,
+    {f: 3, c: 35539}, {f: 3, c: 35544}, 35549, {f: 3, c: 35551}, 35555, 35557,
+    {f: 3, c: 35560}, 35564, {f: 2, c: 35567}, 35570, {f: 2, c: 35572}, 35577,
+    35579, 35581, 35583, 35587, 35590, {f: 2, c: 35592}, {f: 3, c: 35595},
+    35599, {f: 3, c: 35601}, 35605, 35608, 35612, {f: 3, c: 35614},
+    {f: 4, c: 35618}, 35623, {f: 2, c: 35625}, {f: 5, c: 35630},
+    {f: 5, c: 35636}, {f: 4, c: 35642}, {f: 10, c: 35647}, {f: 4, c: 35658},
+    {f: 6, c: 35664}, 35671, 35675, {f: 9, c: 35677}, {f: 4, c: 35687},
+    {f: 2, c: 35693}, {f: 3, c: 35697}, {f: 2, c: 35701}, {f: 5, c: 35704},
+    {f: 2, c: 35710}, {f: 9, c: 35713}, {f: 3, c: 35723}, {f: 3, c: 35727},
+    35732, {f: 5, c: 35735}, 35741, 35743, 35756, 35761, 35771, 35783, 35792,
+    35818, 35849, 35870, {f: 9, c: 35896}, {f: 4, c: 35906}, {f: 2, c: 35914},
+    {f: 3, c: 35917}, {f: 4, c: 35921}, {f: 4, c: 35926}, {f: 6, c: 35931},
+    {f: 7, c: 35939}, {f: 7, c: 35948}, {f: 4, c: 35956}, {f: 7, c: 35963},
+    {f: 2, c: 35971}, {f: 3, c: 35974}, 35979, {f: 7, c: 35981},
+    {f: 3, c: 35989}, {f: 4, c: 35993}, 35999, {f: 4, c: 36003},
+    {f: 2, c: 36013}, 36017, 36021, 36025, 36030, 36038, 36041,
+    {f: 6, c: 36043}, 36052, {f: 4, c: 36054}, 36059, 36061, 36063, 36069,
+    {f: 2, c: 36072}, {f: 6, c: 36078}, {f: 5, c: 36085}, {f: 5, c: 36095},
+    {f: 2, c: 36102}, 36105, 36108, 36110, {f: 5, c: 36113}, {f: 4, c: 36119},
+    36128, {f: 2, c: 36177}, 36183, 36191, 36197, {f: 3, c: 36200}, 36204,
+    {f: 2, c: 36206}, {f: 2, c: 36209}, {f: 9, c: 36216}, {f: 2, c: 36226},
+    {f: 4, c: 36230}, {f: 5, c: 36236}, {f: 2, c: 36242}, {f: 3, c: 36246},
+    {f: 5, c: 36250}, {f: 3, c: 36256}, {f: 4, c: 36260}, {f: 8, c: 36265},
+    {f: 2, c: 36278}, 36281, 36283, 36285, {f: 3, c: 36288}, 36293,
+    {f: 4, c: 36295}, 36301, 36304, {f: 4, c: 36306}, {f: 2, c: 36312}, 36316,
+    {f: 3, c: 36320}, {f: 3, c: 36325}, 36329, {f: 2, c: 36333},
+    {f: 3, c: 36336}, 36340, 36342, 36348, {f: 7, c: 36350}, {f: 3, c: 36358},
+    36363, {f: 2, c: 36365}, {f: 3, c: 36369}, {f: 8, c: 36373},
+    {f: 2, c: 36384}, {f: 5, c: 36388}, 36395, 36397, 36400, {f: 2, c: 36402},
+    {f: 3, c: 36406}, {f: 2, c: 36411}, {f: 2, c: 36414}, 36419,
+    {f: 2, c: 36421}, {f: 4, c: 36429}, {f: 2, c: 36435}, {f: 3, c: 36438},
+    {f: 9, c: 36442}, {f: 2, c: 36452}, {f: 2, c: 36455}, {f: 2, c: 36458},
+    36462, 36465, 36467, 36469, {f: 3, c: 36471}, 36475, {f: 2, c: 36477},
+    36480, {f: 3, c: 36482}, 36486, 36488, 36492, 36494, {f: 5, c: 36501},
+    36507, 36509, {f: 2, c: 36511}, {f: 3, c: 36514}, {f: 3, c: 36519},
+    {f: 2, c: 36525}, {f: 2, c: 36528}, {f: 7, c: 36531}, {f: 5, c: 36539},
+    {f: 9, c: 36545}, {f: 3, c: 36559}, 36563, {f: 6, c: 36565},
+    {f: 3, c: 36572}, {f: 4, c: 36576}, {f: 6, c: 36581}, {f: 6, c: 36588},
+    {f: 5, c: 36595}, 36605, {f: 4, c: 36607}, 36612, 36614, 36616,
+    {f: 7, c: 36619}, 36627, {f: 5, c: 36630}, {f: 5, c: 36640},
+    {f: 2, c: 36647}, {f: 4, c: 36651}, {f: 3, c: 36656}, {f: 4, c: 36660},
+    {f: 2, c: 36665}, {f: 2, c: 36668}, {f: 2, c: 36672}, 36675,
+    {f: 2, c: 36679}, {f: 3, c: 36682}, {f: 5, c: 36687}, {f: 10, c: 36693},
+    36704, 36707, 36709, 36714, 36736, 36748, 36754, 36765, {f: 3, c: 36768},
+    {f: 2, c: 36772}, 36775, 36778, 36780, {f: 2, c: 36787}, [12193, 36789],
+    {f: 2, c: 36791}, {f: 3, c: 36794}, {f: 2, c: 36799}, 36803, 36806,
+    {f: 5, c: 36809}, 36815, 36818, {f: 2, c: 36822}, 36826, {f: 2, c: 36832},
+    36835, 36839, 36844, 36847, {f: 2, c: 36849}, {f: 2, c: 36853},
+    {f: 3, c: 36858}, {f: 2, c: 36862}, {f: 2, c: 36871}, 36876, 36878, 36883,
+    36888, 36892, {f: 2, c: 36900}, {f: 6, c: 36903}, {f: 2, c: 36912},
+    {f: 2, c: 36915}, 36919, {f: 2, c: 36921}, 36925, {f: 2, c: 36927}, 36931,
+    {f: 2, c: 36933}, {f: 3, c: 36936}, 36940, 36950, {f: 2, c: 36953}, 36957,
+    36959, 36961, 36964, {f: 2, c: 36966}, {f: 3, c: 36970}, {f: 3, c: 36975},
+    36979, 36982, 36985, 36987, 36990, {f: 2, c: 36997}, 37001,
+    {f: 3, c: 37004}, 37010, 37012, 37014, 37016, 37018, 37020,
+    {f: 3, c: 37022}, {f: 2, c: 37028}, {f: 3, c: 37031}, 37035, 37037, 37042,
+    37047, {f: 2, c: 37052}, {f: 2, c: 37055}, {f: 2, c: 37058}, 37062,
+    {f: 2, c: 37064}, {f: 3, c: 37067}, 37074, {f: 3, c: 37076},
+    {f: 3, c: 37080}, 37086, 37088, {f: 3, c: 37091}, {f: 2, c: 37097}, 37100,
+    37102, {f: 4, c: 37104}, {f: 2, c: 37110}, {f: 4, c: 37113},
+    {f: 3, c: 37119}, 37123, 37125, {f: 2, c: 37127}, {f: 8, c: 37130}, 37139,
+    37141, {f: 2, c: 37143}, {f: 4, c: 37146}, {f: 3, c: 37151},
+    {f: 3, c: 37156}, {f: 5, c: 37160}, 37166, 37171, 37173, {f: 2, c: 37175},
+    {f: 8, c: 37179}, {f: 2, c: 37188}, 37191, 37201, {f: 4, c: 37203},
+    {f: 2, c: 37208}, {f: 2, c: 37211}, {f: 2, c: 37215}, {f: 3, c: 37222},
+    37227, 37229, 37235, {f: 3, c: 37242}, {f: 5, c: 37248}, 37254, 37256,
+    37258, {f: 2, c: 37262}, {f: 3, c: 37267}, {f: 3, c: 37271},
+    {f: 5, c: 37277}, {f: 6, c: 37284}, {f: 4, c: 37296}, {f: 4, c: 37302},
+    {f: 5, c: 37307}, 37314, 37316, [12196, 37318], 37320, 37328, 37334,
+    {f: 2, c: 37338}, {f: 5, c: 37342}, {f: 2, c: 37349}, 37352,
+    {f: 11, c: 37354}, 37366, 37368, {f: 5, c: 37371}, {f: 2, c: 37378},
+    {f: 3, c: 37381}, {f: 3, c: 37386}, 37391, {f: 2, c: 37394},
+    {f: 8, c: 37398}, {f: 4, c: 37407}, 37412, {f: 6, c: 37416}, 37423,
+    {f: 2, c: 37425}, {f: 2, c: 37429}, {f: 2, c: 37435}, {f: 4, c: 37441},
+    {f: 2, c: 37446}, {f: 3, c: 37450}, {f: 3, c: 37454}, {f: 3, c: 37458},
+    37462, {f: 2, c: 37464}, {f: 2, c: 37468}, {f: 3, c: 37471},
+    {f: 3, c: 37475}, {f: 5, c: 37479}, {f: 6, c: 37486}, {f: 3, c: 37493},
+    37497, {f: 3, c: 37500}, {f: 2, c: 37505}, 37508, {f: 8, c: 37510},
+    {f: 2, c: 37519}, 37522, {f: 2, c: 37524}, 37527, 37529, 37531,
+    {f: 3, c: 37533}, {f: 2, c: 37537}, 37540, 37543, 37549, {f: 2, c: 37551},
+    {f: 5, c: 37554}, 37560, 37562, {f: 4, c: 37565}, 37570, 37572, 37574,
+    {f: 3, c: 37577}, {f: 2, c: 37581}, {f: 2, c: 37584}, {f: 10, c: 37587},
+    37598, {f: 3, c: 37600}, 37607, 37609, {f: 2, c: 37611}, {f: 4, c: 37618},
+    37623, {f: 3, c: 37625}, {f: 4, c: 37629}, {f: 4, c: 37634},
+    {f: 7, c: 37641}, 37649, {f: 2, c: 37651}, {f: 2, c: 37654},
+    {f: 3, c: 37660}, 37665, {f: 3, c: 37667}, 37671, {f: 2, c: 37673},
+    {f: 2, c: 37676}, {f: 2, c: 37680}, {f: 2, c: 37684}, 37687,
+    {f: 5, c: 37689}, 37695, 37698, {f: 2, c: 37700}, {f: 3, c: 37704}, 37708,
+    {f: 6, c: 37710}, {f: 3, c: 37717}, {f: 2, c: 37721}, {f: 8, c: 37724},
+    {f: 3, c: 37734}, 37739, {f: 3, c: 37741}, {f: 4, c: 37745},
+    {f: 3, c: 37751}, {f: 3, c: 37755}, {f: 3, c: 37759}, 37763,
+    {f: 2, c: 37765}, {f: 2, c: 37768}, {f: 4, c: 37771}, {f: 6, c: 37776},
+    37783, {f: 9, c: 37785}, {f: 2, c: 37796}, 37800, 37803, 37805, 37807,
+    {f: 2, c: 37809}, 37812, {f: 2, c: 37814}, {f: 6, c: 37817},
+    {f: 3, c: 37824}, {f: 3, c: 37828}, 37833, 37835, {f: 3, c: 37838},
+    {f: 4, c: 37842}, {f: 3, c: 37849}, 37856, 37859, {f: 3, c: 37861},
+    {f: 12, c: 37865}, 37878, 37880, {f: 9, c: 37882}, {f: 7, c: 37892},
+    {f: 4, c: 37900}, 37905, {f: 3, c: 37909}, {f: 3, c: 37914},
+    {f: 2, c: 37918}, {f: 5, c: 37921}, {f: 5, c: 37929}, {f: 3, c: 37935},
+    37940, {f: 2, c: 37942}, 37945, {f: 3, c: 37947}, {f: 4, c: 37952},
+    {f: 5, c: 37957}, 37963, {f: 5, c: 37965}, 37971, {f: 11, c: 37973},
+    {f: 2, c: 37985}, 37988, {f: 5, c: 37990}, 37996, {f: 2, c: 37998}, 38001,
+    {f: 4, c: 38003}, 38008, {f: 2, c: 38010}, {f: 5, c: 38016}, 38033, 38038,
+    38040, 38087, 38095, {f: 2, c: 38099}, 38106, 38118, 38139, 38172, 38176,
+    38183, 38195, 38205, 38211, 38216, 38219, 38229, 38234, 38240, 38254,
+    {f: 2, c: 38260}, {f: 7, c: 38264}, 38273, {f: 2, c: 38276},
+    {f: 2, c: 38279}, 38282, 38285, 38288, 38290, {f: 3, c: 38293},
+    {f: 8, c: 38297}, 38306, {f: 2, c: 38310}, 38314, {f: 4, c: 38318},
+    {f: 3, c: 38323}, {f: 2, c: 38327}, 38330, {f: 3, c: 38336},
+    {f: 2, c: 38340}, 38343, 38345, {f: 3, c: 38349}, {f: 3, c: 38353},
+    {f: 5, c: 38359}, 38365, {f: 2, c: 38367}, {f: 2, c: 38371},
+    {f: 2, c: 38374}, 38380, 38399, 38407, 38419, 38424, 38427, 38430, 38432,
+    {f: 7, c: 38435}, {f: 3, c: 38443}, {f: 2, c: 38447}, {f: 4, c: 38455},
+    38462, 38465, 38467, 38474, {f: 2, c: 38478}, {f: 3, c: 38481},
+    {f: 2, c: 38486}, {f: 2, c: 38489}, 38492, 38494, 38496, {f: 2, c: 38501},
+    38507, {f: 3, c: 38509}, 38513, {f: 4, c: 38521}, {f: 7, c: 38526}, 38535,
+    38537, 38540, {f: 3, c: 38545}, 38550, 38554, {f: 10, c: 38557}, 38569,
+    {f: 5, c: 38571}, 38578, 38581, 38583, 38586, 38591, {f: 2, c: 38594},
+    38600, {f: 2, c: 38602}, {f: 2, c: 38608}, {f: 2, c: 38611},
+    {f: 2, c: 38615}, 38618, {f: 3, c: 38621}, 38625, {f: 4, c: 38628},
+    {f: 4, c: 38635}, {f: 2, c: 38640}, {f: 2, c: 38644}, 38648, 38650,
+    {f: 2, c: 38652}, 38655, {f: 2, c: 38658}, 38661, {f: 3, c: 38666},
+    {f: 3, c: 38672}, {f: 2, c: 38676}, {f: 5, c: 38679}, 38685,
+    {f: 8, c: 38687}, {f: 2, c: 38696}, {f: 2, c: 38699}, {f: 2, c: 38702},
+    38705, {f: 5, c: 38707}, {f: 3, c: 38714}, {f: 3, c: 38719}, 38723,
+    {f: 3, c: 38725}, {f: 8, c: 38729}, [12205, 38737], {f: 2, c: 38740},
+    {f: 2, c: 38743}, {f: 2, c: 38748}, 38751, {f: 2, c: 38755},
+    {f: 2, c: 38758}, {f: 9, c: 38762}, 38773, {f: 5, c: 38775},
+    {f: 8, c: 38781}, {f: 5, c: 38790}, 38796, 38798, 38800, 38803,
+    {f: 3, c: 38805}, {f: 7, c: 38809}, {f: 2, c: 38817}, {f: 2, c: 38820},
+    {f: 4, c: 38823}, 38828, 38830, {f: 2, c: 38832}, 38835, {f: 8, c: 38837},
+    {f: 5, c: 38846}, {f: 2, c: 38852}, {f: 2, c: 38855}, 38858,
+    {f: 6, c: 38861}, {f: 5, c: 38868}, {f: 2, c: 38874}, 38877,
+    {f: 7, c: 38879}, 38888, {f: 5, c: 38894}, 38900, {f: 8, c: 38903}, 38912,
+    38916, 38921, 38923, 38925, {f: 3, c: 38932}, {f: 3, c: 38937},
+    {f: 4, c: 38941}, {f: 2, c: 38946}, 38949, {f: 6, c: 38951},
+    {f: 2, c: 38958}, {f: 6, c: 38961}, {f: 2, c: 38969}, 38972,
+    {f: 8, c: 38974}, {f: 5, c: 38983}, {f: 4, c: 38991}, {f: 3, c: 38997},
+    39002, {f: 2, c: 39004}, {f: 3, c: 39007}, {f: 2, c: 39011}, 39014,
+    {f: 3, c: 39016}, {f: 2, c: 39021}, 39026, 39051, 39054, 39058, 39061,
+    39065, 39075, {f: 5, c: 39081}, 39088, 39090, {f: 2, c: 39092},
+    {f: 5, c: 39095}, {f: 7, c: 39101}, 39109, 39111, {f: 5, c: 39113},
+    {f: 2, c: 39119}, 39124, {f: 2, c: 39126}, {f: 2, c: 39132}, 39137,
+    {f: 4, c: 39139}, 39148, 39150, {f: 2, c: 39152}, 39155, {f: 7, c: 39157},
+    {f: 4, c: 39167}, 39172, {f: 3, c: 39174}, 39179, {f: 2, c: 39182},
+    {f: 4, c: 39188}, {f: 2, c: 39193}, {f: 2, c: 39196}, {f: 2, c: 39199},
+    {f: 6, c: 39202}, {f: 5, c: 39209}, {f: 4, c: 39215}, {f: 3, c: 39220},
+    {f: 4, c: 39224}, 39229, {f: 3, c: 39232}, 39236, {f: 2, c: 39238},
+    {f: 4, c: 39245}, 39251, 39254, {f: 4, c: 39256}, 39261, {f: 3, c: 39263},
+    39268, 39270, 39283, {f: 2, c: 39288}, 39291, 39294, {f: 2, c: 39298},
+    39305, 39308, 39310, {f: 11, c: 39322}, {f: 2, c: 39334}, {f: 3, c: 39337},
+    {f: 2, c: 39343}, 39346, {f: 12, c: 39349}, {f: 14, c: 39362}, 39379,
+    {f: 2, c: 39382}, 39386, 39388, 39390, 39392, {f: 10, c: 39395},
+    {f: 3, c: 39406}, {f: 13, c: 39410}, 39424, {f: 3, c: 39426},
+    {f: 7, c: 39430}, {f: 6, c: 39440}, {f: 2, c: 39447}, {f: 17, c: 39450},
+    39468, 39471, {f: 5, c: 39473}, {f: 5, c: 39481}, 39487, {f: 4, c: 39494},
+    {f: 2, c: 39499}, 39502, {f: 5, c: 39504}, 39510, {f: 2, c: 39512},
+    {f: 3, c: 39516}, {f: 2, c: 39520}, 39523, {f: 4, c: 39526}, 39531, 39538,
+    39555, 39561, {f: 2, c: 39565}, {f: 2, c: 39572}, 39577, 39590,
+    {f: 6, c: 39593}, {f: 4, c: 39602}, 39609, 39611, {f: 3, c: 39613},
+    {f: 2, c: 39619}, {f: 5, c: 39622}, {f: 2, c: 39629}, 39632, 39639,
+    {f: 6, c: 39641}, 39648, {f: 4, c: 39650}, {f: 4, c: 39655}, 39660,
+    {f: 9, c: 39664}, 39674, {f: 7, c: 39676}, {f: 2, c: 39684}, 39687,
+    {f: 4, c: 39689}, 39694, {f: 3, c: 39696}, {f: 6, c: 39700},
+    {f: 4, c: 39707}, {f: 2, c: 39712}, 39716, 39718, 39720, {f: 4, c: 39722},
+    39728, {f: 8, c: 39731}, {f: 4, c: 39741}, 39750, {f: 3, c: 39754}, 39760,
+    {f: 2, c: 39762}, {f: 3, c: 39765}, 39769, {f: 20, c: 39771},
+    {f: 4, c: 39792}, {f: 2, c: 39797}, {f: 9, c: 39800}, 39810,
+    {f: 10, c: 39812}, 39823, {f: 7, c: 39827}, {f: 2, c: 39835},
+    {f: 11, c: 39839}, 39852, {f: 17, c: 39855}, {f: 5, c: 39874}, 39880,
+    {f: 9, c: 39883}, 39893, {f: 4, c: 39895}, 39900, {f: 3, c: 39902}, 39907,
+    {f: 2, c: 39909}, 39913, {f: 4, c: 39916}, {f: 3, c: 39921},
+    {f: 8, c: 39925}, 39934, {f: 8, c: 39936}, {f: 3, c: 39946},
+    {f: 2, c: 39950}, 39953, {f: 12, c: 39956}, {f: 2, c: 39969}, 39972,
+    {f: 2, c: 39974}, {f: 3, c: 39978}, {f: 3, c: 39982}, 39988, 39990, 39992,
+    39994, {f: 2, c: 39996}, {f: 6, c: 39999}, {f: 2, c: 40006},
+    {f: 8, c: 40010}, 40019, 40021, {f: 4, c: 40025}, 40030, {f: 7, c: 40032},
+    {f: 5, c: 40040}, {f: 10, c: 40046}, 40057, 40059, {f: 2, c: 40061}, 40064,
+    {f: 2, c: 40067}, {f: 2, c: 40073}, 40076, 40079, 40083, {f: 4, c: 40086},
+    40093, 40106, 40108, 40111, 40121, {f: 5, c: 40126}, {f: 2, c: 40136},
+    {f: 2, c: 40145}, {f: 2, c: 40154}, {f: 2, c: 40160}, {f: 2, c: 40163},
+    {f: 3, c: 40166}, {f: 2, c: 40170}, {f: 6, c: 40173}, 40181,
+    {f: 15, c: 40183}, 40200, {f: 11, c: 40202}, {f: 5, c: 40214}, 40220,
+    40222, {f: 3, c: 40224}, {f: 2, c: 40228}, 40231, {f: 6, c: 40233},
+    {f: 10, c: 40241}, {f: 3, c: 40252}, {f: 2, c: 40256}, {f: 14, c: 40259},
+    {f: 8, c: 40276}, {f: 2, c: 40286}, {f: 8, c: 40290}, 40299,
+    {f: 2, c: 40301}, {f: 2, c: 40304}, {f: 20, c: 40307}, 40328,
+    {f: 9, c: 40330}, {f: 4, c: 40340}, 40345, {f: 10, c: 40347},
+    {f: 3, c: 40358}, {f: 5, c: 40362}, {f: 4, c: 40368}, {f: 6, c: 40373},
+    {f: 3, c: 40381}, 40385, 40387, {f: 14, c: 40389}, {f: 3, c: 40404}, 40408,
+    {f: 10, c: 40411}, {f: 8, c: 40423}, {f: 2, c: 40432}, {f: 4, c: 40436},
+    {f: 17, c: 40443}, {f: 8, c: 40461}, {f: 4, c: 40470}, 40476, 40484, 40487,
+    40494, 40496, 40500, {f: 2, c: 40507}, 40512, 40525, 40528,
+    {f: 3, c: 40530}, 40534, 40537, 40541, {f: 4, c: 40543}, 40549,
+    {f: 2, c: 40558}, 40562, 40564, {f: 3, c: 40566}, 40571, {f: 2, c: 40576},
+    {f: 4, c: 40579}, {f: 2, c: 40585}, {f: 6, c: 40588}, {f: 3, c: 40596},
+    {f: 5, c: 40600}, 40606, {f: 5, c: 40608}, {f: 2, c: 40615},
+    {f: 5, c: 40618}, {f: 4, c: 40624}, {f: 2, c: 40630}, {f: 2, c: 40633},
+    40636, {f: 4, c: 40639}, [12232, 40643], {f: 4, c: 40645},
+    {f: 2, c: 40650}, 40656, {f: 2, c: 40658}, {f: 3, c: 40661},
+    {f: 2, c: 40665}, 40673, {f: 2, c: 40675}, 40678, {f: 4, c: 40683},
+    {f: 2, c: 40688}, 40691, {f: 2, c: 40693}, 40696, 40698, {f: 9, c: 40704},
+    40714, 40716, 40719, {f: 2, c: 40721}, 40724, 40726, 40728,
+    {f: 6, c: 40730}, 40737, {f: 9, c: 40739}, {f: 2, c: 40749},
+    {f: 7, c: 40752}, 40760, 40762, 40764, {f: 5, c: 40767}, {f: 5, c: 40773},
+    {f: 3, c: 40780}, 40787, {f: 4, c: 40789}, {f: 2, c: 40794},
+    {f: 2, c: 40797}, 40802, {f: 2, c: 40804}, {f: 3, c: 40807}, 40811,
+    {f: 5, c: 40813}, {f: 4, c: 40819}, {f: 7, c: 40824}, {f: 2, c: 40833},
+    {f: 2, c: 40846}, {f: 3, c: 40849}, {f: 3, c: 40854}, {f: 2, c: 40861},
+    {f: 5, c: 40865}, 63788, {f: 3, c: 64013}, 64017, {f: 2, c: 64019}, 64024,
+    {f: 3, c: 64031}, {f: 2, c: 64035}, {f: 3, c: 64039}, 11905,
+    [59414, 131207], [59415, 131209], [59416, 131276], 11908, 13427, 13383,
+    11912, 11915, 59422, 13726, 13850, 13838, 11916, 11927, 14702, 14616,
+    59430, 14799, 14815, 14963, 14800, {f: 2, c: 59435}, 15182, 15470, 15584,
+    11943, [59441, 136663], 59442, 11946, 16470, 16735, 11950, 17207, 11955,
+    {f: 2, c: 11958}, [59451, 141711], 17329, 17324, 11963, 17373, 17622,
+    18017, 17996, [59459, 132361], 18211, 18217, 18300, 18317, 11978, 18759,
+    18810, 18813, {f: 2, c: 18818}, {f: 2, c: 18821}, 18847, 18843, 18871,
+    18870, [59476, 133533], [59477, 147966], 19619, {f: 3, c: 19615}, 19575,
+    19618, {f: 7, c: 19731}, 19886, 59492, {s: 226}, 8364, 165, 0, 0, 12351,
+    {s: 17}, 12436, {s: 14}, 12535, 12537, 12536, 12538, 0, {f: 3, c: 12339},
+    {f: 3, c: 12344}, {f: 3, c: 12586}, {f: 24, c: 12704}, 11904,
+    {f: 2, c: 11906}, {f: 3, c: 11909}, {f: 2, c: 11913}, {f: 10, c: 11917},
+    {f: 2, c: 11928}, {f: 12, c: 11931}, {f: 2, c: 11944}, {f: 3, c: 11947},
+    {f: 4, c: 11951}, {f: 2, c: 11956}, {f: 3, c: 11960}, {f: 14, c: 11964},
+    {f: 41, c: 11979}, {f: 71, c: 13312}, {f: 43, c: 13384},
+    {f: 298, c: 13428}, {f: 111, c: 13727}, {f: 11, c: 13839},
+    {f: 765, c: 13851}, {f: 85, c: 14617}, {f: 96, c: 14703},
+    {f: 14, c: 14801}, {f: 147, c: 14816}, {f: 218, c: 14964},
+    {f: 287, c: 15183}, {f: 113, c: 15471}, {f: 885, c: 15585},
+    {f: 264, c: 16471}, {f: 471, c: 16736}, {f: 116, c: 17208},
+    {f: 4, c: 17325}, {f: 43, c: 17330}, {f: 248, c: 17374},
+    {f: 373, c: 17623}, {f: 20, c: 17997}, {f: 193, c: 18018},
+    {f: 5, c: 18212}, {f: 82, c: 18218}, {f: 16, c: 18301}, {f: 441, c: 18318},
+    {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}]
+};
 
-  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() {
@@ -13840,7 +14320,8 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
 
   function prepareKeyData(fileId, password, ownerPassword, userPassword,
                           flags, revision, keyLength, encryptMetadata) {
-    var hashData = new Uint8Array(100), i = 0, j, n;
+    var hashDataSize = 40 + ownerPassword.length + fileId.length;
+    var hashData = new Uint8Array(hashDataSize), i = 0, j, n;
     if (password) {
       n = Math.min(32, password.length);
       for (; i < n; ++i)
@@ -13955,8 +14436,8 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
       keyLength < 40 || (keyLength % 8) !== 0)
       error('invalid key length');
     // prepare keys
-    var ownerPassword = stringToBytes(dict.get('O'));
-    var userPassword = stringToBytes(dict.get('U'));
+    var ownerPassword = stringToBytes(dict.get('O')).subarray(0, 32);
+    var userPassword = stringToBytes(dict.get('U')).subarray(0, 32);
     var flags = dict.get('P');
     var revision = dict.get('R');
     var encryptMetadata = algorithm == 4 &&  // meaningful when V is 4
@@ -14067,7 +14548,7 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
 
 var PartialEvaluator = (function PartialEvaluatorClosure() {
   function PartialEvaluator(pdfManager, xref, handler, pageIndex,
-                            uniquePrefix, idCounters) {
+                            uniquePrefix, idCounters, fontCache) {
     this.state = new EvalState();
     this.stateStack = [];
 
@@ -14077,121 +14558,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
     this.pageIndex = pageIndex;
     this.uniquePrefix = uniquePrefix;
     this.idCounters = idCounters;
-    this.fontCache = new RefSetCache();
+    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: { fnName: 'setLineWidth', numArgs: 1, variableArgs: false },
-    J: { fnName: 'setLineCap', numArgs: 1, variableArgs: false },
-    j: { fnName: 'setLineJoin', numArgs: 1, variableArgs: false },
-    M: { fnName: 'setMiterLimit', numArgs: 1, variableArgs: false },
-    d: { fnName: 'setDash', numArgs: 2, variableArgs: false },
-    ri: { fnName: 'setRenderingIntent', numArgs: 1, variableArgs: false },
-    i: { fnName: 'setFlatness', numArgs: 1, variableArgs: false },
-    gs: { fnName: 'setGState', numArgs: 1, variableArgs: false },
-    q: { fnName: 'save', numArgs: 0, variableArgs: false },
-    Q: { fnName: 'restore', numArgs: 0, variableArgs: false },
-    cm: { fnName: 'transform', numArgs: 6, variableArgs: false },
-
-    // Path
-    m: { fnName: 'moveTo', numArgs: 2, variableArgs: false },
-    l: { fnName: 'lineTo', numArgs: 2, variableArgs: false },
-    c: { fnName: 'curveTo', numArgs: 6, variableArgs: false },
-    v: { fnName: 'curveTo2', numArgs: 4, variableArgs: false },
-    y: { fnName: 'curveTo3', numArgs: 4, variableArgs: false },
-    h: { fnName: 'closePath', numArgs: 0, variableArgs: false },
-    re: { fnName: 'rectangle', numArgs: 4, variableArgs: false },
-    S: { fnName: 'stroke', numArgs: 0, variableArgs: false },
-    s: { fnName: 'closeStroke', numArgs: 0, variableArgs: false },
-    f: { fnName: 'fill', numArgs: 0, variableArgs: false },
-    F: { fnName: 'fill', numArgs: 0, variableArgs: false },
-    'f*': { fnName: 'eoFill', numArgs: 0, variableArgs: false },
-    B: { fnName: 'fillStroke', numArgs: 0, variableArgs: false },
-    'B*': { fnName: 'eoFillStroke', numArgs: 0, variableArgs: false },
-    b: { fnName: 'closeFillStroke', numArgs: 0, variableArgs: false },
-    'b*': { fnName: 'closeEOFillStroke', numArgs: 0, variableArgs: false },
-    n: { fnName: 'endPath', numArgs: 0, variableArgs: false },
-
-    // Clipping
-    W: { fnName: 'clip', numArgs: 0, variableArgs: false },
-    'W*': { fnName: 'eoClip', numArgs: 0, variableArgs: false },
-
-    // Text
-    BT: { fnName: 'beginText', numArgs: 0, variableArgs: false },
-    ET: { fnName: 'endText', numArgs: 0, variableArgs: false },
-    Tc: { fnName: 'setCharSpacing', numArgs: 1, variableArgs: false },
-    Tw: { fnName: 'setWordSpacing', numArgs: 1, variableArgs: false },
-    Tz: { fnName: 'setHScale', numArgs: 1, variableArgs: false },
-    TL: { fnName: 'setLeading', numArgs: 1, variableArgs: false },
-    Tf: { fnName: 'setFont', numArgs: 2, variableArgs: false },
-    Tr: { fnName: 'setTextRenderingMode', numArgs: 1, variableArgs: false },
-    Ts: { fnName: 'setTextRise', numArgs: 1, variableArgs: false },
-    Td: { fnName: 'moveText', numArgs: 2, variableArgs: false },
-    TD: { fnName: 'setLeadingMoveText', numArgs: 2, variableArgs: false },
-    Tm: { fnName: 'setTextMatrix', numArgs: 6, variableArgs: false },
-    'T*': { fnName: 'nextLine', numArgs: 0, variableArgs: false },
-    Tj: { fnName: 'showText', numArgs: 1, variableArgs: false },
-    TJ: { fnName: 'showSpacedText', numArgs: 1, variableArgs: false },
-    '\'': { fnName: 'nextLineShowText', numArgs: 1, variableArgs: false },
-    '"': { fnName: 'nextLineSetSpacingShowText', numArgs: 3,
-      variableArgs: false },
-
-    // Type3 fonts
-    d0: { fnName: 'setCharWidth', numArgs: 2, variableArgs: false },
-    d1: { fnName: 'setCharWidthAndBounds', numArgs: 6, variableArgs: false },
-
-    // Color
-    CS: { fnName: 'setStrokeColorSpace', numArgs: 1, variableArgs: false },
-    cs: { fnName: 'setFillColorSpace', numArgs: 1, variableArgs: false },
-    SC: { fnName: 'setStrokeColor', numArgs: 4, variableArgs: true },
-    SCN: { fnName: 'setStrokeColorN', numArgs: 33, variableArgs: true },
-    sc: { fnName: 'setFillColor', numArgs: 4, variableArgs: true },
-    scn: { fnName: 'setFillColorN', numArgs: 33, variableArgs: true },
-    G: { fnName: 'setStrokeGray', numArgs: 1, variableArgs: false },
-    g: { fnName: 'setFillGray', numArgs: 1, variableArgs: false },
-    RG: { fnName: 'setStrokeRGBColor', numArgs: 3, variableArgs: false },
-    rg: { fnName: 'setFillRGBColor', numArgs: 3, variableArgs: false },
-    K: { fnName: 'setStrokeCMYKColor', numArgs: 4, variableArgs: false },
-    k: { fnName: 'setFillCMYKColor', numArgs: 4, variableArgs: false },
-
-    // Shading
-    sh: { fnName: 'shadingFill', numArgs: 1, variableArgs: false },
-
-    // Images
-    BI: { fnName: 'beginInlineImage', numArgs: 0, variableArgs: false },
-    ID: { fnName: 'beginImageData', numArgs: 0, variableArgs: false },
-    EI: { fnName: 'endInlineImage', numArgs: 1, variableArgs: false },
-
-    // XObjects
-    Do: { fnName: 'paintXObject', numArgs: 1, variableArgs: false },
-    MP: { fnName: 'markPoint', numArgs: 1, variableArgs: false },
-    DP: { fnName: 'markPointProps', numArgs: 2, variableArgs: false },
-    BMC: { fnName: 'beginMarkedContent', numArgs: 1, variableArgs: false },
-    BDC: { fnName: 'beginMarkedContentProps', numArgs: 2, variableArgs: false },
-    EMC: { fnName: 'endMarkedContent', numArgs: 0, variableArgs: false },
-
-    // Compatibility
-    BX: { fnName: 'beginCompat', numArgs: 0, variableArgs: false },
-    EX: { fnName: '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 = {
@@ -14237,7 +14606,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
 
     buildFormXObject: function PartialEvaluator_buildFormXObject(resources,
                                                                  xobj, smask,
-                                                                 operatorList) {
+                                                                 operatorList,
+                                                                 state) {
       var self = this;
 
       var matrix = xobj.dict.get('Matrix');
@@ -14259,17 +14629,17 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
           // There is also a group colorspace, but since we put everything in
           // RGB I'm not sure we need it.
         }
-        operatorList.addOp('beginGroup', [groupOptions]);
+        operatorList.addOp(OPS.beginGroup, [groupOptions]);
       }
 
-      operatorList.addOp('paintFormXObjectBegin', [matrix, bbox]);
+      operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]);
 
       this.getOperatorList(xobj, xobj.dict.get('Resources') || resources,
-                           operatorList);
-      operatorList.addOp('paintFormXObjectEnd', []);
+                           operatorList, state);
+      operatorList.addOp(OPS.paintFormXObjectEnd, []);
 
       if (group) {
-        operatorList.addOp('endGroup', [groupOptions]);
+        operatorList.addOp(OPS.endGroup, [groupOptions]);
       }
     },
 
@@ -14300,9 +14670,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
         var decode = dict.get('Decode', 'D');
         var inverseDecode = !!decode && decode[0] > 0;
 
-        operatorList.addOp('paintImageMaskXObject',
-          [PDFImage.createMask(imgArray, width, height,
-                                            inverseDecode)]
+        operatorList.addOp(OPS.paintImageMaskXObject,
+          [PDFImage.createMask(imgArray, width, height, inverseDecode)]
         );
         return;
       }
@@ -14318,7 +14687,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
         var imageObj = new PDFImage(this.xref, resources, image,
                                     inline, null, null);
         var imgData = imageObj.getImageData();
-        operatorList.addOp('paintInlineImageXObject', [imgData]);
+        operatorList.addOp(OPS.paintInlineImageXObject, [imgData]);
         return;
       }
 
@@ -14332,7 +14701,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
       if (!softMask && !mask && image instanceof JpegStream &&
           image.isNativelySupported(this.xref, resources)) {
         // These JPEGs don't need any more processing so we can just send it.
-        operatorList.addOp('paintJpegXObject', args);
+        operatorList.addOp(OPS.paintJpegXObject, args);
         this.handler.send(
             'obj', [objId, this.pageIndex, 'JpegStream', image.getIR()]);
         return;
@@ -14341,10 +14710,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
 
       PDFImage.buildImage(function(imageObj) {
           var imgData = imageObj.getImageData();
-          self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData]);
+          self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData],
+                            null, [imgData.data.buffer]);
         }, self.handler, self.xref, resources, image, inline);
 
-      operatorList.addOp('paintImageXObject', args);
+      operatorList.addOp(OPS.paintImageXObject, args);
     },
 
     handleTilingType: function PartialEvaluator_handleTilingType(
@@ -14446,9 +14816,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
             gStateObj.push([key, value]);
             break;
           case 'SMask':
-            // We support the default so don't trigger the TODO.
+            // We support the default so don't trigger a warning bar.
             if (!isName(value) || value.name != 'None')
-              TODO('graphic state operator ' + key);
+              UnsupportedManager.notify(UNSUPPORTED_FEATURES.smask);
             break;
           // Only generate info log messages for the following since
           // they are unlikey to have a big impact on the rendering.
@@ -14483,7 +14853,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
         setGStateForKey(gStateObj, key, value);
       }
 
-      operatorList.addOp('setGState', [gStateObj]);
+      operatorList.addOp(OPS.setGState, [gStateObj]);
     },
 
     loadFont: function PartialEvaluator_loadFont(fontName, font, xref,
@@ -14514,22 +14884,31 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
         return this.fontCache.get(fontRef);
       }
 
-
       font = xref.fetchIfRef(fontRef);
       if (!isDict(font)) {
         return errorFont();
       }
-      this.fontCache.put(fontRef, font);
+      // 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);
+      }
 
       // keep track of each font we translated so the caller can
       // load them asynchronously before calling display on a page
-      font.loadedName = 'g_font_' + fontRef.num + '_' + fontRef.gen;
+      font.loadedName = 'g_font_' + (fontRefIsDict ?
+        fontName.replace(/\W/g, '') : (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;
@@ -14562,7 +14941,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
 
     getOperatorList: function PartialEvaluator_getOperatorList(stream,
                                                                resources,
-                                                               operatorList) {
+                                                               operatorList,
+                                                               evaluatorState) {
 
       var self = this;
       var xref = this.xref;
@@ -14573,154 +14953,131 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
       resources = resources || new Dict();
       var xobjs = resources.get('XObject') || new Dict();
       var patterns = resources.get('Pattern') || new Dict();
-      // 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 = [];
-      nextOp:
-      while (true) {
-
-        var obj = parser.getObj();
-
-        if (isEOF(obj)) {
-          break;
-        }
+      var preprocessor = new EvaluatorPreprocessor(stream, xref);
+      if (evaluatorState) {
+        preprocessor.setState(evaluatorState);
+      }
 
-        if (isCmd(obj)) {
-          var cmd = obj.cmd;
+      var promise = new LegacyPromise();
+      var operation;
+      while ((operation = preprocessor.read())) {
+          var args = operation.args;
+          var fn = operation.fn;
 
-          // Check that the command is valid
-          var opSpec = OP_MAP[cmd];
-          if (!opSpec) {
-            warn('Unknown command "' + cmd + '"');
-            continue;
-          }
-
-          var fn = opSpec.fnName;
+          switch (fn) {
+            case OPS.setStrokeColorN:
+            case OPS.setFillColorN:
+              if (args[args.length - 1].code) {
+                break;
+              }
+              // compile tiling patterns
+              var patternName = args[args.length - 1];
+              // SCN/scn applies patterns along with normal colors
+              var pattern;
+              if (isName(patternName) &&
+                  (pattern = patterns.get(patternName.name))) {
+
+                var dict = isStream(pattern) ? pattern.dict : pattern;
+                var typeNum = dict.get('PatternType');
+
+                if (typeNum == TILING_PATTERN) {
+                  self.handleTilingType(fn, args, resources, pattern, dict,
+                                        operatorList);
+                  args = [];
+                  continue;
+                } else if (typeNum == SHADING_PATTERN) {
+                  var shading = dict.get('Shading');
+                  var matrix = dict.get('Matrix');
+                  var pattern = Pattern.parseShading(shading, matrix, xref,
+                                                      resources);
+                  args = pattern.getIR();
+                } else {
+                  error('Unkown PatternType ' + typeNum);
+                }
+              }
+              break;
+            case OPS.paintXObject:
+              if (args[0].code) {
+                break;
+              }
+              // eagerly compile XForm objects
+              var name = args[0].name;
+              var xobj = xobjs.get(name);
+              if (xobj) {
+                assertWellFormed(
+                    isStream(xobj), 'XObject should be a stream');
+
+                var type = xobj.dict.get('Subtype');
+                assertWellFormed(
+                  isName(type),
+                  'XObject should have a Name subtype'
+                );
 
-          // 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');
+                if ('Form' == type.name) {
+                  self.buildFormXObject(resources, xobj, null, operatorList,
+                                        preprocessor.getState());
+                  args = [];
+                  continue;
+                } else if ('Image' == type.name) {
+                  self.buildPaintImageXObject(resources, xobj, false,
+                                              operatorList);
+                  args = [];
+                  continue;
+                } else {
+                  error('Unhandled XObject subtype ' + type.name);
+                }
+              }
+              break;
+            case OPS.setFont:
+              // eagerly collect all fonts
+              var loadedName = self.handleSetFont(resources, args, null,
+                                                  operatorList);
+              operatorList.addDependency(loadedName);
+              args[0] = loadedName;
+              break;
+            case OPS.endInlineImage:
+              self.buildPaintImageXObject(resources, args[0], true,
+                                          operatorList);
               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
-
-          if ((cmd == 'SCN' || cmd == 'scn') &&
-               !args[args.length - 1].code) {
-            // compile tiling patterns
-            var patternName = args[args.length - 1];
-            // SCN/scn applies patterns along with normal colors
-            var pattern;
-            if (isName(patternName) &&
-                (pattern = patterns.get(patternName.name))) {
-
-              var dict = isStream(pattern) ? pattern.dict : pattern;
-              var typeNum = dict.get('PatternType');
-
-              if (typeNum == TILING_PATTERN) {
-                self.handleTilingType(fn, args, resources, pattern, dict,
-                                      operatorList);
-                args = [];
-                continue;
-              } else if (typeNum == SHADING_PATTERN) {
-                var shading = dict.get('Shading');
-                var matrix = dict.get('Matrix');
-                var pattern = Pattern.parseShading(shading, matrix, xref,
-                                                    resources);
-                args = pattern.getIR();
-              } else {
-                error('Unkown PatternType ' + typeNum);
-              }
-            }
-          } else if (cmd == 'Do' && !args[0].code) {
-            // eagerly compile XForm objects
-            var name = args[0].name;
-            var xobj = xobjs.get(name);
-            if (xobj) {
-              assertWellFormed(
-                  isStream(xobj), 'XObject should be a stream');
-
-              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);
-                args = [];
-                continue;
-              } else if ('Image' == type.name) {
-                self.buildPaintImageXObject(resources, xobj, false,
-                                            operatorList);
-                args = [];
-                continue;
-              } else {
-                error('Unhandled XObject subtype ' + type.name);
+            case OPS.save:
+              var old = this.state;
+              this.stateStack.push(this.state);
+              this.state = old.clone();
+              break;
+            case OPS.restore:
+              var prev = this.stateStack.pop();
+              if (prev) {
+                this.state = prev;
               }
-            }
-          } else if (cmd == 'Tf') { // eagerly collect all fonts
-            var loadedName = self.handleSetFont(resources, args, null,
-                                                operatorList);
-            operatorList.addDependency(loadedName);
-            fn = 'setFont';
-            args[0] = loadedName;
-          } else if (cmd == 'EI') {
-            self.buildPaintImageXObject(resources, args[0], true, operatorList);
-            args = [];
-            continue;
-          } else if (cmd === 'q') { // save
-            var old = this.state;
-            this.stateStack.push(this.state);
-            this.state = old.clone();
-          } else if (cmd === 'Q') { // restore
-            var prev = this.stateStack.pop();
-            if (prev) {
-              this.state = prev;
-            }
-          } else if (cmd === 'Tj') { // showText
-            args[0] = this.handleText(args[0]);
-          } else if (cmd === 'TJ') { // showSpacedText
-            var arr = args[0];
-            var arrLength = arr.length;
-            for (var i = 0; i < arrLength; ++i) {
-              if (isString(arr[i])) {
-                arr[i] = this.handleText(arr[i]);
+              break;
+            case OPS.showText:
+              args[0] = this.handleText(args[0]);
+              break;
+            case OPS.showSpacedText:
+              var arr = args[0];
+              var arrLength = arr.length;
+              for (var i = 0; i < arrLength; ++i) {
+                if (isString(arr[i])) {
+                  arr[i] = this.handleText(arr[i]);
+                }
               }
-            }
-          } else if (cmd === '\'') { // nextLineShowText
-            args[0] = this.handleText(args[0]);
-          } else if (cmd === '"') { // nextLineSetSpacingShowText
-            args[2] = this.handleText(args[2]);
-          } else if (cmd === 'Tr') { // setTextRenderingMode
-            this.state.textRenderingMode = args[0];
-          }
-
-          switch (fn) {
+              break;
+            case OPS.nextLineShowText:
+              args[0] = this.handleText(args[0]);
+              break;
+            case OPS.nextLineSetSpacingShowText:
+              args[2] = this.handleText(args[2]);
+              break;
+            case OPS.setTextRenderingMode:
+              this.state.textRenderingMode = args[0];
+              break;
             // Parse the ColorSpace data to a raw format.
-            case 'setFillColorSpace':
-            case 'setStrokeColorSpace':
+            case OPS.setFillColorSpace:
+            case OPS.setStrokeColorSpace:
               args = [ColorSpace.parseToIR(args[0], xref, resources)];
               break;
-            case 'shadingFill':
+            case OPS.shadingFill:
               var shadingRes = resources.get('Shading');
               if (!shadingRes)
                 error('No shading resource found');
@@ -14733,9 +15090,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
                   shading, null, xref, resources);
               var patternIR = shadingFill.getIR();
               args = [patternIR];
-              fn = 'shadingFill';
+              fn = OPS.shadingFill;
               break;
-            case 'setGState':
+            case OPS.setGState:
               var dictName = args[0];
               var extGState = resources.get('ExtGState');
 
@@ -14745,16 +15102,16 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
               var gState = extGState.get(dictName.name);
               self.setGState(resources, gState, operatorList);
               args = [];
-              continue nextOp;
+              continue;
           } // switch
 
           operatorList.addOp(fn, args);
-          args = [];
-          parser.saveState();
-        } else if (obj !== null && obj !== undefined) {
-          args.push(obj instanceof Dict ? obj.getAll() : obj);
-          assertWellFormed(args.length <= 33, 'Too many arguments');
-        }
+      }
+
+      // 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, []);
       }
 
       return operatorList;
@@ -14791,65 +15148,55 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
       // The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd.
       var xobjs = null;
 
-      var parser = new Parser(new Lexer(stream), false);
+      var preprocessor = new EvaluatorPreprocessor(stream, xref);
       var res = resources;
-      var args = [], obj;
 
       var chunk = '';
       var font = null;
       var charSpace = 0, wordSpace = 0;
-      while (!isEOF(obj = parser.getObj())) {
-        if (isCmd(obj)) {
-          var cmd = obj.cmd;
-          switch (cmd) {
+      var operation;
+      while ((operation = preprocessor.read())) {
+          var fn = operation.fn;
+          var args = operation.args;
+          switch (fn) {
             // TODO: Add support for SAVE/RESTORE and XFORM here.
-            case 'Tf':
+            case OPS.setFont:
               font = handleSetFont(args[0].name).translated;
               textState.fontSize = args[1];
               break;
-            case 'Ts':
+            case OPS.setTextRise:
               textState.textRise = args[0];
               break;
-            case 'Tz':
+            case OPS.setHScale:
               textState.textHScale = args[0] / 100;
               break;
-            case 'TL':
+            case OPS.setLeading:
               textState.leading = args[0];
               break;
-            case 'Td':
+            case OPS.moveText:
               textState.translateTextMatrix(args[0], args[1]);
               break;
-            case 'TD':
+            case OPS.setLeadingMoveText:
               textState.leading = -args[1];
               textState.translateTextMatrix(args[0], args[1]);
               break;
-            case 'T*':
+            case OPS.nextLine:
               textState.translateTextMatrix(0, -textState.leading);
               break;
-            case 'Tm':
+            case OPS.setTextMatrix:
               textState.setTextMatrix(args[0], args[1],
                                        args[2], args[3], args[4], args[5]);
               break;
-            case 'Tc':
+            case OPS.setCharSpacing:
               charSpace = args[0];
               break;
-            case 'Tw':
+            case OPS.setWordSpacing:
               wordSpace = args[0];
               break;
-            case 'q':
-              textState.push();
-              break;
-            case 'Q':
-              textState.pop();
-              break;
-            case 'BT':
+            case OPS.beginText:
               textState.initialiseTextObj();
               break;
-            case 'cm':
-              textState.transformCTM(args[0], args[1], args[2],
-                                args[3], args[4], args[5]);
-              break;
-            case 'TJ':
+            case OPS.showSpacedText:
               var items = args[0];
               for (var j = 0, jj = items.length; j < jj; j++) {
                 if (typeof items[j] === 'string') {
@@ -14867,20 +15214,20 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
                 }
               }
               break;
-            case 'Tj':
+            case OPS.showText:
               chunk += fontCharsToUnicode(args[0], font);
               break;
-            case '\'':
+            case OPS.nextLineShowText:
               // 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 '"':
+            case OPS.nextLineSetSpacingShowText:
               // Note comment in "'"
               chunk += fontCharsToUnicode(args[2], font);
               break;
-            case 'Do':
+            case OPS.paintXObject:
               // Set the chunk such that the following if won't add something
               // to the state.
               chunk = '';
@@ -14914,7 +15261,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
                 state
               );
               break;
-            case 'gs':
+            case OPS.setGState:
               var dictName = args[0];
               var extGState = resources.get('ExtGState');
 
@@ -14933,11 +15280,18 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
 
           if (chunk !== '') {
             var bidiText = PDFJS.bidi(chunk, -1, font.vertical);
-            var renderParams = textState.calcRenderParams();
+            var renderParams = textState.calcRenderParams(preprocessor.ctm);
             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;
@@ -14946,12 +15300,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
 
             chunk = '';
           }
-
-          args = [];
-        } else if (obj !== null && obj !== undefined) {
-          assertWellFormed(args.length <= 33, 'Too many arguments');
-          args.push(obj);
-        }
       } // while
 
       return state;
@@ -14999,10 +15347,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
                           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 also
+      // Heuristic: we have to check if the font is a standard one and has
+      // Symbolic font name
       if (!!(flags & FontFlags.Symbolic)) {
-        baseEncoding = !properties.file ? Encodings.symbolsEncoding :
-                                          Encodings.MacRomanEncoding;
+        baseEncoding = !properties.file && /Symbol/i.test(properties.name) ?
+          Encodings.SymbolSetEncoding : Encodings.MacRomanEncoding;
       }
       if (dict.has('Encoding')) {
         var encoding = dict.get('Encoding');
@@ -15270,6 +15619,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
 
           var properties = {
             type: type.name,
+            name: baseFontName,
             widths: metrics.widths,
             defaultWidth: metrics.defaultWidth,
             flags: flags,
@@ -15328,6 +15678,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
 
       var properties = {
         type: type.name,
+        name: fontName.name,
         subtype: subtype,
         file: fontFile,
         length1: length1,
@@ -15371,6 +15722,18 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
   PartialEvaluator.optimizeQueue =
       function PartialEvaluator_optimizeQueue(queue) {
 
+    function squash(array, index, howMany, element) {
+      if (isArray(array)) {
+        array.splice(index, howMany, element);
+      } else {
+        // Replace the element.
+        array[index] = element;
+        // Shift everything after the element up.
+        var sub = array.subarray(index + howMany);
+        array.set(sub, index + 1);
+      }
+    }
+
     var fnArray = queue.fnArray, argsArray = queue.argsArray;
     // grouping paintInlineImageXObject's into paintInlineImageXObjectGroup
     // searching for (save, transform, paintInlineImageXObject, restore)+
@@ -15378,10 +15741,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
     var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;
     var MAX_WIDTH = 1000;
     var IMAGE_PADDING = 1;
-    for (var i = 0, ii = fnArray.length; i < ii; i++) {
-      if (fnArray[i] === 'paintInlineImageXObject' &&
-          fnArray[i - 2] === 'save' && fnArray[i - 1] === 'transform' &&
-          fnArray[i + 1] === 'restore') {
+    for (var i = 0, ii = argsArray.length; i < ii; i++) {
+      if (fnArray[i] === OPS.paintInlineImageXObject &&
+          fnArray[i - 2] === OPS.save && fnArray[i - 1] === OPS.transform &&
+          fnArray[i + 1] === OPS.restore) {
         var j = i - 2;
         for (i += 2; i < ii && fnArray[i - 4] === fnArray[i]; i++) {
         }
@@ -15446,21 +15809,21 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
           }
         }
         // replacing queue items
-        fnArray.splice(j, count * 4, ['paintInlineImageXObjectGroup']);
+        squash(fnArray, j, count * 4, OPS.paintInlineImageXObjectGroup);
         argsArray.splice(j, count * 4,
           [{width: imgWidth, height: imgHeight, data: imgData}, map]);
         i = j;
-        ii = fnArray.length;
+        ii = argsArray.length;
       }
     }
     // grouping paintImageMaskXObject's into paintImageMaskXObjectGroup
     // searching for (save, transform, paintImageMaskXObject, restore)+
     var MIN_IMAGES_IN_MASKS_BLOCK = 10;
     var MAX_IMAGES_IN_MASKS_BLOCK = 100;
-    for (var i = 0, ii = fnArray.length; i < ii; i++) {
-      if (fnArray[i] === 'paintImageMaskXObject' &&
-          fnArray[i - 2] === 'save' && fnArray[i - 1] === 'transform' &&
-          fnArray[i + 1] === 'restore') {
+    for (var i = 0, ii = argsArray.length; i < ii; i++) {
+      if (fnArray[i] === OPS.paintImageMaskXObject &&
+          fnArray[i - 2] === OPS.save && fnArray[i - 1] === OPS.transform &&
+          fnArray[i + 1] === OPS.restore) {
         var j = i - 2;
         for (i += 2; i < ii && fnArray[i - 4] === fnArray[i]; i++) {
         }
@@ -15477,37 +15840,68 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
             height: maskParams.height, transform: transform});
         }
         // replacing queue items
-        fnArray.splice(j, count * 4, ['paintImageMaskXObjectGroup']);
+        squash(fnArray, j, count * 4, OPS.paintImageMaskXObjectGroup);
         argsArray.splice(j, count * 4, [images]);
         i = j;
-        ii = fnArray.length;
+        ii = argsArray.length;
       }
     }
   };
 
-
   return PartialEvaluator;
 })();
 
-
 var OperatorList = (function OperatorListClosure() {
   var CHUNK_SIZE = 100;
 
-  function OperatorList(messageHandler, pageIndex) {
+    function getTransfers(queue) {
+      var transfers = [];
+      var fnArray = queue.fnArray, argsArray = queue.argsArray;
+      for (var i = 0, ii = queue.length; i < ii; i++) {
+        switch (fnArray[i]) {
+          case OPS.paintInlineImageXObject:
+          case OPS.paintInlineImageXObjectGroup:
+          case OPS.paintImageMaskXObject:
+            var arg = argsArray[i][0]; // first param in imgData
+            transfers.push(arg.data.buffer);
+            break;
+        }
+      }
+      return transfers;
+    }
+
+
+    function OperatorList(messageHandler, pageIndex) {
     this.messageHandler = messageHandler;
-    this.fnArray = [];
+    // When there isn't a message handler the fn array needs to be able to grow
+    // since we can't flush the operators.
+    if (messageHandler) {
+      this.fnArray = new Uint8Array(CHUNK_SIZE);
+    } else {
+      this.fnArray = [];
+    }
     this.argsArray = [];
     this.dependencies = {},
     this.pageIndex = pageIndex;
+    this.fnIndex = 0;
   }
 
   OperatorList.prototype = {
 
+    get length() {
+      return this.argsArray.length;
+    },
+
     addOp: function(fn, args) {
-      this.fnArray.push(fn);
-      this.argsArray.push(args);
-      if (this.messageHandler && this.fnArray.length >= CHUNK_SIZE) {
-        this.flush();
+      if (this.messageHandler) {
+        this.fnArray[this.fnIndex++] = fn;
+        this.argsArray.push(args);
+        if (this.fnIndex >= CHUNK_SIZE) {
+          this.flush();
+        }
+      } else {
+        this.fnArray.push(fn);
+        this.argsArray.push(args);
       }
     },
 
@@ -15516,7 +15910,7 @@ var OperatorList = (function OperatorListClosure() {
         return;
       }
       this.dependencies[dependency] = true;
-      this.addOp('dependency', [dependency]);
+      this.addOp(OPS.dependency, [dependency]);
     },
 
     addDependencies: function(dependencies) {
@@ -15526,40 +15920,44 @@ var OperatorList = (function OperatorListClosure() {
     },
 
     addOpList: function(opList) {
-      Util.concatenateToArray(this.fnArray, opList.fnArray);
-      Util.concatenateToArray(this.argsArray, opList.argsArray);
       Util.extendObj(this.dependencies, opList.dependencies);
+      for (var i = 0, ii = opList.length; i < ii; i++) {
+        this.addOp(opList.fnArray[i], opList.argsArray[i]);
+      }
     },
 
     getIR: function() {
       return {
         fnArray: this.fnArray,
-        argsArray: this.argsArray
+        argsArray: this.argsArray,
+        length: this.length
       };
     },
 
     flush: function(lastChunk) {
       PartialEvaluator.optimizeQueue(this);
+      var transfers = getTransfers(this);
       this.messageHandler.send('RenderPageChunk', {
         operatorList: {
           fnArray: this.fnArray,
           argsArray: this.argsArray,
-          lastChunk: lastChunk
+          lastChunk: lastChunk,
+          length: this.length
         },
         pageIndex: this.pageIndex
-      });
+      }, null, transfers);
       this.dependencies = [];
-      this.fnArray = [];
+      this.fnIndex = 0;
       this.argsArray = [];
     }
   };
 
   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
@@ -15568,12 +15966,6 @@ var TextState = (function TextStateClosure() {
     this.textRise = 0;
   }
   TextState.prototype = {
-    push: function TextState_push() {
-      this.stateStack.push(this.ctm.slice());
-    },
-    pop: function TextStae_pop() {
-      this.ctm = this.stateStack.pop();
-    },
     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;
@@ -15582,24 +15974,13 @@ var TextState = (function TextStateClosure() {
       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() {
+    calcRenderParams: function TextState_calcRenderingParams(cm) {
       var tm = this.textMatrix;
-      var cm = this.ctm;
       var a = this.fontSize;
       var b = a * this.textHScale;
       var c = this.textRise;
@@ -15642,6 +16023,221 @@ var EvalState = (function EvalStateClosure() {
   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
@@ -15848,8 +16444,8 @@ var Encodings = {
     'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash',
     'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn',
     'ydieresis'],
-  symbolsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+  SymbolSetEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
     'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent',
     'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus',
     'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
@@ -16078,6 +16674,76 @@ var HalfwidthCMaps = {
   '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:
@@ -16117,7 +16783,7 @@ function sjis83pvToUnicode(str) {
     // TODO: 83pv has incompatible mappings in ed40..ee9c range.
     return decodeBytes(bytes, 'shift_jis', true);
   } catch (e) {
-    TODO('Unsupported 83pv character found');
+    warn('Unsupported 83pv character found');
     // Just retry without checking errors for now.
     return decodeBytes(bytes, 'shift_jis');
   }
@@ -16129,7 +16795,7 @@ function sjis90pvToUnicode(str) {
     // TODO: 90pv has incompatible mappings in 8740..879c and eb41..ee9c.
     return decodeBytes(bytes, 'shift_jis', true);
   } catch (e) {
-    TODO('Unsupported 90pv character found');
+    warn('Unsupported 90pv character found');
     // Just retry without checking errors for now.
     return decodeBytes(bytes, 'shift_jis');
   }
@@ -17805,6 +18471,8 @@ var Font = (function FontClosure() {
     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') {
@@ -17832,6 +18500,7 @@ var Font = (function FontClosure() {
       // 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);
@@ -17847,6 +18516,17 @@ var Font = (function FontClosure() {
 
       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;
@@ -18699,6 +19379,17 @@ var Font = (function FontClosure() {
           error('cmap table has unsupported format: ' + format);
         }
 
+        // removing duplicate entries
+        mappings.sort(function (a, b) {
+          return a.charcode - b.charcode;
+        });
+        for (var i = 1; i < mappings.length; i++) {
+          if (mappings[i - 1].charcode === mappings[i].charcode) {
+            mappings.splice(i, 1);
+            i--;
+          }
+        }
+
         return {
           platformId: potentialTable.platformId,
           encodingId: potentialTable.encodingId,
@@ -18774,8 +19465,8 @@ var Font = (function FontClosure() {
         for (var i = 0; i < flagsCount; i++) {
           var flag = glyf[j++];
           if (flag & 0xC0) {
-            // reserved flags must be zero, rejecting
-            return 0;
+            // reserved flags must be zero, cleaning up
+            glyf[j - 1] = flag & 0x3F;
           }
           var xyLength = ((flag & 2) ? 1 : (flag & 16) ? 0 : 2) +
                          ((flag & 4) ? 1 : (flag & 32) ? 0 : 2);
@@ -18786,6 +19477,10 @@ var Font = (function FontClosure() {
             coordinatesLength += repeat * xyLength;
           }
         }
+        // glyph without coordinates will be rejected
+        if (coordinatesLength === 0) {
+          return 0;
+        }
         var glyphDataLength = j + coordinatesLength;
         if (glyphDataLength > glyf.length) {
           // not enough data for coordinates
@@ -18884,6 +19579,13 @@ var Font = (function FontClosure() {
           };
         }
         var locaData = loca.data;
+        var locaDataSize = itemSize * (1 + numGlyphs);
+        // is loca.data too short or long?
+        if (locaData.length !== locaDataSize) {
+          locaData = new Uint8Array(locaDataSize);
+          locaData.set(loca.data.subarray(0, locaDataSize));
+          loca.data = locaData;
+        }
         // removing the invalid glyphs
         var oldGlyfData = glyf.data;
         var oldGlyfDataLength = oldGlyfData.length;
@@ -18927,9 +19629,7 @@ var Font = (function FontClosure() {
             glyf.data.set(newGlyfData.subarray(0, writeOffset));
           }
           glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset);
-          loca.data = new Uint8Array(locaData.length + itemSize);
-          loca.data.set(locaData);
-          itemEncode(loca.data, locaData.length,
+          itemEncode(loca.data, locaData.length - itemSize,
                      writeOffset + firstEntryLength);
         } else {
           glyf.data = newGlyfData.subarray(0, writeOffset);
@@ -19129,6 +19829,11 @@ var Font = (function FontClosure() {
                 callstack.push({data: data, i: i, stackTop: stack.length - 1});
                 functionsCalled.push(funcId);
                 var pc = ttContext.functionsDefined[funcId];
+                if (!pc) {
+                  warn('TT: CALL non-existent function');
+                  ttContext.hintsValid = false;
+                  return;
+                }
                 data = pc.data;
                 i = pc.i;
               }
@@ -19149,6 +19854,11 @@ var Font = (function FontClosure() {
               lastEndf = i;
             } else {
               var pc = callstack.pop();
+              if (!pc) {
+                warn('TT: ENDF bad stack');
+                ttContext.hintsValid = false;
+                return;
+              }
               var funcId = functionsCalled.pop();
               data = pc.data;
               i = pc.i;
@@ -19248,7 +19958,7 @@ var Font = (function FontClosure() {
         }
       }
 
-      function sanitizeTTPrograms(fpgm, prep) {
+      function sanitizeTTPrograms(fpgm, prep, cvt) {
         var ttContext = {
           functionsDefined: [],
           functionsUsed: [],
@@ -19265,6 +19975,11 @@ var Font = (function FontClosure() {
         if (fpgm) {
           checkInvalidFunctions(ttContext, maxFunctionDefs);
         }
+        if (cvt && (cvt.length & 1)) {
+          var cvtData = new Uint8Array(cvt.length + 1);
+          cvtData.set(cvt.data);
+          cvt.data = cvtData;
+        }
         return ttContext.hintsValid;
       }
 
@@ -19284,6 +19999,9 @@ var Font = (function FontClosure() {
         if (VALID_TABLES.indexOf(table.tag) < 0) {
           continue; // skipping table if it's not a required or optional table
         }
+        if (table.length === 0) {
+          continue; // skipping empty tables
+        }
         tables[table.tag] = table;
       }
 
@@ -19318,7 +20036,14 @@ var Font = (function FontClosure() {
       var numGlyphs = int16(font.getBytes(2));
       var maxFunctionDefs = 0;
       if (version >= 0x00010000 && tables.maxp.length >= 22) {
-        font.pos += 14;
+        // maxZones can be invalid
+        font.pos += 8;
+        var maxZones = int16(font.getBytes(2));
+        if (maxZones > 2) { // reset to 2 if font has invalid maxZones
+          tables.maxp.data[14] = 0;
+          tables.maxp.data[15] = 2;
+        }
+        font.pos += 4;
         maxFunctionDefs = int16(font.getBytes(2));
       }
 
@@ -19333,10 +20058,11 @@ var Font = (function FontClosure() {
       }
 
       var hintsValid = sanitizeTTPrograms(tables.fpgm, tables.prep,
-                                          maxFunctionDefs);
+                                          tables['cvt '], maxFunctionDefs);
       if (!hintsValid) {
         delete tables.fpgm;
         delete tables.prep;
+        delete tables['cvt '];
       }
 
       // Tables needs to be written by ascendant alphabetic order
@@ -19370,7 +20096,6 @@ var Font = (function FontClosure() {
       if (isTrueType) {
         var isGlyphLocationsLong = int16([tables.head.data[50],
                                           tables.head.data[51]]);
-
         sanitizeGlyphLocations(tables.loca, tables.glyf, numGlyphs,
                                isGlyphLocationsLong, hintsValid, dupFirstEntry);
       }
@@ -19916,7 +20641,7 @@ var Font = (function FontClosure() {
       var cidEncoding = properties.cidEncoding;
       if (properties.toUnicode) {
         if (cidEncoding && cidEncoding.indexOf('Identity-') !== 0) {
-          TODO('Need to create a reverse mapping from \'ToUnicode\' CMap');
+          warn('Need to create a reverse mapping from \'ToUnicode\' CMap');
         }
         return; // 'ToUnicode' CMap will be used
       }
@@ -20174,8 +20899,10 @@ var Font = (function FontClosure() {
           var glyph = this.charToGlyph(charcode);
           glyphs.push(glyph);
           // placing null after each word break charcode (ASCII SPACE)
-          if (charcode == 0x20)
+          // Ignore occurences of 0x20 in multiple-byte codes.
+          if (length === 1 && chars.charCodeAt(i - 1) === 0x20) {
             glyphs.push(null);
+          }
         }
       }
       else {
@@ -20817,13 +21544,21 @@ var Type1Parser = (function Type1ParserClosure() {
 
               for (var j = 0; j < size; j++) {
                 var token = this.getToken();
-                if (token === 'dup') {
-                  var index = this.readInt();
-                  this.getToken(); // read in '/'
-                  var glyph = this.getToken();
-                  encoding[index] = glyph;
-                  this.getToken(); // read the in 'put'
+                // skipping till first dup or def (e.g. ignoring for statement)
+                while (token !== 'dup' && token !== 'def') {
+                  token = this.getToken();
+                  if (token === null) {
+                    return; // invalid header
+                  }
+                }
+                if (token === 'def') {
+                  break; // read all array data
                 }
+                var index = this.readInt();
+                this.getToken(); // read in '/'
+                var glyph = this.getToken();
+                encoding[index] = glyph;
+                this.getToken(); // read the in 'put'
               }
             }
             if (properties.overridableEncoding && encoding) {
@@ -20831,6 +21566,13 @@ var Type1Parser = (function Type1ParserClosure() {
               break;
             }
             break;
+          case 'FontBBox':
+            var fontBBox = this.readNumberArray();
+            // adjusting ascent/descent
+            properties.ascent = fontBBox[3];
+            properties.descent = fontBBox[1];
+            properties.ascentScaled = true;
+            break;
         }
       }
     }
@@ -20913,13 +21655,33 @@ var CFFStandardStrings = [
 
 // Type1Font is also a CIDFontType0.
 var Type1Font = function Type1Font(name, file, properties) {
+  // Some bad generators embed pfb file as is, we have to strip 6-byte headers.
+  // Also, length1 and length2 might be off by 6 bytes as well.
+  // http://www.math.ubc.ca/~cass/piscript/type1.pdf
+  var PFB_HEADER_SIZE = 6;
+  var headerBlockLength = properties.length1;
+  var eexecBlockLength = properties.length2;
+  var pfbHeader = file.peekBytes(PFB_HEADER_SIZE);
+  var pfbHeaderPresent = pfbHeader[0] == 0x80 && pfbHeader[1] == 0x01;
+  if (pfbHeaderPresent) {
+    file.skip(PFB_HEADER_SIZE);
+    headerBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
+                        (pfbHeader[3] << 8) | pfbHeader[2];
+  }
+
   // Get the data block containing glyphs and subrs informations
-  var headerBlock = new Stream(file.getBytes(properties.length1));
+  var headerBlock = new Stream(file.getBytes(headerBlockLength));
   var headerBlockParser = new Type1Parser(headerBlock);
   headerBlockParser.extractFontHeader(properties);
 
+  if (pfbHeaderPresent) {
+    pfbHeader = file.getBytes(PFB_HEADER_SIZE);
+    eexecBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
+                       (pfbHeader[3] << 8) | pfbHeader[2];
+  }
+
   // Decrypt the data blocks and retrieve it's content
-  var eexecBlock = new Stream(file.getBytes(properties.length2));
+  var eexecBlock = new Stream(file.getBytes(eexecBlockLength));
   var eexecBlockParser = new Type1Parser(eexecBlock, true);
   var data = eexecBlockParser.extractFontProgram();
   for (var info in data.properties)
@@ -21151,6 +21913,9 @@ var CFFFont = (function CFFFontClosure() {
       var unassignedUnicodeItems = [];
       var inverseEncoding = [];
       var gidStart = 0;
+      if (charsets[0] === '.notdef') {
+        gidStart = 1;
+      }
       // According to section 9.7.4.2 CIDFontType0C glyph selection should be
       // handled differently.
       if (this.properties.subtype === 'CIDFontType0C') {
@@ -21183,9 +21948,6 @@ var CFFFont = (function CFFFontClosure() {
             inverseEncoding[gid] = charcode | 0;
           }
         }
-        if (charsets[0] === '.notdef') {
-          gidStart = 1;
-        }
       }
 
       for (var i = gidStart, ii = charsets.length; i < ii; i++) {
@@ -27560,7 +28322,7 @@ var PDFImage = (function PDFImageClosure() {
     if (image.getParams) {
       // JPX/JPEG2000 streams directly contain bits per component
       // and color space mode information.
-      TODO('get params from actual stream');
+      warn('get params from actual stream');
       // var bits = ...
       // var colorspace = ...
     }
@@ -27593,7 +28355,7 @@ var PDFImage = (function PDFImageClosure() {
     if (!this.imageMask) {
       var colorSpace = dict.get('ColorSpace', 'CS');
       if (!colorSpace) {
-        TODO('JPX images (which don"t require color spaces');
+        warn('JPX images (which don"t require color spaces');
         colorSpace = new Name('DeviceRGB');
       }
       this.colorSpace = ColorSpace.parse(colorSpace, xref, res);
@@ -27635,9 +28397,9 @@ var PDFImage = (function PDFImageClosure() {
    */
   PDFImage.buildImage = function PDFImage_buildImage(callback, handler, xref,
                                                      res, image, inline) {
-    var imageDataPromise = new Promise();
-    var smaskPromise = new Promise();
-    var maskPromise = new Promise();
+    var imageDataPromise = new LegacyPromise();
+    var smaskPromise = new LegacyPromise();
+    var maskPromise = new LegacyPromise();
     // The image data and smask data may not be ready yet, wait till both are
     // resolved.
     Promise.all([imageDataPromise, smaskPromise, maskPromise]).then(
@@ -27715,26 +28477,21 @@ var PDFImage = (function PDFImageClosure() {
 
   PDFImage.createMask = function PDFImage_createMask(imgArray, width, height,
                                                      inverseDecode) {
-    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};
+    // 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};
   };
 
   PDFImage.prototype = {
@@ -30963,21 +31720,6 @@ var Parser = (function ParserClosure() {
   }
 
   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();
@@ -32182,12 +32924,18 @@ var FlateStream = (function FlateStreamClosure() {
       var buffer = this.ensureBuffer(bufferLength + blockLen);
       var end = bufferLength + blockLen;
       this.bufferLength = end;
-      for (var n = bufferLength; n < end; ++n) {
-        if (typeof (b = bytes[bytesPos++]) == 'undefined') {
+      if (blockLen === 0) {
+        if (typeof bytes[bytesPos] == 'undefined') {
           this.eof = true;
-          break;
         }
-        buffer[n] = b;
+      } else {
+        for (var n = bufferLength; n < end; ++n) {
+          if (typeof (b = bytes[bytesPos++]) == 'undefined') {
+            this.eof = true;
+            break;
+          }
+          buffer[n] = b;
+        }
       }
       this.bytesPos = bytesPos;
       return;
@@ -32506,7 +33254,7 @@ var JpegStream = (function JpegStreamClosure() {
     }
   };
   JpegStream.prototype.getIR = function JpegStream_getIR() {
-    return bytesToString(this.bytes);
+    return PDFJS.createObjectURL(this.bytes, 'image/jpeg');
   };
   /**
    * Checks if the image can be decoded and displayed by the browser without any
@@ -32650,6 +33398,16 @@ var Jbig2Stream = (function Jbig2StreamClosure() {
     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();
@@ -34002,7 +34760,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
     var pdfManager;
 
     function loadDocument(recoveryMode) {
-      var loadDocumentPromise = new Promise();
+      var loadDocumentPromise = new LegacyPromise();
 
       var parseSuccess = function parseSuccess() {
         var numPagesPromise = pdfManager.ensureModel('numPages');
@@ -34046,7 +34804,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
     }
 
     function getPdfManager(data) {
-      var pdfManagerPromise = new Promise();
+      var pdfManagerPromise = new LegacyPromise();
 
       var source = data.source;
       var disableRange = data.disableRange;
@@ -34069,7 +34827,8 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
       }
 
       var networkManager = new NetworkManager(source.url, {
-        httpHeaders: source.httpHeaders
+        httpHeaders: source.httpHeaders,
+        withCredentials: source.withCredentials
       });
       var fullRequestXhrId = networkManager.requestFull({
         onHeadersReceived: function onHeadersReceived() {
@@ -34148,6 +34907,9 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
         handler.send('test', false);
         return;
       }
+      // making sure postMessage transfers are working
+      var supportTransfers = data[0] === 255;
+      handler.postMessageTransfers = supportTransfers;
       // check if the response property is supported by xhr
       var xhr = new XMLHttpRequest();
       var responseExists = 'response' in xhr;
@@ -34161,14 +34923,16 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
         handler.send('test', false);
         return;
       }
-      handler.send('test', true);
+      handler.send('test', {
+        supportTypedArray: true,
+        supportTransfers: supportTransfers
+      });
     });
 
     handler.on('GetDocRequest', function wphSetupDoc(data) {
 
       var onSuccess = function(doc) {
         handler.send('GetDoc', { pdfInfo: doc });
-        pdfManager.ensureModel('traversePages', []).then(null, onFailure);
       };
 
       var onFailure = function(e) {
@@ -34200,6 +34964,8 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
       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) {
@@ -34208,7 +34974,8 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
             if (ex instanceof PasswordException) {
               // after password exception prepare to receive a new password
               // to repeat loading
-              pdfManager.passwordChangedPromise = new Promise();
+              pdfManager.passwordChangedPromise =
+                new LegacyPromise();
               pdfManager.passwordChangedPromise.then(pdfManagerReady);
             }
 
@@ -34245,24 +35012,31 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
       });
     });
 
+    handler.on('GetPageIndex', function wphSetupGetPageIndex(data, deferred) {
+      var ref = new Ref(data.ref.num, data.ref.gen);
+      pdfManager.pdfModel.catalog.getPageIndex(ref).then(function (pageIndex) {
+        deferred.resolve(pageIndex);
+      }, deferred.reject);
+    });
+
     handler.on('GetDestinations',
-      function wphSetupGetDestinations(data, promise) {
+      function wphSetupGetDestinations(data, deferred) {
         pdfManager.ensureCatalog('destinations').then(function(destinations) {
-          promise.resolve(destinations);
+          deferred.resolve(destinations);
         });
       }
     );
 
-    handler.on('GetData', function wphSetupGetData(data, promise) {
+    handler.on('GetData', function wphSetupGetData(data, deferred) {
       pdfManager.requestLoadedStream();
       pdfManager.onLoadedStream().then(function(stream) {
-        promise.resolve(stream.bytes);
+        deferred.resolve(stream.bytes);
       });
     });
 
-    handler.on('DataLoaded', function wphSetupDataLoaded(data, promise) {
+    handler.on('DataLoaded', function wphSetupDataLoaded(data, deferred) {
       pdfManager.onLoadedStream().then(function(stream) {
-        promise.resolve({ length: stream.bytes.byteLength });
+        deferred.resolve({ length: stream.bytes.byteLength });
       });
     });
 
@@ -34291,7 +35065,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
         // Pre compile the pdf page and fetch the fonts/images.
         page.getOperatorList(handler).then(function(operatorList) {
 
-          log('page=%d - getOperatorList: time=%dms, len=%d', pageNum,
+          info('page=%d - getOperatorList: time=%dms, len=%d', pageNum,
               Date.now() - start, operatorList.fnArray.length);
 
         }, function(e) {
@@ -34327,24 +35101,29 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
       });
     }, this);
 
-    handler.on('GetTextContent', function wphExtractText(data, promise) {
+    handler.on('GetTextContent', function wphExtractText(data, deferred) {
       pdfManager.getPage(data.pageIndex).then(function(page) {
         var pageNum = data.pageIndex + 1;
         var start = Date.now();
         page.extractTextContent().then(function(textContent) {
-          promise.resolve(textContent);
-          log('text indexing: page=%d - time=%dms', pageNum,
+          deferred.resolve(textContent);
+          info('text indexing: page=%d - time=%dms', pageNum,
               Date.now() - start);
         }, function (e) {
           // Skip errored pages
-          promise.reject(e);
+          deferred.reject(e);
         });
       });
     });
 
-    handler.on('Terminate', function wphTerminate(data, promise) {
+    handler.on('Cleanup', function wphCleanup(data, deferred) {
+      pdfManager.cleanup();
+      deferred.resolve(true);
+    });
+
+    handler.on('Terminate', function wphTerminate(data, deferred) {
       pdfManager.terminate();
-      promise.resolve();
+      deferred.resolve();
     });
   }
 };
@@ -34376,25 +35155,25 @@ var workerConsole = {
   timeEnd: function timeEnd(name) {
     var time = consoleTimer[name];
     if (!time) {
-      error('Unkown timer name ' + name);
+      error('Unknown timer name ' + name);
     }
     this.log('Timer:', name, Date.now() - time);
   }
 };
 
+
 // Worker thread?
 if (typeof window === 'undefined') {
-  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
-      });
-    }
+  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
+    });
   });
 
   var handler = new MessageHandler('worker_processor', this);
@@ -36076,6 +36855,19 @@ var JpxImage = (function JpxImageClosure() {
       }
       return ll;
     };
+    Transform.prototype.expand = function expand(buffer, bufferPadding, step) {
+        // Section F.3.7 extending... using max extension of 4
+        var i1 = bufferPadding - 1, j1 = bufferPadding + 1;
+        var i2 = bufferPadding + step - 2, j2 = bufferPadding + step;
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+    };
     Transform.prototype.iterate = function Transform_iterate(ll, hl, lh, hh,
                                                             u0, v0) {
       var llWidth = ll.width, llHeight = ll.height, llItems = ll.items;
@@ -36129,18 +36921,7 @@ var JpxImage = (function JpxImageClosure() {
         for (var u = 0; u < width; u++, k++, l++)
           buffer[l] = items[k];
 
-        // Section F.3.7 extending... using max extension of 4
-        var i1 = bufferPadding - 1, j1 = bufferPadding + 1;
-        var i2 = bufferPadding + width - 2, j2 = bufferPadding + width;
-        buffer[i1--] = buffer[j1++];
-        buffer[j2++] = buffer[i2--];
-        buffer[i1--] = buffer[j1++];
-        buffer[j2++] = buffer[i2--];
-        buffer[i1--] = buffer[j1++];
-        buffer[j2++] = buffer[i2--];
-        buffer[i1--] = buffer[j1++];
-        buffer[j2++] = buffer[i2--];
-
+        this.expand(buffer, bufferPadding, width);
         this.filter(buffer, bufferPadding, width, u0, bufferOut);
 
         k = v * width;
@@ -36164,18 +36945,7 @@ var JpxImage = (function JpxImageClosure() {
         for (var v = 0; v < height; v++, k += width, l++)
           buffer[l] = items[k];
 
-        // Section F.3.7 extending... using max extension of 4
-        var i1 = bufferPadding - 1, j1 = bufferPadding + 1;
-        var i2 = bufferPadding + height - 2, j2 = bufferPadding + height;
-        buffer[i1--] = buffer[j1++];
-        buffer[j2++] = buffer[i2--];
-        buffer[i1--] = buffer[j1++];
-        buffer[j2++] = buffer[i2--];
-        buffer[i1--] = buffer[j1++];
-        buffer[j2++] = buffer[i2--];
-        buffer[i1--] = buffer[j1++];
-        buffer[j2++] = buffer[i2--];
-
+        this.expand(buffer, bufferPadding, height);
         this.filter(buffer, bufferPadding, height, v0, bufferOut);
 
         k = u;
diff --git a/plugins/pdfviewer/viewer/viewer.css b/plugins/pdfviewer/viewer/viewer.css
index 1b36776..9c31d6a 100644
--- a/plugins/pdfviewer/viewer/viewer.css
+++ b/plugins/pdfviewer/viewer/viewer.css
@@ -20,6 +20,8 @@
 
 html {
   height: 100%;
+  /* Font size is needed to make the activity bar the correct size. */
+  font-size: 10px;
 }
 
 body {
@@ -45,8 +47,7 @@ select {
 #viewerContainer:-webkit-full-screen {
   top: 0px;
   border-top: 2px solid transparent;
-  background-color: #404040;
-  background-image: url(images/texture.png);
+  background-color: #000;
   width: 100%;
   height: 100%;
   overflow: hidden;
@@ -56,8 +57,7 @@ select {
 #viewerContainer:-moz-full-screen {
   top: 0px;
   border-top: 2px solid transparent;
-  background-color: #404040;
-  background-image: url(images/texture.png);
+  background-color: #000;
   width: 100%;
   height: 100%;
   overflow: hidden;
@@ -74,15 +74,13 @@ select {
 }
 
 #viewerContainer:-ms-fullscreen::-ms-backdrop {
-  background-color: #404040;
-  background-image: url(images/texture.png);
+  background-color: #000;
 }
 
 #viewerContainer:fullscreen {
   top: 0px;
   border-top: 2px solid transparent;
-  background-color: #404040;
-  background-image: url(images/texture.png);
+  background-color: #000;
   width: 100%;
   height: 100%;
   overflow: hidden;
@@ -167,6 +165,7 @@ html[dir='rtl'] .innerCenter {
 #outerContainer {
   width: 100%;
   height: 100%;
+  position: relative;
 }
 
 #sidebarContainer {
@@ -400,6 +399,7 @@ html[dir='rtl'] .secondaryToolbar {
   max-width: 200px;
   max-height: 400px;
   overflow-y: auto;
+  margin-bottom: -4px;
 }
 
 .doorHanger,
@@ -894,20 +894,25 @@ html[dir="rtl"] .secondaryToolbarButton.print::before {
   content: url(images/toolbarButton-download.png);
 }
 
-.toolbarButton.bookmark {
+.toolbarButton.bookmark,
+.secondaryToolbarButton.bookmark {
   -webkit-box-sizing: border-box;
   -moz-box-sizing: border-box;
   box-sizing: border-box;
-  margin-top: 3px;
   padding-top: 4px;
+  text-decoration: none;
+}
+.secondaryToolbarButton.bookmark {
+  padding-top: 5px;
 }
 
-#viewBookmark[href='#'] {
+.bookmark[href='#'] {
   opacity: .5;
   pointer-events: none;
 }
 
-.toolbarButton.bookmark::before {
+.toolbarButton.bookmark::before,
+.secondaryToolbarButton.bookmark::before {
   content: url(images/toolbarButton-bookmark.png);
 }
 
@@ -944,9 +949,11 @@ html[dir="rtl"] .secondaryToolbarButton {
   padding-right: 24px;
   text-align: right;
 }
-
-#secondaryToolbarButtonContainer :last-child {
-  margin-bottom: 0;
+html[dir="ltr"] .secondaryToolbarButton.bookmark {
+  padding-left: 27px;
+}
+html[dir="rtl"] .secondaryToolbarButton.bookmark {
+  padding-right: 27px;
 }
 
 html[dir="ltr"] .secondaryToolbarButton > span {
@@ -972,6 +979,10 @@ html[dir="rtl"] .secondaryToolbarButton > span {
   content: url(images/secondaryToolbarButton-rotateCw.png);
 }
 
+.secondaryToolbarButton.handTool::before {
+  content: url(images/secondaryToolbarButton-handTool.png);
+}
+
 .verticalToolbarSeparator {
   display: block;
   padding: 8px 0;
@@ -1023,6 +1034,7 @@ html[dir='rtl'] .verticalToolbarSeparator {
 }
 
 .toolbarField.pageNumber {
+  -moz-appearance: textfield; /* hides the spinner in moz */
   min-width: 16px;
   text-align: right;
   width: 40px;
@@ -1070,6 +1082,11 @@ html[dir='rtl'] .verticalToolbarSeparator {
 
 .thumbnail {
   float: left;
+  margin-bottom: 5px;
+}
+
+#thumbnailView > a:last-of-type > .thumbnail {
+  margin-bottom: 10px;
 }
 
 .thumbnail:not([data-loaded]) {
@@ -1190,22 +1207,6 @@ html[dir='rtl'] .outlineItem > a {
   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;
 }
@@ -1417,6 +1418,10 @@ canvas {
   background: white;
   color: black;
   margin-top: 5px;
+  visibility: hidden;
+  position: fixed;
+  right: 0;
+  top: 0;
 }
 
 #PDFBug {
@@ -1478,6 +1483,32 @@ canvas {
   color: black;
 }
 
+.grab-to-pan-grab * {
+  cursor: url("images/grab.cur"), move !important;
+  cursor: -webkit-grab !important;
+  cursor: -moz-grab !important;
+  cursor: grab !important;
+}
+.grab-to-pan-grabbing,
+.grab-to-pan-grabbing * {
+  cursor: url("images/grabbing.cur"), move !important;
+  cursor: -webkit-grabbing !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;
 }
diff --git a/plugins/pdfviewer/viewer/viewer.html b/plugins/pdfviewer/viewer/viewer.html
index 7608f1a..f91077a 100644
--- a/plugins/pdfviewer/viewer/viewer.html
+++ b/plugins/pdfviewer/viewer/viewer.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html>
 <!--
 Copyright 2012 Mozilla Foundation
 
@@ -31,12 +31,12 @@ limitations under the License.
 <!-- This snippet is used in production, see Makefile -->
 <link rel="resource" type="application/l10n" href="locale/locale.properties"/>
 <script type="text/javascript" src="l10n.js"></script>
-<script type="text/javascript" src="pdf.js"></script>
+<script type="text/javascript" src="pdf.min.js"></script>
 
 
 
     <script type="text/javascript" src="debugger.js"></script>
-    <script type="text/javascript" src="viewer.js"></script>
+    <script type="text/javascript" src="viewer.min.js"></script>
 
   </head>
 
@@ -88,27 +88,45 @@ limitations under the License.
               <span data-l10n-id="presentation_mode_label">Presentation Mode</span>
             </button>
 
+            <button id="secondaryOpenFile" class="secondaryToolbarButton openFile hidden" title="Open File" tabindex="19" data-l10n-id="open_file">
+              <span data-l10n-id="open_file_label">Open</span>
+            </button>
+
             <button id="secondaryPrint" class="secondaryToolbarButton print visibleMediumView" title="Print" tabindex="20" data-l10n-id="print">
               <span data-l10n-id="print_label">Print</span>
             </button>
 
+            <button id="secondaryDownload" class="secondaryToolbarButton download hidden" title="Download" tabindex="21" data-l10n-id="download">
+              <span data-l10n-id="download_label">Download</span>
+            </button>
+
+            <a href="#" id="secondaryViewBookmark" class="secondaryToolbarButton bookmark hidden" title="Current view (copy or open in new window)" tabindex="22" data-l10n-id="bookmark">
+              <span data-l10n-id="bookmark_label">Current View</span>
+            </a>
+
             <div class="horizontalToolbarSeparator visibleLargeView"></div>
 
-            <button id="firstPage" class="secondaryToolbarButton firstPage" title="Go to First Page" tabindex="22" data-l10n-id="first_page">
+            <button id="firstPage" class="secondaryToolbarButton firstPage" title="Go to First Page" tabindex="23" data-l10n-id="first_page">
               <span data-l10n-id="first_page_label">Go to First Page</span>
             </button>
-            <button id="lastPage" class="secondaryToolbarButton lastPage" title="Go to Last Page" tabindex="23" data-l10n-id="last_page">
+            <button id="lastPage" class="secondaryToolbarButton lastPage" title="Go to Last Page" tabindex="24" data-l10n-id="last_page">
               <span data-l10n-id="last_page_label">Go to Last Page</span>
             </button>
 
             <div class="horizontalToolbarSeparator"></div>
 
-            <button id="pageRotateCw" class="secondaryToolbarButton rotateCw" title="Rotate Clockwise" tabindex="24" data-l10n-id="page_rotate_cw">
+            <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="25" data-l10n-id="page_rotate_ccw">
+            <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>
         </div>  <!-- secondaryToolbar -->
 
@@ -134,7 +152,6 @@ limitations under the License.
                 </div>
                 <label id="pageNumberLabel" class="toolbarLabel" for="pageNumber" data-l10n-id="page_label">Page: </label>
                 <input type="number" id="pageNumber" class="toolbarField pageNumber" value="1" size="4" min="1" tabindex="8">
-                </input>
                 <span id="numPages" class="toolbarLabel"></span>
               </div>
               <div id="toolbarViewerRight">
@@ -142,10 +159,22 @@ limitations under the License.
                   <span data-l10n-id="presentation_mode_label">Presentation Mode</span>
                 </button>
 
+                <button id="openFile" class="toolbarButton openFile hidden" title="Open File" tabindex="13" data-l10n-id="open_file">
+                  <span data-l10n-id="open_file_label">Open</span>
+                </button>
+
                 <button id="print" class="toolbarButton print hiddenMediumView" title="Print" tabindex="14" data-l10n-id="print">
                   <span data-l10n-id="print_label">Print</span>
                 </button>
 
+                <button id="download" class="toolbarButton download hidden" title="Download" tabindex="15" data-l10n-id="download">
+                  <span data-l10n-id="download_label">Download</span>
+                </button>
+                <!-- <div class="toolbarButtonSpacer"></div> -->
+                <a href="#" id="viewBookmark" class="toolbarButton bookmark hidden" title="Current view (copy or open in new window)" tabindex="16" data-l10n-id="bookmark">
+                  <span data-l10n-id="bookmark_label">Current View</span>
+                </a>
+
                 <div class="verticalToolbarSeparator hiddenSmallView"></div>
                 
                 <button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="17" data-l10n-id="tools">
@@ -244,6 +273,78 @@ limitations under the License.
 
     </div> <!-- outerContainer -->
     <div id="printContainer"></div>
+<div id="mozPrintCallback-shim" hidden>
+  <style scoped>
+#mozPrintCallback-shim {
+  position: fixed;
+  top: 0;
+  left: 0;
+  height: 100%;
+  width: 100%;
+  z-index: 9999999;
+
+  display: block;
+  text-align: center;
+  background-color: rgba(0, 0, 0, 0.5);
+}
+#mozPrintCallback-shim[hidden] {
+  display: none;
+}
+ at media print {
+  #mozPrintCallback-shim {
+    display: none;
+  }
+}
+
+#mozPrintCallback-shim .mozPrintCallback-dialog-box {
+  display: inline-block;
+  margin: -50px auto 0;
+  position: relative;
+  top: 45%;
+  left: 0;
+  min-width: 220px;
+  max-width: 400px;
+
+  padding: 9px;
+
+  border: 1px solid hsla(0, 0%, 0%, .5);
+  border-radius: 2px;
+  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
+
+  background-color: #474747;
+
+  color: hsl(0, 0%, 85%);
+  font-size: 16px;
+  line-height: 20px;
+}
+#mozPrintCallback-shim .progress-row {
+  clear: both;
+  padding: 1em 0;
+}
+#mozPrintCallback-shim progress {
+  width: 100%;
+}
+#mozPrintCallback-shim .relative-progress {
+  clear: both;
+  float: right;
+}
+#mozPrintCallback-shim .progress-actions {
+  clear: both;
+}
+  </style>
+  <div class="mozPrintCallback-dialog-box">
+    <!-- TODO: Localise the following strings -->
+    Preparing document for printing...
+    <div class="progress-row">
+      <progress value="0" max="100"></progress>
+      <span class="relative-progress">0%</span>
+    </div>
+    <div class="progress-actions">
+      <input type="button" value="Cancel" class="mozPrintCallback-cancel">
+    </div>
+  </div>
+</div>
+
   </body>
 </html>
 
diff --git a/plugins/pdfviewer/viewer/viewer.js b/plugins/pdfviewer/viewer/viewer.js
index 8500af4..b94a444 100644
--- a/plugins/pdfviewer/viewer/viewer.js
+++ b/plugins/pdfviewer/viewer/viewer.js
@@ -1,93 +1,5449 @@
-var DEFAULT_URL=null,DEFAULT_SCALE="auto",DEFAULT_SCALE_DELTA=1.1,UNKNOWN_SCALE=0,CACHE_SIZE=20,CSS_UNITS=96/72,SCROLLBAR_PADDING=40,VERTICAL_PADDING=5,MIN_SCALE=0.25,MAX_SCALE=4,IMAGE_DIR="./images/",SETTINGS_MEMORY=20,ANNOT_MIN_SIZE=10,RenderingStates={INITIAL:0,RUNNING:1,PAUSED:2,FINISHED:3},FindStates={FIND_FOUND:0,FIND_NOTFOUND:1,FIND_WRAPPED:2,FIND_PENDING:3};PDFJS.workerSrc="pdf.js";var mozL10n=document.mozL10n||document.webL10n;
-function getFileName(a){var b=a.indexOf("#"),c=a.indexOf("?"),b=Math.min(0<b?b:a.length,0<c?c:a.length);return a.substring(a.lastIndexOf("/",b)+1,b)}function scrollIntoView(a,b){for(var c=a.offsetParent,d=a.offsetTop;c.clientHeight==c.scrollHeight;)if(d+=c.offsetTop,c=c.offsetParent,!c)return;b&&(d+=b.top);c.scrollTop=d}
-var Cache=function(a){var b=[];this.push=function(c){var d=b.indexOf(c);0<=d&&b.splice(d);b.push(c);b.length>a&&b.shift().destroy()}},ProgressBar=function(){function a(a,c){this.div=document.querySelector(a+" .progress");this.height=c.height||100;this.width=c.width||100;this.units=c.units||"%";this.div.style.height=this.height+this.units}a.prototype={updateBar:function(){if(this._indeterminate)this.div.classList.add("indeterminate");else{var a=this.width*this._percent/100;95<this._percent?this.div.classList.add("full"):
-this.div.classList.remove("full");this.div.classList.remove("indeterminate");this.div.style.width=a+this.units}},get percent(){return this._percent},set percent(a){this._indeterminate=isNaN(a);this._percent=Math.min(Math.max(a,0),100);this.updateBar()}};return a}(),Settings=function(){function a(a){this.fingerprint=a;this.initializedPromise=new PDFJS.Promise;a=function(a){this.initialize(a||"{}");this.initializedPromise.resolve()}.bind(this);b&&a(localStorage.getItem("database"))}var b;try{b="localStorage"in
-window&&null!==window.localStorage&&localStorage}catch(c){b=!1}a.prototype={initialize:function(a){a=JSON.parse(a);"files"in a||(a.files=[]);a.files.length>=SETTINGS_MEMORY&&a.files.shift();for(var b,c=0,e=a.files.length;c<e;c++)if(a.files[c].fingerprint==this.fingerprint){b=c;break}"number"!=typeof b&&(b=a.files.push({fingerprint:this.fingerprint})-1);this.file=a.files[b];this.database=a},set:function(a,c){if(this.initializedPromise.isResolved){this.file[a]=c;var h=JSON.stringify(this.database);
-b&&localStorage.setItem("database",h)}},get:function(a,b){return this.initializedPromise.isResolved?this.file[a]||b:b}};return a}(),cache=new Cache(CACHE_SIZE),currentPageNumber=1,PDFFindController={startedTextExtraction:!1,extractTextPromises:[],active:!1,pageContents:[],pageMatches:[],selected:{pageIdx:-1,matchIdx:-1},offset:{pageIdx:null,matchIdx:null},resumePageIdx:null,resumeCallback:null,state:null,dirtyMatch:!1,findTimeout:null,initialize:function(){var a=["find","findagain","findhighlightallchange",
-"findcasesensitivitychange"];this.handleEvent=this.handleEvent.bind(this);for(var b=0;b<a.length;b++)window.addEventListener(a[b],this.handleEvent)},calcFindMatch:function(a){var b=this.pageContents[a],c=this.state.query,d=this.state.caseSensitive,f=c.length;if(0!==f){d||(b=b.toLowerCase(),c=c.toLowerCase());for(var d=[],h=-f;;){h=b.indexOf(c,h+f);if(-1===h)break;d.push(h)}this.pageMatches[a]=d;this.updatePage(a);this.resumePageIdx===a&&(a=this.resumeCallback,this.resumeCallback=this.resumePageIdx=
-null,a())}},extractText:function(){function a(b){PDFView.pages[b].getTextContent().then(function(c){c=c.bidiTexts;for(var e="",g=0;g<c.length;g++)e+=c[g].str;d.pageContents.push(e);d.extractTextPromises[b].resolve(b);b+1<PDFView.pages.length&&a(b+1)})}if(!this.startedTextExtraction){this.startedTextExtraction=!0;this.pageContents=[];for(var b=0,c=PDFView.pdfDocument.numPages;b<c;b++)this.extractTextPromises.push(new PDFJS.Promise);var d=this;a(0);return this.extractTextPromise}},handleEvent:function(a){if(null===
-this.state||"findagain"!==a.type)this.dirtyMatch=!0;this.state=a.detail;this.updateUIState(FindStates.FIND_PENDING);this.extractText();clearTimeout(this.findTimeout);"find"===a.type?this.findTimeout=setTimeout(this.nextMatch.bind(this),250):this.nextMatch()},updatePage:function(a){var b=PDFView.pages[a];this.selected.pageIdx===a&&b.scrollIntoView();b.textLayer&&b.textLayer.updateMatches()},nextMatch:function(){var a=this.state.findPrevious,b=PDFView.pages.length;this.active=!0;if(this.dirtyMatch){this.dirtyMatch=
-!1;this.selected.pageIdx=this.selected.matchIdx=-1;this.offset.pageIdx=a?b-1:0;this.offset.matchIdx=null;this.hadMatch=!1;this.resumePageIdx=this.resumeCallback=null;this.pageMatches=[];for(var c=this,d=0;d<b;d++)this.updatePage(d),this.extractTextPromises[d].onData(function(a){setTimeout(function(){c.calcFindMatch(a)})})}if(""===this.state.query)this.updateUIState(FindStates.FIND_FOUND);else if(!this.resumeCallback){b=this.offset;if(null!==b.matchIdx){d=this.pageMatches[b.pageIdx].length;if(!a&&
-b.matchIdx+1<d||a&&0<b.matchIdx){this.hadMatch=!0;b.matchIdx=a?b.matchIdx-1:b.matchIdx+1;this.updateMatch(!0);return}this.advanceOffsetPage(a)}this.nextPageMatch()}},nextPageMatch:function(){null!==this.resumePageIdx&&console.error("There can only be one pending page.");var a=function(a){var b=this.offset;a=a.length;var c=this.state.findPrevious;if(a)this.hadMatch=!0,b.matchIdx=c?a-1:0,this.updateMatch(!0);else{this.advanceOffsetPage(c);if(b.wrapped&&(b.matchIdx=null,!this.hadMatch)){this.updateMatch(!1);
-return}this.nextPageMatch()}}.bind(this),b=this.offset.pageIdx,c=this.pageMatches;c[b]?a(c[b]):(this.resumeCallback=function(){a(c[b])},this.resumePageIdx=b)},advanceOffsetPage:function(a){var b=this.offset,c=this.extractTextPromises.length;b.pageIdx=a?b.pageIdx-1:b.pageIdx+1;b.matchIdx=null;if(b.pageIdx>=c||0>b.pageIdx)b.pageIdx=a?c-1:0,b.wrapped=!0},updateMatch:function(a){var b=FindStates.FIND_NOTFOUND,c=this.offset.wrapped;this.offset.wrapped=!1;a&&(a=this.selected.pageIdx,this.selected.pageIdx=
-this.offset.pageIdx,this.selected.matchIdx=this.offset.matchIdx,b=c?FindStates.FIND_WRAPPED:FindStates.FIND_FOUND,-1!==a&&a!==this.selected.pageIdx&&this.updatePage(a));this.updateUIState(b,this.state.findPrevious);-1!==this.selected.pageIdx&&this.updatePage(this.selected.pageIdx,!0)},updateUIState:function(a,b){PDFView.supportsIntegratedFind?FirefoxCom.request("updateFindControlState",{result:a,findPrevious:b}):PDFFindBar.updateUIState(a,b)}},PDFFindBar={opened:!1,initialize:function(){this.bar=
-document.getElementById("findbar");this.toggleButton=document.getElementById("viewFind");this.findField=document.getElementById("findInput");this.highlightAll=document.getElementById("findHighlightAll");this.caseSensitive=document.getElementById("findMatchCase");this.findMsg=document.getElementById("findMsg");this.findStatusIcon=document.getElementById("findStatusIcon");var a=this;this.toggleButton.addEventListener("click",function(){a.toggle()});this.findField.addEventListener("input",function(){a.dispatchEvent("")});
-this.bar.addEventListener("keydown",function(b){switch(b.keyCode){case 13:b.target===a.findField&&a.dispatchEvent("again",b.shiftKey);break;case 27:a.close()}});document.getElementById("findPrevious").addEventListener("click",function(){a.dispatchEvent("again",!0)});document.getElementById("findNext").addEventListener("click",function(){a.dispatchEvent("again",!1)});this.highlightAll.addEventListener("click",function(){a.dispatchEvent("highlightallchange")});this.caseSensitive.addEventListener("click",
-function(){a.dispatchEvent("casesensitivitychange")})},dispatchEvent:function(a,b){var c=document.createEvent("CustomEvent");c.initCustomEvent("find"+a,!0,!0,{query:this.findField.value,caseSensitive:this.caseSensitive.checked,highlightAll:this.highlightAll.checked,findPrevious:b});return window.dispatchEvent(c)},updateUIState:function(a,b){var c=!1,d="",f="";switch(a){case FindStates.FIND_PENDING:f="pending";break;case FindStates.FIND_NOTFOUND:d=mozL10n.get("find_not_found",null,"Phrase not found");
-c=!0;break;case FindStates.FIND_WRAPPED:d=b?mozL10n.get("find_reached_top",null,"Reached top of document, continued from bottom"):mozL10n.get("find_reached_bottom",null,"Reached end of document, continued from top")}c?this.findField.classList.add("notFound"):this.findField.classList.remove("notFound");this.findField.setAttribute("data-status",f);this.findMsg.textContent=d},open:function(){this.opened||(this.opened=!0,this.toggleButton.classList.add("toggled"),this.bar.classList.remove("hidden"),this.findField.select(),
-this.findField.focus())},close:function(){this.opened&&(this.opened=!1,this.toggleButton.classList.remove("toggled"),this.bar.classList.add("hidden"),PDFFindController.active=!1)},toggle:function(){this.opened?this.close():this.open()}},PDFView={pages:[],thumbnails:[],currentScale:UNKNOWN_SCALE,currentScaleValue:null,initialBookmark:document.location.hash.substring(1),startedTextExtraction:!1,pageText:[],container:null,thumbnailContainer:null,initialized:!1,fellback:!1,pdfDocument:null,sidebarOpen:!1,
-pageViewScroll:null,thumbnailViewScroll:null,isFullscreen:!1,previousScale:null,pageRotation:0,mouseScrollTimeStamp:0,mouseScrollDelta:0,lastScroll:0,previousPageNumber:1,initialize:function(){var a=this,b=this.container=document.getElementById("viewerContainer");this.pageViewScroll={};this.watchScroll(b,this.pageViewScroll,updateViewarea);var c=this.thumbnailContainer=document.getElementById("thumbnailView");this.thumbnailViewScroll={};this.watchScroll(c,this.thumbnailViewScroll,this.renderHighestPriority.bind(this));
-PDFFindBar.initialize();PDFFindController.initialize();this.initialized=!0;b.addEventListener("scroll",function(){a.lastScroll=Date.now()},!1)},watchScroll:function(a,b,c){b.down=!0;b.lastY=a.scrollTop;a.addEventListener("scroll",function(d){d=a.scrollTop;var f=b.lastY;d>f?b.down=!0:d<f&&(b.down=!1);b.lastY=d;c()},!0)},setScale:function(a,b,c){if(a!=this.currentScale){for(var d=this.pages,f=0;f<d.length;f++)d[f].update(a*CSS_UNITS);c||this.currentScale==a||this.pages[this.page-1].scrollIntoView();
-this.currentScale=a;c=document.createEvent("UIEvents");c.initUIEvent("scalechange",!1,!1,window,0);c.scale=a;c.resetAutoSettings=b;window.dispatchEvent(c)}},parseScale:function(a,b,c){if("custom"!=a){var d=parseFloat(a);this.currentScaleValue=a;if(d)this.setScale(d,!0,c);else{var f=this.container,h=this.pages[this.page-1];if(h){var e=(f.clientWidth-SCROLLBAR_PADDING)/h.width*h.scale/CSS_UNITS,f=(f.clientHeight-VERTICAL_PADDING)/h.height*h.scale/CSS_UNITS;switch(a){case "page-actual":d=1;break;case "page-width":d=
-e;break;case "page-height":d=f;break;case "page-fit":d=Math.min(e,f);break;case "auto":d=Math.min(1,e)}this.setScale(d,b,c);selectScaleOption(a)}}}},zoomIn:function(){var a=(this.currentScale*DEFAULT_SCALE_DELTA).toFixed(2),a=Math.min(MAX_SCALE,a);this.parseScale(a,!0)},zoomOut:function(){var a=(this.currentScale/DEFAULT_SCALE_DELTA).toFixed(2),a=Math.max(MIN_SCALE,a);this.parseScale(a,!0)},set page(a){var b=this.pages;document.getElementById("pageNumber");var c=document.createEvent("UIEvents");c.initUIEvent("pagechange",
-!1,!1,window,0);0<a&&a<=b.length?(b[a-1].updateStats(),this.previousPageNumber=currentPageNumber,currentPageNumber=a,c.pageNumber=a,window.dispatchEvent(c),updateViewarea.inProgress||this.loading&&1==a||b[a-1].scrollIntoView()):(this.previousPageNumber=a,c.pageNumber=this.page,window.dispatchEvent(c))},get page(){return currentPageNumber},get supportsPrinting(){var a="mozPrintCallback"in document.createElement("canvas");Object.defineProperty(this,"supportsPrinting",{value:a,enumerable:!0,configurable:!0,
-writable:!1});return a},get supportsFullscreen(){var a=document.documentElement,a=a.requestFullscreen||a.mozRequestFullScreen||a.webkitRequestFullScreen;window.frameElement&&(a=!1);Object.defineProperty(this,"supportsFullScreen",{value:a,enumerable:!0,configurable:!0,writable:!1});return a},get supportsIntegratedFind(){Object.defineProperty(this,"supportsIntegratedFind",{value:!1,enumerable:!0,configurable:!0,writable:!1});return!1},get supportsDocumentFonts(){Object.defineProperty(this,"supportsDocumentFonts",
-{value:!0,enumerable:!0,configurable:!0,writable:!1});return!0},get isHorizontalScrollbarEnabled(){var a=document.getElementById("viewerContainer");return a.scrollWidth>a.clientWidth},initPassiveLoading:function(){PDFView.loadingBar||(PDFView.loadingBar=new ProgressBar("#loadingBar",{}));window.addEventListener("message",function(a){var b=a.data;if("object"===typeof b&&"pdfjsLoadAction"in b)switch(b.pdfjsLoadAction){case "progress":PDFView.progress(b.loaded/b.total);break;case "complete":if(!b.data){PDFView.error(mozL10n.get("loading_error",
-null,"An error occurred while loading the PDF."),a);break}PDFView.open(b.data,0)}});FirefoxCom.requestSync("initPassiveLoading",null)},setTitleUsingUrl:function(a){this.url=a;try{this.setTitle(decodeURIComponent(getFileName(a))||a)}catch(b){this.setTitle(a)}},setTitle:function(a){document.title=a},open:function(a,b,c){var d={password:c};"string"===typeof a?(this.setTitleUsingUrl(a),d.url=a):a&&"byteLength"in a&&(d.data=a);PDFView.loadingBar||(PDFView.loadingBar=new ProgressBar("#loadingBar",{}));
-this.pdfDocument=null;var f=this;f.loading=!0;PDFJS.getDocument(d).then(function(a){f.load(a,b);f.loading=!1},function(d,e){if(e&&"PasswordException"===e.name&&"needpassword"===e.code){var g=mozL10n.get("request_password",null,"PDF is protected by a password:");if((c=prompt(g))&&0<c.length)return PDFView.open(a,b,c)}g=mozL10n.get("loading_error",null,"An error occurred while loading the PDF.");e&&"InvalidPDFException"===e.name&&(g=mozL10n.get("invalid_file_error",null,"Invalid or corrupted PDF file."));
-document.getElementById("loading").textContent=mozL10n.get("loading_error_indicator",null,"Error");f.error(g,{message:d});f.loading=!1},function(a){f.progress(a.loaded/a.total)})},download:function(){var a=this.url.split("#")[0];window.open(a+"#pdfjs.action=download","_parent")},fallback:function(){},navigateTo:function(a){"string"===typeof a&&(a=this.destinations[a]);if(a instanceof Array){var b=a[0],b=b instanceof Object?this.pagesRefMap[b.num+" "+b.gen+" R"]:b+1;b>this.pages.length&&(b=this.pages.length);
-b&&(this.page=b,this.pages[b-1].scrollIntoView(a))}},getDestinationHash:function(a){if("string"===typeof a)return PDFView.getAnchorUrl("#"+escape(a));if(a instanceof Array){var b=a[0];if(b=b instanceof Object?this.pagesRefMap[b.num+" "+b.gen+" R"]:b+1){var b=PDFView.getAnchorUrl("#page="+b),c=a[1];"object"===typeof c&&"name"in c&&"XYZ"==c.name&&(b+="&zoom="+100*(a[4]||this.currentScale),a[2]||a[3])&&(b+=","+(a[2]||0)+","+(a[3]||0));return b}}return""},getAnchorUrl:function(a){return a},getOutputScale:function(){var a=
-"devicePixelRatio"in window?window.devicePixelRatio:1;return{sx:a,sy:a,scaled:1!=a}},error:function(a,b){var c=mozL10n.get("error_version_info",{version:PDFJS.version||"?",build:PDFJS.build||"?"},"PDF.js v{{version}} (build: {{build}})")+"\n";b&&(c+=mozL10n.get("error_message",{message:b.message},"Message: {{message}}"),b.stack?c+="\n"+mozL10n.get("error_stack",{stack:b.stack},"Stack: {{stack}}"):(b.filename&&(c+="\n"+mozL10n.get("error_file",{file:b.filename},"File: {{file}}")),b.lineNumber&&(c+=
-"\n"+mozL10n.get("error_line",{line:b.lineNumber},"Line: {{line}}"))));document.getElementById("loadingBox").setAttribute("hidden","true");var d=document.getElementById("errorWrapper");d.removeAttribute("hidden");document.getElementById("errorMessage").textContent=a;document.getElementById("errorClose").onclick=function(){d.setAttribute("hidden","true")};var f=document.getElementById("errorMoreInfo"),h=document.getElementById("errorShowMore"),e=document.getElementById("errorShowLess");h.onclick=function(){f.removeAttribute("hidden");
-h.setAttribute("hidden","true");e.removeAttribute("hidden")};e.onclick=function(){f.setAttribute("hidden","true");h.removeAttribute("hidden");e.setAttribute("hidden","true")};h.removeAttribute("hidden");e.setAttribute("hidden","true");f.value=c;f.rows=c.split("\n").length-1},progress:function(a){a=Math.round(100*a);PDFView.loadingBar.percent=a},load:function(a,b){function c(a,b){a.onAfterDraw=function(){b.setImage(a.canvas)}}this.pdfDocument=a;document.getElementById("errorWrapper").setAttribute("hidden",
-"true");document.getElementById("loadingBox").setAttribute("hidden","true");document.getElementById("loading").textContent="";var d=document.getElementById("thumbnailView");for(d.parentNode.scrollTop=0;d.hasChildNodes();)d.removeChild(d.lastChild);"_loadingInterval"in d&&clearInterval(d._loadingInterval);for(var f=document.getElementById("viewer");f.hasChildNodes();)f.removeChild(f.lastChild);var h=a.numPages,e=a.fingerprint;document.getElementById("numPages").textContent=mozL10n.get("page_of",{pageCount:h},
-"of {{pageCount}}");document.getElementById("pageNumber").max=h;PDFView.documentFingerprint=e;var g=PDFView.store=new Settings(e),e=g.initializedPromise;this.pageRotation=0;var k=this.pages=[];this.pageText=[];this.startedTextExtraction=!1;for(var n={},l=this.thumbnails=[],m=[],s=1;s<=h;s++)m.push(a.getPage(s));var r=this,m=PDFJS.Promise.all(m);m.then(function(a){for(var p=1;p<=h;p++){var e=a[p-1],g=new PageView(f,e,p,b,e.stats,r.navigateTo.bind(r)),m=new ThumbnailView(d,e,p);c(g,m);k.push(g);l.push(m);
-e=e.ref;n[e.num+" "+e.gen+" R"]=p}r.pagesRefMap=n});s=a.getDestinations();s.then(function(a){r.destinations=a});PDFJS.Promise.all([m,s,e]).then(function(){a.getOutline().then(function(a){r.outline=new DocumentOutlineView(a)});var c=null;if(g.get("exists",!1))var c=g.get("page","1"),d=g.get("zoom",PDFView.currentScale),f=g.get("scrollLeft","0"),e=g.get("scrollTop","0"),c="page="+c+"&zoom="+d+","+f+","+e;r.setInitialView(c,b)});a.getMetadata().then(function(b){var c=b.info;b=b.metadata;r.documentInfo=
-c;r.metadata=b;console.log("PDF "+a.fingerprint+" ["+c.PDFFormatVersion+" "+(c.Producer||"-")+" / "+(c.Creator||"-")+"]"+(PDFJS.version?" (PDF.js: "+PDFJS.version+")":""));var d;b&&b.has("dc:title")&&(d=b.get("dc:title"));!d&&c&&c.Title&&(d=c.Title);d&&r.setTitle(d+" - "+document.title)})},setInitialView:function(a,b){this.currentScale=0;this.currentScaleValue=null;this.initialBookmark?(this.setHash(this.initialBookmark),this.initialBookmark=null):a?this.setHash(a):b&&(this.parseScale(b,!0),this.page=
-1);PDFView.currentScale===UNKNOWN_SCALE&&this.parseScale(DEFAULT_SCALE,!0)},renderHighestPriority:function(){var a=this.getVisiblePages();(a=this.getHighestPriority(a,this.pages,this.pageViewScroll.down))?this.renderView(a,"page"):this.sidebarOpen&&(a=this.getVisibleThumbs(),(a=this.getHighestPriority(a,this.thumbnails,this.thumbnailViewScroll.down))&&this.renderView(a,"thumbnail"))},getHighestPriority:function(a,b,c){var d=a.views,f=d.length;if(0===f)return!1;for(var h=0;h<f;++h){var e=d[h].view;
-if(!this.isViewFinished(e))return e}a=c?a.last.id:a.first.id-2;return b[a]&&!this.isViewFinished(b[a])?b[a]:!1},isViewFinished:function(a){return a.renderingState===RenderingStates.FINISHED},renderView:function(a,b){switch(a.renderingState){case RenderingStates.FINISHED:return!1;case RenderingStates.PAUSED:PDFView.highestPriorityPage=b+a.id;a.resume();break;case RenderingStates.RUNNING:PDFView.highestPriorityPage=b+a.id;break;case RenderingStates.INITIAL:PDFView.highestPriorityPage=b+a.id,a.draw(this.renderHighestPriority.bind(this))}return!0},
-setHash:function(a){if(a)if(0<=a.indexOf("=")){var b=PDFView.parseQueryString(a);if("nameddest"in b)PDFView.navigateTo(b.nameddest);else if("page"in b)if(a=b.page|0||1,"zoom"in b){var b=b.zoom.split(","),c=b[0],d=parseFloat(c);d&&(c=d/100);this.pages[a-1].scrollIntoView([null,{name:"XYZ"},b[1]|0,b[2]|0,c])}else this.page=a}else/^\d+$/.test(a)?this.page=a:PDFView.navigateTo(unescape(a))},switchSidebarView:function(a){var b=document.getElementById("thumbnailView"),c=document.getElementById("outlineView"),
-d=document.getElementById("viewThumbnail"),f=document.getElementById("viewOutline");switch(a){case "thumbs":a=b.classList.contains("hidden");d.classList.add("toggled");f.classList.remove("toggled");b.classList.remove("hidden");c.classList.add("hidden");PDFView.renderHighestPriority();a&&scrollIntoView(document.getElementById("thumbnailContainer"+this.page));break;case "outline":d.classList.remove("toggled"),f.classList.add("toggled"),b.classList.add("hidden"),c.classList.remove("hidden"),f.getAttribute("disabled")}},
-getVisiblePages:function(){return this.getVisibleElements(this.container,this.pages,!0)},getVisibleThumbs:function(){return this.getVisibleElements(this.thumbnailContainer,this.thumbnails)},getVisibleElements:function(a,b,c){for(var d=0,f,h=a.scrollTop,e=1,g=b.length;e<=g;++e){f=b[e-1];d=f.el.offsetTop;if(d+f.el.clientHeight>h)break;d+=f.el.clientHeight}var k=[];if(this.isFullscreen)return c=this.pages[this.page-1],k.push({id:c.id,view:c}),{first:c,last:c,views:k};a=h+a.clientHeight;for(var n,l,m;e<=
-g&&d<a;++e)f=b[e-1],m=f.el.clientHeight,d=f.el.offsetTop,n=d+m,l=Math.max(0,h-d)+Math.max(0,n-a),l=Math.floor(100*(m-l)/m),k.push({id:f.id,y:d,view:f,percent:l}),d=n;b=k[0];d=k[k.length-1];c&&k.sort(function(a,b){var c=a.percent-b.percent;return 0.0010<Math.abs(c)?-c:a.id-b.id});return{first:b,last:d,views:k}},parseQueryString:function(a){a=a.split("&");for(var b={},c=0;c<a.length;++c){var d=a[c].split("="),f=1<d.length?d[1]:null;b[unescape(d[0])]=unescape(f)}return b},beforePrint:function(){if(this.supportsPrinting){document.querySelector("body").setAttribute("data-mozPrintCallback",
-!0);for(var a=0,b=this.pages.length;a<b;++a)this.pages[a].beforePrint()}else a=mozL10n.get("printing_not_supported",null,"Warning: Printing is not fully supported by this browser."),this.error(a)},afterPrint:function(){for(var a=document.getElementById("printContainer");a.hasChildNodes();)a.removeChild(a.lastChild)},fullscreen:function(){if(document.fullscreenElement||document.mozFullScreen||document.webkitIsFullScreen)return!1;var a=document.getElementById("viewerContainer");if(document.documentElement.requestFullscreen)a.requestFullscreen();
-else if(document.documentElement.mozRequestFullScreen)a.mozRequestFullScreen();else if(document.documentElement.webkitRequestFullScreen)a.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);else return!1;this.isFullscreen=!0;var b=this.pages[this.page-1];this.previousScale=this.currentScaleValue;this.parseScale("page-fit",!0);setTimeout(function(){b.scrollIntoView()},0);this.showPresentationControls();return!0},exitFullscreen:function(){this.isFullscreen=!1;this.parseScale(this.previousScale);this.page=
-this.page;this.clearMouseScrollState();this.hidePresentationControls()},showPresentationControls:function(){var a=document.getElementById("viewerContainer");this.presentationControlsTimeout?clearTimeout(this.presentationControlsTimeout):a.classList.add("presentationControls");this.presentationControlsTimeout=setTimeout(function(){a.classList.remove("presentationControls");delete PDFView.presentationControlsTimeout},3E3)},hidePresentationControls:function(){this.presentationControlsTimeout&&(clearTimeout(this.presentationControlsTimeout),
-delete this.presentationControlsTimeout,document.getElementById("viewerContainer").classList.remove("presentationControls"))},rotatePages:function(a){this.pageRotation=(this.pageRotation+360+a)%360;a=0;for(var b=this.pages.length;a<b;a++){var c=this.pages[a];c.update(c.scale,this.pageRotation)}a=0;for(b=this.thumbnails.length;a<b;a++)this.thumbnails[a].updateRotation(this.pageRotation);var d=this.pages[this.page-1];this.parseScale(this.currentScaleValue,!0);this.renderHighestPriority();setTimeout(function(){d.scrollIntoView()},
-0)},mouseScroll:function(a){var b=(new Date).getTime(),c=this.mouseScrollTimeStamp;b>c&&50>b-c||((0<this.mouseScrollDelta&&0>a||0>this.mouseScrollDelta&&0<a)&&this.clearMouseScrollState(),this.mouseScrollDelta+=a,120<=Math.abs(this.mouseScrollDelta)&&(a=0<this.mouseScrollDelta?-1:1,this.clearMouseScrollState(),c=this.page,1==c&&-1==a||c==this.pages.length&&1==a||(this.page+=a,this.mouseScrollTimeStamp=b)))},clearMouseScrollState:function(){this.mouseScrollDelta=this.mouseScrollTimeStamp=0}},PageView=
-function(a,b,c,d,f,h){function e(a,b){function c(a,b){a.href=PDFView.getDestinationHash(b);a.onclick=function(){b&&PDFView.navigateTo(b);return!1}}function d(a,c,f){f||(f=b.convertToViewportRectangle(c.rect),f=PDFJS.Util.normalizeRect(f));a=document.createElement(a);a.style.left=Math.floor(f[0])+"px";a.style.top=Math.floor(f[1])+"px";a.style.width=Math.ceil(f[2]-f[0])+"px";a.style.height=Math.ceil(f[3]-f[1])+"px";return a}function f(a){var c=document.createElement("section");c.className="annotText";
-var e=b.convertToViewportRectangle(a.rect),e=PDFJS.Util.normalizeRect(e);e[3]-e[1]<ANNOT_MIN_SIZE&&(e[3]=e[1]+ANNOT_MIN_SIZE);e[2]-e[0]<ANNOT_MIN_SIZE&&(e[2]=e[0]+(e[3]-e[1]));var h=d("img",a,e),g=a.name;h.src=IMAGE_DIR+"annotation-"+g.toLowerCase()+".svg";h.alt=mozL10n.get("text_annotation_type",{type:g},"[{{type}} Annotation]");var k=document.createElement("div");k.setAttribute("hidden",!0);var g=document.createElement("h1"),l=document.createElement("p");k.style.left=Math.floor(e[2])+"px";k.style.top=
-Math.floor(e[1])+"px";g.textContent=a.title;if(a.content||a.title){e=document.createElement("span");a=a.content.split(/(?:\r\n?|\n)/);for(var s=0,v=a.length;s<v;++s)e.appendChild(document.createTextNode(a[s])),s<v-1&&e.appendChild(document.createElement("br"));l.appendChild(e);h.addEventListener("mouseover",function(){k.removeAttribute("hidden")},!1);h.addEventListener("mouseout",function(){k.setAttribute("hidden",!0)},!1)}else k.setAttribute("hidden",!0);k.appendChild(g);k.appendChild(l);c.appendChild(h);
-c.appendChild(k);return c}a.getAnnotations().then(function(a){for(var b=0;b<a.length;b++){var e=a[b];switch(e.type){case "Link":var h=d("a",e);h.href=e.url||"";e.url||c(h,"dest"in e?e.dest:null);g.appendChild(h);break;case "Text":(e=f(e))&&g.appendChild(e);break;case "Widget":PDFView.fallback()}}})}this.id=c;this.pdfPage=b;this.rotation=0;this.scale=d||1;this.viewport=this.pdfPage.getViewport(this.scale,this.pdfPage.rotate);this.renderingState=RenderingStates.INITIAL;this.textLayer=this.textContent=
-this.resume=null;c=document.createElement("a");c.name=""+this.id;var g=this.el=document.createElement("div");g.id="pageContainer"+this.id;g.className="page";g.style.width=Math.floor(this.viewport.width)+"px";g.style.height=Math.floor(this.viewport.height)+"px";a.appendChild(c);a.appendChild(g);this.destroy=function(){this.update();this.pdfPage.destroy()};this.update=function(a,b){this.renderingState=RenderingStates.INITIAL;this.resume=null;"undefined"!==typeof b&&(this.rotation=b);this.scale=a||this.scale;
-var c=this.pdfPage.getViewport(this.scale,(this.rotation+this.pdfPage.rotate)%360);this.viewport=c;g.style.width=Math.floor(c.width)+"px";for(g.style.height=Math.floor(c.height)+"px";g.hasChildNodes();)g.removeChild(g.lastChild);g.removeAttribute("data-loaded");delete this.canvas;this.loadingIconDiv=document.createElement("div");this.loadingIconDiv.className="loadingIcon";g.appendChild(this.loadingIconDiv)};Object.defineProperty(this,"width",{get:function(){return this.viewport.width},enumerable:!0});
-Object.defineProperty(this,"height",{get:function(){return this.viewport.height},enumerable:!0});this.getPagePoint=function(a,b){return this.viewport.convertToPdfPoint(a,b)};this.scrollIntoView=function(a){if(a){var b=0,c=0,d=0,f=0,e;e=0;switch(a[1].name){case "XYZ":b=a[2];c=a[3];e=a[4];break;case "Fit":case "FitB":e="page-fit";break;case "FitH":case "FitBH":c=a[2];e="page-width";break;case "FitV":case "FitBV":b=a[2];e="page-height";break;case "FitR":b=a[2];c=a[3];d=a[4]-b;f=a[5]-c;a=(this.container.clientWidth-
-SCROLLBAR_PADDING)/d/CSS_UNITS;e=(this.container.clientHeight-SCROLLBAR_PADDING)/f/CSS_UNITS;e=Math.min(a,e);break;default:return}e&&e!==PDFView.currentScale?PDFView.parseScale(e,!0,!0):PDFView.currentScale===UNKNOWN_SCALE&&PDFView.parseScale(DEFAULT_SCALE,!0,!0);var h=[this.viewport.convertToViewportPoint(b,c),this.viewport.convertToViewportPoint(b+d,c+f)];setTimeout(function(){var a=Math.min(h[0][0],h[1][0]),b=Math.min(h[0][1],h[1][1]),c=Math.abs(h[0][0]-h[1][0]),d=Math.abs(h[0][1]-h[1][1]);scrollIntoView(g,
-{left:a,top:b,width:c,height:d})},0)}else scrollIntoView(g)};this.getTextContent=function(){this.textContent||(this.textContent=this.pdfPage.getTextContent());return this.textContent};this.draw=function(a){function c(d){p.renderingState=RenderingStates.FINISHED;p.loadingIconDiv&&(g.removeChild(p.loadingIconDiv),delete p.loadingIconDiv);d&&PDFView.error(mozL10n.get("rendering_error",null,"An error occurred while rendering the page."),d);p.stats=b.stats;p.updateStats();if(p.onAfterDraw)p.onAfterDraw();
-cache.push(p);a()}this.renderingState!==RenderingStates.INITIAL&&error("Must be in new state before drawing");this.renderingState=RenderingStates.RUNNING;var d=document.createElement("canvas");d.id="page"+this.id;d.mozOpaque=!0;g.appendChild(d);this.canvas=d;var f=null;PDFJS.disableTextLayer||(f=document.createElement("div"),f.className="textLayer",g.appendChild(f));var h=this.textLayer=f?new TextLayerBuilder(f,this.id-1):null,r=this.viewport,q=PDFView.getOutputScale();d.width=Math.floor(r.width)*
-q.sx;d.height=Math.floor(r.height)*q.sy;q.scaled&&(r="scale("+1/q.sx+", "+1/q.sy+")",CustomStyle.setProp("transform",d,r),CustomStyle.setProp("transformOrigin",d,"0% 0%"),f&&(CustomStyle.setProp("transform",f,r),CustomStyle.setProp("transformOrigin",f,"0% 0%")));f=d.getContext("2d");f.save();f.fillStyle="rgb(255, 255, 255)";f.fillRect(0,0,d.width,d.height);f.restore();q.scaled&&f.scale(q.sx,q.sy);var p=this;this.pdfPage.render({canvasContext:f,viewport:this.viewport,textLayer:h,continueCallback:function(a){PDFView.highestPriorityPage!==
-"page"+p.id?(p.renderingState=RenderingStates.PAUSED,p.resume=function(){p.renderingState=RenderingStates.RUNNING;a()}):a()}}).then(function(){c(null)},function(a){c(a)});h&&this.getTextContent().then(function(a){h.setTextContent(a)});e(this.pdfPage,this.viewport);g.setAttribute("data-loaded",!0)};this.beforePrint=function(){var a=this.pdfPage,b=a.getViewport(1),c=this.canvas=document.createElement("canvas");c.width=2*Math.floor(b.width);c.height=2*Math.floor(b.height);c.style.width=2*b.width+"pt";
-c.style.height=2*b.height+"pt";CustomStyle.setProp("transform",c,"scale(0.5, 0.5)");CustomStyle.setProp("transformOrigin",c,"0% 0%");document.getElementById("printContainer").appendChild(c);var d=this;c.mozPrintCallback=function(f){var e=f.context;e.save();e.fillStyle="rgb(255, 255, 255)";e.fillRect(0,0,c.width,c.height);e.restore();e.scale(2,2);a.render({canvasContext:e,viewport:b}).then(function(){f.done();d.pdfPage.destroy()},function(a){console.error(a);"abort"in object?f.abort():f.done();d.pdfPage.destroy()})}};
-this.updateStats=function(){PDFJS.pdfBug&&Stats.enabled&&Stats.add(this.id,this.stats)}},ThumbnailView=function(a,b,c){function d(){var a=document.createElement("canvas");a.id="thumbnail"+c;a.mozOpaque=!0;a.width=l;a.height=m;a.className="thumbnailImage";a.setAttribute("aria-label",mozL10n.get("thumb_page_canvas",{page:c},"Thumbnail of Page {{page}}"));r.setAttribute("data-loaded",!0);q.appendChild(a);a=a.getContext("2d");a.save();a.fillStyle="rgb(255, 255, 255)";a.fillRect(0,0,l,m);a.restore();return a}
-var f=document.createElement("a");f.href=PDFView.getAnchorUrl("#page="+c);f.title=mozL10n.get("thumb_page_title",{page:c},"Page {{page}}");f.onclick=function(){PDFView.page=c;return!1};var h=0,e=(h+b.rotate)%360,g=b.getViewport(1,e),k=this.width=g.width,n=this.height=g.height;this.id=c;var l=98,m=l/this.width*this.height,s=this.scaleX=l/k;this.scaleY=m/n;var r=this.el=document.createElement("div");r.id="thumbnailContainer"+c;r.className="thumbnail";1===c&&r.classList.add("selected");var q=document.createElement("div");
-q.className="thumbnailSelectionRing";q.style.width=l+"px";q.style.height=m+"px";r.appendChild(q);f.appendChild(r);a.appendChild(f);this.hasImage=!1;this.renderingState=RenderingStates.INITIAL;this.updateRotation=function(a){h=a;e=(h+b.rotate)%360;g=b.getViewport(1,e);k=this.width=g.width;n=this.height=g.height;m=l/this.width*this.height;s=this.scaleX=l/k;this.scaleY=m/n;r.removeAttribute("data-loaded");q.textContent="";q.style.width=l+"px";q.style.height=m+"px";this.hasImage=!1;this.renderingState=
-RenderingStates.INITIAL;this.resume=null};this.drawingRequired=function(){return!this.hasImage};this.draw=function(a){this.renderingState!==RenderingStates.INITIAL&&error("Must be in new state before drawing");this.renderingState=RenderingStates.RUNNING;if(this.hasImage)a();else{var c=this,f=d(),h=b.getViewport(s,e);b.render({canvasContext:f,viewport:h,continueCallback:function(a){PDFView.highestPriorityPage!=="thumbnail"+c.id?(c.renderingState=RenderingStates.PAUSED,c.resume=function(){c.renderingState=
-RenderingStates.RUNNING;a()}):a()}}).then(function(){c.renderingState=RenderingStates.FINISHED;a()},function(b){c.renderingState=RenderingStates.FINISHED;a()});this.hasImage=!0}};this.setImage=function(a){if(!this.hasImage&&a){this.renderingState=RenderingStates.FINISHED;var b=d();b.drawImage(a,0,0,a.width,a.height,0,0,b.canvas.width,b.canvas.height);this.hasImage=!0}}},DocumentOutlineView=function(a){function b(a,b){a.href=PDFView.getDestinationHash(b.dest);a.onclick=function(a){PDFView.navigateTo(b.dest);
-return!1}}for(var c=document.getElementById("outlineView");c.firstChild;)c.removeChild(c.firstChild);if(a)for(c=[{parent:c,items:a}];0<c.length;){a=c.shift();var d,f=a.items.length;for(d=0;d<f;d++){var h=a.items[d],e=document.createElement("div");e.className="outlineItem";var g=document.createElement("a");b(g,h);g.textContent=h.title;e.appendChild(g);0<h.items.length&&(g=document.createElement("div"),g.className="outlineItems",e.appendChild(g),c.push({parent:g,items:h.items}));a.parent.appendChild(e)}}else a=
-document.createElement("div"),a.classList.add("noOutline"),a.textContent=mozL10n.get("no_outline",null,"No Outline Available"),c.appendChild(a)},CustomStyle=function(){function a(){}var b=["ms","Moz","Webkit","O"],c={};a.getProp=function(a,f){if(1==arguments.length&&"string"==typeof c[a])return c[a];f=f||document.documentElement;var h=f.style,e,g;if("string"==typeof h[a])return c[a]=a;g=a.charAt(0).toUpperCase()+a.slice(1);for(var k=0,n=b.length;k<n;k++)if(e=b[k]+g,"string"==typeof h[e])return c[a]=
-e;return c[a]="undefined"};a.setProp=function(a,b,c){a=this.getProp(a);"undefined"!=a&&(b.style[a]=c)};return a}(),TextLayerBuilder=function(a,b){var c=document.createDocumentFragment();this.textLayerDiv=a;this.divContentDone=this.layoutDone=!1;this.pageIdx=b;this.matches=[];this.beginLayout=function(){this.textDivs=[];this.textLayerQueue=[];this.renderingDone=!1};this.endLayout=function(){this.layoutDone=!0;this.insertDivContent()};this.renderLayer=function(){var a=this.textDivs,b=this.textLayerDiv,
-h=document.createElement("canvas").getContext("2d");if(!(1E5<a.length)){for(var e=0,g=a.length;e<g;e++){var k=a[e];c.appendChild(k);h.font=k.style.fontSize+" "+k.style.fontFamily;var n=h.measureText(k.textContent).width;0<n&&(CustomStyle.setProp("transform",k,"scale("+k.dataset.canvasWidth/n+", 1)"),CustomStyle.setProp("transformOrigin",k,"0% 0%"),b.appendChild(k))}this.renderingDone=!0;this.updateMatches();b.appendChild(c)}};this.setupRenderLayoutTimer=function(){var a=this;200<Date.now()-PDFView.lastScroll?
-this.renderLayer():(this.renderTimer&&clearTimeout(this.renderTimer),this.renderTimer=setTimeout(function(){a.setupRenderLayoutTimer()},200))};this.appendText=function(a){var b=document.createElement("div"),c=a.fontSize*a.vScale;b.dataset.canvasWidth=a.canvasWidth*a.hScale;b.dataset.fontName=a.fontName;b.style.fontSize=c+"px";b.style.fontFamily=a.fontFamily;b.style.left=a.x+"px";b.style.top=a.y-c+"px";this.textDivs.push(b)};this.insertDivContent=function(){if(this.layoutDone&&!this.divContentDone&&
-this.textContent){this.divContentDone=!0;for(var a=this.textDivs,b=this.textContent.bidiTexts,c=0;c<b.length;c++){var e=b[c],g=a[c];g.textContent=e.str;g.dir=e.ltr?"ltr":"rtl"}this.setupRenderLayoutTimer()}};this.setTextContent=function(a){this.textContent=a;this.insertDivContent()};this.convertMatches=function(a){for(var b=0,c=0,e=this.textContent.bidiTexts,g=e.length-1,k=PDFFindController.state.query.length,n=[],l=0;l<a.length;l++){for(var m=a[l];b!==g&&m>=c+e[b].str.length;)c+=e[b].str.length,
-b++;b==e.length&&console.error("Could not find matching mapping");for(var s={begin:{divIdx:b,offset:m-c}},m=m+k;b!==g&&m>c+e[b].str.length;)c+=e[b].str.length,b++;s.end={divIdx:b,offset:m-c};n.push(s)}return n};this.renderMatches=function(a){function b(a,c){var d=a.divIdx,f=g[d];f.textContent="";var h=e[d].str.substring(0,a.offset),h=document.createTextNode(h);if(c){var d=n&&d===l,k=document.createElement("span");k.className=c+(d?" selected":"");k.appendChild(h);f.appendChild(k)}else f.appendChild(h)}
-function c(a,b,d){var f=a.divIdx,h=g[f];a=e[f].str.substring(a.offset,b.offset);a=document.createTextNode(a);d?(b=document.createElement("span"),b.className=d,b.appendChild(a),h.appendChild(b)):h.appendChild(a)}if(0!==a.length){var e=this.textContent.bidiTexts,g=this.textDivs,k=null,n=this.pageIdx===PDFFindController.selected.pageIdx,l=PDFFindController.selected.matchIdx,m={divIdx:-1,offset:void 0},s=l,r=s+1;if(PDFFindController.state.highlightAll)s=0,r=a.length;else if(!n)return;for(;s<r;s++){var q=
-a[s],p=q.begin,q=q.end,u=n&&s===l,t=u?" selected":"";u&&scrollIntoView(g[p.divIdx],{top:-50});k&&p.divIdx===k.divIdx?c(k,p):(null!==k&&c(k,m),b(p));if(p.divIdx===q.divIdx)c(p,q,"highlight"+t);else{c(p,m,"highlight begin"+t);for(k=p.divIdx+1;k<q.divIdx;k++)g[k].className="highlight middle"+t;b(q,"highlight end"+t)}k=q}k&&c(k,m)}};this.updateMatches=function(){if(this.renderingDone){for(var a=this.matches,b=this.textDivs,c=this.textContent.bidiTexts,e=-1,g=0;g<a.length;g++){for(var k=a[g],e=Math.max(e,
-k.begin.divIdx);e<=k.end.divIdx;e++){var n=b[e];n.textContent=c[e].str;n.className=""}e=k.end.divIdx+1}PDFFindController.active&&(this.matches=this.convertMatches(PDFFindController.pageMatches[this.pageIdx]||[]),this.renderMatches(this.matches))}}};
-document.addEventListener("DOMContentLoaded",function(a){PDFView.initialize();a=PDFView.parseQueryString(document.location.search.substring(1)).file||DEFAULT_URL;window.File&&window.FileReader&&window.FileList&&window.Blob&&(document.getElementById("fileInput").value=null);var b=document.location.hash.substring(1),b=PDFView.parseQueryString(b);"disableWorker"in b&&(PDFJS.disableWorker="true"===b.disableWorker);var c=navigator.language;"locale"in b&&(c=b.locale);mozL10n.setLanguage(c);if("textLayer"in
-b)switch(b.textLayer){case "off":PDFJS.disableTextLayer=!0;break;case "visible":case "shadow":case "hover":document.getElementById("viewer").classList.add("textLayer-"+b.textLayer)}"pdfBug"in b&&(PDFJS.pdfBug=!0,b=b.pdfBug.split(","),PDFBug.enable(b),PDFBug.init());PDFView.supportsPrinting||document.getElementById("print").classList.add("hidden");PDFView.supportsFullscreen||document.getElementById("fullscreen").classList.add("hidden");PDFView.supportsIntegratedFind&&document.querySelector("#viewFind").classList.add("hidden");
-PDFJS.LogManager.addLogger({warn:function(){PDFView.fallback()}});var d=document.getElementById("mainContainer"),f=document.getElementById("outerContainer");d.addEventListener("transitionend",function(a){a.target==d&&(a=document.createEvent("UIEvents"),a.initUIEvent("resize",!1,!1,window,0),window.dispatchEvent(a),f.classList.remove("sidebarMoving"))},!0);document.getElementById("sidebarToggle").addEventListener("click",function(){this.classList.toggle("toggled");f.classList.add("sidebarMoving");
-f.classList.toggle("sidebarOpen");PDFView.sidebarOpen=f.classList.contains("sidebarOpen");PDFView.renderHighestPriority()});document.getElementById("viewThumbnail").addEventListener("click",function(){PDFView.switchSidebarView("thumbs")});document.getElementById("viewOutline").addEventListener("click",function(){PDFView.switchSidebarView("outline")});document.getElementById("previous").addEventListener("click",function(){PDFView.page--});document.getElementById("next").addEventListener("click",function(){PDFView.page++});
-document.querySelector(".zoomIn").addEventListener("click",function(){PDFView.zoomIn()});document.querySelector(".zoomOut").addEventListener("click",function(){PDFView.zoomOut()});document.getElementById("fullscreen").addEventListener("click",function(){PDFView.fullscreen()});document.getElementById("print").addEventListener("click",function(){window.print()});document.getElementById("pageNumber").addEventListener("change",function(){PDFView.page=this.value});document.getElementById("scaleSelect").addEventListener("change",
-function(){PDFView.parseScale(this.value)});document.getElementById("first_page").addEventListener("click",function(){PDFView.page=1});document.getElementById("last_page").addEventListener("click",function(){PDFView.page=PDFView.pdfDocument.numPages});document.getElementById("page_rotate_ccw").addEventListener("click",function(){PDFView.rotatePages(-90)});document.getElementById("page_rotate_cw").addEventListener("click",function(){PDFView.rotatePages(90)});PDFView.open(a,0)},!0);
-function updateViewarea(){if(PDFView.initialized){var a=PDFView.getVisiblePages(),b=a.views;if(0!==b.length){PDFView.renderHighestPriority();for(var c=PDFView.page,a=a.first,d=0,f=b.length,h=!1;d<f;++d){var e=b[d];if(100>e.percent)break;if(e.id===PDFView.page){h=!0;break}}h||(c=b[0].id);PDFView.isFullscreen||(updateViewarea.inProgress=!0,PDFView.page=c,updateViewarea.inProgress=!1);var b=PDFView.currentScale,c=PDFView.currentScaleValue,g=c==b?100*b:c,k=a.id,b="#page="+k+("&zoom="+g),n=PDFView.pages[k-
-1].getPagePoint(PDFView.container.scrollLeft,PDFView.container.scrollTop-a.y),b=b+(","+Math.round(n[0])+","+Math.round(n[1])),l=PDFView.store;l.initializedPromise.then(function(){l.set("exists",!0);l.set("page",k);l.set("zoom",g);l.set("scrollLeft",Math.round(n[0]));l.set("scrollTop",Math.round(n[1]))});PDFView.getAnchorUrl(b)}}}
-window.addEventListener("resize",function(a){PDFView.initialized&&(document.getElementById("pageWidthOption").selected||document.getElementById("pageFitOption").selected||document.getElementById("pageAutoOption").selected)&&PDFView.parseScale(document.getElementById("scaleSelect").value);updateViewarea()});window.addEventListener("hashchange",function(a){PDFView.setHash(document.location.hash.substring(1))});
-window.addEventListener("change",function(a){var b=a.target.files;b&&0!=b.length&&(a=new FileReader,a.onload=function(a){a=new Uint8Array(a.target.result);PDFView.open(a,0)},b=b[0],a.readAsArrayBuffer(b),PDFView.setTitleUsingUrl(b.name))},!0);function selectScaleOption(a){for(var b=document.getElementById("scaleSelect").options,c=!1,d=0;d<b.length;d++){var f=b[d];f.value!=a?f.selected=!1:c=f.selected=!0}return c}
-window.addEventListener("localized",function(a){document.getElementsByTagName("html")[0].dir=mozL10n.getDirection()},!0);
-window.addEventListener("scalechange",function(a){var b=document.getElementById("customScaleOption");b.selected=!1;!a.resetAutoSettings&&(document.getElementById("pageWidthOption").selected||document.getElementById("pageFitOption").selected||document.getElementById("pageAutoOption").selected)||selectScaleOption(""+a.scale)||(b.textContent=Math.round(1E4*a.scale)/100+"%",b.selected=!0);updateViewarea()},!0);
-window.addEventListener("pagechange",function(a){a=a.pageNumber;if(PDFView.previousPageNumber!==a){document.getElementById("pageNumber").value=a;var b=document.querySelector(".thumbnail.selected");b&&b.classList.remove("selected");b=document.getElementById("thumbnailContainer"+a);b.classList.add("selected");var c=PDFView.getVisibleThumbs(),d=c.views.length;if(0<d){var f=c.first.id,c=1<d?c.last.id:f;(a<=f||a>=c)&&scrollIntoView(b)}}document.getElementById("previous").disabled=1>=a;document.getElementById("next").disabled=
-a>=PDFView.pages.length},!0);window.addEventListener("DOMMouseScroll",function(a){if(a.ctrlKey){a.preventDefault();var b=a.detail;a=0<b?"zoomOut":"zoomIn";for(var c=0,b=Math.abs(b);c<b;c++)PDFView[a]()}else PDFView.isFullscreen&&PDFView.mouseScroll(-40*a.detail)},!1);window.addEventListener("mousemove",function(a){PDFView.isFullscreen&&PDFView.showPresentationControls()},!1);window.addEventListener("mousedown",function(a){PDFView.isFullscreen&&0===a.button&&(a.preventDefault(),PDFView.page++)},!1);
-window.addEventListener("keydown",function(a){var b=!1,c=(a.ctrlKey?1:0)|(a.altKey?2:0)|(a.shiftKey?4:0)|(a.metaKey?8:0);if(1==c||8==c)switch(a.keyCode){case 70:PDFView.supportsIntegratedFind||(PDFFindBar.toggle(),b=!0);break;case 61:case 107:case 187:case 171:PDFView.zoomIn();b=!0;break;case 173:case 109:case 189:PDFView.zoomOut();b=!0;break;case 48:case 96:PDFView.parseScale(DEFAULT_SCALE,!0),b=!0}if(1==c||8==c||5==c||12==c)switch(a.keyCode){case 71:PDFView.supportsIntegratedFind||(PDFFindBar.dispatchEvent("again",
-5==c||12==c),b=!0)}if(b)a.preventDefault();else{var d=document.activeElement;if(!d||"INPUT"!=d.tagName&&"SELECT"!=d.tagName){for(var f=document.getElementById("toolbar");d;){if(d===f&&!PDFView.isFullscreen)return;d=d.parentNode}if(0==c)switch(a.keyCode){case 38:case 33:case 8:if(!PDFView.isFullscreen&&"page-fit"!==PDFView.currentScaleValue)break;case 37:if(PDFView.isHorizontalScrollbarEnabled)break;case 75:case 80:PDFView.page--;b=!0;break;case 40:case 34:case 32:if(!PDFView.isFullscreen&&"page-fit"!==
-PDFView.currentScaleValue)break;case 39:if(PDFView.isHorizontalScrollbarEnabled)break;case 74:case 78:PDFView.page++;b=!0;break;case 36:PDFView.isFullscreen&&(PDFView.page=1,b=!0);break;case 35:PDFView.isFullscreen&&(PDFView.page=PDFView.pdfDocument.numPages,b=!0);break;case 82:PDFView.rotatePages(90)}if(4==c)switch(a.keyCode){case 82:PDFView.rotatePages(-90)}b&&(a.preventDefault(),PDFView.clearMouseScrollState())}}});window.addEventListener("beforeprint",function(a){PDFView.beforePrint()});
-window.addEventListener("afterprint",function(a){PDFView.afterPrint()});(function(){function a(a){document.fullscreenElement||document.mozFullScreen||document.webkitIsFullScreen||PDFView.exitFullscreen()}window.addEventListener("fullscreenchange",a,!1);window.addEventListener("mozfullscreenchange",a,!1);window.addEventListener("webkitfullscreenchange",a,!1)})();
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* Copyright 2012 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* globals 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 */
+
+'use strict';
+
+var DEFAULT_URL = null;
+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 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,
+  FIND_NOTFOUND: 1,
+  FIND_WRAPPED: 2,
+  FIND_PENDING: 3
+};
+
+PDFJS.imageResourcesPath = './images/';
+  PDFJS.workerSrc = 'pdf.worker.js';
+
+var mozL10n = document.mozL10n || document.webL10n;
+
+
+// optimised CSS custom property getter/setter
+var CustomStyle = (function CustomStyleClosure() {
+
+  // As noted on: http://www.zachstronaut.com/posts/2009/02/17/
+  //              animate-css-transforms-firefox-webkit.html
+  // in some versions of IE9 it is critical that ms appear in this list
+  // before Moz
+  var prefixes = ['ms', 'Moz', 'Webkit', 'O'];
+  var _cache = { };
+
+  function CustomStyle() {
+  }
+
+  CustomStyle.getProp = function get(propName, element) {
+    // check cache only when no element is given
+    if (arguments.length == 1 && typeof _cache[propName] == 'string') {
+      return _cache[propName];
+    }
+
+    element = element || document.documentElement;
+    var style = element.style, prefixed, uPropName;
+
+    // test standard property first
+    if (typeof style[propName] == 'string') {
+      return (_cache[propName] = propName);
+    }
+
+    // capitalize
+    uPropName = propName.charAt(0).toUpperCase() + propName.slice(1);
+
+    // test vendor specific properties
+    for (var i = 0, l = prefixes.length; i < l; i++) {
+      prefixed = prefixes[i] + uPropName;
+      if (typeof style[prefixed] == 'string') {
+        return (_cache[propName] = prefixed);
+      }
+    }
+
+    //if all fails then set to undefined
+    return (_cache[propName] = 'undefined');
+  };
+
+  CustomStyle.setProp = function set(propName, element, str) {
+    var prop = this.getProp(propName);
+    if (prop != 'undefined')
+      element.style[prop] = str;
+  };
+
+  return CustomStyle;
+})();
+
+function getFileName(url) {
+  var anchor = url.indexOf('#');
+  var query = url.indexOf('?');
+  var end = Math.min(
+    anchor > 0 ? anchor : url.length,
+    query > 0 ? query : url.length);
+  return url.substring(url.lastIndexOf('/', end) + 1, end);
+}
+
+/**
+ * Returns scale factor for the canvas. It makes sense for the HiDPI displays.
+ * @return {Object} The object with horizontal (sx) and vertical (sy)
+                    scales. The scaled property is set to false if scaling is
+                    not required, true otherwise.
+ */
+function getOutputScale(ctx) {
+  var devicePixelRatio = window.devicePixelRatio || 1;
+  var backingStoreRatio = ctx.webkitBackingStorePixelRatio ||
+                          ctx.mozBackingStorePixelRatio ||
+                          ctx.msBackingStorePixelRatio ||
+                          ctx.oBackingStorePixelRatio ||
+                          ctx.backingStorePixelRatio || 1;
+  var pixelRatio = devicePixelRatio / backingStoreRatio;
+  return {
+    sx: pixelRatio,
+    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.
+ */
+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) {
+    if (parent.dataset._scaleY) {
+      offsetY /= parent.dataset._scaleY;
+      offsetX /= parent.dataset._scaleX;
+    }
+    offsetY += parent.offsetTop;
+    offsetX += parent.offsetLeft;
+    parent = parent.offsetParent;
+    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;
+    }
+  }
+  parent.scrollTop = offsetY;
+}
+
+/**
+ * Event handler to suppress context menu.
+ */
+function noContextMenuHandler(e) {
+  e.preventDefault();
+}
+
+/**
+ * Returns the filename or guessed filename from the url (see issue 3455).
+ * url {String} The original PDF location.
+ * @return {String} Guessed PDF file name.
+ */
+function getPDFFileNameFromURL(url) {
+  var reURI = /^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
+  //            SCHEME      HOST         1.PATH  2.QUERY   3.REF
+  // Pattern to get last matching NAME.pdf
+  var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
+  var splitURI = reURI.exec(url);
+  var suggestedFilename = reFilename.exec(splitURI[1]) ||
+                           reFilename.exec(splitURI[2]) ||
+                           reFilename.exec(splitURI[3]);
+  if (suggestedFilename) {
+    suggestedFilename = suggestedFilename[0];
+    if (suggestedFilename.indexOf('%') != -1) {
+      // URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf
+      try {
+        suggestedFilename =
+          reFilename.exec(decodeURIComponent(suggestedFilename))[0];
+      } catch(e) { // Possible (extremely rare) errors:
+        // URIError "Malformed URI", e.g. for "%AA.pdf"
+        // TypeError "null has no properties", e.g. for "%2F.pdf"
+      }
+    }
+  }
+  return suggestedFilename || 'document.pdf';
+}
+
+var ProgressBar = (function ProgressBarClosure() {
+
+  function clamp(v, min, max) {
+    return Math.min(Math.max(v, min), max);
+  }
+
+  function ProgressBar(id, opts) {
+
+    // Fetch the sub-elements for later.
+    this.div = document.querySelector(id + ' .progress');
+
+    // Get the loading bar element, so it can be resized to fit the viewer.
+    this.bar = this.div.parentNode;
+
+    // Get options, with sensible defaults.
+    this.height = opts.height || 100;
+    this.width = opts.width || 100;
+    this.units = opts.units || '%';
+
+    // Initialize heights.
+    this.div.style.height = this.height + this.units;
+    this.percent = 0;
+  }
+
+  ProgressBar.prototype = {
+
+    updateBar: function ProgressBar_updateBar() {
+      if (this._indeterminate) {
+        this.div.classList.add('indeterminate');
+        this.div.style.width = this.width + this.units;
+        return;
+      }
+
+      this.div.classList.remove('indeterminate');
+      var progressSize = this.width * this._percent / 100;
+      this.div.style.width = progressSize + this.units;
+    },
+
+    get percent() {
+      return this._percent;
+    },
+
+    set percent(val) {
+      this._indeterminate = isNaN(val);
+      this._percent = clamp(val, 0, 100);
+      this.updateBar();
+    },
+
+    setWidth: function ProgressBar_setWidth(viewer) {
+      if (viewer) {
+        var container = viewer.parentNode;
+        var scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
+        if (scrollbarWidth > 0) {
+          this.bar.setAttribute('style', 'width: calc(100% - ' +
+                                         scrollbarWidth + 'px);');
+        }
+      }
+    },
+
+    hide: function ProgressBar_hide() {
+      this.bar.classList.add('hidden');
+      this.bar.removeAttribute('style');
+    }
+  };
+
+  return ProgressBar;
+})();
+
+var Cache = function cacheCache(size) {
+  var data = [];
+  this.push = function cachePush(view) {
+    var i = data.indexOf(view);
+    if (i >= 0)
+      data.splice(i);
+    data.push(view);
+    if (data.length > size)
+      data.shift().destroy();
+  };
+};
+
+var isLocalStorageEnabled = (function isLocalStorageEnabledClosure() {
+  // Feature test as per http://diveintohtml5.info/storage.html
+  // The additional localStorage call is to get around a FF quirk, see
+  // bug #495747 in bugzilla
+  try {
+    return ('localStorage' in window && window['localStorage'] !== null &&
+            localStorage);
+  } catch (e) {
+    return false;
+  }
+})();
+
+
+
+var EXPORTED_SYMBOLS = ['DEFAULT_PREFERENCES'];
+
+var DEFAULT_PREFERENCES = {
+  showPreviousViewOnLoad: true,
+  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();
+      return readFromStoragePromise;
+    },
+
+    reset: function Preferences_reset() {
+      if (this.isInitializedPromiseResolved) {
+        this.prefs = {};
+        this.writeToStorage(this.prefs);
+      }
+    },
+
+    set: function Preferences_set(name, value) {
+      if (!this.isInitializedPromiseResolved) {
+        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;
+      }
+      var valueType = typeof value;
+      var defaultType = typeof DEFAULT_PREFERENCES[name];
+
+      if (valueType !== defaultType) {
+        if (valueType === 'number' && defaultType === 'string') {
+          value = value.toString();
+        } else {
+          console.error('Preferences_set: \'' + value + '\' is a \"' +
+                        valueType + '\", expected a \"' + defaultType + '\".');
+          return;
+        }
+      }
+      this.prefs[name] = value;
+      this.writeToStorage(this.prefs);
+    },
+
+    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) {
+        var pref = this.prefs[name];
+
+        if (pref !== undefined) {
+          return pref;
+        }
+      }
+      return defaultPref;
+    }
+  };
+
+  return Preferences;
+})();
+
+
+Preferences.prototype.writeToStorage = function(prefObj) {
+  if (isLocalStorageEnabled) {
+    localStorage.setItem('preferences', JSON.stringify(prefObj));
+  }
+};
+
+Preferences.prototype.readFromStorage = function() {
+  var readFromStoragePromise = new Promise(function (resolve) {
+    if (isLocalStorageEnabled) {
+      var readPrefs = JSON.parse(localStorage.getItem('preferences'));
+      resolve(readPrefs);
+    }
+  });
+  return readFromStoragePromise;
+};
+
+
+(function mozPrintCallbackPolyfillClosure() {
+  if ('mozPrintCallback' in document.createElement('canvas')) {
+    return;
+  }
+  // Cause positive result on feature-detection:
+  HTMLCanvasElement.prototype.mozPrintCallback = undefined;
+
+  var canvases;   // During print task: non-live NodeList of <canvas> elements
+  var index;      // Index of <canvas> element that is being processed
+
+  var print = window.print;
+  window.print = function print() {
+    if (canvases) {
+      console.warn('Ignored window.print() because of a pending print job.');
+      return;
+    }
+    try {
+      dispatchEvent('beforeprint');
+    } finally {
+      canvases = document.querySelectorAll('canvas');
+      index = -1;
+      next();
+    }
+  };
+
+  function dispatchEvent(eventType) {
+    var event = document.createEvent('CustomEvent');
+    event.initCustomEvent(eventType, false, false, 'custom');
+    window.dispatchEvent(event);
+  }
+
+  function next() {
+    if (!canvases) {
+      return; // Print task cancelled by user (state reset in abort())
+    }
+
+    renderProgress();
+    if (++index < canvases.length) {
+      var canvas = canvases[index];
+      if (typeof canvas.mozPrintCallback === 'function') {
+        canvas.mozPrintCallback({
+          context: canvas.getContext('2d'),
+          abort: abort,
+          done: next
+        });
+      } else {
+        next();
+      }
+    } else {
+      renderProgress();
+      print.call(window);
+      setTimeout(abort, 20); // Tidy-up
+    }
+  }
+
+  function abort() {
+    if (canvases) {
+      canvases = null;
+      renderProgress();
+      dispatchEvent('afterprint');
+    }
+  }
+
+  function renderProgress() {
+    var progressContainer = document.getElementById('mozPrintCallback-shim');
+    if (canvases) {
+      var progress = Math.round(100 * index / canvases.length);
+      var progressBar = progressContainer.querySelector('progress');
+      var progressPerc = progressContainer.querySelector('.relative-progress');
+      progressBar.value = progress;
+      progressPerc.textContent = progress + '%';
+      progressContainer.removeAttribute('hidden');
+      progressContainer.onclick = abort;
+    } else {
+      progressContainer.setAttribute('hidden', '');
+    }
+  }
+
+  var hasAttachEvent = !!document.attachEvent;
+
+  window.addEventListener('keydown', function(event) {
+    if (event.keyCode === 80/*P*/ && (event.ctrlKey || event.metaKey)) {
+      window.print();
+      if (hasAttachEvent) {
+        // Only attachEvent can cancel Ctrl + P dialog in IE <=10
+        // attachEvent is gone in IE11, so the dialog will re-appear in IE11.
+        return;
+      }
+      event.preventDefault();
+      if (event.stopImmediatePropagation) {
+        event.stopImmediatePropagation();
+      } else {
+        event.stopPropagation();
+      }
+      return;
+    }
+    if (event.keyCode === 27 && canvases) { // Esc
+      abort();
+    }
+  }, true);
+  if (hasAttachEvent) {
+    document.attachEvent('onkeydown', function(event) {
+      event = event || window.event;
+      if (event.keyCode === 80/*P*/ && event.ctrlKey) {
+        event.keyCode = 0;
+        return false;
+      }
+    });
+  }
+
+  if ('onbeforeprint' in window) {
+    // Do not propagate before/afterprint events when they are not triggered
+    // from within this polyfill. (FF/IE).
+    var stopPropagationIfNeeded = function(event) {
+      if (event.detail !== 'custom' && event.stopImmediatePropagation) {
+        event.stopImmediatePropagation();
+      }
+    };
+    window.addEventListener('beforeprint', stopPropagationIfNeeded, false);
+    window.addEventListener('afterprint', stopPropagationIfNeeded, false);
+  }
+})();
+
+
+
+var DownloadManager = (function DownloadManagerClosure() {
+
+  function download(blobUrl, filename) {
+    var a = document.createElement('a');
+    if (a.click) {
+      // Use a.click() if available. Otherwise, Chrome might show
+      // "Unsafe JavaScript attempt to initiate a navigation change
+      //  for frame with URL" and not open the PDF at all.
+      // Supported by (not mentioned = untested):
+      // - Firefox 6 - 19 (4- does not support a.click, 5 ignores a.click)
+      // - Chrome 19 - 26 (18- does not support a.click)
+      // - Opera 9 - 12.15
+      // - Internet Explorer 6 - 10
+      // - Safari 6 (5.1- does not support a.click)
+      a.href = blobUrl;
+      a.target = '_parent';
+      // Use a.download if available. This increases the likelihood that
+      // the file is downloaded instead of opened by another PDF plugin.
+      if ('download' in a) {
+        a.download = filename;
+      }
+      // <a> must be in the document for IE and recent Firefox versions.
+      // (otherwise .click() is ignored)
+      (document.body || document.documentElement).appendChild(a);
+      a.click();
+      a.parentNode.removeChild(a);
+    } else {
+      if (window.top === window &&
+          blobUrl.split('#')[0] === window.location.href.split('#')[0]) {
+        // If _parent == self, then opening an identical URL with different
+        // location hash will only cause a navigation, not a download.
+        var padCharacter = blobUrl.indexOf('?') === -1 ? '?' : '&';
+        blobUrl = blobUrl.replace(/#|$/, padCharacter + '$&');
+      }
+      window.open(blobUrl, '_parent');
+    }
+  }
+
+  function DownloadManager() {}
+
+  DownloadManager.prototype = {
+    downloadUrl: function DownloadManager_downloadUrl(url, filename) {
+      if (!PDFJS.isValidUrl(url, true)) {
+        return; // restricted/invalid URL
+      }
+
+      download(url + '#pdfjs.action=download', filename);
+    },
+
+    download: function DownloadManager_download(blob, url, filename) {
+      if (!URL) {
+        // URL.createObjectURL is not supported
+        this.downloadUrl(url, filename);
+        return;
+      }
+
+      if (navigator.msSaveBlob) {
+        // IE10 / IE11
+        if (!navigator.msSaveBlob(blob, filename)) {
+          this.downloadUrl(url, filename);
+        }
+        return;
+      }
+
+      var blobUrl = URL.createObjectURL(blob);
+      download(blobUrl, filename);
+    }
+  };
+
+  return DownloadManager;
+})();
+
+
+
+var cache = new Cache(CACHE_SIZE);
+var currentPageNumber = 1;
+
+
+/**
+ * View History - This is a utility for saving various view parameters for
+ *                recently opened files.
+ *
+ * The way that the view parameters 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) {
+    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.initialize(db || '{}');
+      initializedPromiseResolve();
+    }).bind(this);
+
+
+
+    if (isLocalStorageEnabled) {
+      resolvePromise(localStorage.getItem('database'));
+    }
+  }
+
+  ViewHistory.prototype = {
+    initialize: function ViewHistory_initialize(database) {
+      database = JSON.parse(database);
+      if (!('files' in database)) {
+        database.files = [];
+      }
+      if (database.files.length >= VIEW_HISTORY_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;
+        }
+      }
+      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) {
+        return;
+      }
+      var file = this.file;
+      file[name] = val;
+      var database = JSON.stringify(this.database);
+
+
+
+      if (isLocalStorageEnabled) {
+        localStorage.setItem('database', database);
+      }
+    },
+
+    get: function ViewHistory_get(name, defaultValue) {
+      if (!this.isInitializedPromiseResolved) {
+        return defaultValue;
+      }
+      return this.file[name] || defaultValue;
+    }
+  };
+
+  return ViewHistory;
+})();
+
+
+/* globals PDFFindController, FindStates, mozL10n */
+
+/**
+ * Creates a "search bar" given set of DOM elements
+ * that act as controls for searching, or for setting
+ * search preferences in the UI. This object also sets
+ * up the appropriate events for the controls. Actual
+ * searching is done by PDFFindController
+ */
+var PDFFindBar = {
+
+  opened: false,
+  bar: null,
+  toggleButton: null,
+  findField: null,
+  highlightAll: null,
+  caseSensitive: null,
+  findMsg: null,
+  findStatusIcon: null,
+  findPreviousButton: null,
+  findNextButton: null,
+
+  initialize: function(options) {
+    if(typeof PDFFindController === 'undefined' || PDFFindController === null) {
+        throw 'PDFFindBar cannot be initialized ' +
+            'without a PDFFindController instance.';
+    }
+
+    this.bar = options.bar;
+    this.toggleButton = options.toggleButton;
+    this.findField = options.findField;
+    this.highlightAll = options.highlightAllCheckbox;
+    this.caseSensitive = options.caseSensitiveCheckbox;
+    this.findMsg = options.findMsg;
+    this.findStatusIcon = options.findStatusIcon;
+    this.findPreviousButton = options.findPreviousButton;
+    this.findNextButton = options.findNextButton;
+
+    var self = this;
+    this.toggleButton.addEventListener('click', function() {
+      self.toggle();
+    });
+
+    this.findField.addEventListener('input', function() {
+      self.dispatchEvent('');
+    });
+
+    this.bar.addEventListener('keydown', function(evt) {
+      switch (evt.keyCode) {
+        case 13: // Enter
+          if (evt.target === self.findField) {
+            self.dispatchEvent('again', evt.shiftKey);
+          }
+          break;
+        case 27: // Escape
+          self.close();
+          break;
+      }
+    });
+
+    this.findPreviousButton.addEventListener('click',
+      function() { self.dispatchEvent('again', true); }
+    );
+
+    this.findNextButton.addEventListener('click', function() {
+      self.dispatchEvent('again', false);
+    });
+
+    this.highlightAll.addEventListener('click', function() {
+      self.dispatchEvent('highlightallchange');
+    });
+
+    this.caseSensitive.addEventListener('click', function() {
+      self.dispatchEvent('casesensitivitychange');
+    });
+  },
+
+  dispatchEvent: function(aType, aFindPrevious) {
+    var event = document.createEvent('CustomEvent');
+    event.initCustomEvent('find' + aType, true, true, {
+      query: this.findField.value,
+      caseSensitive: this.caseSensitive.checked,
+      highlightAll: this.highlightAll.checked,
+      findPrevious: aFindPrevious
+    });
+    return window.dispatchEvent(event);
+  },
+
+  updateUIState: function(state, previous) {
+    var notFound = false;
+    var findMsg = '';
+    var status = '';
+
+    switch (state) {
+      case FindStates.FIND_FOUND:
+        break;
+
+      case FindStates.FIND_PENDING:
+        status = 'pending';
+        break;
+
+      case FindStates.FIND_NOTFOUND:
+        findMsg = mozL10n.get('find_not_found', null, 'Phrase not found');
+        notFound = true;
+        break;
+
+      case FindStates.FIND_WRAPPED:
+        if (previous) {
+          findMsg = mozL10n.get('find_reached_top', null,
+                      'Reached top of document, continued from bottom');
+        } else {
+          findMsg = mozL10n.get('find_reached_bottom', null,
+                                'Reached end of document, continued from top');
+        }
+        break;
+    }
+
+    if (notFound) {
+      this.findField.classList.add('notFound');
+    } else {
+      this.findField.classList.remove('notFound');
+    }
+
+    this.findField.setAttribute('data-status', status);
+    this.findMsg.textContent = findMsg;
+  },
+
+  open: function() {
+    if (!this.opened) {
+      this.opened = true;
+      this.toggleButton.classList.add('toggled');
+      this.bar.classList.remove('hidden');
+    }
+
+    this.findField.select();
+    this.findField.focus();
+  },
+
+  close: function() {
+    if (!this.opened) return;
+
+    this.opened = false;
+    this.toggleButton.classList.remove('toggled');
+    this.bar.classList.add('hidden');
+
+    PDFFindController.active = false;
+  },
+
+  toggle: function() {
+    if (this.opened) {
+      this.close();
+    } else {
+      this.open();
+    }
+  }
+};
+
+
+
+/* globals PDFFindBar, PDFJS, FindStates, FirefoxCom, Promise */
+
+/**
+ * Provides a "search" or "find" functionality for the PDF.
+ * This object actually performs the search for a given string.
+ */
+
+var PDFFindController = {
+  startedTextExtraction: false,
+
+  extractTextPromises: [],
+
+  pendingFindMatches: {},
+
+  // If active, find results will be highlighted.
+  active: false,
+
+  // Stores the text for each page.
+  pageContents: [],
+
+  pageMatches: [],
+
+  // Currently selected match.
+  selected: {
+    pageIdx: -1,
+    matchIdx: -1
+  },
+
+  // Where find algorithm currently is in the document.
+  offset: {
+    pageIdx: null,
+    matchIdx: null
+  },
+
+  resumePageIdx: null,
+
+  resumeCallback: null,
+
+  state: null,
+
+  dirtyMatch: false,
+
+  findTimeout: null,
+
+  pdfPageSource: null,
+
+  integratedFind: false,
+
+  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() {
+    this.startedTextExtraction = false;
+    this.extractTextPromises = [];
+    this.active = false;
+  },
+
+  calcFindMatch: function(pageIndex) {
+    var pageContent = this.pageContents[pageIndex];
+    var query = this.state.query;
+    var caseSensitive = this.state.caseSensitive;
+    var queryLen = query.length;
+
+    if (queryLen === 0) {
+      // Do nothing the matches should be wiped out already.
+      return;
+    }
+
+    if (!caseSensitive) {
+      pageContent = pageContent.toLowerCase();
+      query = query.toLowerCase();
+    }
+
+    var matches = [];
+
+    var matchIdx = -queryLen;
+    while (true) {
+      matchIdx = pageContent.indexOf(query, matchIdx + queryLen);
+      if (matchIdx === -1) {
+        break;
+      }
+
+      matches.push(matchIdx);
+    }
+    this.pageMatches[pageIndex] = matches;
+    this.updatePage(pageIndex);
+    if (this.resumePageIdx === pageIndex) {
+      var callback = this.resumeCallback;
+      this.resumePageIdx = null;
+      this.resumeCallback = null;
+      callback();
+    }
+  },
+
+  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);
+      }));
+    }
+
+    var self = this;
+    function extractPageText(pageIndex) {
+      self.pdfPageSource.pages[pageIndex].getTextContent().then(
+        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);
+          if ((pageIndex + 1) < self.pdfPageSource.pages.length)
+            extractPageText(pageIndex + 1);
+        }
+      );
+    }
+    extractPageText(0);
+  },
+
+  handleEvent: function(e) {
+    if (this.state === null || e.type !== 'findagain') {
+      this.dirtyMatch = true;
+    }
+    this.state = e.detail;
+    this.updateUIState(FindStates.FIND_PENDING);
+
+    this.firstPagePromise.then(function() {
+      this.extractText();
+
+      clearTimeout(this.findTimeout);
+      if (e.type === 'find') {
+        // Only trigger the find action after 250ms of silence.
+        this.findTimeout = setTimeout(this.nextMatch.bind(this), 250);
+      } else {
+        this.nextMatch();
+      }
+    }.bind(this));
+  },
+
+  updatePage: function(idx) {
+    var page = this.pdfPageSource.pages[idx];
+
+    if (this.selected.pageIdx === idx) {
+      // If the page is selected, scroll the page into view, which triggers
+      // rendering the page, which adds the textLayer. Once the textLayer is
+      // build, it will scroll onto the selected match.
+      page.scrollIntoView();
+    }
+
+    if (page.textLayer) {
+      page.textLayer.updateMatches();
+    }
+  },
+
+  nextMatch: function() {
+    var previous = this.state.findPrevious;
+    var currentPageIndex = this.pdfPageSource.page - 1;
+    var numPages = this.pdfPageSource.pages.length;
+
+    this.active = true;
+
+    if (this.dirtyMatch) {
+      // Need to recalculate the matches, reset everything.
+      this.dirtyMatch = false;
+      this.selected.pageIdx = this.selected.matchIdx = -1;
+      this.offset.pageIdx = currentPageIndex;
+      this.offset.matchIdx = null;
+      this.hadMatch = false;
+      this.resumeCallback = null;
+      this.resumePageIdx = null;
+      this.pageMatches = [];
+      var self = this;
+
+      for (var i = 0; i < numPages; i++) {
+        // Wipe out any previous highlighted matches.
+        this.updatePage(i);
+
+        // As soon as the text is extracted start finding the matches.
+        if (!(i in this.pendingFindMatches)) {
+          this.pendingFindMatches[i] = true;
+          this.extractTextPromises[i].then(function(pageIdx) {
+            delete self.pendingFindMatches[pageIdx];
+            self.calcFindMatch(pageIdx);
+          });
+        }
+      }
+    }
+
+    // If there's no query there's no point in searching.
+    if (this.state.query === '') {
+      this.updateUIState(FindStates.FIND_FOUND);
+      return;
+    }
+
+    // If we're waiting on a page, we return since we can't do anything else.
+    if (this.resumeCallback) {
+      return;
+    }
+
+    var offset = this.offset;
+    // If there's already a matchIdx that means we are iterating through a
+    // page's matches.
+    if (offset.matchIdx !== null) {
+      var numPageMatches = this.pageMatches[offset.pageIdx].length;
+      if ((!previous && offset.matchIdx + 1 < numPageMatches) ||
+          (previous && offset.matchIdx > 0)) {
+        // The simple case, we just have advance the matchIdx to select the next
+        // match on the page.
+        this.hadMatch = true;
+        offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1;
+        this.updateMatch(true);
+        return;
+      }
+      // We went beyond the current page's matches, so we advance to the next
+      // page.
+      this.advanceOffsetPage(previous);
+    }
+    // Start searching through the page.
+    this.nextPageMatch();
+  },
+
+  nextPageMatch: function() {
+    if (this.resumePageIdx !== null)
+      console.error('There can only be one pending page.');
+
+    var matchesReady = function(matches) {
+      var offset = this.offset;
+      var numMatches = matches.length;
+      var previous = this.state.findPrevious;
+      if (numMatches) {
+        // There were matches for the page, so initialize the matchIdx.
+        this.hadMatch = true;
+        offset.matchIdx = previous ? numMatches - 1 : 0;
+        this.updateMatch(true);
+      } else {
+        // No matches attempt to search the next page.
+        this.advanceOffsetPage(previous);
+        if (offset.wrapped) {
+          offset.matchIdx = null;
+          if (!this.hadMatch) {
+            // No point in wrapping there were no matches.
+            this.updateMatch(false);
+            return;
+          }
+        }
+        // Search the next page.
+        this.nextPageMatch();
+      }
+    }.bind(this);
+
+    var pageIdx = this.offset.pageIdx;
+    var pageMatches = this.pageMatches;
+    if (!pageMatches[pageIdx]) {
+      // The matches aren't ready setup a callback so we can be notified,
+      // when they are ready.
+      this.resumeCallback = function() {
+        matchesReady(pageMatches[pageIdx]);
+      };
+      this.resumePageIdx = pageIdx;
+      return;
+    }
+    // The matches are finished already.
+    matchesReady(pageMatches[pageIdx]);
+  },
+
+  advanceOffsetPage: function(previous) {
+    var offset = this.offset;
+    var numPages = this.extractTextPromises.length;
+    offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1;
+    offset.matchIdx = null;
+    if (offset.pageIdx >= numPages || offset.pageIdx < 0) {
+      offset.pageIdx = previous ? numPages - 1 : 0;
+      offset.wrapped = true;
+      return;
+    }
+  },
+
+  updateMatch: function(found) {
+    var state = FindStates.FIND_NOTFOUND;
+    var wrapped = this.offset.wrapped;
+    this.offset.wrapped = false;
+    if (found) {
+      var previousPage = this.selected.pageIdx;
+      this.selected.pageIdx = this.offset.pageIdx;
+      this.selected.matchIdx = this.offset.matchIdx;
+      state = wrapped ? FindStates.FIND_WRAPPED : FindStates.FIND_FOUND;
+      // Update the currently selected page to wipe out any selected matches.
+      if (previousPage !== -1 && previousPage !== this.selected.pageIdx) {
+        this.updatePage(previousPage);
+      }
+    }
+    this.updateUIState(state, this.state.findPrevious);
+    if (this.selected.pageIdx !== -1) {
+      this.updatePage(this.selected.pageIdx, true);
+    }
+  },
+
+  updateUIState: function(state, previous) {
+    if (this.integratedFind) {
+      FirefoxCom.request('updateFindControlState',
+                         {result: state, findPrevious: previous});
+      return;
+    }
+    PDFFindBar.updateUIState(state, previous);
+  }
+};
+
+
+
+var PDFHistory = {
+  initialized: false,
+  initialDestination: null,
+
+  initialize: function pdfHistoryInitialize(fingerprint) {
+    if (PDFJS.disableHistory || PDFView.isViewerEmbedded) {
+      // The browsing history is only enabled when the viewer is standalone,
+      // i.e. not when it is embedded in a web page.
+      return;
+    }
+    this.initialized = true;
+    this.reInitialized = false;
+    this.allowHashChange = true;
+    this.historyUnlocked = true;
+
+    this.previousHash = window.location.hash.substring(1);
+    this.currentBookmark = '';
+    this.currentPage = 0;
+    this.updatePreviousBookmark = false;
+    this.previousBookmark = '';
+    this.previousPage = 0;
+    this.nextHashParam = '';
+
+    this.fingerprint = fingerprint;
+    this.currentUid = this.uid = 0;
+    this.current = {};
+
+    var state = window.history.state;
+    if (this._isStateObjectDefined(state)) {
+      // This corresponds to navigating back to the document
+      // from another page in the browser history.
+      if (state.target.dest) {
+        this.initialDestination = state.target.dest;
+      } else {
+        PDFView.initialBookmark = state.target.hash;
+      }
+      this.currentUid = state.uid;
+      this.uid = state.uid + 1;
+      this.current = state.target;
+    } else {
+      // This corresponds to the loading of a new document.
+      if (state && state.fingerprint &&
+          this.fingerprint !== state.fingerprint) {
+        // Reinitialize the browsing history when a new document
+        // is opened in the web viewer.
+        this.reInitialized = true;
+      }
+      this._pushOrReplaceState({ fingerprint: this.fingerprint }, true);
+    }
+
+    var self = this;
+    window.addEventListener('popstate', function pdfHistoryPopstate(evt) {
+      evt.preventDefault();
+      evt.stopPropagation();
+
+      if (!self.historyUnlocked) {
+        return;
+      }
+      if (evt.state) {
+        // Move back/forward in the history.
+        self._goTo(evt.state);
+      } else {
+        // Handle the user modifying the hash of a loaded document.
+        self.previousHash = window.location.hash.substring(1);
+
+        // If the history is empty when the hash changes,
+        // update the previous entry in the browser history.
+        if (self.uid === 0) {
+          var previousParams = (self.previousHash && self.currentBookmark &&
+                                self.previousHash !== self.currentBookmark) ?
+            { hash: self.currentBookmark, page: self.currentPage } :
+            { page: 1 };
+          self.historyUnlocked = false;
+          self.allowHashChange = false;
+          window.history.back();
+          self._pushToHistory(previousParams, false, true);
+          window.history.forward();
+          self.historyUnlocked = true;
+        }
+        self._pushToHistory({ hash: self.previousHash }, false, true);
+        self._updatePreviousBookmark();
+      }
+    }, false);
+
+    function pdfHistoryBeforeUnload() {
+      var previousParams = self._getPreviousParams(null, true);
+      if (previousParams) {
+        var replacePrevious = (!self.current.dest &&
+                               self.current.hash !== self.previousHash);
+        self._pushToHistory(previousParams, false, replacePrevious);
+        self._updatePreviousBookmark();
+      }
+      // Remove the event listener when navigating away from the document,
+      // since 'beforeunload' prevents Firefox from caching the document.
+      window.removeEventListener('beforeunload', pdfHistoryBeforeUnload, false);
+    }
+    window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false);
+
+    window.addEventListener('pageshow', function pdfHistoryPageShow(evt) {
+      // If the entire viewer (including the PDF file) is cached in the browser,
+      // we need to reattach the 'beforeunload' event listener since
+      // the 'DOMContentLoaded' event is not fired on 'pageshow'.
+      window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false);
+    }, false);
+  },
+
+  _isStateObjectDefined: function pdfHistory_isStateObjectDefined(state) {
+    return (state && state.uid >= 0 &&
+            state.fingerprint && this.fingerprint === state.fingerprint &&
+            state.target && state.target.hash) ? true : false;
+  },
+
+  _pushOrReplaceState: function pdfHistory_pushOrReplaceState(stateObj,
+                                                              replace) {
+    if (replace) {
+      window.history.replaceState(stateObj, '', document.URL);
+    } else {
+      window.history.pushState(stateObj, '', document.URL);
+    }
+  },
+
+  get isHashChangeUnlocked() {
+    if (!this.initialized) {
+      return true;
+    }
+    // If the current hash changes when moving back/forward in the history,
+    // this will trigger a 'popstate' event *as well* as a 'hashchange' event.
+    // Since the hash generally won't correspond to the exact the position
+    // stored in the history's state object, triggering the 'hashchange' event
+    // can thus corrupt the browser history.
+    //
+    // When the hash changes during a 'popstate' event, we *only* prevent the
+    // first 'hashchange' event and immediately reset allowHashChange.
+    // If it is not reset, the user would not be able to change the hash.
+
+    var temp = this.allowHashChange;
+    this.allowHashChange = true;
+    return temp;
+  },
+
+  _updatePreviousBookmark: function pdfHistory_updatePreviousBookmark() {
+    if (this.updatePreviousBookmark &&
+        this.currentBookmark && this.currentPage) {
+      this.previousBookmark = this.currentBookmark;
+      this.previousPage = this.currentPage;
+      this.updatePreviousBookmark = false;
+    }
+  },
+
+  updateCurrentBookmark: function pdfHistoryUpdateCurrentBookmark(bookmark,
+                                                                  pageNum) {
+    if (this.initialized) {
+      this.currentBookmark = bookmark.substring(1);
+      this.currentPage = pageNum | 0;
+      this._updatePreviousBookmark();
+    }
+  },
+
+  updateNextHashParam: function pdfHistoryUpdateNextHashParam(param) {
+    if (this.initialized) {
+      this.nextHashParam = param;
+    }
+  },
+
+  push: function pdfHistoryPush(params, isInitialBookmark) {
+    if (!(this.initialized && this.historyUnlocked)) {
+      return;
+    }
+    if (params.dest && !params.hash) {
+      params.hash = (this.current.hash && this.current.dest &&
+                     this.current.dest === params.dest) ?
+        this.current.hash :
+        PDFView.getDestinationHash(params.dest).split('#')[1];
+    }
+    if (params.page) {
+      params.page |= 0;
+    }
+    if (isInitialBookmark) {
+      var target = window.history.state.target;
+      if (!target) {
+        // Invoked when the user specifies an initial bookmark,
+        // thus setting PDFView.initialBookmark, when the document is loaded.
+        this._pushToHistory(params, false);
+        this.previousHash = window.location.hash.substring(1);
+      }
+      this.updatePreviousBookmark = this.nextHashParam ? false : true;
+      if (target) {
+        // If the current document is reloaded,
+        // avoid creating duplicate entries in the history.
+        this._updatePreviousBookmark();
+      }
+      return;
+    }
+    if (this.nextHashParam) {
+      if (this.nextHashParam === params.hash) {
+        this.nextHashParam = null;
+        this.updatePreviousBookmark = true;
+        return;
+      } else {
+        this.nextHashParam = null;
+      }
+    }
+
+    if (params.hash) {
+      if (this.current.hash) {
+        if (this.current.hash !== params.hash) {
+          this._pushToHistory(params, true);
+        } else {
+          if (!this.current.page && params.page) {
+            this._pushToHistory(params, false, true);
+          }
+          this.updatePreviousBookmark = true;
+        }
+      } else {
+        this._pushToHistory(params, true);
+      }
+    } else if (this.current.page && params.page &&
+               this.current.page !== params.page) {
+      this._pushToHistory(params, true);
+    }
+  },
+
+  _getPreviousParams: function pdfHistory_getPreviousParams(onlyCheckPage,
+                                                            beforeUnload) {
+    if (!(this.currentBookmark && this.currentPage)) {
+      return null;
+    } else if (this.updatePreviousBookmark) {
+      this.updatePreviousBookmark = false;
+    }
+    if (this.uid > 0 && !(this.previousBookmark && this.previousPage)) {
+      // Prevent the history from getting stuck in the current state,
+      // effectively preventing the user from going back/forward in the history.
+      //
+      // This happens if the current position in the document didn't change when
+      // the history was previously updated. The reasons for this are either:
+      // 1. The current zoom value is such that the document does not need to,
+      //    or cannot, be scrolled to display the destination.
+      // 2. The previous destination is broken, and doesn't actally point to a
+      //    position within the document.
+      //    (This is either due to a bad PDF generator, or the user making a
+      //     mistake when entering a destination in the hash parameters.)
+      return null;
+    }
+    if ((!this.current.dest && !onlyCheckPage) || beforeUnload) {
+      if (this.previousBookmark === this.currentBookmark) {
+        return null;
+      }
+    } else if (this.current.page || onlyCheckPage) {
+      if (this.previousPage === this.currentPage) {
+        return null;
+      }
+    } else {
+      return null;
+    }
+    var params = { hash: this.currentBookmark, page: this.currentPage };
+    if (PresentationMode.active) {
+      params.hash = null;
+    }
+    return params;
+  },
+
+  _stateObj: function pdfHistory_stateObj(params) {
+    return { fingerprint: this.fingerprint, uid: this.uid, target: params };
+  },
+
+  _pushToHistory: function pdfHistory_pushToHistory(params,
+                                                    addPrevious, overwrite) {
+    if (!this.initialized) {
+      return;
+    }
+    if (!params.hash && params.page) {
+      params.hash = ('page=' + params.page);
+    }
+    if (addPrevious && !overwrite) {
+      var previousParams = this._getPreviousParams();
+      if (previousParams) {
+        var replacePrevious = (!this.current.dest &&
+                               this.current.hash !== this.previousHash);
+        this._pushToHistory(previousParams, false, replacePrevious);
+      }
+    }
+    this._pushOrReplaceState(this._stateObj(params),
+                             (overwrite || this.uid === 0));
+    this.currentUid = this.uid++;
+    this.current = params;
+    this.updatePreviousBookmark = true;
+  },
+
+  _goTo: function pdfHistory_goTo(state) {
+    if (!(this.initialized && this.historyUnlocked &&
+          this._isStateObjectDefined(state))) {
+      return;
+    }
+    if (!this.reInitialized && state.uid < this.currentUid) {
+      var previousParams = this._getPreviousParams(true);
+      if (previousParams) {
+        this._pushToHistory(this.current, false);
+        this._pushToHistory(previousParams, false);
+        this.currentUid = state.uid;
+        window.history.back();
+        return;
+      }
+    }
+    this.historyUnlocked = false;
+
+    if (state.target.dest) {
+      PDFView.navigateTo(state.target.dest);
+    } else {
+      PDFView.setHash(state.target.hash);
+    }
+    this.currentUid = state.uid;
+    if (state.uid > this.uid) {
+      this.uid = state.uid;
+    }
+    this.current = state.target;
+    this.updatePreviousBookmark = true;
+
+    var currentHash = window.location.hash.substring(1);
+    if (this.previousHash !== currentHash) {
+      this.allowHashChange = false;
+    }
+    this.previousHash = currentHash;
+
+    this.historyUnlocked = true;
+  },
+
+  back: function pdfHistoryBack() {
+    this.go(-1);
+  },
+
+  forward: function pdfHistoryForward() {
+    this.go(1);
+  },
+
+  go: function pdfHistoryGo(direction) {
+    if (this.initialized && this.historyUnlocked) {
+      var state = window.history.state;
+      if (direction === -1 && state && state.uid > 0) {
+        window.history.back();
+      } else if (direction === 1 && state && state.uid < (this.uid - 1)) {
+        window.history.forward();
+      }
+    }
+  }
+};
+
+
+var SecondaryToolbar = {
+  opened: false,
+  previousContainerHeight: null,
+  newContainerHeight: null,
+
+  initialize: function secondaryToolbarInitialize(options) {
+    this.toolbar = options.toolbar;
+    this.presentationMode = options.presentationMode;
+    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.firstPage = options.firstPage;
+    this.lastPage = options.lastPage;
+    this.pageRotateCw = options.pageRotateCw;
+    this.pageRotateCcw = options.pageRotateCcw;
+
+    // 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.firstPage, handler: this.firstPageClick },
+      { element: this.lastPage, handler: this.lastPageClick },
+      { element: this.pageRotateCw, handler: this.pageRotateCwClick },
+      { 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));
+      }
+    }
+  },
+
+  // Event handling functions.
+  presentationModeClick: function secondaryToolbarPresentationModeClick(evt) {
+    this.presentationMode.request();
+    this.close();
+  },
+
+  openFileClick: function secondaryToolbarOpenFileClick(evt) {
+    document.getElementById('fileInput').click();
+    this.close(evt.target);
+  },
+
+  printClick: function secondaryToolbarPrintClick(evt) {
+    window.print();
+    this.close(evt.target);
+  },
+
+  downloadClick: function secondaryToolbarDownloadClick(evt) {
+    PDFView.download();
+    this.close(evt.target);
+  },
+
+  firstPageClick: function secondaryToolbarFirstPageClick(evt) {
+    PDFView.page = 1;
+  },
+
+  lastPageClick: function secondaryToolbarLastPageClick(evt) {
+    PDFView.page = PDFView.pdfDocument.numPages;
+  },
+
+  pageRotateCwClick: function secondaryToolbarPageRotateCwClick(evt) {
+    PDFView.rotatePages(90);
+  },
+
+  pageRotateCcwClick: function secondaryToolbarPageRotateCcwClick(evt) {
+    PDFView.rotatePages(-90);
+  },
+
+  // 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;
+    }
+    this.buttonContainer.setAttribute('style',
+      'max-height: ' + (this.newContainerHeight - SCROLLBAR_PADDING) + 'px;');
+    this.previousContainerHeight = this.newContainerHeight;
+  },
+
+  open: function secondaryToolbarOpen() {
+    if (this.opened) {
+      return;
+    }
+    this.opened = true;
+    this.toggleButton.classList.add('toggled');
+    this.toolbar.classList.remove('hidden');
+  },
+
+  close: function secondaryToolbarClose(target) {
+    if (!this.opened) {
+      return;
+    } else if (target && !this.toolbar.contains(target)) {
+      return;
+    }
+    this.opened = false;
+    this.toolbar.classList.add('hidden');
+    this.toggleButton.classList.remove('toggled');
+  },
+
+  toggle: function secondaryToolbarToggle() {
+    if (this.opened) {
+      this.close();
+    } else {
+      this.open();
+    }
+  }
+};
+
+
+var PasswordPrompt = {
+  visible: false,
+  updatePassword: null,
+  reason: null,
+  overlayContainer: null,
+  passwordField: null,
+  passwordText: null,
+  passwordSubmit: null,
+  passwordCancel: null,
+
+  initialize: function secondaryToolbarInitialize(options) {
+    this.overlayContainer = options.overlayContainer;
+    this.passwordField = options.passwordField;
+    this.passwordText = options.passwordText;
+    this.passwordSubmit = options.passwordSubmit;
+    this.passwordCancel = options.passwordCancel;
+
+    // Attach the event listeners.
+    this.passwordSubmit.addEventListener('click',
+      this.verifyPassword.bind(this));
+
+    this.passwordCancel.addEventListener('click', this.hide.bind(this));
+
+    this.passwordField.addEventListener('keydown',
+      function (e) {
+        if (e.keyCode === 13) { // Enter key
+          this.verifyPassword();
+        }
+      }.bind(this));
+
+    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.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.');
+    }
+
+    this.passwordText.textContent = promptString;
+  },
+
+  hide: function passwordPromptClose() {
+    if (!this.visible) {
+      return;
+    }
+    this.visible = false;
+    this.passwordField.value = '';
+    this.overlayContainer.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,
+  prevCoords: { x: null, y: null },
+
+  initialize: function presentationModeInitialize(options) {
+    this.container = options.container;
+    this.secondaryToolbar = options.secondaryToolbar;
+
+    this.viewer = this.container.firstElementChild;
+
+    this.firstPage = options.firstPage;
+    this.lastPage = options.lastPage;
+    this.pageRotateCw = options.pageRotateCw;
+    this.pageRotateCcw = options.pageRotateCcw;
+
+    this.firstPage.addEventListener('click', function() {
+      this.contextMenuOpen = false;
+      this.secondaryToolbar.firstPageClick();
+    }.bind(this));
+    this.lastPage.addEventListener('click', function() {
+      this.contextMenuOpen = false;
+      this.secondaryToolbar.lastPageClick();
+    }.bind(this));
+
+    this.pageRotateCw.addEventListener('click', function() {
+      this.contextMenuOpen = false;
+      this.secondaryToolbar.pageRotateCwClick();
+    }.bind(this));
+    this.pageRotateCcw.addEventListener('click', function() {
+      this.contextMenuOpen = false;
+      this.secondaryToolbar.pageRotateCcwClick();
+    }.bind(this));
+  },
+
+  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) {
+      this.container.msRequestFullscreen();
+    } else {
+      return false;
+    }
+
+    this.args = {
+      page: PDFView.page,
+      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);
+
+    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() {
+    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);
+
+    window.removeEventListener('mousemove', this.mouseMove, false);
+    window.removeEventListener('mousedown', this.mouseDown, false);
+    window.removeEventListener('contextmenu', this.contextMenu, false);
+
+    this.hideControls();
+    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));
+  },
+
+  showControls: function presentationModeShowControls() {
+    if (this.controlsTimeout) {
+      clearTimeout(this.controlsTimeout);
+    } else {
+      this.container.classList.add(SELECTOR);
+    }
+    this.controlsTimeout = setTimeout(function hideControlsTimeout() {
+      this.container.classList.remove(SELECTOR);
+      delete this.controlsTimeout;
+    }.bind(this), DELAY_BEFORE_HIDING_CONTROLS);
+  },
+
+  hideControls: function presentationModeHideControls() {
+    if (!this.controlsTimeout) {
+      return;
+    }
+    this.container.classList.remove(SELECTOR);
+    clearTimeout(this.controlsTimeout);
+    delete this.controlsTimeout;
+  },
+
+  mouseMove: function presentationModeMouseMove(evt) {
+    // Workaround for a bug in WebKit browsers that causes the 'mousemove' event
+    // to be fired when the cursor is changed. For details, see:
+    // http://code.google.com/p/chromium/issues/detail?id=103041.
+
+    var currCoords = { x: evt.clientX, y: evt.clientY };
+    var prevCoords = PresentationMode.prevCoords;
+    PresentationMode.prevCoords = currCoords;
+
+    if (currCoords.x === prevCoords.x && currCoords.y === prevCoords.y) {
+      return;
+    }
+    PresentationMode.showControls();
+  },
+
+  mouseDown: function presentationModeMouseDown(evt) {
+    var self = PresentationMode;
+    if (self.contextMenuOpen) {
+      self.contextMenuOpen = false;
+      evt.preventDefault();
+      return;
+    }
+
+    if (evt.button === 0) {
+      // Enable clicking of links in presentation mode. Please note:
+      // Only links pointing to destinations in the current PDF document work.
+      var isInternalLink = (evt.target.href &&
+                            evt.target.classList.contains('internalLink'));
+      if (!isInternalLink) {
+        // Unless an internal link was clicked, advance one page.
+        evt.preventDefault();
+        PDFView.page += (evt.shiftKey ? -1 : 1);
+      }
+    }
+  },
+
+  contextMenu: function presentationModeContextMenu(evt) {
+    PresentationMode.contextMenuOpen = true;
+  }
+};
+
+(function presentationModeClosure() {
+  function presentationModeChange(e) {
+    if (PresentationMode.isFullscreen) {
+      PresentationMode.enter();
+    } else {
+      PresentationMode.exit();
+    }
+  }
+
+  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 at 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.handTool.toggle, false);
+    }
+    // TODO: Read global prefs and call this.handTool.activate() if needed.
+  },
+
+  toggle: function handToolToggle() {
+    this.handTool.toggle();
+  },
+
+  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 PDFView = {
+  pages: [],
+  thumbnails: [],
+  currentScale: UNKNOWN_SCALE,
+  currentScaleValue: null,
+  initialBookmark: document.location.hash.substring(1),
+  container: null,
+  thumbnailContainer: null,
+  initialized: false,
+  fellback: false,
+  pdfDocument: null,
+  sidebarOpen: false,
+  pageViewScroll: null,
+  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);
+
+    var thumbnailContainer = this.thumbnailContainer =
+                             document.getElementById('thumbnailView');
+    this.thumbnailViewScroll = {};
+    this.watchScroll(thumbnailContainer, this.thumbnailViewScroll,
+                     this.renderHighestPriority.bind(this));
+
+    PDFFindBar.initialize({
+      bar: document.getElementById('findbar'),
+      toggleButton: document.getElementById('viewFind'),
+      findField: document.getElementById('findInput'),
+      highlightAllCheckbox: document.getElementById('findHighlightAll'),
+      caseSensitiveCheckbox: document.getElementById('findMatchCase'),
+      findMsg: document.getElementById('findMsg'),
+      findStatusIcon: document.getElementById('findStatusIcon'),
+      findPreviousButton: document.getElementById('findPrevious'),
+      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'),
+      firstPage: document.getElementById('firstPage'),
+      lastPage: document.getElementById('lastPage'),
+      pageRotateCw: document.getElementById('pageRotateCw'),
+      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')
+    });
+
+    PresentationMode.initialize({
+      container: container,
+      secondaryToolbar: SecondaryToolbar,
+      firstPage: document.getElementById('contextFirstPage'),
+      lastPage: document.getElementById('contextLastPage'),
+      pageRotateCw: document.getElementById('contextPageRotateCw'),
+      pageRotateCcw: document.getElementById('contextPageRotateCcw')
+    });
+
+    this.initialized = true;
+    container.addEventListener('scroll', function() {
+      self.lastScroll = Date.now();
+    }, false);
+  },
+
+  getPage: function pdfViewGetPage(n) {
+    return this.pdfDocument.getPage(n);
+  },
+
+  // Helper function to keep track whether a div was scrolled up or down and
+  // then call a callback.
+  watchScroll: function pdfViewWatchScroll(viewAreaElement, state, callback) {
+    state.down = true;
+    state.lastY = viewAreaElement.scrollTop;
+    viewAreaElement.addEventListener('scroll', function webViewerScroll(evt) {
+      var currentY = viewAreaElement.scrollTop;
+      var lastY = state.lastY;
+      if (currentY > lastY)
+        state.down = true;
+      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);
+    } 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) {
+        case 'page-actual':
+          scale = 1;
+          break;
+        case 'page-width':
+          scale = pageWidthScale;
+          break;
+        case 'page-height':
+          scale = pageHeightScale;
+          break;
+        case 'page-fit':
+          scale = Math.min(pageWidthScale, pageHeightScale);
+          break;
+        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);
+
+      selectScaleOption(value);
+    }
+  },
+
+  zoomIn: function pdfViewZoomIn(ticks) {
+    var newScale = this.currentScale;
+    do {
+      newScale = (newScale * DEFAULT_SCALE_DELTA).toFixed(2);
+      newScale = Math.ceil(newScale * 10) / 10;
+      newScale = Math.min(MAX_SCALE, newScale);
+    } while (--ticks && newScale < MAX_SCALE);
+    this.setScale(newScale, true);
+  },
+
+  zoomOut: function pdfViewZoomOut(ticks) {
+    var newScale = this.currentScale;
+    do {
+      newScale = (newScale / DEFAULT_SCALE_DELTA).toFixed(2);
+      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 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;
+    }
+
+    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) {
+      return;
+    }
+    // Avoid scrolling the first page during loading
+    if (this.loading && val === 1) {
+      return;
+    }
+    pages[val - 1].scrollIntoView();
+  },
+
+  get page() {
+    return currentPageNumber;
+  },
+
+  get supportsPrinting() {
+    var canvas = document.createElement('canvas');
+    var value = 'mozPrintCallback' in canvas;
+    // shadow
+    Object.defineProperty(this, 'supportsPrinting', { value: value,
+                                                      enumerable: true,
+                                                      configurable: true,
+                                                      writable: false });
+    return value;
+  },
+
+  get supportsFullscreen() {
+    var doc = document.documentElement;
+    var support = doc.requestFullscreen || doc.mozRequestFullScreen ||
+                  doc.webkitRequestFullScreen || doc.msRequestFullscreen;
+
+    if (document.fullscreenEnabled === false ||
+        document.mozFullScreenEnabled === false ||
+        document.webkitFullscreenEnabled === false ||
+        document.msFullscreenEnabled === false) {
+      support = false;
+    } else if (this.isViewerEmbedded) {
+      // Need to check if the viewer is embedded as well, to prevent issues with
+      // presentation mode when the viewer is embedded in '<object>' tags.
+      support = false;
+    }
+
+    Object.defineProperty(this, 'supportsFullscreen', { value: support,
+                                                        enumerable: true,
+                                                        configurable: true,
+                                                        writable: false });
+    return support;
+  },
+
+  get supportsIntegratedFind() {
+    var support = false;
+    Object.defineProperty(this, 'supportsIntegratedFind', { value: support,
+                                                            enumerable: true,
+                                                            configurable: true,
+                                                            writable: false });
+    return support;
+  },
+
+  get supportsDocumentFonts() {
+    var support = true;
+    Object.defineProperty(this, 'supportsDocumentFonts', { value: support,
+                                                           enumerable: true,
+                                                           configurable: true,
+                                                           writable: false });
+    return support;
+  },
+
+  get supportsDocumentColors() {
+    var support = true;
+    Object.defineProperty(this, 'supportsDocumentColors', { value: support,
+                                                            enumerable: true,
+                                                            configurable: true,
+                                                            writable: false });
+    return support;
+  },
+
+  get loadingBar() {
+    var bar = new ProgressBar('#loadingBar', {});
+    Object.defineProperty(this, 'loadingBar', { value: bar,
+                                                enumerable: true,
+                                                configurable: true,
+                                                writable: false });
+    return bar;
+  },
+
+  get isHorizontalScrollbarEnabled() {
+    return (PresentationMode.active ? false :
+            (this.container.scrollWidth > this.container.clientWidth));
+  },
+
+  initPassiveLoading: function pdfViewInitPassiveLoading() {
+    var pdfDataRangeTransport = {
+      rangeListeners: [],
+      progressListeners: [],
+
+      addRangeListener: function PdfDataRangeTransport_addRangeListener(
+                                   listener) {
+        this.rangeListeners.push(listener);
+      },
+
+      addProgressListener: function PdfDataRangeTransport_addProgressListener(
+                                      listener) {
+        this.progressListeners.push(listener);
+      },
+
+      onDataRange: function PdfDataRangeTransport_onDataRange(begin, chunk) {
+        var listeners = this.rangeListeners;
+        for (var i = 0, n = listeners.length; i < n; ++i) {
+          listeners[i](begin, chunk);
+        }
+      },
+
+      onDataProgress: function PdfDataRangeTransport_onDataProgress(loaded) {
+        var listeners = this.progressListeners;
+        for (var i = 0, n = listeners.length; i < n; ++i) {
+          listeners[i](loaded);
+        }
+      },
+
+      requestDataRange: function PdfDataRangeTransport_requestDataRange(
+                                  begin, end) {
+        FirefoxCom.request('requestDataRange', { begin: begin, end: end });
+      }
+    };
+
+    window.addEventListener('message', function windowMessage(e) {
+      var args = e.data;
+
+      if (typeof args !== 'object' || !('pdfjsLoadAction' in args))
+        return;
+      switch (args.pdfjsLoadAction) {
+        case 'supportsRangedLoading':
+          PDFView.open(args.pdfUrl, 0, undefined, pdfDataRangeTransport, {
+            length: args.length,
+            initialData: args.data
+          });
+          break;
+        case 'range':
+          pdfDataRangeTransport.onDataRange(args.begin, args.chunk);
+          break;
+        case 'rangeProgress':
+          pdfDataRangeTransport.onDataProgress(args.loaded);
+          break;
+        case 'progress':
+          PDFView.progress(args.loaded / args.total);
+          break;
+        case 'complete':
+          if (!args.data) {
+            PDFView.error(mozL10n.get('loading_error', null,
+                          'An error occurred while loading the PDF.'), e);
+            break;
+          }
+          PDFView.open(args.data, 0);
+          break;
+      }
+    });
+    FirefoxCom.requestSync('initPassiveLoading', null);
+  },
+
+  setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
+    this.url = url;
+    try {
+      this.setTitle(decodeURIComponent(getFileName(url)) || url);
+    } catch (e) {
+      // decodeURIComponent may throw URIError,
+      // fall back to using the unprocessed url in that case
+      this.setTitle(url);
+    }
+  },
+
+  setTitle: function pdfViewSetTitle(title) {
+    document.title = title;
+  },
+
+  // TODO(mack): This function signature should really be pdfViewOpen(url, args)
+  open: function pdfViewOpen(url, scale, password,
+                             pdfDataRangeTransport, args) {
+    var parameters = {password: password};
+    if (typeof url === 'string') { // URL
+      this.setTitleUsingUrl(url);
+      parameters.url = url;
+    } else if (url && 'byteLength' in url) { // ArrayBuffer
+      parameters.data = url;
+    }
+    if (args) {
+      for (var prop in args) {
+        parameters[prop] = args[prop];
+      }
+    }
+
+    this.pdfDocument = null;
+    var self = this;
+    self.loading = true;
+    var passwordNeeded = function passwordNeeded(updatePassword, reason) {
+      PasswordPrompt.updatePassword = updatePassword;
+      PasswordPrompt.reason = reason;
+      PasswordPrompt.show();
+    };
+
+    function getDocumentProgress(progressData) {
+      self.progress(progressData.loaded / progressData.total);
+    }
+
+    PDFJS.getDocument(parameters, pdfDataRangeTransport, passwordNeeded,
+                      getDocumentProgress).then(
+      function getDocumentCallback(pdfDocument) {
+        self.load(pdfDocument, scale);
+        self.loading = false;
+      },
+      function getDocumentError(message, exception) {
+        var loadingErrorMessage = mozL10n.get('loading_error', null,
+          'An error occurred while loading the PDF.');
+
+        if (exception && exception.name === 'InvalidPDFException') {
+          // change error message also for other builds
+          var loadingErrorMessage = mozL10n.get('invalid_file_error', null,
+                                        'Invalid or corrupted PDF file.');
+        }
+
+        if (exception && exception.name === 'MissingPDFException') {
+          // special message for missing PDF's
+          var loadingErrorMessage = mozL10n.get('missing_file_error', null,
+                                        'Missing PDF file.');
+
+        }
+
+        var moreInfo = {
+          message: message
+        };
+        self.error(loadingErrorMessage, moreInfo);
+        self.loading = false;
+      }
+    );
+  },
+
+  download: function pdfViewDownload() {
+    function noData() {
+      downloadManager.downloadUrl(url, filename);
+    }
+
+    var url = this.url.split('#')[0];
+    var filename = getPDFFileNameFromURL(url);
+    var downloadManager = new DownloadManager();
+    downloadManager.onerror = function (err) {
+      // This error won't really be helpful because it's likely the
+      // fallback won't work either (or is already open).
+      PDFView.error('PDF failed to download.');
+    };
+
+    if (!this.pdfDocument) { // the PDF is not ready yet
+      noData();
+      return;
+    }
+
+    this.pdfDocument.getData().then(
+      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) {
+    return;
+  },
+
+  navigateTo: function pdfViewNavigateTo(dest) {
+    var destString = '';
+    var self = this;
+
+    var goToDestination = function(destRef) {
+      self.pendingRefStr = null;
+      // dest array looks like that: <page-ref> </XYZ|FitXXX> <args..>
+      var pageNumber = destRef instanceof Object ?
+        self.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] :
+        (destRef + 1);
+      if (pageNumber) {
+        if (pageNumber > self.pages.length) {
+          pageNumber = self.pages.length;
+        }
+        var currentPage = self.pages[pageNumber - 1];
+        currentPage.scrollIntoView(dest);
+
+        // Update the browsing history.
+        PDFHistory.push({ dest: dest, hash: destString, page: pageNumber });
+      } else {
+        self.pdfDocument.getPageIndex(destRef).then(function (pageIndex) {
+          var pageNum = pageIndex + 1;
+          self.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] = pageNum;
+          goToDestination(destRef);
+        });
+      }
+    };
+
+    this.destinationsPromise.then(function() {
+      if (typeof dest === 'string') {
+        destString = dest;
+        dest = self.destinations[dest];
+      }
+      if (!(dest instanceof Array)) {
+        return; // invalid destination
+      }
+      goToDestination(dest[0]);
+    });
+  },
+
+  getDestinationHash: function pdfViewGetDestinationHash(dest) {
+    if (typeof dest === 'string')
+      return PDFView.getAnchorUrl('#' + escape(dest));
+    if (dest instanceof Array) {
+      var destRef = dest[0]; // see navigateTo method for dest format
+      var pageNumber = destRef instanceof Object ?
+        this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] :
+        (destRef + 1);
+      if (pageNumber) {
+        var pdfOpenParams = PDFView.getAnchorUrl('#page=' + pageNumber);
+        var destKind = dest[1];
+        if (typeof destKind === 'object' && 'name' in destKind &&
+            destKind.name == 'XYZ') {
+          var scale = (dest[4] || this.currentScaleValue);
+          var scaleNumber = parseFloat(scale);
+          if (scaleNumber) {
+            scale = scaleNumber * 100;
+          }
+          pdfOpenParams += '&zoom=' + scale;
+          if (dest[2] || dest[3]) {
+            pdfOpenParams += ',' + (dest[2] || 0) + ',' + (dest[3] || 0);
+          }
+        }
+        return pdfOpenParams;
+      }
+    }
+    return '';
+  },
+
+  /**
+   * Prefix the full url on anchor links to make sure that links are resolved
+   * relative to the current URL instead of the one defined in <base href>.
+   * @param {String} anchor The anchor hash, including the #.
+   */
+  getAnchorUrl: function getAnchorUrl(anchor) {
+    return anchor;
+  },
+
+  /**
+   * Show the error box.
+   * @param {String} message A message that is human readable.
+   * @param {Object} moreInfo (optional) Further information about the error
+   *                            that is more technical.  Should have a 'message'
+   *                            and optionally a 'stack' property.
+   */
+  error: function pdfViewError(message, moreInfo) {
+    var moreInfoText = mozL10n.get('error_version_info',
+      {version: PDFJS.version || '?', build: PDFJS.build || '?'},
+      'PDF.js v{{version}} (build: {{build}})') + '\n';
+    if (moreInfo) {
+      moreInfoText +=
+        mozL10n.get('error_message', {message: moreInfo.message},
+        'Message: {{message}}');
+      if (moreInfo.stack) {
+        moreInfoText += '\n' +
+          mozL10n.get('error_stack', {stack: moreInfo.stack},
+          'Stack: {{stack}}');
+      } else {
+        if (moreInfo.filename) {
+          moreInfoText += '\n' +
+            mozL10n.get('error_file', {file: moreInfo.filename},
+            'File: {{file}}');
+        }
+        if (moreInfo.lineNumber) {
+          moreInfoText += '\n' +
+            mozL10n.get('error_line', {line: moreInfo.lineNumber},
+            'Line: {{line}}');
+        }
+      }
+    }
+
+    var errorWrapper = document.getElementById('errorWrapper');
+    errorWrapper.removeAttribute('hidden');
+
+    var errorMessage = document.getElementById('errorMessage');
+    errorMessage.textContent = message;
+
+    var closeButton = document.getElementById('errorClose');
+    closeButton.onclick = function() {
+      errorWrapper.setAttribute('hidden', 'true');
+    };
+
+    var errorMoreInfo = document.getElementById('errorMoreInfo');
+    var moreInfoButton = document.getElementById('errorShowMore');
+    var lessInfoButton = document.getElementById('errorShowLess');
+    moreInfoButton.onclick = function() {
+      errorMoreInfo.removeAttribute('hidden');
+      moreInfoButton.setAttribute('hidden', 'true');
+      lessInfoButton.removeAttribute('hidden');
+      errorMoreInfo.style.height = errorMoreInfo.scrollHeight + 'px';
+    };
+    lessInfoButton.onclick = function() {
+      errorMoreInfo.setAttribute('hidden', 'true');
+      moreInfoButton.removeAttribute('hidden');
+      lessInfoButton.setAttribute('hidden', 'true');
+    };
+    moreInfoButton.oncontextmenu = noContextMenuHandler;
+    lessInfoButton.oncontextmenu = noContextMenuHandler;
+    closeButton.oncontextmenu = noContextMenuHandler;
+    moreInfoButton.removeAttribute('hidden');
+    lessInfoButton.setAttribute('hidden', 'true');
+    errorMoreInfo.value = moreInfoText;
+  },
+
+  progress: function pdfViewProgress(level) {
+    var percent = Math.round(level * 100);
+    // When we transition from full request to range requests, it's possible
+    // that we discard some of the loaded data. This can cause the loading
+    // bar to move backwards. So prevent this by only updating the bar if it
+    // increases.
+    if (percent > PDFView.loadingBar.percent) {
+      PDFView.loadingBar.percent = percent;
+    }
+  },
+
+  load: function pdfViewLoad(pdfDocument, scale) {
+    var self = this;
+    var isOnePageRenderedResolved = false;
+    var resolveOnePageRendered = null;
+    var onePageRendered = new Promise(function (resolve) {
+      resolveOnePageRendered = resolve;
+    });
+    function bindOnAfterDraw(pageView, thumbnailView) {
+      // when page is painted, using the image as thumbnail base
+      pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() {
+        if (!isOnePageRenderedResolved) {
+          isOnePageRenderedResolved = true;
+          resolveOnePageRendered();
+        }
+        thumbnailView.setImage(pageView.canvas);
+      };
+    }
+
+    PDFFindController.reset();
+
+    this.pdfDocument = pdfDocument;
+
+    var errorWrapper = document.getElementById('errorWrapper');
+    errorWrapper.setAttribute('hidden', 'true');
+
+    pdfDocument.dataLoaded().then(function() {
+      PDFView.loadingBar.hide();
+      var outerContainer = document.getElementById('outerContainer');
+      outerContainer.classList.remove('loadingInProgress');
+    });
+
+    var thumbsView = document.getElementById('thumbnailView');
+    thumbsView.parentNode.scrollTop = 0;
+
+    while (thumbsView.hasChildNodes())
+      thumbsView.removeChild(thumbsView.lastChild);
+
+    if ('_loadingInterval' in thumbsView)
+      clearInterval(thumbsView._loadingInterval);
+
+    var container = document.getElementById('viewer');
+    while (container.hasChildNodes())
+      container.removeChild(container.lastChild);
+
+    var pagesCount = pdfDocument.numPages;
+
+    var id = pdfDocument.fingerprint;
+    document.getElementById('numPages').textContent =
+      mozL10n.get('page_of', {pageCount: pagesCount}, 'of {{pageCount}}');
+    document.getElementById('pageNumber').max = pagesCount;
+
+    var prefs = PDFView.prefs = new Preferences();
+    PDFView.documentFingerprint = id;
+    var store = PDFView.store = new ViewHistory(id);
+
+    this.pageRotation = 0;
+
+    var pages = this.pages = [];
+    var pagesRefMap = this.pagesRefMap = {};
+    var thumbnails = this.thumbnails = [];
+
+    var resolvePagesPromise;
+    var pagesPromise = new Promise(function (resolve) {
+      resolvePagesPromise = resolve;
+    });
+    this.pagesPromise = pagesPromise;
+
+    var firstPagePromise = pdfDocument.getPage(1);
+
+    // Fetch a single page so we can get a viewport that will be the default
+    // viewport for all pages
+    firstPagePromise.then(function(pdfPage) {
+      var viewport = pdfPage.getViewport((scale || 1.0) * CSS_UNITS);
+      for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
+        var viewportClone = viewport.clone();
+        var pageView = new PageView(container, pageNum, scale,
+                                    self.navigateTo.bind(self),
+                                    viewportClone);
+        var thumbnailView = new ThumbnailView(thumbsView, pageNum,
+                                              viewportClone);
+        bindOnAfterDraw(pageView, thumbnailView);
+        pages.push(pageView);
+        thumbnails.push(thumbnailView);
+      }
+
+      // Fetch all the pages since the viewport is needed before printing
+      // starts to create the correct size canvas. Wait until one page is
+      // rendered so we don't tie up too many resources early on.
+      onePageRendered.then(function () {
+        if (!PDFJS.disableAutoFetch) {
+          var getPagesLeft = pagesCount;
+          for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
+            pdfDocument.getPage(pageNum).then(function (pageNum, pdfPage) {
+              var pageView = pages[pageNum - 1];
+              if (!pageView.pdfPage) {
+                pageView.setPdfPage(pdfPage);
+              }
+              var refStr = pdfPage.ref.num + ' ' + pdfPage.ref.gen + ' R';
+              pagesRefMap[refStr] = pageNum;
+              getPagesLeft--;
+              if (!getPagesLeft) {
+                resolvePagesPromise();
+              }
+            }.bind(null, pageNum));
+          }
+        } else {
+          // XXX: Printing is semi-broken with auto fetch disabled.
+          resolvePagesPromise();
+        }
+      });
+
+      var event = document.createEvent('CustomEvent');
+      event.initCustomEvent('documentload', true, true, {});
+      window.dispatchEvent(event);
+
+      PDFView.loadingBar.setWidth(container);
+
+      PDFFindController.resolveFirstPage();
+    });
+
+    var prefsPromise = prefs.initializedPromise;
+    var storePromise = store.initializedPromise;
+    Promise.all([firstPagePromise, prefsPromise, storePromise]).
+        then(function() {
+      var showPreviousViewOnLoad = prefs.get('showPreviousViewOnLoad');
+      var defaultZoomValue = prefs.get('defaultZoomValue');
+
+      var storedHash = null;
+      if (showPreviousViewOnLoad && store.get('exists', false)) {
+        var pageNum = store.get('page', '1');
+        var zoom = defaultZoomValue || store.get('zoom', PDFView.currentScale);
+        var left = store.get('scrollLeft', '0');
+        var top = store.get('scrollTop', '0');
+
+        storedHash = 'page=' + pageNum + '&zoom=' + zoom + ',' +
+                     left + ',' + top;
+      } else if (defaultZoomValue) {
+        storedHash = 'page=1&zoom=' + defaultZoomValue;
+      }
+      // Initialize the browsing history.
+      PDFHistory.initialize(self.documentFingerprint);
+
+      self.setInitialView(storedHash, scale);
+
+      // Make all navigation keys work on document load,
+      // unless the viewer is embedded in a web page.
+      if (!self.isViewerEmbedded) {
+        self.container.focus();
+      }
+    });
+
+    pagesPromise.then(function() {
+      if (PDFView.supportsPrinting) {
+        pdfDocument.getJavaScript().then(function(javaScript) {
+          if (javaScript.length) {
+            console.warn('Warning: JavaScript is not supported');
+            PDFView.fallback(PDFJS.UNSUPPORTED_FEATURES.javaScript);
+          }
+          // Hack to support auto printing.
+          var regex = /\bprint\s*\(/g;
+          for (var i = 0, ii = javaScript.length; i < ii; i++) {
+            var js = javaScript[i];
+            if (js && regex.test(js)) {
+              setTimeout(function() {
+                window.print();
+              });
+              return;
+            }
+          }
+        });
+      }
+    });
+
+    var destinationsPromise =
+      this.destinationsPromise = pdfDocument.getDestinations();
+    destinationsPromise.then(function(destinations) {
+      self.destinations = destinations;
+    });
+
+    // outline depends on destinations and pagesRefMap
+    var promises = [pagesPromise, destinationsPromise,
+                    PDFView.animationStartedPromise];
+    Promise.all(promises).then(function() {
+      pdfDocument.getOutline().then(function(outline) {
+        self.outline = new DocumentOutlineView(outline);
+        document.getElementById('viewOutline').disabled = !outline;
+
+        if (outline && prefs.get('ifAvailableShowOutlineOnLoad')) {
+          if (!self.sidebarOpen) {
+            document.getElementById('sidebarToggle').click();
+          }
+          self.switchSidebarView('outline');
+        }
+      });
+    });
+
+    pdfDocument.getMetadata().then(function(data) {
+      var info = data.info, metadata = data.metadata;
+      self.documentInfo = info;
+      self.metadata = metadata;
+
+      // Provides some basic debug information
+      console.log('PDF ' + pdfDocument.fingerprint + ' [' +
+                  info.PDFFormatVersion + ' ' + (info.Producer || '-') +
+                  ' / ' + (info.Creator || '-') + ']' +
+                  (PDFJS.version ? ' (PDF.js: ' + PDFJS.version + ')' : ''));
+
+      var pdfTitle;
+      if (metadata) {
+        if (metadata.has('dc:title'))
+          pdfTitle = metadata.get('dc:title');
+      }
+
+      if (!pdfTitle && info && info['Title'])
+        pdfTitle = info['Title'];
+
+      if (pdfTitle)
+        self.setTitle(pdfTitle + ' - ' + document.title);
+
+      if (info.IsAcroFormPresent) {
+        console.warn('Warning: AcroForm/XFA is not supported');
+        PDFView.fallback(PDFJS.UNSUPPORTED_FEATURES.forms);
+      }
+
+    });
+  },
+
+  setInitialView: function pdfViewSetInitialView(storedHash, scale) {
+    // Reset the current scale, as otherwise the page's scale might not get
+    // updated if the zoom level stayed the same.
+    this.currentScale = 0;
+    this.currentScaleValue = null;
+    // When opening a new file (when one is already loaded in the viewer):
+    // Reset 'currentPageNumber', since otherwise the page's scale will be wrong
+    // if 'currentPageNumber' is larger than the number of pages in the file.
+    document.getElementById('pageNumber').value = currentPageNumber = 1;
+    // Reset the current position when loading a new file,
+    // to prevent displaying the wrong position in the document.
+    this.currentPosition = null;
+
+    if (PDFHistory.initialDestination) {
+      this.navigateTo(PDFHistory.initialDestination);
+      PDFHistory.initialDestination = null;
+    } else if (this.initialBookmark) {
+      this.setHash(this.initialBookmark);
+      PDFHistory.push({ hash: this.initialBookmark }, !!this.initialBookmark);
+      this.initialBookmark = null;
+    } else if (storedHash) {
+      this.setHash(storedHash);
+    } else if (scale) {
+      this.setScale(scale, true);
+      this.page = 1;
+    }
+
+    if (PDFView.currentScale === UNKNOWN_SCALE) {
+      // Scale was not initialized: invalid bookmark or scale was not specified.
+      // Setting the default one.
+      this.setScale(DEFAULT_SCALE, true);
+    }
+  },
+
+  renderHighestPriority: function pdfViewRenderHighestPriority() {
+    if (PDFView.idleTimeout) {
+      clearTimeout(PDFView.idleTimeout);
+      PDFView.idleTimeout = null;
+    }
+
+    // Pages have a higher priority than thumbnails, so check them first.
+    var visiblePages = this.getVisiblePages();
+    var pageView = this.getHighestPriority(visiblePages, this.pages,
+                                           this.pageViewScroll.down);
+    if (pageView) {
+      this.renderView(pageView, 'page');
+      return;
+    }
+    // No pages needed rendering so check thumbnails.
+    if (this.sidebarOpen) {
+      var visibleThumbs = this.getVisibleThumbs();
+      var thumbView = this.getHighestPriority(visibleThumbs,
+                                              this.thumbnails,
+                                              this.thumbnailViewScroll.down);
+      if (thumbView) {
+        this.renderView(thumbView, 'thumbnail');
+        return;
+      }
+    }
+
+    PDFView.idleTimeout = setTimeout(function () {
+      PDFView.cleanup();
+    }, CLEANUP_TIMEOUT);
+  },
+
+  cleanup: function pdfViewCleanup() {
+    for (var i = 0, ii = this.pages.length; i < ii; i++) {
+      if (this.pages[i] &&
+          this.pages[i].renderingState !== RenderingStates.FINISHED) {
+        this.pages[i].reset();
+      }
+    }
+    this.pdfDocument.cleanup();
+  },
+
+  getHighestPriority: function pdfViewGetHighestPriority(visible, views,
+                                                         scrolledDown) {
+    // The state has changed figure out which page has the highest priority to
+    // render next (if any).
+    // Priority:
+    // 1 visible pages
+    // 2 if last scrolled down page after the visible pages
+    // 2 if last scrolled up page before the visible pages
+    var visibleViews = visible.views;
+
+    var numVisible = visibleViews.length;
+    if (numVisible === 0) {
+      return false;
+    }
+    for (var i = 0; i < numVisible; ++i) {
+      var view = visibleViews[i].view;
+      if (!this.isViewFinished(view))
+        return view;
+    }
+
+    // All the visible views have rendered, try to render next/previous pages.
+    if (scrolledDown) {
+      var nextPageIndex = visible.last.id;
+      // ID's start at 1 so no need to add 1.
+      if (views[nextPageIndex] && !this.isViewFinished(views[nextPageIndex]))
+        return views[nextPageIndex];
+    } else {
+      var previousPageIndex = visible.first.id - 2;
+      if (views[previousPageIndex] &&
+          !this.isViewFinished(views[previousPageIndex]))
+        return views[previousPageIndex];
+    }
+    // Everything that needs to be rendered has been.
+    return false;
+  },
+
+  isViewFinished: function pdfViewIsViewFinished(view) {
+    return view.renderingState === RenderingStates.FINISHED;
+  },
+
+  // Render a page or thumbnail view. This calls the appropriate function based
+  // on the views state. If the view is already rendered it will return false.
+  renderView: function pdfViewRender(view, type) {
+    var state = view.renderingState;
+    switch (state) {
+      case RenderingStates.FINISHED:
+        return false;
+      case RenderingStates.PAUSED:
+        PDFView.highestPriorityPage = type + view.id;
+        view.resume();
+        break;
+      case RenderingStates.RUNNING:
+        PDFView.highestPriorityPage = type + view.id;
+        break;
+      case RenderingStates.INITIAL:
+        PDFView.highestPriorityPage = type + view.id;
+        view.draw(this.renderHighestPriority.bind(this));
+        break;
+    }
+    return true;
+  },
+
+  setHash: function pdfViewSetHash(hash) {
+    if (!hash)
+      return;
+
+    if (hash.indexOf('=') >= 0) {
+      var params = PDFView.parseQueryString(hash);
+      // borrowing syntax from "Parameters for Opening PDF Files"
+      if ('nameddest' in params) {
+        PDFHistory.updateNextHashParam(params.nameddest);
+        PDFView.navigateTo(params.nameddest);
+        return;
+      }
+      var pageNumber, dest;
+      if ('page' in params) {
+        pageNumber = (params.page | 0) || 1;
+      }
+      if ('zoom' in params) {
+        var zoomArgs = params.zoom.split(','); // scale,left,top
+        // building destination array
+
+        // If the zoom value, it has to get divided by 100. If it is a string,
+        // it should stay as it is.
+        var zoomArg = zoomArgs[0];
+        var zoomArgNumber = parseFloat(zoomArg);
+        if (zoomArgNumber) {
+          zoomArg = zoomArgNumber / 100;
+        }
+        dest = [null, {name: 'XYZ'},
+                zoomArgs.length > 1 ? (zoomArgs[1] | 0) : null,
+                zoomArgs.length > 2 ? (zoomArgs[2] | 0) : null,
+                zoomArg];
+      }
+      if (dest) {
+        var currentPage = this.pages[(pageNumber || this.page) - 1];
+        currentPage.scrollIntoView(dest);
+      } else if (pageNumber) {
+        this.page = pageNumber; // simple page
+      }
+      if ('pagemode' in params) {
+        var toggle = document.getElementById('sidebarToggle');
+        if (params.pagemode === 'thumbs' || params.pagemode === 'bookmarks') {
+          if (!this.sidebarOpen) {
+            toggle.click();
+          }
+          this.switchSidebarView(params.pagemode === 'thumbs' ?
+                                 'thumbs' : 'outline');
+        } else if (params.pagemode === 'none' && this.sidebarOpen) {
+          toggle.click();
+        }
+      }
+    } else if (/^\d+$/.test(hash)) { // page number
+      this.page = hash;
+    } else { // named destination
+      PDFHistory.updateNextHashParam(unescape(hash));
+      PDFView.navigateTo(unescape(hash));
+    }
+  },
+
+  switchSidebarView: function pdfViewSwitchSidebarView(view) {
+    var thumbsView = document.getElementById('thumbnailView');
+    var outlineView = document.getElementById('outlineView');
+
+    var thumbsButton = document.getElementById('viewThumbnail');
+    var outlineButton = document.getElementById('viewOutline');
+
+    switch (view) {
+      case 'thumbs':
+        var wasOutlineViewVisible = thumbsView.classList.contains('hidden');
+
+        thumbsButton.classList.add('toggled');
+        outlineButton.classList.remove('toggled');
+        thumbsView.classList.remove('hidden');
+        outlineView.classList.add('hidden');
+
+        PDFView.renderHighestPriority();
+
+        if (wasOutlineViewVisible) {
+          // Ensure that the thumbnail of the current page is visible
+          // when switching from the outline view.
+          scrollIntoView(document.getElementById('thumbnailContainer' +
+                                                 this.page));
+        }
+        break;
+
+      case 'outline':
+        thumbsButton.classList.remove('toggled');
+        outlineButton.classList.add('toggled');
+        thumbsView.classList.add('hidden');
+        outlineView.classList.remove('hidden');
+
+        if (outlineButton.getAttribute('disabled'))
+          return;
+        break;
+    }
+  },
+
+  getVisiblePages: function pdfViewGetVisiblePages() {
+    return this.getVisibleElements(this.container, this.pages,
+                                   !PresentationMode.active);
+  },
+
+  getVisibleThumbs: function pdfViewGetVisibleThumbs() {
+    return this.getVisibleElements(this.thumbnailContainer, this.thumbnails);
+  },
+
+  // Generic helper to find out what elements are visible within a scroll pane.
+  getVisibleElements: function pdfViewGetVisibleElements(
+      scrollEl, views, sortByVisibility) {
+    var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight;
+    var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth;
+
+    var visible = [], view;
+    var currentHeight, viewHeight, hiddenHeight, percentHeight;
+    var currentWidth, viewWidth;
+    for (var i = 0, ii = views.length; i < ii; ++i) {
+      view = views[i];
+      currentHeight = view.el.offsetTop + view.el.clientTop;
+      viewHeight = view.el.clientHeight;
+      if ((currentHeight + viewHeight) < top) {
+        continue;
+      }
+      if (currentHeight > bottom) {
+        break;
+      }
+      currentWidth = view.el.offsetLeft + view.el.clientLeft;
+      viewWidth = view.el.clientWidth;
+      if ((currentWidth + viewWidth) < left || currentWidth > right) {
+        continue;
+      }
+      hiddenHeight = Math.max(0, top - currentHeight) +
+                     Math.max(0, currentHeight + viewHeight - bottom);
+      percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0;
+
+      visible.push({ id: view.id, x: currentWidth, y: currentHeight,
+                     view: view, percent: percentHeight });
+    }
+
+    var first = visible[0];
+    var last = visible[visible.length - 1];
+
+    if (sortByVisibility) {
+      visible.sort(function(a, b) {
+        var pc = a.percent - b.percent;
+        if (Math.abs(pc) > 0.001) {
+          return -pc;
+        }
+        return a.id - b.id; // ensure stability
+      });
+    }
+    return {first: first, last: last, views: visible};
+  },
+
+  // Helper function to parse query string (e.g. ?param1=value&parm2=...).
+  parseQueryString: function pdfViewParseQueryString(query) {
+    var parts = query.split('&');
+    var params = {};
+    for (var i = 0, ii = parts.length; i < parts.length; ++i) {
+      var param = parts[i].split('=');
+      var key = param[0];
+      var value = param.length > 1 ? param[1] : null;
+      params[decodeURIComponent(key)] = decodeURIComponent(value);
+    }
+    return params;
+  },
+
+  beforePrint: function pdfViewSetupBeforePrint() {
+    if (!this.supportsPrinting) {
+      var printMessage = mozL10n.get('printing_not_supported', null,
+          'Warning: Printing is not fully supported by this browser.');
+      this.error(printMessage);
+      return;
+    }
+
+    var alertNotReady = false;
+    if (!this.pages.length) {
+      alertNotReady = true;
+    } else {
+      for (var i = 0, ii = this.pages.length; i < ii; ++i) {
+        if (!this.pages[i].pdfPage) {
+          alertNotReady = true;
+          break;
+        }
+      }
+    }
+    if (alertNotReady) {
+      var notReadyMessage = mozL10n.get('printing_not_ready', null,
+          'Warning: The PDF is not fully loaded for printing.');
+      window.alert(notReadyMessage);
+      return;
+    }
+
+    var body = document.querySelector('body');
+    body.setAttribute('data-mozPrintCallback', true);
+    for (var i = 0, ii = this.pages.length; i < ii; ++i) {
+      this.pages[i].beforePrint();
+    }
+  },
+
+  afterPrint: function pdfViewSetupAfterPrint() {
+    var div = document.getElementById('printContainer');
+    while (div.hasChildNodes())
+      div.removeChild(div.lastChild);
+  },
+
+  rotatePages: function pdfViewRotatePages(delta) {
+    var currentPage = this.pages[this.page - 1];
+    this.pageRotation = (this.pageRotation + 360 + delta) % 360;
+
+    for (var i = 0, l = this.pages.length; i < l; i++) {
+      var page = this.pages[i];
+      page.update(page.scale, this.pageRotation);
+    }
+
+    for (var i = 0, l = this.thumbnails.length; i < l; i++) {
+      var thumb = this.thumbnails[i];
+      thumb.update(this.pageRotation);
+    }
+
+    this.setScale(this.currentScaleValue, true, true);
+
+    this.renderHighestPriority();
+
+    if (currentPage) {
+      currentPage.scrollIntoView();
+    }
+  },
+
+  /**
+   * This function flips the page in presentation mode if the user scrolls up
+   * or down with large enough motion and prevents page flipping too often.
+   *
+   * @this {PDFView}
+   * @param {number} mouseScrollDelta The delta value from the mouse event.
+   */
+  mouseScroll: function pdfViewMouseScroll(mouseScrollDelta) {
+    var MOUSE_SCROLL_COOLDOWN_TIME = 50;
+
+    var currentTime = (new Date()).getTime();
+    var storedTime = this.mouseScrollTimeStamp;
+
+    // In case one page has already been flipped there is a cooldown time
+    // which has to expire before next page can be scrolled on to.
+    if (currentTime > storedTime &&
+        currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME)
+      return;
+
+    // In case the user decides to scroll to the opposite direction than before
+    // clear the accumulated delta.
+    if ((this.mouseScrollDelta > 0 && mouseScrollDelta < 0) ||
+        (this.mouseScrollDelta < 0 && mouseScrollDelta > 0))
+      this.clearMouseScrollState();
+
+    this.mouseScrollDelta += mouseScrollDelta;
+
+    var PAGE_FLIP_THRESHOLD = 120;
+    if (Math.abs(this.mouseScrollDelta) >= PAGE_FLIP_THRESHOLD) {
+
+      var PageFlipDirection = {
+        UP: -1,
+        DOWN: 1
+      };
+
+      // In presentation mode scroll one page at a time.
+      var pageFlipDirection = (this.mouseScrollDelta > 0) ?
+                                PageFlipDirection.UP :
+                                PageFlipDirection.DOWN;
+      this.clearMouseScrollState();
+      var currentPage = this.page;
+
+      // In case we are already on the first or the last page there is no need
+      // to do anything.
+      if ((currentPage == 1 && pageFlipDirection == PageFlipDirection.UP) ||
+          (currentPage == this.pages.length &&
+           pageFlipDirection == PageFlipDirection.DOWN))
+        return;
+
+      this.page += pageFlipDirection;
+      this.mouseScrollTimeStamp = currentTime;
+    }
+  },
+
+  /**
+   * This function clears the member attributes used with mouse scrolling in
+   * presentation mode.
+   *
+   * @this {PDFView}
+   */
+  clearMouseScrollState: function pdfViewClearMouseScrollState() {
+    this.mouseScrollTimeStamp = 0;
+    this.mouseScrollDelta = 0;
+  }
+};
+
+
+var PageView = function pageView(container, id, scale,
+                                 navigateTo, defaultViewport) {
+  this.id = id;
+
+  this.rotation = 0;
+  this.scale = scale || 1.0;
+  this.viewport = defaultViewport;
+  this.pdfPageRotate = defaultViewport.rotation;
+
+  this.renderingState = RenderingStates.INITIAL;
+  this.resume = null;
+
+  this.textLayer = null;
+
+  this.zoomLayer = null;
+
+  this.annotationLayer = null;
+
+  var anchor = document.createElement('a');
+  anchor.name = '' + this.id;
+
+  var div = this.el = document.createElement('div');
+  div.id = 'pageContainer' + this.id;
+  div.className = 'page';
+  div.style.width = Math.floor(this.viewport.width) + 'px';
+  div.style.height = Math.floor(this.viewport.height) + 'px';
+
+  container.appendChild(anchor);
+  container.appendChild(div);
+
+  this.setPdfPage = function pageViewSetPdfPage(pdfPage) {
+    this.pdfPage = pdfPage;
+    this.pdfPageRotate = pdfPage.rotate;
+    var totalRotation = (this.rotation + this.pdfPageRotate) % 360;
+    this.viewport = pdfPage.getViewport(this.scale * CSS_UNITS, totalRotation);
+    this.stats = pdfPage.stats;
+    this.reset();
+  };
+
+  this.destroy = function pageViewDestroy() {
+    this.zoomLayer = null;
+    this.reset();
+    if (this.pdfPage) {
+      this.pdfPage.destroy();
+    }
+  };
+
+  this.reset = function pageViewReset() {
+    if (this.renderTask) {
+      this.renderTask.cancel();
+    }
+    this.resume = null;
+    this.renderingState = RenderingStates.INITIAL;
+
+    div.style.width = Math.floor(this.viewport.width) + 'px';
+    div.style.height = Math.floor(this.viewport.height) + 'px';
+
+    var childNodes = div.childNodes;
+    for (var i = div.childNodes.length - 1; i >= 0; i--) {
+      var node = childNodes[i];
+      if (this.zoomLayer && this.zoomLayer === node) {
+        continue;
+      }
+      div.removeChild(node);
+    }
+    div.removeAttribute('data-loaded');
+
+    this.annotationLayer = null;
+
+    delete this.canvas;
+
+    this.loadingIconDiv = document.createElement('div');
+    this.loadingIconDiv.className = 'loadingIcon';
+    div.appendChild(this.loadingIconDiv);
+  };
+
+  this.update = function pageViewUpdate(scale, rotation) {
+    this.scale = scale || this.scale;
+
+    if (typeof rotation !== 'undefined') {
+      this.rotation = rotation;
+    }
+
+    var totalRotation = (this.rotation + this.pdfPageRotate) % 360;
+    this.viewport = this.viewport.clone({
+      scale: this.scale * CSS_UNITS,
+      rotation: totalRotation
+    });
+
+    if (USE_ONLY_CSS_ZOOM && this.canvas) {
+      this.cssTransform(this.canvas);
+      return;
+    } else if (this.canvas && !this.zoomLayer) {
+      this.zoomLayer = this.canvas.parentNode;
+      this.zoomLayer.style.position = 'absolute';
+    }
+    if (this.zoomLayer) {
+      this.cssTransform(this.zoomLayer.firstChild);
+    }
+    this.reset();
+  };
+
+  this.cssTransform = function pageCssTransform(canvas) {
+    // Scale canvas, canvas wrapper, and page container.
+    var width = this.viewport.width;
+    var height = this.viewport.height;
+    canvas.style.width = canvas.parentNode.style.width = div.style.width =
+        Math.floor(width) + 'px';
+    canvas.style.height = canvas.parentNode.style.height = div.style.height =
+        Math.floor(height) + 'px';
+    // The canvas may have been originally rotated, so rotate relative to that.
+    var relativeRotation = this.viewport.rotation - canvas._viewport.rotation;
+    var absRotation = Math.abs(relativeRotation);
+    var scaleX = 1, scaleY = 1;
+    if (absRotation === 90 || absRotation === 270) {
+      // Scale x and y because of the rotation.
+      scaleX = height / width;
+      scaleY = width / height;
+    }
+    var cssTransform = 'rotate(' + relativeRotation + 'deg) ' +
+                       'scale(' + scaleX + ',' + scaleY + ')';
+    CustomStyle.setProp('transform', canvas, cssTransform);
+
+    if (this.textLayer) {
+      // Rotating the text layer is more complicated since the divs inside the
+      // the text layer are rotated.
+      // TODO: This could probably be simplified by drawing the text layer in
+      // one orientation then rotating overall.
+      var textRelativeRotation = this.viewport.rotation -
+                                 this.textLayer.viewport.rotation;
+      var textAbsRotation = Math.abs(textRelativeRotation);
+      var scale = (width / canvas.width);
+      if (textAbsRotation === 90 || textAbsRotation === 270) {
+        scale = width / canvas.height;
+      }
+      var textLayerDiv = this.textLayer.textLayerDiv;
+      var transX, transY;
+      switch (textAbsRotation) {
+        case 0:
+          transX = transY = 0;
+          break;
+        case 90:
+          transX = 0;
+          transY = '-' + textLayerDiv.style.height;
+          break;
+        case 180:
+          transX = '-' + textLayerDiv.style.width;
+          transY = '-' + textLayerDiv.style.height;
+          break;
+        case 270:
+          transX = '-' + textLayerDiv.style.width;
+          transY = 0;
+          break;
+        default:
+          console.error('Bad rotation value.');
+          break;
+      }
+      CustomStyle.setProp('transform', textLayerDiv,
+                          'rotate(' + textAbsRotation + 'deg) ' +
+                            'scale(' + scale + ', ' + scale + ') ' +
+                            'translate(' + transX + ', ' + transY + ')');
+      CustomStyle.setProp('transformOrigin', textLayerDiv, '0% 0%');
+    }
+
+    if (USE_ONLY_CSS_ZOOM && this.annotationLayer) {
+      setupAnnotations(div, this.pdfPage, this.viewport);
+    }
+  };
+
+  Object.defineProperty(this, 'width', {
+    get: function PageView_getWidth() {
+      return this.viewport.width;
+    },
+    enumerable: true
+  });
+
+  Object.defineProperty(this, 'height', {
+    get: function PageView_getHeight() {
+      return this.viewport.height;
+    },
+    enumerable: true
+  });
+
+  var self = this;
+
+  function setupAnnotations(pageDiv, pdfPage, viewport) {
+
+    function bindLink(link, dest) {
+      link.href = PDFView.getDestinationHash(dest);
+      link.onclick = function pageViewSetupLinksOnclick() {
+        if (dest) {
+          PDFView.navigateTo(dest);
+        }
+        return false;
+      };
+      if (dest) {
+        link.className = 'internalLink';
+      }
+    }
+
+    function bindNamedAction(link, action) {
+      link.href = PDFView.getAnchorUrl('');
+      link.onclick = function pageViewSetupNamedActionOnClick() {
+        // See PDF reference, table 8.45 - Named action
+        switch (action) {
+          case 'GoToPage':
+            document.getElementById('pageNumber').focus();
+            break;
+
+          case 'GoBack':
+            PDFHistory.back();
+            break;
+
+          case 'GoForward':
+            PDFHistory.forward();
+            break;
+
+          case 'Find':
+            if (!PDFView.supportsIntegratedFind) {
+              PDFFindBar.toggle();
+            }
+            break;
+
+          case 'NextPage':
+            PDFView.page++;
+            break;
+
+          case 'PrevPage':
+            PDFView.page--;
+            break;
+
+          case 'LastPage':
+            PDFView.page = PDFView.pages.length;
+            break;
+
+          case 'FirstPage':
+            PDFView.page = 1;
+            break;
+
+          default:
+            break; // No action according to spec
+        }
+        return false;
+      };
+      link.className = 'internalLink';
+    }
+
+    pdfPage.getAnnotations().then(function(annotationsData) {
+      if (self.annotationLayer) {
+        // If an annotationLayer already exists, delete it to avoid creating
+        // duplicate annotations when rapidly re-zooming the document.
+        pageDiv.removeChild(self.annotationLayer);
+        self.annotationLayer = null;
+      }
+      viewport = viewport.clone({ dontFlip: true });
+      for (var i = 0; i < annotationsData.length; i++) {
+        var data = annotationsData[i];
+        var annotation = PDFJS.Annotation.fromData(data);
+        if (!annotation || !annotation.hasHtml()) {
+          continue;
+        }
+
+        var element = annotation.getHtmlElement(pdfPage.commonObjs);
+        mozL10n.translate(element);
+
+        data = annotation.getData();
+        var rect = data.rect;
+        var view = pdfPage.view;
+        rect = PDFJS.Util.normalizeRect([
+          rect[0],
+          view[3] - rect[1] + view[1],
+          rect[2],
+          view[3] - rect[3] + view[1]
+        ]);
+        element.style.left = rect[0] + 'px';
+        element.style.top = rect[1] + 'px';
+        element.style.position = 'absolute';
+
+        var transform = viewport.transform;
+        var transformStr = 'matrix(' + transform.join(',') + ')';
+        CustomStyle.setProp('transform', element, transformStr);
+        var transformOriginStr = -rect[0] + 'px ' + -rect[1] + 'px';
+        CustomStyle.setProp('transformOrigin', element, transformOriginStr);
+
+        if (data.subtype === 'Link' && !data.url) {
+          if (data.action) {
+            bindNamedAction(element, data.action);
+          } else {
+            bindLink(element, ('dest' in data) ? data.dest : null);
+          }
+        }
+
+        if (!self.annotationLayer) {
+          var annotationLayerDiv = document.createElement('div');
+          annotationLayerDiv.className = 'annotationLayer';
+          pageDiv.appendChild(annotationLayerDiv);
+          self.annotationLayer = annotationLayerDiv;
+        }
+        self.annotationLayer.appendChild(element);
+      }
+    });
+  }
+
+  this.getPagePoint = function pageViewGetPagePoint(x, y) {
+    return this.viewport.convertToPdfPoint(x, y);
+  };
+
+  this.scrollIntoView = function pageViewScrollIntoView(dest) {
+    if (PresentationMode.active) { // Avoid breaking presentation mode.
+      dest = null;
+      PDFView.setScale(PDFView.currentScaleValue, true, true);
+    }
+    if (!dest) {
+      scrollIntoView(div);
+      return;
+    }
+
+    var x = 0, y = 0;
+    var width = 0, height = 0, widthScale, heightScale;
+    var changeOrientation = !!(this.rotation % 180);
+    var pageWidth = (changeOrientation ? this.height : this.width) /
+      this.scale / CSS_UNITS;
+    var pageHeight = (changeOrientation ? this.width : this.height) /
+      this.scale / CSS_UNITS;
+    var scale = 0;
+    switch (dest[1].name) {
+      case 'XYZ':
+        x = dest[2];
+        y = dest[3];
+        scale = dest[4];
+        // If x and/or y coordinates are not supplied, default to
+        // _top_ left of the page (not the obvious bottom left,
+        // since aligning the bottom of the intended page with the
+        // top of the window is rarely helpful).
+        x = x !== null ? x : 0;
+        y = y !== null ? y : pageHeight;
+        break;
+      case 'Fit':
+      case 'FitB':
+        scale = 'page-fit';
+        break;
+      case 'FitH':
+      case 'FitBH':
+        y = dest[2];
+        scale = 'page-width';
+        break;
+      case 'FitV':
+      case 'FitBV':
+        x = dest[2];
+        width = pageWidth;
+        height = pageHeight;
+        scale = 'page-height';
+        break;
+      case 'FitR':
+        x = dest[2];
+        y = dest[3];
+        width = dest[4] - x;
+        height = dest[5] - y;
+        widthScale = (PDFView.container.clientWidth - SCROLLBAR_PADDING) /
+          width / CSS_UNITS;
+        heightScale = (PDFView.container.clientHeight - SCROLLBAR_PADDING) /
+          height / CSS_UNITS;
+        scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));
+        break;
+      default:
+        return;
+    }
+
+    if (scale && scale !== PDFView.currentScale) {
+      PDFView.setScale(scale, true, true);
+    } else if (PDFView.currentScale === UNKNOWN_SCALE) {
+      PDFView.setScale(DEFAULT_SCALE, true, true);
+    }
+
+    if (scale === 'page-fit' && !dest[4]) {
+      scrollIntoView(div);
+      return;
+    }
+
+    var boundingRect = [
+      this.viewport.convertToViewportPoint(x, y),
+      this.viewport.convertToViewportPoint(x + width, y + height)
+    ];
+    var left = Math.min(boundingRect[0][0], boundingRect[1][0]);
+    var top = Math.min(boundingRect[0][1], boundingRect[1][1]);
+
+    scrollIntoView(div, { left: left, top: top });
+  };
+
+  this.getTextContent = function pageviewGetTextContent() {
+    return PDFView.getPage(this.id).then(function(pdfPage) {
+      return pdfPage.getTextContent();
+    });
+  };
+
+  this.draw = function pageviewDraw(callback) {
+    var pdfPage = this.pdfPage;
+
+    if (this.pagePdfPromise) {
+      return;
+    }
+    if (!pdfPage) {
+      var promise = PDFView.getPage(this.id);
+      promise.then(function(pdfPage) {
+        delete this.pagePdfPromise;
+        this.setPdfPage(pdfPage);
+        this.draw(callback);
+      }.bind(this));
+      this.pagePdfPromise = promise;
+      return;
+    }
+
+    if (this.renderingState !== RenderingStates.INITIAL) {
+      console.error('Must be in new state before drawing');
+    }
+
+    this.renderingState = RenderingStates.RUNNING;
+
+    var viewport = this.viewport;
+    // Wrap the canvas so if it has a css transform for highdpi the overflow
+    // will be hidden in FF.
+    var canvasWrapper = document.createElement('div');
+    canvasWrapper.style.width = div.style.width;
+    canvasWrapper.style.height = div.style.height;
+    canvasWrapper.classList.add('canvasWrapper');
+
+    var canvas = document.createElement('canvas');
+    canvas.id = 'page' + this.id;
+    canvasWrapper.appendChild(canvas);
+    div.appendChild(canvasWrapper);
+    this.canvas = canvas;
+
+    var scale = this.scale;
+    var ctx = canvas.getContext('2d');
+    var outputScale = getOutputScale(ctx);
+
+    if (USE_ONLY_CSS_ZOOM) {
+      var actualSizeViewport = viewport.clone({ scale: CSS_UNITS });
+      // Use a scale that will make the canvas be the original intended size
+      // of the page.
+      outputScale.sx *= actualSizeViewport.width / viewport.width;
+      outputScale.sy *= actualSizeViewport.height / viewport.height;
+      outputScale.scaled = true;
+    }
+
+    canvas.width = (Math.floor(viewport.width) * outputScale.sx) | 0;
+    canvas.height = (Math.floor(viewport.height) * outputScale.sy) | 0;
+    canvas.style.width = Math.floor(viewport.width) + 'px';
+    canvas.style.height = Math.floor(viewport.height) + 'px';
+    // Add the viewport so it's known what it was originally drawn with.
+    canvas._viewport = viewport;
+
+    var textLayerDiv = null;
+    if (!PDFJS.disableTextLayer) {
+      textLayerDiv = document.createElement('div');
+      textLayerDiv.className = 'textLayer';
+      textLayerDiv.style.width = canvas.width + 'px';
+      textLayerDiv.style.height = canvas.height + 'px';
+      div.appendChild(textLayerDiv);
+    }
+    var textLayer = this.textLayer =
+      textLayerDiv ? new TextLayerBuilder({
+        textLayerDiv: textLayerDiv,
+        pageIndex: this.id - 1,
+        lastScrollSource: PDFView,
+        viewport: this.viewport,
+        isViewerInPresentationMode: PresentationMode.active
+      }) : null;
+    // TODO(mack): use data attributes to store these
+    ctx._scaleX = outputScale.sx;
+    ctx._scaleY = outputScale.sy;
+    if (outputScale.scaled) {
+      ctx.scale(outputScale.sx, outputScale.sy);
+    }
+    if (outputScale.scaled && textLayerDiv) {
+      var cssScale = 'scale(' + (1 / outputScale.sx) + ', ' +
+                                (1 / outputScale.sy) + ')';
+      CustomStyle.setProp('transform' , textLayerDiv, cssScale);
+      CustomStyle.setProp('transformOrigin' , textLayerDiv, '0% 0%');
+      textLayerDiv.dataset._scaleX = outputScale.sx;
+      textLayerDiv.dataset._scaleY = outputScale.sy;
+    }
+
+
+    // Rendering area
+
+    var self = this;
+    function pageViewDrawCallback(error) {
+      // The renderTask may have been replaced by a new one, so only remove the
+      // reference to the renderTask if it matches the one that is triggering
+      // this callback.
+      if (renderTask === self.renderTask) {
+        self.renderTask = null;
+      }
+
+      if (error === 'cancelled') {
+        return;
+      }
+
+      self.renderingState = RenderingStates.FINISHED;
+
+      if (self.loadingIconDiv) {
+        div.removeChild(self.loadingIconDiv);
+        delete self.loadingIconDiv;
+      }
+
+      if (self.zoomLayer) {
+        div.removeChild(self.zoomLayer);
+        self.zoomLayer = null;
+      }
+
+      if (error) {
+        PDFView.error(mozL10n.get('rendering_error', null,
+          'An error occurred while rendering the page.'), error);
+      }
+
+      self.stats = pdfPage.stats;
+      self.updateStats();
+      if (self.onAfterDraw) {
+        self.onAfterDraw();
+      }
+
+      cache.push(self);
+
+      var event = document.createEvent('CustomEvent');
+      event.initCustomEvent('pagerender', true, true, {
+        pageNumber: pdfPage.pageNumber
+      });
+      div.dispatchEvent(event);
+
+      callback();
+    }
+
+    var renderContext = {
+      canvasContext: ctx,
+      viewport: this.viewport,
+      textLayer: textLayer,
+      continueCallback: function pdfViewcContinueCallback(cont) {
+        if (PDFView.highestPriorityPage !== 'page' + self.id) {
+          self.renderingState = RenderingStates.PAUSED;
+          self.resume = function resumeCallback() {
+            self.renderingState = RenderingStates.RUNNING;
+            cont();
+          };
+          return;
+        }
+        cont();
+      }
+    };
+    var renderTask = this.renderTask = this.pdfPage.render(renderContext);
+
+    this.renderTask.promise.then(
+      function pdfPageRenderCallback() {
+        pageViewDrawCallback(null);
+      },
+      function pdfPageRenderError(error) {
+        pageViewDrawCallback(error);
+      }
+    );
+
+    if (textLayer) {
+      this.getTextContent().then(
+        function textContentResolved(textContent) {
+          textLayer.setTextContent(textContent);
+        }
+      );
+    }
+
+    setupAnnotations(div, pdfPage, this.viewport);
+    div.setAttribute('data-loaded', true);
+  };
+
+  this.beforePrint = function pageViewBeforePrint() {
+    var pdfPage = this.pdfPage;
+
+    var viewport = pdfPage.getViewport(1);
+    // Use the same hack we use for high dpi displays for printing to get better
+    // output until bug 811002 is fixed in FF.
+    var PRINT_OUTPUT_SCALE = 2;
+    var canvas = document.createElement('canvas');
+    canvas.width = Math.floor(viewport.width) * PRINT_OUTPUT_SCALE;
+    canvas.height = Math.floor(viewport.height) * PRINT_OUTPUT_SCALE;
+    canvas.style.width = (PRINT_OUTPUT_SCALE * viewport.width) + 'pt';
+    canvas.style.height = (PRINT_OUTPUT_SCALE * viewport.height) + 'pt';
+    var cssScale = 'scale(' + (1 / PRINT_OUTPUT_SCALE) + ', ' +
+                              (1 / PRINT_OUTPUT_SCALE) + ')';
+    CustomStyle.setProp('transform' , canvas, cssScale);
+    CustomStyle.setProp('transformOrigin' , canvas, '0% 0%');
+
+    var printContainer = document.getElementById('printContainer');
+    var canvasWrapper = document.createElement('div');
+    canvasWrapper.style.width = viewport.width + 'pt';
+    canvasWrapper.style.height = viewport.height + 'pt';
+    canvasWrapper.appendChild(canvas);
+    printContainer.appendChild(canvasWrapper);
+
+    var self = this;
+    canvas.mozPrintCallback = function(obj) {
+      var ctx = obj.context;
+
+      ctx.save();
+      ctx.fillStyle = 'rgb(255, 255, 255)';
+      ctx.fillRect(0, 0, canvas.width, canvas.height);
+      ctx.restore();
+      ctx.scale(PRINT_OUTPUT_SCALE, PRINT_OUTPUT_SCALE);
+
+      var renderContext = {
+        canvasContext: ctx,
+        viewport: viewport
+      };
+
+      pdfPage.render(renderContext).promise.then(function() {
+        // Tell the printEngine that rendering this canvas/page has finished.
+        obj.done();
+        self.pdfPage.destroy();
+      }, function(error) {
+        console.error(error);
+        // Tell the printEngine that rendering this canvas/page has failed.
+        // This will make the print proces stop.
+        if ('abort' in obj) {
+          obj.abort();
+        } else {
+          obj.done();
+        }
+        self.pdfPage.destroy();
+      });
+    };
+  };
+
+  this.updateStats = function pageViewUpdateStats() {
+    if (!this.stats) {
+      return;
+    }
+
+    if (PDFJS.pdfBug && Stats.enabled) {
+      var stats = this.stats;
+      Stats.add(this.id, stats);
+    }
+  };
+};
+
+
+var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
+  var anchor = document.createElement('a');
+  anchor.href = PDFView.getAnchorUrl('#page=' + id);
+  anchor.title = mozL10n.get('thumb_page_title', {page: id}, 'Page {{page}}');
+  anchor.onclick = function stopNavigation() {
+    PDFView.page = id;
+    return false;
+  };
+
+  this.pdfPage = undefined;
+  this.viewport = defaultViewport;
+  this.pdfPageRotate = defaultViewport.rotation;
+
+  this.rotation = 0;
+  this.pageWidth = this.viewport.width;
+  this.pageHeight = this.viewport.height;
+  this.pageRatio = this.pageWidth / this.pageHeight;
+  this.id = id;
+
+  this.canvasWidth = 98;
+  this.canvasHeight = this.canvasWidth / this.pageWidth * this.pageHeight;
+  this.scale = (this.canvasWidth / this.pageWidth);
+
+  var div = this.el = document.createElement('div');
+  div.id = 'thumbnailContainer' + id;
+  div.className = 'thumbnail';
+
+  if (id === 1) {
+    // Highlight the thumbnail of the first page when no page number is
+    // specified (or exists in cache) when the document is loaded.
+    div.classList.add('selected');
+  }
+
+  var ring = document.createElement('div');
+  ring.className = 'thumbnailSelectionRing';
+  ring.style.width = this.canvasWidth + 'px';
+  ring.style.height = this.canvasHeight + 'px';
+
+  div.appendChild(ring);
+  anchor.appendChild(div);
+  container.appendChild(anchor);
+
+  this.hasImage = false;
+  this.renderingState = RenderingStates.INITIAL;
+
+  this.setPdfPage = function thumbnailViewSetPdfPage(pdfPage) {
+    this.pdfPage = pdfPage;
+    this.pdfPageRotate = pdfPage.rotate;
+    var totalRotation = (this.rotation + this.pdfPageRotate) % 360;
+    this.viewport = pdfPage.getViewport(1, totalRotation);
+    this.update();
+  };
+
+  this.update = function thumbnailViewUpdate(rotation) {
+    if (rotation !== undefined) {
+      this.rotation = rotation;
+    }
+    var totalRotation = (this.rotation + this.pdfPageRotate) % 360;
+    this.viewport = this.viewport.clone({
+      scale: 1,
+      rotation: totalRotation
+    });
+    this.pageWidth = this.viewport.width;
+    this.pageHeight = this.viewport.height;
+    this.pageRatio = this.pageWidth / this.pageHeight;
+
+    this.canvasHeight = this.canvasWidth / this.pageWidth * this.pageHeight;
+    this.scale = (this.canvasWidth / this.pageWidth);
+
+    div.removeAttribute('data-loaded');
+    ring.textContent = '';
+    ring.style.width = this.canvasWidth + 'px';
+    ring.style.height = this.canvasHeight + 'px';
+
+    this.hasImage = false;
+    this.renderingState = RenderingStates.INITIAL;
+    this.resume = null;
+  };
+
+  this.getPageDrawContext = function thumbnailViewGetPageDrawContext() {
+    var canvas = document.createElement('canvas');
+    canvas.id = 'thumbnail' + id;
+
+    canvas.width = this.canvasWidth;
+    canvas.height = this.canvasHeight;
+    canvas.className = 'thumbnailImage';
+    canvas.setAttribute('aria-label', mozL10n.get('thumb_page_canvas',
+      {page: id}, 'Thumbnail of Page {{page}}'));
+
+    div.setAttribute('data-loaded', true);
+
+    ring.appendChild(canvas);
+
+    var ctx = canvas.getContext('2d');
+    ctx.save();
+    ctx.fillStyle = 'rgb(255, 255, 255)';
+    ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
+    ctx.restore();
+    return ctx;
+  };
+
+  this.drawingRequired = function thumbnailViewDrawingRequired() {
+    return !this.hasImage;
+  };
+
+  this.draw = function thumbnailViewDraw(callback) {
+    if (!this.pdfPage) {
+      var promise = PDFView.getPage(this.id);
+      promise.then(function(pdfPage) {
+        this.setPdfPage(pdfPage);
+        this.draw(callback);
+      }.bind(this));
+      return;
+    }
+
+    if (this.renderingState !== RenderingStates.INITIAL) {
+      console.error('Must be in new state before drawing');
+    }
+
+    this.renderingState = RenderingStates.RUNNING;
+    if (this.hasImage) {
+      callback();
+      return;
+    }
+
+    var self = this;
+    var ctx = this.getPageDrawContext();
+    var drawViewport = this.viewport.clone({ scale: this.scale });
+    var renderContext = {
+      canvasContext: ctx,
+      viewport: drawViewport,
+      continueCallback: function(cont) {
+        if (PDFView.highestPriorityPage !== 'thumbnail' + self.id) {
+          self.renderingState = RenderingStates.PAUSED;
+          self.resume = function() {
+            self.renderingState = RenderingStates.RUNNING;
+            cont();
+          };
+          return;
+        }
+        cont();
+      }
+    };
+    this.pdfPage.render(renderContext).promise.then(
+      function pdfPageRenderCallback() {
+        self.renderingState = RenderingStates.FINISHED;
+        callback();
+      },
+      function pdfPageRenderError(error) {
+        self.renderingState = RenderingStates.FINISHED;
+        callback();
+      }
+    );
+    this.hasImage = true;
+  };
+
+  this.setImage = function thumbnailViewSetImage(img) {
+    if (!this.pdfPage) {
+      var promise = PDFView.getPage(this.id);
+      promise.then(function(pdfPage) {
+        this.setPdfPage(pdfPage);
+        this.setImage(img);
+      }.bind(this));
+      return;
+    }
+    if (this.hasImage || !img) {
+      return;
+    }
+    this.renderingState = RenderingStates.FINISHED;
+    var ctx = this.getPageDrawContext();
+    ctx.drawImage(img, 0, 0, img.width, img.height,
+                  0, 0, ctx.canvas.width, ctx.canvas.height);
+
+    this.hasImage = true;
+  };
+};
+
+
+var FIND_SCROLL_OFFSET_TOP = -50;
+var FIND_SCROLL_OFFSET_LEFT = -400;
+
+/**
+ * TextLayerBuilder provides text-selection
+ * functionality for the PDF. It does this
+ * by creating overlay divs over the PDF
+ * text. This divs contain text that matches
+ * the PDF text they are overlaying. This
+ * object also provides for a way to highlight
+ * text that is being searched for.
+ */
+var TextLayerBuilder = function textLayerBuilder(options) {
+  var textLayerFrag = document.createDocumentFragment();
+
+  this.textLayerDiv = options.textLayerDiv;
+  this.layoutDone = false;
+  this.divContentDone = false;
+  this.pageIdx = options.pageIndex;
+  this.matches = [];
+  this.lastScrollSource = options.lastScrollSource;
+  this.viewport = options.viewport;
+  this.isViewerInPresentationMode = options.isViewerInPresentationMode;
+
+  if(typeof PDFFindController === 'undefined') {
+      window.PDFFindController = null;
+  }
+
+  if(typeof this.lastScrollSource === 'undefined') {
+      this.lastScrollSource = null;
+  }
+
+  this.beginLayout = function textLayerBuilderBeginLayout() {
+    this.textDivs = [];
+    this.renderingDone = false;
+  };
+
+  this.endLayout = function textLayerBuilderEndLayout() {
+    this.layoutDone = true;
+    this.insertDivContent();
+  };
+
+  this.renderLayer = function textLayerBuilderRenderLayer() {
+    var self = this;
+    var textDivs = this.textDivs;
+    var bidiTexts = this.textContent.bidiTexts;
+    var textLayerDiv = this.textLayerDiv;
+    var canvas = document.createElement('canvas');
+    var ctx = canvas.getContext('2d');
+
+    // No point in rendering so many divs as it'd make the browser unusable
+    // even after the divs are rendered
+    var MAX_TEXT_DIVS_TO_RENDER = 100000;
+    if (textDivs.length > MAX_TEXT_DIVS_TO_RENDER)
+      return;
+
+    for (var i = 0, ii = textDivs.length; i < ii; i++) {
+      var textDiv = textDivs[i];
+      if ('isWhitespace' in textDiv.dataset) {
+        continue;
+      }
+
+      ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily;
+      var width = ctx.measureText(textDiv.textContent).width;
+
+      if (width > 0) {
+        textLayerFrag.appendChild(textDiv);
+        var textScale = textDiv.dataset.canvasWidth / width;
+        var rotation = textDiv.dataset.angle;
+        var transform = 'scale(' + textScale + ', 1)';
+        transform = 'rotate(' + rotation + 'deg) ' + transform;
+        CustomStyle.setProp('transform' , textDiv, transform);
+        CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
+      }
+    }
+
+    textLayerDiv.appendChild(textLayerFrag);
+    this.renderingDone = true;
+    this.updateMatches();
+  };
+
+  this.setupRenderLayoutTimer = function textLayerSetupRenderLayoutTimer() {
+    // Schedule renderLayout() if user has been scrolling, otherwise
+    // run it right away
+    var RENDER_DELAY = 200; // in ms
+    var self = this;
+    var lastScroll = this.lastScrollSource === null ?
+        0 : this.lastScrollSource.lastScroll;
+
+    if (Date.now() - lastScroll > RENDER_DELAY) {
+      // Render right away
+      this.renderLayer();
+    } else {
+      // Schedule
+      if (this.renderTimer)
+        clearTimeout(this.renderTimer);
+      this.renderTimer = setTimeout(function() {
+        self.setupRenderLayoutTimer();
+      }, RENDER_DELAY);
+    }
+  };
+
+  this.appendText = function textLayerBuilderAppendText(geom) {
+    var textDiv = document.createElement('div');
+
+    // vScale and hScale already contain the scaling to pixel units
+    var fontHeight = geom.fontSize * Math.abs(geom.vScale);
+    textDiv.dataset.canvasWidth = geom.canvasWidth * Math.abs(geom.hScale);
+    textDiv.dataset.fontName = geom.fontName;
+    textDiv.dataset.angle = geom.angle * (180 / Math.PI);
+
+    textDiv.style.fontSize = fontHeight + 'px';
+    textDiv.style.fontFamily = geom.fontFamily;
+    var fontAscent = geom.ascent ? geom.ascent * fontHeight :
+      geom.descent ? (1 + geom.descent) * fontHeight : fontHeight;
+    textDiv.style.left = (geom.x + (fontAscent * Math.sin(geom.angle))) + 'px';
+    textDiv.style.top = (geom.y - (fontAscent * Math.cos(geom.angle))) + 'px';
+
+    // The content of the div is set in the `setTextContent` function.
+
+    this.textDivs.push(textDiv);
+  };
+
+  this.insertDivContent = function textLayerUpdateTextContent() {
+    // Only set the content of the divs once layout has finished, the content
+    // for the divs is available and content is not yet set on the divs.
+    if (!this.layoutDone || this.divContentDone || !this.textContent)
+      return;
+
+    this.divContentDone = true;
+
+    var textDivs = this.textDivs;
+    var bidiTexts = this.textContent.bidiTexts;
+
+    for (var i = 0; i < bidiTexts.length; i++) {
+      var bidiText = bidiTexts[i];
+      var textDiv = textDivs[i];
+      if (!/\S/.test(bidiText.str)) {
+        textDiv.dataset.isWhitespace = true;
+        continue;
+      }
+
+      textDiv.textContent = bidiText.str;
+      // TODO refactor text layer to use text content position
+      /**
+       * var arr = this.viewport.convertToViewportPoint(bidiText.x, bidiText.y);
+       * textDiv.style.left = arr[0] + 'px';
+       * textDiv.style.top = arr[1] + 'px';
+       */
+      // bidiText.dir may be 'ttb' for vertical texts.
+      textDiv.dir = bidiText.dir;
+    }
+
+    this.setupRenderLayoutTimer();
+  };
+
+  this.setTextContent = function textLayerBuilderSetTextContent(textContent) {
+    this.textContent = textContent;
+    this.insertDivContent();
+  };
+
+  this.convertMatches = function textLayerBuilderConvertMatches(matches) {
+    var i = 0;
+    var iIndex = 0;
+    var bidiTexts = this.textContent.bidiTexts;
+    var end = bidiTexts.length - 1;
+    var queryLen = PDFFindController === null ?
+        0 : PDFFindController.state.query.length;
+
+    var lastDivIdx = -1;
+    var pos;
+
+    var ret = [];
+
+    // Loop over all the matches.
+    for (var m = 0; m < matches.length; m++) {
+      var matchIdx = matches[m];
+      // # Calculate the begin position.
+
+      // Loop over the divIdxs.
+      while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) {
+        iIndex += bidiTexts[i].str.length;
+        i++;
+      }
+
+      // TODO: Do proper handling here if something goes wrong.
+      if (i == bidiTexts.length) {
+        console.error('Could not find matching mapping');
+      }
+
+      var match = {
+        begin: {
+          divIdx: i,
+          offset: matchIdx - iIndex
+        }
+      };
+
+      // # Calculate the end position.
+      matchIdx += queryLen;
+
+      // Somewhat same array as above, but use a > instead of >= to get the end
+      // position right.
+      while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) {
+        iIndex += bidiTexts[i].str.length;
+        i++;
+      }
+
+      match.end = {
+        divIdx: i,
+        offset: matchIdx - iIndex
+      };
+      ret.push(match);
+    }
+
+    return ret;
+  };
+
+  this.renderMatches = function textLayerBuilder_renderMatches(matches) {
+    // Early exit if there is nothing to render.
+    if (matches.length === 0) {
+      return;
+    }
+
+    var bidiTexts = this.textContent.bidiTexts;
+    var textDivs = this.textDivs;
+    var prevEnd = null;
+    var isSelectedPage = PDFFindController === null ?
+        false : (this.pageIdx === PDFFindController.selected.pageIdx);
+
+    var selectedMatchIdx = PDFFindController === null ?
+        -1 : PDFFindController.selected.matchIdx;
+
+    var highlightAll = PDFFindController === null ?
+        false : PDFFindController.state.highlightAll;
+
+    var infty = {
+      divIdx: -1,
+      offset: undefined
+    };
+
+    function beginText(begin, className) {
+      var divIdx = begin.divIdx;
+      var div = textDivs[divIdx];
+      div.textContent = '';
+
+      var content = bidiTexts[divIdx].str.substring(0, begin.offset);
+      var node = document.createTextNode(content);
+      if (className) {
+        var isSelected = isSelectedPage &&
+                          divIdx === selectedMatchIdx;
+        var span = document.createElement('span');
+        span.className = className + (isSelected ? ' selected' : '');
+        span.appendChild(node);
+        div.appendChild(span);
+        return;
+      }
+      div.appendChild(node);
+    }
+
+    function appendText(from, to, className) {
+      var divIdx = from.divIdx;
+      var div = textDivs[divIdx];
+
+      var content = bidiTexts[divIdx].str.substring(from.offset, to.offset);
+      var node = document.createTextNode(content);
+      if (className) {
+        var span = document.createElement('span');
+        span.className = className;
+        span.appendChild(node);
+        div.appendChild(span);
+        return;
+      }
+      div.appendChild(node);
+    }
+
+    function highlightDiv(divIdx, className) {
+      textDivs[divIdx].className = className;
+    }
+
+    var i0 = selectedMatchIdx, i1 = i0 + 1, i;
+
+    if (highlightAll) {
+      i0 = 0;
+      i1 = matches.length;
+    } else if (!isSelectedPage) {
+      // Not highlighting all and this isn't the selected page, so do nothing.
+      return;
+    }
+
+    for (i = i0; i < i1; i++) {
+      var match = matches[i];
+      var begin = match.begin;
+      var end = match.end;
+
+      var isSelected = isSelectedPage && i === selectedMatchIdx;
+      var highlightSuffix = (isSelected ? ' selected' : '');
+      if (isSelected && !this.isViewerInPresentationMode) {
+        scrollIntoView(textDivs[begin.divIdx], { top: FIND_SCROLL_OFFSET_TOP,
+                                               left: FIND_SCROLL_OFFSET_LEFT });
+      }
+
+      // Match inside new div.
+      if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
+        // If there was a previous div, then add the text at the end
+        if (prevEnd !== null) {
+          appendText(prevEnd, infty);
+        }
+        // clears the divs and set the content until the begin point.
+        beginText(begin);
+      } else {
+        appendText(prevEnd, begin);
+      }
+
+      if (begin.divIdx === end.divIdx) {
+        appendText(begin, end, 'highlight' + highlightSuffix);
+      } else {
+        appendText(begin, infty, 'highlight begin' + highlightSuffix);
+        for (var n = begin.divIdx + 1; n < end.divIdx; n++) {
+          highlightDiv(n, 'highlight middle' + highlightSuffix);
+        }
+        beginText(end, 'highlight end' + highlightSuffix);
+      }
+      prevEnd = end;
+    }
+
+    if (prevEnd) {
+      appendText(prevEnd, infty);
+    }
+  };
+
+  this.updateMatches = function textLayerUpdateMatches() {
+    // Only show matches, once all rendering is done.
+    if (!this.renderingDone)
+      return;
+
+    // Clear out all matches.
+    var matches = this.matches;
+    var textDivs = this.textDivs;
+    var bidiTexts = this.textContent.bidiTexts;
+    var clearedUntilDivIdx = -1;
+
+    // Clear out all current matches.
+    for (var i = 0; i < matches.length; i++) {
+      var match = matches[i];
+      var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
+      for (var n = begin; n <= match.end.divIdx; n++) {
+        var div = textDivs[n];
+        div.textContent = bidiTexts[n].str;
+        div.className = '';
+      }
+      clearedUntilDivIdx = match.end.divIdx + 1;
+    }
+
+    if (PDFFindController === null || !PDFFindController.active)
+      return;
+
+    // Convert the matches on the page controller into the match format used
+    // for the textLayer.
+    this.matches = matches =
+      this.convertMatches(PDFFindController === null ?
+          [] : (PDFFindController.pageMatches[this.pageIdx] || []));
+
+    this.renderMatches(this.matches);
+  };
+};
+
+
+
+var DocumentOutlineView = function documentOutlineView(outline) {
+  var outlineView = document.getElementById('outlineView');
+  var outlineButton = document.getElementById('viewOutline');
+  while (outlineView.firstChild)
+    outlineView.removeChild(outlineView.firstChild);
+
+  if (!outline) {
+    if (!outlineView.classList.contains('hidden'))
+      PDFView.switchSidebarView('thumbs');
+
+    return;
+  }
+
+  function bindItemLink(domObj, item) {
+    domObj.href = PDFView.getDestinationHash(item.dest);
+    domObj.onclick = function documentOutlineViewOnclick(e) {
+      PDFView.navigateTo(item.dest);
+      return false;
+    };
+  }
+
+
+  var queue = [{parent: outlineView, items: outline}];
+  while (queue.length > 0) {
+    var levelData = queue.shift();
+    var i, n = levelData.items.length;
+    for (i = 0; i < n; i++) {
+      var item = levelData.items[i];
+      var div = document.createElement('div');
+      div.className = 'outlineItem';
+      var a = document.createElement('a');
+      bindItemLink(a, item);
+      a.textContent = item.title;
+      div.appendChild(a);
+
+      if (item.items.length > 0) {
+        var itemsDiv = document.createElement('div');
+        itemsDiv.className = 'outlineItems';
+        div.appendChild(itemsDiv);
+        queue.push({parent: itemsDiv, items: item.items});
+      }
+
+      levelData.parent.appendChild(div);
+    }
+  }
+};
+
+
+document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
+  PDFView.initialize();
+
+  var params = PDFView.parseQueryString(document.location.search.substring(1));
+  var file = params.file || DEFAULT_URL;
+
+
+  var fileInput = document.createElement('input');
+  fileInput.id = 'fileInput';
+  fileInput.className = 'fileInput';
+  fileInput.setAttribute('type', 'file');
+  fileInput.oncontextmenu = noContextMenuHandler;
+  document.body.appendChild(fileInput);
+
+  if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
+    //document.getElementById('openFile').setAttribute('hidden', 'true');
+    //document.getElementById('secondaryOpenFile').setAttribute('hidden', 'true');
+  } else {
+    document.getElementById('fileInput').value = null;
+  }
+
+  // Special debugging flags in the hash section of the URL.
+  var hash = document.location.hash.substring(1);
+  var hashParams = PDFView.parseQueryString(hash);
+
+  if ('disableWorker' in hashParams) {
+    PDFJS.disableWorker = (hashParams['disableWorker'] === 'true');
+  }
+
+  if ('disableRange' in hashParams) {
+    PDFJS.disableRange = (hashParams['disableRange'] === 'true');
+  }
+
+  if ('disableAutoFetch' in hashParams) {
+    PDFJS.disableAutoFetch = (hashParams['disableAutoFetch'] === 'true');
+  }
+
+  if ('disableFontFace' in hashParams) {
+    PDFJS.disableFontFace = (hashParams['disableFontFace'] === 'true');
+  }
+
+  if ('disableHistory' in hashParams) {
+    PDFJS.disableHistory = (hashParams['disableHistory'] === 'true');
+  }
+
+  if ('useOnlyCssZoom' in hashParams) {
+    USE_ONLY_CSS_ZOOM = (hashParams['useOnlyCssZoom'] === 'true');
+  }
+
+  if ('verbosity' in hashParams) {
+    PDFJS.verbosity = hashParams['verbosity'] | 0;
+  }
+
+  if ('ignoreCurrentPositionOnZoom' in hashParams) {
+    IGNORE_CURRENT_POSITION_ON_ZOOM =
+      (hashParams['ignoreCurrentPositionOnZoom'] === 'true');
+  }
+
+  var locale = navigator.language;
+  if ('locale' in hashParams)
+    locale = hashParams['locale'];
+  mozL10n.setLanguage(locale);
+
+  if ('textLayer' in hashParams) {
+    switch (hashParams['textLayer']) {
+      case 'off':
+        PDFJS.disableTextLayer = true;
+        break;
+      case 'visible':
+      case 'shadow':
+      case 'hover':
+        var viewer = document.getElementById('viewer');
+        viewer.classList.add('textLayer-' + hashParams['textLayer']);
+        break;
+    }
+  }
+
+  if ('pdfBug' in hashParams) {
+    PDFJS.pdfBug = true;
+    var pdfBug = hashParams['pdfBug'];
+    var enabled = pdfBug.split(',');
+    PDFBug.enable(enabled);
+    PDFBug.init();
+  }
+
+  if (!PDFView.supportsPrinting) {
+    document.getElementById('print').classList.add('hidden');
+    document.getElementById('secondaryPrint').classList.add('hidden');
+  }
+
+  if (!PDFView.supportsFullscreen) {
+    document.getElementById('presentationMode').classList.add('hidden');
+    document.getElementById('secondaryPresentationMode').
+      classList.add('hidden');
+  }
+
+  if (PDFView.supportsIntegratedFind) {
+    document.getElementById('viewFind').classList.add('hidden');
+  }
+
+  // Listen for unsuporrted features to trigger the fallback UI.
+  PDFJS.UnsupportedManager.listen(PDFView.fallback.bind(PDFView));
+
+  // Suppress context menus for some controls
+  document.getElementById('scaleSelect').oncontextmenu = noContextMenuHandler;
+
+  var mainContainer = document.getElementById('mainContainer');
+  var outerContainer = document.getElementById('outerContainer');
+  mainContainer.addEventListener('transitionend', function(e) {
+    if (e.target == mainContainer) {
+      var event = document.createEvent('UIEvents');
+      event.initUIEvent('resize', false, false, window, 0);
+      window.dispatchEvent(event);
+      outerContainer.classList.remove('sidebarMoving');
+    }
+  }, true);
+
+  document.getElementById('sidebarToggle').addEventListener('click',
+    function() {
+      this.classList.toggle('toggled');
+      outerContainer.classList.add('sidebarMoving');
+      outerContainer.classList.toggle('sidebarOpen');
+      PDFView.sidebarOpen = outerContainer.classList.contains('sidebarOpen');
+      PDFView.renderHighestPriority();
+    });
+
+  document.getElementById('viewThumbnail').addEventListener('click',
+    function() {
+      PDFView.switchSidebarView('thumbs');
+    });
+
+  document.getElementById('viewOutline').addEventListener('click',
+    function() {
+      PDFView.switchSidebarView('outline');
+    });
+
+  document.getElementById('previous').addEventListener('click',
+    function() {
+      PDFView.page--;
+    });
+
+  document.getElementById('next').addEventListener('click',
+    function() {
+      PDFView.page++;
+    });
+
+  document.getElementById('zoomIn').addEventListener('click',
+    function() {
+      PDFView.zoomIn();
+    });
+
+  document.getElementById('zoomOut').addEventListener('click',
+    function() {
+      PDFView.zoomOut();
+    });
+
+  document.getElementById('pageNumber').addEventListener('click',
+    function() {
+      this.select();
+    });
+
+  document.getElementById('pageNumber').addEventListener('change',
+    function() {
+      // Handle the user inputting a floating point number.
+      PDFView.page = (this.value | 0);
+
+      if (this.value !== (this.value | 0).toString()) {
+        this.value = PDFView.page;
+      }
+    });
+
+  document.getElementById('scaleSelect').addEventListener('change',
+    function() {
+      PDFView.setScale(this.value);
+    });
+
+  document.getElementById('presentationMode').addEventListener('click',
+    SecondaryToolbar.presentationModeClick.bind(SecondaryToolbar));
+
+//  document.getElementById('openFile').addEventListener('click',
+//    SecondaryToolbar.openFileClick.bind(SecondaryToolbar));
+
+  document.getElementById('print').addEventListener('click',
+    SecondaryToolbar.printClick.bind(SecondaryToolbar));
+
+//  document.getElementById('download').addEventListener('click',
+//    SecondaryToolbar.downloadClick.bind(SecondaryToolbar));
+
+
+  PDFView.open(file, 0);
+}, true);
+
+function updateViewarea() {
+
+  if (!PDFView.initialized)
+    return;
+  var visible = PDFView.getVisiblePages();
+  var visiblePages = visible.views;
+  if (visiblePages.length === 0) {
+    return;
+  }
+
+  PDFView.renderHighestPriority();
+
+  var currentId = PDFView.page;
+  var firstPage = visible.first;
+
+  for (var i = 0, ii = visiblePages.length, stillFullyVisible = false;
+       i < ii; ++i) {
+    var page = visiblePages[i];
+
+    if (page.percent < 100)
+      break;
+
+    if (page.id === PDFView.page) {
+      stillFullyVisible = true;
+      break;
+    }
+  }
+
+  if (!stillFullyVisible) {
+    currentId = visiblePages[0].id;
+  }
+
+  updateViewarea.inProgress = true; // used in "set page"
+  PDFView.page = currentId;
+  updateViewarea.inProgress = false;
+
+  var currentScale = PDFView.currentScale;
+  var currentScaleValue = PDFView.currentScaleValue;
+  var normalizedScaleValue = parseFloat(currentScaleValue) === currentScale ?
+    Math.round(currentScale * 10000) / 100 : currentScaleValue;
+
+  var pageNumber = firstPage.id;
+  var pdfOpenParams = '#page=' + pageNumber;
+  pdfOpenParams += '&zoom=' + normalizedScaleValue;
+  var currentPage = PDFView.pages[pageNumber - 1];
+  var container = PDFView.container;
+  var topLeft = currentPage.getPagePoint((container.scrollLeft - firstPage.x),
+                                         (container.scrollTop - firstPage.y));
+  var intLeft = Math.round(topLeft[0]);
+  var intTop = Math.round(topLeft[1]);
+  pdfOpenParams += ',' + intLeft + ',' + intTop;
+
+  if (PresentationMode.active || PresentationMode.switchInProgress) {
+    PDFView.currentPosition = null;
+  } else {
+    PDFView.currentPosition = { page: pageNumber, left: intLeft, top: intTop };
+  }
+
+  var store = PDFView.store;
+  store.initializedPromise.then(function() {
+    store.set('exists', true);
+    store.set('page', pageNumber);
+    store.set('zoom', normalizedScaleValue);
+    store.set('scrollLeft', intLeft);
+    store.set('scrollTop', intTop);
+  });
+  var href = PDFView.getAnchorUrl(pdfOpenParams);
+  document.getElementById('viewBookmark').href = href;
+  document.getElementById('secondaryViewBookmark').href = href;
+
+  // Update the current bookmark in the browsing history.
+  PDFHistory.updateCurrentBookmark(pdfOpenParams, pageNumber);
+}
+
+window.addEventListener('resize', function webViewerResize(evt) {
+  if (PDFView.initialized &&
+      (document.getElementById('pageWidthOption').selected ||
+       document.getElementById('pageFitOption').selected ||
+       document.getElementById('pageAutoOption').selected)) {
+    PDFView.setScale(document.getElementById('scaleSelect').value);
+  }
+  updateViewarea();
+
+  // Set the 'max-height' CSS property of the secondary toolbar.
+  SecondaryToolbar.setMaxHeight(PDFView.container);
+});
+
+window.addEventListener('hashchange', function webViewerHashchange(evt) {
+  if (PDFHistory.isHashChangeUnlocked) {
+    PDFView.setHash(document.location.hash.substring(1));
+  }
+});
+
+window.addEventListener('change', function webViewerChange(evt) {
+  var files = evt.target.files;
+  if (!files || files.length === 0)
+    return;
+
+  // Read the local file into a Uint8Array.
+  var fileReader = new FileReader();
+  fileReader.onload = function webViewerChangeFileReaderOnload(evt) {
+    var buffer = evt.target.result;
+    var uint8Array = new Uint8Array(buffer);
+    PDFView.open(uint8Array, 0);
+  };
+
+  var file = files[0];
+  fileReader.readAsArrayBuffer(file);
+  PDFView.setTitleUsingUrl(file.name);
+
+  // URL does not reflect proper document location - hiding some icons.
+  document.getElementById('viewBookmark').setAttribute('hidden', 'true');
+  document.getElementById('secondaryViewBookmark').
+    setAttribute('hidden', 'true');
+  document.getElementById('download').setAttribute('hidden', 'true');
+  document.getElementById('secondaryDownload').setAttribute('hidden', 'true');
+}, true);
+
+function selectScaleOption(value) {
+  var options = document.getElementById('scaleSelect').options;
+  var predefinedValueFound = false;
+  for (var i = 0; i < options.length; i++) {
+    var option = options[i];
+    if (option.value != value) {
+      option.selected = false;
+      continue;
+    }
+    option.selected = true;
+    predefinedValueFound = true;
+  }
+  return predefinedValueFound;
+}
+
+window.addEventListener('localized', function localized(evt) {
+  document.getElementsByTagName('html')[0].dir = mozL10n.getDirection();
+
+  PDFView.animationStartedPromise.then(function() {
+    // Adjust the width of the zoom box to fit the content.
+    // Note: This is only done if the zoom box is actually visible,
+    // since otherwise element.clientWidth will return 0.
+    var container = document.getElementById('scaleSelectContainer');
+    if (container.clientWidth > 0) {
+      var select = document.getElementById('scaleSelect');
+      select.setAttribute('style', 'min-width: inherit;');
+      var width = select.clientWidth + SCALE_SELECT_CONTAINER_PADDING;
+      select.setAttribute('style', 'min-width: ' +
+                                   (width + SCALE_SELECT_PADDING) + 'px;');
+      container.setAttribute('style', 'min-width: ' + width + 'px; ' +
+                                      'max-width: ' + width + 'px;');
+    }
+
+    // Set the 'max-height' CSS property of the secondary toolbar.
+    SecondaryToolbar.setMaxHeight(PDFView.container);
+  });
+}, true);
+
+window.addEventListener('scalechange', function scalechange(evt) {
+  document.getElementById('zoomOut').disabled = (evt.scale === MIN_SCALE);
+  document.getElementById('zoomIn').disabled = (evt.scale === MAX_SCALE);
+
+  var customScaleOption = document.getElementById('customScaleOption');
+  customScaleOption.selected = false;
+
+  if (!evt.resetAutoSettings &&
+      (document.getElementById('pageWidthOption').selected ||
+       document.getElementById('pageFitOption').selected ||
+       document.getElementById('pageAutoOption').selected)) {
+    updateViewarea();
+    return;
+  }
+
+  var predefinedValueFound = selectScaleOption('' + evt.scale);
+  if (!predefinedValueFound) {
+    customScaleOption.textContent = Math.round(evt.scale * 10000) / 100 + '%';
+    customScaleOption.selected = true;
+  }
+  updateViewarea();
+}, true);
+
+window.addEventListener('pagechange', function pagechange(evt) {
+  var page = evt.pageNumber;
+  if (PDFView.previousPageNumber !== page) {
+    document.getElementById('pageNumber').value = page;
+    var selected = document.querySelector('.thumbnail.selected');
+    if (selected) {
+      selected.classList.remove('selected');
+    }
+    var thumbnail = document.getElementById('thumbnailContainer' + page);
+    thumbnail.classList.add('selected');
+    var visibleThumbs = PDFView.getVisibleThumbs();
+    var numVisibleThumbs = visibleThumbs.views.length;
+
+    // If the thumbnail isn't currently visible, scroll it into view.
+    if (numVisibleThumbs > 0) {
+      var first = visibleThumbs.first.id;
+      // Account for only one thumbnail being visible.
+      var last = (numVisibleThumbs > 1 ? visibleThumbs.last.id : first);
+      if (page <= first || page >= last) {
+        scrollIntoView(thumbnail, { top: THUMBNAIL_SCROLL_MARGIN });
+      }
+    }
+  }
+  document.getElementById('previous').disabled = (page <= 1);
+  document.getElementById('next').disabled = (page >= PDFView.pages.length);
+}, true);
+
+// Firefox specific event, so that we can prevent browser from zooming
+window.addEventListener('DOMMouseScroll', function(evt) {
+  if (evt.ctrlKey) {
+    evt.preventDefault();
+
+    var ticks = evt.detail;
+    var direction = (ticks > 0) ? 'zoomOut' : 'zoomIn';
+    PDFView[direction](Math.abs(ticks));
+  } else if (PresentationMode.active) {
+    var FIREFOX_DELTA_FACTOR = -40;
+    PDFView.mouseScroll(evt.detail * FIREFOX_DELTA_FACTOR);
+  }
+}, false);
+
+window.addEventListener('click', function click(evt) {
+  if (!PresentationMode.active) {
+    if (SecondaryToolbar.opened && PDFView.container.contains(evt.target)) {
+      SecondaryToolbar.close();
+    }
+  } else if (evt.button === 0) {
+    // Necessary since preventDefault() in 'mousedown' won't stop
+    // the event propagation in all circumstances in presentation mode.
+    evt.preventDefault();
+  }
+}, false);
+
+window.addEventListener('keydown', function keydown(evt) {
+  if (PasswordPrompt.visible) {
+    return;
+  }
+
+  var handled = false;
+  var cmd = (evt.ctrlKey ? 1 : 0) |
+            (evt.altKey ? 2 : 0) |
+            (evt.shiftKey ? 4 : 0) |
+            (evt.metaKey ? 8 : 0);
+
+  // First, handle the key bindings that are independent whether an input
+  // control is selected or not.
+  if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) {
+    // either CTRL or META key with optional SHIFT.
+    switch (evt.keyCode) {
+      case 70: // f
+        if (!PDFView.supportsIntegratedFind) {
+          PDFFindBar.open();
+          handled = true;
+        }
+        break;
+      case 71: // g
+        if (!PDFView.supportsIntegratedFind) {
+          PDFFindBar.dispatchEvent('again', cmd === 5 || cmd === 12);
+          handled = true;
+        }
+        break;
+      case 61: // FF/Mac '='
+      case 107: // FF '+' and '='
+      case 187: // Chrome '+'
+      case 171: // FF with German keyboard
+        PDFView.zoomIn();
+        handled = true;
+        break;
+      case 173: // FF/Mac '-'
+      case 109: // FF '-'
+      case 189: // Chrome '-'
+        PDFView.zoomOut();
+        handled = true;
+        break;
+      case 48: // '0'
+      case 96: // '0' on Numpad of Swedish keyboard
+        // keeping it unhandled (to restore page zoom to 100%)
+        setTimeout(function () {
+          // ... and resetting the scale after browser adjusts its scale
+          PDFView.setScale(DEFAULT_SCALE, true);
+        });
+        handled = false;
+        break;
+    }
+  }
+
+  // CTRL+ALT or Option+Command
+  if (cmd === 3 || cmd === 10) {
+    switch (evt.keyCode) {
+      case 80: // p
+        SecondaryToolbar.presentationModeClick();
+        handled = true;
+        break;
+      case 71: // g
+        // focuses input#pageNumber field
+        document.getElementById('pageNumber').select();
+        handled = true;
+        break;
+    }
+  }
+
+  if (handled) {
+    evt.preventDefault();
+    return;
+  }
+
+  // Some shortcuts should not get handled if a control/input element
+  // is selected.
+  var curElement = document.activeElement || document.querySelector(':focus');
+  if (curElement && (curElement.tagName.toUpperCase() === 'INPUT' ||
+                     curElement.tagName.toUpperCase() === 'TEXTAREA' ||
+                     curElement.tagName.toUpperCase() === 'SELECT')) {
+    // Make sure that the secondary toolbar is closed when Escape is pressed.
+    if (evt.keyCode !== 27) { // 'Esc'
+      return;
+    }
+  }
+  var controlsElement = document.getElementById('toolbar');
+  while (curElement) {
+    if (curElement === controlsElement && !PresentationMode.active)
+      return; // ignoring if the 'toolbar' element is focused
+    curElement = curElement.parentNode;
+  }
+
+  if (cmd === 0) { // no control key pressed at all.
+    switch (evt.keyCode) {
+      case 38: // up arrow
+      case 33: // pg up
+      case 8: // backspace
+        if (!PresentationMode.active &&
+            PDFView.currentScaleValue !== 'page-fit') {
+          break;
+        }
+        /* in presentation mode */
+        /* falls through */
+      case 37: // left arrow
+        // horizontal scrolling using arrow keys
+        if (PDFView.isHorizontalScrollbarEnabled) {
+          break;
+        }
+        /* falls through */
+      case 75: // 'k'
+      case 80: // 'p'
+        PDFView.page--;
+        handled = true;
+        break;
+      case 27: // esc key
+        if (SecondaryToolbar.opened) {
+          SecondaryToolbar.close();
+          handled = true;
+        }
+        if (!PDFView.supportsIntegratedFind && PDFFindBar.opened) {
+          PDFFindBar.close();
+          handled = true;
+        }
+        break;
+      case 40: // down arrow
+      case 34: // pg down
+      case 32: // spacebar
+        if (!PresentationMode.active &&
+            PDFView.currentScaleValue !== 'page-fit') {
+          break;
+        }
+        /* falls through */
+      case 39: // right arrow
+        // horizontal scrolling using arrow keys
+        if (PDFView.isHorizontalScrollbarEnabled) {
+          break;
+        }
+        /* falls through */
+      case 74: // 'j'
+      case 78: // 'n'
+        PDFView.page++;
+        handled = true;
+        break;
+
+      case 36: // home
+        if (PresentationMode.active) {
+          PDFView.page = 1;
+          handled = true;
+        }
+        break;
+      case 35: // end
+        if (PresentationMode.active) {
+          PDFView.page = PDFView.pdfDocument.numPages;
+          handled = true;
+        }
+        break;
+
+      case 72: // 'h'
+        if (!PresentationMode.active) {
+          HandTool.toggle();
+        }
+        break;
+      case 82: // 'r'
+        PDFView.rotatePages(90);
+        break;
+    }
+  }
+
+  if (cmd === 4) { // shift-key
+    switch (evt.keyCode) {
+      case 32: // spacebar
+        if (!PresentationMode.active &&
+            PDFView.currentScaleValue !== 'page-fit') {
+          break;
+        }
+        PDFView.page--;
+        handled = true;
+        break;
+
+      case 82: // 'r'
+        PDFView.rotatePages(-90);
+        break;
+    }
+  }
+
+  if (cmd === 2) { // alt-key
+    switch (evt.keyCode) {
+      case 37: // left arrow
+        if (PresentationMode.active) {
+          PDFHistory.back();
+          handled = true;
+        }
+        break;
+      case 39: // right arrow
+        if (PresentationMode.active) {
+          PDFHistory.forward();
+          handled = true;
+        }
+        break;
+    }
+  }
+
+  if (handled) {
+    evt.preventDefault();
+    PDFView.clearMouseScrollState();
+  }
+});
+
+window.addEventListener('beforeprint', function beforePrint(evt) {
+  PDFView.beforePrint();
+});
+
+window.addEventListener('afterprint', function afterPrint(evt) {
+  PDFView.afterPrint();
+});
+
+(function animationStartedClosure() {
+  // The offsetParent is not set until the pdf.js iframe or object is visible.
+  // Waiting for first animation.
+  var requestAnimationFrame = window.requestAnimationFrame ||
+                              window.mozRequestAnimationFrame ||
+                              window.webkitRequestAnimationFrame ||
+                              window.oRequestAnimationFrame ||
+                              window.msRequestAnimationFrame ||
+                              function startAtOnce(callback) { callback(); };
+  PDFView.animationStartedPromise = new Promise(function (resolve) {
+    requestAnimationFrame(function onAnimationFrame() {
+      resolve();
+    });
+  });
+})();
+
+
diff --git a/plugins/pdfviewer/viewer/viewer.min.js b/plugins/pdfviewer/viewer/viewer.min.js
new file mode 100644
index 0000000..e11ec84
--- /dev/null
+++ b/plugins/pdfviewer/viewer/viewer.min.js
@@ -0,0 +1,164 @@
+var DEFAULT_URL=null,DEFAULT_SCALE="auto",DEFAULT_SCALE_DELTA=1.1,UNKNOWN_SCALE=0,CACHE_SIZE=20,CSS_UNITS=96/72,SCROLLBAR_PADDING=40,VERTICAL_PADDING=5,MAX_AUTO_SCALE=1.25,MIN_SCALE=0.25,MAX_SCALE=4,VIEW_HISTORY_MEMORY=20,SCALE_SELECT_CONTAINER_PADDING=8,SCALE_SELECT_PADDING=22,THUMBNAIL_SCROLL_MARGIN=-19,USE_ONLY_CSS_ZOOM=!1,CLEANUP_TIMEOUT=3E4,IGNORE_CURRENT_POSITION_ON_ZOOM=!1,RenderingStates={INITIAL:0,RUNNING:1,PAUSED:2,FINISHED:3},FindStates={FIND_FOUND:0,FIND_NOTFOUND:1,FIND_WRAPPED:2,FIND_PENDING:3};
+PDFJS.imageResourcesPath="./images/";PDFJS.workerSrc="pdf.worker.js";
+var mozL10n=document.mozL10n||document.webL10n,CustomStyle=function(){function a(){}var b=["ms","Moz","Webkit","O"],c={};a.getProp=function(a,e){if(1==arguments.length&&"string"==typeof c[a])return c[a];e=e||document.documentElement;var g=e.style,h,f;if("string"==typeof g[a])return c[a]=a;f=a.charAt(0).toUpperCase()+a.slice(1);for(var k=0,s=b.length;k<s;k++)if(h=b[k]+f,"string"==typeof g[h])return c[a]=h;return c[a]="undefined"};a.setProp=function(a,b,c){a=this.getProp(a);"undefined"!=a&&(b.style[a]=
+c)};return a}();function getFileName(a){var b=a.indexOf("#"),c=a.indexOf("?"),b=Math.min(0<b?b:a.length,0<c?c:a.length);return a.substring(a.lastIndexOf("/",b)+1,b)}function getOutputScale(a){a=(window.devicePixelRatio||1)/(a.webkitBackingStorePixelRatio||a.mozBackingStorePixelRatio||a.msBackingStorePixelRatio||a.oBackingStorePixelRatio||a.backingStorePixelRatio||1);return{sx:a,sy:a,scaled:1!=a}}
+function scrollIntoView(a,b){var c=a.offsetParent,d=a.offsetTop+a.clientTop,e=a.offsetLeft+a.clientLeft;if(c){for(;c.clientHeight===c.scrollHeight;)if(c.dataset._scaleY&&(d/=c.dataset._scaleY,e/=c.dataset._scaleX),d+=c.offsetTop,e+=c.offsetLeft,c=c.offsetParent,!c)return;b&&(void 0!==b.top&&(d+=b.top),void 0!==b.left&&(e+=b.left,c.scrollLeft=e));c.scrollTop=d}else console.error("offsetParent is not set -- cannot scroll")}function noContextMenuHandler(a){a.preventDefault()}
+function getPDFFileNameFromURL(a){var b=/[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;a=/^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/.exec(a);if(a=b.exec(a[1])||b.exec(a[2])||b.exec(a[3]))if(a=a[0],-1!=a.indexOf("%"))try{a=b.exec(decodeURIComponent(a))[0]}catch(c){}return a||"document.pdf"}
+var ProgressBar=function(){function a(a,c){this.div=document.querySelector(a+" .progress");this.bar=this.div.parentNode;this.height=c.height||100;this.width=c.width||100;this.units=c.units||"%";this.div.style.height=this.height+this.units;this.percent=0}a.prototype={updateBar:function(){this._indeterminate?(this.div.classList.add("indeterminate"),this.div.style.width=this.width+this.units):(this.div.classList.remove("indeterminate"),this.div.style.width=this.width*this._percent/100+this.units)},get percent(){return this._percent},
+set percent(a){this._indeterminate=isNaN(a);this._percent=Math.min(Math.max(a,0),100);this.updateBar()},setWidth:function(a){a&&(a=a.parentNode.offsetWidth-a.offsetWidth,0<a&&this.bar.setAttribute("style","width: calc(100% - "+a+"px);"))},hide:function(){this.bar.classList.add("hidden");this.bar.removeAttribute("style")}};return a}(),Cache=function(a){var b=[];this.push=function(c){var d=b.indexOf(c);0<=d&&b.splice(d);b.push(c);b.length>a&&b.shift().destroy()}},isLocalStorageEnabled=function(){try{return"localStorage"in
+window&&null!==window.localStorage&&localStorage}catch(a){return!1}}(),EXPORTED_SYMBOLS=["DEFAULT_PREFERENCES"],DEFAULT_PREFERENCES={showPreviousViewOnLoad:!0,defaultZoomValue:"",ifAvailableShowOutlineOnLoad:!1},Preferences=function(){function a(){this.prefs={};this.isInitializedPromiseResolved=!1;this.initializedPromise=this.readFromStorage().then(function(a){this.isInitializedPromiseResolved=!0;a&&(this.prefs=a)}.bind(this))}a.prototype={writeToStorage:function(a){},readFromStorage:function(){return Promise.resolve()},
+reset:function(){this.isInitializedPromiseResolved&&(this.prefs={},this.writeToStorage(this.prefs))},set:function(a,c){if(this.isInitializedPromiseResolved)if(void 0===DEFAULT_PREFERENCES[a])console.error("Preferences_set: '"+a+"' is undefined.");else if(void 0===c)console.error("Preferences_set: no value is specified.");else{var d=typeof c,e=typeof DEFAULT_PREFERENCES[a];if(d!==e)if("number"===d&&"string"===e)c=c.toString();else{console.error("Preferences_set: '"+c+"' is a \""+d+'", expected a "'+
+e+'".');return}this.prefs[a]=c;this.writeToStorage(this.prefs)}},get:function(a){var c=DEFAULT_PREFERENCES[a];if(void 0===c)console.error("Preferences_get: '"+a+"' is undefined.");else return this.isInitializedPromiseResolved&&(a=this.prefs[a],void 0!==a)?a:c}};return a}();Preferences.prototype.writeToStorage=function(a){isLocalStorageEnabled&&localStorage.setItem("preferences",JSON.stringify(a))};
+Preferences.prototype.readFromStorage=function(){return new Promise(function(a){if(isLocalStorageEnabled){var b=JSON.parse(localStorage.getItem("preferences"));a(b)}})};
+(function(){function a(a){var b=document.createEvent("CustomEvent");b.initCustomEvent(a,!1,!1,"custom");window.dispatchEvent(b)}function b(){if(e)if(d(),++g<e.length){var a=e[g];"function"===typeof a.mozPrintCallback?a.mozPrintCallback({context:a.getContext("2d"),abort:c,done:b}):b()}else d(),h.call(window),setTimeout(c,20)}function c(){e&&(e=null,d(),a("afterprint"))}function d(){var a=document.getElementById("mozPrintCallback-shim");if(e){var b=Math.round(100*g/e.length),d=a.querySelector("progress"),
+h=a.querySelector(".relative-progress");d.value=b;h.textContent=b+"%";a.removeAttribute("hidden");a.onclick=c}else a.setAttribute("hidden","")}if(!("mozPrintCallback"in document.createElement("canvas"))){HTMLCanvasElement.prototype.mozPrintCallback=void 0;var e,g,h=window.print;window.print=function(){if(e)console.warn("Ignored window.print() because of a pending print job.");else try{a("beforeprint")}finally{e=document.querySelectorAll("canvas"),g=-1,b()}};var f=!!document.attachEvent;window.addEventListener("keydown",
+function(a){80===a.keyCode&&(a.ctrlKey||a.metaKey)?(window.print(),f||(a.preventDefault(),a.stopImmediatePropagation?a.stopImmediatePropagation():a.stopPropagation())):27===a.keyCode&&e&&c()},!0);f&&document.attachEvent("onkeydown",function(a){a=a||window.event;if(80===a.keyCode&&a.ctrlKey)return a.keyCode=0,!1});if("onbeforeprint"in window){var k=function(a){"custom"!==a.detail&&a.stopImmediatePropagation&&a.stopImmediatePropagation()};window.addEventListener("beforeprint",k,!1);window.addEventListener("afterprint",
+k,!1)}}})();
+var DownloadManager=function(){function a(a,b){var e=document.createElement("a");e.click?(e.href=a,e.target="_parent","download"in e&&(e.download=b),(document.body||document.documentElement).appendChild(e),e.click(),e.parentNode.removeChild(e)):(window.top===window&&a.split("#")[0]===window.location.href.split("#")[0]&&(e=-1===a.indexOf("?")?"?":"&",a=a.replace(/#|$/,e+"$&")),window.open(a,"_parent"))}function b(){}b.prototype={downloadUrl:function(b,d){PDFJS.isValidUrl(b,!0)&&a(b+"#pdfjs.action=download",d)},
+download:function(b,d,e){URL?navigator.msSaveBlob?navigator.msSaveBlob(b,e)||this.downloadUrl(d,e):(b=URL.createObjectURL(b),a(b,e)):this.downloadUrl(d,e)}};return b}(),cache=new Cache(CACHE_SIZE),currentPageNumber=1,ViewHistory=function(){function a(a){this.fingerprint=a;var c;this.isInitializedPromiseResolved=!1;this.initializedPromise=new Promise(function(a){c=a});a=function(a){this.isInitializedPromiseResolved=!0;this.initialize(a||"{}");c()}.bind(this);isLocalStorageEnabled&&a(localStorage.getItem("database"))}
+a.prototype={initialize:function(a){a=JSON.parse(a);"files"in a||(a.files=[]);a.files.length>=VIEW_HISTORY_MEMORY&&a.files.shift();for(var c,d=0,e=a.files.length;d<e;d++)if(a.files[d].fingerprint===this.fingerprint){c=d;break}"number"!==typeof c&&(c=a.files.push({fingerprint:this.fingerprint})-1);this.file=a.files[c];this.database=a},set:function(a,c){if(this.isInitializedPromiseResolved){this.file[a]=c;var d=JSON.stringify(this.database);isLocalStorageEnabled&&localStorage.setItem("database",d)}},
+get:function(a,c){return this.isInitializedPromiseResolved?this.file[a]||c:c}};return a}(),PDFFindBar={opened:!1,bar:null,toggleButton:null,findField:null,highlightAll:null,caseSensitive:null,findMsg:null,findStatusIcon:null,findPreviousButton:null,findNextButton:null,initialize:function(a){if("undefined"===typeof PDFFindController||null===PDFFindController)throw"PDFFindBar cannot be initialized without a PDFFindController instance.";this.bar=a.bar;this.toggleButton=a.toggleButton;this.findField=
+a.findField;this.highlightAll=a.highlightAllCheckbox;this.caseSensitive=a.caseSensitiveCheckbox;this.findMsg=a.findMsg;this.findStatusIcon=a.findStatusIcon;this.findPreviousButton=a.findPreviousButton;this.findNextButton=a.findNextButton;var b=this;this.toggleButton.addEventListener("click",function(){b.toggle()});this.findField.addEventListener("input",function(){b.dispatchEvent("")});this.bar.addEventListener("keydown",function(a){switch(a.keyCode){case 13:a.target===b.findField&&b.dispatchEvent("again",
+a.shiftKey);break;case 27:b.close()}});this.findPreviousButton.addEventListener("click",function(){b.dispatchEvent("again",!0)});this.findNextButton.addEventListener("click",function(){b.dispatchEvent("again",!1)});this.highlightAll.addEventListener("click",function(){b.dispatchEvent("highlightallchange")});this.caseSensitive.addEventListener("click",function(){b.dispatchEvent("casesensitivitychange")})},dispatchEvent:function(a,b){var c=document.createEvent("CustomEvent");c.initCustomEvent("find"+
+a,!0,!0,{query:this.findField.value,caseSensitive:this.caseSensitive.checked,highlightAll:this.highlightAll.checked,findPrevious:b});return window.dispatchEvent(c)},updateUIState:function(a,b){var c=!1,d="",e="";switch(a){case FindStates.FIND_PENDING:e="pending";break;case FindStates.FIND_NOTFOUND:d=mozL10n.get("find_not_found",null,"Phrase not found");c=!0;break;case FindStates.FIND_WRAPPED:d=b?mozL10n.get("find_reached_top",null,"Reached top of document, continued from bottom"):mozL10n.get("find_reached_bottom",
+null,"Reached end of document, continued from top")}c?this.findField.classList.add("notFound"):this.findField.classList.remove("notFound");this.findField.setAttribute("data-status",e);this.findMsg.textContent=d},open:function(){this.opened||(this.opened=!0,this.toggleButton.classList.add("toggled"),this.bar.classList.remove("hidden"));this.findField.select();this.findField.focus()},close:function(){this.opened&&(this.opened=!1,this.toggleButton.classList.remove("toggled"),this.bar.classList.add("hidden"),
+PDFFindController.active=!1)},toggle:function(){this.opened?this.close():this.open()}},PDFFindController={startedTextExtraction:!1,extractTextPromises:[],pendingFindMatches:{},active:!1,pageContents:[],pageMatches:[],selected:{pageIdx:-1,matchIdx:-1},offset:{pageIdx:null,matchIdx:null},resumePageIdx:null,resumeCallback:null,state:null,dirtyMatch:!1,findTimeout:null,pdfPageSource:null,integratedFind:!1,initialize:function(a){if("undefined"===typeof PDFFindBar||null===PDFFindBar)throw"PDFFindController cannot be initialized without a PDFFindController instance";
+this.pdfPageSource=a.pdfPageSource;this.integratedFind=a.integratedFind;a=["find","findagain","findhighlightallchange","findcasesensitivitychange"];this.firstPagePromise=new Promise(function(a){this.resolveFirstPage=a}.bind(this));this.handleEvent=this.handleEvent.bind(this);for(var b=0;b<a.length;b++)window.addEventListener(a[b],this.handleEvent)},reset:function(){this.startedTextExtraction=!1;this.extractTextPromises=[];this.active=!1},calcFindMatch:function(a){var b=this.pageContents[a],c=this.state.query,
+d=this.state.caseSensitive,e=c.length;if(0!==e){d||(b=b.toLowerCase(),c=c.toLowerCase());for(var d=[],g=-e;;){g=b.indexOf(c,g+e);if(-1===g)break;d.push(g)}this.pageMatches[a]=d;this.updatePage(a);this.resumePageIdx===a&&(a=this.resumeCallback,this.resumeCallback=this.resumePageIdx=null,a())}},extractText:function(){function a(c){e.pdfPageSource.pages[c].getTextContent().then(function(d){d=d.bidiTexts;for(var f="",k=0;k<d.length;k++)f+=d[k].str;e.pageContents.push(f);b[c](c);c+1<e.pdfPageSource.pages.length&&
+a(c+1)})}if(!this.startedTextExtraction){this.startedTextExtraction=!0;this.pageContents=[];for(var b=[],c=0,d=this.pdfPageSource.pdfDocument.numPages;c<d;c++)this.extractTextPromises.push(new Promise(function(a){b.push(a)}));var e=this;a(0)}},handleEvent:function(a){if(null===this.state||"findagain"!==a.type)this.dirtyMatch=!0;this.state=a.detail;this.updateUIState(FindStates.FIND_PENDING);this.firstPagePromise.then(function(){this.extractText();clearTimeout(this.findTimeout);"find"===a.type?this.findTimeout=
+setTimeout(this.nextMatch.bind(this),250):this.nextMatch()}.bind(this))},updatePage:function(a){var b=this.pdfPageSource.pages[a];this.selected.pageIdx===a&&b.scrollIntoView();b.textLayer&&b.textLayer.updateMatches()},nextMatch:function(){var a=this.state.findPrevious,b=this.pdfPageSource.page-1,c=this.pdfPageSource.pages.length;this.active=!0;if(this.dirtyMatch){this.dirtyMatch=!1;this.selected.pageIdx=this.selected.matchIdx=-1;this.offset.pageIdx=b;this.offset.matchIdx=null;this.hadMatch=!1;this.resumePageIdx=
+this.resumeCallback=null;this.pageMatches=[];for(var d=this,b=0;b<c;b++)this.updatePage(b),b in this.pendingFindMatches||(this.pendingFindMatches[b]=!0,this.extractTextPromises[b].then(function(a){delete d.pendingFindMatches[a];d.calcFindMatch(a)}))}if(""===this.state.query)this.updateUIState(FindStates.FIND_FOUND);else if(!this.resumeCallback){c=this.offset;if(null!==c.matchIdx){b=this.pageMatches[c.pageIdx].length;if(!a&&c.matchIdx+1<b||a&&0<c.matchIdx){this.hadMatch=!0;c.matchIdx=a?c.matchIdx-
+1:c.matchIdx+1;this.updateMatch(!0);return}this.advanceOffsetPage(a)}this.nextPageMatch()}},nextPageMatch:function(){null!==this.resumePageIdx&&console.error("There can only be one pending page.");var a=function(a){var b=this.offset;a=a.length;var c=this.state.findPrevious;if(a)this.hadMatch=!0,b.matchIdx=c?a-1:0,this.updateMatch(!0);else{this.advanceOffsetPage(c);if(b.wrapped&&(b.matchIdx=null,!this.hadMatch)){this.updateMatch(!1);return}this.nextPageMatch()}}.bind(this),b=this.offset.pageIdx,c=
+this.pageMatches;c[b]?a(c[b]):(this.resumeCallback=function(){a(c[b])},this.resumePageIdx=b)},advanceOffsetPage:function(a){var b=this.offset,c=this.extractTextPromises.length;b.pageIdx=a?b.pageIdx-1:b.pageIdx+1;b.matchIdx=null;if(b.pageIdx>=c||0>b.pageIdx)b.pageIdx=a?c-1:0,b.wrapped=!0},updateMatch:function(a){var b=FindStates.FIND_NOTFOUND,c=this.offset.wrapped;this.offset.wrapped=!1;a&&(a=this.selected.pageIdx,this.selected.pageIdx=this.offset.pageIdx,this.selected.matchIdx=this.offset.matchIdx,
+b=c?FindStates.FIND_WRAPPED:FindStates.FIND_FOUND,-1!==a&&a!==this.selected.pageIdx&&this.updatePage(a));this.updateUIState(b,this.state.findPrevious);-1!==this.selected.pageIdx&&this.updatePage(this.selected.pageIdx,!0)},updateUIState:function(a,b){this.integratedFind?FirefoxCom.request("updateFindControlState",{result:a,findPrevious:b}):PDFFindBar.updateUIState(a,b)}},PDFHistory={initialized:!1,initialDestination:null,initialize:function(a){function b(){var a=c._getPreviousParams(null,!0);a&&(c._pushToHistory(a,
+!1,!c.current.dest&&c.current.hash!==c.previousHash),c._updatePreviousBookmark());window.removeEventListener("beforeunload",b,!1)}if(!PDFJS.disableHistory&&!PDFView.isViewerEmbedded){this.initialized=!0;this.reInitialized=!1;this.historyUnlocked=this.allowHashChange=!0;this.previousHash=window.location.hash.substring(1);this.currentBookmark="";this.currentPage=0;this.updatePreviousBookmark=!1;this.previousBookmark="";this.previousPage=0;this.nextHashParam="";this.fingerprint=a;this.currentUid=this.uid=
+0;this.current={};a=window.history.state;this._isStateObjectDefined(a)?(a.target.dest?this.initialDestination=a.target.dest:PDFView.initialBookmark=a.target.hash,this.currentUid=a.uid,this.uid=a.uid+1,this.current=a.target):(a&&a.fingerprint&&this.fingerprint!==a.fingerprint&&(this.reInitialized=!0),this._pushOrReplaceState({fingerprint:this.fingerprint},!0));var c=this;window.addEventListener("popstate",function(a){a.preventDefault();a.stopPropagation();c.historyUnlocked&&(a.state?c._goTo(a.state):
+(c.previousHash=window.location.hash.substring(1),0===c.uid&&(a=c.previousHash&&c.currentBookmark&&c.previousHash!==c.currentBookmark?{hash:c.currentBookmark,page:c.currentPage}:{page:1},c.historyUnlocked=!1,c.allowHashChange=!1,window.history.back(),c._pushToHistory(a,!1,!0),window.history.forward(),c.historyUnlocked=!0),c._pushToHistory({hash:c.previousHash},!1,!0),c._updatePreviousBookmark()))},!1);window.addEventListener("beforeunload",b,!1);window.addEventListener("pageshow",function(a){window.addEventListener("beforeunload",
+b,!1)},!1)}},_isStateObjectDefined:function(a){return a&&0<=a.uid&&a.fingerprint&&this.fingerprint===a.fingerprint&&a.target&&a.target.hash?!0:!1},_pushOrReplaceState:function(a,b){b?window.history.replaceState(a,"",document.URL):window.history.pushState(a,"",document.URL)},get isHashChangeUnlocked(){if(!this.initialized)return!0;var a=this.allowHashChange;this.allowHashChange=!0;return a},_updatePreviousBookmark:function(){this.updatePreviousBookmark&&this.currentBookmark&&this.currentPage&&(this.previousBookmark=
+this.currentBookmark,this.previousPage=this.currentPage,this.updatePreviousBookmark=!1)},updateCurrentBookmark:function(a,b){this.initialized&&(this.currentBookmark=a.substring(1),this.currentPage=b|0,this._updatePreviousBookmark())},updateNextHashParam:function(a){this.initialized&&(this.nextHashParam=a)},push:function(a,b){if(this.initialized&&this.historyUnlocked)if(a.dest&&!a.hash&&(a.hash=this.current.hash&&this.current.dest&&this.current.dest===a.dest?this.current.hash:PDFView.getDestinationHash(a.dest).split("#")[1]),
+a.page&&(a.page|=0),b){var c=window.history.state.target;c||(this._pushToHistory(a,!1),this.previousHash=window.location.hash.substring(1));this.updatePreviousBookmark=this.nextHashParam?!1:!0;c&&this._updatePreviousBookmark()}else{if(this.nextHashParam){if(this.nextHashParam===a.hash){this.nextHashParam=null;this.updatePreviousBookmark=!0;return}this.nextHashParam=null}a.hash?this.current.hash?this.current.hash!==a.hash?this._pushToHistory(a,!0):(!this.current.page&&a.page&&this._pushToHistory(a,
+!1,!0),this.updatePreviousBookmark=!0):this._pushToHistory(a,!0):this.current.page&&a.page&&this.current.page!==a.page&&this._pushToHistory(a,!0)}},_getPreviousParams:function(a,b){if(!this.currentBookmark||!this.currentPage)return null;this.updatePreviousBookmark&&(this.updatePreviousBookmark=!1);if(0<this.uid&&(!this.previousBookmark||!this.previousPage))return null;if(!this.current.dest&&!a||b){if(this.previousBookmark===this.currentBookmark)return null}else if(this.current.page||a){if(this.previousPage===
+this.currentPage)return null}else return null;var c={hash:this.currentBookmark,page:this.currentPage};PresentationMode.active&&(c.hash=null);return c},_stateObj:function(a){return{fingerprint:this.fingerprint,uid:this.uid,target:a}},_pushToHistory:function(a,b,c){this.initialized&&(!a.hash&&a.page&&(a.hash="page="+a.page),b&&!c&&(b=this._getPreviousParams())&&this._pushToHistory(b,!1,!this.current.dest&&this.current.hash!==this.previousHash),this._pushOrReplaceState(this._stateObj(a),c||0===this.uid),
+this.currentUid=this.uid++,this.current=a,this.updatePreviousBookmark=!0)},_goTo:function(a){if(this.initialized&&this.historyUnlocked&&this._isStateObjectDefined(a)){if(!this.reInitialized&&a.uid<this.currentUid){var b=this._getPreviousParams(!0);if(b){this._pushToHistory(this.current,!1);this._pushToHistory(b,!1);this.currentUid=a.uid;window.history.back();return}}this.historyUnlocked=!1;a.target.dest?PDFView.navigateTo(a.target.dest):PDFView.setHash(a.target.hash);this.currentUid=a.uid;a.uid>this.uid&&
+(this.uid=a.uid);this.current=a.target;this.updatePreviousBookmark=!0;a=window.location.hash.substring(1);this.previousHash!==a&&(this.allowHashChange=!1);this.previousHash=a;this.historyUnlocked=!0}},back:function(){this.go(-1)},forward:function(){this.go(1)},go:function(a){if(this.initialized&&this.historyUnlocked){var b=window.history.state;-1===a&&b&&0<b.uid?window.history.back():1===a&&b&&b.uid<this.uid-1&&window.history.forward()}}},SecondaryToolbar={opened:!1,previousContainerHeight:null,newContainerHeight:null,
+initialize:function(a){this.toolbar=a.toolbar;this.presentationMode=a.presentationMode;this.buttonContainer=this.toolbar.firstElementChild;this.toggleButton=a.toggleButton;this.presentationModeButton=a.presentationModeButton;this.openFile=a.openFile;this.print=a.print;this.download=a.download;this.firstPage=a.firstPage;this.lastPage=a.lastPage;this.pageRotateCw=a.pageRotateCw;this.pageRotateCcw=a.pageRotateCcw;a=[{element:this.toggleButton,handler:this.toggle},{element:this.presentationModeButton,
+handler:this.presentationModeClick},{element:this.print,handler:this.printClick},{element:this.firstPage,handler:this.firstPageClick},{element:this.lastPage,handler:this.lastPageClick},{element:this.pageRotateCw,handler:this.pageRotateCwClick},{element:this.pageRotateCcw,handler:this.pageRotateCcwClick}];for(var b in a){var c=a[b].element;c&&c.addEventListener("click",a[b].handler.bind(this))}},presentationModeClick:function(a){this.presentationMode.request();this.close()},openFileClick:function(a){document.getElementById("fileInput").click();
+this.close(a.target)},printClick:function(a){window.print();this.close(a.target)},downloadClick:function(a){PDFView.download();this.close(a.target)},firstPageClick:function(a){PDFView.page=1},lastPageClick:function(a){PDFView.page=PDFView.pdfDocument.numPages},pageRotateCwClick:function(a){PDFView.rotatePages(90)},pageRotateCcwClick:function(a){PDFView.rotatePages(-90)},setMaxHeight:function(a){a&&this.buttonContainer&&(this.newContainerHeight=a.clientHeight,this.previousContainerHeight!==this.newContainerHeight&&
+(this.buttonContainer.setAttribute("style","max-height: "+(this.newContainerHeight-SCROLLBAR_PADDING)+"px;"),this.previousContainerHeight=this.newContainerHeight))},open:function(){this.opened||(this.opened=!0,this.toggleButton.classList.add("toggled"),this.toolbar.classList.remove("hidden"))},close:function(a){!this.opened||a&&!this.toolbar.contains(a)||(this.opened=!1,this.toolbar.classList.add("hidden"),this.toggleButton.classList.remove("toggled"))},toggle:function(){this.opened?this.close():
+this.open()}},PasswordPrompt={visible:!1,updatePassword:null,reason:null,overlayContainer:null,passwordField:null,passwordText:null,passwordSubmit:null,passwordCancel:null,initialize:function(a){this.overlayContainer=a.overlayContainer;this.passwordField=a.passwordField;this.passwordText=a.passwordText;this.passwordSubmit=a.passwordSubmit;this.passwordCancel=a.passwordCancel;this.passwordSubmit.addEventListener("click",this.verifyPassword.bind(this));this.passwordCancel.addEventListener("click",this.hide.bind(this));
+this.passwordField.addEventListener("keydown",function(a){13===a.keyCode&&this.verifyPassword()}.bind(this));this.overlayContainer.addEventListener("keydown",function(a){27===a.keyCode&&this.hide()}.bind(this))},show:function(){if(!this.visible){this.visible=!0;this.overlayContainer.classList.remove("hidden");this.passwordField.focus();var a=mozL10n.get("password_label",null,"Enter the password to open this PDF file.");this.reason===PDFJS.PasswordResponses.INCORRECT_PASSWORD&&(a=mozL10n.get("password_invalid",
+null,"Invalid password. Please try again."));this.passwordText.textContent=a}},hide:function(){this.visible&&(this.visible=!1,this.passwordField.value="",this.overlayContainer.classList.add("hidden"))},verifyPassword:function(){var a=this.passwordField.value;if(a&&0<a.length)return this.hide(),this.updatePassword(a)}},DELAY_BEFORE_HIDING_CONTROLS=3E3,SELECTOR="presentationControls",DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS=1E3,PresentationMode={active:!1,args:null,contextMenuOpen:!1,prevCoords:{x:null,
+y:null},initialize:function(a){this.container=a.container;this.secondaryToolbar=a.secondaryToolbar;this.viewer=this.container.firstElementChild;this.firstPage=a.firstPage;this.lastPage=a.lastPage;this.pageRotateCw=a.pageRotateCw;this.pageRotateCcw=a.pageRotateCcw;this.firstPage.addEventListener("click",function(){this.contextMenuOpen=!1;this.secondaryToolbar.firstPageClick()}.bind(this));this.lastPage.addEventListener("click",function(){this.contextMenuOpen=!1;this.secondaryToolbar.lastPageClick()}.bind(this));
+this.pageRotateCw.addEventListener("click",function(){this.contextMenuOpen=!1;this.secondaryToolbar.pageRotateCwClick()}.bind(this));this.pageRotateCcw.addEventListener("click",function(){this.contextMenuOpen=!1;this.secondaryToolbar.pageRotateCcwClick()}.bind(this))},get isFullscreen(){return document.fullscreenElement||document.mozFullScreen||document.webkitIsFullScreen||document.msFullscreenElement},_setSwitchInProgress:function(){this.switchInProgress&&clearTimeout(this.switchInProgress);this.switchInProgress=
+setTimeout(function(){delete this.switchInProgress}.bind(this),DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS);PDFView.currentPosition=null},_resetSwitchInProgress:function(){this.switchInProgress&&(clearTimeout(this.switchInProgress),delete this.switchInProgress)},request:function(){if(!PDFView.supportsFullscreen||this.isFullscreen||!this.viewer.hasChildNodes())return!1;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)this.container.msRequestFullscreen();else return!1;this.args={page:PDFView.page,previousScale:PDFView.currentScaleValue};return!0},enter:function(){this.active=!0;this._resetSwitchInProgress();setTimeout(function(){PDFView.page=this.args.page;PDFView.setScale("page-fit",!0)}.bind(this),0);window.addEventListener("mousemove",this.mouseMove,!1);
+window.addEventListener("mousedown",this.mouseDown,!1);window.addEventListener("contextmenu",this.contextMenu,!1);this.showControls();HandTool.enterPresentationMode();this.contextMenuOpen=!1;this.container.setAttribute("contextmenu","viewerContextMenu")},exit:function(){var a=PDFView.page;setTimeout(function(){PDFView.setScale(this.args.previousScale);PDFView.page=a;this.active=!1;this.args=null}.bind(this),0);window.removeEventListener("mousemove",this.mouseMove,!1);window.removeEventListener("mousedown",
+this.mouseDown,!1);window.removeEventListener("contextmenu",this.contextMenu,!1);this.hideControls();PDFView.clearMouseScrollState();HandTool.exitPresentationMode();this.container.removeAttribute("contextmenu");this.contextMenuOpen=!1;scrollIntoView(document.getElementById("thumbnailContainer"+a))},showControls:function(){this.controlsTimeout?clearTimeout(this.controlsTimeout):this.container.classList.add(SELECTOR);this.controlsTimeout=setTimeout(function(){this.container.classList.remove(SELECTOR);
+delete this.controlsTimeout}.bind(this),DELAY_BEFORE_HIDING_CONTROLS)},hideControls:function(){this.controlsTimeout&&(this.container.classList.remove(SELECTOR),clearTimeout(this.controlsTimeout),delete this.controlsTimeout)},mouseMove:function(a){a={x:a.clientX,y:a.clientY};var b=PresentationMode.prevCoords;PresentationMode.prevCoords=a;a.x===b.x&&a.y===b.y||PresentationMode.showControls()},mouseDown:function(a){var b=PresentationMode;b.contextMenuOpen?(b.contextMenuOpen=!1,a.preventDefault()):0!==
+a.button||a.target.href&&a.target.classList.contains("internalLink")||(a.preventDefault(),PDFView.page+=a.shiftKey?-1:1)},contextMenu:function(a){PresentationMode.contextMenuOpen=!0}};(function(){function a(a){PresentationMode.isFullscreen?PresentationMode.enter():PresentationMode.exit()}window.addEventListener("fullscreenchange",a,!1);window.addEventListener("mozfullscreenchange",a,!1);window.addEventListener("webkitfullscreenchange",a,!1);window.addEventListener("MSFullscreenChange",a,!1)})();"use strict";
+var GrabToPan=function(){function a(a){this.element=a.element;this.document=a.element.ownerDocument;"function"===typeof a.ignoreTarget&&(this.ignoreTarget=a.ignoreTarget);this.onActiveChanged=a.onActiveChanged;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)}a.prototype={CSS_CLASS_GRAB:"grab-to-pan-grab",
+CSS_CLASS_GRABBING:"grab-to-pan-grabbing",activate:function(){if(!this.active&&(this.active=!0,this.element.addEventListener("mousedown",this._onmousedown,!0),this.element.classList.add(this.CSS_CLASS_GRAB),this.onActiveChanged))this.onActiveChanged(!0)},deactivate:function(){if(this.active&&(this.active=!1,this.element.removeEventListener("mousedown",this._onmousedown,!0),this._endPan(),this.element.classList.remove(this.CSS_CLASS_GRAB),this.onActiveChanged))this.onActiveChanged(!1)},toggle:function(){this.active?
+this.deactivate():this.activate()},ignoreTarget:function(a){return a[b]("a[href], a[href] *, input, textarea, button, button *, select, option")},_onmousedown:function(a){if(0===a.button&&!this.ignoreTarget(a.target)){if(a.originalTarget)try{a.originalTarget.tagName}catch(b){return}this.scrollLeftStart=this.element.scrollLeft;this.scrollTopStart=this.element.scrollTop;this.clientXStart=a.clientX;this.clientYStart=a.clientY;this.document.addEventListener("mousemove",this._onmousemove,!0);this.document.addEventListener("mouseup",
+this._endPan,!0);this.element.addEventListener("scroll",this._endPan,!0);a.preventDefault();a.stopPropagation();this.element.classList.remove(this.CSS_CLASS_GRAB);this.document.documentElement.classList.add(this.CSS_CLASS_GRABBING)}},_onmousemove:function(a){this.element.removeEventListener("scroll",this._endPan,!0);var b;b="buttons"in a&&c?!(a.buttons|1):e||g?0===a.which:void 0;b?this.document.removeEventListener("mousemove",this._onmousemove,!0):(b=a.clientX-this.clientXStart,this.element.scrollTop=
+this.scrollTopStart-(a.clientY-this.clientYStart),this.element.scrollLeft=this.scrollLeftStart-b)},_endPan:function(){this.element.removeEventListener("scroll",this._endPan,!0);this.document.removeEventListener("mousemove",this._onmousemove,!0);this.document.removeEventListener("mouseup",this._endPan,!0);this.document.documentElement.classList.remove(this.CSS_CLASS_GRABBING);this.element.classList.add(this.CSS_CLASS_GRAB)}};var b;["webkitM","mozM","msM","oM","m"].some(function(a){a+="atches";a in
+document.documentElement&&(b=a);a+="Selector";a in document.documentElement&&(b=a);return b});var c=!document.documentMode||9<document.documentMode,d=window.chrome,e=d&&(d.webstore||d.app),g=/Apple/.test(navigator.vendor)&&/Version\/([6-9]\d*|[1-5]\d+)/.test(navigator.userAgent);return a}(),HandTool={initialize:function(a){var b=a.toggleHandTool;this.handTool=new GrabToPan({element:a.container,onActiveChanged:function(a){b&&(a?(b.title=mozL10n.get("hand_tool_disable.title",null,"Disable hand tool"),
+b.firstElementChild.textContent=mozL10n.get("hand_tool_disable_label",null,"Disable hand tool")):(b.title=mozL10n.get("hand_tool_enable.title",null,"Enable hand tool"),b.firstElementChild.textContent=mozL10n.get("hand_tool_enable_label",null,"Enable hand tool")))}});b&&b.addEventListener("click",this.handTool.toggle,!1)},toggle:function(){this.handTool.toggle()},enterPresentationMode:function(){this.handTool.active&&(this.wasActive=!0,this.handTool.deactivate())},exitPresentationMode:function(){this.wasActive&&
+(this.wasActive=null,this.handTool.activate())}},PDFView={pages:[],thumbnails:[],currentScale:UNKNOWN_SCALE,currentScaleValue:null,initialBookmark:document.location.hash.substring(1),container:null,thumbnailContainer:null,initialized:!1,fellback:!1,pdfDocument:null,sidebarOpen:!1,pageViewScroll:null,thumbnailViewScroll:null,pageRotation:0,mouseScrollTimeStamp:0,mouseScrollDelta:0,lastScroll:0,previousPageNumber:1,isViewerEmbedded:window.parent!==window,idleTimeout:null,currentPosition:null,initialize:function(){var a=
+this,b=this.container=document.getElementById("viewerContainer");this.pageViewScroll={};this.watchScroll(b,this.pageViewScroll,updateViewarea);var c=this.thumbnailContainer=document.getElementById("thumbnailView");this.thumbnailViewScroll={};this.watchScroll(c,this.thumbnailViewScroll,this.renderHighestPriority.bind(this));PDFFindBar.initialize({bar:document.getElementById("findbar"),toggleButton:document.getElementById("viewFind"),findField:document.getElementById("findInput"),highlightAllCheckbox:document.getElementById("findHighlightAll"),
+caseSensitiveCheckbox:document.getElementById("findMatchCase"),findMsg:document.getElementById("findMsg"),findStatusIcon:document.getElementById("findStatusIcon"),findPreviousButton:document.getElementById("findPrevious"),findNextButton:document.getElementById("findNext")});PDFFindController.initialize({pdfPageSource:this,integratedFind:this.supportsIntegratedFind});HandTool.initialize({container:b,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"),firstPage:document.getElementById("firstPage"),lastPage:document.getElementById("lastPage"),pageRotateCw:document.getElementById("pageRotateCw"),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")});PresentationMode.initialize({container:b,secondaryToolbar:SecondaryToolbar,firstPage:document.getElementById("contextFirstPage"),lastPage:document.getElementById("contextLastPage"),pageRotateCw:document.getElementById("contextPageRotateCw"),
+pageRotateCcw:document.getElementById("contextPageRotateCcw")});this.initialized=!0;b.addEventListener("scroll",function(){a.lastScroll=Date.now()},!1)},getPage:function(a){return this.pdfDocument.getPage(a)},watchScroll:function(a,b,c){b.down=!0;b.lastY=a.scrollTop;a.addEventListener("scroll",function(d){d=a.scrollTop;var e=b.lastY;d>e?b.down=!0:d<e&&(b.down=!1);b.lastY=d;c()},!0)},_setScaleUpdatePages:function(a,b,c,d){this.currentScaleValue=b;if(a!==this.currentScale){b=0;for(var e=this.pages.length;b<
+e;b++)this.pages[b].update(a);this.currentScale=a;if(!d){d=this.page;var g;this.currentPosition&&!IGNORE_CURRENT_POSITION_ON_ZOOM&&(d=this.currentPosition.page,g=[null,{name:"XYZ"},this.currentPosition.left,this.currentPosition.top,null]);this.pages[d-1].scrollIntoView(g)}g=document.createEvent("UIEvents");g.initUIEvent("scalechange",!1,!1,window,0);g.scale=a;g.resetAutoSettings=c;window.dispatchEvent(g)}},setScale:function(a,b,c){if("custom"!==a){var d=parseFloat(a);if(0<d)this._setScaleUpdatePages(d,
+a,!0,c);else{var e=this.pages[this.page-1];if(e){d=(this.container.clientWidth-SCROLLBAR_PADDING)/e.width*e.scale;e=(this.container.clientHeight-VERTICAL_PADDING)/e.height*e.scale;switch(a){case "page-actual":d=1;break;case "page-width":break;case "page-height":d=e;break;case "page-fit":d=Math.min(d,e);break;case "auto":d=Math.min(MAX_AUTO_SCALE,d);break;default:console.error("pdfViewSetScale: '"+a+"' is an unknown zoom value.");return}this._setScaleUpdatePages(d,a,b,c);selectScaleOption(a)}}}},zoomIn:function(a){var b=
+this.currentScale;do b=(b*DEFAULT_SCALE_DELTA).toFixed(2),b=Math.ceil(10*b)/10,b=Math.min(MAX_SCALE,b);while(--a&&b<MAX_SCALE);this.setScale(b,!0)},zoomOut:function(a){var b=this.currentScale;do b=(b/DEFAULT_SCALE_DELTA).toFixed(2),b=Math.floor(10*b)/10,b=Math.max(MIN_SCALE,b);while(--a&&b>MIN_SCALE);this.setScale(b,!0)},set page(a){var b=this.pages,c=document.createEvent("UIEvents");c.initUIEvent("pagechange",!1,!1,window,0);0<a&&a<=b.length?(b[a-1].updateStats(),this.previousPageNumber=currentPageNumber,
+currentPageNumber=a,c.pageNumber=a,window.dispatchEvent(c),updateViewarea.inProgress||this.loading&&1===a||b[a-1].scrollIntoView()):(this.previousPageNumber=a,c.pageNumber=this.page,window.dispatchEvent(c))},get page(){return currentPageNumber},get supportsPrinting(){var a="mozPrintCallback"in document.createElement("canvas");Object.defineProperty(this,"supportsPrinting",{value:a,enumerable:!0,configurable:!0,writable:!1});return a},get supportsFullscreen(){var a=document.documentElement,a=a.requestFullscreen||
+a.mozRequestFullScreen||a.webkitRequestFullScreen||a.msRequestFullscreen;!1===document.fullscreenEnabled||!1===document.mozFullScreenEnabled||!1===document.webkitFullscreenEnabled||!1===document.msFullscreenEnabled?a=!1:this.isViewerEmbedded&&(a=!1);Object.defineProperty(this,"supportsFullscreen",{value:a,enumerable:!0,configurable:!0,writable:!1});return a},get supportsIntegratedFind(){Object.defineProperty(this,"supportsIntegratedFind",{value:!1,enumerable:!0,configurable:!0,writable:!1});return!1},
+get supportsDocumentFonts(){Object.defineProperty(this,"supportsDocumentFonts",{value:!0,enumerable:!0,configurable:!0,writable:!1});return!0},get supportsDocumentColors(){Object.defineProperty(this,"supportsDocumentColors",{value:!0,enumerable:!0,configurable:!0,writable:!1});return!0},get loadingBar(){var a=new ProgressBar("#loadingBar",{});Object.defineProperty(this,"loadingBar",{value:a,enumerable:!0,configurable:!0,writable:!1});return a},get isHorizontalScrollbarEnabled(){return PresentationMode.active?
+!1:this.container.scrollWidth>this.container.clientWidth},initPassiveLoading:function(){var a={rangeListeners:[],progressListeners:[],addRangeListener:function(a){this.rangeListeners.push(a)},addProgressListener:function(a){this.progressListeners.push(a)},onDataRange:function(a,c){for(var d=this.rangeListeners,e=0,g=d.length;e<g;++e)d[e](a,c)},onDataProgress:function(a){for(var c=this.progressListeners,d=0,e=c.length;d<e;++d)c[d](a)},requestDataRange:function(a,c){FirefoxCom.request("requestDataRange",
+{begin:a,end:c})}};window.addEventListener("message",function(b){var c=b.data;if("object"===typeof c&&"pdfjsLoadAction"in c)switch(c.pdfjsLoadAction){case "supportsRangedLoading":PDFView.open(c.pdfUrl,0,void 0,a,{length:c.length,initialData:c.data});break;case "range":a.onDataRange(c.begin,c.chunk);break;case "rangeProgress":a.onDataProgress(c.loaded);break;case "progress":PDFView.progress(c.loaded/c.total);break;case "complete":if(!c.data){PDFView.error(mozL10n.get("loading_error",null,"An error occurred while loading the PDF."),
+b);break}PDFView.open(c.data,0)}});FirefoxCom.requestSync("initPassiveLoading",null)},setTitleUsingUrl:function(a){this.url=a;try{this.setTitle(decodeURIComponent(getFileName(a))||a)}catch(b){this.setTitle(a)}},setTitle:function(a){document.title=a},open:function(a,b,c,d,e){c={password:c};"string"===typeof a?(this.setTitleUsingUrl(a),c.url=a):a&&"byteLength"in a&&(c.data=a);if(e)for(var g in e)c[g]=e[g];this.pdfDocument=null;var h=this;h.loading=!0;PDFJS.getDocument(c,d,function(a,b){PasswordPrompt.updatePassword=
+a;PasswordPrompt.reason=b;PasswordPrompt.show()},function(a){h.progress(a.loaded/a.total)}).then(function(a){h.load(a,b);h.loading=!1},function(a,b){var c=mozL10n.get("loading_error",null,"An error occurred while loading the PDF.");b&&"InvalidPDFException"===b.name&&(c=mozL10n.get("invalid_file_error",null,"Invalid or corrupted PDF file."));b&&"MissingPDFException"===b.name&&(c=mozL10n.get("missing_file_error",null,"Missing PDF file."));h.error(c,{message:a});h.loading=!1})},download:function(){function a(){d.downloadUrl(b,
+c)}var b=this.url.split("#")[0],c=getPDFFileNameFromURL(b),d=new DownloadManager;d.onerror=function(a){PDFView.error("PDF failed to download.")};this.pdfDocument?this.pdfDocument.getData().then(function(a){a=PDFJS.createBlob(a,"application/pdf");d.download(a,b,c)},a).then(null,a):a()},fallback:function(a){},navigateTo:function(a){var b="",c=this,d=function(e){c.pendingRefStr=null;var g=e instanceof Object?c.pagesRefMap[e.num+" "+e.gen+" R"]:e+1;g?(g>c.pages.length&&(g=c.pages.length),c.pages[g-1].scrollIntoView(a),
+PDFHistory.push({dest:a,hash:b,page:g})):c.pdfDocument.getPageIndex(e).then(function(a){c.pagesRefMap[e.num+" "+e.gen+" R"]=a+1;d(e)})};this.destinationsPromise.then(function(){"string"===typeof a&&(b=a,a=c.destinations[a]);a instanceof Array&&d(a[0])})},getDestinationHash:function(a){if("string"===typeof a)return PDFView.getAnchorUrl("#"+escape(a));if(a instanceof Array){var b=a[0];if(b=b instanceof Object?this.pagesRefMap[b.num+" "+b.gen+" R"]:b+1){var b=PDFView.getAnchorUrl("#page="+b),c=a[1];
+if("object"===typeof c&&"name"in c&&"XYZ"==c.name){var c=a[4]||this.currentScaleValue,d=parseFloat(c);d&&(c=100*d);b+="&zoom="+c;if(a[2]||a[3])b+=","+(a[2]||0)+","+(a[3]||0)}return b}}return""},getAnchorUrl:function(a){return a},error:function(a,b){var c=mozL10n.get("error_version_info",{version:PDFJS.version||"?",build:PDFJS.build||"?"},"PDF.js v{{version}} (build: {{build}})")+"\n";b&&(c+=mozL10n.get("error_message",{message:b.message},"Message: {{message}}"),b.stack?c+="\n"+mozL10n.get("error_stack",
+{stack:b.stack},"Stack: {{stack}}"):(b.filename&&(c+="\n"+mozL10n.get("error_file",{file:b.filename},"File: {{file}}")),b.lineNumber&&(c+="\n"+mozL10n.get("error_line",{line:b.lineNumber},"Line: {{line}}"))));var d=document.getElementById("errorWrapper");d.removeAttribute("hidden");document.getElementById("errorMessage").textContent=a;var e=document.getElementById("errorClose");e.onclick=function(){d.setAttribute("hidden","true")};var g=document.getElementById("errorMoreInfo"),h=document.getElementById("errorShowMore"),
+f=document.getElementById("errorShowLess");h.onclick=function(){g.removeAttribute("hidden");h.setAttribute("hidden","true");f.removeAttribute("hidden");g.style.height=g.scrollHeight+"px"};f.onclick=function(){g.setAttribute("hidden","true");h.removeAttribute("hidden");f.setAttribute("hidden","true")};h.oncontextmenu=noContextMenuHandler;f.oncontextmenu=noContextMenuHandler;e.oncontextmenu=noContextMenuHandler;h.removeAttribute("hidden");f.setAttribute("hidden","true");g.value=c},progress:function(a){a=
+Math.round(100*a);a>PDFView.loadingBar.percent&&(PDFView.loadingBar.percent=a)},load:function(a,b){function c(a,b){a.onAfterDraw=function(){e||(e=!0,g());b.setImage(a.canvas)}}var d=this,e=!1,g=null,h=new Promise(function(a){g=a});PDFFindController.reset();this.pdfDocument=a;document.getElementById("errorWrapper").setAttribute("hidden","true");a.dataLoaded().then(function(){PDFView.loadingBar.hide();document.getElementById("outerContainer").classList.remove("loadingInProgress")});var f=document.getElementById("thumbnailView");
+for(f.parentNode.scrollTop=0;f.hasChildNodes();)f.removeChild(f.lastChild);"_loadingInterval"in f&&clearInterval(f._loadingInterval);for(var k=document.getElementById("viewer");k.hasChildNodes();)k.removeChild(k.lastChild);var s=a.numPages,n=a.fingerprint;document.getElementById("numPages").textContent=mozL10n.get("page_of",{pageCount:s},"of {{pageCount}}");document.getElementById("pageNumber").max=s;var q=PDFView.prefs=new Preferences;PDFView.documentFingerprint=n;var t=PDFView.store=new ViewHistory(n);
+this.pageRotation=0;var u=this.pages=[],p=this.pagesRefMap={},l=this.thumbnails=[],r;this.pagesPromise=n=new Promise(function(a){r=a});var m=a.getPage(1);m.then(function(e){e=e.getViewport((b||1)*CSS_UNITS);for(var g=1;g<=s;++g){var n=e.clone(),q=new PageView(k,g,b,d.navigateTo.bind(d),n),n=new ThumbnailView(f,g,n);c(q,n);u.push(q);l.push(n)}h.then(function(){if(PDFJS.disableAutoFetch)r();else for(var b=s,c=1;c<=s;++c)a.getPage(c).then(function(a,c){var d=u[a-1];d.pdfPage||d.setPdfPage(c);p[c.ref.num+
+" "+c.ref.gen+" R"]=a;b--;b||r()}.bind(null,c))});e=document.createEvent("CustomEvent");e.initCustomEvent("documentload",!0,!0,{});window.dispatchEvent(e);PDFView.loadingBar.setWidth(k);PDFFindController.resolveFirstPage()});Promise.all([m,q.initializedPromise,t.initializedPromise]).then(function(){var a=q.get("showPreviousViewOnLoad"),c=q.get("defaultZoomValue"),e=null;if(a&&t.get("exists",!1))var a=t.get("page","1"),c=c||t.get("zoom",PDFView.currentScale),e=t.get("scrollLeft","0"),h=t.get("scrollTop",
+"0"),e="page="+a+"&zoom="+c+","+e+","+h;else c&&(e="page=1&zoom="+c);PDFHistory.initialize(d.documentFingerprint);d.setInitialView(e,b);d.isViewerEmbedded||d.container.focus()});n.then(function(){PDFView.supportsPrinting&&a.getJavaScript().then(function(a){a.length&&(console.warn("Warning: JavaScript is not supported"),PDFView.fallback(PDFJS.UNSUPPORTED_FEATURES.javaScript));for(var b=/\bprint\s*\(/g,c=0,d=a.length;c<d;c++){var e=a[c];if(e&&b.test(e)){setTimeout(function(){window.print()});break}}})});
+m=this.destinationsPromise=a.getDestinations();m.then(function(a){d.destinations=a});Promise.all([n,m,PDFView.animationStartedPromise]).then(function(){a.getOutline().then(function(a){d.outline=new DocumentOutlineView(a);document.getElementById("viewOutline").disabled=!a;a&&q.get("ifAvailableShowOutlineOnLoad")&&(d.sidebarOpen||document.getElementById("sidebarToggle").click(),d.switchSidebarView("outline"))})});a.getMetadata().then(function(b){var c=b.info;b=b.metadata;d.documentInfo=c;d.metadata=
+b;console.log("PDF "+a.fingerprint+" ["+c.PDFFormatVersion+" "+(c.Producer||"-")+" / "+(c.Creator||"-")+"]"+(PDFJS.version?" (PDF.js: "+PDFJS.version+")":""));var e;b&&b.has("dc:title")&&(e=b.get("dc:title"));!e&&c&&c.Title&&(e=c.Title);e&&d.setTitle(e+" - "+document.title);c.IsAcroFormPresent&&(console.warn("Warning: AcroForm/XFA is not supported"),PDFView.fallback(PDFJS.UNSUPPORTED_FEATURES.forms))})},setInitialView:function(a,b){this.currentScale=0;this.currentScaleValue=null;document.getElementById("pageNumber").value=
+currentPageNumber=1;this.currentPosition=null;PDFHistory.initialDestination?(this.navigateTo(PDFHistory.initialDestination),PDFHistory.initialDestination=null):this.initialBookmark?(this.setHash(this.initialBookmark),PDFHistory.push({hash:this.initialBookmark},!!this.initialBookmark),this.initialBookmark=null):a?this.setHash(a):b&&(this.setScale(b,!0),this.page=1);PDFView.currentScale===UNKNOWN_SCALE&&this.setScale(DEFAULT_SCALE,!0)},renderHighestPriority:function(){PDFView.idleTimeout&&(clearTimeout(PDFView.idleTimeout),
+PDFView.idleTimeout=null);var a=this.getVisiblePages();if(a=this.getHighestPriority(a,this.pages,this.pageViewScroll.down))this.renderView(a,"page");else{if(this.sidebarOpen&&(a=this.getVisibleThumbs(),a=this.getHighestPriority(a,this.thumbnails,this.thumbnailViewScroll.down))){this.renderView(a,"thumbnail");return}PDFView.idleTimeout=setTimeout(function(){PDFView.cleanup()},CLEANUP_TIMEOUT)}},cleanup:function(){for(var a=0,b=this.pages.length;a<b;a++)this.pages[a]&&this.pages[a].renderingState!==
+RenderingStates.FINISHED&&this.pages[a].reset();this.pdfDocument.cleanup()},getHighestPriority:function(a,b,c){var d=a.views,e=d.length;if(0===e)return!1;for(var g=0;g<e;++g){var h=d[g].view;if(!this.isViewFinished(h))return h}a=c?a.last.id:a.first.id-2;return b[a]&&!this.isViewFinished(b[a])?b[a]:!1},isViewFinished:function(a){return a.renderingState===RenderingStates.FINISHED},renderView:function(a,b){switch(a.renderingState){case RenderingStates.FINISHED:return!1;case RenderingStates.PAUSED:PDFView.highestPriorityPage=
+b+a.id;a.resume();break;case RenderingStates.RUNNING:PDFView.highestPriorityPage=b+a.id;break;case RenderingStates.INITIAL:PDFView.highestPriorityPage=b+a.id,a.draw(this.renderHighestPriority.bind(this))}return!0},setHash:function(a){if(a)if(0<=a.indexOf("="))if(a=PDFView.parseQueryString(a),"nameddest"in a)PDFHistory.updateNextHashParam(a.nameddest),PDFView.navigateTo(a.nameddest);else{var b,c;"page"in a&&(b=a.page|0||1);if("zoom"in a){c=a.zoom.split(",");var d=c[0],e=parseFloat(d);e&&(d=e/100);
+c=[null,{name:"XYZ"},1<c.length?c[1]|0:null,2<c.length?c[2]|0:null,d]}c?this.pages[(b||this.page)-1].scrollIntoView(c):b&&(this.page=b);"pagemode"in a&&(b=document.getElementById("sidebarToggle"),"thumbs"===a.pagemode||"bookmarks"===a.pagemode?(this.sidebarOpen||b.click(),this.switchSidebarView("thumbs"===a.pagemode?"thumbs":"outline")):"none"===a.pagemode&&this.sidebarOpen&&b.click())}else/^\d+$/.test(a)?this.page=a:(PDFHistory.updateNextHashParam(unescape(a)),PDFView.navigateTo(unescape(a)))},switchSidebarView:function(a){var b=
+document.getElementById("thumbnailView"),c=document.getElementById("outlineView"),d=document.getElementById("viewThumbnail"),e=document.getElementById("viewOutline");switch(a){case "thumbs":a=b.classList.contains("hidden");d.classList.add("toggled");e.classList.remove("toggled");b.classList.remove("hidden");c.classList.add("hidden");PDFView.renderHighestPriority();a&&scrollIntoView(document.getElementById("thumbnailContainer"+this.page));break;case "outline":d.classList.remove("toggled"),e.classList.add("toggled"),
+b.classList.add("hidden"),c.classList.remove("hidden"),e.getAttribute("disabled")}},getVisiblePages:function(){return this.getVisibleElements(this.container,this.pages,!PresentationMode.active)},getVisibleThumbs:function(){return this.getVisibleElements(this.thumbnailContainer,this.thumbnails)},getVisibleElements:function(a,b,c){var d=a.scrollTop,e=d+a.clientHeight,g=a.scrollLeft,h=g+a.clientWidth;a=[];for(var f,k,s,n,q,t=0,u=b.length;t<u;++t)if(f=b[t],k=f.el.offsetTop+f.el.clientTop,s=f.el.clientHeight,
+!(k+s<d)){if(k>e)break;q=f.el.offsetLeft+f.el.clientLeft;n=f.el.clientWidth;q+n<g||q>h||(n=Math.max(0,d-k)+Math.max(0,k+s-e),s=100*(s-n)/s|0,a.push({id:f.id,x:q,y:k,view:f,percent:s}))}b=a[0];d=a[a.length-1];c&&a.sort(function(a,b){var c=a.percent-b.percent;return 0.0010<Math.abs(c)?-c:a.id-b.id});return{first:b,last:d,views:a}},parseQueryString:function(a){a=a.split("&");for(var b={},c=0;c<a.length;++c){var d=a[c].split("="),e=1<d.length?d[1]:null;b[decodeURIComponent(d[0])]=decodeURIComponent(e)}return b},
+beforePrint:function(){if(this.supportsPrinting){var a=!1;if(this.pages.length)for(var b=0,c=this.pages.length;b<c;++b){if(!this.pages[b].pdfPage){a=!0;break}}else a=!0;if(a)a=mozL10n.get("printing_not_ready",null,"Warning: The PDF is not fully loaded for printing."),window.alert(a);else for(document.querySelector("body").setAttribute("data-mozPrintCallback",!0),b=0,c=this.pages.length;b<c;++b)this.pages[b].beforePrint()}else a=mozL10n.get("printing_not_supported",null,"Warning: Printing is not fully supported by this browser."),
+this.error(a)},afterPrint:function(){for(var a=document.getElementById("printContainer");a.hasChildNodes();)a.removeChild(a.lastChild)},rotatePages:function(a){var b=this.pages[this.page-1];this.pageRotation=(this.pageRotation+360+a)%360;a=0;for(var c=this.pages.length;a<c;a++){var d=this.pages[a];d.update(d.scale,this.pageRotation)}a=0;for(c=this.thumbnails.length;a<c;a++)this.thumbnails[a].update(this.pageRotation);this.setScale(this.currentScaleValue,!0,!0);this.renderHighestPriority();b&&b.scrollIntoView()},
+mouseScroll:function(a){var b=(new Date).getTime(),c=this.mouseScrollTimeStamp;b>c&&50>b-c||((0<this.mouseScrollDelta&&0>a||0>this.mouseScrollDelta&&0<a)&&this.clearMouseScrollState(),this.mouseScrollDelta+=a,120<=Math.abs(this.mouseScrollDelta)&&(a=0<this.mouseScrollDelta?-1:1,this.clearMouseScrollState(),c=this.page,1==c&&-1==a||c==this.pages.length&&1==a||(this.page+=a,this.mouseScrollTimeStamp=b)))},clearMouseScrollState:function(){this.mouseScrollDelta=this.mouseScrollTimeStamp=0}},PageView=
+function(a,b,c,d,e){function g(a,b,c){function d(a,b){a.href=PDFView.getDestinationHash(b);a.onclick=function(){b&&PDFView.navigateTo(b);return!1};b&&(a.className="internalLink")}function e(a,b){a.href=PDFView.getAnchorUrl("");a.onclick=function(){switch(b){case "GoToPage":document.getElementById("pageNumber").focus();break;case "GoBack":PDFHistory.back();break;case "GoForward":PDFHistory.forward();break;case "Find":PDFView.supportsIntegratedFind||PDFFindBar.toggle();break;case "NextPage":PDFView.page++;
+break;case "PrevPage":PDFView.page--;break;case "LastPage":PDFView.page=PDFView.pages.length;break;case "FirstPage":PDFView.page=1}return!1};a.className="internalLink"}b.getAnnotations().then(function(h){f.annotationLayer&&(a.removeChild(f.annotationLayer),f.annotationLayer=null);c=c.clone({dontFlip:!0});for(var g=0;g<h.length;g++){var l=h[g];if((l=PDFJS.Annotation.fromData(l))&&l.hasHtml()){var r=l.getHtmlElement(b.commonObjs);mozL10n.translate(r);var l=l.getData(),m=l.rect,v=b.view,m=PDFJS.Util.normalizeRect([m[0],
+v[3]-m[1]+v[1],m[2],v[3]-m[3]+v[1]]);r.style.left=m[0]+"px";r.style.top=m[1]+"px";r.style.position="absolute";v="matrix("+c.transform.join(",")+")";CustomStyle.setProp("transform",r,v);CustomStyle.setProp("transformOrigin",r,-m[0]+"px "+-m[1]+"px");"Link"!==l.subtype||l.url||(l.action?e(r,l.action):d(r,"dest"in l?l.dest:null));f.annotationLayer||(l=document.createElement("div"),l.className="annotationLayer",a.appendChild(l),f.annotationLayer=l);f.annotationLayer.appendChild(r)}}})}this.id=b;this.rotation=
+0;this.scale=c||1;this.viewport=e;this.pdfPageRotate=e.rotation;this.renderingState=RenderingStates.INITIAL;this.annotationLayer=this.zoomLayer=this.textLayer=this.resume=null;b=document.createElement("a");b.name=""+this.id;var h=this.el=document.createElement("div");h.id="pageContainer"+this.id;h.className="page";h.style.width=Math.floor(this.viewport.width)+"px";h.style.height=Math.floor(this.viewport.height)+"px";a.appendChild(b);a.appendChild(h);this.setPdfPage=function(a){this.pdfPage=a;this.pdfPageRotate=
+a.rotate;this.viewport=a.getViewport(this.scale*CSS_UNITS,(this.rotation+this.pdfPageRotate)%360);this.stats=a.stats;this.reset()};this.destroy=function(){this.zoomLayer=null;this.reset();this.pdfPage&&this.pdfPage.destroy()};this.reset=function(){this.renderTask&&this.renderTask.cancel();this.resume=null;this.renderingState=RenderingStates.INITIAL;h.style.width=Math.floor(this.viewport.width)+"px";h.style.height=Math.floor(this.viewport.height)+"px";for(var a=h.childNodes,b=h.childNodes.length-1;0<=
+b;b--){var c=a[b];this.zoomLayer&&this.zoomLayer===c||h.removeChild(c)}h.removeAttribute("data-loaded");this.annotationLayer=null;delete this.canvas;this.loadingIconDiv=document.createElement("div");this.loadingIconDiv.className="loadingIcon";h.appendChild(this.loadingIconDiv)};this.update=function(a,b){this.scale=a||this.scale;"undefined"!==typeof b&&(this.rotation=b);this.viewport=this.viewport.clone({scale:this.scale*CSS_UNITS,rotation:(this.rotation+this.pdfPageRotate)%360});USE_ONLY_CSS_ZOOM&&
+this.canvas?this.cssTransform(this.canvas):(this.canvas&&!this.zoomLayer&&(this.zoomLayer=this.canvas.parentNode,this.zoomLayer.style.position="absolute"),this.zoomLayer&&this.cssTransform(this.zoomLayer.firstChild),this.reset())};this.cssTransform=function(a){var b=this.viewport.width,c=this.viewport.height;a.style.width=a.parentNode.style.width=h.style.width=Math.floor(b)+"px";a.style.height=a.parentNode.style.height=h.style.height=Math.floor(c)+"px";var d=this.viewport.rotation-a._viewport.rotation,
+e=Math.abs(d),f=1,p=1;if(90===e||270===e)f=c/b,p=b/c;CustomStyle.setProp("transform",a,"rotate("+d+"deg) scale("+f+","+p+")");if(this.textLayer){c=Math.abs(this.viewport.rotation-this.textLayer.viewport.rotation);d=b/a.width;if(90===c||270===c)d=b/a.height;a=this.textLayer.textLayerDiv;var l,r;switch(c){case 0:l=r=0;break;case 90:l=0;r="-"+a.style.height;break;case 180:l="-"+a.style.width;r="-"+a.style.height;break;case 270:l="-"+a.style.width;r=0;break;default:console.error("Bad rotation value.")}CustomStyle.setProp("transform",
+a,"rotate("+c+"deg) scale("+d+", "+d+") translate("+l+", "+r+")");CustomStyle.setProp("transformOrigin",a,"0% 0%")}USE_ONLY_CSS_ZOOM&&this.annotationLayer&&g(h,this.pdfPage,this.viewport)};Object.defineProperty(this,"width",{get:function(){return this.viewport.width},enumerable:!0});Object.defineProperty(this,"height",{get:function(){return this.viewport.height},enumerable:!0});var f=this;this.getPagePoint=function(a,b){return this.viewport.convertToPdfPoint(a,b)};this.scrollIntoView=function(a){PresentationMode.active&&
+(a=null,PDFView.setScale(PDFView.currentScaleValue,!0,!0));if(a){var b=0,c=0,d=0,e=0,g,f;f=!!(this.rotation%180);g=(f?this.height:this.width)/this.scale/CSS_UNITS;f=(f?this.width:this.height)/this.scale/CSS_UNITS;var l=0;switch(a[1].name){case "XYZ":b=a[2];c=a[3];l=a[4];b=null!==b?b:0;c=null!==c?c:f;break;case "Fit":case "FitB":l="page-fit";break;case "FitH":case "FitBH":c=a[2];l="page-width";break;case "FitV":case "FitBV":b=a[2];d=g;e=f;l="page-height";break;case "FitR":b=a[2];c=a[3];d=a[4]-b;e=
+a[5]-c;g=(PDFView.container.clientWidth-SCROLLBAR_PADDING)/d/CSS_UNITS;f=(PDFView.container.clientHeight-SCROLLBAR_PADDING)/e/CSS_UNITS;l=Math.min(Math.abs(g),Math.abs(f));break;default:return}l&&l!==PDFView.currentScale?PDFView.setScale(l,!0,!0):PDFView.currentScale===UNKNOWN_SCALE&&PDFView.setScale(DEFAULT_SCALE,!0,!0);"page-fit"!==l||a[4]?(b=[this.viewport.convertToViewportPoint(b,c),this.viewport.convertToViewportPoint(b+d,c+e)],a=Math.min(b[0][0],b[1][0]),b=Math.min(b[0][1],b[1][1]),scrollIntoView(h,
+{left:a,top:b})):scrollIntoView(h)}else scrollIntoView(h)};this.getTextContent=function(){return PDFView.getPage(this.id).then(function(a){return a.getTextContent()})};this.draw=function(a){function b(d){v===m.renderTask&&(m.renderTask=null);if("cancelled"!==d){m.renderingState=RenderingStates.FINISHED;m.loadingIconDiv&&(h.removeChild(m.loadingIconDiv),delete m.loadingIconDiv);m.zoomLayer&&(h.removeChild(m.zoomLayer),m.zoomLayer=null);d&&PDFView.error(mozL10n.get("rendering_error",null,"An error occurred while rendering the page."),
+d);m.stats=c.stats;m.updateStats();if(m.onAfterDraw)m.onAfterDraw();cache.push(m);d=document.createEvent("CustomEvent");d.initCustomEvent("pagerender",!0,!0,{pageNumber:c.pageNumber});h.dispatchEvent(d);a()}}var c=this.pdfPage;if(!this.pagePdfPromise)if(c){this.renderingState!==RenderingStates.INITIAL&&console.error("Must be in new state before drawing");this.renderingState=RenderingStates.RUNNING;var d=this.viewport,e=document.createElement("div");e.style.width=h.style.width;e.style.height=h.style.height;
+e.classList.add("canvasWrapper");var f=document.createElement("canvas");f.id="page"+this.id;e.appendChild(f);h.appendChild(e);this.canvas=f;var e=f.getContext("2d"),p=getOutputScale(e);if(USE_ONLY_CSS_ZOOM){var l=d.clone({scale:CSS_UNITS});p.sx*=l.width/d.width;p.sy*=l.height/d.height;p.scaled=!0}f.width=Math.floor(d.width)*p.sx|0;f.height=Math.floor(d.height)*p.sy|0;f.style.width=Math.floor(d.width)+"px";f.style.height=Math.floor(d.height)+"px";f._viewport=d;d=null;PDFJS.disableTextLayer||(d=document.createElement("div"),
+d.className="textLayer",d.style.width=f.width+"px",d.style.height=f.height+"px",h.appendChild(d));var r=this.textLayer=d?new TextLayerBuilder({textLayerDiv:d,pageIndex:this.id-1,lastScrollSource:PDFView,viewport:this.viewport,isViewerInPresentationMode:PresentationMode.active}):null;e._scaleX=p.sx;e._scaleY=p.sy;p.scaled&&e.scale(p.sx,p.sy);p.scaled&&d&&(CustomStyle.setProp("transform",d,"scale("+1/p.sx+", "+1/p.sy+")"),CustomStyle.setProp("transformOrigin",d,"0% 0%"),d.dataset._scaleX=p.sx,d.dataset._scaleY=
+p.sy);var m=this,v=this.renderTask=this.pdfPage.render({canvasContext:e,viewport:this.viewport,textLayer:r,continueCallback:function(a){PDFView.highestPriorityPage!=="page"+m.id?(m.renderingState=RenderingStates.PAUSED,m.resume=function(){m.renderingState=RenderingStates.RUNNING;a()}):a()}});this.renderTask.promise.then(function(){b(null)},function(a){b(a)});r&&this.getTextContent().then(function(a){r.setTextContent(a)});g(h,c,this.viewport);h.setAttribute("data-loaded",!0)}else f=PDFView.getPage(this.id),
+f.then(function(b){delete this.pagePdfPromise;this.setPdfPage(b);this.draw(a)}.bind(this)),this.pagePdfPromise=f};this.beforePrint=function(){var a=this.pdfPage,b=a.getViewport(1),c=document.createElement("canvas");c.width=2*Math.floor(b.width);c.height=2*Math.floor(b.height);c.style.width=2*b.width+"pt";c.style.height=2*b.height+"pt";CustomStyle.setProp("transform",c,"scale(0.5, 0.5)");CustomStyle.setProp("transformOrigin",c,"0% 0%");var d=document.getElementById("printContainer"),e=document.createElement("div");
+e.style.width=b.width+"pt";e.style.height=b.height+"pt";e.appendChild(c);d.appendChild(e);var h=this;c.mozPrintCallback=function(d){var e=d.context;e.save();e.fillStyle="rgb(255, 255, 255)";e.fillRect(0,0,c.width,c.height);e.restore();e.scale(2,2);a.render({canvasContext:e,viewport:b}).promise.then(function(){d.done();h.pdfPage.destroy()},function(a){console.error(a);"abort"in d?d.abort():d.done();h.pdfPage.destroy()})}};this.updateStats=function(){this.stats&&PDFJS.pdfBug&&Stats.enabled&&Stats.add(this.id,
+this.stats)}},ThumbnailView=function(a,b,c){var d=document.createElement("a");d.href=PDFView.getAnchorUrl("#page="+b);d.title=mozL10n.get("thumb_page_title",{page:b},"Page {{page}}");d.onclick=function(){PDFView.page=b;return!1};this.pdfPage=void 0;this.viewport=c;this.pdfPageRotate=c.rotation;this.rotation=0;this.pageWidth=this.viewport.width;this.pageHeight=this.viewport.height;this.pageRatio=this.pageWidth/this.pageHeight;this.id=b;this.canvasWidth=98;this.canvasHeight=this.canvasWidth/this.pageWidth*
+this.pageHeight;this.scale=this.canvasWidth/this.pageWidth;var e=this.el=document.createElement("div");e.id="thumbnailContainer"+b;e.className="thumbnail";1===b&&e.classList.add("selected");var g=document.createElement("div");g.className="thumbnailSelectionRing";g.style.width=this.canvasWidth+"px";g.style.height=this.canvasHeight+"px";e.appendChild(g);d.appendChild(e);a.appendChild(d);this.hasImage=!1;this.renderingState=RenderingStates.INITIAL;this.setPdfPage=function(a){this.pdfPage=a;this.pdfPageRotate=
+a.rotate;this.viewport=a.getViewport(1,(this.rotation+this.pdfPageRotate)%360);this.update()};this.update=function(a){void 0!==a&&(this.rotation=a);this.viewport=this.viewport.clone({scale:1,rotation:(this.rotation+this.pdfPageRotate)%360});this.pageWidth=this.viewport.width;this.pageHeight=this.viewport.height;this.pageRatio=this.pageWidth/this.pageHeight;this.canvasHeight=this.canvasWidth/this.pageWidth*this.pageHeight;this.scale=this.canvasWidth/this.pageWidth;e.removeAttribute("data-loaded");
+g.textContent="";g.style.width=this.canvasWidth+"px";g.style.height=this.canvasHeight+"px";this.hasImage=!1;this.renderingState=RenderingStates.INITIAL;this.resume=null};this.getPageDrawContext=function(){var a=document.createElement("canvas");a.id="thumbnail"+b;a.width=this.canvasWidth;a.height=this.canvasHeight;a.className="thumbnailImage";a.setAttribute("aria-label",mozL10n.get("thumb_page_canvas",{page:b},"Thumbnail of Page {{page}}"));e.setAttribute("data-loaded",!0);g.appendChild(a);a=a.getContext("2d");
+a.save();a.fillStyle="rgb(255, 255, 255)";a.fillRect(0,0,this.canvasWidth,this.canvasHeight);a.restore();return a};this.drawingRequired=function(){return!this.hasImage};this.draw=function(a){if(this.pdfPage)if(this.renderingState!==RenderingStates.INITIAL&&console.error("Must be in new state before drawing"),this.renderingState=RenderingStates.RUNNING,this.hasImage)a();else{var b=this,c=this.getPageDrawContext(),d=this.viewport.clone({scale:this.scale});this.pdfPage.render({canvasContext:c,viewport:d,
+continueCallback:function(a){PDFView.highestPriorityPage!=="thumbnail"+b.id?(b.renderingState=RenderingStates.PAUSED,b.resume=function(){b.renderingState=RenderingStates.RUNNING;a()}):a()}}).promise.then(function(){b.renderingState=RenderingStates.FINISHED;a()},function(c){b.renderingState=RenderingStates.FINISHED;a()});this.hasImage=!0}else PDFView.getPage(this.id).then(function(b){this.setPdfPage(b);this.draw(a)}.bind(this))};this.setImage=function(a){if(!this.pdfPage)PDFView.getPage(this.id).then(function(b){this.setPdfPage(b);
+this.setImage(a)}.bind(this));else if(!this.hasImage&&a){this.renderingState=RenderingStates.FINISHED;var b=this.getPageDrawContext();b.drawImage(a,0,0,a.width,a.height,0,0,b.canvas.width,b.canvas.height);this.hasImage=!0}}},FIND_SCROLL_OFFSET_TOP=-50,FIND_SCROLL_OFFSET_LEFT=-400,TextLayerBuilder=function(a){var b=document.createDocumentFragment();this.textLayerDiv=a.textLayerDiv;this.divContentDone=this.layoutDone=!1;this.pageIdx=a.pageIndex;this.matches=[];this.lastScrollSource=a.lastScrollSource;
+this.viewport=a.viewport;this.isViewerInPresentationMode=a.isViewerInPresentationMode;"undefined"===typeof PDFFindController&&(window.PDFFindController=null);"undefined"===typeof this.lastScrollSource&&(this.lastScrollSource=null);this.beginLayout=function(){this.textDivs=[];this.renderingDone=!1};this.endLayout=function(){this.layoutDone=!0;this.insertDivContent()};this.renderLayer=function(){var a=this.textDivs,d=this.textLayerDiv,e=document.createElement("canvas").getContext("2d");if(!(1E5<a.length)){for(var g=
+0,h=a.length;g<h;g++){var f=a[g];if(!("isWhitespace"in f.dataset)){e.font=f.style.fontSize+" "+f.style.fontFamily;var k=e.measureText(f.textContent).width;0<k&&(b.appendChild(f),k="scale("+f.dataset.canvasWidth/k+", 1)",k="rotate("+f.dataset.angle+"deg) "+k,CustomStyle.setProp("transform",f,k),CustomStyle.setProp("transformOrigin",f,"0% 0%"))}}d.appendChild(b);this.renderingDone=!0;this.updateMatches()}};this.setupRenderLayoutTimer=function(){var a=this,b=null===this.lastScrollSource?0:this.lastScrollSource.lastScroll;
+200<Date.now()-b?this.renderLayer():(this.renderTimer&&clearTimeout(this.renderTimer),this.renderTimer=setTimeout(function(){a.setupRenderLayoutTimer()},200))};this.appendText=function(a){var b=document.createElement("div"),e=a.fontSize*Math.abs(a.vScale);b.dataset.canvasWidth=a.canvasWidth*Math.abs(a.hScale);b.dataset.fontName=a.fontName;b.dataset.angle=180/Math.PI*a.angle;b.style.fontSize=e+"px";b.style.fontFamily=a.fontFamily;e=a.ascent?a.ascent*e:a.descent?(1+a.descent)*e:e;b.style.left=a.x+e*
+Math.sin(a.angle)+"px";b.style.top=a.y-e*Math.cos(a.angle)+"px";this.textDivs.push(b)};this.insertDivContent=function(){if(this.layoutDone&&!this.divContentDone&&this.textContent){this.divContentDone=!0;for(var a=this.textDivs,b=this.textContent.bidiTexts,e=0;e<b.length;e++){var g=b[e],h=a[e];/\S/.test(g.str)?(h.textContent=g.str,h.dir=g.dir):h.dataset.isWhitespace=!0}this.setupRenderLayoutTimer()}};this.setTextContent=function(a){this.textContent=a;this.insertDivContent()};this.convertMatches=function(a){for(var b=
+0,e=0,g=this.textContent.bidiTexts,h=g.length-1,f=null===PDFFindController?0:PDFFindController.state.query.length,k=[],s=0;s<a.length;s++){for(var n=a[s];b!==h&&n>=e+g[b].str.length;)e+=g[b].str.length,b++;b==g.length&&console.error("Could not find matching mapping");for(var q={begin:{divIdx:b,offset:n-e}},n=n+f;b!==h&&n>e+g[b].str.length;)e+=g[b].str.length,b++;q.end={divIdx:b,offset:n-e};k.push(q)}return k};this.renderMatches=function(a){function b(a,c){var d=a.divIdx,e=h[d];e.textContent="";var f=
+g[d].str.substring(0,a.offset),f=document.createTextNode(f);if(c){var d=k&&d===s,l=document.createElement("span");l.className=c+(d?" selected":"");l.appendChild(f);e.appendChild(l)}else e.appendChild(f)}function e(a,b,c){var d=a.divIdx,e=h[d];a=g[d].str.substring(a.offset,b.offset);a=document.createTextNode(a);c?(b=document.createElement("span"),b.className=c,b.appendChild(a),e.appendChild(b)):e.appendChild(a)}if(0!==a.length){var g=this.textContent.bidiTexts,h=this.textDivs,f=null,k=null===PDFFindController?
+!1:this.pageIdx===PDFFindController.selected.pageIdx,s=null===PDFFindController?-1:PDFFindController.selected.matchIdx,n={divIdx:-1,offset:void 0},q=s,t=q+1;if(null===PDFFindController?0:PDFFindController.state.highlightAll)q=0,t=a.length;else if(!k)return;for(;q<t;q++){var u=a[q],p=u.begin,u=u.end,l=k&&q===s,r=l?" selected":"";l&&!this.isViewerInPresentationMode&&scrollIntoView(h[p.divIdx],{top:FIND_SCROLL_OFFSET_TOP,left:FIND_SCROLL_OFFSET_LEFT});f&&p.divIdx===f.divIdx?e(f,p):(null!==f&&e(f,n),
+b(p));if(p.divIdx===u.divIdx)e(p,u,"highlight"+r);else{e(p,n,"highlight begin"+r);for(f=p.divIdx+1;f<u.divIdx;f++)h[f].className="highlight middle"+r;b(u,"highlight end"+r)}f=u}f&&e(f,n)}};this.updateMatches=function(){if(this.renderingDone){for(var a=this.matches,b=this.textDivs,e=this.textContent.bidiTexts,g=-1,h=0;h<a.length;h++){for(var f=a[h],g=Math.max(g,f.begin.divIdx);g<=f.end.divIdx;g++){var k=b[g];k.textContent=e[g].str;k.className=""}g=f.end.divIdx+1}null!==PDFFindController&&PDFFindController.active&&
+(this.matches=this.convertMatches(null===PDFFindController?[]:PDFFindController.pageMatches[this.pageIdx]||[]),this.renderMatches(this.matches))}}},DocumentOutlineView=function(a){function b(a,b){a.href=PDFView.getDestinationHash(b.dest);a.onclick=function(a){PDFView.navigateTo(b.dest);return!1}}var c=document.getElementById("outlineView");for(document.getElementById("viewOutline");c.firstChild;)c.removeChild(c.firstChild);if(a)for(a=[{parent:c,items:a}];0<a.length;){var c=a.shift(),d,e=c.items.length;
+for(d=0;d<e;d++){var g=c.items[d],h=document.createElement("div");h.className="outlineItem";var f=document.createElement("a");b(f,g);f.textContent=g.title;h.appendChild(f);0<g.items.length&&(f=document.createElement("div"),f.className="outlineItems",h.appendChild(f),a.push({parent:f,items:g.items}));c.parent.appendChild(h)}}else c.classList.contains("hidden")||PDFView.switchSidebarView("thumbs")};
+document.addEventListener("DOMContentLoaded",function(a){PDFView.initialize();a=PDFView.parseQueryString(document.location.search.substring(1)).file||DEFAULT_URL;var b=document.createElement("input");b.id="fileInput";b.className="fileInput";b.setAttribute("type","file");b.oncontextmenu=noContextMenuHandler;document.body.appendChild(b);window.File&&window.FileReader&&window.FileList&&window.Blob&&(document.getElementById("fileInput").value=null);b=document.location.hash.substring(1);b=PDFView.parseQueryString(b);
+"disableWorker"in b&&(PDFJS.disableWorker="true"===b.disableWorker);"disableRange"in b&&(PDFJS.disableRange="true"===b.disableRange);"disableAutoFetch"in b&&(PDFJS.disableAutoFetch="true"===b.disableAutoFetch);"disableFontFace"in b&&(PDFJS.disableFontFace="true"===b.disableFontFace);"disableHistory"in b&&(PDFJS.disableHistory="true"===b.disableHistory);"useOnlyCssZoom"in b&&(USE_ONLY_CSS_ZOOM="true"===b.useOnlyCssZoom);"verbosity"in b&&(PDFJS.verbosity=b.verbosity|0);"ignoreCurrentPositionOnZoom"in
+b&&(IGNORE_CURRENT_POSITION_ON_ZOOM="true"===b.ignoreCurrentPositionOnZoom);var c=navigator.language;"locale"in b&&(c=b.locale);mozL10n.setLanguage(c);if("textLayer"in b)switch(b.textLayer){case "off":PDFJS.disableTextLayer=!0;break;case "visible":case "shadow":case "hover":document.getElementById("viewer").classList.add("textLayer-"+b.textLayer)}"pdfBug"in b&&(PDFJS.pdfBug=!0,b=b.pdfBug.split(","),PDFBug.enable(b),PDFBug.init());PDFView.supportsPrinting||(document.getElementById("print").classList.add("hidden"),
+document.getElementById("secondaryPrint").classList.add("hidden"));PDFView.supportsFullscreen||(document.getElementById("presentationMode").classList.add("hidden"),document.getElementById("secondaryPresentationMode").classList.add("hidden"));PDFView.supportsIntegratedFind&&document.getElementById("viewFind").classList.add("hidden");PDFJS.UnsupportedManager.listen(PDFView.fallback.bind(PDFView));document.getElementById("scaleSelect").oncontextmenu=noContextMenuHandler;var d=document.getElementById("mainContainer"),
+e=document.getElementById("outerContainer");d.addEventListener("transitionend",function(a){a.target==d&&(a=document.createEvent("UIEvents"),a.initUIEvent("resize",!1,!1,window,0),window.dispatchEvent(a),e.classList.remove("sidebarMoving"))},!0);document.getElementById("sidebarToggle").addEventListener("click",function(){this.classList.toggle("toggled");e.classList.add("sidebarMoving");e.classList.toggle("sidebarOpen");PDFView.sidebarOpen=e.classList.contains("sidebarOpen");PDFView.renderHighestPriority()});
+document.getElementById("viewThumbnail").addEventListener("click",function(){PDFView.switchSidebarView("thumbs")});document.getElementById("viewOutline").addEventListener("click",function(){PDFView.switchSidebarView("outline")});document.getElementById("previous").addEventListener("click",function(){PDFView.page--});document.getElementById("next").addEventListener("click",function(){PDFView.page++});document.getElementById("zoomIn").addEventListener("click",function(){PDFView.zoomIn()});document.getElementById("zoomOut").addEventListener("click",
+function(){PDFView.zoomOut()});document.getElementById("pageNumber").addEventListener("click",function(){this.select()});document.getElementById("pageNumber").addEventListener("change",function(){PDFView.page=this.value|0;this.value!==(this.value|0).toString()&&(this.value=PDFView.page)});document.getElementById("scaleSelect").addEventListener("change",function(){PDFView.setScale(this.value)});document.getElementById("presentationMode").addEventListener("click",SecondaryToolbar.presentationModeClick.bind(SecondaryToolbar));
+document.getElementById("print").addEventListener("click",SecondaryToolbar.printClick.bind(SecondaryToolbar));PDFView.open(a,0)},!0);
+function updateViewarea(){if(PDFView.initialized){var a=PDFView.getVisiblePages(),b=a.views;if(0!==b.length){PDFView.renderHighestPriority();for(var c=PDFView.page,a=a.first,d=0,e=b.length,g=!1;d<e;++d){var h=b[d];if(100>h.percent)break;if(h.id===PDFView.page){g=!0;break}}g||(c=b[0].id);updateViewarea.inProgress=!0;PDFView.page=c;updateViewarea.inProgress=!1;var b=PDFView.currentScale,c=PDFView.currentScaleValue,f=parseFloat(c)===b?Math.round(1E4*b)/100:c,k=a.id,b="#page="+k+("&zoom="+f),c=PDFView.container,
+a=PDFView.pages[k-1].getPagePoint(c.scrollLeft-a.x,c.scrollTop-a.y),s=Math.round(a[0]),n=Math.round(a[1]),b=b+(","+s+","+n);PDFView.currentPosition=PresentationMode.active||PresentationMode.switchInProgress?null:{page:k,left:s,top:n};var q=PDFView.store;q.initializedPromise.then(function(){q.set("exists",!0);q.set("page",k);q.set("zoom",f);q.set("scrollLeft",s);q.set("scrollTop",n)});a=PDFView.getAnchorUrl(b);document.getElementById("viewBookmark").href=a;document.getElementById("secondaryViewBookmark").href=
+a;PDFHistory.updateCurrentBookmark(b,k)}}}window.addEventListener("resize",function(a){PDFView.initialized&&(document.getElementById("pageWidthOption").selected||document.getElementById("pageFitOption").selected||document.getElementById("pageAutoOption").selected)&&PDFView.setScale(document.getElementById("scaleSelect").value);updateViewarea();SecondaryToolbar.setMaxHeight(PDFView.container)});window.addEventListener("hashchange",function(a){PDFHistory.isHashChangeUnlocked&&PDFView.setHash(document.location.hash.substring(1))});
+window.addEventListener("change",function(a){var b=a.target.files;b&&0!==b.length&&(a=new FileReader,a.onload=function(a){a=new Uint8Array(a.target.result);PDFView.open(a,0)},b=b[0],a.readAsArrayBuffer(b),PDFView.setTitleUsingUrl(b.name),document.getElementById("viewBookmark").setAttribute("hidden","true"),document.getElementById("secondaryViewBookmark").setAttribute("hidden","true"),document.getElementById("download").setAttribute("hidden","true"),document.getElementById("secondaryDownload").setAttribute("hidden",
+"true"))},!0);function selectScaleOption(a){for(var b=document.getElementById("scaleSelect").options,c=!1,d=0;d<b.length;d++){var e=b[d];e.value!=a?e.selected=!1:c=e.selected=!0}return c}
+window.addEventListener("localized",function(a){document.getElementsByTagName("html")[0].dir=mozL10n.getDirection();PDFView.animationStartedPromise.then(function(){var a=document.getElementById("scaleSelectContainer");if(0<a.clientWidth){var c=document.getElementById("scaleSelect");c.setAttribute("style","min-width: inherit;");var d=c.clientWidth+SCALE_SELECT_CONTAINER_PADDING;c.setAttribute("style","min-width: "+(d+SCALE_SELECT_PADDING)+"px;");a.setAttribute("style","min-width: "+d+"px; max-width: "+
+d+"px;")}SecondaryToolbar.setMaxHeight(PDFView.container)})},!0);
+window.addEventListener("scalechange",function(a){document.getElementById("zoomOut").disabled=a.scale===MIN_SCALE;document.getElementById("zoomIn").disabled=a.scale===MAX_SCALE;var b=document.getElementById("customScaleOption");b.selected=!1;!a.resetAutoSettings&&(document.getElementById("pageWidthOption").selected||document.getElementById("pageFitOption").selected||document.getElementById("pageAutoOption").selected)||selectScaleOption(""+a.scale)||(b.textContent=Math.round(1E4*a.scale)/100+"%",b.selected=
+!0);updateViewarea()},!0);
+window.addEventListener("pagechange",function(a){a=a.pageNumber;if(PDFView.previousPageNumber!==a){document.getElementById("pageNumber").value=a;var b=document.querySelector(".thumbnail.selected");b&&b.classList.remove("selected");b=document.getElementById("thumbnailContainer"+a);b.classList.add("selected");var c=PDFView.getVisibleThumbs(),d=c.views.length;if(0<d){var e=c.first.id,c=1<d?c.last.id:e;(a<=e||a>=c)&&scrollIntoView(b,{top:THUMBNAIL_SCROLL_MARGIN})}}document.getElementById("previous").disabled=1>=
+a;document.getElementById("next").disabled=a>=PDFView.pages.length},!0);window.addEventListener("DOMMouseScroll",function(a){a.ctrlKey?(a.preventDefault(),a=a.detail,PDFView[0<a?"zoomOut":"zoomIn"](Math.abs(a))):PresentationMode.active&&PDFView.mouseScroll(-40*a.detail)},!1);window.addEventListener("click",function(a){PresentationMode.active?0===a.button&&a.preventDefault():SecondaryToolbar.opened&&PDFView.container.contains(a.target)&&SecondaryToolbar.close()},!1);
+window.addEventListener("keydown",function(a){if(!PasswordPrompt.visible){var b=!1,c=(a.ctrlKey?1:0)|(a.altKey?2:0)|(a.shiftKey?4:0)|(a.metaKey?8:0);if(1===c||8===c||5===c||12===c)switch(a.keyCode){case 70:PDFView.supportsIntegratedFind||(PDFFindBar.open(),b=!0);break;case 71:PDFView.supportsIntegratedFind||(PDFFindBar.dispatchEvent("again",5===c||12===c),b=!0);break;case 61:case 107:case 187:case 171:PDFView.zoomIn();b=!0;break;case 173:case 109:case 189:PDFView.zoomOut();b=!0;break;case 48:case 96:setTimeout(function(){PDFView.setScale(DEFAULT_SCALE,
+!0)}),b=!1}if(3===c||10===c)switch(a.keyCode){case 80:SecondaryToolbar.presentationModeClick();b=!0;break;case 71:document.getElementById("pageNumber").select(),b=!0}if(b)a.preventDefault();else{var d=document.activeElement||document.querySelector(":focus");if(!d||"INPUT"!==d.tagName.toUpperCase()&&"TEXTAREA"!==d.tagName.toUpperCase()&&"SELECT"!==d.tagName.toUpperCase()||27===a.keyCode){for(var e=document.getElementById("toolbar");d;){if(d===e&&!PresentationMode.active)return;d=d.parentNode}if(0===
+c)switch(a.keyCode){case 38:case 33:case 8:if(!PresentationMode.active&&"page-fit"!==PDFView.currentScaleValue)break;case 37:if(PDFView.isHorizontalScrollbarEnabled)break;case 75:case 80:PDFView.page--;b=!0;break;case 27:SecondaryToolbar.opened&&(SecondaryToolbar.close(),b=!0);!PDFView.supportsIntegratedFind&&PDFFindBar.opened&&(PDFFindBar.close(),b=!0);break;case 40:case 34:case 32:if(!PresentationMode.active&&"page-fit"!==PDFView.currentScaleValue)break;case 39:if(PDFView.isHorizontalScrollbarEnabled)break;
+case 74:case 78:PDFView.page++;b=!0;break;case 36:PresentationMode.active&&(PDFView.page=1,b=!0);break;case 35:PresentationMode.active&&(PDFView.page=PDFView.pdfDocument.numPages,b=!0);break;case 72:PresentationMode.active||HandTool.toggle();break;case 82:PDFView.rotatePages(90)}if(4===c)switch(a.keyCode){case 32:if(!PresentationMode.active&&"page-fit"!==PDFView.currentScaleValue)break;PDFView.page--;b=!0;break;case 82:PDFView.rotatePages(-90)}if(2===c)switch(a.keyCode){case 37:PresentationMode.active&&
+(PDFHistory.back(),b=!0);break;case 39:PresentationMode.active&&(PDFHistory.forward(),b=!0)}b&&(a.preventDefault(),PDFView.clearMouseScrollState())}}}});window.addEventListener("beforeprint",function(a){PDFView.beforePrint()});window.addEventListener("afterprint",function(a){PDFView.afterPrint()});
+(function(){var a=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){a()};PDFView.animationStartedPromise=new Promise(function(b){a(function(){b()})})})();




More information about the commits mailing list