Merge ImageCanvasProxy and CanvasProxy. Add support for rendering multiple canvas objects on the worker and assemble them again on the main thread.
This commit is contained in:
parent
c9c24ee5c3
commit
897ac256fc
@ -1,23 +1,23 @@
|
|||||||
var ImageCanvasProxyCounter = 0;
|
// var ImageCanvasProxyCounter = 0;
|
||||||
function ImageCanvasProxy(width, height) {
|
// function ImageCanvasProxy(width, height) {
|
||||||
this.id = ImageCanvasProxyCounter++;
|
// this.id = ImageCanvasProxyCounter++;
|
||||||
this.width = width;
|
// this.width = width;
|
||||||
this.height = height;
|
// this.height = height;
|
||||||
|
//
|
||||||
// Using `Uint8ClampedArray` seems to be the type of ImageData - at least
|
// // Using `Uint8ClampedArray` seems to be the type of ImageData - at least
|
||||||
// Firebug tells me so.
|
// // Firebug tells me so.
|
||||||
this.imgData = {
|
// this.imgData = {
|
||||||
data: Uint8ClampedArray(width * height * 4)
|
// data: Uint8ClampedArray(width * height * 4)
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
ImageCanvasProxy.prototype.putImageData = function(imgData) {
|
// ImageCanvasProxy.prototype.putImageData = function(imgData) {
|
||||||
// this.ctx.putImageData(imgData, 0, 0);
|
// // this.ctx.putImageData(imgData, 0, 0);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
ImageCanvasProxy.prototype.getCanvas = function() {
|
// ImageCanvasProxy.prototype.getCanvas = function() {
|
||||||
return this;
|
// return this;
|
||||||
}
|
// }
|
||||||
|
|
||||||
var JpegStreamProxyCounter = 0;
|
var JpegStreamProxyCounter = 0;
|
||||||
// WebWorker Proxy for JpegStream.
|
// WebWorker Proxy for JpegStream.
|
||||||
@ -61,7 +61,10 @@ function GradientProxy(stack, x0, y0, x1, y1) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var canvasProxyCounter = 0;
|
||||||
function CanvasProxy(width, height) {
|
function CanvasProxy(width, height) {
|
||||||
|
this.id = canvasProxyCounter++;
|
||||||
|
|
||||||
var stack = this.$stack = [];
|
var stack = this.$stack = [];
|
||||||
|
|
||||||
// Dummy context exposed.
|
// Dummy context exposed.
|
||||||
@ -73,12 +76,15 @@ function CanvasProxy(width, height) {
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.getCanvas = function() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// Expose only the minimum of the canvas object - there is no dom to do
|
// Expose only the minimum of the canvas object - there is no dom to do
|
||||||
// more here.
|
// more here.
|
||||||
ctx.canvas = {
|
this.width = width;
|
||||||
width: width,
|
this.height = height;
|
||||||
height: height
|
ctx.canvas = this;
|
||||||
}
|
|
||||||
|
|
||||||
var ctxFunc = [
|
var ctxFunc = [
|
||||||
"createRadialGradient",
|
"createRadialGradient",
|
||||||
@ -127,9 +133,23 @@ function CanvasProxy(width, height) {
|
|||||||
return new GradientProxy(stack, x0, y0, x1, y1);
|
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) {
|
ctx.drawImage = function(image, x, y, width, height, sx, sy, swidth, sheight) {
|
||||||
if (image instanceof ImageCanvasProxy) {
|
if (image instanceof CanvasProxy) {
|
||||||
stack.push(["$drawCanvas", [image.imgData, x, y, image.width, image.height]]);
|
// 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) {
|
} else if(image instanceof JpegStreamProxy) {
|
||||||
stack.push(["$drawImage", [image.id, x, y, sx, sy, swidth, sheight]])
|
stack.push(["$drawImage", [image.id, x, y, sx, sy, swidth, sheight]])
|
||||||
} else {
|
} else {
|
||||||
@ -214,6 +234,11 @@ function CanvasProxy(width, height) {
|
|||||||
|
|
||||||
CanvasProxy.prototype.flush = function() {
|
CanvasProxy.prototype.flush = function() {
|
||||||
postMessage("canvas_proxy_stack");
|
postMessage("canvas_proxy_stack");
|
||||||
postMessage(this.$stack);
|
postMessage({
|
||||||
|
id: this.id,
|
||||||
|
stack: this.$stack,
|
||||||
|
width: this.width,
|
||||||
|
height: this.height
|
||||||
|
});
|
||||||
this.$stack.length = 0;
|
this.$stack.length = 0;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,8 @@ function toc(msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var myWorker = new Worker('worker.js');
|
var myWorker = new Worker('worker.js');
|
||||||
var images = {};
|
var imagesList = {};
|
||||||
|
var canvasList = {};
|
||||||
var gradient;
|
var gradient;
|
||||||
|
|
||||||
var currentX = 0;
|
var currentX = 0;
|
||||||
@ -41,27 +42,40 @@ var special = {
|
|||||||
currentX += this.measureText(text).width;
|
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
|
// 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
|
// shape - we are not interessted in the data, as we set it the line
|
||||||
// afterwards to something custome.
|
// afterwards to something custome.
|
||||||
// Can we do better here?
|
// Can we do better here?
|
||||||
var imgData = ctx.getImageData(0, 0, width, height);
|
var imgData = this.getImageData(0, 0, imageData.width, imageData.height);
|
||||||
imgData.data = data;
|
imgData.data = imageData.data;
|
||||||
ctx.putImageData(imgData, x, y);
|
this.putImageData(imgData, x, y);
|
||||||
},
|
},
|
||||||
|
|
||||||
"$drawImage": function(id, x, y, sx, sy, swidth, sheight) {
|
"$drawImage": function(id, x, y, sx, sy, swidth, sheight) {
|
||||||
var image = images[id];
|
var image = imagesList[id];
|
||||||
if (!image) {
|
if (!image) {
|
||||||
throw "Image not found";
|
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);
|
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) {
|
"$createLinearGradient": function(x0, y0, x1, y1) {
|
||||||
gradient = ctx.createLinearGradient(x0, y0, x1, y1);
|
gradient = this.createLinearGradient(x0, y0, x1, y1);
|
||||||
},
|
},
|
||||||
|
|
||||||
"$addColorStop": function(i, rgba) {
|
"$addColorStop": function(i, rgba) {
|
||||||
@ -69,16 +83,17 @@ var special = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
"$fillStyleGradient": function() {
|
"$fillStyleGradient": function() {
|
||||||
ctx.fillStyle = gradient;
|
this.fillStyle = gradient;
|
||||||
},
|
},
|
||||||
|
|
||||||
"$strokeStyleGradient": function() {
|
"$strokeStyleGradient": function() {
|
||||||
ctx.strokeStyle = gradient;
|
this.strokeStyle = gradient;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var gStack;
|
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 < stack.length; i++) {
|
||||||
// for (var i = 0; i < 1000; i++) {
|
// for (var i = 0; i < 1000; i++) {
|
||||||
var opp = stack[i];
|
var opp = stack[i];
|
||||||
@ -135,7 +150,7 @@ myWorker.onmessage = function(event) {
|
|||||||
case JPEG_STREAM:
|
case JPEG_STREAM:
|
||||||
var img = new Image();
|
var img = new Image();
|
||||||
img.src = "data:image/jpeg;base64," + window.btoa(data.str);
|
img.src = "data:image/jpeg;base64," + window.btoa(data.str);
|
||||||
images[data.id] = img;
|
imagesList[data.id] = img;
|
||||||
console.log("got image", data.id)
|
console.log("got image", data.id)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -171,16 +186,25 @@ myWorker.onmessage = function(event) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CANVAS_PROXY_STACK:
|
case CANVAS_PROXY_STACK:
|
||||||
var stack = data;
|
var id = data.id;
|
||||||
|
var stack = data.stack;
|
||||||
gStack = 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
|
// There might be fonts that need to get loaded. Shedule the
|
||||||
// rendering at the end of the event queue ensures this.
|
// rendering at the end of the event queue ensures this.
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
tic();
|
if (id == 0) tic();
|
||||||
renderProxyCanvas(stack);
|
renderProxyCanvas(canvasList[id], stack);
|
||||||
toc("canvas rendering")
|
if (id == 0) toc("canvas rendering")
|
||||||
}, 0);
|
}, 0);
|
||||||
onMessageState = WAIT;
|
onMessageState = WAIT;
|
||||||
break;
|
break;
|
||||||
@ -234,6 +258,7 @@ function prevPage() {
|
|||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
window.canvas = document.getElementById("canvas");
|
window.canvas = document.getElementById("canvas");
|
||||||
window.ctx = canvas.getContext("2d");
|
window.ctx = canvas.getContext("2d");
|
||||||
|
canvasList[0] = window.canvas;
|
||||||
open("compressed.tracemonkey-pldi-09.pdf");
|
open("compressed.tracemonkey-pldi-09.pdf");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -49,7 +49,7 @@ onmessage = function(event) {
|
|||||||
// page.compile will collect all fonts for us, once we have loaded them
|
// page.compile will collect all fonts for us, once we have loaded them
|
||||||
// we can trigger the actual page rendering with page.display
|
// we can trigger the actual page rendering with page.display
|
||||||
var fonts = [];
|
var fonts = [];
|
||||||
var gfx = new CanvasGraphics(canvas.getContext("2d"), ImageCanvasProxy);
|
var gfx = new CanvasGraphics(canvas.getContext("2d"), CanvasProxy);
|
||||||
page.compile(gfx, fonts);
|
page.compile(gfx, fonts);
|
||||||
|
|
||||||
// Inspect fonts and translate the missing one.
|
// Inspect fonts and translate the missing one.
|
||||||
|
Loading…
Reference in New Issue
Block a user