]> git.parisson.com Git - pdf.js.git/commitdiff
First pass on review: worker.js -> pdf_worker.js, Font.bind cleanup + other stuff
authorJulian Viereck <julian.viereck@gmail.com>
Thu, 23 Jun 2011 11:09:36 +0000 (13:09 +0200)
committerJulian Viereck <julian.viereck@gmail.com>
Thu, 23 Jun 2011 21:33:24 +0000 (23:33 +0200)
canvas_proxy.js
fonts.js
pdf.js
pdf_worker.js [new file with mode: 0644]
viewer_worker.html
worker.js [deleted file]
worker_client.js

index 83b57682fca3e254997a77cbc8a483134ee81f78..0b7681bfe4df955717cbd40ac5821ea648245b10 100644 (file)
@@ -1,3 +1,7 @@
+/* -*- 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 JpegStreamProxyCounter = 0;
 // WebWorker Proxy for JpegStream.
@@ -29,16 +33,16 @@ var JpegStreamProxy = (function() {
 // Really simple GradientProxy. There is currently only one active gradient at
 // the time, meaning you can't create a gradient, create a second one and then
 // use the first one again. As this isn't used in pdf.js right now, it's okay.
-function GradientProxy(stack, x0, y0, x1, y1) {
-  stack.push(["$createLinearGradient", [x0, y0, x1, y1]]);
+function GradientProxy(cmdQueue, x0, y0, x1, y1) {
+  cmdQueue.push(["$createLinearGradient", [x0, y0, x1, y1]]);
   this.addColorStop = function(i, rgba) {
-    stack.push(["$addColorStop", [i, rgba]]);
+    cmdQueue.push(["$addColorStop", [i, rgba]]);
   }
 }
 
 // Really simple PatternProxy.
 var patternProxyCounter = 0;
-function PatternProxy(stack, object, kind) {
+function PatternProxy(cmdQueue, object, kind) {
   this.id = patternProxyCounter++;
 
   if (!(object instanceof CanvasProxy) ) {
@@ -49,7 +53,7 @@ function PatternProxy(stack, object, kind) {
   // TODO: Make some kind of dependency management, such that the object
   // gets flushed only if needed.
   object.flush();
-  stack.push(["$createPatternFromCanvas", [this.id, object.id, kind]]);
+  cmdQueue.push(["$createPatternFromCanvas", [this.id, object.id, kind]]);
 }
 
 var canvasProxyCounter = 0;
@@ -57,7 +61,7 @@ function CanvasProxy(width, height) {
   this.id = canvasProxyCounter++;
 
   // The `stack` holds the rendering calls and gets flushed to the main thead.
-  var stack = this.$stack = [];
+  var cmdQueue = this.cmdQueue = [];
 
   // Dummy context that gets exposed.
   var ctx = {};
@@ -119,7 +123,7 @@ function CanvasProxy(width, height) {
   function buildFuncCall(name) {
     return function() {
       // console.log("funcCall", name)
-      stack.push([name, Array.prototype.slice.call(arguments)]);
+      cmdQueue.push([name, Array.prototype.slice.call(arguments)]);
     }
   }
   var name;
@@ -131,11 +135,11 @@ function CanvasProxy(width, height) {
   // Some function calls that need more work.
 
   ctx.createPattern = function(object, kind) {
-    return new PatternProxy(stack, object, kind);
+    return new PatternProxy(cmdQueue, object, kind);
   }
 
   ctx.createLinearGradient = function(x0, y0, x1, y1) {
-    return new GradientProxy(stack, x0, y0, x1, y1);
+    return new GradientProxy(cmdQueue, x0, y0, x1, y1);
   }
 
   ctx.getImageData = function(x, y, w, h) {
@@ -147,16 +151,16 @@ function CanvasProxy(width, height) {
   }
 
   ctx.putImageData = function(data, x, y, width, height) {
-    stack.push(["$putImageData", [data, x, y, width, height]]);
+    cmdQueue.push(["$putImageData", [data, x, y, width, height]]);
   }
 
   ctx.drawImage = function(image, x, y, width, height, sx, sy, swidth, sheight) {
     if (image instanceof CanvasProxy) {
       // Send the image/CanvasProxy to the main thread.
       image.flush();
-      stack.push(["$drawCanvas", [image.id, x, y, sx, sy, swidth, sheight]]);
+      cmdQueue.push(["$drawCanvas", [image.id, x, y, sx, sy, swidth, sheight]]);
     } else if(image instanceof JpegStreamProxy) {
-      stack.push(["$drawImage", [image.id, x, y, sx, sy, swidth, sheight]])
+      cmdQueue.push(["$drawImage", [image.id, x, y, sx, sy, swidth, sheight]])
     } else {
       throw "unkown type to drawImage";
     }
@@ -192,11 +196,26 @@ function CanvasProxy(width, height) {
 
   function buildSetter(name) {
     return function(value) {
-      stack.push(["$", name, value]);
+      cmdQueue.push(["$", name, value]);
       return ctx["$" + name] = value;
     }
   }
 
+  // Setting the value to `stroke|fillStyle` needs special handling, as it
+  // might gets an gradient/pattern.
+  function buildSetterStyle(name) {
+    return function(value) {
+      if (value instanceof GradientProxy) {
+        cmdQueue.push(["$" + name + "Gradient"]);
+      } else if (value instanceof PatternProxy) {
+        cmdQueue.push(["$" + name + "Pattern", [value.id]]);
+      } else {
+        cmdQueue.push(["$", name, value]);
+        return ctx["$" + name] = value;
+      }
+    }
+  }
+
   for (var name in ctxProp) {
     ctx["$" + name] = ctxProp[name];
     ctx.__defineGetter__(name, buildGetter(name));
@@ -204,18 +223,6 @@ function CanvasProxy(width, height) {
     // Special treatment for `fillStyle` and `strokeStyle`: The passed style
     // might be a gradient. Need to check for that.
     if (name == "fillStyle" || name == "strokeStyle") {
-      function buildSetterStyle(name) {
-        return function(value) {
-          if (value instanceof GradientProxy) {
-            stack.push(["$" + name + "Gradient"]);
-          } else if (value instanceof PatternProxy) {
-            stack.push(["$" + name + "Pattern", [value.id]]);
-          } else {
-            stack.push(["$", name, value]);
-            return ctx["$" + name] = value;
-          }
-        }
-      }
       ctx.__defineSetter__(name, buildSetterStyle(name));
     } else {
       ctx.__defineSetter__(name, buildSetter(name));
@@ -224,16 +231,16 @@ function CanvasProxy(width, height) {
 }
 
 /**
-* Sends the current stack of the CanvasProxy over to the main thread and
-* resets the stack.
+* Sends the current cmdQueue of the CanvasProxy over to the main thread and
+* resets the cmdQueue.
 */
 CanvasProxy.prototype.flush = function() {
-  postMessage("canvas_proxy_stack");
+  postMessage("canvas_proxy_cmd_queue");
   postMessage({
-    id:     this.id,
-    stack:  this.$stack,
-    width:  this.width,
-    height: this.height
+    id:         this.id,
+    cmdQueue:   this.cmdQueue,
+    width:      this.width,
+    height:     this.height
   });
-  this.$stack.length = 0;
+  this.cmdQueue.length = 0;
 }
index 9c9201b722317fe07b109876011ed9f607d482df..a3604c6b9b777d627d31d50337a62cb80e2b3803 100644 (file)
--- a/fonts.js
+++ b/fonts.js
@@ -759,88 +759,15 @@ var Font = (function () {
       var data = this.font;
       var fontName = this.name;
 
-      var isWorker = (typeof window == "undefined");
-      /** Hack begin */
-      if (!isWorker) {
-
-          // Actually there is not event when a font has finished downloading so
-          // the following code are a dirty hack to 'guess' when a font is ready
-          var canvas = document.createElement("canvas");
-          var style = "border: 1px solid black; position:absolute; top: " +
-                       (debug ? (100 * fontCount) : "-200") + "px; left: 2px; width: 340px; height: 100px";
-          canvas.setAttribute("style", style);
-          canvas.setAttribute("width", 340);
-          canvas.setAttribute("heigth", 100);
-          document.body.appendChild(canvas);
-
-          // Get the font size canvas think it will be for 'spaces'
-          var ctx = canvas.getContext("2d");
-          ctx.font = "bold italic 20px " + fontName + ", Symbol, Arial";
-          var testString = "   ";
-
-          // When debugging use the characters provided by the charsets to visually
-          // see what's happening instead of 'spaces'
-          var debug = false;
-          if (debug) {
-            var name = document.createElement("font");
-            name.setAttribute("style", "position: absolute; left: 20px; top: " +
-                              (100 * fontCount + 60) + "px");
-            name.innerHTML = fontName;
-            document.body.appendChild(name);
-
-            // Retrieve font charset
-            var charset = Fonts[fontName].properties.charset || [];
-
-            // if the charset is too small make it repeat a few times
-            var count = 30;
-            while (count-- && charset.length <= 30)
-              charset = charset.concat(charset.slice());
-
-            for (var i = 0; i < charset.length; i++) {
-              var unicode = GlyphsUnicode[charset[i]];
-              if (!unicode)
-                continue;
-              testString += String.fromCharCode(unicode);
-            }
-
-            ctx.fillText(testString, 20, 20);
-          }
-
-          // Periodicaly check for the width of the testString, it will be
-          // different once the real font has loaded
-          var textWidth = ctx.measureText(testString).width;
-
-          var interval = window.setInterval(function canvasInterval(self) {
-            this.start = this.start || Date.now();
-            ctx.font = "bold italic 20px " + fontName + ", Symbol, Arial";
-
-            // For some reasons the font has not loaded, so mark it loaded for the
-            // page to proceed but cry
-            if ((Date.now() - this.start) >= kMaxWaitForFontFace) {
-              window.clearInterval(interval);
-              Fonts[fontName].loading = false;
-              warn("Is " + fontName + " for charset: " + charset + " loaded?");
-              this.start = 0;
-            } else if (textWidth != ctx.measureText(testString).width) {
-              window.clearInterval(interval);
-              Fonts[fontName].loading = false;
-              this.start = 0;
-            }
-
-            if (debug)
-              ctx.fillText(testString, 20, 50);
-          }, 30, this);
-    }
-
-      /** Hack end */
-      //
       // Get the base64 encoding of the binary font data
       var str = "";
       var length = data.length;
       for (var i = 0; i < length; ++i)
         str += String.fromCharCode(data[i]);
 
-      if (isWorker) {
+      // Insert the font-face css on the page. In a web worker, this needs to
+      // be forwareded on the main thread.
+      if (typeof window == "undefined") {
           postMessage("font");
           postMessage(JSON.stringify({
               str: str,
@@ -855,6 +782,19 @@ var Font = (function () {
           var rule = "@font-face { font-family:'" + fontName + "';src:" + url + "}";
           var styleSheet = document.styleSheets[0];
           styleSheet.insertRule(rule, styleSheet.length);
+
+          var div = document.createElement("div");
+          div.innerHTML += "<div style='font-family:" +
+            fontName +
+            ";'>j</div>";
+          document.body.appendChild(div);
+
+          Fonts[fontName].loading = true;
+          window.setTimeout(function() {
+            Fonts[fontName].loading = false;
+          // Timeout of just `0`, `10` doesn't work here, but for me all values
+          // above work. Setting value to 50ms.
+          }, 50);
       }
     }
   };
diff --git a/pdf.js b/pdf.js
index 1223a2bb69b347c53ec0f4dc049e0bbbce98ff7a..84706794619f0c799d12f305b4383fb6497e2608 100644 (file)
--- a/pdf.js
+++ b/pdf.js
@@ -2645,9 +2645,7 @@ var CanvasGraphics = (function() {
             }
 
             var fn = Function("objpool", src);
-            var ret = function (gfx) { fn.call(gfx, objpool); };
-            ret.src = src;
-            return ret;
+            return function (gfx) { fn.call(gfx, objpool); };
         },
 
         endDrawing: function() {
@@ -3015,8 +3013,8 @@ var CanvasGraphics = (function() {
             var botRight = applyMatrix([x0 + xstep, y0 + ystep], matrix);
 
             var tmpCanvas = new this.ScratchCanvas(
-                Math.ceil(botRight[0] - topLeft[0]),    // WIDTH
-                Math.ceil(botRight[1] - topLeft[1])     // HEIGHT
+                Math.ceil(botRight[0] - topLeft[0]),    // width
+                Math.ceil(botRight[1] - topLeft[1])     // height
             );
 
             // set the new canvas element context as the graphics context
diff --git a/pdf_worker.js b/pdf_worker.js
new file mode 100644 (file)
index 0000000..91245ae
--- /dev/null
@@ -0,0 +1,81 @@
+/* -*- 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 timer = null;
+function tic() {
+  timer = Date.now();
+}
+
+function toc(msg) {
+  log(msg + ": " + (Date.now() - timer) + "ms");
+  timer = null;
+}
+
+function log() {
+  var args = Array.prototype.slice.call(arguments);
+  postMessage("log");
+  postMessage(JSON.stringify(args))
+}
+
+var console = {
+  log: log
+}
+
+//
+importScripts("canvas_proxy.js");
+importScripts("pdf.js");
+importScripts("fonts.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("pdf_num_page");
+    postMessage(pdfDocument.numPages)
+    return;
+  }
+  // User requested to render a certain page.
+  else {
+    tic();
+
+    // Let's try to render the first page...
+    var page = pdfDocument.getPage(parseInt(data));
+
+    // 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);
+
+    // Inspect fonts and translate the missing one.
+    var count = fonts.length;
+    for (var i = 0; i < count; i++) {
+      var font = fonts[i];
+      if (Fonts[font.name]) {
+        fontsReady = fontsReady && !Fonts[font.name].loading;
+        continue;
+      }
+
+      // This "builds" the font and sents it over to the main thread.
+      new Font(font.name, font.file, font.properties);
+    }
+    toc("compiled page");
+
+    tic()
+    page.display(gfx);
+    canvas.flush();
+    toc("displayed page");
+  }
+}
index a9f08388f5b42116fda309ab090d48c1f4ddcf9b..a5ffc6a6e76a535e634d7f621a46f904a1446a0b 100644 (file)
@@ -14,6 +14,7 @@ window.onload = function() {
     pdfDoc.onChangePage = function(numPage) {
         document.getElementById("pageNumber").value = numPage;
     }
+    // pdfDoc.open("canvas.pdf", function() {
     pdfDoc.open("compressed.tracemonkey-pldi-09.pdf", function() {
         document.getElementById("numPages").innerHTML = "/" + pdfDoc.numPages;
     })
diff --git a/worker.js b/worker.js
deleted file mode 100644 (file)
index 09e2b81..0000000
--- a/worker.js
+++ /dev/null
@@ -1,78 +0,0 @@
-"use strict";
-
-var timer = null;
-function tic() {
-  timer = Date.now();
-}
-
-function toc(msg) {
-  log(msg + ": " + (Date.now() - timer) + "ms");
-  timer = null;
-}
-
-function log() {
-  var args = Array.prototype.slice.call(arguments);
-  postMessage("log");
-  postMessage(JSON.stringify(args))
-}
-
-var console = {
-  log: log
-}
-
-//
-importScripts("canvas_proxy.js");
-importScripts("pdf.js");
-importScripts("fonts.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("pdf_num_page");
-    postMessage(pdfDocument.numPages)
-    return;
-  }
-  // User requested to render a certain page.
-  else {
-    tic();
-
-    // Let's try to render the first page...
-    var page = pdfDocument.getPage(parseInt(data));
-
-    // 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);
-
-    // Inspect fonts and translate the missing one.
-    var count = fonts.length;
-    for (var i = 0; i < count; i++) {
-      var font = fonts[i];
-      if (Fonts[font.name]) {
-        fontsReady = fontsReady && !Fonts[font.name].loading;
-        continue;
-      }
-
-      // This "builds" the font and sents it over to the main thread.
-      new Font(font.name, font.file, font.properties);
-    }
-    toc("compiled page");
-
-    tic()
-    page.display(gfx);
-    canvas.flush();
-    toc("displayed page");
-  }
-}
index 316ef1fc0737cbf49cb225bf89110bceae4979e0..f69f4f682bb0ad3d348694f1ff77184c95f7b1b2 100644 (file)
@@ -1,3 +1,6 @@
+/* -*- 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 WorkerPDFDoc(canvas) {
@@ -128,10 +131,11 @@ function WorkerPDFDoc(canvas) {
     }
   }
 
-  function renderProxyCanvas(canvas, stack) {
+  function renderProxyCanvas(canvas, cmdQueue) {
     var ctx = canvas.getContext("2d");
-    for (var i = 0; i < stack.length; i++) {
-      var opp = stack[i];
+    var cmdQueueLength = cmdQueue.length;
+    for (var i = 0; i < cmdQueueLength; i++) {
+      var opp = cmdQueue[i];
       if (opp[0] == "$") {
         ctx[opp[1]] = opp[2];
       } else if (opp[0] in ctxSpecial) {
@@ -146,7 +150,7 @@ function WorkerPDFDoc(canvas) {
   * onMessage state machine.
   */
   const WAIT = 0;
-  const CANVAS_PROXY_STACK = 1;
+  const CANVAS_PROXY_CMD_QUEUE = 1;
   const LOG = 2;
   const FONT = 3;
   const PDF_NUM_PAGE = 4;
@@ -170,8 +174,8 @@ function WorkerPDFDoc(canvas) {
             onMessageState = LOG;
             return;
 
-          case "canvas_proxy_stack":
-            onMessageState = CANVAS_PROXY_STACK;
+          case "canvas_proxy_cmd_queue":
+            onMessageState = CANVAS_PROXY_CMD_QUEUE;
             return;
 
           case "font":
@@ -215,6 +219,7 @@ function WorkerPDFDoc(canvas) {
         // Just adding the font-face to the DOM doesn't make it load. It
         // seems it's loaded once Gecko notices it's used. Therefore,
         // add a div on the page using the loaded font.
+        var div = document.createElement("div");
         document.getElementById("fonts").innerHTML += "<div style='font-family:" + data.fontName + "'>j</div>";
 
         onMessageState = WAIT;
@@ -225,9 +230,9 @@ function WorkerPDFDoc(canvas) {
         onMessageState = WAIT;
       break;
 
-      case CANVAS_PROXY_STACK:
+      case CANVAS_PROXY_CMD_QUEUE:
         var id = data.id;
-        var stack = data.stack;
+        var cmdQueue = data.cmdQueue;
 
         // Check if there is already a canvas with the given id. If not,
         // create a new canvas.
@@ -242,7 +247,7 @@ function WorkerPDFDoc(canvas) {
         // rendering at the end of the event queue ensures this.
         setTimeout(function() {
           if (id == 0) tic();
-          renderProxyCanvas(canvasList[id], stack);
+          renderProxyCanvas(canvasList[id], cmdQueue);
           if (id == 0) toc("canvas rendering")
         }, 0);
         onMessageState = WAIT;