-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perf(): optimize rect rendering + calcOwnMatrix #1
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,107 @@ | ||
import * as fabric from "fabric"; | ||
import Engine from "./engine"; | ||
|
||
// fabric.StaticCanvas.prototype.renderCanvas = function (ctx, objects) { | ||
// this.clearContext(this.getContext()); | ||
// this._renderObjects(ctx, objects); | ||
// }; | ||
|
||
const uAffine = (product, curr) => | ||
curr ? fabric.util.multiplyTransformMatrices(curr, product, false) : product; | ||
|
||
const u = (product, curr) => | ||
curr ? fabric.util.multiplyTransformMatrices(curr, product, true) : product; | ||
|
||
const multiplyTransformMatrixArray = (matrices, is2x2) => | ||
matrices.reduceRight(is2x2 ? u : uAffine, fabric.iMatrix.concat()); | ||
|
||
class OptimizedRect extends fabric.Rect { | ||
m; | ||
calcOwnMatrix() { | ||
// return [1, 0, 0, 1, this.left, this.top]; | ||
if (this.m) { | ||
return this.m; | ||
} | ||
const { | ||
angle, | ||
scaleX, | ||
scaleY, | ||
flipX, | ||
flipY, | ||
skewX, | ||
skewY, | ||
left: x, | ||
top: y, | ||
} = this; | ||
|
||
const m = multiplyTransformMatrixArray( | ||
[ | ||
// fabric.util.createTranslateMatrix(x, y), | ||
angle && fabric.util.createRotateMatrix({ angle }), | ||
(scaleX !== 1 || scaleY !== 1 || flipX || flipY) && | ||
fabric.util.createScaleMatrix( | ||
flipX ? -scaleX : scaleX, | ||
flipY ? -scaleY : scaleY | ||
), | ||
skewX && fabric.util.createSkewXMatrix(skewX), | ||
skewY && fabric.util.createSkewYMatrix(skewY), | ||
], | ||
true | ||
); | ||
|
||
m[4] = x; | ||
m[5] = y; | ||
return (this.m = m); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this entirely equivalent? if doing rotate/scale/skew as a 2x2 and then slapping the top/left at the end is the same as starting with the translate as we do today and multiply the ohers as a 2by3, we don't need to swap the order, we can keep the translate as the first step. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should be 100% eq since translation is not affected by the plane when using center origin. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
True, that is why I left it commented out, because if the gain is not huge it is too messy to keep |
||
|
||
// return fabric.util.composeMatrix({ | ||
// angle: this.angle, | ||
// translateX: center.x, | ||
// translateY: center.y, | ||
// scaleX: this.scaleX, | ||
// scaleY: this.scaleY, | ||
// skewX: this.skewX, | ||
// skewY: this.skewY, | ||
// flipX: this.flipX, | ||
// flipY: this.flipY, | ||
// }); | ||
} | ||
|
||
/** | ||
* | ||
* @param {CanvasRenderingContext2D} ctx | ||
*/ | ||
render(ctx) { | ||
const dpr = this.canvas.getRetinaScaling(); | ||
// ctx.resetTransform(); | ||
// ctx.scale(dpr, dpr); | ||
// this.transform(ctx); | ||
const t = this.calcTransformMatrix(); | ||
ctx.setTransform( | ||
dpr * t[0], | ||
t[1], | ||
t[2], | ||
dpr * t[3], | ||
dpr * t[4], | ||
dpr * t[5] | ||
); | ||
ctx.strokeRect(-this.width / 2, -this.height / 2, this.width, this.height); | ||
ctx.fillStyle = "white"; | ||
ctx.fillRect(-this.width / 2, -this.height / 2, this.width, this.height); | ||
// ctx.beginPath(); | ||
// ctx.rect(-this.width / 2, -this.height / 2, this.width, this.height); | ||
// ctx.stroke(); | ||
// ctx.fill(); | ||
|
||
// ctx.beginPath(); | ||
// ctx.rect(-this.width / 2, -this.height / 2, this.width, this.height); | ||
// ctx.closePath(); | ||
// ctx.fillStyle = "white"; | ||
|
||
// ctx.stroke(); | ||
// ctx.fill(); | ||
} | ||
} | ||
|
||
class FabricEngine extends Engine { | ||
constructor() { | ||
super(); | ||
|
@@ -21,6 +122,7 @@ class FabricEngine extends Engine { | |
const r = rects[i]; | ||
r.x -= r.speed; | ||
r.el.left = r.x; | ||
delete r.el.m; | ||
if (r.x + r.size < 0) { | ||
r.x = this.width + r.size; | ||
} | ||
|
@@ -44,7 +146,7 @@ class FabricEngine extends Engine { | |
const size = 10 + Math.random() * 40; | ||
const speed = 1 + Math.random(); | ||
|
||
const fRect = new fabric.Rect({ | ||
const fRect = new OptimizedRect({ | ||
width: size, | ||
height: size, | ||
fill: "white", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to test the perf of this impl of
calcOwnMatrix
try to uncomment this line and compare results. Should be the same