From e16e6c4f9c211dc35c59b8ec35a2365ac2d37b2d Mon Sep 17 00:00:00 2001 From: Milan Hauth Date: Mon, 21 Dec 2020 13:58:30 +0100 Subject: [PATCH 1/2] add(ctx): transformIsIdentic flag --- src/classes/CanvasRenderingContext2D.js | 36 ++++++++++++++++++++++--- src/classes/Path2D.js | 1 + src/mock/createCanvasEvent.js | 9 +++++-- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/classes/CanvasRenderingContext2D.js b/src/classes/CanvasRenderingContext2D.js index d6b897e..20b4ed7 100644 --- a/src/classes/CanvasRenderingContext2D.js +++ b/src/classes/CanvasRenderingContext2D.js @@ -82,7 +82,18 @@ const compositeOperations = [ ]; function getTransformSlice(ctx) { - return ctx._transformStack[ctx._stackIndex].slice(); + return ctx._transformIsIdentic[ctx._stackIndex] + ? undefined + : ctx._transformStack[ctx._stackIndex].slice() + ; +} + +function updateTransformIsIdentic(ctx) { + const t = ctx._transformStack[ctx._stackIndex]; + ctx._transformIsIdentic[ctx._stackIndex] = ( + t[0] == 1 && t[1] == 0 && t[2] == 0 && + t[3] == 1 && t[4] == 0 && t[5] == 0 + ); } /** @@ -129,7 +140,8 @@ export default class CanvasRenderingContext2D { * This array keeps track of the current path, so that fill and stroke operations can store the * path. */ - _path = [createCanvasEvent('beginPath', [1, 0, 0, 1, 0, 0], {})]; + // TODO why is the initial _path array not empty? + _path = [createCanvasEvent('beginPath', undefined, {})]; __getPath() { return this._path.slice(); } @@ -174,6 +186,7 @@ export default class CanvasRenderingContext2D { _textAlignStack = ['start']; _textBaselineStack = ['alphabetic']; _transformStack = [[1, 0, 0, 1, 0, 0]]; + _transformIsIdentic = [true]; _clipStack = [[]]; constructor(canvas) { @@ -661,6 +674,9 @@ export default class CanvasRenderingContext2D { this._transformStack[this._stackIndex][3] = value.d; this._transformStack[this._stackIndex][4] = value.e; this._transformStack[this._stackIndex][5] = value.f; + + updateTransformIsIdentic(this); + const event = createCanvasEvent( 'currentTransform', getTransformSlice(this), @@ -1462,7 +1478,9 @@ export default class CanvasRenderingContext2D { this._transformStack[this._stackIndex][4] = 0; this._transformStack[this._stackIndex][5] = 0; - const event = createCanvasEvent('resetTransform', getTransformSlice(this), { + this._transformIsIdentic[this._stackIndex] = true; + + const event = createCanvasEvent('resetTransform', undefined, { a: 1, b: 0, c: 0, @@ -1477,6 +1495,7 @@ export default class CanvasRenderingContext2D { if (this._stackIndex <= 0) return; this._transformStack.pop(); + this._transformIsIdentic.pop(); this._clipStack.pop(); this._directionStack.pop(); this._fillStyleStack.pop(); @@ -1525,6 +1544,8 @@ export default class CanvasRenderingContext2D { this._transformStack[this._stackIndex][2] = c * cos - a * sin; this._transformStack[this._stackIndex][3] = d * cos - b * sin; + updateTransformIsIdentic(this); + const event = createCanvasEvent('rotate', getTransformSlice(this), { angle, }); @@ -1534,6 +1555,7 @@ export default class CanvasRenderingContext2D { save() { const stackIndex = this._stackIndex; this._transformStack.push(this._transformStack[stackIndex].slice()); + this._transformIsIdentic.push(this._transformIsIdentic[stackIndex]); this._directionStack.push(this._directionStack[stackIndex]); this._fillStyleStack.push(this._fillStyleStack[stackIndex]); this._filterStack.push(this._filterStack[stackIndex]); @@ -1586,6 +1608,8 @@ export default class CanvasRenderingContext2D { this._transformStack[this._stackIndex][2] *= yResult; this._transformStack[this._stackIndex][3] *= yResult; + updateTransformIsIdentic(this); + const event = createCanvasEvent('scale', getTransformSlice(this), { x: xResult, y: yResult, @@ -1693,6 +1717,8 @@ export default class CanvasRenderingContext2D { this._transformStack[this._stackIndex][4] = e; this._transformStack[this._stackIndex][5] = f; + updateTransformIsIdentic(this); + const event = createCanvasEvent('setTransform', getTransformSlice(this), { a, b, @@ -1957,6 +1983,8 @@ export default class CanvasRenderingContext2D { this._transformStack[this._stackIndex][4] = sa * e + sc * f + se; this._transformStack[this._stackIndex][5] = sb * e + sd * f + sf; + updateTransformIsIdentic(this); + const event = createCanvasEvent('transform', getTransformSlice(this), { a, b, @@ -1988,6 +2016,8 @@ export default class CanvasRenderingContext2D { this._transformStack[this._stackIndex][4] += a * xResult + c * yResult; this._transformStack[this._stackIndex][5] += b * xResult + d * yResult; + updateTransformIsIdentic(this); + const event = createCanvasEvent('translate', getTransformSlice(this), { x: xResult, y: yResult, diff --git a/src/classes/Path2D.js b/src/classes/Path2D.js index 2d984e8..d9d8fdc 100644 --- a/src/classes/Path2D.js +++ b/src/classes/Path2D.js @@ -20,6 +20,7 @@ export default class Path2D { _events = []; _stackIndex = 0; _transformStack = [[1, 0, 0, 1, 0, 0]]; + _transformIsIdentic = [true]; constructor() { borrowedFromCanvas.forEach((key) => { diff --git a/src/mock/createCanvasEvent.js b/src/mock/createCanvasEvent.js index 50ff06b..6b393f9 100644 --- a/src/mock/createCanvasEvent.js +++ b/src/mock/createCanvasEvent.js @@ -6,7 +6,9 @@ * @example * interface CanvasRenderingContext2DEvent { * type: string; - * transform: [number, number, number, number, number, number]; // the resulting current transform + * transform?: [number, number, number, number, number, number]; + * // the resulting current transform + * // when undefined, defaults to identity matrix [1, 0, 0, 1, 0, 0] * props: { * // if the event is a property was set, `event.props.value` would be set * [propName: string]: any; @@ -14,5 +16,8 @@ * } */ export default function createCanvasEvent(type, transform, props) { - return { type, transform, props }; + return transform + ? { type, transform, props } + : { type, props } + ; } From 620bbe58d9060986fb2340510fdfea722b824937 Mon Sep 17 00:00:00 2001 From: Milan Hauth Date: Mon, 21 Dec 2020 14:11:19 +0100 Subject: [PATCH 2/2] fix(ctx): update snapshots --- ...enderingContext2D.__clearDrawCalls.js.snap | 8 - ...asRenderingContext2D.__clearEvents.js.snap | 8 - ...nvasRenderingContext2D.__clearPath.js.snap | 24 - ...nderingContext2D.__getClippingPath.js.snap | 120 --- ...sRenderingContext2D.__getDrawCalls.js.snap | 200 ----- ...nvasRenderingContext2D.__getEvents.js.snap | 776 ------------------ ...CanvasRenderingContext2D.__getPath.js.snap | 336 -------- 7 files changed, 1472 deletions(-) diff --git a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearDrawCalls.js.snap b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearDrawCalls.js.snap index 81c3392..b8dc616 100644 --- a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearDrawCalls.js.snap +++ b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearDrawCalls.js.snap @@ -11,14 +11,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "fillRect", }, ] diff --git a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearEvents.js.snap b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearEvents.js.snap index b68b457..063d7c5 100644 --- a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearEvents.js.snap +++ b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearEvents.js.snap @@ -11,14 +11,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "fillRect", }, ] diff --git a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearPath.js.snap b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearPath.js.snap index 00e067f..fc8ecfe 100644 --- a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearPath.js.snap +++ b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearPath.js.snap @@ -4,14 +4,6 @@ exports[`__clearEvents should clear the list of events 1`] = ` Array [ Object { "props": Object {}, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "beginPath", }, ] @@ -21,14 +13,6 @@ exports[`__clearEvents should not prevent additional events from being collected Array [ Object { "props": Object {}, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "beginPath", }, Object { @@ -40,14 +24,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ] diff --git a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__getClippingPath.js.snap b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__getClippingPath.js.snap index bc02a2d..7609a2b 100644 --- a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__getClippingPath.js.snap +++ b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__getClippingPath.js.snap @@ -11,14 +11,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "rect", }, ] @@ -33,14 +25,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "rect", }, Object { @@ -52,14 +36,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ] @@ -74,14 +50,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "rect", }, Object { @@ -93,14 +61,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ] @@ -115,14 +75,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "rect", }, Object { @@ -134,14 +86,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ] @@ -156,14 +100,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "rect", }, Object { @@ -175,14 +111,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, Object { @@ -191,14 +119,6 @@ Array [ "path": Array [ Object { "props": Object {}, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "beginPath", }, Object { @@ -208,14 +128,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "rect", }, Object { @@ -227,26 +139,10 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ], }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "clip", }, Object { @@ -256,14 +152,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "rect", }, Object { @@ -275,14 +163,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ] diff --git a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__getDrawCalls.js.snap b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__getDrawCalls.js.snap index 1155a42..a99ef9c 100644 --- a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__getDrawCalls.js.snap +++ b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__getDrawCalls.js.snap @@ -9,14 +9,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "clearRect", }, ] @@ -40,14 +32,6 @@ Array [ "sx": 0, "sy": 0, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "drawImage", }, ] @@ -71,14 +55,6 @@ Array [ "sx": 0, "sy": 0, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "drawImage", }, ] @@ -102,14 +78,6 @@ Array [ "sx": 0, "sy": 0, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "drawImage", }, ] @@ -123,14 +91,6 @@ Array [ "path": Array [ Object { "props": Object {}, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "beginPath", }, Object { @@ -142,26 +102,10 @@ Array [ "x": 100, "y": 101, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ], }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "fill", }, ] @@ -175,14 +119,6 @@ Array [ "path": Array [ Object { "props": Object {}, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "beginPath", }, Object { @@ -194,26 +130,10 @@ Array [ "x": 100, "y": 101, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ], }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "fill", }, ] @@ -228,14 +148,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "fillRect", }, ] @@ -256,26 +168,10 @@ Array [ "x": 100, "y": 101, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ], }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "fill", }, ] @@ -290,14 +186,6 @@ Array [ "x": 0, "y": 0, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "fillText", }, ] @@ -312,14 +200,6 @@ Array [ "x": 0, "y": 0, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "fillText", }, ] @@ -332,14 +212,6 @@ Array [ "path": Array [ Object { "props": Object {}, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "beginPath", }, Object { @@ -351,26 +223,10 @@ Array [ "x": 100, "y": 101, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ], }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "stroke", }, ] @@ -390,26 +246,10 @@ Array [ "x": 100, "y": 101, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ], }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "stroke", }, ] @@ -424,14 +264,6 @@ Array [ "x": 1, "y": 2, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "strokeRect", }, ] @@ -446,14 +278,6 @@ Array [ "x": 0, "y": 0, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "strokeText", }, ] @@ -468,14 +292,6 @@ Array [ "x": 0, "y": 0, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "strokeText", }, ] @@ -496,26 +312,10 @@ Array [ "x": 100, "y": 101, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ], }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "fill", }, ] diff --git a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__getEvents.js.snap b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__getEvents.js.snap index 4989694..e97187e 100644 --- a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__getEvents.js.snap +++ b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__getEvents.js.snap @@ -30,14 +30,6 @@ Array [ "props": Object { "value": "rtl", }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "direction", }, ] @@ -58,26 +50,10 @@ Array [ "x": 100, "y": 101, }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "arc", }, ], }, - "transform": Array [ - 1, - 0, - 0, - 1, - 0, - 0, - ], "type": "drawFocusIfNeeded", }, ] @@ -90,14 +66,6 @@ Array [ "element":