Skip to content

Commit

Permalink
added golden
Browse files Browse the repository at this point in the history
  • Loading branch information
asturur committed Oct 3, 2024
1 parent 284c29b commit f1a1408
Show file tree
Hide file tree
Showing 15 changed files with 240 additions and 153 deletions.
22 changes: 8 additions & 14 deletions .codesandbox/templates/vanilla/src/testcases/loadingSvgs.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import * as fabric from 'fabric';

const svgString = `<svg class="star-svg" viewBox="4 2 15 15" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/2000/xlink" width="400px" height="400px">
<g>
<g>
<clipPath id="a">
<circle transform="scale(1.2, 1.2) translate(-1, -1)" r="4" cx="8" cy="8" />
const svgString = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" viewBox="5 3 10 10" version="1.1" width="400" height="400">
<clipPath id="t">
<circle r="0.05" transform="translate(5, 7) scale(140, 140)" cx="0.001" cy="0.001" />
</clipPath>
<clipPath id="t" clip-path="url(#a)">
<circle r="6" transform="scale(1.3, 0.8) translate(1, 1)" cx="7" cy="7" />
<clipPath id="c">
<circle transform="translate(12, 10) scale(14, 14)" r="0.5" cx="0.01" cy="0.01" />
</clipPath>
<clipPath id="c" clip-path="url(#t)" >
<circle transform="translate(12, 10) scale(14, 14)" r="0.5" cx="0.01" cy="0.01" />
</clipPath>
<path clip-path="url(#c)" d="M15.422,18.129l-5.264-2.768l-5.265,2.768l1.006-5.863L1.64,8.114l5.887-0.855
l2.632-5.334l2.633,5.334l5.885,0.855l-4.258,4.152L15.422,18.129z" fill="red"/>
</g>
</g>
<g clip-path="url(#t)">
<path clip-path="url(#c)" d="M15.422,18.129l-5.264-2.768l-5.265,2.768l1.006-5.863L1.64,8.114l5.887-0.855
l2.632-5.334l2.633,5.334l5.885,0.855l-4.258,4.152L15.422,18.129z" fill="red"/></g>
</svg>`;

export async function testCase(canvas: fabric.Canvas) {
Expand Down
2 changes: 1 addition & 1 deletion dist/index.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.min.mjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.min.mjs.map

Large diffs are not rendered by default.

170 changes: 108 additions & 62 deletions dist/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1556,10 +1556,14 @@ const createImage = () => getFabricDocument().createElement('img');
*/
const copyCanvasElement = canvas => {
var _newCanvas$getContext;
const newCanvas = createCanvasElementFor(canvas);
(_newCanvas$getContext = newCanvas.getContext('2d')) === null || _newCanvas$getContext === void 0 || _newCanvas$getContext.drawImage(canvas, 0, 0);
return newCanvas;
};
const createCanvasElementFor = canvas => {
const newCanvas = createCanvasElement();
newCanvas.width = canvas.width;
newCanvas.height = canvas.height;
(_newCanvas$getContext = newCanvas.getContext('2d')) === null || _newCanvas$getContext === void 0 || _newCanvas$getContext.drawImage(canvas, 0, 0);
return newCanvas;
};

Expand Down Expand Up @@ -4081,9 +4085,7 @@ class StaticCanvas extends createCollectionMixin(CommonMethods) {
* This essentially copies canvas dimensions since loadFromJSON does not affect canvas size.
*/
cloneWithoutData() {
const el = createCanvasElement();
el.width = this.width;
el.height = this.height;
const el = createCanvasElementFor(this);
return new this.constructor(el);
}

Expand Down Expand Up @@ -4172,10 +4174,11 @@ class StaticCanvas extends createCollectionMixin(CommonMethods) {
translateY = (vp[5] - (top || 0)) * multiplier,
newVp = [newZoom, 0, 0, newZoom, translateX, translateY],
originalRetina = this.enableRetinaScaling,
canvasEl = createCanvasElement(),
canvasEl = createCanvasElementFor({
width: scaledWidth,
height: scaledHeight
}),
objectsToRender = filter ? this._objects.filter(obj => filter(obj)) : this._objects;
canvasEl.width = scaledWidth;
canvasEl.height = scaledHeight;
this.enableRetinaScaling = false;
this.viewportTransform = newVp;
this.width = scaledWidth;
Expand Down Expand Up @@ -7064,7 +7067,7 @@ let FabricObject$1 = class FabricObject extends ObjectGeometry {
this.drawCacheOnCanvas(ctx);
} else {
this._removeCacheCanvas();
this.drawObject(ctx);
this.drawObject(ctx, false, {});
this.dirty = false;
}
ctx.restore();
Expand All @@ -7078,7 +7081,25 @@ let FabricObject$1 = class FabricObject extends ObjectGeometry {
this._createCacheCanvas();
}
if (this.isCacheDirty() && this._cacheContext) {
this.drawObject(this._cacheContext, options.forClipping);
const {
zoomX,
zoomY,
cacheTranslationX,
cacheTranslationY
} = this;
const {
width,
height
} = this._cacheCanvas;
this.drawObject(this._cacheContext, options.forClipping, {
zoomX,
zoomY,
cacheTranslationX,
cacheTranslationY,
width,
height,
parentClipPaths: []
});
this.dirty = false;
}
}
Expand Down Expand Up @@ -7166,7 +7187,7 @@ let FabricObject$1 = class FabricObject extends ObjectGeometry {
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {FabricObject} clipPath
*/
drawClipPathOnCache(ctx, clipPath) {
drawClipPathOnCache(ctx, clipPath, canvasWithClipPath) {
ctx.save();
// DEBUG: uncomment this line, comment the following
// ctx.globalAlpha = 0.4
Expand All @@ -7175,23 +7196,19 @@ let FabricObject$1 = class FabricObject extends ObjectGeometry {
} else {
ctx.globalCompositeOperation = 'destination-in';
}
ctx.setTransform(1, 0, 0, 1, 0, 0);
//ctx.scale(1 / 2, 1 / 2);
if (clipPath.absolutePositioned) {
const m = invertTransform(this.calcTransformMatrix());
ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
}
clipPath.transform(ctx);
ctx.scale(1 / clipPath.zoomX, 1 / clipPath.zoomY);
ctx.drawImage(clipPath._cacheCanvas, -clipPath.cacheTranslationX, -clipPath.cacheTranslationY);
ctx.drawImage(canvasWithClipPath, 0, 0);
ctx.restore();
}

/**
* Execute the drawing operation for an object on a specified context
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {boolean} forClipping apply clipping styles
* @param {DrawContext} context additional context for rendering
*/
drawObject(ctx, forClipping) {
drawObject(ctx, forClipping, context) {
const originalFill = this.fill,
originalStroke = this.stroke;
if (forClipping) {
Expand All @@ -7202,30 +7219,45 @@ let FabricObject$1 = class FabricObject extends ObjectGeometry {
this._renderBackground(ctx);
}
this._render(ctx);
this._drawClipPath(ctx, this.clipPath);
this._drawClipPath(ctx, this.clipPath, context);
this.fill = originalFill;
this.stroke = originalStroke;
}
createClipPathLayer(clipPath, context) {
const canvas = createCanvasElementFor(context);
const ctx = canvas.getContext('2d');
ctx.translate(context.cacheTranslationX, context.cacheTranslationY);
ctx.scale(context.zoomX, context.zoomY);
clipPath._cacheCanvas = canvas;
context.parentClipPaths.forEach(prevClipPath => {
prevClipPath.transform(ctx);
});
context.parentClipPaths.push(clipPath);
if (clipPath.absolutePositioned) {
const m = invertTransform(this.calcTransformMatrix());
ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
}
clipPath.transform(ctx);
clipPath.drawObject(ctx, true, context);
return canvas;
}

/**
* Prepare clipPath state and cache and draw it on instance's cache
* @param {CanvasRenderingContext2D} ctx
* @param {FabricObject} clipPath
*/
_drawClipPath(ctx, clipPath) {
_drawClipPath(ctx, clipPath, context) {
if (!clipPath) {
return;
}
// needed to setup a couple of variables
// path canvas gets overridden with this one.
// TODO find a better solution?
clipPath._set('canvas', this.canvas);
clipPath.shouldCache();
clipPath._transformDone = true;
clipPath.renderCache({
forClipping: true
});
this.drawClipPathOnCache(ctx, clipPath);
const canvas = this.createClipPathLayer(clipPath, context);
this.drawClipPathOnCache(ctx, clipPath, canvas);
}

/**
Expand Down Expand Up @@ -7497,14 +7529,15 @@ let FabricObject$1 = class FabricObject extends ObjectGeometry {
_applyPatternForTransformedGradient(ctx, filler) {
var _pCtx$createPattern;
const dims = this._limitCacheSize(this._getCacheCanvasDimensions()),
pCanvas = createCanvasElement(),
retinaScaling = this.getCanvasRetinaScaling(),
width = dims.x / this.scaleX / retinaScaling,
height = dims.y / this.scaleY / retinaScaling;
// in case width and height are less than 1px, we have to round up.
// since the pattern is no-repeat, this is fine
pCanvas.width = Math.ceil(width);
pCanvas.height = Math.ceil(height);
height = dims.y / this.scaleY / retinaScaling,
pCanvas = createCanvasElementFor({
// in case width and height are less than 1px, we have to round up.
// since the pattern is no-repeat, this is fine
width: Math.ceil(width),
height: Math.ceil(height)
});
const pCtx = pCanvas.getContext('2d');
if (!pCtx) {
return;
Expand Down Expand Up @@ -11321,7 +11354,6 @@ const _excluded$a = ["type", "objects", "layoutManager"];
* This layout manager doesn't do anything and therefore keeps the exact layout the group had when {@link Group#toObject} was called.
*/
class NoopLayoutManager extends LayoutManager {
// eslint-disable-next-line @typescript-eslint/no-empty-function
performLayout() {}
}
const groupDefaultValues = {
Expand Down Expand Up @@ -11705,21 +11737,22 @@ class Group extends createCollectionMixin(FabricObject) {
* Execute the drawing operation for an object on a specified context
* @param {CanvasRenderingContext2D} ctx Context to render on
*/
drawObject(ctx) {
drawObject(ctx, forClipping, context) {
this._renderBackground(ctx);
for (let i = 0; i < this._objects.length; i++) {
var _this$canvas;
const obj = this._objects[i];
// TODO: handle rendering edge case somehow
if ((_this$canvas = this.canvas) !== null && _this$canvas !== void 0 && _this$canvas.preserveObjectStacking && this._objects[i].group !== this) {
if ((_this$canvas = this.canvas) !== null && _this$canvas !== void 0 && _this$canvas.preserveObjectStacking && obj.group !== this) {
ctx.save();
ctx.transform(...invertTransform(this.calcTransformMatrix()));
this._objects[i].render(ctx);
obj.render(ctx);
ctx.restore();
} else if (this._objects[i].group === this) {
this._objects[i].render(ctx);
} else if (obj.group === this) {
obj.render(ctx);
}
}
this._drawClipPath(ctx, this.clipPath);
this._drawClipPath(ctx, this.clipPath, context);
}

/**
Expand Down Expand Up @@ -18858,8 +18891,10 @@ let measuringContext;
*/
function getMeasuringContext() {
if (!measuringContext) {
const canvas = createCanvasElement();
canvas.width = canvas.height = 0;
const canvas = createCanvasElementFor({
width: 0,
height: 0
});
measuringContext = canvas.getContext('2d');
}
return measuringContext;
Expand Down Expand Up @@ -19592,10 +19627,13 @@ class FabricText extends StyledText {
* @return {CanvasPattern} a pattern to use as fill/stroke style
*/
_applyPatternGradientTransformText(filler) {
const pCanvas = createCanvasElement(),
// TODO: verify compatibility with strokeUniform
width = this.width + this.strokeWidth,
// TODO: verify compatibility with strokeUniform
const width = this.width + this.strokeWidth,
height = this.height + this.strokeWidth,
pCanvas = createCanvasElementFor({
width,
height
}),
pCtx = pCanvas.getContext('2d');
pCanvas.width = width;
pCanvas.height = height;
Expand Down Expand Up @@ -23738,9 +23776,10 @@ class WebGLFilterBackend {
* class properties to the GLFilterBackend class.
*/
createWebGLCanvas(width, height) {
const canvas = createCanvasElement();
canvas.width = width;
canvas.height = height;
const canvas = createCanvasElementFor({
width,
height
});
const glOptions = {
alpha: true,
premultipliedAlpha: false,
Expand Down Expand Up @@ -24370,15 +24409,15 @@ class FabricImage extends FabricObject {
this._lastScaleY = scaleY;
return;
}
const canvasEl = createCanvasElement(),
sourceWidth = elementToFilter.width,
sourceHeight = elementToFilter.height;
canvasEl.width = sourceWidth;
canvasEl.height = sourceHeight;
const canvasEl = createCanvasElementFor(elementToFilter),
{
width,
height
} = elementToFilter;
this._element = canvasEl;
this._lastScaleX = filter.scaleX = scaleX;
this._lastScaleY = filter.scaleY = scaleY;
getFilterBackend().applyFilters([filter], elementToFilter, sourceWidth, sourceHeight, this._element);
getFilterBackend().applyFilters([filter], elementToFilter, width, height, this._element);
this._filterScalingX = canvasEl.width / this._originalElement.width;
this._filterScalingY = canvasEl.height / this._originalElement.height;
}
Expand Down Expand Up @@ -24410,9 +24449,10 @@ class FabricImage extends FabricObject {
if (this._element === this._originalElement) {
// if the _element a reference to _originalElement
// we need to create a new element to host the filtered pixels
const canvasEl = createCanvasElement();
canvasEl.width = sourceWidth;
canvasEl.height = sourceHeight;
const canvasEl = createCanvasElementFor({
width: sourceWidth,
height: sourceHeight
});
this._element = canvasEl;
this._filteredEl = canvasEl;
} else if (this._filteredEl) {
Expand Down Expand Up @@ -25093,7 +25133,7 @@ class ElementsParser {
const objTransformInv = invertTransform(obj.calcTransformMatrix());
const clipPathTag = clipPathElements[0].parentElement;
let clipPathOwner = usingElement;
while (clipPathOwner.parentElement && clipPathOwner.getAttribute('clip-path') !== obj.clipPath) {
while (clipPathOwner.parentElement && clipPathOwner.getAttribute('clip-path') && clipPathOwner.getAttribute('clip-path') !== obj.clipPath) {
clipPathOwner = clipPathOwner.parentElement;
}
// move the clipPath tag as sibling to the real element that is using it
Expand Down Expand Up @@ -25530,7 +25570,10 @@ const isWebGLPipelineState = options => {
* putImageData is faster than drawImage for that specific operation.
*/
const isPutImageFaster = (width, height) => {
const targetCanvas = createCanvasElement();
const targetCanvas = createCanvasElementFor({
width,
height
});
const sourceCanvas = createCanvasElement();
const gl = sourceCanvas.getContext('webgl');
// eslint-disable-next-line no-undef
Expand All @@ -25544,8 +25587,6 @@ const isPutImageFaster = (width, height) => {
targetCanvas: targetCanvas
};
let startTime;
targetCanvas.width = width;
targetCanvas.height = height;
startTime = getFabricWindow().performance.now();
WebGLFilterBackend.prototype.copyGLTo2D.call(testContext, gl, testPipelineState);
const drawImageTime = getFabricWindow().performance.now() - startTime;
Expand Down Expand Up @@ -25833,9 +25874,14 @@ class BaseFilter {
*/
createHelpLayer(options) {
if (!options.helpLayer) {
const helpLayer = createCanvasElement();
helpLayer.width = options.sourceWidth;
helpLayer.height = options.sourceHeight;
const {
sourceWidth,
sourceHeight
} = options;
const helpLayer = createCanvasElementFor({
width: sourceWidth,
height: sourceHeight
});
options.helpLayer = helpLayer;
}
}
Expand Down
2 changes: 1 addition & 1 deletion dist/index.mjs.map

Large diffs are not rendered by default.

Loading

0 comments on commit f1a1408

Please sign in to comment.