var canvas;
var ctx;
var canvasGradients = {};
function canvas_rbga(color) {
var a = canvas_opacity(color);
var r = (color >> 16) & 0xFF;
var g = (color >> 8) & 0xFF;
var b = (color >> 0) & 0xFF;
return "rgba(" + r + "," + g + "," + b + "," + a + ")";
}
function canvas_opacity(color) {
var a = (color >> 24) & 0xFF;
return a / 255.;
}
function displayCanvas(displayList) {
if (displayList.clear) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
for (var index = 0; index < displayList.length; ++index) {
drawToCanvas(displayList[index]);
}
}
function drawToCanvas(action) {
ctx.save();
var paint = paintToCanvas(action.paint);
var draw = action.draw;
if ('string' == typeof(draw)) {
draw = (new Function("return " + draw))();
}
if (isArray(draw)) {
assert(draw.length > 0);
var picture = 'draw' in draw[0];
if (picture) {
for (var index = 0; index < draw.length; ++index) {
drawToCanvas(draw[index]);
}
return;
}
ctx.beginPath();
for (var index = 0; index < draw.length; ++index) {
for (var prop in draw[index]) {
var v = draw[index][prop];
switch (prop) {
case 'arcTo':
ctx.arcTo(v[0], v[1], v[2], v[3], v[4]);
break;
case 'close':
ctx.closePath();
break;
case 'cubic':
ctx.moveTo(v[0], v[1]);
ctx.bezierCurveTo(v[2], v[3], v[4], v[5], v[6], v[7]);
break;
case 'line':
ctx.moveTo(v[0], v[1]);
ctx.lineTo(v[2], v[3]);
break;
case 'quad':
ctx.moveTo(v[0], v[1]);
ctx.quadraticCurveTo(v[2], v[3], v[4], v[5]);
break;
default:
assert(0);
}
}
}
if ('fill' == paint.style) {
ctx.fill();
} else {
assert('stroke' == paint.style);
ctx.stroke();
}
} else {
assert('string' in draw);
if ('fill' == paint.style) {
ctx.fillText(draw.string, draw.x, draw.y);
} else {
assert('stroke' == paint.style);
ctx.strokeText(draw.string, draw.x, draw.y);
}
}
ctx.restore();
}
function keyframeCanvasInit(displayList, first) {
if ('canvas' in first && 'clear' == first.canvas) {
displayList.clear = true;
}
}
function paintToCanvas(paint) {
var color;
var inPicture = 'string' == typeof(paint);
if (inPicture) {
paint = (new Function("return " + paint))();
assert('object' == typeof(paint) && !isArray(paint));
}
if ('gradient' in paint) {
var gradient = paint.gradient.split('.');
var gradName = gradient[1];
if (!canvasGradients[gradName]) {
var g = window[gradient[0]][gradient[1]];
var grad = ctx.createRadialGradient(g.cx, g.cy, 0, g.cx, g.cy, g.r);
var stopLen = g.stops.length;
for (var index = 0; index < stopLen; ++index) {
var stop = g.stops[index];
var color = canvas_rbga(stop.color);
grad.addColorStop(index, color);
}
canvasGradients[gradName] = grad;
}
color = canvasGradients[gradName];
if (!inPicture) {
ctx.globalAlpha = canvas_opacity(paint.color);
}
} else {
color = canvas_rbga(paint.color);
}
if ('fill' == paint.style) {
ctx.fillStyle = color;
} else if ('stroke' == paint.style) {
ctx.strokeStyle = color;
} else {
ctx.globalAlpha = canvas_opacity(paint.color);
}
if ('strokeWidth' in paint) {
ctx.lineWidth = paint.strokeWidth;
}
if ('typeface' in paint) {
var typeface = typefaces[paint.typeface];
var font = typeface.style;
if ('textSize' in paint) {
font += " " + paint.textSize;
}
if ('family' in typeface) {
font += " " + typeface.family;
}
ctx.font = font;
if ('textAlign' in paint) {
ctx.textAlign = paint.textAlign;
}
if ('textBaseline' in paint) {
ctx.textBaseline = paint.textBaseline;
}
}
return paint;
}
function setupCanvas() {
canvas = document.getElementById("canvas");
ctx = canvas ? canvas.getContext("2d") : null;
assert(ctx);
var resScale = window.devicePixelRatio ? window.devicePixelRatio : 1;
var unscaledWidth = canvas.width;
var unscaledHeight = canvas.height;
canvas.width = unscaledWidth * resScale;
canvas.height = unscaledHeight * resScale;
canvas.style.width = unscaledWidth + 'px';
canvas.style.height = unscaledHeight + 'px';
if (resScale != 1) {
ctx.scale(resScale, resScale);
}
}