From d2571c94f3733b47acaf2a3d38f2c9610fe82609 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Fri, 26 Aug 2022 10:38:18 +0200 Subject: [PATCH] chore(TS) convert more utils (#8180) Co-authored-by: ShaMan123 --- src/point.class.ts | 2 +- src/util/lang_object.ts | 2 + src/util/misc/boundingBoxFromPoints.ts | 35 +++++++ src/util/misc/matrix.ts | 6 +- src/util/misc/misc.ts | 139 +++---------------------- src/util/misc/objectTransforms.ts | 91 ++++++++++++++++ 6 files changed, 146 insertions(+), 129 deletions(-) create mode 100644 src/util/misc/boundingBoxFromPoints.ts create mode 100644 src/util/misc/objectTransforms.ts diff --git a/src/point.class.ts b/src/point.class.ts index ec7be726a2a..c868a5e368a 100644 --- a/src/point.class.ts +++ b/src/point.class.ts @@ -370,7 +370,7 @@ export class Point { * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied * @return {Point} The transformed point */ - transform(t: TMat2D, ignoreOffset: boolean): Point { + transform(t: TMat2D, ignoreOffset = false): Point { return new Point( t[0] * this.x + t[2] * this.y + (ignoreOffset ? 0 : t[4]), t[1] * this.x + t[3] * this.y + (ignoreOffset ? 0 : t[5]) diff --git a/src/util/lang_object.ts b/src/util/lang_object.ts index 5453712fa67..fea951b98c8 100644 --- a/src/util/lang_object.ts +++ b/src/util/lang_object.ts @@ -1,5 +1,7 @@ //@ts-nocheck +import { fabric } from "../../HEADER"; + /** * Copies all enumerable properties of one js object to another * this does not and cannot compete with generic utils. diff --git a/src/util/misc/boundingBoxFromPoints.ts b/src/util/misc/boundingBoxFromPoints.ts new file mode 100644 index 00000000000..6dd1d479eda --- /dev/null +++ b/src/util/misc/boundingBoxFromPoints.ts @@ -0,0 +1,35 @@ +import { Point } from '../../point.class'; +import { TMat2D } from '../../typedefs'; +import { transformPoint } from './matrix'; + +/** + * Returns coordinates of points's bounding rectangle (left, top, width, height) + * This function does not make sense. + * - it mutates the input in case transform is present + * - is used in 2 instances of the app one with the transform one without + * @static + * @memberOf fabric.util + * @param {Point[]} points 4 points array + * @param {TMat2D} [transform] an array of 6 numbers representing a 2x3 transform matrix + * @return {Object} Object with left, top, width, height properties + */ +export const makeBoundingBoxFromPoints = (points: Point[], transform: TMat2D) => { + if (transform) { + for (let i = 0; i < points.length; i++) { + points[i] = transformPoint(points[i], transform); + } + } + const left = Math.min(points[0].x, points[1].x, points[2].x, points[3].x), + right = Math.max(points[0].x, points[1].x, points[2].x, points[3].x), + width = right - left, + top = Math.min(points[0].y, points[1].y, points[2].y, points[3].y), + bottom = Math.max(points[0].y, points[1].y, points[2].y, points[3].y), + height = bottom - top; + + return { + left, + top, + width, + height, + }; +}; diff --git a/src/util/misc/matrix.ts b/src/util/misc/matrix.ts index 49c42027267..4186db24804 100644 --- a/src/util/misc/matrix.ts +++ b/src/util/misc/matrix.ts @@ -23,7 +23,7 @@ type TScaleMatrixArgs = { skewY?: TDegree; } -type TComposeMatrixArgs = TTranslateMatrixArgs & TRotateMatrixArgs & TScaleMatrixArgs; +export type TComposeMatrixArgs = TTranslateMatrixArgs & TRotateMatrixArgs & TScaleMatrixArgs; /** * Apply transform t to point p * @static @@ -33,7 +33,7 @@ type TComposeMatrixArgs = TTranslateMatrixArgs & TRotateMatrixArgs & TScaleMatri * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied * @return {Point} The transformed point */ -export const transformPoint = (p: Point | IPoint, t: TMat2D, ignoreOffset: boolean): Point => new Point(p).transform(t, ignoreOffset); +export const transformPoint = (p: Point | IPoint, t: TMat2D, ignoreOffset?: boolean): Point => new Point(p).transform(t, ignoreOffset); /** * Invert transformation t @@ -76,7 +76,7 @@ export const multiplyTransformMatrices = (a: TMat2D, b: TMat2D, is2x2?: boolean) * @param {TMat2D} a transformMatrix * @return {Object} Components of transform */ -export const qrDecompose = (a: TMat2D): TComposeMatrixArgs => { +export const qrDecompose = (a: TMat2D): Required> => { const angle = Math.atan2(a[1], a[0]), denom = Math.pow(a[0], 2) + Math.pow(a[1], 2), scaleX = Math.sqrt(denom), diff --git a/src/util/misc/misc.ts b/src/util/misc/misc.ts index d5485d96bfa..c101fe25482 100644 --- a/src/util/misc/misc.ts +++ b/src/util/misc/misc.ts @@ -30,10 +30,14 @@ import { } from './svgParsing'; import { findScaleToFit, findScaleToCover } from './findScaleTo'; import { capValue } from './capValue'; - - /** - * @typedef {[number,number,number,number,number,number]} Matrix - */ +import { + saveObjectTransform, + resetObjectTransform, + addTransformToObject, + applyTransformToObject, + removeTransformFromObject, +} from './objectTransforms'; +import { makeBoundingBoxFromPoints } from './boundingBoxFromPoints'; /** * @namespace fabric.util @@ -82,6 +86,12 @@ import { capValue } from './capValue'; findScaleToFit, findScaleToCover, capValue, + saveObjectTransform, + resetObjectTransform, + addTransformToObject, + applyTransformToObject, + removeTransformFromObject, + makeBoundingBoxFromPoints, /** * Sends a point from the source coordinate plane to the destination coordinate plane.\ * From the canvas/viewer's perspective the point remains unchanged. @@ -142,37 +152,6 @@ import { capValue } from './capValue'; return fabric.util.transformPoint(point, relationAfter === 'child' ? fabric.util.invertTransform(t) : t); }, - /** - * Returns coordinates of points's bounding rectangle (left, top, width, height) - * @static - * @memberOf fabric.util - * @param {Array} points 4 points array - * @param {Array} [transform] an array of 6 numbers representing a 2x3 transform matrix - * @return {Object} Object with left, top, width, height properties - */ - makeBoundingBoxFromPoints: function(points, transform) { - if (transform) { - for (var i = 0; i < points.length; i++) { - points[i] = fabric.util.transformPoint(points[i], transform); - } - } - var xPoints = [points[0].x, points[1].x, points[2].x, points[3].x], - minX = fabric.util.array.min(xPoints), - maxX = fabric.util.array.max(xPoints), - width = maxX - minX, - yPoints = [points[0].y, points[1].y, points[2].y, points[3].y], - minY = fabric.util.array.min(yPoints), - maxY = fabric.util.array.max(yPoints), - height = maxY - minY; - - return { - left: minX, - top: minY, - width: width, - height: height - }; - }, - /** * Returns klass "Class" object of given namespace * @memberOf fabric.util @@ -343,43 +322,6 @@ import { capValue } from './capValue'; } }, - /** - * reset an object transform state to neutral. Top and left are not accounted for - * @static - * @memberOf fabric.util - * @param {fabric.Object} target object to transform - */ - resetObjectTransform: function (target) { - target.scaleX = 1; - target.scaleY = 1; - target.skewX = 0; - target.skewY = 0; - target.flipX = false; - target.flipY = false; - target.rotate(0); - }, - - /** - * Extract Object transform values - * @static - * @memberOf fabric.util - * @param {fabric.Object} target object to read from - * @return {Object} Components of transform - */ - saveObjectTransform: function (target) { - return { - scaleX: target.scaleX, - scaleY: target.scaleY, - skewX: target.skewX, - skewY: target.skewY, - angle: target.angle, - left: target.left, - flipX: target.flipX, - flipY: target.flipY, - top: target.top - }; - }, - /** * Returns true if context has transparent pixel * at specified location (taking tolerance into account) @@ -462,59 +404,6 @@ import { capValue } from './capValue'; return { x: Math.floor(roughWidth), y: perfLimitSizeY }; }, - /** - * given an object and a transform, apply the inverse transform to the object, - * this is equivalent to remove from that object that transformation, so that - * added in a space with the removed transform, the object will be the same as before. - * Removing from an object a transform that scale by 2 is like scaling it by 1/2. - * Removing from an object a transform that rotate by 30deg is like rotating by 30deg - * in the opposite direction. - * This util is used to add objects inside transformed groups or nested groups. - * @memberOf fabric.util - * @param {fabric.Object} object the object you want to transform - * @param {Array} transform the destination transform - */ - removeTransformFromObject: function(object, transform) { - var inverted = fabric.util.invertTransform(transform), - finalTransform = fabric.util.multiplyTransformMatrices(inverted, object.calcOwnMatrix()); - fabric.util.applyTransformToObject(object, finalTransform); - }, - - /** - * given an object and a transform, apply the transform to the object. - * this is equivalent to change the space where the object is drawn. - * Adding to an object a transform that scale by 2 is like scaling it by 2. - * This is used when removing an object from an active selection for example. - * @memberOf fabric.util - * @param {fabric.Object} object the object you want to transform - * @param {Array} transform the destination transform - */ - addTransformToObject: function(object, transform) { - fabric.util.applyTransformToObject( - object, - fabric.util.multiplyTransformMatrices(transform, object.calcOwnMatrix()) - ); - }, - - /** - * discard an object transform state and apply the one from the matrix. - * @memberOf fabric.util - * @param {fabric.Object} object the object you want to transform - * @param {Array} transform the destination transform - */ - applyTransformToObject: function(object, transform) { - var options = fabric.util.qrDecompose(transform), - center = new Point(options.translateX, options.translateY); - object.flipX = false; - object.flipY = false; - object.set('scaleX', options.scaleX); - object.set('scaleY', options.scaleY); - object.skewX = options.skewX; - object.skewY = options.skewY; - object.angle = options.angle; - object.setPositionByOrigin(center, 'center', 'center'); - }, - /** * * A util that abstracts applying transform to objects.\ diff --git a/src/util/misc/objectTransforms.ts b/src/util/misc/objectTransforms.ts new file mode 100644 index 00000000000..a804c71dd3d --- /dev/null +++ b/src/util/misc/objectTransforms.ts @@ -0,0 +1,91 @@ +import { Point } from "../../point.class"; +import { TMat2D } from "../../typedefs"; +import { invertTransform, multiplyTransformMatrices, qrDecompose } from "./matrix"; +import type { TComposeMatrixArgs } from './matrix'; + +type FabricObject = any; + +/** + * given an object and a transform, apply the inverse transform to the object, + * this is equivalent to remove from that object that transformation, so that + * added in a space with the removed transform, the object will be the same as before. + * Removing from an object a transform that scale by 2 is like scaling it by 1/2. + * Removing from an object a transform that rotate by 30deg is like rotating by 30deg + * in the opposite direction. + * This util is used to add objects inside transformed groups or nested groups. + * @memberOf fabric.util + * @param {fabric.Object} object the object you want to transform + * @param {Array} transform the destination transform + */ +export const removeTransformFromObject = (object: FabricObject, transform: TMat2D) => { + const inverted = invertTransform(transform), + finalTransform = multiplyTransformMatrices(inverted, object.calcOwnMatrix()); + applyTransformToObject(object, finalTransform); +}; + +/** + * given an object and a transform, apply the transform to the object. + * this is equivalent to change the space where the object is drawn. + * Adding to an object a transform that scale by 2 is like scaling it by 2. + * This is used when removing an object from an active selection for example. + * @memberOf fabric.util + * @param {fabric.Object} object the object you want to transform + * @param {Array} transform the destination transform + */ +export const addTransformToObject = (object: FabricObject, transform: TMat2D) => + applyTransformToObject( + object, + multiplyTransformMatrices(transform, object.calcOwnMatrix()) + ); + +/** + * discard an object transform state and apply the one from the matrix. + * @memberOf fabric.util + * @param {fabric.Object} object the object you want to transform + * @param {Array} transform the destination transform + */ +export const applyTransformToObject = (object: FabricObject, transform: TMat2D) => { + const { translateX, translateY, scaleX, scaleY, ...otherOptions } = qrDecompose(transform), + center = new Point(translateX, translateY); + object.flipX = false; + object.flipY = false; + Object.assign(object, otherOptions); + object.set({ scaleX, scaleY }); + object.setPositionByOrigin(center, 'center', 'center'); +}; +/** + * reset an object transform state to neutral. Top and left are not accounted for + * @static + * @memberOf fabric.util + * @param {fabric.Object} target object to transform + */ +export const resetObjectTransform = (target: FabricObject) => { + target.scaleX = 1; + target.scaleY = 1; + target.skewX = 0; + target.skewY = 0; + target.flipX = false; + target.flipY = false; + target.rotate(0); +}; + +/** + * Extract Object transform values + * @static + * @memberOf fabric.util + * @param {fabric.Object} target object to read from + * @return {Object} Components of transform + */ +export const saveObjectTransform = ( + target: FabricObject +): TComposeMatrixArgs & { left: number, top: number } =>({ + scaleX: target.scaleX, + scaleY: target.scaleY, + skewX: target.skewX, + skewY: target.skewY, + angle: target.angle, + left: target.left, + flipX: target.flipX, + flipY: target.flipY, + top: target.top +});