-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.
}
}
+var canvasProxyCounter = 0;
function CanvasProxy(width, height) {
+ this.id = canvasProxyCounter++;
+
var stack = this.$stack = [];
// Dummy context exposed.
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",
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 {
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;
}
}
var myWorker = new Worker('worker.js');
-var images = {};
+var imagesList = {};
+var canvasList = {};
var gradient;
var currentX = 0;
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) {
},
"$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];
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;
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;
window.onload = function() {
window.canvas = document.getElementById("canvas");
window.ctx = canvas.getContext("2d");
+ canvasList[0] = window.canvas;
open("compressed.tracemonkey-pldi-09.pdf");
}
</script>