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); } }