]> git.parisson.com Git - pdf.js.git/commitdiff
Merge ImageCanvasProxy and CanvasProxy. Add support for rendering multiple canvas...
authorJulian Viereck <julian.viereck@gmail.com>
Wed, 22 Jun 2011 18:49:33 +0000 (20:49 +0200)
committerJulian Viereck <julian.viereck@gmail.com>
Thu, 23 Jun 2011 21:33:24 +0000 (23:33 +0200)
canvas_proxy.js
viewer_worker.html
worker.js

index 8237574927b8d18c973e36845c388dafe56afc6f..ed209f12631bee9325d805827a6970b96d4ebdcf 100644 (file)
@@ -1,23 +1,23 @@
-var ImageCanvasProxyCounter = 0;
-function ImageCanvasProxy(width, height) {
-    this.id = ImageCanvasProxyCounter++;
-    this.width = width;
-    this.height = height;
-
-    // Using `Uint8ClampedArray` seems to be the type of ImageData - at least
-    // Firebug tells me so.
-    this.imgData = {
-        data: Uint8ClampedArray(width * height * 4)
-    };
-}
-
-ImageCanvasProxy.prototype.putImageData = function(imgData) {
-    // this.ctx.putImageData(imgData, 0, 0);
-}
-
-ImageCanvasProxy.prototype.getCanvas = function() {
-    return this;
-}
+// var ImageCanvasProxyCounter = 0;
+// function ImageCanvasProxy(width, height) {
+//     this.id = ImageCanvasProxyCounter++;
+//     this.width = width;
+//     this.height = height;
+//
+//     // Using `Uint8ClampedArray` seems to be the type of ImageData - at least
+//     // Firebug tells me so.
+//     this.imgData = {
+//         data: Uint8ClampedArray(width * height * 4)
+//     };
+// }
+//
+// ImageCanvasProxy.prototype.putImageData = function(imgData) {
+//     // this.ctx.putImageData(imgData, 0, 0);
+// }
+//
+// ImageCanvasProxy.prototype.getCanvas = function() {
+//     return this;
+// }
 
 var JpegStreamProxyCounter = 0;
 // WebWorker Proxy for JpegStream.
@@ -61,7 +61,10 @@ function GradientProxy(stack, x0, y0, x1, y1) {
     }
 }
 
+var canvasProxyCounter = 0;
 function CanvasProxy(width, height) {
+    this.id = canvasProxyCounter++;
+
     var stack = this.$stack = [];
 
     // Dummy context exposed.
@@ -73,12 +76,15 @@ function CanvasProxy(width, height) {
         return ctx;
     }
 
+    this.getCanvas = function() {
+        return this;
+    }
+
     // Expose only the minimum of the canvas object - there is no dom to do
     // more here.
-    ctx.canvas = {
-        width: width,
-        height: height
-    }
+    this.width = width;
+    this.height = height;
+    ctx.canvas = this;
 
     var ctxFunc = [
         "createRadialGradient",
@@ -127,9 +133,23 @@ function CanvasProxy(width, height) {
         return new GradientProxy(stack, x0, y0, x1, y1);
     }
 
+    ctx.getImageData = function(x, y, w, h) {
+        return {
+            width: w,
+            height: h,
+            data: Uint8ClampedArray(w * h * 4)
+        };
+    }
+
+    ctx.putImageData = function(data, x, y, width, height) {
+        stack.push(["$putImageData", [data, x, y, width, height]]);
+    }
+
     ctx.drawImage = function(image, x, y, width, height, sx, sy, swidth, sheight) {
-        if (image instanceof ImageCanvasProxy) {
-            stack.push(["$drawCanvas", [image.imgData, x, y, image.width, image.height]]);
+        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]]);
         } else if(image instanceof JpegStreamProxy) {
             stack.push(["$drawImage", [image.id, x, y, sx, sy, swidth, sheight]])
         } else {
@@ -214,6 +234,11 @@ function CanvasProxy(width, height) {
 
 CanvasProxy.prototype.flush = function() {
     postMessage("canvas_proxy_stack");
-    postMessage(this.$stack);
+    postMessage({
+        id:     this.id,
+        stack:  this.$stack,
+        width:  this.width,
+        height: this.height
+    });
     this.$stack.length = 0;
 }
index 83c41e6e01481ff8cc42c6b9a33af4b38072a98c..c7041bcbd0a95d08005a349e608b3751ef47576a 100644 (file)
@@ -13,7 +13,8 @@ function toc(msg) {
 }
 
 var myWorker = new Worker('worker.js');
-var images = {};
+var imagesList = {};
+var canvasList = {};
 var gradient;
 
 var currentX = 0;
@@ -41,27 +42,40 @@ var special = {
         currentX += this.measureText(text).width;
     },
 
-    "$drawCanvas": function(data, x, y, width, height) {
+    "$putImageData": function(imageData, x, y) {
         // Ugly: getImageData is called here only to get an object of the right
         // shape - we are not interessted in the data, as we set it the line
         // afterwards to something custome.
         // Can we do better here?
-        var imgData = ctx.getImageData(0, 0, width, height);
-        imgData.data = data;
-        ctx.putImageData(imgData, x, y);
+        var imgData = this.getImageData(0, 0, imageData.width, imageData.height);
+        imgData.data = imageData.data;
+        this.putImageData(imgData, x, y);
     },
 
     "$drawImage": function(id, x, y, sx, sy, swidth, sheight) {
-        var image = images[id];
+        var image = imagesList[id];
         if (!image) {
             throw "Image not found";
         }
-        ctx.drawImage(image, x, y, image.width, image.height,
+        this.drawImage(image, x, y, image.width, image.height,
             sx, sy, swidth, sheight);
     },
 
+    "$drawCanvas": function(id, x, y, sx, sy, swidth, sheight) {
+        var canvas = canvasList[id];
+        if (!canvas) {
+            throw "Canvas not found";
+        }
+        if (sheight != null) {
+            this.drawImage(canvas, x, y, canvas.width, canvas.height,
+                sx, sy, swidth, sheight);
+        } else {
+            this.drawImage(canvas, x, y, canvas.width, canvas.height);
+        }
+    },
+
     "$createLinearGradient": function(x0, y0, x1, y1) {
-        gradient = ctx.createLinearGradient(x0, y0, x1, y1);
+        gradient = this.createLinearGradient(x0, y0, x1, y1);
     },
 
     "$addColorStop": function(i, rgba) {
@@ -69,16 +83,17 @@ var special = {
     },
 
     "$fillStyleGradient": function() {
-        ctx.fillStyle = gradient;
+        this.fillStyle = gradient;
     },
 
     "$strokeStyleGradient": function() {
-        ctx.strokeStyle = gradient;
+        this.strokeStyle = gradient;
     }
 }
 
 var gStack;
-function renderProxyCanvas(stack) {
+function renderProxyCanvas(canvas, stack) {
+    var ctx = canvas.getContext("2d");
     for (var i = 0; i < stack.length; i++) {
     // for (var i = 0; i < 1000; i++) {
         var opp = stack[i];
@@ -135,7 +150,7 @@ myWorker.onmessage = function(event) {
         case JPEG_STREAM:
             var img = new Image();
             img.src = "data:image/jpeg;base64," + window.btoa(data.str);
-            images[data.id] = img;
+            imagesList[data.id] = img;
             console.log("got image", data.id)
             break;
 
@@ -171,16 +186,25 @@ myWorker.onmessage = function(event) {
             break;
 
         case CANVAS_PROXY_STACK:
-            var stack = data;
+            var id = data.id;
+            var stack = data.stack;
             gStack = stack;
-            console.log("canvas stack size", stack.length)
+
+            // Check if there is already a canvas with the given id. If not,
+            // create a new canvas.
+            if (!canvasList[id]) {
+                var newCanvas = document.createElement("canvas");
+                newCanvas.width = data.width;
+                newCanvas.height = data.height;
+                canvasList[id] = newCanvas;
+            }
 
             // There might be fonts that need to get loaded. Shedule the
             // rendering at the end of the event queue ensures this.
             setTimeout(function() {
-                tic();
-                renderProxyCanvas(stack);
-                toc("canvas rendering")
+                if (id == 0) tic();
+                renderProxyCanvas(canvasList[id], stack);
+                if (id == 0) toc("canvas rendering")
             }, 0);
             onMessageState = WAIT;
             break;
@@ -234,6 +258,7 @@ function prevPage() {
 window.onload = function() {
     window.canvas = document.getElementById("canvas");
     window.ctx = canvas.getContext("2d");
+    canvasList[0] = window.canvas;
     open("compressed.tracemonkey-pldi-09.pdf");
 }
 </script>
index 59ad8edea9f1777b19413f14723dee0c00f22bb8..e59e37155ea555681f8065070a8a7ad82163ca76 100644 (file)
--- a/worker.js
+++ b/worker.js
@@ -49,7 +49,7 @@ onmessage = function(event) {
         // 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"), ImageCanvasProxy);
+        var gfx = new CanvasGraphics(canvas.getContext("2d"), CanvasProxy);
         page.compile(gfx, fonts);
 
         // Inspect fonts and translate the missing one.