2011-06-23 03:49:33 +09:00
|
|
|
// 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;
|
|
|
|
// }
|
2011-06-22 17:40:51 +09:00
|
|
|
|
2011-06-22 21:02:54 +09:00
|
|
|
var JpegStreamProxyCounter = 0;
|
|
|
|
// WebWorker Proxy for JpegStream.
|
|
|
|
var JpegStreamProxy = (function() {
|
|
|
|
function constructor(bytes, dict) {
|
|
|
|
this.id = JpegStreamProxyCounter++;
|
|
|
|
this.dict = dict;
|
|
|
|
|
|
|
|
// create DOM image.
|
|
|
|
postMessage("jpeg_stream");
|
|
|
|
postMessage({
|
|
|
|
id: this.id,
|
|
|
|
str: bytesToString(bytes)
|
|
|
|
});
|
|
|
|
|
|
|
|
// var img = new Image();
|
|
|
|
// img.src = "data:image/jpeg;base64," + window.btoa(bytesToString(bytes));
|
|
|
|
// this.domImage = img;
|
|
|
|
}
|
|
|
|
|
|
|
|
constructor.prototype = {
|
|
|
|
getImage: function() {
|
|
|
|
return this;
|
|
|
|
// return this.domImage;
|
|
|
|
},
|
|
|
|
getChar: function() {
|
|
|
|
error("internal error: getChar is not valid on JpegStream");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
return constructor;
|
|
|
|
})();
|
|
|
|
|
2011-06-22 21:25:21 +09:00
|
|
|
// 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]]);
|
|
|
|
this.addColorStop = function(i, rgba) {
|
|
|
|
stack.push(["$addColorStop", [i, rgba]]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-23 04:17:32 +09:00
|
|
|
var patternProxyCounter = 0;
|
|
|
|
function PatternProxy(stack, object, kind) {
|
|
|
|
this.id = patternProxyCounter++;
|
|
|
|
|
|
|
|
if (!(object instanceof CanvasProxy) ) {
|
|
|
|
throw "unkown type to createPattern";
|
|
|
|
}
|
|
|
|
// Flush the object here to ensure it's available on the main thread.
|
|
|
|
// 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]]);
|
|
|
|
}
|
|
|
|
|
2011-06-23 03:49:33 +09:00
|
|
|
var canvasProxyCounter = 0;
|
2011-06-22 06:33:11 +09:00
|
|
|
function CanvasProxy(width, height) {
|
2011-06-23 03:49:33 +09:00
|
|
|
this.id = canvasProxyCounter++;
|
|
|
|
|
2011-06-22 06:33:11 +09:00
|
|
|
var stack = this.$stack = [];
|
|
|
|
|
2011-06-23 03:04:25 +09:00
|
|
|
// Dummy context exposed.
|
|
|
|
var ctx = {};
|
|
|
|
this.getContext = function(type) {
|
|
|
|
if (type != "2d") {
|
|
|
|
throw "CanvasProxy can only provide a 2d context.";
|
|
|
|
}
|
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
|
2011-06-22 06:33:11 +09:00
|
|
|
// Expose only the minimum of the canvas object - there is no dom to do
|
|
|
|
// more here.
|
2011-06-23 03:49:33 +09:00
|
|
|
this.width = width;
|
|
|
|
this.height = height;
|
|
|
|
ctx.canvas = this;
|
2011-06-22 06:33:11 +09:00
|
|
|
|
|
|
|
var ctxFunc = [
|
|
|
|
"createRadialGradient",
|
|
|
|
"arcTo",
|
|
|
|
"arc",
|
|
|
|
"fillText",
|
|
|
|
"strokeText",
|
2011-06-22 16:46:11 +09:00
|
|
|
// "drawImage",
|
|
|
|
// "getImageData",
|
|
|
|
// "putImageData",
|
2011-06-22 06:33:11 +09:00
|
|
|
"createImageData",
|
|
|
|
"drawWindow",
|
|
|
|
"save",
|
|
|
|
"restore",
|
|
|
|
"scale",
|
|
|
|
"rotate",
|
|
|
|
"translate",
|
|
|
|
"transform",
|
|
|
|
"setTransform",
|
2011-06-22 21:25:21 +09:00
|
|
|
// "createLinearGradient",
|
2011-06-23 04:17:32 +09:00
|
|
|
// "createPattern",
|
2011-06-22 06:33:11 +09:00
|
|
|
"clearRect",
|
|
|
|
"fillRect",
|
|
|
|
"strokeRect",
|
|
|
|
"beginPath",
|
|
|
|
"closePath",
|
|
|
|
"moveTo",
|
|
|
|
"lineTo",
|
|
|
|
"quadraticCurveTo",
|
|
|
|
"bezierCurveTo",
|
|
|
|
"rect",
|
|
|
|
"fill",
|
|
|
|
"stroke",
|
|
|
|
"clip",
|
|
|
|
"measureText",
|
2011-06-22 08:28:17 +09:00
|
|
|
"isPointInPath",
|
|
|
|
|
|
|
|
"$setCurrentX",
|
|
|
|
"$addCurrentX",
|
|
|
|
"$saveCurrentX",
|
|
|
|
"$restoreCurrentX",
|
|
|
|
"$showText"
|
2011-06-22 06:33:11 +09:00
|
|
|
];
|
2011-06-22 16:46:11 +09:00
|
|
|
|
2011-06-23 04:17:32 +09:00
|
|
|
ctx.createPattern = function(object, kind) {
|
|
|
|
return new PatternProxy(stack, object, kind);
|
|
|
|
}
|
|
|
|
|
2011-06-23 03:04:25 +09:00
|
|
|
ctx.createLinearGradient = function(x0, y0, x1, y1) {
|
2011-06-22 21:25:21 +09:00
|
|
|
return new GradientProxy(stack, x0, y0, x1, y1);
|
|
|
|
}
|
|
|
|
|
2011-06-23 03:49:33 +09:00
|
|
|
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]]);
|
|
|
|
}
|
|
|
|
|
2011-06-23 03:04:25 +09:00
|
|
|
ctx.drawImage = function(image, x, y, width, height, sx, sy, swidth, sheight) {
|
2011-06-23 03:49:33 +09:00
|
|
|
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]]);
|
2011-06-22 21:02:54 +09:00
|
|
|
} else if(image instanceof JpegStreamProxy) {
|
|
|
|
stack.push(["$drawImage", [image.id, x, y, sx, sy, swidth, sheight]])
|
2011-06-22 17:40:51 +09:00
|
|
|
} else {
|
|
|
|
throw "unkown type to drawImage";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-22 06:33:11 +09:00
|
|
|
function buildFuncCall(name) {
|
|
|
|
return function() {
|
2011-06-22 08:28:17 +09:00
|
|
|
// console.log("funcCall", name)
|
2011-06-22 06:33:11 +09:00
|
|
|
stack.push([name, Array.prototype.slice.call(arguments)]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var name;
|
|
|
|
for (var i = 0; i < ctxFunc.length; i++) {
|
|
|
|
name = ctxFunc[i];
|
2011-06-23 03:04:25 +09:00
|
|
|
ctx[name] = buildFuncCall(name);
|
2011-06-22 06:33:11 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
var ctxProp = {
|
|
|
|
// "canvas"
|
|
|
|
"globalAlpha": "1",
|
|
|
|
"globalCompositeOperation": "source-over",
|
|
|
|
"strokeStyle": "#000000",
|
|
|
|
"fillStyle": "#000000",
|
|
|
|
"lineWidth": "1",
|
|
|
|
"lineCap": "butt",
|
|
|
|
"lineJoin": "miter",
|
|
|
|
"miterLimit": "10",
|
|
|
|
"shadowOffsetX": "0",
|
|
|
|
"shadowOffsetY": "0",
|
|
|
|
"shadowBlur": "0",
|
|
|
|
"shadowColor": "rgba(0, 0, 0, 0)",
|
|
|
|
"font": "10px sans-serif",
|
|
|
|
"textAlign": "start",
|
|
|
|
"textBaseline": "alphabetic",
|
|
|
|
"mozTextStyle": "10px sans-serif",
|
|
|
|
"mozImageSmoothingEnabled": "true",
|
|
|
|
"DRAWWINDOW_DRAW_CARET": "1",
|
|
|
|
"DRAWWINDOW_DO_NOT_FLUSH": "2",
|
|
|
|
"DRAWWINDOW_DRAW_VIEW": "4",
|
|
|
|
"DRAWWINDOW_USE_WIDGET_LAYERS": "8",
|
|
|
|
"DRAWWINDOW_ASYNC_DECODE_IMAGES": "16",
|
|
|
|
}
|
|
|
|
|
|
|
|
function buildGetter(name) {
|
|
|
|
return function() {
|
2011-06-23 03:04:25 +09:00
|
|
|
return ctx["$" + name];
|
2011-06-22 06:33:11 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function buildSetter(name) {
|
|
|
|
return function(value) {
|
|
|
|
stack.push(["$", name, value]);
|
2011-06-23 03:04:25 +09:00
|
|
|
return ctx["$" + name] = value;
|
2011-06-22 06:33:11 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var name in ctxProp) {
|
2011-06-23 03:04:25 +09:00
|
|
|
ctx["$" + name] = ctxProp[name];
|
|
|
|
ctx.__defineGetter__(name, buildGetter(name));
|
2011-06-22 21:25:21 +09:00
|
|
|
|
|
|
|
// 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"]);
|
2011-06-23 04:17:32 +09:00
|
|
|
} else if (value instanceof PatternProxy) {
|
|
|
|
stack.push(["$" + name + "Pattern", [value.id]]);
|
2011-06-22 21:25:21 +09:00
|
|
|
} else {
|
|
|
|
stack.push(["$", name, value]);
|
2011-06-23 03:04:25 +09:00
|
|
|
return ctx["$" + name] = value;
|
2011-06-22 21:25:21 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-23 03:04:25 +09:00
|
|
|
ctx.__defineSetter__(name, buildSetterStyle(name));
|
2011-06-22 21:25:21 +09:00
|
|
|
} else {
|
2011-06-23 03:04:25 +09:00
|
|
|
ctx.__defineSetter__(name, buildSetter(name));
|
2011-06-22 21:25:21 +09:00
|
|
|
}
|
2011-06-22 06:33:11 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CanvasProxy.prototype.flush = function() {
|
|
|
|
postMessage("canvas_proxy_stack");
|
2011-06-23 03:49:33 +09:00
|
|
|
postMessage({
|
|
|
|
id: this.id,
|
|
|
|
stack: this.$stack,
|
|
|
|
width: this.width,
|
|
|
|
height: this.height
|
|
|
|
});
|
2011-06-22 06:33:11 +09:00
|
|
|
this.$stack.length = 0;
|
|
|
|
}
|