From 737ed8417472b9c5084f963de95e3f87779dd7b2 Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Mon, 9 Apr 2012 22:20:57 -0700
Subject: [PATCH 01/29] Initial API implementation

---
 src/api.js      | 141 +++++++++++++++++++++++++++++++
 src/util.js     |  17 +++-
 web/viewer.html |   1 +
 web/viewer.js   | 220 +++++++++++++++++++++++++++---------------------
 4 files changed, 281 insertions(+), 98 deletions(-)
 create mode 100644 src/api.js

diff --git a/src/api.js b/src/api.js
new file mode 100644
index 000000000..a8bb5fb65
--- /dev/null
+++ b/src/api.js
@@ -0,0 +1,141 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+(function pdfApiWrapper() {
+  function PdfPageWrapper(page) {
+    this.page = page;
+  }
+  PdfPageWrapper.prototype = {
+    get width() {
+      return this.page.width;
+    },
+    get height() {
+      return this.page.height;
+    },
+    get stats() {
+      return this.page.stats;
+    },
+    get ref() {
+      return this.page.ref;
+    },
+    get view() {
+      return this.page.view;
+    },
+    rotatePoint: function(x, y) {
+      return this.page.rotatePoint(x, y);
+    },
+    getAnnotations: function() {
+      var promise = new PDFJS.Promise();
+      var annotations = this.page.getAnnotations();
+      promise.resolve(annotations);
+      return promise;
+    },
+    render: function(renderContext) {
+      var promise = new PDFJS.Promise();
+      this.page.startRendering(renderContext.canvasContext,
+        function complete(error) {
+          if (error)
+            promise.reject(error);
+          else
+            promise.resolve();
+        },
+        renderContext.textLayer);
+      return promise;
+    },
+    getTextContent: function() {
+      var promise = new PDFJS.Promise();
+      var textContent = 'page text'; // not implemented
+      promise.resolve(textContent);
+      return promise;
+    },
+    getOperationList: function() {
+      var promise = new PDFJS.Promise();
+      var operationList = { // not implemented
+        dependencyFontsID: null,
+        operatorList: null
+      };
+      promise.resolve(operationList);
+      return promise;
+    }
+  };
+
+  function PdfDocumentWrapper(pdf) {
+    this.pdf = pdf;
+  }
+  PdfDocumentWrapper.prototype = {
+    get numPages() {
+      return this.pdf.numPages;
+    },
+    get fingerprint() {
+      return this.pdf.fingerPrint;
+    },
+    getPage: function(number) {
+      var promise = new PDFJS.Promise();
+      var page = this.pdf.getPage(number);
+      promise.resolve(new PdfPageWrapper(page));
+      return promise;
+    },
+    getDestinations: function() {
+      var promise = new PDFJS.Promise();
+      var destinations = this.pdf.catalog.destinations;
+      promise.resolve(destinations);
+      return promise;
+    },
+    getOutline: function() {
+      var promise = new PDFJS.Promise();
+      var outline = this.pdf.catalog.documentOutline;
+      promise.resolve(outline);
+      return promise;
+    },
+    getMetadata: function() {
+      var promise = new PDFJS.Promise();
+      var info = this.pdf.info;
+      var metadata = this.pdf.catalog.metadata;
+      promise.resolve(info, metadata ? new PDFJS.Metadata(metadata) : null);
+      return promise;
+    }
+  };
+
+  PDFJS.getDocument = function getDocument(source) {
+    var promise = new PDFJS.Promise();
+    if (typeof source === 'string') {
+      // fetch url
+      PDFJS.getPdf(
+        {
+          url: source,
+          progress: function getPdfProgress(evt) {
+            if (evt.lengthComputable)
+              promise.progress({
+                loaded: evt.loaded,
+                total: evt.total
+              });
+          },
+          error: function getPdfError(e) {
+            promise.reject('Unexpected server response of ' +
+              e.target.status + '.');
+          }
+        },
+        function getPdfLoad(data) {
+          var pdf = null;
+          try {
+            pdf = new PDFJS.PDFDoc(data);
+          } catch (e) {
+            promise.reject('An error occurred while reading the PDF.', e);
+          }
+          if (pdf)
+            promise.resolve(new PdfDocumentWrapper(pdf));
+        });
+    } else {
+      // assuming the source is array, instantiating directly from it
+      var pdf = null;
+      try {
+        pdf = new PDFJS.PDFDoc(source);
+      } catch (e) {
+        promise.reject('An error occurred while reading the PDF.', e);
+      }
+      if (pdf)
+        promise.resolve(new PdfDocumentWrapper(pdf));
+    }
+    return promise;
+  };
+})();
diff --git a/src/util.js b/src/util.js
index de7f3c1d5..30fc799f9 100644
--- a/src/util.js
+++ b/src/util.js
@@ -275,7 +275,7 @@ function isPDFFunction(v) {
  * can be set. If any of these happens twice or the data is required before
  * it was set, an exception is throw.
  */
-var Promise = (function PromiseClosure() {
+var Promise = PDFJS.Promise = (function PromiseClosure() {
   var EMPTY_PROMISE = {};
 
   /**
@@ -297,6 +297,7 @@ var Promise = (function PromiseClosure() {
     }
     this.callbacks = [];
     this.errbacks = [];
+    this.progressbacks = [];
   };
   /**
    * Builds a promise that is resolved when all the passed in promises are
@@ -312,7 +313,7 @@ var Promise = (function PromiseClosure() {
       deferred.resolve(results);
       return deferred;
     }
-    for (var i = 0; i < unresolved; ++i) {
+    for (var i = 0, ii = promises.length; i < ii; ++i) {
       var promise = promises[i];
       promise.then((function(i) {
         return function(value) {
@@ -376,6 +377,13 @@ var Promise = (function PromiseClosure() {
       }
     },
 
+    progress: function Promise_progress(data) {
+      var callbacks = this.progressbacks;
+      for (var i = 0, ii = callbacks.length; i < ii; i++) {
+        callbacks[i].call(null, data);
+      }
+    },
+
     reject: function Promise_reject(reason) {
       if (this.isRejected) {
         error('A Promise can be rejected only once ' + this.name);
@@ -393,7 +401,7 @@ var Promise = (function PromiseClosure() {
       }
     },
 
-    then: function Promise_then(callback, errback) {
+    then: function Promise_then(callback, errback, progressback) {
       if (!callback) {
         error('Requiring callback' + this.name);
       }
@@ -410,6 +418,9 @@ var Promise = (function PromiseClosure() {
         if (errback)
           this.errbacks.push(errback);
       }
+
+      if (progressback)
+        this.progressbacks.push(progressback);
     }
   };
 
diff --git a/web/viewer.html b/web/viewer.html
index d275f77c1..ef61ce697 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -11,6 +11,7 @@
         <!-- PDFJSSCRIPT_INCLUDE_BUILD -->
         <script type="text/javascript" src="../src/core.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
         <script type="text/javascript" src="../src/util.js"></script>  <!-- PDFJSSCRIPT_REMOVE_CORE -->
+        <script type="text/javascript" src="../src/api.js"></script>  <!-- PDFJSSCRIPT_REMOVE_CORE -->
         <script type="text/javascript" src="../src/metadata.js"></script>  <!-- PDFJSSCRIPT_REMOVE_CORE -->
         <script type="text/javascript" src="../src/canvas.js"></script>  <!-- PDFJSSCRIPT_REMOVE_CORE -->
         <script type="text/javascript" src="../src/obj.js"></script>  <!-- PDFJSSCRIPT_REMOVE_CORE -->
diff --git a/web/viewer.js b/web/viewer.js
index 3587c96bd..3ca4f805f 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -318,27 +318,25 @@ var PDFView = {
     }
 
     var self = this;
-    PDFJS.getPdf(
-      {
-        url: url,
-        progress: function getPdfProgress(evt) {
-          if (evt.lengthComputable)
-            self.progress(evt.loaded / evt.total);
-        },
-        error: function getPdfError(e) {
-          var loadingIndicator = document.getElementById('loading');
-          loadingIndicator.textContent = 'Error';
-          var moreInfo = {
-            message: 'Unexpected server response of ' + e.target.status + '.'
-          };
-          self.error('An error occurred while loading the PDF.', moreInfo);
-        }
-      },
-      function getPdfLoad(data) {
-        self.loading = true;
-        self.load(data, scale);
+    self.loading = true;
+    PDFJS.getDocument(url).then(
+      function getDocumentCallback(pdfDocument) {
+        self.load(pdfDocument, scale);
         self.loading = false;
-      });
+      },
+      function getDocumentError(message, exception) {
+        var loadingIndicator = document.getElementById('loading');
+        loadingIndicator.textContent = 'Error';
+        var moreInfo = {
+          message: message
+        };
+        self.error('An error occurred while loading the PDF.', moreInfo);
+        self.loading = false;
+      },
+      function getDocumentProgress(progressData) {
+        self.progress(progressData.loaded / progressData.total);
+      }
+    );
   },
 
   download: function pdfViewDownload() {
@@ -461,7 +459,7 @@ var PDFView = {
     PDFView.loadingBar.percent = percent;
   },
 
-  load: function pdfViewLoad(data, scale) {
+  load: function pdfViewLoad(pdfDocument, scale) {
     function bindOnAfterDraw(pageView, thumbnailView) {
       // when page is painted, using the image as thumbnail base
       pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() {
@@ -489,14 +487,8 @@ var PDFView = {
     while (container.hasChildNodes())
       container.removeChild(container.lastChild);
 
-    var pdf;
-    try {
-      pdf = new PDFJS.PDFDoc(data);
-    } catch (e) {
-      this.error('An error occurred while reading the PDF.', e);
-    }
-    var pagesCount = pdf.numPages;
-    var id = pdf.fingerprint;
+    var pagesCount = pdfDocument.numPages;
+    var id = pdfDocument.fingerprint;
     var storedHash = null;
     document.getElementById('numPages').textContent = pagesCount;
     document.getElementById('pageNumber').max = pagesCount;
@@ -514,30 +506,68 @@ var PDFView = {
     var pages = this.pages = [];
     var pagesRefMap = {};
     var thumbnails = this.thumbnails = [];
-    for (var i = 1; i <= pagesCount; i++) {
-      var page = pdf.getPage(i);
-      var pageView = new PageView(container, page, i, page.width, page.height,
-                                  page.stats, this.navigateTo.bind(this));
-      var thumbnailView = new ThumbnailView(sidebar, page, i,
-                                            page.width / page.height);
-      bindOnAfterDraw(pageView, thumbnailView);
+    var pagePromises = [];
+    for (var i = 1; i <= pagesCount; i++)
+      pagePromises.push(pdfDocument.getPage(i));
+    var self = this;
+    var pagesPromise = PDFJS.Promise.all(pagePromises);
+    pagesPromise.then(function(promisedPages) {
+      for (var i = 1; i <= pagesCount; i++) {
+        var page = promisedPages[i - 1];
+        var pageView = new PageView(container, page, i, page.width, page.height,
+                                    page.stats, self.navigateTo.bind(self));
+        var thumbnailView = new ThumbnailView(sidebar, page, i,
+                                              page.width / page.height);
+        bindOnAfterDraw(pageView, thumbnailView);
 
-      pages.push(pageView);
-      thumbnails.push(thumbnailView);
-      var pageRef = page.ref;
-      pagesRefMap[pageRef.num + ' ' + pageRef.gen + ' R'] = i;
-    }
+        pages.push(pageView);
+        thumbnails.push(thumbnailView);
+        var pageRef = page.ref;
+        pagesRefMap[pageRef.num + ' ' + pageRef.gen + ' R'] = i;
+      }
 
-    this.pagesRefMap = pagesRefMap;
-    this.destinations = pdf.catalog.destinations;
+      self.pagesRefMap = pagesRefMap;
+    });
 
-    if (pdf.catalog.documentOutline) {
-      this.outline = new DocumentOutlineView(pdf.catalog.documentOutline);
-      var outlineSwitchButton = document.getElementById('outlineSwitch');
-      outlineSwitchButton.removeAttribute('disabled');
-      this.switchSidebarView('outline');
-    }
+    var destinationsPromise = pdfDocument.getDestinations();
+    destinationsPromise.then(function(destinations) {
+      self.destinations = destinations;
+    });
 
+    // outline and initial view depends on destinations and pagesRefMap
+    PDFJS.Promise.all([pagesPromise, destinationsPromise]).then(function() {
+      pdfDocument.getOutline().then(function(outline) {
+        if (!outline)
+          return;
+
+        self.outline = new DocumentOutlineView(outline);
+        var outlineSwitchButton = document.getElementById('outlineSwitch');
+        outlineSwitchButton.removeAttribute('disabled');
+        self.switchSidebarView('outline');
+      });
+
+      self.setInitialView(storedHash, scale);
+    });
+
+    pdfDocument.getMetadata().then(function(info, metadata) {
+      self.documentInfo = info;
+      self.metadata = metadata;
+
+      var pdfTitle;
+      if (metadata) {
+        if (metadata.has('dc:title'))
+          pdfTitle = metadata.get('dc:title');
+      }
+
+      if (!pdfTitle && info && info['Title'])
+        pdfTitle = info['Title'];
+
+      if (pdfTitle)
+        document.title = pdfTitle + ' - ' + document.title;
+    });
+  },
+
+  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;
@@ -558,24 +588,6 @@ var PDFView = {
       // Setting the default one.
       this.parseScale(kDefaultScale, true);
     }
-
-    this.metadata = null;
-    var metadata = pdf.catalog.metadata;
-    var info = this.documentInfo = pdf.info;
-    var pdfTitle;
-
-    if (metadata) {
-      this.metadata = metadata = new PDFJS.Metadata(metadata);
-
-      if (metadata.has('dc:title'))
-        pdfTitle = metadata.get('dc:title');
-    }
-
-    if (!pdfTitle && info && info['Title'])
-      pdfTitle = info['Title'];
-
-    if (pdfTitle)
-      document.title = pdfTitle + ' - ' + document.title;
   },
 
   setHash: function pdfViewSetHash(hash) {
@@ -711,12 +723,12 @@ var PDFView = {
   }
 };
 
-var PageView = function pageView(container, content, id, pageWidth, pageHeight,
+var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
                                  stats, navigateTo) {
   this.id = id;
-  this.content = content;
+  this.pdfPage = pdfPage;
 
-  var view = this.content.view;
+  var view = pdfPage.view;
   this.x = view.x;
   this.y = view.y;
   this.width = view.width;
@@ -748,7 +760,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
     div.appendChild(this.loadingIconDiv);
   };
 
-  function setupAnnotations(content, scale) {
+  function setupAnnotations(pdfPage, scale) {
     function bindLink(link, dest) {
       link.href = PDFView.getDestinationHash(dest);
       link.onclick = function pageViewSetupLinksOnclick() {
@@ -809,29 +821,30 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
       return container;
     }
 
-    var items = content.getAnnotations();
-    for (var i = 0; i < items.length; i++) {
-      var item = items[i];
-      switch (item.type) {
-        case 'Link':
-          var link = createElementWithStyle('a', item);
-          link.href = item.url || '';
-          if (!item.url)
-            bindLink(link, ('dest' in item) ? item.dest : null);
-          div.appendChild(link);
-          break;
-        case 'Text':
-          var comment = createCommentAnnotation(item.name, item);
-          if (comment)
-            div.appendChild(comment);
-          break;
+    pdfPage.getAnnotations().then(function(items) {
+      for (var i = 0; i < items.length; i++) {
+        var item = items[i];
+        switch (item.type) {
+          case 'Link':
+            var link = createElementWithStyle('a', item);
+            link.href = item.url || '';
+            if (!item.url)
+              bindLink(link, ('dest' in item) ? item.dest : null);
+            div.appendChild(link);
+            break;
+          case 'Text':
+            var comment = createCommentAnnotation(item.name, item);
+            if (comment)
+              div.appendChild(comment);
+            break;
+        }
       }
-    }
+    });
   }
 
   this.getPagePoint = function pageViewGetPagePoint(x, y) {
     var scale = PDFView.currentScale;
-    return this.content.rotatePoint(x / scale, y / scale);
+    return this.pdfPage.rotatePoint(x / scale, y / scale);
   };
 
   this.scrollIntoView = function pageViewScrollIntoView(dest) {
@@ -879,8 +892,8 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
       }
 
       var boundingRect = [
-        this.content.rotatePoint(x, y),
-        this.content.rotatePoint(x + width, y + height)
+        this.pdfPage.rotatePoint(x, y),
+        this.pdfPage.rotatePoint(x + width, y + height)
       ];
 
       if (scale && scale !== PDFView.currentScale)
@@ -948,7 +961,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
     // Rendering area
 
     var self = this;
-    this.content.startRendering(ctx, function pageViewDrawCallback(error) {
+    function pageViewDrawCallback(error) {
       if (self.loadingIconDiv) {
         div.removeChild(self.loadingIconDiv);
         delete self.loadingIconDiv;
@@ -964,9 +977,22 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
 
       cache.push(self);
       callback();
-    }, textLayer);
+    }
 
-    setupAnnotations(this.content, this.scale);
+    var renderContext = {
+      canvasContext: ctx,
+      textLayer: textLayer
+    };
+    this.pdfPage.render(renderContext).then(
+      function pdfPageRenderCallback() {
+        pageViewDrawCallback(null);
+      },
+      function pdfPageRenderError(error) {
+        pageViewDrawCallback(error);
+      }
+    );
+
+    setupAnnotations(this.pdfPage, this.scale);
     div.setAttribute('data-loaded', true);
   };
 
@@ -1397,7 +1423,11 @@ window.addEventListener('change', function webViewerChange(evt) {
 
     for (var i = 0; i < data.length; i++)
       uint8Array[i] = data.charCodeAt(i);
-    PDFView.load(uint8Array);
+
+    // TODO using blob instead?
+    PDFJS.getDocument(uint8Array).then(function(pdfDocument) {
+      PDFView.load(pdfDocument);
+    });
   };
 
   // Read as a binary string since "readAsArrayBuffer" is not yet

From fbd9fcd8fbfa14688e60c58cf062b55d04c2bfe0 Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Tue, 10 Apr 2012 12:17:43 -0700
Subject: [PATCH 02/29] Fix fingerprint name.

---
 src/api.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/api.js b/src/api.js
index a8bb5fb65..220b738a0 100644
--- a/src/api.js
+++ b/src/api.js
@@ -67,7 +67,7 @@
       return this.pdf.numPages;
     },
     get fingerprint() {
-      return this.pdf.fingerPrint;
+      return this.pdf.fingerprint;
     },
     getPage: function(number) {
       var promise = new PDFJS.Promise();

From 47c43b5779451f3011cde8ffb9bb242492315a5a Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Wed, 11 Apr 2012 08:29:44 -0700
Subject: [PATCH 03/29] Removing the rotatePoint, width, height from the API

---
 src/api.js    |  14 +++----
 src/canvas.js |  23 ++---------
 src/core.js   |  81 ++++++---------------------------------
 src/util.js   |  88 +++++++++++++++++++++++++++++++++++++++++-
 web/viewer.js | 103 +++++++++++++++++++++++++-------------------------
 5 files changed, 160 insertions(+), 149 deletions(-)

diff --git a/src/api.js b/src/api.js
index a8bb5fb65..d6d0bc5c6 100644
--- a/src/api.js
+++ b/src/api.js
@@ -6,11 +6,8 @@
     this.page = page;
   }
   PdfPageWrapper.prototype = {
-    get width() {
-      return this.page.width;
-    },
-    get height() {
-      return this.page.height;
+    get rotate() {
+      return this.page.rotate;
     },
     get stats() {
       return this.page.stats;
@@ -21,8 +18,10 @@
     get view() {
       return this.page.view;
     },
-    rotatePoint: function(x, y) {
-      return this.page.rotatePoint(x, y);
+    getViewport: function(scale, rotate) {
+      if (arguments < 2)
+        rotate = this.rotate;
+      return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
     },
     getAnnotations: function() {
       var promise = new PDFJS.Promise();
@@ -33,6 +32,7 @@
     render: function(renderContext) {
       var promise = new PDFJS.Promise();
       this.page.startRendering(renderContext.canvasContext,
+        renderContext.viewport,
         function complete(error) {
           if (error)
             promise.reject(error);
diff --git a/src/canvas.js b/src/canvas.js
index 8f29051fd..9d470fbec 100644
--- a/src/canvas.js
+++ b/src/canvas.js
@@ -241,27 +241,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
       'shadingFill': true
     },
 
-    beginDrawing: function CanvasGraphics_beginDrawing(mediaBox) {
-      var cw = this.ctx.canvas.width, ch = this.ctx.canvas.height;
+    beginDrawing: function CanvasGraphics_beginDrawing(viewport) {
+      var transform = viewport.transform;
       this.ctx.save();
-      switch (mediaBox.rotate) {
-        case 0:
-          this.ctx.transform(1, 0, 0, -1, 0, ch);
-          break;
-        case 90:
-          this.ctx.transform(0, 1, 1, 0, 0, 0);
-          break;
-        case 180:
-          this.ctx.transform(-1, 0, 0, 1, cw, 0);
-          break;
-        case 270:
-          this.ctx.transform(0, -1, -1, 0, cw, ch);
-          break;
-      }
-      // Scale so that canvas units are the same as PDF user space units
-      this.ctx.scale(cw / mediaBox.width, ch / mediaBox.height);
-      // Move the media left-top corner to the (0,0) canvas position
-      this.ctx.translate(-mediaBox.x, -mediaBox.y);
+      this.ctx.transform.apply(this.ctx, transform);
 
       if (this.textLayer)
         this.textLayer.beginLayout();
diff --git a/src/core.js b/src/core.js
index 15cd147e2..f71880852 100644
--- a/src/core.js
+++ b/src/core.js
@@ -100,18 +100,10 @@ var Page = (function PageClosure() {
       return shadow(this, 'mediaBox', obj);
     },
     get view() {
-      var cropBox = this.inheritPageProp('CropBox');
-      var view = {
-        x: 0,
-        y: 0,
-        width: this.width,
-        height: this.height
-      };
-      if (!isArray(cropBox) || cropBox.length !== 4)
-        return shadow(this, 'view', view);
-
       var mediaBox = this.mediaBox;
-      var offsetX = mediaBox[0], offsetY = mediaBox[1];
+      var cropBox = this.inheritPageProp('CropBox');
+      if (!isArray(cropBox) || cropBox.length !== 4)
+        return shadow(this, 'view', mediaBox);
 
       // From the spec, 6th ed., p.963:
       // "The crop, bleed, trim, and art boxes should not ordinarily
@@ -119,42 +111,13 @@ var Page = (function PageClosure() {
       // effectively reduced to their intersection with the media box."
       cropBox = Util.intersect(cropBox, mediaBox);
       if (!cropBox)
-        return shadow(this, 'view', view);
+        return shadow(this, 'view', mediaBox);
 
-      var tl = this.rotatePoint(cropBox[0] - offsetX, cropBox[1] - offsetY);
-      var br = this.rotatePoint(cropBox[2] - offsetX, cropBox[3] - offsetY);
-      view.x = Math.min(tl.x, br.x);
-      view.y = Math.min(tl.y, br.y);
-      view.width = Math.abs(tl.x - br.x);
-      view.height = Math.abs(tl.y - br.y);
-
-      return shadow(this, 'view', view);
+      return shadow(this, 'view', cropBox);
     },
     get annotations() {
       return shadow(this, 'annotations', this.inheritPageProp('Annots'));
     },
-    get width() {
-      var mediaBox = this.mediaBox;
-      var rotate = this.rotate;
-      var width;
-      if (rotate == 0 || rotate == 180) {
-        width = (mediaBox[2] - mediaBox[0]);
-      } else {
-        width = (mediaBox[3] - mediaBox[1]);
-      }
-      return shadow(this, 'width', width);
-    },
-    get height() {
-      var mediaBox = this.mediaBox;
-      var rotate = this.rotate;
-      var height;
-      if (rotate == 0 || rotate == 180) {
-        height = (mediaBox[3] - mediaBox[1]);
-      } else {
-        height = (mediaBox[2] - mediaBox[0]);
-      }
-      return shadow(this, 'height', height);
-    },
     get rotate() {
       var rotate = this.inheritPageProp('Rotate') || 0;
       // Normalize rotation so it's a multiple of 90 and between 0 and 270
@@ -238,7 +201,7 @@ var Page = (function PageClosure() {
       );
     },
 
-    display: function Page_display(gfx, callback) {
+    display: function Page_display(gfx, viewport, callback) {
       var stats = this.stats;
       stats.time('Rendering');
       var xref = this.xref;
@@ -248,10 +211,7 @@ var Page = (function PageClosure() {
 
       gfx.xref = xref;
       gfx.res = resources;
-      gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1],
-            width: this.width,
-            height: this.height,
-            rotate: this.rotate });
+      gfx.beginDrawing(viewport);
 
       var startIdx = 0;
       var length = this.operatorList.fnArray.length;
@@ -276,21 +236,6 @@ var Page = (function PageClosure() {
       }
       next();
     },
-    rotatePoint: function Page_rotatePoint(x, y, reverse) {
-      var rotate = reverse ? (360 - this.rotate) : this.rotate;
-      switch (rotate) {
-        case 180:
-          return {x: this.width - x, y: y};
-        case 90:
-          return {x: this.width - y, y: this.height - x};
-        case 270:
-          return {x: y, y: x};
-        case 360:
-        case 0:
-        default:
-          return {x: x, y: this.height - y};
-      }
-    },
     getLinks: function Page_getLinks() {
       var links = [];
       var annotations = pageGetAnnotations();
@@ -342,15 +287,10 @@ var Page = (function PageClosure() {
         if (!isName(subtype))
           continue;
         var rect = annotation.get('Rect');
-        var topLeftCorner = this.rotatePoint(rect[0], rect[1]);
-        var bottomRightCorner = this.rotatePoint(rect[2], rect[3]);
 
         var item = {};
         item.type = subtype.name;
-        item.x = Math.min(topLeftCorner.x, bottomRightCorner.x);
-        item.y = Math.min(topLeftCorner.y, bottomRightCorner.y);
-        item.width = Math.abs(topLeftCorner.x - bottomRightCorner.x);
-        item.height = Math.abs(topLeftCorner.y - bottomRightCorner.y);
+        item.rect = rect;
         switch (subtype.name) {
           case 'Link':
             var a = annotation.get('A');
@@ -434,7 +374,8 @@ var Page = (function PageClosure() {
       }
       return items;
     },
-    startRendering: function Page_startRendering(ctx, callback, textLayer)  {
+    startRendering: function Page_startRendering(ctx, viewport,
+                                                 callback, textLayer)  {
       var stats = this.stats;
       stats.time('Overall');
       // If there is no displayReadyPromise yet, then the operatorList was never
@@ -449,7 +390,7 @@ var Page = (function PageClosure() {
         function pageDisplayReadyPromise() {
           var gfx = new CanvasGraphics(ctx, this.objs, textLayer);
           try {
-            this.display(gfx, callback);
+            this.display(gfx, viewport, callback);
           } catch (e) {
             if (callback)
               callback(e);
diff --git a/src/util.js b/src/util.js
index 30fc799f9..9989d9c74 100644
--- a/src/util.js
+++ b/src/util.js
@@ -97,6 +97,19 @@ var Util = (function UtilClosure() {
     return [xt, yt];
   };
 
+  Util.applyInverseTransform = function Util_applyTransform(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];
+  };
+
+  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 |
@@ -165,7 +178,7 @@ var Util = (function UtilClosure() {
     }
 
     return result;
-  }
+  };
 
   Util.sign = function Util_sign(num) {
     return num < 0 ? -1 : 1;
@@ -174,6 +187,79 @@ var Util = (function UtilClosure() {
   return Util;
 })();
 
+var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
+  function PageViewport(viewBox, scale, rotate, offsetX, 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;
+    switch (rotate) {
+      case -180:
+      case 180:
+        rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
+        break;
+      case -270:
+      case 90:
+        rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
+        break;
+      case -90:
+      case 270:
+        rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
+        break;
+      case 360:
+      case 0:
+      default:
+        rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
+        break;
+    }
+    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.offsetX = offsetX;
+    this.offsetY = offsetY;
+    this.width = width;
+    this.height = height;
+  }
+  PageViewport.prototype = {
+    convertPointToViewport: function PageViewport_convertPointToViewport(x, y) {
+      return Util.applyTransform([x, y], this.transform);
+    },
+    convertRectangleToViewport:
+      function PageViewport_convertRectangeToViewport(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]];
+    },
+    convertViewportToPoint: function PageViewport_convertViewportToPoint(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,
diff --git a/web/viewer.js b/web/viewer.js
index 3ca4f805f..9fe9a1714 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -358,6 +358,8 @@ var PDFView = {
     var destRef = dest[0];
     var pageNumber = destRef instanceof Object ?
       this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] : (destRef + 1);
+    if (pageNumber > this.pages.length)
+      pageNumber = this.pages.length;
     if (pageNumber) {
       this.page = pageNumber;
       var currentPage = this.pages[pageNumber - 1];
@@ -514,10 +516,9 @@ var PDFView = {
     pagesPromise.then(function(promisedPages) {
       for (var i = 1; i <= pagesCount; i++) {
         var page = promisedPages[i - 1];
-        var pageView = new PageView(container, page, i, page.width, page.height,
+        var pageView = new PageView(container, page, i, scale,
                                     page.stats, self.navigateTo.bind(self));
-        var thumbnailView = new ThumbnailView(sidebar, page, i,
-                                              page.width / page.height);
+        var thumbnailView = new ThumbnailView(sidebar, page, i);
         bindOnAfterDraw(pageView, thumbnailView);
 
         pages.push(pageView);
@@ -664,7 +665,7 @@ var PDFView = {
     var windowTop = window.pageYOffset;
     for (var i = 1; i <= pages.length; ++i) {
       var page = pages[i - 1];
-      var pageHeight = page.height * page.scale + kBottomMargin;
+      var pageHeight = page.height + kBottomMargin;
       if (currentHeight + pageHeight > windowTop)
         break;
 
@@ -723,16 +724,13 @@ var PDFView = {
   }
 };
 
-var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
+var PageView = function pageView(container, pdfPage, id, scale,
                                  stats, navigateTo) {
   this.id = id;
   this.pdfPage = pdfPage;
 
-  var view = pdfPage.view;
-  this.x = view.x;
-  this.y = view.y;
-  this.width = view.width;
-  this.height = view.height;
+  this.scale = scale || 1.0;
+  this.viewport = this.pdfPage.getViewport(scale);
 
   var anchor = document.createElement('a');
   anchor.name = '' + this.id;
@@ -746,8 +744,13 @@ var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
 
   this.update = function pageViewUpdate(scale) {
     this.scale = scale || this.scale;
-    div.style.width = (this.width * this.scale) + 'px';
-    div.style.height = (this.height * this.scale) + 'px';
+    var viewport = this.pdfPage.getViewport(this.scale);
+
+    this.viewport = viewport;
+    this.width = viewport.width;
+    this.height = viewport.height;
+    div.style.width = viewport.width + 'px';
+    div.style.height = viewport.height + 'px';
 
     while (div.hasChildNodes())
       div.removeChild(div.lastChild);
@@ -760,7 +763,7 @@ var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
     div.appendChild(this.loadingIconDiv);
   };
 
-  function setupAnnotations(pdfPage, scale) {
+  function setupAnnotations(pdfPage, viewport) {
     function bindLink(link, dest) {
       link.href = PDFView.getDestinationHash(dest);
       link.onclick = function pageViewSetupLinksOnclick() {
@@ -770,11 +773,13 @@ var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
       };
     }
     function createElementWithStyle(tagName, item) {
+      var rect = viewport.convertRectangleToViewport(item.rect);
+      rect = Util.normalizeRect(rect);
       var element = document.createElement(tagName);
-      element.style.left = (Math.floor(item.x - view.x) * scale) + 'px';
-      element.style.top = (Math.floor(item.y - view.y) * scale) + 'px';
-      element.style.width = Math.ceil(item.width * scale) + 'px';
-      element.style.height = Math.ceil(item.height * scale) + 'px';
+      element.style.left = Math.floor(rect[0]) + 'px';
+      element.style.top = Math.floor(rect[1]) + 'px';
+      element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
+      element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
       return element;
     }
     function createCommentAnnotation(type, item) {
@@ -844,7 +849,7 @@ var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
 
   this.getPagePoint = function pageViewGetPagePoint(x, y) {
     var scale = PDFView.currentScale;
-    return this.pdfPage.rotatePoint(x / scale, y / scale);
+    return this.viewport.convertPointToViewport(x, y);
   };
 
   this.scrollIntoView = function pageViewScrollIntoView(dest) {
@@ -892,8 +897,8 @@ var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
       }
 
       var boundingRect = [
-        this.pdfPage.rotatePoint(x, y),
-        this.pdfPage.rotatePoint(x + width, y + height)
+        this.viewport.convertPointToViewport(x, y),
+        this.viewport.convertPointToViewport(x + width, y + height)
       ];
 
       if (scale && scale !== PDFView.currentScale)
@@ -904,18 +909,18 @@ var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
       setTimeout(function pageViewScrollIntoViewRelayout() {
         // letting page to re-layout before scrolling
         var scale = PDFView.currentScale;
-        var x = Math.min(boundingRect[0].x, boundingRect[1].x);
-        var y = Math.min(boundingRect[0].y, boundingRect[1].y);
-        var width = Math.abs(boundingRect[0].x - boundingRect[1].x);
-        var height = Math.abs(boundingRect[0].y - boundingRect[1].y);
+        var x = Math.min(boundingRect[0][0], boundingRect[1][0]);
+        var y = Math.min(boundingRect[0][1], boundingRect[1][1]);
+        var width = Math.abs(boundingRect[0][0] - boundingRect[1][0]);
+        var height = Math.abs(boundingRect[0][1] - boundingRect[1][1]);
 
         // using temporary div to scroll it into view
         var tempDiv = document.createElement('div');
         tempDiv.style.position = 'absolute';
-        tempDiv.style.left = Math.floor(x * scale) + 'px';
-        tempDiv.style.top = Math.floor(y * scale) + 'px';
-        tempDiv.style.width = Math.ceil(width * scale) + 'px';
-        tempDiv.style.height = Math.ceil(height * scale) + 'px';
+        tempDiv.style.left = Math.floor(x) + 'px';
+        tempDiv.style.top = Math.floor(y) + 'px';
+        tempDiv.style.width = Math.ceil(width) + 'px';
+        tempDiv.style.height = Math.ceil(height) + 'px';
         div.appendChild(tempDiv);
         tempDiv.scrollIntoView(true);
         div.removeChild(tempDiv);
@@ -947,16 +952,15 @@ var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
     }
     var textLayer = textLayerDiv ? new TextLayerBuilder(textLayerDiv) : null;
 
-    var scale = this.scale;
-    canvas.width = pageWidth * scale;
-    canvas.height = pageHeight * scale;
+    var scale = this.scale, viewport = this.viewport;
+    canvas.width = viewport.width;
+    canvas.height = viewport.height;
 
     var ctx = canvas.getContext('2d');
     ctx.save();
     ctx.fillStyle = 'rgb(255, 255, 255)';
     ctx.fillRect(0, 0, canvas.width, canvas.height);
     ctx.restore();
-    ctx.translate(-this.x * scale, -this.y * scale);
 
     // Rendering area
 
@@ -981,6 +985,7 @@ var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
 
     var renderContext = {
       canvasContext: ctx,
+      viewport: this.viewport,
       textLayer: textLayer
     };
     this.pdfPage.render(renderContext).then(
@@ -992,7 +997,7 @@ var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
       }
     );
 
-    setupAnnotations(this.pdfPage, this.scale);
+    setupAnnotations(this.pdfPage, this.viewport);
     div.setAttribute('data-loaded', true);
   };
 
@@ -1004,7 +1009,7 @@ var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
   };
 };
 
-var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
+var ThumbnailView = function thumbnailView(container, pdfPage, id) {
   var anchor = document.createElement('a');
   anchor.href = PDFView.getAnchorUrl('#page=' + id);
   anchor.onclick = function stopNivigation() {
@@ -1012,9 +1017,10 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
     return false;
   };
 
-  var view = page.view;
-  this.width = view.width;
-  this.height = view.height;
+  var viewport = pdfPage.getViewport(1);
+  var pageWidth = viewport.width;
+  var pageHeight = viewport.height;
+  var pageRatio = pageWidth / pageHeight;
   this.id = id;
 
   var maxThumbSize = 134;
@@ -1022,8 +1028,8 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
     maxThumbSize * pageRatio;
   var canvasHeight = pageRatio <= 1 ? maxThumbSize :
     maxThumbSize / pageRatio;
-  var scaleX = this.scaleX = (canvasWidth / this.width);
-  var scaleY = this.scaleY = (canvasHeight / this.height);
+  var scaleX = this.scaleX = (canvasWidth / pageWidth);
+  var scaleY = this.scaleY = (canvasHeight / pageHeight);
 
   var div = document.createElement('div');
   div.id = 'thumbnailContainer' + id;
@@ -1048,15 +1054,8 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
     var ctx = canvas.getContext('2d');
     ctx.save();
     ctx.fillStyle = 'rgb(255, 255, 255)';
-    ctx.fillRect(0, 0, canvas.width, canvas.height);
+    ctx.fillRect(0, 0, canvasWidth, canvasHeight);
     ctx.restore();
-
-    var view = page.view;
-    ctx.translate(-view.x * scaleX, -view.y * scaleY);
-    div.style.width = (view.width * scaleX) + 'px';
-    div.style.height = (view.height * scaleY) + 'px';
-    div.style.lineHeight = (view.height * scaleY) + 'px';
-
     return ctx;
   }
 
@@ -1071,9 +1070,11 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
     }
 
     var ctx = getPageDrawContext();
-    page.startRendering(ctx, function thumbnailViewDrawStartRendering() {
-      callback();
-    });
+    var drawViewport = pdfPage.getViewport(scaleX);
+    page.startRendering(ctx, drawViewport,
+      function thumbnailViewDrawStartRendering() {
+        callback();
+      });
 
     this.hasImage = true;
   };
@@ -1359,7 +1360,7 @@ function updateViewarea() {
   var currentPage = PDFView.pages[pageNumber - 1];
   var topLeft = currentPage.getPagePoint(window.pageXOffset,
     window.pageYOffset - firstPage.y - kViewerTopMargin);
-  pdfOpenParams += ',' + Math.round(topLeft.x) + ',' + Math.round(topLeft.y);
+  pdfOpenParams += ',' + Math.round(topLeft[0]) + ',' + Math.round(topLeft[1]);
 
   var store = PDFView.store;
   store.set('exists', true);

From 2f4423cffb8efc2fdddc3bcbfd250627e49dcd34 Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Wed, 11 Apr 2012 09:42:41 -0700
Subject: [PATCH 04/29] Fixing zoom and rotate issues

---
 src/api.js    |  2 +-
 web/viewer.js | 16 ++++++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/api.js b/src/api.js
index 3d97f53c9..cccd4b152 100644
--- a/src/api.js
+++ b/src/api.js
@@ -19,7 +19,7 @@
       return this.page.view;
     },
     getViewport: function(scale, rotate) {
-      if (arguments < 2)
+      if (arguments.length < 2)
         rotate = this.rotate;
       return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
     },
diff --git a/web/viewer.js b/web/viewer.js
index 9fe9a1714..3c7279fb4 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -747,8 +747,6 @@ var PageView = function pageView(container, pdfPage, id, scale,
     var viewport = this.pdfPage.getViewport(this.scale);
 
     this.viewport = viewport;
-    this.width = viewport.width;
-    this.height = viewport.height;
     div.style.width = viewport.width + 'px';
     div.style.height = viewport.height + 'px';
 
@@ -763,6 +761,20 @@ var PageView = function pageView(container, pdfPage, id, scale,
     div.appendChild(this.loadingIconDiv);
   };
 
+  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
+  });
+
   function setupAnnotations(pdfPage, viewport) {
     function bindLink(link, dest) {
       link.href = PDFView.getDestinationHash(dest);

From d61c4f07f8c3d3869f3932fe1dd42c1993e1a087 Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Wed, 11 Apr 2012 10:18:29 -0700
Subject: [PATCH 05/29] Initial view bug and rename viewport function

---
 src/util.js   |  8 ++++----
 web/viewer.js | 14 +++++++-------
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/src/util.js b/src/util.js
index 9989d9c74..390b08427 100644
--- a/src/util.js
+++ b/src/util.js
@@ -244,16 +244,16 @@ var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
     this.height = height;
   }
   PageViewport.prototype = {
-    convertPointToViewport: function PageViewport_convertPointToViewport(x, y) {
+    convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
       return Util.applyTransform([x, y], this.transform);
     },
-    convertRectangleToViewport:
-      function PageViewport_convertRectangeToViewport(rect) {
+    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]];
     },
-    convertViewportToPoint: function PageViewport_convertViewportToPoint(x, y) {
+    convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
       return Util.applyInverseTransform([x, y], this.transform);
     }
   };
diff --git a/web/viewer.js b/web/viewer.js
index 3c7279fb4..51d4df711 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -730,7 +730,7 @@ var PageView = function pageView(container, pdfPage, id, scale,
   this.pdfPage = pdfPage;
 
   this.scale = scale || 1.0;
-  this.viewport = this.pdfPage.getViewport(scale);
+  this.viewport = this.pdfPage.getViewport(this.scale);
 
   var anchor = document.createElement('a');
   anchor.name = '' + this.id;
@@ -785,7 +785,7 @@ var PageView = function pageView(container, pdfPage, id, scale,
       };
     }
     function createElementWithStyle(tagName, item) {
-      var rect = viewport.convertRectangleToViewport(item.rect);
+      var rect = viewport.convertToViewportRectangle(item.rect);
       rect = Util.normalizeRect(rect);
       var element = document.createElement(tagName);
       element.style.left = Math.floor(rect[0]) + 'px';
@@ -861,7 +861,7 @@ var PageView = function pageView(container, pdfPage, id, scale,
 
   this.getPagePoint = function pageViewGetPagePoint(x, y) {
     var scale = PDFView.currentScale;
-    return this.viewport.convertPointToViewport(x, y);
+    return this.viewport.convertToPdfPoint(x, y);
   };
 
   this.scrollIntoView = function pageViewScrollIntoView(dest) {
@@ -909,8 +909,8 @@ var PageView = function pageView(container, pdfPage, id, scale,
       }
 
       var boundingRect = [
-        this.viewport.convertPointToViewport(x, y),
-        this.viewport.convertPointToViewport(x + width, y + height)
+        this.viewport.convertToViewportPoint(x, y),
+        this.viewport.convertToViewportPoint(x + width, y + height)
       ];
 
       if (scale && scale !== PDFView.currentScale)
@@ -1378,8 +1378,8 @@ function updateViewarea() {
   store.set('exists', true);
   store.set('page', pageNumber);
   store.set('zoom', normalizedScaleValue);
-  store.set('scrollLeft', Math.round(topLeft.x));
-  store.set('scrollTop', Math.round(topLeft.y));
+  store.set('scrollLeft', Math.round(topLeft[0]));
+  store.set('scrollTop', Math.round(topLeft[1]));
   var href = PDFView.getAnchorUrl(pdfOpenParams);
   document.getElementById('viewBookmark').href = href;
 }

From 73cab9c30220711e7204a62c92f49f76ae4242de Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Wed, 11 Apr 2012 15:52:15 -0700
Subject: [PATCH 06/29] Initial API refectoring

---
 src/api.js    | 409 +++++++++++++++++++++++++++++++++++++++++++++-----
 src/core.js   | 344 +-----------------------------------------
 src/worker.js |  21 +++
 3 files changed, 391 insertions(+), 383 deletions(-)

diff --git a/src/api.js b/src/api.js
index cccd4b152..c8f908e7b 100644
--- a/src/api.js
+++ b/src/api.js
@@ -1,22 +1,250 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
+/*
+  PDFDoc.prototype = {
+    destroy: function PDFDoc_destroy() {
+      if (this.worker)
+        this.worker.terminate();
+
+      if (this.fontWorker)
+        this.fontWorker.terminate();
+
+      for (var n in this.pageCache)
+        delete this.pageCache[n];
+
+      delete this.data;
+      delete this.stream;
+      delete this.pdf;
+      delete this.catalog;
+    }
+  };
+*/
+
 (function pdfApiWrapper() {
-  function PdfPageWrapper(page) {
-    this.page = page;
+  function WorkerTransport(promise) {
+    this.workerReadyPromise = promise;
+    this.objs = new PDFObjects();
+
+    this.pageCache = [];
+    this.pagePromises = [];
+    this.fontsLoading = {};
+
+    // 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 (typeof workerSrc === 'undefined') {
+        error('No PDFJS.workerSrc specified');
+      }
+
+      try {
+        var worker;
+        if (PDFJS.isFirefoxExtension) {
+          // The firefox extension can't load the worker from the resource://
+          // url so we have to inline the script and then use the blob loader.
+          var bb = new MozBlobBuilder();
+          bb.append(document.querySelector('#PDFJS_SCRIPT_TAG').textContent);
+          var blobUrl = window.URL.createObjectURL(bb.getBlob());
+          worker = new Worker(blobUrl);
+        } else {
+          // Some versions of FF can't create a worker on localhost, see:
+          // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
+          worker = new Worker(workerSrc);
+        }
+
+        var messageHandler = new MessageHandler('main', worker);
+
+        messageHandler.on('test', function pdfDocTest(supportTypedArray) {
+          if (supportTypedArray) {
+            this.worker = worker;
+            this.setupMessageHandler(messageHandler);
+          } else {
+            globalScope.PDFJS.disableWorker = true;
+            this.setupFakeWorker();
+          }
+        }.bind(this));
+
+        var testObj = new Uint8Array(1);
+        // Some versions of Opera throw a DATA_CLONE_ERR on
+        // serializing the typed array.
+        messageHandler.send('test', testObj);
+        return;
+      } catch (e) {
+        warn('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.setupFakeWorker();
+  }
+  WorkerTransport.prototype = {
+    setupFakeWorker: function WorkerTransport_setupFakeWorker() {
+      // 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.
+      WorkerMessageHandler.setup(messageHandler);
+    },
+
+    setupMessageHandler: function WorkerTransport_setupMessageHandler(messageHandler) {
+      this.messageHandler = messageHandler;
+
+      messageHandler.on('doc', function pdfDocPage(data) {
+        var pdfInfo = data.pdfInfo;
+        var pdfDocument = new PdfDocumentWrapper(pdfInfo, this);
+        this.pdfDocument = pdfDocument;
+        this.workerReadyPromise.resolve(pdfDocument)
+      }, this);
+
+      messageHandler.on('getpage', function pdfDocPage(data) {
+        var pageInfo = data.pageInfo;
+        var page = new PdfPageWrapper(pageInfo, transport);
+        this.pageCache[pageInfo.pageNumber] = pageInfo;
+        var promises = this.pagePromises[pageInfo.pageNumber];
+        delete this.pagePromises[pageInfo.pageNumber];
+        for (var i = 0, ii = promises.length; i < ii; ++i)
+          promises.resolve(page);
+      }, this);
+
+      messageHandler.on('page', function pdfDocPage(data) {
+        var pageNum = data.pageNum;
+        var page = this.pageCache[pageNum];
+        var depFonts = data.depFonts;
+
+        page.stats.timeEnd('Page Request');
+        page.startRenderingFromOperatorList(data.operatorList, depFonts);
+      }, this);
+
+      messageHandler.on('obj', function pdfDocObj(data) {
+        var id = data[0];
+        var type = data[1];
+
+        switch (type) {
+          case 'JpegStream':
+            var imageData = data[2];
+            loadJpegStream(id, imageData, this.objs);
+            break;
+          case 'Image':
+            var imageData = data[2];
+            this.objs.resolve(id, imageData);
+            break;
+          case 'Font':
+            var name = data[2];
+            var file = data[3];
+            var properties = data[4];
+
+            if (file) {
+              // Rewrap the ArrayBuffer in a stream.
+              var fontFileDict = new Dict();
+              file = new Stream(file, 0, file.length, fontFileDict);
+            }
+
+            // At this point, only the font object is created but the font is
+            // not yet attached to the DOM. This is done in `FontLoader.bind`.
+            var font = new Font(name, file, properties);
+            this.objs.resolve(id, font);
+            break;
+          default:
+            error('Got unkown object type ' + type);
+        }
+      }, this);
+
+      messageHandler.on('page_error', function pdfDocError(data) {
+        var page = this.pageCache[data.pageNum];
+        if (page.displayReadyPromise)
+          page.displayReadyPromise.reject(data.error);
+        else
+          error(data.error);
+      }, this);
+
+      messageHandler.on('jpeg_decode', function(data, promise) {
+        var imageData = data[0];
+        var components = data[1];
+        if (components != 3 && components != 1)
+          error('Only 3 component or 1 component can be returned');
+
+        var img = new Image();
+        img.onload = (function messageHandler_onloadClosure() {
+          var width = img.width;
+          var height = img.height;
+          var size = width * height;
+          var rgbaLength = size * 4;
+          var buf = new Uint8Array(size * components);
+          var tmpCanvas = createScratchCanvas(width, height);
+          var tmpCtx = tmpCanvas.getContext('2d');
+          tmpCtx.drawImage(img, 0, 0);
+          var data = tmpCtx.getImageData(0, 0, width, height).data;
+
+          if (components == 3) {
+            for (var i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
+              buf[j] = data[i];
+              buf[j + 1] = data[i + 1];
+              buf[j + 2] = data[i + 2];
+            }
+          } else if (components == 1) {
+            for (var i = 0, j = 0; i < rgbaLength; i += 4, j++) {
+              buf[j] = data[i];
+            }
+          }
+          promise.resolve({ data: buf, width: width, height: height});
+        }).bind(this);
+        var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
+        img.src = src;
+      });
+    },
+
+    sendData: function WorkerTransport_sendData(data) {
+      this.messageHandler.send('doc', data);
+    },
+
+    getPage: function WorkerTransport_getPage(n, promise) {
+      if (this.pageCache[n]) {
+         promise.resolve(pageCache[n]);
+         return;
+      }
+      if (n in this.pagePromises) {
+        this.pagePromises[n].push(promise);
+        return;
+      }
+      this.pagePromises[n] = [promise];
+      this.messageHandler.send('getpage', {page: n});
+    }
+  };
+  function PdfPageWrapper(page, transport) {
+    this.pageInfo = pageInfo;
+    this.transport = transport;
+    this.stats = new StatTimer();
+    this.objs = transport.objs;
   }
   PdfPageWrapper.prototype = {
+    get pageNumber() {
+      return this.pageInfo.pageNumber;
+    },
     get rotate() {
-      return this.page.rotate;
+      return this.pageInfo.rotate;
     },
     get stats() {
-      return this.page.stats;
+      return this.stats;
     },
     get ref() {
-      return this.page.ref;
+      return this.pageInfo.ref;
     },
     get view() {
-      return this.page.view;
+      return this.pageInfo.view;
     },
     getViewport: function(scale, rotate) {
       if (arguments.length < 2)
@@ -25,23 +253,133 @@
     },
     getAnnotations: function() {
       var promise = new PDFJS.Promise();
-      var annotations = this.page.getAnnotations();
+      var annotations = this.pageInfo.annotations;
       promise.resolve(annotations);
       return promise;
     },
     render: function(renderContext) {
-      var promise = new PDFJS.Promise();
-      this.page.startRendering(renderContext.canvasContext,
-        renderContext.viewport,
-        function complete(error) {
+      var promise;
+      var stats = this.stats;
+      stats.time('Overall');
+      // If there is no displayReadyPromise yet, then the operatorList was never
+      // requested before. Make the request and create the promise.
+      if (!this.displayReadyPromise) {
+        this.displayReadyPromise = promise = new Promise();
+
+        this.stats.time('Page Request');
+        this.messageHandler.send('page_request', this.pageNumber + 1);
+      } else
+        promise = this.displayReadyPromise;
+
+      var callback = (function complete(error) {
           if (error)
             promise.reject(error);
           else
             promise.resolve();
-        },
-        renderContext.textLayer);
+        });
+
+      // Once the operatorList and fonts are loaded, do the actual rendering.
+      this.displayReadyPromise.then(
+        function pageDisplayReadyPromise() {
+          var gfx = new CanvasGraphics(renderContext.canvasContext,
+            this.objs, renderContext.textLayer);
+          try {
+            this.display(gfx, renderContext.viewport, callback);
+          } catch (e) {
+            if (callback)
+              callback(e);
+            else
+              error(e);
+          }
+        }.bind(this),
+        function pageDisplayReadPromiseError(reason) {
+          if (callback)
+            callback(reason);
+          else
+            error(reason);
+        }
+      );
+
       return promise;
     },
+
+    startRenderingFromOperatorList:
+      function Page_startRenderingFromOperatorList(operatorList, fonts) {
+      var self = this;
+      this.operatorList = operatorList;
+
+      var displayContinuation = function pageDisplayContinuation() {
+        // Always defer call to display() to work around bug in
+        // Firefox error reporting from XHR callbacks.
+        setTimeout(function pageSetTimeout() {
+          self.displayReadyPromise.resolve();
+        });
+      };
+
+      this.ensureFonts(fonts,
+        function pageStartRenderingFromOperatorListEnsureFonts() {
+          displayContinuation();
+        }
+      );
+    },
+
+    ensureFonts: function Page_ensureFonts(fonts, callback) {
+      this.stats.time('Font Loading');
+      // Convert the font names to the corresponding font obj.
+      for (var i = 0, ii = fonts.length; i < ii; i++) {
+        fonts[i] = this.objs.objs[fonts[i]].data;
+      }
+
+      // Load all the fonts
+      FontLoader.bind(
+        fonts,
+        function pageEnsureFontsFontObjs(fontObjs) {
+          this.stats.timeEnd('Font Loading');
+
+          callback.call(this);
+        }.bind(this)
+      );
+    },
+
+    display: function Page_display(gfx, viewport, callback) {
+      var stats = this.stats;
+      stats.time('Rendering');
+
+/* REMOVE ??? */
+      var xref = this.xref;
+      var resources = this.resources;
+      assertWellFormed(isDict(resources), 'invalid page resources');
+
+      gfx.xref = xref;
+      gfx.res = resources;
+/* REMOVE END */
+
+      gfx.beginDrawing(viewport);
+
+      var startIdx = 0;
+      var length = this.operatorList.fnArray.length;
+      var operatorList = this.operatorList;
+      var stepper = null;
+      if (PDFJS.pdfBug && StepperManager.enabled) {
+        stepper = StepperManager.create(this.pageNumber);
+        stepper.init(operatorList);
+        stepper.nextBreakPoint = stepper.getNextBreakPoint();
+      }
+
+      var self = this;
+      function next() {
+        startIdx =
+          gfx.executeOperatorList(operatorList, startIdx, next, stepper);
+        if (startIdx == length) {
+          gfx.endDrawing();
+          stats.timeEnd('Rendering');
+          stats.timeEnd('Overall');
+          if (callback) callback();
+        }
+      }
+      next();
+    },
+
     getTextContent: function() {
       var promise = new PDFJS.Promise();
       var textContent = 'page text'; // not implemented
@@ -59,45 +397,49 @@
     }
   };
 
-  function PdfDocumentWrapper(pdf) {
-    this.pdf = pdf;
+  function PdfDocumentWrapper(pdfInfo, transport) {
+    this.pdfInfo = pdfInfo;
+    this.transport = transport;
   }
   PdfDocumentWrapper.prototype = {
     get numPages() {
-      return this.pdf.numPages;
+      return this.pdfInfo.numPages;
     },
     get fingerprint() {
-      return this.pdf.fingerprint;
+      return this.pdfInfo.fingerprint;
     },
     getPage: function(number) {
       var promise = new PDFJS.Promise();
-      var page = this.pdf.getPage(number);
-      promise.resolve(new PdfPageWrapper(page));
+      this.transport.getPage(number, promise);
       return promise;
     },
     getDestinations: function() {
       var promise = new PDFJS.Promise();
-      var destinations = this.pdf.catalog.destinations;
+      var destinations = this.pdfInfo.destinations;
       promise.resolve(destinations);
       return promise;
     },
     getOutline: function() {
       var promise = new PDFJS.Promise();
-      var outline = this.pdf.catalog.documentOutline;
+      var outline = this.pdfInfo.documentOutline;
       promise.resolve(outline);
       return promise;
     },
     getMetadata: function() {
       var promise = new PDFJS.Promise();
-      var info = this.pdf.info;
-      var metadata = this.pdf.catalog.metadata;
-      promise.resolve(info, metadata ? new PDFJS.Metadata(metadata) : null);
+      var info = this.pdfInfo.info;
+      var metadata = this.pdfInfo.metadata;
+      promise.resolve({
+        info: info,
+        metadata: metadata ? new PDFJS.Metadata(metadata) : null
+      });
       return promise;
     }
   };
 
   PDFJS.getDocument = function getDocument(source) {
     var promise = new PDFJS.Promise();
+    var transport = new WorkerTransport(promise);
     if (typeof source === 'string') {
       // fetch url
       PDFJS.getPdf(
@@ -116,26 +458,13 @@
           }
         },
         function getPdfLoad(data) {
-          var pdf = null;
-          try {
-            pdf = new PDFJS.PDFDoc(data);
-          } catch (e) {
-            promise.reject('An error occurred while reading the PDF.', e);
-          }
-          if (pdf)
-            promise.resolve(new PdfDocumentWrapper(pdf));
+          transport.sendData(data);
         });
     } else {
       // assuming the source is array, instantiating directly from it
-      var pdf = null;
-      try {
-        pdf = new PDFJS.PDFDoc(source);
-      } catch (e) {
-        promise.reject('An error occurred while reading the PDF.', e);
-      }
-      if (pdf)
-        promise.resolve(new PdfDocumentWrapper(pdf));
+      transport.sendData(source);
     }
     return promise;
   };
 })();
+
diff --git a/src/core.js b/src/core.js
index f71880852..1aa560a46 100644
--- a/src/core.js
+++ b/src/core.js
@@ -133,26 +133,6 @@ var Page = (function PageClosure() {
       return shadow(this, 'rotate', rotate);
     },
 
-    startRenderingFromOperatorList:
-      function Page_startRenderingFromOperatorList(operatorList, fonts) {
-      var self = this;
-      this.operatorList = operatorList;
-
-      var displayContinuation = function pageDisplayContinuation() {
-        // Always defer call to display() to work around bug in
-        // Firefox error reporting from XHR callbacks.
-        setTimeout(function pageSetTimeout() {
-          self.displayReadyPromise.resolve();
-        });
-      };
-
-      this.ensureFonts(fonts,
-        function pageStartRenderingFromOperatorListEnsureFonts() {
-          displayContinuation();
-        }
-      );
-    },
-
     getOperatorList: function Page_getOperatorList(handler, dependency) {
       if (this.operatorList) {
         // content was compiled
@@ -183,59 +163,6 @@ var Page = (function PageClosure() {
       return this.operatorList;
     },
 
-    ensureFonts: function Page_ensureFonts(fonts, callback) {
-      this.stats.time('Font Loading');
-      // Convert the font names to the corresponding font obj.
-      for (var i = 0, ii = fonts.length; i < ii; i++) {
-        fonts[i] = this.objs.objs[fonts[i]].data;
-      }
-
-      // Load all the fonts
-      FontLoader.bind(
-        fonts,
-        function pageEnsureFontsFontObjs(fontObjs) {
-          this.stats.timeEnd('Font Loading');
-
-          callback.call(this);
-        }.bind(this)
-      );
-    },
-
-    display: function Page_display(gfx, viewport, callback) {
-      var stats = this.stats;
-      stats.time('Rendering');
-      var xref = this.xref;
-      var resources = this.resources;
-      var mediaBox = this.mediaBox;
-      assertWellFormed(isDict(resources), 'invalid page resources');
-
-      gfx.xref = xref;
-      gfx.res = resources;
-      gfx.beginDrawing(viewport);
-
-      var startIdx = 0;
-      var length = this.operatorList.fnArray.length;
-      var operatorList = this.operatorList;
-      var stepper = null;
-      if (PDFJS.pdfBug && StepperManager.enabled) {
-        stepper = StepperManager.create(this.pageNumber);
-        stepper.init(operatorList);
-        stepper.nextBreakPoint = stepper.getNextBreakPoint();
-      }
-
-      var self = this;
-      function next() {
-        startIdx =
-          gfx.executeOperatorList(operatorList, startIdx, next, stepper);
-        if (startIdx == length) {
-          gfx.endDrawing();
-          stats.timeEnd('Rendering');
-          stats.timeEnd('Overall');
-          if (callback) callback();
-        }
-      }
-      next();
-    },
     getLinks: function Page_getLinks() {
       var links = [];
       var annotations = pageGetAnnotations();
@@ -376,35 +303,7 @@ var Page = (function PageClosure() {
     },
     startRendering: function Page_startRendering(ctx, viewport,
                                                  callback, textLayer)  {
-      var stats = this.stats;
-      stats.time('Overall');
-      // If there is no displayReadyPromise yet, then the operatorList was never
-      // requested before. Make the request and create the promise.
-      if (!this.displayReadyPromise) {
-        this.pdf.startRendering(this);
-        this.displayReadyPromise = new Promise();
-      }
-
-      // Once the operatorList and fonts are loaded, do the actual rendering.
-      this.displayReadyPromise.then(
-        function pageDisplayReadyPromise() {
-          var gfx = new CanvasGraphics(ctx, this.objs, textLayer);
-          try {
-            this.display(gfx, viewport, callback);
-          } catch (e) {
-            if (callback)
-              callback(e);
-            else
-              error(e);
-          }
-        }.bind(this),
-        function pageDisplayReadPromiseError(reason) {
-          if (callback)
-            callback(reason);
-          else
-            error(reason);
-        }
-      );
+/// DELETE
     }
   };
 
@@ -578,244 +477,3 @@ var PDFDocModel = (function PDFDocModelClosure() {
 
   return PDFDocModel;
 })();
-
-var PDFDoc = (function PDFDocClosure() {
-  function PDFDoc(arg, callback) {
-    var stream = null;
-    var data = null;
-
-    if (isStream(arg)) {
-      stream = arg;
-      data = arg.bytes;
-    } else if (isArrayBuffer(arg)) {
-      stream = new Stream(arg);
-      data = arg;
-    } else {
-      error('PDFDoc: Unknown argument type');
-    }
-
-    this.data = data;
-    this.stream = stream;
-    this.pdfModel = new PDFDocModel(stream);
-    this.fingerprint = this.pdfModel.getFingerprint();
-    this.info = this.pdfModel.getDocumentInfo();
-    this.catalog = this.pdfModel.catalog;
-    this.objs = new PDFObjects();
-
-    this.pageCache = [];
-    this.fontsLoading = {};
-    this.workerReadyPromise = new Promise('workerReady');
-
-    // 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 (typeof workerSrc === 'undefined') {
-        error('No PDFJS.workerSrc specified');
-      }
-
-      try {
-        var worker;
-        if (PDFJS.isFirefoxExtension) {
-          // The firefox extension can't load the worker from the resource://
-          // url so we have to inline the script and then use the blob loader.
-          var bb = new MozBlobBuilder();
-          bb.append(document.querySelector('#PDFJS_SCRIPT_TAG').textContent);
-          var blobUrl = window.URL.createObjectURL(bb.getBlob());
-          worker = new Worker(blobUrl);
-        } else {
-          // Some versions of FF can't create a worker on localhost, see:
-          // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
-          worker = new Worker(workerSrc);
-        }
-
-        var messageHandler = new MessageHandler('main', worker);
-
-        messageHandler.on('test', function pdfDocTest(supportTypedArray) {
-          if (supportTypedArray) {
-            this.worker = worker;
-            this.setupMessageHandler(messageHandler);
-          } else {
-            globalScope.PDFJS.disableWorker = true;
-            this.setupFakeWorker();
-          }
-        }.bind(this));
-
-        var testObj = new Uint8Array(1);
-        // Some versions of Opera throw a DATA_CLONE_ERR on
-        // serializing the typed array.
-        messageHandler.send('test', testObj);
-        return;
-      } catch (e) {
-        warn('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.setupFakeWorker();
-  }
-
-  PDFDoc.prototype = {
-    setupFakeWorker: function PDFDoc_setupFakeWorker() {
-      // If we don't use a worker, just post/sendMessage to the main thread.
-      var fakeWorker = {
-        postMessage: function PDFDoc_postMessage(obj) {
-          fakeWorker.onmessage({data: obj});
-        },
-        terminate: function PDFDoc_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.
-      WorkerMessageHandler.setup(messageHandler);
-    },
-
-
-    setupMessageHandler: function PDFDoc_setupMessageHandler(messageHandler) {
-      this.messageHandler = messageHandler;
-
-      messageHandler.on('page', function pdfDocPage(data) {
-        var pageNum = data.pageNum;
-        var page = this.pageCache[pageNum];
-        var depFonts = data.depFonts;
-
-        page.stats.timeEnd('Page Request');
-        page.startRenderingFromOperatorList(data.operatorList, depFonts);
-      }, this);
-
-      messageHandler.on('obj', function pdfDocObj(data) {
-        var id = data[0];
-        var type = data[1];
-
-        switch (type) {
-          case 'JpegStream':
-            var imageData = data[2];
-            loadJpegStream(id, imageData, this.objs);
-            break;
-          case 'Image':
-            var imageData = data[2];
-            this.objs.resolve(id, imageData);
-            break;
-          case 'Font':
-            var name = data[2];
-            var file = data[3];
-            var properties = data[4];
-
-            if (file) {
-              // Rewrap the ArrayBuffer in a stream.
-              var fontFileDict = new Dict();
-              file = new Stream(file, 0, file.length, fontFileDict);
-            }
-
-            // At this point, only the font object is created but the font is
-            // not yet attached to the DOM. This is done in `FontLoader.bind`.
-            var font = new Font(name, file, properties);
-            this.objs.resolve(id, font);
-            break;
-          default:
-            error('Got unkown object type ' + type);
-        }
-      }, this);
-
-      messageHandler.on('page_error', function pdfDocError(data) {
-        var page = this.pageCache[data.pageNum];
-        if (page.displayReadyPromise)
-          page.displayReadyPromise.reject(data.error);
-        else
-          error(data.error);
-      }, this);
-
-      messageHandler.on('jpeg_decode', function(data, promise) {
-        var imageData = data[0];
-        var components = data[1];
-        if (components != 3 && components != 1)
-          error('Only 3 component or 1 component can be returned');
-
-        var img = new Image();
-        img.onload = (function messageHandler_onloadClosure() {
-          var width = img.width;
-          var height = img.height;
-          var size = width * height;
-          var rgbaLength = size * 4;
-          var buf = new Uint8Array(size * components);
-          var tmpCanvas = createScratchCanvas(width, height);
-          var tmpCtx = tmpCanvas.getContext('2d');
-          tmpCtx.drawImage(img, 0, 0);
-          var data = tmpCtx.getImageData(0, 0, width, height).data;
-
-          if (components == 3) {
-            for (var i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
-              buf[j] = data[i];
-              buf[j + 1] = data[i + 1];
-              buf[j + 2] = data[i + 2];
-            }
-          } else if (components == 1) {
-            for (var i = 0, j = 0; i < rgbaLength; i += 4, j++) {
-              buf[j] = data[i];
-            }
-          }
-          promise.resolve({ data: buf, width: width, height: height});
-        }).bind(this);
-        var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
-        img.src = src;
-      });
-
-      setTimeout(function pdfDocFontReadySetTimeout() {
-        messageHandler.send('doc', this.data);
-        this.workerReadyPromise.resolve(true);
-      }.bind(this));
-    },
-
-    get numPages() {
-      return this.pdfModel.numPages;
-    },
-
-    startRendering: function PDFDoc_startRendering(page) {
-      // The worker might not be ready to receive the page request yet.
-      this.workerReadyPromise.then(function pdfDocStartRenderingThen() {
-        page.stats.time('Page Request');
-        this.messageHandler.send('page_request', page.pageNumber + 1);
-      }.bind(this));
-    },
-
-    getPage: function PDFDoc_getPage(n) {
-      if (this.pageCache[n])
-        return this.pageCache[n];
-
-      var page = this.pdfModel.getPage(n);
-      // Add a reference to the objects such that Page can forward the reference
-      // to the CanvasGraphics and so on.
-      page.objs = this.objs;
-      page.pdf = this;
-      return (this.pageCache[n] = page);
-    },
-
-    destroy: function PDFDoc_destroy() {
-      if (this.worker)
-        this.worker.terminate();
-
-      if (this.fontWorker)
-        this.fontWorker.terminate();
-
-      for (var n in this.pageCache)
-        delete this.pageCache[n];
-
-      delete this.data;
-      delete this.stream;
-      delete this.pdf;
-      delete this.catalog;
-    }
-  };
-
-  return PDFDoc;
-})();
-
-globalScope.PDFJS.PDFDoc = PDFDoc;
-
diff --git a/src/worker.js b/src/worker.js
index 42bd61050..69409ed79 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -89,6 +89,27 @@ var WorkerMessageHandler = {
       // Create only the model of the PDFDoc, which is enough for
       // processing the content of the pdf.
       pdfModel = new PDFDocModel(new Stream(data));
+      var doc = {
+        numPages: pdfModel.numPages,
+        fingerprint: pdfModel.fingerprint,
+        destinations: pdfModel.catalog.destinations,
+        outline: pdfModel.catalog.documentOutline,
+        info: pdfModel.info,
+        metadata: pdfModel.catalog.metadata
+      };
+      handler.send('doc', {pdfInfo: doc});
+    });
+
+    handler.on('getpage', function wphSetupTest(data) {
+      var pdfPage = pdfModel.getPage(data.pageNumber);
+      var page = {
+        pageNumber: data.pageNumber,
+        rotate: pdfPage.rotate,
+        ref: pdfPage.ref,
+        view: pdfPage.view,
+        annotations: pdfPage.getAnnotations(), // REMOVE
+      };
+      handler.send('getpage', {pageInfo: page});
     });
 
     handler.on('page_request', function wphSetupPageRequest(pageNum) {

From fd58f041179816115ca6f8d31434d61f63ae6159 Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Wed, 11 Apr 2012 16:47:42 -0700
Subject: [PATCH 07/29] Refactor API to be async.

---
 src/api.js    | 47 ++++++++++++++++++++++++-----------------------
 src/worker.js |  6 +++---
 web/viewer.js |  2 +-
 3 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/src/api.js b/src/api.js
index c8f908e7b..4a3f001b1 100644
--- a/src/api.js
+++ b/src/api.js
@@ -35,6 +35,7 @@
     // 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.
+    globalScope.PDFJS.disableWorker = true;
     if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
       var workerSrc = PDFJS.workerSrc;
       if (typeof workerSrc === 'undefined') {
@@ -57,6 +58,7 @@
         }
 
         var messageHandler = new MessageHandler('main', worker);
+        this.messageHandler = messageHandler;
 
         messageHandler.on('test', function pdfDocTest(supportTypedArray) {
           if (supportTypedArray) {
@@ -112,20 +114,20 @@
 
       messageHandler.on('getpage', function pdfDocPage(data) {
         var pageInfo = data.pageInfo;
-        var page = new PdfPageWrapper(pageInfo, transport);
-        this.pageCache[pageInfo.pageNumber] = pageInfo;
+        var page = new PdfPageWrapper(pageInfo, this);
+        this.pageCache[pageInfo.pageNumber] = page;
         var promises = this.pagePromises[pageInfo.pageNumber];
         delete this.pagePromises[pageInfo.pageNumber];
         for (var i = 0, ii = promises.length; i < ii; ++i)
-          promises.resolve(page);
+          promises[i].resolve(page);
       }, this);
 
       messageHandler.on('page', function pdfDocPage(data) {
         var pageNum = data.pageNum;
-        var page = this.pageCache[pageNum];
+        var page = this.pageCache[pageNum - 1];
         var depFonts = data.depFonts;
 
-        page.stats.timeEnd('Page Request');
+        //page.stats.timeEnd('Page Request');
         page.startRenderingFromOperatorList(data.operatorList, depFonts);
       }, this);
 
@@ -208,26 +210,26 @@
     },
 
     sendData: function WorkerTransport_sendData(data) {
-      this.messageHandler.send('doc', data);
+      this.messageHandler.send('doc_request', data);
     },
 
     getPage: function WorkerTransport_getPage(n, promise) {
-      if (this.pageCache[n]) {
-         promise.resolve(pageCache[n]);
+      if (this.pageCache[n - 1]) {
+         promise.resolve(pageCache[n - 1]);
          return;
       }
-      if (n in this.pagePromises) {
-        this.pagePromises[n].push(promise);
+      if ((n - 1) in this.pagePromises) {
+        this.pagePromises[n - 1].push(promise);
         return;
       }
-      this.pagePromises[n] = [promise];
-      this.messageHandler.send('getpage', {page: n});
+      this.pagePromises[n - 1] = [promise];
+      this.messageHandler.send('getpage_request', {pageNumber: n - 1});
     }
   };
-  function PdfPageWrapper(page, transport) {
+  function PdfPageWrapper(pageInfo, transport) {
     this.pageInfo = pageInfo;
     this.transport = transport;
-    this.stats = new StatTimer();
+    this._stats = new StatTimer();
     this.objs = transport.objs;
   }
   PdfPageWrapper.prototype = {
@@ -238,7 +240,7 @@
       return this.pageInfo.rotate;
     },
     get stats() {
-      return this.stats;
+      return this._stats;
     },
     get ref() {
       return this.pageInfo.ref;
@@ -258,18 +260,17 @@
       return promise;
     },
     render: function(renderContext) {
-      var promise;
+      var promise = new Promise();
       var stats = this.stats;
       stats.time('Overall');
       // If there is no displayReadyPromise yet, then the operatorList was never
       // requested before. Make the request and create the promise.
       if (!this.displayReadyPromise) {
-        this.displayReadyPromise = promise = new Promise();
+        this.displayReadyPromise = new Promise();
 
-        this.stats.time('Page Request');
-        this.messageHandler.send('page_request', this.pageNumber + 1);
-      } else
-        promise = this.displayReadyPromise;
+        //this.stats.time('Page Request');
+        this.transport.messageHandler.send('page_request', this.pageNumber + 1);
+      }
 
       var callback = (function complete(error) {
           if (error)
@@ -345,14 +346,14 @@
       var stats = this.stats;
       stats.time('Rendering');
 
-/* REMOVE ??? */
+/* REMOVE ??? 
       var xref = this.xref;
       var resources = this.resources;
       assertWellFormed(isDict(resources), 'invalid page resources');
 
       gfx.xref = xref;
       gfx.res = resources;
-/* REMOVE END */
+ REMOVE END */
 
       gfx.beginDrawing(viewport);
 
diff --git a/src/worker.js b/src/worker.js
index 69409ed79..cc9a8a590 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -85,7 +85,7 @@ var WorkerMessageHandler = {
       handler.send('test', data instanceof Uint8Array);
     });
 
-    handler.on('doc', function wphSetupDoc(data) {
+    handler.on('doc_request', function wphSetupDoc(data) {
       // Create only the model of the PDFDoc, which is enough for
       // processing the content of the pdf.
       pdfModel = new PDFDocModel(new Stream(data));
@@ -100,8 +100,8 @@ var WorkerMessageHandler = {
       handler.send('doc', {pdfInfo: doc});
     });
 
-    handler.on('getpage', function wphSetupTest(data) {
-      var pdfPage = pdfModel.getPage(data.pageNumber);
+    handler.on('getpage_request', function wphSetupTest(data) {
+      var pdfPage = pdfModel.getPage(data.pageNumber + 1);
       var page = {
         pageNumber: data.pageNumber,
         rotate: pdfPage.rotate,
diff --git a/web/viewer.js b/web/viewer.js
index 51d4df711..bda342aa7 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -986,7 +986,7 @@ var PageView = function pageView(container, pdfPage, id, scale,
       if (error)
         PDFView.error('An error occurred while rendering the page.', error);
 
-      self.stats = content.stats;
+      self.stats = pdfPage.stats;
       self.updateStats();
       if (self.onAfterDraw)
         self.onAfterDraw();

From 3b83a42a9122c1b7546535eaf215fe64d2b51f92 Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Wed, 11 Apr 2012 17:09:55 -0700
Subject: [PATCH 08/29] Outline fix, destroy, and linting

---
 src/api.js    | 65 +++++++++++++++++++--------------------------------
 src/worker.js |  2 +-
 2 files changed, 25 insertions(+), 42 deletions(-)

diff --git a/src/api.js b/src/api.js
index 4a3f001b1..82e85681c 100644
--- a/src/api.js
+++ b/src/api.js
@@ -1,26 +1,6 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-/*
-  PDFDoc.prototype = {
-    destroy: function PDFDoc_destroy() {
-      if (this.worker)
-        this.worker.terminate();
-
-      if (this.fontWorker)
-        this.fontWorker.terminate();
-
-      for (var n in this.pageCache)
-        delete this.pageCache[n];
-
-      delete this.data;
-      delete this.stream;
-      delete this.pdf;
-      delete this.catalog;
-    }
-  };
-*/
-
 (function pdfApiWrapper() {
   function WorkerTransport(promise) {
     this.workerReadyPromise = promise;
@@ -60,7 +40,7 @@
         var messageHandler = new MessageHandler('main', worker);
         this.messageHandler = messageHandler;
 
-        messageHandler.on('test', function pdfDocTest(supportTypedArray) {
+        messageHandler.on('test', function transportTest(supportTypedArray) {
           if (supportTypedArray) {
             this.worker = worker;
             this.setupMessageHandler(messageHandler);
@@ -85,6 +65,13 @@
     this.setupFakeWorker();
   }
   WorkerTransport.prototype = {
+    destroy: function WorkerTransport_destroy() {
+      if (this.worker)
+        this.worker.terminate();
+
+      for (var n in this.pageCache)
+        delete this.pageCache[n];
+    },
     setupFakeWorker: function WorkerTransport_setupFakeWorker() {
       // If we don't use a worker, just post/sendMessage to the main thread.
       var fakeWorker = {
@@ -102,17 +89,18 @@
       WorkerMessageHandler.setup(messageHandler);
     },
 
-    setupMessageHandler: function WorkerTransport_setupMessageHandler(messageHandler) {
+    setupMessageHandler:
+      function WorkerTransport_setupMessageHandler(messageHandler) {
       this.messageHandler = messageHandler;
 
-      messageHandler.on('doc', function pdfDocPage(data) {
+      messageHandler.on('doc', function transportPage(data) {
         var pdfInfo = data.pdfInfo;
         var pdfDocument = new PdfDocumentWrapper(pdfInfo, this);
         this.pdfDocument = pdfDocument;
-        this.workerReadyPromise.resolve(pdfDocument)
+        this.workerReadyPromise.resolve(pdfDocument);
       }, this);
 
-      messageHandler.on('getpage', function pdfDocPage(data) {
+      messageHandler.on('getpage', function transportPage(data) {
         var pageInfo = data.pageInfo;
         var page = new PdfPageWrapper(pageInfo, this);
         this.pageCache[pageInfo.pageNumber] = page;
@@ -122,7 +110,7 @@
           promises[i].resolve(page);
       }, this);
 
-      messageHandler.on('page', function pdfDocPage(data) {
+      messageHandler.on('page', function transportPage(data) {
         var pageNum = data.pageNum;
         var page = this.pageCache[pageNum - 1];
         var depFonts = data.depFonts;
@@ -131,7 +119,7 @@
         page.startRenderingFromOperatorList(data.operatorList, depFonts);
       }, this);
 
-      messageHandler.on('obj', function pdfDocObj(data) {
+      messageHandler.on('obj', function transportObj(data) {
         var id = data[0];
         var type = data[1];
 
@@ -165,7 +153,7 @@
         }
       }, this);
 
-      messageHandler.on('page_error', function pdfDocError(data) {
+      messageHandler.on('page_error', function transportError(data) {
         var page = this.pageCache[data.pageNum];
         if (page.displayReadyPromise)
           page.displayReadyPromise.reject(data.error);
@@ -305,7 +293,8 @@
     },
 
     startRenderingFromOperatorList:
-      function Page_startRenderingFromOperatorList(operatorList, fonts) {
+      function PdfPageWrapper_startRenderingFromOperatorList(operatorList,
+                                                             fonts) {
       var self = this;
       this.operatorList = operatorList;
 
@@ -324,7 +313,7 @@
       );
     },
 
-    ensureFonts: function Page_ensureFonts(fonts, callback) {
+    ensureFonts: function PdfPageWrapper_ensureFonts(fonts, callback) {
       this.stats.time('Font Loading');
       // Convert the font names to the corresponding font obj.
       for (var i = 0, ii = fonts.length; i < ii; i++) {
@@ -342,19 +331,10 @@
       );
     },
 
-    display: function Page_display(gfx, viewport, callback) {
+    display: function PdfPageWrapper_display(gfx, viewport, callback) {
       var stats = this.stats;
       stats.time('Rendering');
 
-/* REMOVE ??? 
-      var xref = this.xref;
-      var resources = this.resources;
-      assertWellFormed(isDict(resources), 'invalid page resources');
-
-      gfx.xref = xref;
-      gfx.res = resources;
- REMOVE END */
-
       gfx.beginDrawing(viewport);
 
       var startIdx = 0;
@@ -422,7 +402,7 @@
     },
     getOutline: function() {
       var promise = new PDFJS.Promise();
-      var outline = this.pdfInfo.documentOutline;
+      var outline = this.pdfInfo.outline;
       promise.resolve(outline);
       return promise;
     },
@@ -435,6 +415,9 @@
         metadata: metadata ? new PDFJS.Metadata(metadata) : null
       });
       return promise;
+    },
+    destroy: function() {
+      this.transport.destroy();
     }
   };
 
diff --git a/src/worker.js b/src/worker.js
index cc9a8a590..fcde756b9 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -107,7 +107,7 @@ var WorkerMessageHandler = {
         rotate: pdfPage.rotate,
         ref: pdfPage.ref,
         view: pdfPage.view,
-        annotations: pdfPage.getAnnotations(), // REMOVE
+        annotations: pdfPage.getAnnotations()
       };
       handler.send('getpage', {pageInfo: page});
     });

From 5608f8e445ce16aadd4f7a9e92bb61d4554ec104 Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Wed, 11 Apr 2012 18:05:43 -0700
Subject: [PATCH 09/29] Test refactoring for async api.

---
 src/api.js           |  3 +-
 test/driver.js       | 81 ++++++++++++++++++++++++--------------------
 test/test_slave.html |  1 +
 3 files changed, 47 insertions(+), 38 deletions(-)

diff --git a/src/api.js b/src/api.js
index 82e85681c..3d683af07 100644
--- a/src/api.js
+++ b/src/api.js
@@ -15,7 +15,6 @@
     // 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.
-    globalScope.PDFJS.disableWorker = true;
     if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
       var workerSrc = PDFJS.workerSrc;
       if (typeof workerSrc === 'undefined') {
@@ -203,7 +202,7 @@
 
     getPage: function WorkerTransport_getPage(n, promise) {
       if (this.pageCache[n - 1]) {
-         promise.resolve(pageCache[n - 1]);
+         promise.resolve(this.pageCache[n - 1]);
          return;
       }
       if ((n - 1) in this.pagePromises) {
diff --git a/test/driver.js b/test/driver.js
index a1dc4b242..600f53c9c 100644
--- a/test/driver.js
+++ b/test/driver.js
@@ -100,13 +100,24 @@ function nextTask() {
 
   getPdf(task.file, function nextTaskGetPdf(data) {
     var failure;
+    function continuation() {
+      task.pageNum = task.firstPage || 1;
+      nextPage(task, failure);
+    }
     try {
-      task.pdfDoc = new PDFJS.PDFDoc(data);
+      var promise = PDFJS.getDocument(data);
+      promise.then(function(doc) {
+        task.pdfDoc = doc;
+        continuation();
+      }, function(e) {
+        failure = 'load PDF doc : ' + e;
+        continuation();
+      });
+      return;
     } catch (e) {
       failure = 'load PDF doc : ' + exceptionToString(e);
     }
-    task.pageNum = task.firstPage || 1;
-    nextPage(task, failure);
+    continuation();
   });
 }
 
@@ -163,45 +174,43 @@ function nextPage(task, loadError) {
       log(' loading page ' + task.pageNum + '/' + task.pdfDoc.numPages +
           '... ');
       var ctx = canvas.getContext('2d');
-      page = task.pdfDoc.getPage(task.pageNum);
+      task.pdfDoc.getPage(task.pageNum).then(function(page) {
+        var pdfToCssUnitsCoef = 96.0 / 72.0;
+        // using mediaBox for the canvas size
+        var pageWidth = page.width;
+        var pageHeight = page.height;
+        canvas.width = pageWidth * pdfToCssUnitsCoef;
+        canvas.height = pageHeight * pdfToCssUnitsCoef;
+        clear(ctx);
 
-      var pdfToCssUnitsCoef = 96.0 / 72.0;
-      // using mediaBox for the canvas size
-      var pageWidth = page.width;
-      var pageHeight = page.height;
-      canvas.width = pageWidth * pdfToCssUnitsCoef;
-      canvas.height = pageHeight * pdfToCssUnitsCoef;
-      clear(ctx);
-
-      // using the text layer builder that does nothing to test
-      // text layer creation operations
-      var textLayerBuilder = {
-        beginLayout: function nullTextLayerBuilderBeginLayout() {},
-        endLayout: function nullTextLayerBuilderEndLayout() {},
-        appendText: function nullTextLayerBuilderAppendText(text, fontName,
-                                                            fontSize) {}
-      };
-
-      page.startRendering(
-        ctx,
-        function nextPageStartRendering(error) {
-          var failureMessage = false;
-          if (error)
-            failureMessage = 'render : ' + error.message;
-          snapshotCurrentPage(task, failureMessage);
+        // using the text layer builder that does nothing to test
+        // text layer creation operations
+        var textLayerBuilder = {
+          beginLayout: function nullTextLayerBuilderBeginLayout() {},
+          endLayout: function nullTextLayerBuilderEndLayout() {},
+          appendText: function nullTextLayerBuilderAppendText(text, fontName,
+                                                              fontSize) {}
+        };
+        var renderContext = {
+          canvasContext: ctx,
+          textLayer: textLayerBuilder,
+          viewport: page.getViewport(1)
+        };
+        page.render(renderContext).then(function() {
+          snapshotCurrentPage(task, false);
         },
-        textLayerBuilder
-      );
+        function(error) {
+          snapshotCurrentPage(task, 'render : ' + error);
+        });
+      },
+      function(error) {
+        snapshotCurrentPage(task, 'render : ' + error);
+      });
     } catch (e) {
       failure = 'page setup : ' + exceptionToString(e);
+      snapshotCurrentPage(task, failure);
     }
   }
-
-  if (failure) {
-    // Skip right to snapshotting if there was a failure, since the
-    // fonts might be in an inconsistent state.
-    snapshotCurrentPage(task, failure);
-  }
 }
 
 function snapshotCurrentPage(task, failure) {
diff --git a/test/test_slave.html b/test/test_slave.html
index 50bb067e1..7c2097110 100644
--- a/test/test_slave.html
+++ b/test/test_slave.html
@@ -5,6 +5,7 @@
     <style type="text/css"></style>
     <script type="text/javascript" src="/src/core.js"></script>
     <script type="text/javascript" src="/src/util.js"></script>
+    <script type="text/javascript" src="/src/api.js"></script>
     <script type="text/javascript" src="/src/canvas.js"></script>
     <script type="text/javascript" src="/src/obj.js"></script>
     <script type="text/javascript" src="/src/function.js"></script>

From b312719d7e0cf1a45dda0b4ad871a45162ed6f5b Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Thu, 12 Apr 2012 08:23:38 -0700
Subject: [PATCH 10/29] Fixes test driver and examples

---
 examples/acroforms/forms.js    | 149 +++++++++++++++++----------------
 examples/acroforms/index.html  |   1 +
 examples/helloworld/hello.js   |  42 ++++++----
 examples/helloworld/index.html |   1 +
 src/util.js                    |   1 +
 test/driver.js                 |   8 +-
 6 files changed, 109 insertions(+), 93 deletions(-)

diff --git a/examples/acroforms/forms.js b/examples/acroforms/forms.js
index 6ec92766d..868825fc7 100644
--- a/examples/acroforms/forms.js
+++ b/examples/acroforms/forms.js
@@ -9,7 +9,7 @@
 
 var formFields = {};
 
-function setupForm(div, content, scale) {
+function setupForm(div, content, viewport) {
   function bindInputItem(input, item) {
     if (input.name in formFields) {
       var value = formFields[input.name];
@@ -27,16 +27,20 @@ function setupForm(div, content, scale) {
   }
   function createElementWithStyle(tagName, item) {
     var element = document.createElement(tagName);
-    element.style.left = (item.x * scale) + 'px';
-    element.style.top = (item.y * scale) + 'px';
-    element.style.width = Math.ceil(item.width * scale) + 'px';
-    element.style.height = Math.ceil(item.height * scale) + 'px';
+    var rect = Util.normalizeRect(
+      viewport.convertToViewportRectangle(item.rect));
+    element.style.left = Math.floor(rect[0]) + 'px';
+    element.style.top = Math.floor(rect[1]) + 'px';
+    element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
+    element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
     return element;
   }
   function assignFontStyle(element, item) {
     var fontStyles = '';
-    if ('fontSize' in item)
-      fontStyles += 'font-size: ' + Math.round(item.fontSize * scale) + 'px;';
+    if ('fontSize' in item) {
+      fontStyles += 'font-size: ' + Math.round(item.fontSize *
+        viewport.fontScale) + 'px;';
+    }
     switch (item.textAlignment) {
       case 0:
         fontStyles += 'text-align: left;';
@@ -51,83 +55,88 @@ function setupForm(div, content, scale) {
     element.setAttribute('style', element.getAttribute('style') + fontStyles);
   }
 
-  var items = content.getAnnotations();
-  for (var i = 0; i < items.length; i++) {
-    var item = items[i];
-    switch (item.type) {
-      case 'Widget':
-        if (item.fieldType != 'Tx' && item.fieldType != 'Btn' &&
-            item.fieldType != 'Ch')
-          break;
-        var inputDiv = createElementWithStyle('div', item);
-        inputDiv.className = 'inputHint';
-        div.appendChild(inputDiv);
-        var input;
-        if (item.fieldType == 'Tx') {
-          input = createElementWithStyle('input', item);
-        }
-        if (item.fieldType == 'Btn') {
-          input = createElementWithStyle('input', item);
-          if (item.flags & 32768) {
-            input.type = 'radio';
-             // radio button is not supported
-          } else if (item.flags & 65536) {
-            input.type = 'button';
-            // pushbutton is not supported
-          } else {
-            input.type = 'checkbox';
+  content.getAnnotations().then(function(items) {
+    for (var i = 0; i < items.length; i++) {
+      var item = items[i];
+      switch (item.type) {
+        case 'Widget':
+          if (item.fieldType != 'Tx' && item.fieldType != 'Btn' &&
+              item.fieldType != 'Ch')
+            break;
+          var inputDiv = createElementWithStyle('div', item);
+          inputDiv.className = 'inputHint';
+          div.appendChild(inputDiv);
+          var input;
+          if (item.fieldType == 'Tx') {
+            input = createElementWithStyle('input', item);
           }
-        }
-        if (item.fieldType == 'Ch') {
-          input = createElementWithStyle('select', item);
-          // select box is not supported
-        }
-        input.className = 'inputControl';
-        input.name = item.fullName;
-        input.title = item.alternativeText;
-        assignFontStyle(input, item);
-        bindInputItem(input, item);
-        div.appendChild(input);
-        break;
+          if (item.fieldType == 'Btn') {
+            input = createElementWithStyle('input', item);
+            if (item.flags & 32768) {
+              input.type = 'radio';
+               // radio button is not supported
+            } else if (item.flags & 65536) {
+              input.type = 'button';
+              // pushbutton is not supported
+            } else {
+              input.type = 'checkbox';
+            }
+          }
+          if (item.fieldType == 'Ch') {
+            input = createElementWithStyle('select', item);
+            // select box is not supported
+          }
+          input.className = 'inputControl';
+          input.name = item.fullName;
+          input.title = item.alternativeText;
+          assignFontStyle(input, item);
+          bindInputItem(input, item);
+          div.appendChild(input);
+          break;
+      }
     }
-  }
+  });
 }
 
 function renderPage(div, pdf, pageNumber, callback) {
-  var page = pdf.getPage(pageNumber);
-  var scale = 1.5;
+  pdf.getPage(pageNumber).then(function(page) {
+    var scale = 1.5;
+    var viewport = page.getViewport(scale);
 
-  var pageDisplayWidth = page.width * scale;
-  var pageDisplayHeight = page.height * scale;
+    var pageDisplayWidth = viewport.width;
+    var pageDisplayHeight = viewport.height;
 
-  var pageDivHolder = document.createElement('div');
-  pageDivHolder.className = 'pdfpage';
-  pageDivHolder.style.width = pageDisplayWidth + 'px';
-  pageDivHolder.style.height = pageDisplayHeight + 'px';
-  div.appendChild(pageDivHolder);
+    var pageDivHolder = document.createElement('div');
+    pageDivHolder.className = 'pdfpage';
+    pageDivHolder.style.width = pageDisplayWidth + 'px';
+    pageDivHolder.style.height = pageDisplayHeight + 'px';
+    div.appendChild(pageDivHolder);
 
-  // Prepare canvas using PDF page dimensions
-  var canvas = document.createElement('canvas');
-  var context = canvas.getContext('2d');
-  canvas.width = pageDisplayWidth;
-  canvas.height = pageDisplayHeight;
-  pageDivHolder.appendChild(canvas);
+    // Prepare canvas using PDF page dimensions
+    var canvas = document.createElement('canvas');
+    var context = canvas.getContext('2d');
+    canvas.width = pageDisplayWidth;
+    canvas.height = pageDisplayHeight;
+    pageDivHolder.appendChild(canvas);
 
 
-  // Render PDF page into canvas context
-  page.startRendering(context, callback);
+    // Render PDF page into canvas context
+    var renderContext = {
+      canvasContext: context,
+      viewport: viewport
+    };
+    page.render(renderContext).then(callback);
 
-  // Prepare and populate form elements layer
-  var formDiv = document.createElement('div');
-  pageDivHolder.appendChild(formDiv);
+    // Prepare and populate form elements layer
+    var formDiv = document.createElement('div');
+    pageDivHolder.appendChild(formDiv);
 
-  setupForm(formDiv, page, scale);
+    setupForm(formDiv, page, viewport);
+  });
 }
 
-PDFJS.getPdf(pdfWithFormsPath, function getPdfForm(data) {
-  // Instantiate PDFDoc with PDF data
-  var pdf = new PDFJS.PDFDoc(data);
-  
+// Fetch the PDF document from the URL using promices
+PDFJS.getDocument(pdfWithFormsPath).then(function getPdfForm(pdf) {
   // Rendering all pages starting from first
   var viewer = document.getElementById('viewer');
   var pageNumber = 1;
diff --git a/examples/acroforms/index.html b/examples/acroforms/index.html
index 8a9053f78..858ad649f 100644
--- a/examples/acroforms/index.html
+++ b/examples/acroforms/index.html
@@ -6,6 +6,7 @@
   <!-- In production, change the content of PDFJS.workerSrc below -->
   <script type="text/javascript" src="../../src/core.js"></script>
   <script type="text/javascript" src="../../src/util.js"></script>
+  <script type="text/javascript" src="../../src/api.js"></script>
   <script type="text/javascript" src="../../src/canvas.js"></script>
   <script type="text/javascript" src="../../src/obj.js"></script>
   <script type="text/javascript" src="../../src/function.js"></script>
diff --git a/examples/helloworld/hello.js b/examples/helloworld/hello.js
index 45e61eb6f..7bf18d65b 100644
--- a/examples/helloworld/hello.js
+++ b/examples/helloworld/hello.js
@@ -7,25 +7,31 @@
 
 'use strict';
 
-PDFJS.getPdf('helloworld.pdf', function getPdfHelloWorld(data) {
-  //
-  // Instantiate PDFDoc with PDF data
-  //
-  var pdf = new PDFJS.PDFDoc(data);
-  var page = pdf.getPage(1);
-  var scale = 1.5;
+//
+// Fetch the PDF document from the URL using promices
+//
+PDFJS.getDocument('helloworld.pdf').then(function(pdf) {
+  // Using promise to fetch the page
+  pdf.getPage(1).then(function(page) {
+    var scale = 1.5;
+    var viewport = page.getViewport(scale);
 
-  //
-  // Prepare canvas using PDF page dimensions
-  //
-  var canvas = document.getElementById('the-canvas');
-  var context = canvas.getContext('2d');
-  canvas.height = page.height * scale;
-  canvas.width = page.width * scale;
+    //
+    // Prepare canvas using PDF page dimensions
+    //
+    var canvas = document.getElementById('the-canvas');
+    var context = canvas.getContext('2d');
+    canvas.height = viewport.height;
+    canvas.width = viewport.width;
 
-  //
-  // Render PDF page into canvas context
-  //
-  page.startRendering(context);
+    //
+    // Render PDF page into canvas context
+    //
+    var renderContext = {
+      canvasContext: context,
+      viewport: viewport
+    };
+    page.render(renderContext);
+  });
 });
 
diff --git a/examples/helloworld/index.html b/examples/helloworld/index.html
index c6af616e6..c9df98809 100644
--- a/examples/helloworld/index.html
+++ b/examples/helloworld/index.html
@@ -6,6 +6,7 @@
   <!-- In production, change the content of PDFJS.workerSrc below -->
   <script type="text/javascript" src="../../src/core.js"></script>
   <script type="text/javascript" src="../../src/util.js"></script>
+  <script type="text/javascript" src="../../src/api.js"></script>
   <script type="text/javascript" src="../../src/canvas.js"></script>
   <script type="text/javascript" src="../../src/obj.js"></script>
   <script type="text/javascript" src="../../src/function.js"></script>
diff --git a/src/util.js b/src/util.js
index 390b08427..6ec4bc9cb 100644
--- a/src/util.js
+++ b/src/util.js
@@ -242,6 +242,7 @@ var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
     this.offsetY = offsetY;
     this.width = width;
     this.height = height;
+    this.fontScale = scale;
   }
   PageViewport.prototype = {
     convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
diff --git a/test/driver.js b/test/driver.js
index 600f53c9c..993a31349 100644
--- a/test/driver.js
+++ b/test/driver.js
@@ -176,11 +176,9 @@ function nextPage(task, loadError) {
       var ctx = canvas.getContext('2d');
       task.pdfDoc.getPage(task.pageNum).then(function(page) {
         var pdfToCssUnitsCoef = 96.0 / 72.0;
-        // using mediaBox for the canvas size
-        var pageWidth = page.width;
-        var pageHeight = page.height;
-        canvas.width = pageWidth * pdfToCssUnitsCoef;
-        canvas.height = pageHeight * pdfToCssUnitsCoef;
+        var viewport = page.getViewport(pdfToCssUnitsCoef);
+        canvas.width = viewport.width;
+        canvas.height = viewport.height;
         clear(ctx);
 
         // using the text layer builder that does nothing to test

From b6c587bb9801fba9dcacfe3e3c82a6f967425a67 Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Thu, 12 Apr 2012 09:59:17 -0700
Subject: [PATCH 11/29] Fix driver viewport.

---
 test/driver.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/driver.js b/test/driver.js
index 993a31349..be66aa216 100644
--- a/test/driver.js
+++ b/test/driver.js
@@ -192,7 +192,7 @@ function nextPage(task, loadError) {
         var renderContext = {
           canvasContext: ctx,
           textLayer: textLayerBuilder,
-          viewport: page.getViewport(1)
+          viewport: viewport
         };
         page.render(renderContext).then(function() {
           snapshotCurrentPage(task, false);

From f0687c4d50f4f674620b5cada5120421d2ba60c8 Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Thu, 12 Apr 2012 10:01:07 -0700
Subject: [PATCH 12/29] Refactor pageNumber/pageIndex concept

---
 src/api.js    | 54 +++++++++++++++++++++++----------------------------
 src/worker.js | 17 ++++++++--------
 2 files changed, 33 insertions(+), 38 deletions(-)

diff --git a/src/api.js b/src/api.js
index 3d683af07..e3969563a 100644
--- a/src/api.js
+++ b/src/api.js
@@ -68,8 +68,8 @@
       if (this.worker)
         this.worker.terminate();
 
-      for (var n in this.pageCache)
-        delete this.pageCache[n];
+      this.pageCache = [];
+      this.pagePromises = [];
     },
     setupFakeWorker: function WorkerTransport_setupFakeWorker() {
       // If we don't use a worker, just post/sendMessage to the main thread.
@@ -92,7 +92,7 @@
       function WorkerTransport_setupMessageHandler(messageHandler) {
       this.messageHandler = messageHandler;
 
-      messageHandler.on('doc', function transportPage(data) {
+      messageHandler.on('getdoc', function transportDoc(data) {
         var pdfInfo = data.pdfInfo;
         var pdfDocument = new PdfDocumentWrapper(pdfInfo, this);
         this.pdfDocument = pdfDocument;
@@ -102,19 +102,16 @@
       messageHandler.on('getpage', function transportPage(data) {
         var pageInfo = data.pageInfo;
         var page = new PdfPageWrapper(pageInfo, this);
-        this.pageCache[pageInfo.pageNumber] = page;
-        var promises = this.pagePromises[pageInfo.pageNumber];
-        delete this.pagePromises[pageInfo.pageNumber];
-        for (var i = 0, ii = promises.length; i < ii; ++i)
-          promises[i].resolve(page);
+        this.pageCache[pageInfo.pageIndex] = page;
+        var promise = this.pagePromises[pageInfo.pageIndex];
+        promise.resolve(page);
       }, this);
 
-      messageHandler.on('page', function transportPage(data) {
-        var pageNum = data.pageNum;
-        var page = this.pageCache[pageNum - 1];
+      messageHandler.on('renderpage', function transportRender(data) {
+        var page = this.pageCache[data.pageIndex];
         var depFonts = data.depFonts;
 
-        //page.stats.timeEnd('Page Request');
+        page.stats.timeEnd('Page Request');
         page.startRenderingFromOperatorList(data.operatorList, depFonts);
       }, this);
 
@@ -197,20 +194,17 @@
     },
 
     sendData: function WorkerTransport_sendData(data) {
-      this.messageHandler.send('doc_request', data);
+      this.messageHandler.send('getdoc_request', data);
     },
 
-    getPage: function WorkerTransport_getPage(n, promise) {
-      if (this.pageCache[n - 1]) {
-         promise.resolve(this.pageCache[n - 1]);
-         return;
-      }
-      if ((n - 1) in this.pagePromises) {
-        this.pagePromises[n - 1].push(promise);
-        return;
-      }
-      this.pagePromises[n - 1] = [promise];
-      this.messageHandler.send('getpage_request', {pageNumber: n - 1});
+    getPage: function WorkerTransport_getPage(pageNumber, promise) {
+      var pageIndex = pageNumber - 1;
+      if (pageIndex in this.pagePromises)
+        return this.pagePromises[pageIndex];
+      var promise = new PDFJS.Promise('Page ' + pageNumber);
+      this.pagePromises[pageIndex] = promise;
+      this.messageHandler.send('getpage_request', { pageIndex: pageIndex });
+      return promise;
     }
   };
   function PdfPageWrapper(pageInfo, transport) {
@@ -221,7 +215,7 @@
   }
   PdfPageWrapper.prototype = {
     get pageNumber() {
-      return this.pageInfo.pageNumber;
+      return this.pageInfo.pageIndex + 1;
     },
     get rotate() {
       return this.pageInfo.rotate;
@@ -255,8 +249,10 @@
       if (!this.displayReadyPromise) {
         this.displayReadyPromise = new Promise();
 
-        //this.stats.time('Page Request');
-        this.transport.messageHandler.send('page_request', this.pageNumber + 1);
+        this.stats.time('Page Request');
+        this.transport.messageHandler.send('renderpage_request', {
+          pageIndex: this.pageNumber - 1
+        });
       }
 
       var callback = (function complete(error) {
@@ -389,9 +385,7 @@
       return this.pdfInfo.fingerprint;
     },
     getPage: function(number) {
-      var promise = new PDFJS.Promise();
-      this.transport.getPage(number, promise);
-      return promise;
+      return this.transport.getPage(number);
     },
     getDestinations: function() {
       var promise = new PDFJS.Promise();
diff --git a/src/worker.js b/src/worker.js
index fcde756b9..f61e4b509 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -85,7 +85,7 @@ var WorkerMessageHandler = {
       handler.send('test', data instanceof Uint8Array);
     });
 
-    handler.on('doc_request', function wphSetupDoc(data) {
+    handler.on('getdoc_request', function wphSetupDoc(data) {
       // Create only the model of the PDFDoc, which is enough for
       // processing the content of the pdf.
       pdfModel = new PDFDocModel(new Stream(data));
@@ -97,13 +97,14 @@ var WorkerMessageHandler = {
         info: pdfModel.info,
         metadata: pdfModel.catalog.metadata
       };
-      handler.send('doc', {pdfInfo: doc});
+      handler.send('getdoc', {pdfInfo: doc});
     });
 
     handler.on('getpage_request', function wphSetupTest(data) {
-      var pdfPage = pdfModel.getPage(data.pageNumber + 1);
+      var pageNumber = data.pageIndex + 1;
+      var pdfPage = pdfModel.getPage(pageNumber);
       var page = {
-        pageNumber: data.pageNumber,
+        pageIndex: data.pageIndex,
         rotate: pdfPage.rotate,
         ref: pdfPage.ref,
         view: pdfPage.view,
@@ -112,8 +113,8 @@ var WorkerMessageHandler = {
       handler.send('getpage', {pageInfo: page});
     });
 
-    handler.on('page_request', function wphSetupPageRequest(pageNum) {
-      pageNum = parseInt(pageNum);
+    handler.on('renderpage_request', function wphSetupPageRequest(data) {
+      var pageNum = data.pageIndex + 1;
 
 
       // The following code does quite the same as
@@ -170,8 +171,8 @@ var WorkerMessageHandler = {
         }
       }
 
-      handler.send('page', {
-        pageNum: pageNum,
+      handler.send('renderpage', {
+        pageIndex: data.pageIndex,
         operatorList: operatorList,
         depFonts: Object.keys(fonts)
       });

From 2c49cab3a111e541e4ea1acc1907fd742ff2c57d Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Thu, 12 Apr 2012 12:11:22 -0700
Subject: [PATCH 13/29] Fixing names.

---
 src/api.js    | 500 +++++++++++++++++++++++++-------------------------
 src/core.js   |  26 +--
 src/image.js  |   2 +-
 src/worker.js |  16 +-
 4 files changed, 276 insertions(+), 268 deletions(-)

diff --git a/src/api.js b/src/api.js
index e3969563a..72d8cae66 100644
--- a/src/api.js
+++ b/src/api.js
@@ -1,7 +1,250 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-(function pdfApiWrapper() {
+PDFJS.getDocument = function getDocument(source) {
+  var promise = new PDFJS.Promise();
+  var transport = new WorkerTransport(promise);
+  if (typeof source === 'string') {
+    // fetch url
+    PDFJS.getPdf(
+      {
+        url: source,
+        progress: function getPDFProgress(evt) {
+          if (evt.lengthComputable)
+            promise.progress({
+              loaded: evt.loaded,
+              total: evt.total
+            });
+        },
+        error: function getPDFError(e) {
+          promise.reject('Unexpected server response of ' +
+            e.target.status + '.');
+        }
+      },
+      function getPDFLoad(data) {
+        transport.sendData(data);
+      });
+  } else {
+    // assuming the source is array, instantiating directly from it
+    transport.sendData(source);
+  }
+  return promise;
+};
+
+var PDFDocumentProxy = (function() {
+  function PDFDocumentProxy(pdfInfo, transport) {
+    this.pdfInfo = pdfInfo;
+    this.transport = transport;
+  }
+  PDFDocumentProxy.prototype = {
+    get numPages() {
+      return this.pdfInfo.numPages;
+    },
+    get fingerprint() {
+      return this.pdfInfo.fingerprint;
+    },
+    getPage: function(number) {
+      return this.transport.getPage(number);
+    },
+    getDestinations: function() {
+      var promise = new PDFJS.Promise();
+      var destinations = this.pdfInfo.destinations;
+      promise.resolve(destinations);
+      return promise;
+    },
+    getOutline: function() {
+      var promise = new PDFJS.Promise();
+      var outline = this.pdfInfo.outline;
+      promise.resolve(outline);
+      return promise;
+    },
+    getMetadata: function() {
+      var promise = new PDFJS.Promise();
+      var info = this.pdfInfo.info;
+      var metadata = this.pdfInfo.metadata;
+      promise.resolve({
+        info: info,
+        metadata: metadata ? new PDFJS.Metadata(metadata) : null
+      });
+      return promise;
+    },
+    destroy: function() {
+      this.transport.destroy();
+    }
+  };
+  return PDFDocumentProxy;
+})();
+
+var PDFPageProxy = (function PDFPageProxyClosure() {
+  function PDFPageProxy(pageInfo, transport) {
+    this.pageInfo = pageInfo;
+    this.transport = transport;
+    this._stats = new StatTimer();
+    this.objs = transport.objs;
+  }
+  PDFPageProxy.prototype = {
+    get pageNumber() {
+      return this.pageInfo.pageIndex + 1;
+    },
+    get rotate() {
+      return this.pageInfo.rotate;
+    },
+    get stats() {
+      return this._stats;
+    },
+    get ref() {
+      return this.pageInfo.ref;
+    },
+    get view() {
+      return this.pageInfo.view;
+    },
+    getViewport: function(scale, rotate) {
+      if (arguments.length < 2)
+        rotate = this.rotate;
+      return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
+    },
+    getAnnotations: function() {
+      var promise = new PDFJS.Promise();
+      var annotations = this.pageInfo.annotations;
+      promise.resolve(annotations);
+      return promise;
+    },
+    render: function(renderContext) {
+      var promise = new Promise();
+      var stats = this.stats;
+      stats.time('Overall');
+      // If there is no displayReadyPromise yet, then the operatorList was never
+      // requested before. Make the request and create the promise.
+      if (!this.displayReadyPromise) {
+        this.displayReadyPromise = new Promise();
+
+        this.stats.time('Page Request');
+        this.transport.messageHandler.send('RenderPageRequest', {
+          pageIndex: this.pageNumber - 1
+        });
+      }
+
+      var callback = (function complete(error) {
+          if (error)
+            promise.reject(error);
+          else
+            promise.resolve();
+        });
+
+      // Once the operatorList and fonts are loaded, do the actual rendering.
+      this.displayReadyPromise.then(
+        function pageDisplayReadyPromise() {
+          var gfx = new CanvasGraphics(renderContext.canvasContext,
+            this.objs, renderContext.textLayer);
+          try {
+            this.display(gfx, renderContext.viewport, callback);
+          } catch (e) {
+            if (callback)
+              callback(e);
+            else
+              error(e);
+          }
+        }.bind(this),
+        function pageDisplayReadPromiseError(reason) {
+          if (callback)
+            callback(reason);
+          else
+            error(reason);
+        }
+      );
+
+      return promise;
+    },
+
+    startRenderingFromOperatorList:
+      function PDFPageWrapper_startRenderingFromOperatorList(operatorList,
+                                                             fonts) {
+      var self = this;
+      this.operatorList = operatorList;
+
+      var displayContinuation = function pageDisplayContinuation() {
+        // Always defer call to display() to work around bug in
+        // Firefox error reporting from XHR callbacks.
+        setTimeout(function pageSetTimeout() {
+          self.displayReadyPromise.resolve();
+        });
+      };
+
+      this.ensureFonts(fonts,
+        function pageStartRenderingFromOperatorListEnsureFonts() {
+          displayContinuation();
+        }
+      );
+    },
+
+    ensureFonts: function PDFPageWrapper_ensureFonts(fonts, callback) {
+      this.stats.time('Font Loading');
+      // Convert the font names to the corresponding font obj.
+      for (var i = 0, ii = fonts.length; i < ii; i++) {
+        fonts[i] = this.objs.objs[fonts[i]].data;
+      }
+
+      // Load all the fonts
+      FontLoader.bind(
+        fonts,
+        function pageEnsureFontsFontObjs(fontObjs) {
+          this.stats.timeEnd('Font Loading');
+
+          callback.call(this);
+        }.bind(this)
+      );
+    },
+
+    display: function PDFPageWrapper_display(gfx, viewport, callback) {
+      var stats = this.stats;
+      stats.time('Rendering');
+
+      gfx.beginDrawing(viewport);
+
+      var startIdx = 0;
+      var length = this.operatorList.fnArray.length;
+      var operatorList = this.operatorList;
+      var stepper = null;
+      if (PDFJS.pdfBug && StepperManager.enabled) {
+        stepper = StepperManager.create(this.pageNumber);
+        stepper.init(operatorList);
+        stepper.nextBreakPoint = stepper.getNextBreakPoint();
+      }
+
+      var self = this;
+      function next() {
+        startIdx =
+          gfx.executeOperatorList(operatorList, startIdx, next, stepper);
+        if (startIdx == length) {
+          gfx.endDrawing();
+          stats.timeEnd('Rendering');
+          stats.timeEnd('Overall');
+          if (callback) callback();
+        }
+      }
+      next();
+    },
+
+    getTextContent: function() {
+      var promise = new PDFJS.Promise();
+      var textContent = 'page text'; // not implemented
+      promise.resolve(textContent);
+      return promise;
+    },
+    getOperationList: function() {
+      var promise = new PDFJS.Promise();
+      var operationList = { // not implemented
+        dependencyFontsID: null,
+        operatorList: null
+      };
+      promise.resolve(operationList);
+      return promise;
+    }
+  };
+  return PDFPageProxy;
+})();
+
+var WorkerTransport = (function WorkerTransportClosure() {
   function WorkerTransport(promise) {
     this.workerReadyPromise = promise;
     this.objs = new PDFObjects();
@@ -92,22 +335,22 @@
       function WorkerTransport_setupMessageHandler(messageHandler) {
       this.messageHandler = messageHandler;
 
-      messageHandler.on('getdoc', function transportDoc(data) {
+      messageHandler.on('GetDoc', function transportDoc(data) {
         var pdfInfo = data.pdfInfo;
-        var pdfDocument = new PdfDocumentWrapper(pdfInfo, this);
+        var pdfDocument = new PDFDocumentProxy(pdfInfo, this);
         this.pdfDocument = pdfDocument;
         this.workerReadyPromise.resolve(pdfDocument);
       }, this);
 
-      messageHandler.on('getpage', function transportPage(data) {
+      messageHandler.on('GetPage', function transportPage(data) {
         var pageInfo = data.pageInfo;
-        var page = new PdfPageWrapper(pageInfo, this);
+        var page = new PDFPageProxy(pageInfo, this);
         this.pageCache[pageInfo.pageIndex] = page;
         var promise = this.pagePromises[pageInfo.pageIndex];
         promise.resolve(page);
       }, this);
 
-      messageHandler.on('renderpage', function transportRender(data) {
+      messageHandler.on('RenderPage', function transportRender(data) {
         var page = this.pageCache[data.pageIndex];
         var depFonts = data.depFonts;
 
@@ -149,7 +392,7 @@
         }
       }, this);
 
-      messageHandler.on('page_error', function transportError(data) {
+      messageHandler.on('PageError', function transportError(data) {
         var page = this.pageCache[data.pageNum];
         if (page.displayReadyPromise)
           page.displayReadyPromise.reject(data.error);
@@ -157,7 +400,7 @@
           error(data.error);
       }, this);
 
-      messageHandler.on('jpeg_decode', function(data, promise) {
+      messageHandler.on('JpegDecode', function(data, promise) {
         var imageData = data[0];
         var components = data[1];
         if (components != 3 && components != 1)
@@ -194,7 +437,7 @@
     },
 
     sendData: function WorkerTransport_sendData(data) {
-      this.messageHandler.send('getdoc_request', data);
+      this.messageHandler.send('GetDocRequest', data);
     },
 
     getPage: function WorkerTransport_getPage(pageNumber, promise) {
@@ -203,245 +446,10 @@
         return this.pagePromises[pageIndex];
       var promise = new PDFJS.Promise('Page ' + pageNumber);
       this.pagePromises[pageIndex] = promise;
-      this.messageHandler.send('getpage_request', { pageIndex: pageIndex });
+      this.messageHandler.send('GetPageRequest', { pageIndex: pageIndex });
       return promise;
     }
   };
-  function PdfPageWrapper(pageInfo, transport) {
-    this.pageInfo = pageInfo;
-    this.transport = transport;
-    this._stats = new StatTimer();
-    this.objs = transport.objs;
-  }
-  PdfPageWrapper.prototype = {
-    get pageNumber() {
-      return this.pageInfo.pageIndex + 1;
-    },
-    get rotate() {
-      return this.pageInfo.rotate;
-    },
-    get stats() {
-      return this._stats;
-    },
-    get ref() {
-      return this.pageInfo.ref;
-    },
-    get view() {
-      return this.pageInfo.view;
-    },
-    getViewport: function(scale, rotate) {
-      if (arguments.length < 2)
-        rotate = this.rotate;
-      return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
-    },
-    getAnnotations: function() {
-      var promise = new PDFJS.Promise();
-      var annotations = this.pageInfo.annotations;
-      promise.resolve(annotations);
-      return promise;
-    },
-    render: function(renderContext) {
-      var promise = new Promise();
-      var stats = this.stats;
-      stats.time('Overall');
-      // If there is no displayReadyPromise yet, then the operatorList was never
-      // requested before. Make the request and create the promise.
-      if (!this.displayReadyPromise) {
-        this.displayReadyPromise = new Promise();
+  return WorkerTransport;
 
-        this.stats.time('Page Request');
-        this.transport.messageHandler.send('renderpage_request', {
-          pageIndex: this.pageNumber - 1
-        });
-      }
-
-      var callback = (function complete(error) {
-          if (error)
-            promise.reject(error);
-          else
-            promise.resolve();
-        });
-
-      // Once the operatorList and fonts are loaded, do the actual rendering.
-      this.displayReadyPromise.then(
-        function pageDisplayReadyPromise() {
-          var gfx = new CanvasGraphics(renderContext.canvasContext,
-            this.objs, renderContext.textLayer);
-          try {
-            this.display(gfx, renderContext.viewport, callback);
-          } catch (e) {
-            if (callback)
-              callback(e);
-            else
-              error(e);
-          }
-        }.bind(this),
-        function pageDisplayReadPromiseError(reason) {
-          if (callback)
-            callback(reason);
-          else
-            error(reason);
-        }
-      );
-
-      return promise;
-    },
-
-    startRenderingFromOperatorList:
-      function PdfPageWrapper_startRenderingFromOperatorList(operatorList,
-                                                             fonts) {
-      var self = this;
-      this.operatorList = operatorList;
-
-      var displayContinuation = function pageDisplayContinuation() {
-        // Always defer call to display() to work around bug in
-        // Firefox error reporting from XHR callbacks.
-        setTimeout(function pageSetTimeout() {
-          self.displayReadyPromise.resolve();
-        });
-      };
-
-      this.ensureFonts(fonts,
-        function pageStartRenderingFromOperatorListEnsureFonts() {
-          displayContinuation();
-        }
-      );
-    },
-
-    ensureFonts: function PdfPageWrapper_ensureFonts(fonts, callback) {
-      this.stats.time('Font Loading');
-      // Convert the font names to the corresponding font obj.
-      for (var i = 0, ii = fonts.length; i < ii; i++) {
-        fonts[i] = this.objs.objs[fonts[i]].data;
-      }
-
-      // Load all the fonts
-      FontLoader.bind(
-        fonts,
-        function pageEnsureFontsFontObjs(fontObjs) {
-          this.stats.timeEnd('Font Loading');
-
-          callback.call(this);
-        }.bind(this)
-      );
-    },
-
-    display: function PdfPageWrapper_display(gfx, viewport, callback) {
-      var stats = this.stats;
-      stats.time('Rendering');
-
-      gfx.beginDrawing(viewport);
-
-      var startIdx = 0;
-      var length = this.operatorList.fnArray.length;
-      var operatorList = this.operatorList;
-      var stepper = null;
-      if (PDFJS.pdfBug && StepperManager.enabled) {
-        stepper = StepperManager.create(this.pageNumber);
-        stepper.init(operatorList);
-        stepper.nextBreakPoint = stepper.getNextBreakPoint();
-      }
-
-      var self = this;
-      function next() {
-        startIdx =
-          gfx.executeOperatorList(operatorList, startIdx, next, stepper);
-        if (startIdx == length) {
-          gfx.endDrawing();
-          stats.timeEnd('Rendering');
-          stats.timeEnd('Overall');
-          if (callback) callback();
-        }
-      }
-      next();
-    },
-
-    getTextContent: function() {
-      var promise = new PDFJS.Promise();
-      var textContent = 'page text'; // not implemented
-      promise.resolve(textContent);
-      return promise;
-    },
-    getOperationList: function() {
-      var promise = new PDFJS.Promise();
-      var operationList = { // not implemented
-        dependencyFontsID: null,
-        operatorList: null
-      };
-      promise.resolve(operationList);
-      return promise;
-    }
-  };
-
-  function PdfDocumentWrapper(pdfInfo, transport) {
-    this.pdfInfo = pdfInfo;
-    this.transport = transport;
-  }
-  PdfDocumentWrapper.prototype = {
-    get numPages() {
-      return this.pdfInfo.numPages;
-    },
-    get fingerprint() {
-      return this.pdfInfo.fingerprint;
-    },
-    getPage: function(number) {
-      return this.transport.getPage(number);
-    },
-    getDestinations: function() {
-      var promise = new PDFJS.Promise();
-      var destinations = this.pdfInfo.destinations;
-      promise.resolve(destinations);
-      return promise;
-    },
-    getOutline: function() {
-      var promise = new PDFJS.Promise();
-      var outline = this.pdfInfo.outline;
-      promise.resolve(outline);
-      return promise;
-    },
-    getMetadata: function() {
-      var promise = new PDFJS.Promise();
-      var info = this.pdfInfo.info;
-      var metadata = this.pdfInfo.metadata;
-      promise.resolve({
-        info: info,
-        metadata: metadata ? new PDFJS.Metadata(metadata) : null
-      });
-      return promise;
-    },
-    destroy: function() {
-      this.transport.destroy();
-    }
-  };
-
-  PDFJS.getDocument = function getDocument(source) {
-    var promise = new PDFJS.Promise();
-    var transport = new WorkerTransport(promise);
-    if (typeof source === 'string') {
-      // fetch url
-      PDFJS.getPdf(
-        {
-          url: source,
-          progress: function getPdfProgress(evt) {
-            if (evt.lengthComputable)
-              promise.progress({
-                loaded: evt.loaded,
-                total: evt.total
-              });
-          },
-          error: function getPdfError(e) {
-            promise.reject('Unexpected server response of ' +
-              e.target.status + '.');
-          }
-        },
-        function getPdfLoad(data) {
-          transport.sendData(data);
-        });
-    } else {
-      // assuming the source is array, instantiating directly from it
-      transport.sendData(source);
-    }
-    return promise;
-  };
 })();
-
diff --git a/src/core.js b/src/core.js
index 1aa560a46..ed35ce49e 100644
--- a/src/core.js
+++ b/src/core.js
@@ -311,20 +311,20 @@ var Page = (function PageClosure() {
 })();
 
 /**
- * The `PDFDocModel` holds all the data of the PDF file. Compared to the
+ * The `PDFDocument` holds all the data of the PDF file. Compared to the
  * `PDFDoc`, this one doesn't have any job management code.
- * Right now there exists one PDFDocModel on the main thread + one object
+ * Right now there exists one PDFDocument on the main thread + one object
  * for each worker. If there is no worker support enabled, there are two
- * `PDFDocModel` objects on the main thread created.
+ * `PDFDocument` objects on the main thread created.
  */
-var PDFDocModel = (function PDFDocModelClosure() {
-  function PDFDocModel(arg, callback) {
+var PDFDocument = (function PDFDocumentClosure() {
+  function PDFDocument(arg, callback) {
     if (isStream(arg))
       init.call(this, arg);
     else if (isArrayBuffer(arg))
       init.call(this, new Stream(arg));
     else
-      error('PDFDocModel: Unknown argument type');
+      error('PDFDocument: Unknown argument type');
   }
 
   function init(stream) {
@@ -350,7 +350,7 @@ var PDFDocModel = (function PDFDocModelClosure() {
     return true; /* found */
   }
 
-  PDFDocModel.prototype = {
+  PDFDocument.prototype = {
     get linearization() {
       var length = this.stream.length;
       var linearization = false;
@@ -411,7 +411,7 @@ var PDFDocModel = (function PDFDocModelClosure() {
     },
     // Find the header, remove leading garbage and setup the stream
     // starting from the header.
-    checkHeader: function PDFDocModel_checkHeader() {
+    checkHeader: function PDFDocument_checkHeader() {
       var stream = this.stream;
       stream.reset();
       if (find(stream, '%PDF-', 1024)) {
@@ -421,7 +421,7 @@ var PDFDocModel = (function PDFDocModelClosure() {
       }
       // May not be a PDF file, continue anyway.
     },
-    setup: function PDFDocModel_setup(ownerPassword, userPassword) {
+    setup: function PDFDocument_setup(ownerPassword, userPassword) {
       this.checkHeader();
       var xref = new XRef(this.stream,
                           this.startXRef,
@@ -435,7 +435,7 @@ var PDFDocModel = (function PDFDocModelClosure() {
       // shadow the prototype getter
       return shadow(this, 'numPages', num);
     },
-    getDocumentInfo: function PDFDocModel_getDocumentInfo() {
+    getDocumentInfo: function PDFDocument_getDocumentInfo() {
       var info;
       if (this.xref.trailer.has('Info')) {
         var infoDict = this.xref.trailer.get('Info');
@@ -449,7 +449,7 @@ var PDFDocModel = (function PDFDocModelClosure() {
 
       return shadow(this, 'getDocumentInfo', info);
     },
-    getFingerprint: function PDFDocModel_getFingerprint() {
+    getFingerprint: function PDFDocument_getFingerprint() {
       var xref = this.xref, fileID;
       if (xref.trailer.has('ID')) {
         fileID = '';
@@ -470,10 +470,10 @@ var PDFDocModel = (function PDFDocModelClosure() {
 
       return shadow(this, 'getFingerprint', fileID);
     },
-    getPage: function PDFDocModel_getPage(n) {
+    getPage: function PDFDocument_getPage(n) {
       return this.catalog.getPage(n);
     }
   };
 
-  return PDFDocModel;
+  return PDFDocument;
 })();
diff --git a/src/image.js b/src/image.js
index 035e2f754..c8c19f9e5 100644
--- a/src/image.js
+++ b/src/image.js
@@ -15,7 +15,7 @@ var PDFImage = (function PDFImageClosure() {
       var colorSpace = dict.get('ColorSpace', 'CS');
       colorSpace = ColorSpace.parse(colorSpace, xref, res);
       var numComps = colorSpace.numComps;
-      handler.send('jpeg_decode', [image.getIR(), numComps], function(message) {
+      handler.send('JpegDecode', [image.getIR(), numComps], function(message) {
         var data = message.data;
         var stream = new Stream(data, 0, data.length, image.dict);
         promise.resolve(stream);
diff --git a/src/worker.js b/src/worker.js
index f61e4b509..2075ff0eb 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -85,10 +85,10 @@ var WorkerMessageHandler = {
       handler.send('test', data instanceof Uint8Array);
     });
 
-    handler.on('getdoc_request', function wphSetupDoc(data) {
+    handler.on('GetDocRequest', function wphSetupDoc(data) {
       // Create only the model of the PDFDoc, which is enough for
       // processing the content of the pdf.
-      pdfModel = new PDFDocModel(new Stream(data));
+      pdfModel = new PDFDocument(new Stream(data));
       var doc = {
         numPages: pdfModel.numPages,
         fingerprint: pdfModel.fingerprint,
@@ -97,10 +97,10 @@ var WorkerMessageHandler = {
         info: pdfModel.info,
         metadata: pdfModel.catalog.metadata
       };
-      handler.send('getdoc', {pdfInfo: doc});
+      handler.send('GetDoc', {pdfInfo: doc});
     });
 
-    handler.on('getpage_request', function wphSetupTest(data) {
+    handler.on('GetPageRequest', function wphSetupTest(data) {
       var pageNumber = data.pageIndex + 1;
       var pdfPage = pdfModel.getPage(pageNumber);
       var page = {
@@ -110,10 +110,10 @@ var WorkerMessageHandler = {
         view: pdfPage.view,
         annotations: pdfPage.getAnnotations()
       };
-      handler.send('getpage', {pageInfo: page});
+      handler.send('GetPage', {pageInfo: page});
     });
 
-    handler.on('renderpage_request', function wphSetupPageRequest(data) {
+    handler.on('RenderPageRequest', function wphSetupPageRequest(data) {
       var pageNum = data.pageIndex + 1;
 
 
@@ -152,7 +152,7 @@ var WorkerMessageHandler = {
           };
         }
 
-        handler.send('page_error', {
+        handler.send('PageError', {
           pageNum: pageNum,
           error: e
         });
@@ -171,7 +171,7 @@ var WorkerMessageHandler = {
         }
       }
 
-      handler.send('renderpage', {
+      handler.send('RenderPage', {
         pageIndex: data.pageIndex,
         operatorList: operatorList,
         depFonts: Object.keys(fonts)

From 7c35f10af84776b709bdd155a3cd794519f142e1 Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Thu, 12 Apr 2012 13:04:03 -0700
Subject: [PATCH 14/29] Fix thumbnail view.

---
 src/core.js   |  4 ----
 web/viewer.js | 19 +++++++++++++------
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/src/core.js b/src/core.js
index ed35ce49e..bba95ab06 100644
--- a/src/core.js
+++ b/src/core.js
@@ -300,10 +300,6 @@ var Page = (function PageClosure() {
         items.push(item);
       }
       return items;
-    },
-    startRendering: function Page_startRendering(ctx, viewport,
-                                                 callback, textLayer)  {
-/// DELETE
     }
   };
 
diff --git a/web/viewer.js b/web/viewer.js
index bda342aa7..4a6a91e7a 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -1036,9 +1036,9 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) {
   this.id = id;
 
   var maxThumbSize = 134;
-  var canvasWidth = pageRatio >= 1 ? maxThumbSize :
+  var canvasWidth = this.width = pageRatio >= 1 ? maxThumbSize :
     maxThumbSize * pageRatio;
-  var canvasHeight = pageRatio <= 1 ? maxThumbSize :
+  var canvasHeight = this.height = pageRatio <= 1 ? maxThumbSize :
     maxThumbSize / pageRatio;
   var scaleX = this.scaleX = (canvasWidth / pageWidth);
   var scaleY = this.scaleY = (canvasHeight / pageHeight);
@@ -1083,11 +1083,18 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) {
 
     var ctx = getPageDrawContext();
     var drawViewport = pdfPage.getViewport(scaleX);
-    page.startRendering(ctx, drawViewport,
-      function thumbnailViewDrawStartRendering() {
+    var renderContext = {
+      canvasContext: ctx,
+      viewport: drawViewport
+    };
+    pdfPage.render(renderContext).then(
+      function pdfPageRenderCallback() {
         callback();
-      });
-
+      },
+      function pdfPageRenderError(error) {
+        callback();
+      }
+    );
     this.hasImage = true;
   };
 

From 494fd1ccf9eff089f1176bf8199ce15e9fe0488f Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Thu, 12 Apr 2012 14:02:47 -0700
Subject: [PATCH 15/29] Fixes make files, removes stats from backend, stepper

---
 Makefile        |  1 +
 make.js         |  1 +
 src/api.js      |  3 ++-
 src/core.js     |  5 -----
 web/debugger.js | 32 ++++++++++++++++----------------
 5 files changed, 20 insertions(+), 22 deletions(-)

diff --git a/Makefile b/Makefile
index 3cc423350..d4457e08f 100644
--- a/Makefile
+++ b/Makefile
@@ -20,6 +20,7 @@ all: bundle
 PDF_JS_FILES = \
   core.js \
   util.js \
+  api.js \
   canvas.js \
   obj.js \
   function.js \
diff --git a/make.js b/make.js
index e0975fec8..2ee0d4cbd 100755
--- a/make.js
+++ b/make.js
@@ -79,6 +79,7 @@ target.bundle = function() {
   var SRC_FILES =
        ['core.js',
         'util.js',
+        'api.js',
         'canvas.js',
         'obj.js',
         'function.js',
diff --git a/src/api.js b/src/api.js
index 72d8cae66..b14ea138d 100644
--- a/src/api.js
+++ b/src/api.js
@@ -80,6 +80,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
     this.pageInfo = pageInfo;
     this.transport = transport;
     this._stats = new StatTimer();
+    this._stats.enabled = !!globalScope.PDFJS.enableStats;
     this.objs = transport.objs;
   }
   PDFPageProxy.prototype = {
@@ -206,7 +207,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
       var operatorList = this.operatorList;
       var stepper = null;
       if (PDFJS.pdfBug && StepperManager.enabled) {
-        stepper = StepperManager.create(this.pageNumber);
+        stepper = StepperManager.create(this.pageNumber - 1);
         stepper.init(operatorList);
         stepper.nextBreakPoint = stepper.getNextBreakPoint();
       }
diff --git a/src/core.js b/src/core.js
index bba95ab06..41f9a9c61 100644
--- a/src/core.js
+++ b/src/core.js
@@ -63,8 +63,6 @@ var Page = (function PageClosure() {
   function Page(xref, pageNumber, pageDict, ref) {
     this.pageNumber = pageNumber;
     this.pageDict = pageDict;
-    this.stats = new StatTimer();
-    this.stats.enabled = !!globalScope.PDFJS.enableStats;
     this.xref = xref;
     this.ref = ref;
 
@@ -139,8 +137,6 @@ var Page = (function PageClosure() {
         return this.operatorList;
       }
 
-      this.stats.time('Build IR Queue');
-
       var xref = this.xref;
       var content = this.content;
       var resources = this.resources;
@@ -159,7 +155,6 @@ var Page = (function PageClosure() {
                                 xref, handler, 'p' + this.pageNumber + '_');
 
       this.operatorList = pe.getOperatorList(content, resources, dependency);
-      this.stats.timeEnd('Build IR Queue');
       return this.operatorList;
     },
 
diff --git a/web/debugger.js b/web/debugger.js
index 00f5f6fd4..610a63854 100644
--- a/web/debugger.js
+++ b/web/debugger.js
@@ -163,29 +163,29 @@ var StepperManager = (function StepperManagerClosure() {
     enabled: false,
     active: false,
     // Stepper specific functions.
-    create: function create(pageNumber) {
+    create: function create(pageIndex) {
       var debug = document.createElement('div');
-      debug.id = 'stepper' + pageNumber;
+      debug.id = 'stepper' + pageIndex;
       debug.setAttribute('hidden', true);
       debug.className = 'stepper';
       stepperDiv.appendChild(debug);
       var b = document.createElement('option');
-      b.textContent = 'Page ' + (pageNumber + 1);
-      b.value = pageNumber;
+      b.textContent = 'Page ' + (pageIndex + 1);
+      b.value = pageIndex;
       stepperChooser.appendChild(b);
-      var initBreakPoints = breakPoints[pageNumber] || [];
-      var stepper = new Stepper(debug, pageNumber, initBreakPoints);
+      var initBreakPoints = breakPoints[pageIndex] || [];
+      var stepper = new Stepper(debug, pageIndex, initBreakPoints);
       steppers.push(stepper);
       if (steppers.length === 1)
-        this.selectStepper(pageNumber, false);
+        this.selectStepper(pageIndex, false);
       return stepper;
     },
-    selectStepper: function selectStepper(pageNumber, selectPanel) {
+    selectStepper: function selectStepper(pageIndex, selectPanel) {
       if (selectPanel)
         this.manager.selectPanel(1);
       for (var i = 0; i < steppers.length; ++i) {
         var stepper = steppers[i];
-        if (stepper.pageNumber == pageNumber)
+        if (stepper.pageIndex == pageIndex)
           stepper.panel.removeAttribute('hidden');
         else
           stepper.panel.setAttribute('hidden', true);
@@ -193,11 +193,11 @@ var StepperManager = (function StepperManagerClosure() {
       var options = stepperChooser.options;
       for (var i = 0; i < options.length; ++i) {
         var option = options[i];
-        option.selected = option.value == pageNumber;
+        option.selected = option.value == pageIndex;
       }
     },
-    saveBreakPoints: function saveBreakPoints(pageNumber, bps) {
-      breakPoints[pageNumber] = bps;
+    saveBreakPoints: function saveBreakPoints(pageIndex, bps) {
+      breakPoints[pageIndex] = bps;
       sessionStorage.setItem('pdfjsBreakPoints', JSON.stringify(breakPoints));
     }
   };
@@ -205,12 +205,12 @@ var StepperManager = (function StepperManagerClosure() {
 
 // The stepper for each page's IRQueue.
 var Stepper = (function StepperClosure() {
-  function Stepper(panel, pageNumber, initialBreakPoints) {
+  function Stepper(panel, pageIndex, initialBreakPoints) {
     this.panel = panel;
     this.len;
     this.breakPoint = 0;
     this.nextBreakPoint = null;
-    this.pageNumber = pageNumber;
+    this.pageIndex = pageIndex;
     this.breakPoints = initialBreakPoints;
     this.currentIdx = -1;
   }
@@ -256,7 +256,7 @@ var Stepper = (function StepperClosure() {
               self.breakPoints.push(x);
             else
               self.breakPoints.splice(self.breakPoints.indexOf(x), 1);
-            StepperManager.saveBreakPoints(self.pageNumber, self.breakPoints);
+            StepperManager.saveBreakPoints(self.pageIndex, self.breakPoints);
           }
         })(i);
 
@@ -278,7 +278,7 @@ var Stepper = (function StepperClosure() {
       return null;
     },
     breakIt: function breakIt(idx, callback) {
-      StepperManager.selectStepper(this.pageNumber, true);
+      StepperManager.selectStepper(this.pageIndex, true);
       var self = this;
       var dom = document;
       self.currentIdx = idx;

From 07fc34551d7785433a6d2d0d6ca79d2e32220b17 Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Thu, 12 Apr 2012 14:07:11 -0700
Subject: [PATCH 16/29] Minor clean up.

---
 src/api.js | 29 ++++++++++-------------------
 1 file changed, 10 insertions(+), 19 deletions(-)

diff --git a/src/api.js b/src/api.js
index 72d8cae66..841f3fe00 100644
--- a/src/api.js
+++ b/src/api.js
@@ -79,7 +79,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
   function PDFPageProxy(pageInfo, transport) {
     this.pageInfo = pageInfo;
     this.transport = transport;
-    this._stats = new StatTimer();
+    this.stats = new StatTimer();
     this.objs = transport.objs;
   }
   PDFPageProxy.prototype = {
@@ -89,9 +89,6 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
     get rotate() {
       return this.pageInfo.rotate;
     },
-    get stats() {
-      return this._stats;
-    },
     get ref() {
       return this.pageInfo.ref;
     },
@@ -124,12 +121,12 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
         });
       }
 
-      var callback = (function complete(error) {
-          if (error)
-            promise.reject(error);
-          else
-            promise.resolve();
-        });
+      function complete(error) {
+        if (error)
+          promise.reject(error);
+        else
+          promise.resolve();
+      };
 
       // Once the operatorList and fonts are loaded, do the actual rendering.
       this.displayReadyPromise.then(
@@ -137,19 +134,13 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
           var gfx = new CanvasGraphics(renderContext.canvasContext,
             this.objs, renderContext.textLayer);
           try {
-            this.display(gfx, renderContext.viewport, callback);
+            this.display(gfx, renderContext.viewport, complete);
           } catch (e) {
-            if (callback)
-              callback(e);
-            else
-              error(e);
+            complete(e);
           }
         }.bind(this),
         function pageDisplayReadPromiseError(reason) {
-          if (callback)
-            callback(reason);
-          else
-            error(reason);
+          complete(reason);
         }
       );
 

From 23df48bf0e540277348121603fcd0c368fe87ff1 Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Thu, 12 Apr 2012 15:14:18 -0700
Subject: [PATCH 17/29] Fix page error handling.

---
 src/api.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/api.js b/src/api.js
index 05e8a952f..f1baefade 100644
--- a/src/api.js
+++ b/src/api.js
@@ -385,7 +385,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
       }, this);
 
       messageHandler.on('PageError', function transportError(data) {
-        var page = this.pageCache[data.pageNum];
+        var page = this.pageCache[data.pageNum - 1];
         if (page.displayReadyPromise)
           page.displayReadyPromise.reject(data.error);
         else

From eba8f5a22cc8997a73947ba5cc023edf8c50cc9d Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Thu, 12 Apr 2012 15:14:18 -0700
Subject: [PATCH 18/29] Fix finger print, remove unused code

---
 src/worker.js | 2 +-
 web/viewer.js | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/worker.js b/src/worker.js
index 2075ff0eb..d7b9b5718 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -91,7 +91,7 @@ var WorkerMessageHandler = {
       pdfModel = new PDFDocument(new Stream(data));
       var doc = {
         numPages: pdfModel.numPages,
-        fingerprint: pdfModel.fingerprint,
+        fingerprint: pdfModel.getFingerprint(),
         destinations: pdfModel.catalog.destinations,
         outline: pdfModel.catalog.documentOutline,
         info: pdfModel.info,
diff --git a/web/viewer.js b/web/viewer.js
index 4a6a91e7a..35ee38e42 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -860,7 +860,6 @@ var PageView = function pageView(container, pdfPage, id, scale,
   }
 
   this.getPagePoint = function pageViewGetPagePoint(x, y) {
-    var scale = PDFView.currentScale;
     return this.viewport.convertToPdfPoint(x, y);
   };
 

From dee158d80c926e02c7a7573bc3d87659b2e64408 Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Thu, 12 Apr 2012 15:56:17 -0700
Subject: [PATCH 19/29] Fix title info for PDF document

---
 src/worker.js | 2 +-
 web/viewer.js | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/worker.js b/src/worker.js
index d7b9b5718..5cecc6cf2 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -94,7 +94,7 @@ var WorkerMessageHandler = {
         fingerprint: pdfModel.getFingerprint(),
         destinations: pdfModel.catalog.destinations,
         outline: pdfModel.catalog.documentOutline,
-        info: pdfModel.info,
+        info: pdfModel.getDocumentInfo(),
         metadata: pdfModel.catalog.metadata
       };
       handler.send('GetDoc', {pdfInfo: doc});
diff --git a/web/viewer.js b/web/viewer.js
index 35ee38e42..5b43ee7e1 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -550,7 +550,8 @@ var PDFView = {
       self.setInitialView(storedHash, scale);
     });
 
-    pdfDocument.getMetadata().then(function(info, metadata) {
+    pdfDocument.getMetadata().then(function(data) {
+      var info = data.info, metadata = data.metadata;
       self.documentInfo = info;
       self.metadata = metadata;
 

From 3925e374177d9e5b8d470c92b8b23c31fdf11b4e Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Thu, 12 Apr 2012 17:59:30 -0700
Subject: [PATCH 20/29] Add basic api unit testing.

---
 test/pdfs/.gitignore        |   2 +-
 test/pdfs/basicapi.pdf      | Bin 0 -> 105779 bytes
 test/unit/api_spec.js       | 107 ++++++++++++++++++++++++++++++++++++
 test/unit/jsTestDriver.conf |  60 ++++++++++----------
 4 files changed, 139 insertions(+), 30 deletions(-)
 create mode 100644 test/pdfs/basicapi.pdf
 create mode 100644 test/unit/api_spec.js

diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore
index 2a7c27875..e4b9fb10c 100644
--- a/test/pdfs/.gitignore
+++ b/test/pdfs/.gitignore
@@ -31,4 +31,4 @@
 !issue1002.pdf
 !issue925.pdf
 !gradientfill.pdf
-
+!basicapi.pdf
diff --git a/test/pdfs/basicapi.pdf b/test/pdfs/basicapi.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..31ffcfe9feb708602cb42c25534eaa6ef12b2c25
GIT binary patch
literal 105779
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
BznTC5

literal 0
HcmV?d00001

diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js
new file mode 100644
index 000000000..72c6434b1
--- /dev/null
+++ b/test/unit/api_spec.js
@@ -0,0 +1,107 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+'use strict';
+
+describe('api', function() {
+  var basicApiUrl = '/basicapi.pdf';
+  function waitsForPromise(promise) {
+    waitsFor(function() {
+      return promise.isResolved || promise.isRejected;
+    }, 250);
+  }
+  function expectAfterPromise(promise, successCallback) {
+    waitsForPromise(promise);
+    runs(function() {
+      promise.then(successCallback,
+      function(error, e) {
+        // Shouldn't get here.
+        expect(false).toEqual(true);
+      });
+    });
+  }
+  describe('PDFJS', function() {
+    describe('getDocument', function() {
+      it('creates pdf doc from URL', function() {
+        console.log('what is');
+        debugger;
+        var promise = PDFJS.getDocument(basicApiUrl);
+        expectAfterPromise(promise, function(data) {
+          expect(true).toEqual(true);
+        });
+      });
+      /*
+      it('creates pdf doc from typed array', function() {
+        // TODO
+      });
+      */
+    });
+  });
+  describe('PDFDocument', function() {
+    var promise = PDFJS.getDocument(basicApiUrl);
+    waitsForPromise(promise);
+    var doc;
+    runs(function() {
+      promise.then(function(data) { doc = data; });
+    });
+    it('gets number of pages', function() {
+      expect(doc.numPages).toEqual(3);
+    });
+    it('gets fingerprint', function() {
+      expect(typeof doc.fingerprint).toEqual('string');
+    });
+    it('gets page', function() {
+      var promise = doc.getPage(1);
+      expectAfterPromise(promise, function(data) {
+        expect(true).toEqual(true);
+      });
+    });
+    it('gets destinations', function() {
+      var promise = doc.getDestinations();
+      expectAfterPromise(promise, function(data) {
+        // TODO this seems to be broken for the test pdf
+      });
+    });
+    it('gets outline', function() {
+      var promise = doc.getOutline();
+      expectAfterPromise(promise, function(outline) {
+        // Two top level entries.
+        expect(outline.length).toEqual(2);
+        // Make sure some basic attributes are set.
+        expect(outline[1].title).toEqual('Chapter 1');
+        expect(outline[1].items.length).toEqual(1);
+        expect(outline[1].items[0].title).toEqual('Paragraph 1.1');
+      });
+    });
+    it('gets metadata', function() {
+      var promise = doc.getMetadata();
+      expectAfterPromise(promise, function(metadata) {
+        expect(metadata.info['Title']).toEqual('Basic API Test');
+        expect(metadata.metadata.get('dc:title')).toEqual('Basic API Test');
+      });
+    });
+  });
+  describe('Page', function() {
+    var promise = new Promise();
+    PDFJS.getDocument(basicApiUrl).then(function(doc) {
+      doc.getPage(1).then(function(data) {
+        promise.resolve(data);
+      });
+    });
+    waitsForPromise(promise);
+    var page;
+    runs(function() {
+      promise.then(function(data) {
+        page = data;
+      });
+    });
+    it('gets ref', function() {
+      expect(page.ref).toEqual({num: 15, gen: 0});
+    });
+    // TODO rotate
+    // TODO viewport
+    // TODO annotaions
+    // TOOD text content
+    // TODO operation list
+  });
+});
diff --git a/test/unit/jsTestDriver.conf b/test/unit/jsTestDriver.conf
index 9a26df6a4..8ff218093 100644
--- a/test/unit/jsTestDriver.conf
+++ b/test/unit/jsTestDriver.conf
@@ -1,32 +1,34 @@
 server: http://localhost:4224
 
-load:
-  - ../../external/jasmine/jasmine.js
-  - ../../external/jasmineAdapter/JasmineAdapter.js
-  - ../../src/obj.js
-  - ../../src/core.js
-  - ../../src/util.js
-  - ../../src/canvas.js
-  - ../../src/obj.js
-  - ../../src/function.js
-  - ../../src/charsets.js
-  - ../../src/cidmaps.js
-  - ../../src/colorspace.js
-  - ../../src/crypto.js
-  - ../../src/evaluator.js
-  - ../../src/fonts.js
-  - ../../src/glyphlist.js
-  - ../../src/image.js
-  - ../../src/metrics.js
-  - ../../src/parser.js
-  - ../../src/pattern.js
-  - ../../src/stream.js
-  - ../../src/worker.js
-  - ../../src/bidi.js
-  - ../../external/jpgjs/jpg.js
-  - ../unit/obj_spec.js
-  - ../unit/font_spec.js
-  - ../unit/function_spec.js
-  - ../unit/crypto_spec.js
-  - ../unit/stream_spec.js
+basepath: ..
 
+load:
+  - ../external/jasmine/jasmine.js
+  - ../external/jasmineAdapter/JasmineAdapter.js
+  - ../src/obj.js
+  - ../src/core.js
+  - ../src/util.js
+  - ../src/api.js
+  - ../src/canvas.js
+  - ../src/obj.js
+  - ../src/function.js
+  - ../src/charsets.js
+  - ../src/cidmaps.js
+  - ../src/colorspace.js
+  - ../src/crypto.js
+  - ../src/evaluator.js
+  - ../src/fonts.js
+  - ../src/glyphlist.js
+  - ../src/image.js
+  - ../src/metrics.js
+  - ../src/parser.js
+  - ../src/pattern.js
+  - ../src/stream.js
+  - ../src/worker.js
+  - ../src/bidi.js
+  - ../src/metadata.js
+  - ../external/jpgjs/jpg.js
+  - unit/api_spec.js
+
+gateway:
+ - {matcher: "*.pdf", server: "http://localhost:8888/test/pdfs/"}

From 19c0c6a983562294251bfa2fa02a1b2a71bc876c Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Thu, 12 Apr 2012 18:09:25 -0700
Subject: [PATCH 21/29] Add back other unit tests. Disable worker.

---
 test/unit/api_spec.js       | 2 ++
 test/unit/jsTestDriver.conf | 5 +++++
 2 files changed, 7 insertions(+)

diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js
index 72c6434b1..318dbb42a 100644
--- a/test/unit/api_spec.js
+++ b/test/unit/api_spec.js
@@ -4,6 +4,8 @@
 'use strict';
 
 describe('api', function() {
+  // TODO run with worker enabled
+  PDFJS.disableWorker = true;
   var basicApiUrl = '/basicapi.pdf';
   function waitsForPromise(promise) {
     waitsFor(function() {
diff --git a/test/unit/jsTestDriver.conf b/test/unit/jsTestDriver.conf
index 8ff218093..b0f917b66 100644
--- a/test/unit/jsTestDriver.conf
+++ b/test/unit/jsTestDriver.conf
@@ -28,6 +28,11 @@ load:
   - ../src/bidi.js
   - ../src/metadata.js
   - ../external/jpgjs/jpg.js
+  - unit/obj_spec.js
+  - unit/font_spec.js
+  - unit/function_spec.js
+  - unit/crypto_spec.js
+  - unit/stream_spec.js
   - unit/api_spec.js
 
 gateway:

From c207d4a7d6e383de4c9b1b1eedbda6f56860f1b7 Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Fri, 13 Apr 2012 09:25:08 -0700
Subject: [PATCH 22/29] Add docs to API.

---
 src/api.js | 118 +++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 109 insertions(+), 9 deletions(-)

diff --git a/src/api.js b/src/api.js
index f1baefade..74c58a61d 100644
--- a/src/api.js
+++ b/src/api.js
@@ -1,6 +1,16 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
+/**
+ * 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} source Either a url to a PDF is located or a
+ * typed array already populated with data.
+ * @return {Promise} A promise that is resolved with {PDFDocumentProxy} object.
+ */
 PDFJS.getDocument = function getDocument(source) {
   var promise = new PDFJS.Promise();
   var transport = new WorkerTransport(promise);
@@ -31,33 +41,74 @@ PDFJS.getDocument = function getDocument(source) {
   return promise;
 };
 
+/**
+ * Proxy to a PDFDocument in the worker thread. Also, contains commonly used
+ * properties that can be read synchronously.
+ */
 var PDFDocumentProxy = (function() {
   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;
     },
+    /**
+     * @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(number) {
       return this.transport.getPage(number);
     },
+    /**
+     * @return {Promise} A promise that is resolved with a lookup table for
+     * mapping named destinations to reference numbers.
+     */
     getDestinations: function() {
       var promise = new PDFJS.Promise();
       var destinations = this.pdfInfo.destinations;
       promise.resolve(destinations);
       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() {
       var promise = new PDFJS.Promise();
       var outline = this.pdfInfo.outline;
       promise.resolve(outline);
       return promise;
     },
+    /**
+     * @return {Promise} A promise that is resolved with an {object} that has
+     * info and metadata properties.  Info is an {object} filled with anything
+     * available in the information dictionary and similarly metadata is a
+     * {Metadata} object with information from the metadata section of the PDF.
+     */
     getMetadata: function() {
       var promise = new PDFJS.Promise();
       var info = this.pdfInfo.info;
@@ -84,30 +135,66 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
     this.objs = transport.objs;
   }
   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(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() {
       var promise = new PDFJS.Promise();
       var annotations = this.pageInfo.annotations;
       promise.resolve(annotations);
       return promise;
     },
-    render: function(renderContext) {
+    /**
+     * 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.
+     * }
+     * @return {Promise} A promise that is resolved when the page finishes
+     * rendering.
+     */
+    render: function(params) {
       var promise = new Promise();
       var stats = this.stats;
       stats.time('Overall');
@@ -132,10 +219,10 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
       // Once the operatorList and fonts are loaded, do the actual rendering.
       this.displayReadyPromise.then(
         function pageDisplayReadyPromise() {
-          var gfx = new CanvasGraphics(renderContext.canvasContext,
-            this.objs, renderContext.textLayer);
+          var gfx = new CanvasGraphics(params.canvasContext,
+            this.objs, params.textLayer);
           try {
-            this.display(gfx, renderContext.viewport, complete);
+            this.display(gfx, params.viewport, complete);
           } catch (e) {
             complete(e);
           }
@@ -147,7 +234,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
 
       return promise;
     },
-
+    /**
+     * For internal use only.
+     */
     startRenderingFromOperatorList:
       function PDFPageWrapper_startRenderingFromOperatorList(operatorList,
                                                              fonts) {
@@ -168,7 +257,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
         }
       );
     },
-
+    /**
+     * For internal use only.
+     */
     ensureFonts: function PDFPageWrapper_ensureFonts(fonts, callback) {
       this.stats.time('Font Loading');
       // Convert the font names to the corresponding font obj.
@@ -186,7 +277,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
         }.bind(this)
       );
     },
-
+    /**
+     * For internal use only.
+     */
     display: function PDFPageWrapper_display(gfx, viewport, callback) {
       var stats = this.stats;
       stats.time('Rendering');
@@ -216,13 +309,18 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
       }
       next();
     },
-
+    /**
+     * Stub for future feature.
+     */
     getTextContent: function() {
       var promise = new PDFJS.Promise();
       var textContent = 'page text'; // not implemented
       promise.resolve(textContent);
       return promise;
     },
+    /**
+     * Stub for future feature.
+     */
     getOperationList: function() {
       var promise = new PDFJS.Promise();
       var operationList = { // not implemented
@@ -235,7 +333,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
   };
   return PDFPageProxy;
 })();
-
+/**
+ * For internal use only.
+ */
 var WorkerTransport = (function WorkerTransportClosure() {
   function WorkerTransport(promise) {
     this.workerReadyPromise = promise;

From f679f0dfe8bc0f6d2f54a8f645576011ffcbd9ab Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Fri, 13 Apr 2012 09:33:36 -0700
Subject: [PATCH 23/29] Move open after everything is initialized.

---
 web/viewer.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/web/viewer.js b/web/viewer.js
index 5b43ee7e1..b1876c814 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -1284,7 +1284,6 @@ window.addEventListener('load', function webViewerLoad(evt) {
 
   var file = PDFJS.isFirefoxExtension ?
               window.location.toString() : params.file || kDefaultURL;
-  PDFView.open(file, 0);
 
   if (PDFJS.isFirefoxExtension || !window.File || !window.FileReader ||
       !window.FileList || !window.Blob) {
@@ -1316,6 +1315,7 @@ window.addEventListener('load', function webViewerLoad(evt) {
 
   var sidebarScrollView = document.getElementById('sidebarScrollView');
   sidebarScrollView.addEventListener('scroll', updateThumbViewArea, true);
+  PDFView.open(file, 0);
 }, true);
 
 /**

From e1b4fc5ac73c7466ef6b12b80e93119a9520531e Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Fri, 13 Apr 2012 16:04:57 -0500
Subject: [PATCH 24/29] Enabled workers during testing

---
 test/driver.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/driver.js b/test/driver.js
index be66aa216..26c5a156a 100644
--- a/test/driver.js
+++ b/test/driver.js
@@ -10,7 +10,7 @@
 // Disable worker support for running test as
 //   https://github.com/mozilla/pdf.js/pull/764#issuecomment-2638944
 //   "firefox-bin: Fatal IO error 12 (Cannot allocate memory) on X server :1."
-PDFJS.disableWorker = true;
+// PDFJS.disableWorker = true;
 
 var appPath, browser, canvas, currentTaskIdx, manifest, stdout;
 var inFlightRequests = 0;

From 42911f1fc975b6f87a39ddb7bf66dc44dfeae37d Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Sat, 14 Apr 2012 13:54:31 -0700
Subject: [PATCH 25/29] Async getAnnotations(); hide map and xref for Dict

---
 src/api.js       | 19 ++++++++++++--
 src/evaluator.js |  2 +-
 src/obj.js       | 64 +++++++++++++++++++++++++-----------------------
 src/worker.js    | 16 ++++++++----
 4 files changed, 63 insertions(+), 38 deletions(-)

diff --git a/src/api.js b/src/api.js
index f1baefade..479134bd2 100644
--- a/src/api.js
+++ b/src/api.js
@@ -102,9 +102,12 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
       return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
     },
     getAnnotations: function() {
+      if (this.annotationsPromise)
+        return this.annotationsPromise;
+
       var promise = new PDFJS.Promise();
-      var annotations = this.pageInfo.annotations;
-      promise.resolve(annotations);
+      this.annotationsPromise = promise;
+      this.transport.getAnnotations(this.pageInfo.pageIndex);
       return promise;
     },
     render: function(renderContext) {
@@ -209,6 +212,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
           gfx.executeOperatorList(operatorList, startIdx, next, stepper);
         if (startIdx == length) {
           gfx.endDrawing();
+          delete this.operatorList;
           stats.timeEnd('Rendering');
           stats.timeEnd('Overall');
           if (callback) callback();
@@ -342,6 +346,12 @@ var WorkerTransport = (function WorkerTransportClosure() {
         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('RenderPage', function transportRender(data) {
         var page = this.pageCache[data.pageIndex];
         var depFonts = data.depFonts;
@@ -440,6 +450,11 @@ var WorkerTransport = (function WorkerTransportClosure() {
       this.pagePromises[pageIndex] = promise;
       this.messageHandler.send('GetPageRequest', { pageIndex: pageIndex });
       return promise;
+    },
+
+    getAnnotations: function WorkerTransport_getAnnotations(pageIndex) {
+      this.messageHandler.send('GetAnnotationsRequest',
+        { pageIndex: pageIndex });
     }
   };
   return WorkerTransport;
diff --git a/src/evaluator.js b/src/evaluator.js
index 350ab20b2..50274a9ed 100644
--- a/src/evaluator.js
+++ b/src/evaluator.js
@@ -466,7 +466,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
           args = [];
         } else if (obj != null) {
           assertWellFormed(args.length <= 33, 'Too many arguments');
-          args.push(obj);
+          args.push(obj instanceof Dict ? obj.getAll() : obj);
         }
       }
 
diff --git a/src/obj.js b/src/obj.js
index 200b40a7f..c905a7dc5 100644
--- a/src/obj.js
+++ b/src/obj.js
@@ -37,51 +37,55 @@ var Dict = (function DictClosure() {
   // xref is optional
   function Dict(xref) {
     // Map should only be used internally, use functions below to access.
-    this.map = Object.create(null);
-    this.xref = xref;
-  }
+    var map = Object.create(null);
+
+    this.assignXref = function Dict_assingXref(newXref) {
+      xref = newXref;
+    };
 
-  Dict.prototype = {
     // automatically dereferences Ref objects
-    get: function Dict_get(key1, key2, key3) {
+    this.get = function Dict_get(key1, key2, key3) {
       var value;
-      var xref = this.xref;
-      if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map ||
+      if (typeof (value = map[key1]) != 'undefined' || key1 in map ||
           typeof key2 == 'undefined') {
-        return xref ? this.xref.fetchIfRef(value) : value;
+        return xref ? xref.fetchIfRef(value) : value;
       }
-      if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map ||
+      if (typeof (value = map[key2]) != 'undefined' || key2 in map ||
           typeof key3 == 'undefined') {
-        return xref ? this.xref.fetchIfRef(value) : value;
+        return xref ? xref.fetchIfRef(value) : value;
       }
-      value = this.map[key3] || null;
-      return xref ? this.xref.fetchIfRef(value) : value;
-    },
+      value = map[key3] || null;
+      return xref ? xref.fetchIfRef(value) : value;
+    };
+
     // no dereferencing
-    getRaw: function Dict_getRaw(key) {
-      return this.map[key];
-    },
+    this.getRaw = function Dict_getRaw(key) {
+      return map[key];
+    };
+
     // creates new map and dereferences all Refs
-    getAll: function Dict_getAll() {
+    this.getAll = function Dict_getAll() {
       var all = {};
-      for (var key in this.map)
-        all[key] = this.get(key);
+      for (var key in map) {
+        var obj = this.get(key);
+        all[key] = obj instanceof Dict ? obj.getAll() : obj;
+      }
       return all;
-    },
+    };
 
-    set: function Dict_set(key, value) {
-      this.map[key] = value;
-    },
+    this.set = function Dict_set(key, value) {
+      map[key] = value;
+    };
 
-    has: function Dict_has(key) {
-      return key in this.map;
-    },
+    this.has = function Dict_has(key) {
+      return key in map;
+    };
 
-    forEach: function Dict_forEach(callback) {
-      for (var key in this.map) {
+    this.forEach = function Dict_forEach(callback) {
+      for (var key in map) {
         callback(key, this.get(key));
       }
-    }
+    };
   };
 
   return Dict;
@@ -299,7 +303,7 @@ var XRef = (function XRefClosure() {
     this.entries = [];
     this.xrefstms = {};
     var trailerDict = this.readXRef(startXRef);
-    trailerDict.xref = this;
+    trailerDict.assignXref(this);
     this.trailer = trailerDict;
     // prepare the XRef cache
     this.cache = [];
diff --git a/src/worker.js b/src/worker.js
index 5cecc6cf2..25f3f52cd 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -100,20 +100,27 @@ var WorkerMessageHandler = {
       handler.send('GetDoc', {pdfInfo: doc});
     });
 
-    handler.on('GetPageRequest', function wphSetupTest(data) {
+    handler.on('GetPageRequest', function wphSetupGetPage(data) {
       var pageNumber = data.pageIndex + 1;
       var pdfPage = pdfModel.getPage(pageNumber);
       var page = {
         pageIndex: data.pageIndex,
         rotate: pdfPage.rotate,
         ref: pdfPage.ref,
-        view: pdfPage.view,
-        annotations: pdfPage.getAnnotations()
+        view: pdfPage.view
       };
       handler.send('GetPage', {pageInfo: page});
     });
 
-    handler.on('RenderPageRequest', function wphSetupPageRequest(data) {
+    handler.on('GetAnnotationsRequest', function wphSetupGetAnnotations(data) {
+      var pdfPage = pdfModel.getPage(data.pageIndex + 1);
+      handler.send('GetAnnotations', {
+        pageIndex: data.pageIndex,
+        annotations: pdfPage.getAnnotations()
+      });
+    });
+
+    handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
       var pageNum = data.pageIndex + 1;
 
 
@@ -170,7 +177,6 @@ var WorkerMessageHandler = {
           fonts[dep] = true;
         }
       }
-
       handler.send('RenderPage', {
         pageIndex: data.pageIndex,
         operatorList: operatorList,

From 6bf640260fec1ee16226613e50d96f58fd4bfc08 Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Sat, 14 Apr 2012 17:52:49 -0700
Subject: [PATCH 26/29] Fix jsdoc comment; remove resources dict from type3
 properties

---
 src/api.js       | 7 ++++++-
 src/evaluator.js | 1 -
 src/fonts.js     | 1 -
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/api.js b/src/api.js
index 996dd1b42..0e27d2369 100644
--- a/src/api.js
+++ b/src/api.js
@@ -193,7 +193,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
      *   canvasContext(required): A 2D context of a DOM Canvas object.,
      *   textLayer(optional): An object that has beginLayout, endLayout, and
      *                        appendText functions.
-     * }
+     * }.
      * @return {Promise} A promise that is resolved when the page finishes
      * rendering.
      */
@@ -415,6 +415,11 @@ var WorkerTransport = (function WorkerTransportClosure() {
       var fakeWorker = {
         postMessage: function WorkerTransport_postMessage(obj) {
           fakeWorker.onmessage({data: obj});
+          try {
+          testF.contentWindow.postMessage(obj, "*");
+          } catch(e) {
+          debugger;
+          }
         },
         terminate: function WorkerTransport_terminate() {}
       };
diff --git a/src/evaluator.js b/src/evaluator.js
index 50274a9ed..c57e291c0 100644
--- a/src/evaluator.js
+++ b/src/evaluator.js
@@ -862,7 +862,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
         properties.coded = true;
         var charProcs = dict.get('CharProcs').getAll();
         var fontResources = dict.get('Resources') || resources;
-        properties.resources = fontResources;
         properties.charProcOperatorList = {};
         for (var key in charProcs) {
           var glyphStream = charProcs[key];
diff --git a/src/fonts.js b/src/fonts.js
index 7fdab8fbb..7693f5839 100644
--- a/src/fonts.js
+++ b/src/fonts.js
@@ -766,7 +766,6 @@ var Font = (function FontClosure() {
     this.name = name;
     this.coded = properties.coded;
     this.charProcOperatorList = properties.charProcOperatorList;
-    this.resources = properties.resources;
     this.sizes = [];
 
     var names = name.split('+');

From 12b0282836d5fb9ee3d72106e7a7897150c05993 Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Sat, 14 Apr 2012 17:57:14 -0500
Subject: [PATCH 27/29] Remove debug code

---
 src/api.js | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/src/api.js b/src/api.js
index 0e27d2369..18644ebe6 100644
--- a/src/api.js
+++ b/src/api.js
@@ -415,11 +415,6 @@ var WorkerTransport = (function WorkerTransportClosure() {
       var fakeWorker = {
         postMessage: function WorkerTransport_postMessage(obj) {
           fakeWorker.onmessage({data: obj});
-          try {
-          testF.contentWindow.postMessage(obj, "*");
-          } catch(e) {
-          debugger;
-          }
         },
         terminate: function WorkerTransport_terminate() {}
       };

From 50349658affcb3bfa18705c952563289fff14537 Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Sun, 15 Apr 2012 21:12:00 -0500
Subject: [PATCH 28/29] Temporary avoiding chrome on linux failures

---
 test/test_manifest.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/test/test_manifest.json b/test/test_manifest.json
index 6a083bdf7..207c41c22 100644
--- a/test/test_manifest.json
+++ b/test/test_manifest.json
@@ -29,6 +29,7 @@
        "file": "pdfs/pdf.pdf",
        "md5": "dbdb23c939d2be09b43126c3c56060c7",
        "link": true,
+       "pageLimit": 500,
        "rounds": 1,
        "type": "load"
     },

From 04c8d1454d9fa30c376b08b667184c6bf449819e Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Mon, 16 Apr 2012 09:45:49 -0700
Subject: [PATCH 29/29] Add Util functions to PDFJS.

---
 src/util.js   | 2 +-
 web/viewer.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/util.js b/src/util.js
index 6ec4bc9cb..63f6115a7 100644
--- a/src/util.js
+++ b/src/util.js
@@ -76,7 +76,7 @@ function stringToBytes(str) {
 
 var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
 
-var Util = (function UtilClosure() {
+var Util = PDFJS.Util = (function UtilClosure() {
   function Util() {}
 
   Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
diff --git a/web/viewer.js b/web/viewer.js
index b1876c814..68f0a6a33 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -787,7 +787,7 @@ var PageView = function pageView(container, pdfPage, id, scale,
     }
     function createElementWithStyle(tagName, item) {
       var rect = viewport.convertToViewportRectangle(item.rect);
-      rect = Util.normalizeRect(rect);
+      rect = PDFJS.Util.normalizeRect(rect);
       var element = document.createElement(tagName);
       element.style.left = Math.floor(rect[0]) + 'px';
       element.style.top = Math.floor(rect[1]) + 'px';