168 lines
5.1 KiB
JavaScript
168 lines
5.1 KiB
JavaScript
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);
|
|
}
|
|
}
|