|
|
|
@ -59,15 +59,121 @@ function ScratchCanvas(width, height) {
@@ -59,15 +59,121 @@ function ScratchCanvas(width, height) {
|
|
|
|
|
return canvas; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function addContextCurrentTransform(ctx) { |
|
|
|
|
// If the context doesn't expose a `mozCurrentTransform`, add a JS based on.
|
|
|
|
|
if (!ctx.mozCurrentTransform) { |
|
|
|
|
// Store the original context
|
|
|
|
|
ctx._originalSave = ctx.save; |
|
|
|
|
ctx._originalRestore = ctx.restore; |
|
|
|
|
ctx._originalRotate = ctx.rotate; |
|
|
|
|
ctx._originalScale = ctx.scale; |
|
|
|
|
ctx._originalTranslate = ctx.translate; |
|
|
|
|
ctx._originalTransform = ctx.transform; |
|
|
|
|
|
|
|
|
|
ctx._transformMatrix = [1, 0, 0, 1, 0, 0]; |
|
|
|
|
ctx._transformStack = []; |
|
|
|
|
|
|
|
|
|
Object.defineProperty(ctx, 'mozCurrentTransform', { |
|
|
|
|
get: function getCurrentTransform() { |
|
|
|
|
return this._transformMatrix; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
Object.defineProperty(ctx, 'mozCurrentTransformInverse', { |
|
|
|
|
get: function getCurrentTransformInverse() { |
|
|
|
|
// Calculation done using WolframAlpha:
|
|
|
|
|
// http://www.wolframalpha.com/input/?
|
|
|
|
|
// i=Inverse+{{a%2C+c%2C+e}%2C+{b%2C+d%2C+f}%2C+{0%2C+0%2C+1}}
|
|
|
|
|
|
|
|
|
|
var m = this._transformMatrix; |
|
|
|
|
var a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5]; |
|
|
|
|
|
|
|
|
|
var ad_bc = a * d - b * c; |
|
|
|
|
var bc_ad = b * c - a * d; |
|
|
|
|
|
|
|
|
|
return [ |
|
|
|
|
d / ad_bc, |
|
|
|
|
b / bc_ad, |
|
|
|
|
c / bc_ad, |
|
|
|
|
a / ad_bc, |
|
|
|
|
(d * e - c * f) / bc_ad, |
|
|
|
|
(b * e - a * f) / ad_bc |
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
ctx.save = function ctxSave() { |
|
|
|
|
var old = this._transformMatrix; |
|
|
|
|
this._transformStack.push(old); |
|
|
|
|
this._transformMatrix = old.slice(0, 6); |
|
|
|
|
|
|
|
|
|
this._originalSave(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
ctx.restore = function ctxRestore() { |
|
|
|
|
var prev = this._transformStack.pop(); |
|
|
|
|
if (prev) { |
|
|
|
|
this._transformMatrix = prev; |
|
|
|
|
this._originalRestore(); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
ctx.translate = function ctxTranslate(x, y) { |
|
|
|
|
var m = this._transformMatrix; |
|
|
|
|
m[4] = m[0] * x + m[2] * y + m[4]; |
|
|
|
|
m[5] = m[1] * x + m[3] * y + m[5]; |
|
|
|
|
|
|
|
|
|
this._originalTranslate(x, y); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
ctx.scale = function ctxScale(x, y) { |
|
|
|
|
var m = this._transformMatrix; |
|
|
|
|
m[0] = m[0] * x; |
|
|
|
|
m[1] = m[1] * x; |
|
|
|
|
m[2] = m[2] * y; |
|
|
|
|
m[3] = m[3] * y; |
|
|
|
|
|
|
|
|
|
this._originalScale(x, y); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
ctx.transform = function ctxTransform(a, b, c, d, e, f) { |
|
|
|
|
var m = this._transformMatrix; |
|
|
|
|
this._transformMatrix = [ |
|
|
|
|
m[0] * a + m[2] * b, |
|
|
|
|
m[1] * a + m[3] * b, |
|
|
|
|
m[0] * c + m[2] * d, |
|
|
|
|
m[1] * c + m[3] * d, |
|
|
|
|
m[0] * e + m[2] * f + m[4], |
|
|
|
|
m[1] * e + m[3] * f + m[5] |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
ctx._originalTransform(a, b, c, d, e, f); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
ctx.rotate = function ctxRotate(angle) { |
|
|
|
|
var cosValue = Math.cos(angle); |
|
|
|
|
var sinValue = Math.sin(angle); |
|
|
|
|
|
|
|
|
|
var m = this._transformMatrix; |
|
|
|
|
this._transformMatrix = [ |
|
|
|
|
m[0] * cosValue + m[2] * sinValue, |
|
|
|
|
m[1] * cosValue + m[3] * sinValue, |
|
|
|
|
m[0] * (-sinValue) + m[2] * cosValue, |
|
|
|
|
m[1] * (-sinValue) + m[3] * cosValue, |
|
|
|
|
m[4], |
|
|
|
|
m[5] |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
this._originalRotate(angle); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var CanvasGraphics = (function canvasGraphics() { |
|
|
|
|
// Defines the time the executeIRQueue is going to be executing
|
|
|
|
|
// before it stops and shedules a continue of execution.
|
|
|
|
|
var kExecutionTime = 50; |
|
|
|
|
|
|
|
|
|
// Number of IR commands to execute before checking
|
|
|
|
|
// if we execute longer then `kExecutionTime`.
|
|
|
|
|
var kExecutionTimeCheck = 500; |
|
|
|
|
|
|
|
|
|
function constructor(canvasCtx, objs) { |
|
|
|
|
this.ctx = canvasCtx; |
|
|
|
|
this.current = new CanvasExtraState(); |
|
|
|
@ -77,6 +183,10 @@ var CanvasGraphics = (function canvasGraphics() {
@@ -77,6 +183,10 @@ var CanvasGraphics = (function canvasGraphics() {
|
|
|
|
|
this.xobjs = null; |
|
|
|
|
this.ScratchCanvas = ScratchCanvas; |
|
|
|
|
this.objs = objs; |
|
|
|
|
|
|
|
|
|
if (canvasCtx) { |
|
|
|
|
addContextCurrentTransform(canvasCtx); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var LINE_CAP_STYLES = ['butt', 'round', 'square']; |
|
|
|
@ -112,31 +222,33 @@ var CanvasGraphics = (function canvasGraphics() {
@@ -112,31 +222,33 @@ var CanvasGraphics = (function canvasGraphics() {
|
|
|
|
|
var i = executionStartIdx || 0; |
|
|
|
|
var argsArrayLen = argsArray.length; |
|
|
|
|
|
|
|
|
|
// Sometimes the IRQueue to execute is empty.
|
|
|
|
|
if (argsArrayLen == i) { |
|
|
|
|
return i; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var executionEndIdx; |
|
|
|
|
var startTime = Date.now(); |
|
|
|
|
|
|
|
|
|
var objs = this.objs; |
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
executionEndIdx = Math.min(argsArrayLen, i + kExecutionTimeCheck); |
|
|
|
|
|
|
|
|
|
for (i; i < executionEndIdx; i++) { |
|
|
|
|
if (fnArray[i] !== 'dependency') { |
|
|
|
|
this[fnArray[i]].apply(this, argsArray[i]); |
|
|
|
|
} else { |
|
|
|
|
var deps = argsArray[i]; |
|
|
|
|
for (var n = 0, nn = deps.length; n < nn; n++) { |
|
|
|
|
var depObjId = deps[n]; |
|
|
|
|
|
|
|
|
|
// If the promise isn't resolved yet, add the continueCallback
|
|
|
|
|
// to the promise and bail out.
|
|
|
|
|
if (!objs.isResolved(depObjId)) { |
|
|
|
|
objs.get(depObjId, continueCallback); |
|
|
|
|
return i; |
|
|
|
|
} |
|
|
|
|
while (true) { |
|
|
|
|
if (fnArray[i] !== 'dependency') { |
|
|
|
|
this[fnArray[i]].apply(this, argsArray[i]); |
|
|
|
|
} else { |
|
|
|
|
var deps = argsArray[i]; |
|
|
|
|
for (var n = 0, nn = deps.length; n < nn; n++) { |
|
|
|
|
var depObjId = deps[n]; |
|
|
|
|
|
|
|
|
|
// If the promise isn't resolved yet, add the continueCallback
|
|
|
|
|
// to the promise and bail out.
|
|
|
|
|
if (!objs.isResolved(depObjId)) { |
|
|
|
|
objs.get(depObjId, continueCallback); |
|
|
|
|
return i; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
i++; |
|
|
|
|
|
|
|
|
|
// If the entire IRQueue was executed, stop as were done.
|
|
|
|
|
if (i == argsArrayLen) { |
|
|
|
@ -153,7 +265,7 @@ var CanvasGraphics = (function canvasGraphics() {
@@ -153,7 +265,7 @@ var CanvasGraphics = (function canvasGraphics() {
|
|
|
|
|
|
|
|
|
|
// If the IRQueue isn't executed completly yet OR the execution time
|
|
|
|
|
// was short enough, do another execution round.
|
|
|
|
|
} while (true); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
endDrawing: function canvasGraphicsEndDrawing() { |
|
|
|
|