From 71ff8ee5865a077f0235ec0065d87b3c61f9c7a2 Mon Sep 17 00:00:00 2001
From: Julian Viereck <julian.viereck@gmail.com>
Date: Mon, 5 Sep 2011 17:42:58 -0700
Subject: [PATCH] backup

---
 pdf.js                    | 60 ++++++++++++++-----------
 web/viewer.html           |  1 +
 worker.js                 | 32 ++++++++++++-
 worker/boot.js            | 63 ++++++++++++++++++++++++++
 worker/console.js         |  2 +-
 worker/message_handler.js | 23 ++++++++++
 worker/pdf.js             | 95 ---------------------------------------
 7 files changed, 154 insertions(+), 122 deletions(-)
 create mode 100644 worker/boot.js
 create mode 100644 worker/message_handler.js
 delete mode 100644 worker/pdf.js

diff --git a/pdf.js b/pdf.js
index bc75e8b52..39d36780f 100644
--- a/pdf.js
+++ b/pdf.js
@@ -3358,18 +3358,48 @@ var Page = (function() {
     },
 
     startRendering: function(canvasCtx, continuation) {
+      var gfx = new CanvasGraphics(canvasCtx);
+
+      // If there is already some code to render, then use it directly.
+      if (this.code) {
+        this.display(gfx);
+        return;
+      }
+      
       var self = this;
       var stats = self.stats;
       stats.compile = stats.fonts = stats.render = 0;
-
-      var gfx = new CanvasGraphics(canvasCtx);
+      
       var fonts = [];
       var images = new ImagesLoader();
 
-      this.compile(gfx, fonts, images);
+      var preCompilation = this.preCompile(gfx, fonts, images);
       stats.compile = Date.now();
+      
+      // Make a copy of the necessary datat to build a font later. The `font`
+      // object will be sent to the main thread later on.
+      var fontsBackup = fonts;
+      fonts = [];
+      for (var i = 0; i < fontsBackup.length; i++) {
+        var orgFont = fontsBackup[i];
+      
+        var font = {
+          name:       orgFont.name,
+          file:       orgFont.file,
+          properties: orgFont.properties
+        }
+        fonts.push(font);
+      }
 
+      this.startRenderingFromPreCompilation(gfx, preCompilation, fonts, images, continuation);
+    },
+    
+    startRenderingFromPreCompilation: function(gfx, preCompilation, fonts, images, continuation) {
+      var self = this;
+      
       var displayContinuation = function() {
+        self.code = gfx.postCompile(preCompilation);
+        
         // Always defer call to display() to work around bug in
         // Firefox error reporting from XHR callbacks.
         setTimeout(function() {
@@ -3384,22 +3414,6 @@ var Page = (function() {
         });
       };
       
-      // Make a copy of the necessary datat to build a font later. The `font`
-      // object will be sent to the main thread later on.
-      var fontsBackup = fonts;
-      fonts = [];
-      for (var i = 0; i < fontsBackup.length; i++) {
-        var orgFont = fontsBackup[i];
-        var orgFontObj = orgFont.fontObj;
-      
-        var font = {
-          name:       orgFont.name,
-          file:       orgFont.file,
-          properties: orgFont.properties
-        }
-        fonts.push(font);
-      }
-
       this.ensureFonts(fonts, function() {
         images.notifyOnLoad(function() {
           stats.images = Date.now();
@@ -3424,12 +3438,8 @@ var Page = (function() {
           content[i] = xref.fetchIfRef(content[i]);
         content = new StreamsSequenceStream(content);
       }
-      return gfx.preCompile(content, xref, resources, fonts, images);
-    },
-
-    compile: function(gfx, fonts, images) {
-      var preCompilation = this.preCompile(gfx, fonts, images);
-      this.code = gfx.postCompile(preCompilation);
+      return gfx.preCompile(content, xref, resources, fonts, images, 
+                this.pageNumber + "_");
     },
     
     ensureFonts: function(fonts, callback) {
diff --git a/web/viewer.html b/web/viewer.html
index d236f840e..871db8ce6 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -12,6 +12,7 @@
         <script type="text/javascript" src="../glyphlist.js"></script>
         <script type="text/javascript" src="../metrics.js"></script>
         <script type="text/javascript" src="../worker.js"></script>
+        <script type="text/javascript" src="../worker/message_handler.js"></script>
   </head>
 
   <body>
diff --git a/worker.js b/worker.js
index d26735005..61f8c0934 100644
--- a/worker.js
+++ b/worker.js
@@ -25,8 +25,21 @@ var WorkerPage = (function() {
     },
     
     startRendering: function(ctx, callback, errback)  {
+      this.ctx = ctx;
+      this.callback = callback;
       // TODO: Place the worker magic HERE.
-      this.page.startRendering(ctx, callback, errback);
+      // this.page.startRendering(ctx, callback, errback);
+      
+      this.workerPDF.startRendering(this)
+    },
+    
+    startRenderingFromPreCompilation: function(preCompilation, fonts, images) {
+      var gfx = new CanvasGraphics(this.ctx);
+      
+      // TODO: Add proper handling for images loaded by the worker.
+      var images = new ImagesLoader();
+      
+      this.page.startRenderingFromPreCompilation(gfx, preCompilation, fonts, images, this.callback);
     },
     
     getLinks: function() {
@@ -46,6 +59,19 @@ var WorkerPDFDoc = (function() {
     this.catalog = this.pdf.catalog;
     
     this.pageCache = [];
+    
+    this.worker = new Worker("worker/boot.js");
+    this.handler = new MessageHandler({
+      "page": function(data) {
+        var pageNum = data.pageNum;
+        var page = this.pageCache[pageNum];
+        
+        page.startRenderingFromPreCompilation(data.preCompilation, data.fonts, data.images);
+      }
+    }, this.worker.postMessage, this);
+    this.worker.onmessage = this.handler.onMessage;
+    
+    this.handler.send("doc", data);
   }
 
   constructor.prototype = {
@@ -53,6 +79,10 @@ var WorkerPDFDoc = (function() {
       return this.pdf.numPages;
     },
     
+    startRendering: function(page) {
+      this.handler.send("page", page.page.pageNumber);
+    },
+    
     getPage: function(n) {
       if (this.pageCache[n]) {
         return this.pageCache[n];
diff --git a/worker/boot.js b/worker/boot.js
new file mode 100644
index 000000000..4ec65a1de
--- /dev/null
+++ b/worker/boot.js
@@ -0,0 +1,63 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+'use strict';
+
+//
+importScripts('console.js');
+importScripts('event_handler.js');
+importScripts('../pdf.js');
+importScripts('../fonts.js');
+importScripts('../crypto.js');
+importScripts('../glyphlist.js');
+
+// Listen for messages from the main thread.
+var pdfDoc = null;
+
+var handler = new MessageHandler({
+  "doc": function(data) {
+    pdfDocument = new PDFDoc(new Stream(data));
+    console.log("setup pdfDoc");
+  },
+  
+  "page": function(pageNum) {
+    pageNum = parseInt(pageNum);
+    console.log("about to process page", pageNum);
+    
+    var page = pdfDocument.getPage(pageNum);
+    
+    // The following code does quite the same as Page.prototype.startRendering,
+    // but stops at one point and sends the result back to the main thread.
+    var gfx = new CanvasGraphics(canvasCtx);
+    var fonts = [];
+    // TODO: Figure out how image loading is handled inside the worker.
+    var images = new ImagesLoader();
+    
+    // Pre compile the pdf page and fetch the fonts/images.
+    var preCompilation = page.preCompile(gfx, fonts, images);
+    
+    // Extract the minimum of font data that is required to build all required
+    // font stuff on the main thread.
+    var fontsMin = [];
+    for (var i = 0; i < fonts.length; i++) {
+      var font = fonts[i];
+    
+      fontsMin.push({
+        name:       orgFont.name,
+        file:       orgFont.file,
+        properties: orgFont.properties
+      });
+    }
+    
+    // TODO: Handle images here.
+    
+    handler.send("page", {
+      pageNum:        pageNum,
+      fonts:          fontsMin,
+      images:         [],
+      preCompilation: preCompilation,
+    });
+  }
+}, postMessage);
+
+onmessage = handler.onMessage;
diff --git a/worker/console.js b/worker/console.js
index fc49583a6..74a2d56a3 100644
--- a/worker/console.js
+++ b/worker/console.js
@@ -9,7 +9,7 @@ var console = {
     var args = Array.prototype.slice.call(arguments);
     postMessage({
       action: 'log',
-      data: args
+      data:   args
     });
   },
 
diff --git a/worker/message_handler.js b/worker/message_handler.js
new file mode 100644
index 000000000..b97558ee6
--- /dev/null
+++ b/worker/message_handler.js
@@ -0,0 +1,23 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+'use strict';
+
+
+function MessageHandler(actionHandler, postMessage, scope) {
+  this.onMessage = function(event) {
+    var data = event.data;
+    if (data.action in actionHandler) {
+      actionHandler[data.action].call(scope, data.data);
+    } else {
+      throw 'Unkown action from worker: ' + data.action;
+    }
+  };
+  
+  this.send = function(actionName, data) {
+    postMessage({
+      action: actionName,
+      data:   data
+    });
+  }
+}
\ No newline at end of file
diff --git a/worker/pdf.js b/worker/pdf.js
deleted file mode 100644
index 8cb6342db..000000000
--- a/worker/pdf.js
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-
-'use strict';
-
-var consoleTimer = {};
-var console = {
-  log: function log() {
-    var args = Array.prototype.slice.call(arguments);
-    postMessage({
-      action: 'log',
-      data: args
-    });
-  },
-
-  time: function(name) {
-    consoleTimer[name] = Date.now();
-  },
-
-  timeEnd: function(name) {
-    var time = consoleTimer[name];
-    if (time == null) {
-      throw 'Unkown timer name ' + name;
-    }
-    this.log('Timer:', name, Date.now() - time);
-  }
-};
-
-//
-importScripts('console.js');
-importScripts('canvas.js');
-importScripts('../pdf.js');
-importScripts('../fonts.js');
-importScripts('../crypto.js');
-importScripts('../glyphlist.js');
-
-// Use the JpegStreamProxy proxy.
-JpegStream = JpegStreamProxy;
-
-// Create the WebWorkerProxyCanvas.
-var canvas = new CanvasProxy(1224, 1584);
-
-// Listen for messages from the main thread.
-var pdfDocument = null;
-onmessage = function(event) {
-  var data = event.data;
-  // If there is no pdfDocument yet, then the sent data is the PDFDocument.
-  if (!pdfDocument) {
-    pdfDocument = new PDFDoc(new Stream(data));
-    postMessage({
-      action: 'pdf_num_pages',
-      data: pdfDocument.numPages
-    });
-    return;
-  }
-  // User requested to render a certain page.
-  else {
-    console.time('compile');
-
-    // Let's try to render the first page...
-    var page = pdfDocument.getPage(parseInt(data));
-
-    var pdfToCssUnitsCoef = 96.0 / 72.0;
-    var pageWidth = (page.mediaBox[2] - page.mediaBox[0]) * pdfToCssUnitsCoef;
-    var pageHeight = (page.mediaBox[3] - page.mediaBox[1]) * pdfToCssUnitsCoef;
-    postMessage({
-      action: 'setup_page',
-      data: pageWidth + ',' + pageHeight
-    });
-
-    // Set canvas size.
-    canvas.width = pageWidth;
-    canvas.height = pageHeight;
-
-    // page.compile will collect all fonts for us, once we have loaded them
-    // we can trigger the actual page rendering with page.display
-    var fonts = [];
-    var gfx = new CanvasGraphics(canvas.getContext('2d'), CanvasProxy);
-    page.compile(gfx, fonts);
-    console.timeEnd('compile');
-
-    // Send fonts to the main thread.
-    console.time('fonts');
-    postMessage({
-      action: 'fonts',
-      data: fonts
-    });
-    console.timeEnd('fonts');
-
-    console.time('display');
-    page.display(gfx);
-    canvas.flush();
-    console.timeEnd('display');
-  }
-};