From 653946c50c1d6d04c953decfd0873fd873bb04bf Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:14:31 +0200 Subject: [PATCH 01/26] svg --- src/parser/parseAttributes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/parseAttributes.ts b/src/parser/parseAttributes.ts index ae02a0e27ea..d17d4b60650 100644 --- a/src/parser/parseAttributes.ts +++ b/src/parser/parseAttributes.ts @@ -16,7 +16,7 @@ import { setStrokeFillOpacity } from './setStrokeFillOpacity'; * @param {Array} attributes Array of attributes to parse * @return {Object} object containing parsed attributes' names/values */ -export function parseAttributes(element, attributes, svgUid) { +export function parseAttributes(element, attributes, svgUid?: string) { if (!element) { return; } From b371499a478ce41e1ac60d1ce17c3e3c1bb571c4 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:14:40 +0200 Subject: [PATCH 02/26] SHARED_ATTRIBUTES --- HEADER.js | 28 ---------------------------- src/parser/attributes.ts | 25 +++++++++++++++++++++++++ src/parser/index.ts | 3 ++- 3 files changed, 27 insertions(+), 29 deletions(-) create mode 100644 src/parser/attributes.ts diff --git a/HEADER.js b/HEADER.js index 6aef6023249..8a59a9b5e1b 100644 --- a/HEADER.js +++ b/HEADER.js @@ -69,34 +69,6 @@ fabric.isTouchSupported = fabric.isLikelyNode = typeof Buffer !== 'undefined' && typeof window === 'undefined'; -/* _FROM_SVG_START_ */ -/** - * Attributes parsed from all SVG elements - * @type array - */ -fabric.SHARED_ATTRIBUTES = [ - 'display', - 'transform', - 'fill', - 'fill-opacity', - 'fill-rule', - 'opacity', - 'stroke', - 'stroke-dasharray', - 'stroke-linecap', - 'stroke-dashoffset', - 'stroke-linejoin', - 'stroke-miterlimit', - 'stroke-opacity', - 'stroke-width', - 'id', - 'paint-order', - 'vector-effect', - 'instantiated_by_use', - 'clip-path', -]; -/* _FROM_SVG_END_ */ - /** * @todo move to config when window is exported */ diff --git a/src/parser/attributes.ts b/src/parser/attributes.ts new file mode 100644 index 00000000000..f16412dcd5a --- /dev/null +++ b/src/parser/attributes.ts @@ -0,0 +1,25 @@ +/** + * Attributes parsed from all SVG elements + * @type array + */ +export const SHARED_ATTRIBUTES = [ + 'display', + 'transform', + 'fill', + 'fill-opacity', + 'fill-rule', + 'opacity', + 'stroke', + 'stroke-dasharray', + 'stroke-linecap', + 'stroke-dashoffset', + 'stroke-linejoin', + 'stroke-miterlimit', + 'stroke-opacity', + 'stroke-width', + 'id', + 'paint-order', + 'vector-effect', + 'instantiated_by_use', + 'clip-path', +]; diff --git a/src/parser/index.ts b/src/parser/index.ts index 18dffc9314f..02646cbfe65 100644 --- a/src/parser/index.ts +++ b/src/parser/index.ts @@ -1,5 +1,5 @@ -//@ts-nocheck import { fabric } from '../../HEADER'; +import { SHARED_ATTRIBUTES } from './attributes'; import { clipPaths, cssRules, gradientDefs } from './constants'; import { ElementsParser } from './elements_parser'; import { getCSSRules } from './getCSSRules'; @@ -15,6 +15,7 @@ import { parseSVGDocument } from './parseSVGDocument'; import { parseTransformAttribute } from './parseTransformAttribute'; Object.assign(fabric, { + SHARED_ATTRIBUTES, cssRules, gradientDefs, clipPaths, From a71cfc23d6d028600e490a13f20e8f335f9cc427 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:20:37 +0200 Subject: [PATCH 03/26] migrate --- src/shapes/circle.class.ts | 424 ++++++++++++++++++------------------- test/unit/circle.js | 2 +- 2 files changed, 211 insertions(+), 215 deletions(-) diff --git a/src/shapes/circle.class.ts b/src/shapes/circle.class.ts index 690b98db097..a65300c8099 100644 --- a/src/shapes/circle.class.ts +++ b/src/shapes/circle.class.ts @@ -1,232 +1,228 @@ -//@ts-nocheck import { fabric } from '../../HEADER'; +import { SHARED_ATTRIBUTES } from '../parser/attributes'; +import { parseAttributes } from '../parser/parseAttributes'; +import { cos } from '../util/misc/cos'; +import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; +import { sin } from '../util/misc/sin'; import { FabricObject } from './fabricObject.class'; -const degreesToRadians = fabric.util.degreesToRadians; - /** * Circle class * @class Circle * @extends fabric.Object * @see {@link Circle#initialize} for constructor definition */ -const Circle = fabric.util.createClass( - FabricObject, - /** @lends Circle.prototype */ { - /** - * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged}) - * as well as for history (undo/redo) purposes - * @type Array - */ - stateProperties: FabricObject.prototype.stateProperties.concat( - 'radius', - 'startAngle', - 'endAngle' - ), - - /** - * Type of an object - * @type String - * @default - */ - type: 'circle', - - /** - * Radius of this circle - * @type Number - * @default - */ - radius: 0, - - /** - * degrees of start of the circle. - * probably will change to degrees in next major version - * @type Number 0 - 359 - * @default 0 - */ - startAngle: 0, - - /** - * End angle of the circle - * probably will change to degrees in next major version - * @type Number 1 - 360 - * @default 360 - */ - endAngle: 360, - - cacheProperties: FabricObject.prototype.cacheProperties.concat( - 'radius', - 'startAngle', - 'endAngle' - ), - - /** - * @private - * @param {String} key - * @param {*} value - * @return {Circle} thisArg - */ - _set: function (key, value) { - this.callSuper('_set', key, value); - - if (key === 'radius') { - this.setRadius(value); - } - - return this; - }, - - /** - * @private - * @param {CanvasRenderingContext2D} ctx context to render on - */ - _render: function (ctx) { - ctx.beginPath(); - ctx.arc( - 0, - 0, - this.radius, - degreesToRadians(this.startAngle), - degreesToRadians(this.endAngle), - false - ); - this._renderPaintInOrder(ctx); - }, - - /** - * Returns horizontal radius of an object (according to how an object is scaled) - * @return {Number} - */ - getRadiusX: function () { - return this.get('radius') * this.get('scaleX'); - }, - - /** - * Returns vertical radius of an object (according to how an object is scaled) - * @return {Number} - */ - getRadiusY: function () { - return this.get('radius') * this.get('scaleY'); - }, - - /** - * Sets radius of an object (and updates width accordingly) - * @return {Circle} thisArg - */ - setRadius: function (value) { - this.radius = value; - return this.set('width', value * 2).set('height', value * 2); - }, - - /** - * Returns object representation of an instance - * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output - * @return {Object} object representation of an instance - */ - toObject: function (propertiesToInclude) { - return this.callSuper( - 'toObject', - ['radius', 'startAngle', 'endAngle'].concat(propertiesToInclude) - ); - }, - - /* _TO_SVG_START_ */ - - /** - * Returns svg representation of an instance - * @return {Array} an array of strings with the specific svg representation - * of the instance - */ - _toSVG: function () { - const angle = (this.endAngle - this.startAngle) % 360; - - if (angle === 0) { - return [ - '\n', - ]; - } else { - const { radius } = this; - const start = degreesToRadians(this.startAngle), - end = degreesToRadians(this.endAngle), - startX = fabric.util.cos(start) * radius, - startY = fabric.util.sin(start) * radius, - endX = fabric.util.cos(end) * radius, - endY = fabric.util.sin(end) * radius, - largeFlag = angle > 180 ? '1' : '0'; - return [ - '\n', - ]; - } - }, - /* _TO_SVG_END_ */ +export class Circle extends FabricObject { + /** + * Radius of this circle + * @type Number + * @default + */ + radius: number; + + /** + * degrees of start of the circle. + * probably will change to degrees in next major version + * @type Number 0 - 359 + * @default 0 + */ + startAngle: number; + + /** + * End angle of the circle + * probably will change to degrees in next major version + * @type Number 1 - 360 + * @default 360 + */ + endAngle: number; + + /** + * @private + * @param {String} key + * @param {*} value + * @return {Circle} thisArg + */ + _set(key: string, value: any) { + super._set(key, value); + + if (key === 'radius') { + this.setRadius(value); + } + + return this; } -); -/* _FROM_SVG_START_ */ -/** - * List of attribute names to account for when parsing SVG element (used by {@link Circle.fromElement}) - * @static - * @memberOf Circle - * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement - */ -Circle.ATTRIBUTE_NAMES = ['cx', 'cy', 'r', ...fabric.SHARED_ATTRIBUTES]; - -/** - * Returns {@link Circle} instance from an SVG element - * @static - * @memberOf Circle - * @param {SVGElement} element Element to parse - * @param {Function} [callback] Options callback invoked after parsing is finished - * @param {Object} [options] Partial Circle object to default missing properties on the element. - * @throws {Error} If value of `r` attribute is missing or invalid - */ -Circle.fromElement = function (element, callback) { - const { - left = 0, - top = 0, - radius, - ...otherParsedAttributes - } = fabric.parseAttributes(element, Circle.ATTRIBUTE_NAMES); - - if (!radius || radius < 0) { - throw new Error( - 'value of `r` attribute is required and can not be negative' + /** + * @private + * @param {CanvasRenderingContext2D} ctx context to render on + */ + _render(ctx: CanvasRenderingContext2D) { + ctx.beginPath(); + ctx.arc( + 0, + 0, + this.radius, + degreesToRadians(this.startAngle), + degreesToRadians(this.endAngle), + false ); + this._renderPaintInOrder(ctx); } - // this probably requires to be fixed for default origins not being top/left. - callback( - new fabric.Circle({ - ...otherParsedAttributes, - radius, - left: left - radius, - top: top - radius, - }) - ); -}; + /** + * Returns horizontal radius of an object (according to how an object is scaled) + * @return {Number} + */ + getRadiusX(): number { + return this.get('radius') * this.get('scaleX'); + } -/* _FROM_SVG_END_ */ + /** + * Returns vertical radius of an object (according to how an object is scaled) + * @return {Number} + */ + getRadiusY(): number { + return this.get('radius') * this.get('scaleY'); + } -/** - * Returns {@link Circle} instance from an object representation - * @static - * @memberOf Circle - * @param {Object} object Object to create an instance from - * @returns {Promise} - */ -Circle.fromObject = (object) => FabricObject._fromObject(fabric.Circle, object); + /** + * Sets radius of an object (and updates width accordingly) + */ + setRadius(value: number) { + this.radius = value; + this.set({ width: value * 2, height: value * 2 }); + } + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject(propertiesToInclude: (keyof this)[] = []): object { + return super.toObject([ + 'radius', + 'startAngle', + 'endAngle', + ...propertiesToInclude, + ]); + } + + /* _TO_SVG_START_ */ + + /** + * Returns svg representation of an instance + * @return {Array} an array of strings with the specific svg representation + * of the instance + */ + _toSVG(): (string | number)[] { + const angle = (this.endAngle - this.startAngle) % 360; + + if (angle === 0) { + return [ + '\n', + ]; + } else { + const { radius } = this; + const start = degreesToRadians(this.startAngle), + end = degreesToRadians(this.endAngle), + startX = cos(start) * radius, + startY = sin(start) * radius, + endX = cos(end) * radius, + endY = sin(end) * radius, + largeFlag = angle > 180 ? '1' : '0'; + return [ + '\n', + ]; + } + } + /* _TO_SVG_END_ */ + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link Circle.fromElement}) + * @static + * @memberOf Circle + * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement + */ + static ATTRIBUTE_NAMES = ['cx', 'cy', 'r', ...SHARED_ATTRIBUTES]; + + /** + * Returns {@link Circle} instance from an SVG element + * @static + * @memberOf Circle + * @param {SVGElement} element Element to parse + * @param {Function} [callback] Options callback invoked after parsing is finished + * @param {Object} [options] Partial Circle object to default missing properties on the element. + * @throws {Error} If value of `r` attribute is missing or invalid + */ + static fromElement = function ( + element: SVGElement, + callback: (circle: Circle) => any + ) { + const { + left = 0, + top = 0, + radius, + ...otherParsedAttributes + } = parseAttributes(element, Circle.ATTRIBUTE_NAMES); + + if (!radius || radius < 0) { + throw new Error( + 'value of `r` attribute is required and can not be negative' + ); + } + + // this probably requires to be fixed for default origins not being top/left. + callback( + new Circle({ + ...otherParsedAttributes, + radius, + left: left - radius, + top: top - radius, + }) + ); + }; + + /* _FROM_SVG_END_ */ + + /** + * Returns {@link Circle} instance from an object representation + * @static + * @memberOf Circle + * @param {Object} object Object to create an instance from + * @returns {Promise} + */ + static fromObject = (object: object): Promise => + FabricObject._fromObject(Circle, object); +} + +Object.assign(Circle.prototype, { + type: 'circle', + radius: 0, + startAngle: 0, + endAngle: 360, + stateProperties: FabricObject.prototype.stateProperties.concat( + 'radius', + 'startAngle', + 'endAngle' + ), + cacheProperties: FabricObject.prototype.cacheProperties.concat( + 'radius', + 'startAngle', + 'endAngle' + ), +}); fabric.Circle = Circle; -export { Circle }; diff --git a/test/unit/circle.js b/test/unit/circle.js index b12575139dd..789a81ec506 100644 --- a/test/unit/circle.js +++ b/test/unit/circle.js @@ -56,7 +56,7 @@ assert.equal(circle.width, 20); assert.equal(circle.height, 20); - assert.equal(circle, circle.setRadius(20)); + circle.setRadius(20); assert.equal(circle.getRadiusX(), 20); assert.equal(circle.getRadiusY(), 20); From e169232e46d194729cfc95ee57a45eb1d3317fe2 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:24:04 +0200 Subject: [PATCH 04/26] Update circle.class.ts --- src/shapes/circle.class.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/shapes/circle.class.ts b/src/shapes/circle.class.ts index a65300c8099..f474820c6ae 100644 --- a/src/shapes/circle.class.ts +++ b/src/shapes/circle.class.ts @@ -6,12 +6,6 @@ import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; import { sin } from '../util/misc/sin'; import { FabricObject } from './fabricObject.class'; -/** - * Circle class - * @class Circle - * @extends fabric.Object - * @see {@link Circle#initialize} for constructor definition - */ export class Circle extends FabricObject { /** * Radius of this circle @@ -40,7 +34,6 @@ export class Circle extends FabricObject { * @private * @param {String} key * @param {*} value - * @return {Circle} thisArg */ _set(key: string, value: any) { super._set(key, value); From b0d03793c19361006dfde7bc1ebd0eb66187391a Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:26:36 +0200 Subject: [PATCH 05/26] Update circle.class.ts --- src/shapes/circle.class.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/shapes/circle.class.ts b/src/shapes/circle.class.ts index f474820c6ae..dcef31c82ef 100644 --- a/src/shapes/circle.class.ts +++ b/src/shapes/circle.class.ts @@ -1,6 +1,7 @@ import { fabric } from '../../HEADER'; import { SHARED_ATTRIBUTES } from '../parser/attributes'; import { parseAttributes } from '../parser/parseAttributes'; +import { TClassProperties } from '../typedefs'; import { cos } from '../util/misc/cos'; import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; import { sin } from '../util/misc/sin'; @@ -201,7 +202,7 @@ export class Circle extends FabricObject { FabricObject._fromObject(Circle, object); } -Object.assign(Circle.prototype, { +export const defaultValues: Partial> = { type: 'circle', radius: 0, startAngle: 0, @@ -216,6 +217,8 @@ Object.assign(Circle.prototype, { 'startAngle', 'endAngle' ), -}); +}; + +Object.assign(Circle.prototype, defaultValues); fabric.Circle = Circle; From 4e7e4985b8765791d5753313d4e3cfa903806b85 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:29:49 +0200 Subject: [PATCH 06/26] defaults --- src/shapes/circle.class.ts | 9 +++++---- src/shapes/object.class.ts | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/shapes/circle.class.ts b/src/shapes/circle.class.ts index dcef31c82ef..254cf359ccf 100644 --- a/src/shapes/circle.class.ts +++ b/src/shapes/circle.class.ts @@ -6,6 +6,7 @@ import { cos } from '../util/misc/cos'; import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; import { sin } from '../util/misc/sin'; import { FabricObject } from './fabricObject.class'; +import { fabricObjectDefaultValues } from './object.class'; export class Circle extends FabricObject { /** @@ -202,23 +203,23 @@ export class Circle extends FabricObject { FabricObject._fromObject(Circle, object); } -export const defaultValues: Partial> = { +export const circleDefaultValues: Partial> = { type: 'circle', radius: 0, startAngle: 0, endAngle: 360, - stateProperties: FabricObject.prototype.stateProperties.concat( + stateProperties: fabricObjectDefaultValues.stateProperties.concat( 'radius', 'startAngle', 'endAngle' ), - cacheProperties: FabricObject.prototype.cacheProperties.concat( + cacheProperties: fabricObjectDefaultValues.cacheProperties.concat( 'radius', 'startAngle', 'endAngle' ), }; -Object.assign(Circle.prototype, defaultValues); +Object.assign(Circle.prototype, circleDefaultValues); fabric.Circle = Circle; diff --git a/src/shapes/object.class.ts b/src/shapes/object.class.ts index ceeee9e14a7..2be5a720649 100644 --- a/src/shapes/object.class.ts +++ b/src/shapes/object.class.ts @@ -1991,7 +1991,7 @@ export class FabricObject extends ObjectGeometry { } } -const fabricObjectDefaultValues: TClassProperties = { +export const fabricObjectDefaultValues: TClassProperties = { type: 'object', originX: 'left', originY: 'top', From 403d791c9e07bfa387c4205fd2e4af17c8d63656 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:31:13 +0200 Subject: [PATCH 07/26] static --- src/shapes/circle.class.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/shapes/circle.class.ts b/src/shapes/circle.class.ts index 254cf359ccf..dfbb9c83cc1 100644 --- a/src/shapes/circle.class.ts +++ b/src/shapes/circle.class.ts @@ -162,10 +162,7 @@ export class Circle extends FabricObject { * @param {Object} [options] Partial Circle object to default missing properties on the element. * @throws {Error} If value of `r` attribute is missing or invalid */ - static fromElement = function ( - element: SVGElement, - callback: (circle: Circle) => any - ) { + static fromElement(element: SVGElement, callback: (circle: Circle) => any) { const { left = 0, top = 0, @@ -188,7 +185,7 @@ export class Circle extends FabricObject { top: top - radius, }) ); - }; + } /* _FROM_SVG_END_ */ @@ -199,8 +196,9 @@ export class Circle extends FabricObject { * @param {Object} object Object to create an instance from * @returns {Promise} */ - static fromObject = (object: object): Promise => - FabricObject._fromObject(Circle, object); + static fromObject(object: object): Promise { + return FabricObject._fromObject(Circle, object); + } } export const circleDefaultValues: Partial> = { From 575af883da4a1c5e4ac25645fb92cbd7a6a19966 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:33:05 +0200 Subject: [PATCH 08/26] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92517990158..d1d38a56c6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [next] +- chore(TS): migrate Circle [#8406](https://github.com/fabricjs/fabric.js/pull/8406) - chore(TS): convert Object interactivity mixin to its own class [#8401](https://github.com/fabricjs/fabric.js/pull/8401) - chore(TS): Convert controls e6/ts [#8400](https://github.com/fabricjs/fabric.js/pull/8400) - ci(): remove buggy changelog action in favor of `git diff` bash script + direct git how to merge `CHANGELOG.md` [#8309](https://github.com/fabricjs/fabric.js/pull/8346) From 8f64f7723e514e53cf3b5194d1d8b859f4f79db3 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 20:43:23 +0200 Subject: [PATCH 09/26] init --- src/shapes/polygon.class.ts | 86 ++---- src/shapes/polyline.class.ts | 578 +++++++++++++++++------------------ 2 files changed, 317 insertions(+), 347 deletions(-) diff --git a/src/shapes/polygon.class.ts b/src/shapes/polygon.class.ts index d388ad5d68c..d4fa9160fdd 100644 --- a/src/shapes/polygon.class.ts +++ b/src/shapes/polygon.class.ts @@ -1,77 +1,51 @@ -//@ts-nocheck - -import { projectStrokeOnPoints } from '../util/misc/projectStroke'; - -(function (global) { - var fabric = global.fabric || (global.fabric = {}); - +export class Polygon extends fabric.Polyline { /** - * Polygon class - * @class fabric.Polygon - * @extends fabric.Polyline - * @see {@link fabric.Polygon#initialize} for constructor definition + * @todo make this method protected when migrating */ - fabric.Polygon = fabric.util.createClass( - fabric.Polyline, - /** @lends fabric.Polygon.prototype */ { - /** - * Type of an object - * @type String - * @default - */ - type: 'polygon', - - /** - * @private - */ - _projectStrokeOnPoints: function () { - return projectStrokeOnPoints(this.points, this); - }, - - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - _render: function (ctx) { - if (!this.commonRender(ctx)) { - return; - } - ctx.closePath(); - this._renderPaintInOrder(ctx); - }, - } - ); + isOpen() { + return false; + } - /* _FROM_SVG_START_ */ /** - * List of attribute names to account for when parsing SVG element (used by `fabric.Polygon.fromElement`) + * List of attribute names to account for when parsing SVG element (used by `Polygon.fromElement`) * @static - * @memberOf fabric.Polygon + * @memberOf Polygon * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement */ - fabric.Polygon.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); + static ATTRIBUTE_NAMES = SHARED_ATTRIBUTES.concat(); /** - * Returns {@link fabric.Polygon} instance from an SVG element + * Returns {@link Polygon} instance from an SVG element * @static - * @memberOf fabric.Polygon + * @memberOf Polygon * @param {SVGElement} element Element to parse * @param {Function} callback callback function invoked after parsing * @param {Object} [options] Options object */ - fabric.Polygon.fromElement = fabric.Polyline.fromElementGenerator('Polygon'); - /* _FROM_SVG_END_ */ + static fromElement = fabric.Polyline.fromElementGenerator('Polygon'); /** - * Returns fabric.Polygon instance from an object representation + * Returns Polygon instance from an object representation * @static - * @memberOf fabric.Polygon + * @memberOf Polygon * @param {Object} object Object to create an instance from - * @returns {Promise} + * @returns {Promise} */ - fabric.Polygon.fromObject = function (object) { - return fabric.Object._fromObject(fabric.Polygon, object, { + static fromObject(object) { + return FabricObject._fromObject(Polygon, object, { extraParam: 'points', }); - }; -})(typeof exports !== 'undefined' ? exports : window); + } +} + +export const polygonDefaultValues: Partial> = { + type: 'polygon', +}; + +Object.assign(Polygon.prototype, polygonDefaultValues); +/** @todo TODO_JS_MIGRATION remove next line after refactoring build */ +fabric.Polygon = Polygon; + +/* _FROM_SVG_START_ */ + +/* _FROM_SVG_END_ */ diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index 6584e0348f0..9908d3e1a42 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -1,318 +1,292 @@ -//@ts-nocheck - +import { fabric } from '../../HEADER'; import { config } from '../config'; import { parseAttributes } from '../parser/parseAttributes'; import { parsePointsAttribute } from '../parser/parsePointsAttribute'; import { Point } from '../point.class'; +import { TClassProperties } from '../typedefs'; import { makeBoundingBoxFromPoints } from '../util/misc/boundingBoxFromPoints'; import { projectStrokeOnPoints } from '../util/misc/projectStroke'; import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; +import { toFixed } from '../util/misc/toFixed'; +import { FabricObject } from './object.class'; -(function (global) { - var fabric = global.fabric || (global.fabric = {}), - extend = fabric.util.object.extend, - toFixed = fabric.util.toFixed; - +export class Polyline extends FabricObject { /** - * Polyline class - * @class fabric.Polyline - * @extends fabric.Object - * @see {@link fabric.Polyline#initialize} for constructor definition + * Points array + * @type Array + * @default */ - fabric.Polyline = fabric.util.createClass( - fabric.Object, - /** @lends fabric.Polyline.prototype */ { - /** - * Type of an object - * @type String - * @default - */ - type: 'polyline', - - /** - * Points array - * @type Array - * @default - */ - points: null, - - /** - * WARNING: Feature in progress - * Calculate the exact bounding box taking in account strokeWidth on acute angles - * this will be turned to true by default on fabric 6.0 - * maybe will be left in as an optimization since calculations may be slow - * @deprecated - * @type Boolean - * @default false - * @todo set default to true and remove flag and related logic - */ - exactBoundingBox: false, + points: Point[]; - initialized: false, - - cacheProperties: fabric.Object.prototype.cacheProperties.concat('points'), + /** + * WARNING: Feature in progress + * Calculate the exact bounding box taking in account strokeWidth on acute angles + * this will be turned to true by default on fabric 6.0 + * maybe will be left in as an optimization since calculations may be slow + * @deprecated + * @type Boolean + * @default false + * @todo set default to true and remove flag and related logic + */ + exactBoundingBox: boolean; - /** - * A list of properties that if changed trigger a recalculation of dimensions - * @todo check if you really need to recalculate for all cases - */ - strokeBBoxAffectingProperties: [ - 'skewX', - 'skewY', - 'strokeLineCap', - 'strokeLineJoin', - 'strokeMiterLimit', - 'strokeWidth', - 'strokeUniform', - 'points', - ], + initialized: boolean; - /** - * Constructor - * @param {Array} points Array of points (where each point is an object with x and y) - * @param {Object} [options] Options object - * @return {fabric.Polyline} thisArg - * @example - * var poly = new fabric.Polyline([ - * { x: 10, y: 10 }, - * { x: 50, y: 30 }, - * { x: 40, y: 70 }, - * { x: 60, y: 50 }, - * { x: 100, y: 150 }, - * { x: 40, y: 100 } - * ], { - * stroke: 'red', - * left: 100, - * top: 100 - * }); - */ - initialize: function (points, options = {}) { - this.points = points || []; - this.callSuper('initialize', options); - this.initialized = true; - const bboxTL = this.setDimensions(); - const origin = this.translateToGivenOrigin( - new Point(options.left ?? bboxTL.x, options.top ?? bboxTL.y), - typeof options.left === 'number' ? this.originX : 'left', - typeof options.top === 'number' ? this.originY : 'top', - this.originX, - this.originY - ); - this.setPositionByOrigin(origin, this.originX, this.originY); - }, + /** + * A list of properties that if changed trigger a recalculation of dimensions + * @todo check if you really need to recalculate for all cases + */ + strokeBBoxAffectingProperties: (keyof this)[]; - /** - * @private - */ - _projectStrokeOnPoints: function () { - return projectStrokeOnPoints(this.points, this, true); - }, + /** + * Constructor + * @param {Array} points Array of points (where each point is an object with x and y) + * @param {Object} [options] Options object + * @return {Polyline} thisArg + * @example + * var poly = new Polyline([ + * { x: 10, y: 10 }, + * { x: 50, y: 30 }, + * { x: 40, y: 70 }, + * { x: 60, y: 50 }, + * { x: 100, y: 150 }, + * { x: 40, y: 100 } + * ], { + * stroke: 'red', + * left: 100, + * top: 100 + * }); + */ + constructor(points: Point[] = [], options = {}) { + super({ points, ...options }); + this.initialized = true; + const bboxTL = this.setDimensions(); + const origin = this.translateToGivenOrigin( + new Point(options.left ?? bboxTL.x, options.top ?? bboxTL.y), + typeof options.left === 'number' ? this.originX : 'left', + typeof options.top === 'number' ? this.originY : 'top', + this.originX, + this.originY + ); + this.setPositionByOrigin(origin, this.originX, this.originY); + } - /** - * Calculate the polygon bounding box - * @private - */ - _calcDimensions: function () { - const points = this.exactBoundingBox - ? this._projectStrokeOnPoints().map( - (projection) => projection.projectedPoint - ) - : this.points; - if (points.length === 0) { - return { - left: 0, - top: 0, - width: 0, - height: 0, - pathOffset: new Point(), - }; - } - const bbox = makeBoundingBoxFromPoints(points); - const bboxNoStroke = makeBoundingBoxFromPoints(this.points); - const offsetX = bbox.left + bbox.width / 2, - offsetY = bbox.top + bbox.height / 2; - const pathOffsetX = - offsetX - offsetY * Math.tan(degreesToRadians(this.skewX)); - const pathOffsetY = - offsetY - pathOffsetX * Math.tan(degreesToRadians(this.skewY)); - // TODO: remove next line - const legacyCorrection = - !this.fromSVG && !this.exactBoundingBox ? this.strokeWidth / 2 : 0; - return { - ...bbox, - left: bbox.left - legacyCorrection, - top: bbox.top - legacyCorrection, - pathOffset: new Point(pathOffsetX, pathOffsetY), - strokeOffset: new Point(bboxNoStroke.left, bboxNoStroke.top).subtract( - bbox.left, - bbox.top - ), - }; - }, + /** + * @private + */ + _projectStrokeOnPoints() { + return projectStrokeOnPoints(this.points, this, true); + } - /** - * @returns {Point} top left position of the bounding box, useful for complementary positioning - */ - setDimensions: function () { - const { left, top, width, height, pathOffset, strokeOffset } = - this._calcDimensions(); - this.set({ width, height, pathOffset, strokeOffset }); - return new Point(left, top); - }, + /** + * Calculate the polygon bounding box + * @private + */ + _calcDimensions() { + const points = this.exactBoundingBox + ? this._projectStrokeOnPoints().map( + (projection) => projection.projectedPoint + ) + : this.points; + if (points.length === 0) { + return { + left: 0, + top: 0, + width: 0, + height: 0, + pathOffset: new Point(), + }; + } + const bbox = makeBoundingBoxFromPoints(points); + const bboxNoStroke = makeBoundingBoxFromPoints(this.points); + const offsetX = bbox.left + bbox.width / 2, + offsetY = bbox.top + bbox.height / 2; + const pathOffsetX = + offsetX - offsetY * Math.tan(degreesToRadians(this.skewX)); + const pathOffsetY = + offsetY - pathOffsetX * Math.tan(degreesToRadians(this.skewY)); + // TODO: remove next line + const legacyCorrection = + !this.fromSVG && !this.exactBoundingBox ? this.strokeWidth / 2 : 0; + return { + ...bbox, + left: bbox.left - legacyCorrection, + top: bbox.top - legacyCorrection, + pathOffset: new Point(pathOffsetX, pathOffsetY), + strokeOffset: new Point(bboxNoStroke.left, bboxNoStroke.top).subtract( + bbox.left, + bbox.top + ), + }; + } - /** - * @override stroke is taken in account in size - */ - _getNonTransformedDimensions: function () { - return this.exactBoundingBox - ? new Point(this.width, this.height) - : this.callSuper('_getNonTransformedDimensions'); - }, + /** + * @returns {Point} top left position of the bounding box, useful for complementary positioning + */ + setDimensions() { + const { left, top, width, height, pathOffset, strokeOffset } = + this._calcDimensions(); + this.set({ width, height, pathOffset, strokeOffset }); + return new Point(left, top); + } - /** - * @override stroke and skewing are taken into account when projecting stroke on points, - * therefore we don't want the default calculation to account for skewing as well - * - * @private - */ - _getTransformedDimensions: function (options) { - return this.exactBoundingBox - ? this.callSuper('_getTransformedDimensions', { - ...(options || {}), - // disable stroke bbox calculations - strokeWidth: 0, - // disable skewing bbox calculations - skewX: 0, - skewY: 0, - }) - : this.callSuper('_getTransformedDimensions', options); - }, + /** + * @override stroke is taken in account in size + */ + _getNonTransformedDimensions() { + return this.exactBoundingBox + ? new Point(this.width, this.height) + : super._getNonTransformedDimensions(); + } - /** - * Recalculates dimensions when changing skew and scale - * @private - */ - _set: function (key, value) { - const changed = this.initialized && this[key] !== value; - const output = this.callSuper('_set', key, value); - if ( - changed && - (((key === 'scaleX' || key === 'scaleY') && - this.strokeUniform && - this.strokeBBoxAffectingProperties.includes('strokeUniform') && - this.strokeLineJoin !== 'round') || - this.strokeBBoxAffectingProperties.includes(key)) - ) { - this.setDimensions(); - } - return output; - }, + /** + * @override stroke and skewing are taken into account when projecting stroke on points, + * therefore we don't want the default calculation to account for skewing as well + * + * @private + */ + _getTransformedDimensions(options) { + return this.exactBoundingBox + ? super._getTransformedDimensions({ + ...(options || {}), + // disable stroke bbox calculations + strokeWidth: 0, + // disable skewing bbox calculations + skewX: 0, + skewY: 0, + }) + : super._getTransformedDimensions(options); + } - /** - * Returns object representation of an instance - * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output - * @return {Object} Object representation of an instance - */ - toObject: function (propertiesToInclude) { - return extend(this.callSuper('toObject', propertiesToInclude), { - points: this.points.concat(), - }); - }, + /** + * Recalculates dimensions when changing skew and scale + * @private + */ + _set(key, value) { + const changed = this.initialized && this[key] !== value; + const output = super._set(key, value); + if ( + changed && + (((key === 'scaleX' || key === 'scaleY') && + this.strokeUniform && + this.strokeBBoxAffectingProperties.includes('strokeUniform') && + this.strokeLineJoin !== 'round') || + this.strokeBBoxAffectingProperties.includes(key)) + ) { + this.setDimensions(); + } + return output; + } - /* _TO_SVG_START_ */ - /** - * Returns svg representation of an instance - * @return {Array} an array of strings with the specific svg representation - * of the instance - */ - _toSVG: function () { - var points = [], - diffX = this.pathOffset.x, - diffY = this.pathOffset.y, - NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS; + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} Object representation of an instance + */ + toObject(propertiesToInclude) { + return { + ...super.toObject(propertiesToInclude), + points: this.points.concat(), + }; + } - for (var i = 0, len = this.points.length; i < len; i++) { - points.push( - toFixed(this.points[i].x - diffX, NUM_FRACTION_DIGITS), - ',', - toFixed(this.points[i].y - diffY, NUM_FRACTION_DIGITS), - ' ' - ); - } - return [ - '<' + this.type + ' ', - 'COMMON_PARTS', - 'points="', - points.join(''), - '" />\n', - ]; - }, - /* _TO_SVG_END_ */ + /** + * Returns svg representation of an instance + * @return {Array} an array of strings with the specific svg representation + * of the instance + */ + _toSVG() { + var points = [], + diffX = this.pathOffset.x, + diffY = this.pathOffset.y, + NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS; - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - commonRender: function (ctx) { - var point, - len = this.points.length, - x = this.pathOffset.x, - y = this.pathOffset.y; + for (var i = 0, len = this.points.length; i < len; i++) { + points.push( + toFixed(this.points[i].x - diffX, NUM_FRACTION_DIGITS), + ',', + toFixed(this.points[i].y - diffY, NUM_FRACTION_DIGITS), + ' ' + ); + } + return [ + '<' + this.type + ' ', + 'COMMON_PARTS', + 'points="', + points.join(''), + '" />\n', + ]; + } - if (!len || isNaN(this.points[len - 1].y)) { - // do not draw if no points or odd points - // NaN comes from parseFloat of a empty string in parser - return false; - } - ctx.beginPath(); - ctx.moveTo(this.points[0].x - x, this.points[0].y - y); - for (var i = 0; i < len; i++) { - point = this.points[i]; - ctx.lineTo(point.x - x, point.y - y); - } - return true; - }, + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + commonRender(ctx) { + var point, + len = this.points.length, + x = this.pathOffset.x, + y = this.pathOffset.y; - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - _render: function (ctx) { - if (!this.commonRender(ctx)) { - return; - } - this._renderPaintInOrder(ctx); - }, + if (!len || isNaN(this.points[len - 1].y)) { + // do not draw if no points or odd points + // NaN comes from parseFloat of a empty string in parser + return false; + } + ctx.beginPath(); + ctx.moveTo(this.points[0].x - x, this.points[0].y - y); + for (var i = 0; i < len; i++) { + point = this.points[i]; + ctx.lineTo(point.x - x, point.y - y); + } + return true; + } - /** - * Returns complexity of an instance - * @return {Number} complexity of this instance - */ - complexity: function () { - return this.get('points').length; - }, + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render(ctx) { + if (!this.commonRender(ctx)) { + return; } - ); + this._renderPaintInOrder(ctx); + } - /* _FROM_SVG_START_ */ /** - * List of attribute names to account for when parsing SVG element (used by {@link fabric.Polyline.fromElement}) + * Returns complexity of an instance + * @return {Number} complexity of this instance + */ + complexity() { + return this.get('points').length; + } + + /** + * List of attribute names to account for when parsing SVG element (used by {@link Polyline.fromElement}) * @static - * @memberOf fabric.Polyline + * @memberOf Polyline * @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement */ - fabric.Polyline.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(); + static ATTRIBUTE_NAMES = [...SHARED_ATTRIBUTES]; + + static fromElement = Polyline.fromElementGenerator('Polyline'); /** - * Returns fabric.Polyline instance from an SVG element + * Returns Polyline instance from an SVG element * @static - * @memberOf fabric.Polyline + * @memberOf Polyline * @param {SVGElement} element Element to parser * @param {Function} callback callback function invoked after parsing * @param {Object} [options] Options object */ - fabric.Polyline.fromElementGenerator = function (_class) { - return function (element, callback, options = {}) { + static fromElementGenerator< + K extends { new (points: Point[], options: any): InstanceType } + >(klass: K) { + return function ( + element: SVGElement, + callback: (poly: InstanceType) => any, + options = {} + ) { if (!element) { return callback(null); } @@ -321,33 +295,55 @@ import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; // eslint-disable-next-line @typescript-eslint/no-unused-vars { left, top, ...parsedAttributes } = parseAttributes( element, - fabric[_class].ATTRIBUTE_NAMES + klass.ATTRIBUTE_NAMES ); callback( - new fabric[_class](points, { + new klass(points, { ...parsedAttributes, ...options, fromSVG: true, }) ); }; - }; - - fabric.Polyline.fromElement = - fabric.Polyline.fromElementGenerator('Polyline'); - - /* _FROM_SVG_END_ */ + } /** - * Returns fabric.Polyline instance from an object representation + * Returns Polyline instance from an object representation * @static - * @memberOf fabric.Polyline + * @memberOf Polyline * @param {Object} object Object to create an instance from - * @returns {Promise} + * @returns {Promise} */ - fabric.Polyline.fromObject = function (object) { - return fabric.Object._fromObject(fabric.Polyline, object, { + static fromObject(object) { + return FabricObject._fromObject(Polyline, object, { extraParam: 'points', }); - }; -})(typeof exports !== 'undefined' ? exports : window); + } +} + +export const polylineDefaultValues: Partial> = { + type: 'polyline', + points: [], + exactBoundingBox: false, + initialized: false, + cacheProperties: FabricObject.prototype.cacheProperties.concat('points'), + strokeBBoxAffectingProperties: [ + 'skewX', + 'skewY', + 'strokeLineCap', + 'strokeLineJoin', + 'strokeMiterLimit', + 'strokeWidth', + 'strokeUniform', + 'points', + ], +}; + +Object.assign(Polyline.prototype, polylineDefaultValues); + +/** @todo TODO_JS_MIGRATION remove next line after refactoring build */ +fabric.Polyline = Polyline; + +/* _FROM_SVG_START_ */ + +/* _FROM_SVG_END_ */ From ec4ac19c138d0b161c97c23fe1d6fe553228e656 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 20:46:49 +0200 Subject: [PATCH 10/26] more --- src/shapes/polygon.class.ts | 18 ++++++++++++------ src/shapes/polyline.class.ts | 3 ++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/shapes/polygon.class.ts b/src/shapes/polygon.class.ts index d4fa9160fdd..2815652eb44 100644 --- a/src/shapes/polygon.class.ts +++ b/src/shapes/polygon.class.ts @@ -1,4 +1,10 @@ -export class Polygon extends fabric.Polyline { +import { fabric } from '../../HEADER'; +import { SHARED_ATTRIBUTES } from '../parser/attributes'; +import { TClassProperties } from '../typedefs'; +import { FabricObject } from './object.class'; +import { Polyline } from './polyline.class'; + +export class Polygon extends Polyline { /** * @todo make this method protected when migrating */ @@ -6,6 +12,8 @@ export class Polygon extends fabric.Polyline { return false; } + /* _FROM_SVG_START_ */ + /** * List of attribute names to account for when parsing SVG element (used by `Polygon.fromElement`) * @static @@ -22,7 +30,9 @@ export class Polygon extends fabric.Polyline { * @param {Function} callback callback function invoked after parsing * @param {Object} [options] Options object */ - static fromElement = fabric.Polyline.fromElementGenerator('Polygon'); + static fromElement = Polyline.fromElementGenerator(Polygon); + + /* _FROM_SVG_END_ */ /** * Returns Polygon instance from an object representation @@ -45,7 +55,3 @@ export const polygonDefaultValues: Partial> = { Object.assign(Polygon.prototype, polygonDefaultValues); /** @todo TODO_JS_MIGRATION remove next line after refactoring build */ fabric.Polygon = Polygon; - -/* _FROM_SVG_START_ */ - -/* _FROM_SVG_END_ */ diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index 9908d3e1a42..e023bdaa212 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -1,5 +1,6 @@ import { fabric } from '../../HEADER'; import { config } from '../config'; +import { SHARED_ATTRIBUTES } from '../parser/attributes'; import { parseAttributes } from '../parser/parseAttributes'; import { parsePointsAttribute } from '../parser/parsePointsAttribute'; import { Point } from '../point.class'; @@ -269,7 +270,7 @@ export class Polyline extends FabricObject { */ static ATTRIBUTE_NAMES = [...SHARED_ATTRIBUTES]; - static fromElement = Polyline.fromElementGenerator('Polyline'); + static fromElement = Polyline.fromElementGenerator(Polyline); /** * Returns Polyline instance from an SVG element From 1c21ea14706975baa7836b255478e2dcb17feebe Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 22:15:02 +0200 Subject: [PATCH 11/26] m --- src/shapes/polygon.class.ts | 5 +---- src/shapes/polyline.class.ts | 41 ++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/shapes/polygon.class.ts b/src/shapes/polygon.class.ts index 2815652eb44..03b84e0c27c 100644 --- a/src/shapes/polygon.class.ts +++ b/src/shapes/polygon.class.ts @@ -5,10 +5,7 @@ import { FabricObject } from './object.class'; import { Polyline } from './polyline.class'; export class Polygon extends Polyline { - /** - * @todo make this method protected when migrating - */ - isOpen() { + protected isOpen() { return false; } diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index e023bdaa212..c4d13192c80 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -58,7 +58,7 @@ export class Polyline extends FabricObject { * top: 100 * }); */ - constructor(points: Point[] = [], options = {}) { + constructor(points: Point[] = [], options: object = {}): Polyline { super({ points, ...options }); this.initialized = true; const bboxTL = this.setDimensions(); @@ -72,11 +72,12 @@ export class Polyline extends FabricObject { this.setPositionByOrigin(origin, this.originX, this.originY); } - /** - * @private - */ - _projectStrokeOnPoints() { - return projectStrokeOnPoints(this.points, this, true); + protected isOpen() { + return true; + } + + private _projectStrokeOnPoints() { + return projectStrokeOnPoints(this.points, this, this.isOpen); } /** @@ -124,7 +125,7 @@ export class Polyline extends FabricObject { /** * @returns {Point} top left position of the bounding box, useful for complementary positioning */ - setDimensions() { + setDimensions(): Point { const { left, top, width, height, pathOffset, strokeOffset } = this._calcDimensions(); this.set({ width, height, pathOffset, strokeOffset }); @@ -184,7 +185,7 @@ export class Polyline extends FabricObject { * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output * @return {Object} Object representation of an instance */ - toObject(propertiesToInclude) { + toObject(propertiesToInclude: Array): object { return { ...super.toObject(propertiesToInclude), points: this.points.concat(), @@ -196,13 +197,13 @@ export class Polyline extends FabricObject { * @return {Array} an array of strings with the specific svg representation * of the instance */ - _toSVG() { - var points = [], + _toSVG(): Array { + const points = [], diffX = this.pathOffset.x, diffY = this.pathOffset.y, NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS; - for (var i = 0, len = this.points.length; i < len; i++) { + for (let i = 0, len = this.points.length; i < len; i++) { points.push( toFixed(this.points[i].x - diffX, NUM_FRACTION_DIGITS), ',', @@ -223,8 +224,8 @@ export class Polyline extends FabricObject { * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - commonRender(ctx) { - var point, + commonRender(ctx: CanvasRenderingContext2D) { + let point, len = this.points.length, x = this.pathOffset.x, y = this.pathOffset.y; @@ -236,7 +237,7 @@ export class Polyline extends FabricObject { } ctx.beginPath(); ctx.moveTo(this.points[0].x - x, this.points[0].y - y); - for (var i = 0; i < len; i++) { + for (let i = 0; i < len; i++) { point = this.points[i]; ctx.lineTo(point.x - x, point.y - y); } @@ -247,7 +248,7 @@ export class Polyline extends FabricObject { * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - _render(ctx) { + _render(ctx: CanvasRenderingContext2D) { if (!this.commonRender(ctx)) { return; } @@ -258,8 +259,8 @@ export class Polyline extends FabricObject { * Returns complexity of an instance * @return {Number} complexity of this instance */ - complexity() { - return this.get('points').length; + complexity(): number { + return this.points.length; } /** @@ -280,9 +281,7 @@ export class Polyline extends FabricObject { * @param {Function} callback callback function invoked after parsing * @param {Object} [options] Options object */ - static fromElementGenerator< - K extends { new (points: Point[], options: any): InstanceType } - >(klass: K) { + static fromElementGenerator(klass: K) { return function ( element: SVGElement, callback: (poly: InstanceType) => any, @@ -315,7 +314,7 @@ export class Polyline extends FabricObject { * @param {Object} object Object to create an instance from * @returns {Promise} */ - static fromObject(object) { + static fromObject(object: object): Promise { return FabricObject._fromObject(Polyline, object, { extraParam: 'points', }); From 4ba47fa5556ba27d952f281822147567ed1550e6 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 22:29:13 +0200 Subject: [PATCH 12/26] poly --- src/parser/parsePointsAttribute.ts | 15 +++++++-------- src/shapes/polyline.class.ts | 20 +++++++++++++------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/parser/parsePointsAttribute.ts b/src/parser/parsePointsAttribute.ts index 1ac59752231..636f4c6ac9c 100644 --- a/src/parser/parsePointsAttribute.ts +++ b/src/parser/parsePointsAttribute.ts @@ -1,5 +1,7 @@ //@ts-nocheck +import { Point } from '../point.class'; + /** * Parses "points" attribute, returning an array of values * @static @@ -17,15 +19,12 @@ export function parsePointsAttribute(points) { points = points.replace(/,/g, ' ').trim(); points = points.split(/\s+/); - let parsedPoints = [], - i, - len; + const parsedPoints: Point[] = []; - for (i = 0, len = points.length; i < len; i += 2) { - parsedPoints.push({ - x: parseFloat(points[i]), - y: parseFloat(points[i + 1]), - }); + for (let i = 0; i < points.length; i += 2) { + parsedPoints.push( + new Point(parseFloat(points[i]), parseFloat(points[i + 1])) + ); } // odd number of points is an error diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index c4d13192c80..41c24ff85f2 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -38,6 +38,8 @@ export class Polyline extends FabricObject { * @todo check if you really need to recalculate for all cases */ strokeBBoxAffectingProperties: (keyof this)[]; + fromSVG: boolean; + pathOffset: Point; /** * Constructor @@ -58,7 +60,7 @@ export class Polyline extends FabricObject { * top: 100 * }); */ - constructor(points: Point[] = [], options: object = {}): Polyline { + constructor(points: Point[] = [], options: any = {}) { super({ points, ...options }); this.initialized = true; const bboxTL = this.setDimensions(); @@ -116,8 +118,7 @@ export class Polyline extends FabricObject { top: bbox.top - legacyCorrection, pathOffset: new Point(pathOffsetX, pathOffsetY), strokeOffset: new Point(bboxNoStroke.left, bboxNoStroke.top).subtract( - bbox.left, - bbox.top + new Point(bbox.left, bbox.top) ), }; } @@ -197,7 +198,7 @@ export class Polyline extends FabricObject { * @return {Array} an array of strings with the specific svg representation * of the instance */ - _toSVG(): Array { + _toSVG() { const points = [], diffX = this.pathOffset.x, diffY = this.pathOffset.y, @@ -281,10 +282,15 @@ export class Polyline extends FabricObject { * @param {Function} callback callback function invoked after parsing * @param {Object} [options] Options object */ - static fromElementGenerator(klass: K) { + static fromElementGenerator< + T extends { + new (points: Point[], options: any): any; + ATTRIBUTE_NAMES: string[]; + } + >(klass: T) { return function ( element: SVGElement, - callback: (poly: InstanceType) => any, + callback: (poly: InstanceType) => any, options = {} ) { if (!element) { @@ -298,7 +304,7 @@ export class Polyline extends FabricObject { klass.ATTRIBUTE_NAMES ); callback( - new klass(points, { + new klass(points || [], { ...parsedAttributes, ...options, fromSVG: true, From c66798cfb7e65c98653f76c4645a649d293f25b4 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 22:30:14 +0200 Subject: [PATCH 13/26] Update polyline.class.ts --- src/shapes/polyline.class.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index 41c24ff85f2..a1fcbbecdc9 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -253,6 +253,7 @@ export class Polyline extends FabricObject { if (!this.commonRender(ctx)) { return; } + !this.isOpen() && ctx.closePath(); this._renderPaintInOrder(ctx); } From 63442ff41093e758de62a3d95c0dd29f92b5a13b Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 22:43:16 +0200 Subject: [PATCH 14/26] more --- src/mixins/object_origin.mixin.ts | 4 ++-- src/shapes/object.class.ts | 6 +++--- src/shapes/polygon.class.ts | 11 +---------- src/shapes/polyline.class.ts | 16 ++++++++-------- 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/mixins/object_origin.mixin.ts b/src/mixins/object_origin.mixin.ts index 37ac9e11afe..f5b12cc465f 100644 --- a/src/mixins/object_origin.mixin.ts +++ b/src/mixins/object_origin.mixin.ts @@ -1,10 +1,10 @@ import { Point } from '../point.class'; import { transformPoint } from '../util/misc/matrix'; import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; -import { CommonMethods } from './shared_methods.mixin'; -import { TDegree, TOriginX, TOriginY } from '../typedefs'; import { Group } from '../shapes/group.class'; +import { TDegree, TOriginX, TOriginY } from '../typedefs'; import { sizeAfterTransform } from '../util/misc/objectTransforms'; +import { CommonMethods } from './shared_methods.mixin'; const originOffset = { left: -0.5, diff --git a/src/shapes/object.class.ts b/src/shapes/object.class.ts index 2be5a720649..52379133a1d 100644 --- a/src/shapes/object.class.ts +++ b/src/shapes/object.class.ts @@ -235,14 +235,14 @@ export class FabricObject extends ObjectGeometry { * @type String * @default butt */ - strokeLineCap: string; + strokeLineCap: CanvasLineCap; /** * Corner style of an object's stroke (one of "bevel", "round", "miter") * @type String * @default */ - strokeLineJoin: string; + strokeLineJoin: CanvasLineJoin; /** * Maximum miter length (used for strokeLineJoin = "miter") of an object's stroke @@ -1012,7 +1012,7 @@ export class FabricObject extends ObjectGeometry { * @param {*} value * @return {fabric.Object} thisArg */ - _set(key: string, value: any) { + _set(key: K, value: V) { const shouldConstrainValue = key === 'scaleX' || key === 'scaleY', isChanged = this[key] !== value; diff --git a/src/shapes/polygon.class.ts b/src/shapes/polygon.class.ts index 03b84e0c27c..f8ad577c8f0 100644 --- a/src/shapes/polygon.class.ts +++ b/src/shapes/polygon.class.ts @@ -1,5 +1,4 @@ import { fabric } from '../../HEADER'; -import { SHARED_ATTRIBUTES } from '../parser/attributes'; import { TClassProperties } from '../typedefs'; import { FabricObject } from './object.class'; import { Polyline } from './polyline.class'; @@ -11,14 +10,6 @@ export class Polygon extends Polyline { /* _FROM_SVG_START_ */ - /** - * List of attribute names to account for when parsing SVG element (used by `Polygon.fromElement`) - * @static - * @memberOf Polygon - * @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement - */ - static ATTRIBUTE_NAMES = SHARED_ATTRIBUTES.concat(); - /** * Returns {@link Polygon} instance from an SVG element * @static @@ -38,7 +29,7 @@ export class Polygon extends Polyline { * @param {Object} object Object to create an instance from * @returns {Promise} */ - static fromObject(object) { + static fromObject(object: any) { return FabricObject._fromObject(Polygon, object, { extraParam: 'points', }); diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index a1fcbbecdc9..d6e98444c9a 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -79,7 +79,7 @@ export class Polyline extends FabricObject { } private _projectStrokeOnPoints() { - return projectStrokeOnPoints(this.points, this, this.isOpen); + return projectStrokeOnPoints(this.points, this, this.isOpen()); } /** @@ -99,6 +99,7 @@ export class Polyline extends FabricObject { width: 0, height: 0, pathOffset: new Point(), + strokeOffset: new Point(), }; } const bbox = makeBoundingBoxFromPoints(points); @@ -148,7 +149,7 @@ export class Polyline extends FabricObject { * * @private */ - _getTransformedDimensions(options) { + _getTransformedDimensions(options: any) { return this.exactBoundingBox ? super._getTransformedDimensions({ ...(options || {}), @@ -165,7 +166,7 @@ export class Polyline extends FabricObject { * Recalculates dimensions when changing skew and scale * @private */ - _set(key, value) { + _set(key: K, value: V) { const changed = this.initialized && this[key] !== value; const output = super._set(key, value); if ( @@ -186,7 +187,7 @@ export class Polyline extends FabricObject { * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output * @return {Object} Object representation of an instance */ - toObject(propertiesToInclude: Array): object { + toObject(propertiesToInclude: (keyof this)[]): object { return { ...super.toObject(propertiesToInclude), points: this.points.concat(), @@ -226,8 +227,7 @@ export class Polyline extends FabricObject { * @param {CanvasRenderingContext2D} ctx Context to render on */ commonRender(ctx: CanvasRenderingContext2D) { - let point, - len = this.points.length, + const len = this.points.length, x = this.pathOffset.x, y = this.pathOffset.y; @@ -239,7 +239,7 @@ export class Polyline extends FabricObject { ctx.beginPath(); ctx.moveTo(this.points[0].x - x, this.points[0].y - y); for (let i = 0; i < len; i++) { - point = this.points[i]; + const point = this.points[i]; ctx.lineTo(point.x - x, point.y - y); } return true; @@ -291,7 +291,7 @@ export class Polyline extends FabricObject { >(klass: T) { return function ( element: SVGElement, - callback: (poly: InstanceType) => any, + callback: (poly: InstanceType | null) => any, options = {} ) { if (!element) { From fd2afa64b9b644ff68cd6c9f8c392d0ee52fdd6a Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 22:48:26 +0200 Subject: [PATCH 15/26] unpleasant --- src/shapes/object.class.ts | 2 +- src/shapes/polyline.class.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shapes/object.class.ts b/src/shapes/object.class.ts index 52379133a1d..1a3ad04d2c6 100644 --- a/src/shapes/object.class.ts +++ b/src/shapes/object.class.ts @@ -1012,7 +1012,7 @@ export class FabricObject extends ObjectGeometry { * @param {*} value * @return {fabric.Object} thisArg */ - _set(key: K, value: V) { + _set(key: string, value: any) { const shouldConstrainValue = key === 'scaleX' || key === 'scaleY', isChanged = this[key] !== value; diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index d6e98444c9a..e5dc538f853 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -166,8 +166,8 @@ export class Polyline extends FabricObject { * Recalculates dimensions when changing skew and scale * @private */ - _set(key: K, value: V) { - const changed = this.initialized && this[key] !== value; + _set(key: string, value: any) { + const changed = this.initialized && this[key as keyof this] !== value; const output = super._set(key, value); if ( changed && @@ -175,7 +175,7 @@ export class Polyline extends FabricObject { this.strokeUniform && this.strokeBBoxAffectingProperties.includes('strokeUniform') && this.strokeLineJoin !== 'round') || - this.strokeBBoxAffectingProperties.includes(key)) + this.strokeBBoxAffectingProperties.includes(key as keyof this)) ) { this.setDimensions(); } From 4b6cc542c542d9bbc003de74ac141db89467b64d Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 22:51:38 +0200 Subject: [PATCH 16/26] imports --- src/shapes/polyline.class.ts | 5 +++-- test/unit/polygon.js | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index e5dc538f853..ab689747e1c 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -9,7 +9,8 @@ import { makeBoundingBoxFromPoints } from '../util/misc/boundingBoxFromPoints'; import { projectStrokeOnPoints } from '../util/misc/projectStroke'; import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; import { toFixed } from '../util/misc/toFixed'; -import { FabricObject } from './object.class'; +import { FabricObject } from './fabricObject.class'; +import { fabricObjectDefaultValues } from './object.class'; export class Polyline extends FabricObject { /** @@ -333,7 +334,7 @@ export const polylineDefaultValues: Partial> = { points: [], exactBoundingBox: false, initialized: false, - cacheProperties: FabricObject.prototype.cacheProperties.concat('points'), + cacheProperties: fabricObjectDefaultValues.cacheProperties.concat('points'), strokeBBoxAffectingProperties: [ 'skewX', 'skewY', diff --git a/test/unit/polygon.js b/test/unit/polygon.js index c91493341c9..bda87ead65a 100644 --- a/test/unit/polygon.js +++ b/test/unit/polygon.js @@ -58,6 +58,7 @@ var polygon = new fabric.Polygon(getPoints()); assert.ok(polygon instanceof fabric.Polygon); + assert.ok(polygon instanceof fabric.Polyline); assert.ok(polygon instanceof fabric.Object); assert.equal(polygon.type, 'polygon'); From 535fee06bb177a98b2cc6f63b290061d0eb2f8e3 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 22:54:22 +0200 Subject: [PATCH 17/26] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77fa33d7b28..bff53526c69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## [next] -- chore(TS): migrate Circle [#8406](https://github.com/fabricjs/fabric.js/pull/8406) +- chore(TS): migrate Polyline/Polygon [#8417](https://github.com/fabricjs/fabric.js/pull/8417) - chore(TS): migrate Ellipse [#8408](https://github.com/fabricjs/fabric.js/pull/8408) - chore(TS): migrate Triangle to TS [#8410](https://github.com/fabricjs/fabric.js/pull/8410) - chore(TS): migrate Circle to TS [#8406](https://github.com/fabricjs/fabric.js/pull/8406) From de8b31184f9a2ab680ba4e6be60fa6e24d8d09d9 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 23:03:10 +0200 Subject: [PATCH 18/26] more --- src/point.class.ts | 2 -- src/shapes/polyline.class.ts | 31 ++++++++++++------------------- test/unit/point.js | 1 - 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/point.class.ts b/src/point.class.ts index 530df68c9a0..5c201e80900 100644 --- a/src/point.class.ts +++ b/src/point.class.ts @@ -16,8 +16,6 @@ export class Point { y: number; - type = 'point'; - constructor(); constructor(x: number, y: number); constructor(point: IPoint); diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index ab689747e1c..964bcf975cd 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -39,9 +39,13 @@ export class Polyline extends FabricObject { * @todo check if you really need to recalculate for all cases */ strokeBBoxAffectingProperties: (keyof this)[]; + fromSVG: boolean; + pathOffset: Point; + strokeOffset: Point; + /** * Constructor * @param {Array} points Array of points (where each point is an object with x and y) @@ -227,7 +231,7 @@ export class Polyline extends FabricObject { * @private * @param {CanvasRenderingContext2D} ctx Context to render on */ - commonRender(ctx: CanvasRenderingContext2D) { + _render(ctx: CanvasRenderingContext2D) { const len = this.points.length, x = this.pathOffset.x, y = this.pathOffset.y; @@ -235,7 +239,7 @@ export class Polyline extends FabricObject { if (!len || isNaN(this.points[len - 1].y)) { // do not draw if no points or odd points // NaN comes from parseFloat of a empty string in parser - return false; + return; } ctx.beginPath(); ctx.moveTo(this.points[0].x - x, this.points[0].y - y); @@ -243,17 +247,6 @@ export class Polyline extends FabricObject { const point = this.points[i]; ctx.lineTo(point.x - x, point.y - y); } - return true; - } - - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - _render(ctx: CanvasRenderingContext2D) { - if (!this.commonRender(ctx)) { - return; - } !this.isOpen() && ctx.closePath(); this._renderPaintInOrder(ctx); } @@ -266,6 +259,8 @@ export class Polyline extends FabricObject { return this.points.length; } + /* _FROM_SVG_START_ */ + /** * List of attribute names to account for when parsing SVG element (used by {@link Polyline.fromElement}) * @static @@ -274,8 +269,6 @@ export class Polyline extends FabricObject { */ static ATTRIBUTE_NAMES = [...SHARED_ATTRIBUTES]; - static fromElement = Polyline.fromElementGenerator(Polyline); - /** * Returns Polyline instance from an SVG element * @static @@ -315,6 +308,10 @@ export class Polyline extends FabricObject { }; } + static fromElement = Polyline.fromElementGenerator(Polyline); + + /* _FROM_SVG_END_ */ + /** * Returns Polyline instance from an object representation * @static @@ -351,7 +348,3 @@ Object.assign(Polyline.prototype, polylineDefaultValues); /** @todo TODO_JS_MIGRATION remove next line after refactoring build */ fabric.Polyline = Polyline; - -/* _FROM_SVG_START_ */ - -/* _FROM_SVG_END_ */ diff --git a/test/unit/point.js b/test/unit/point.js index 0096de3d8b3..2384877d5ce 100644 --- a/test/unit/point.js +++ b/test/unit/point.js @@ -11,7 +11,6 @@ assert.ok(point instanceof fabric.Point); assert.ok(point.constructor === fabric.Point); assert.ok(typeof point.constructor === 'function'); - assert.equal(point.type, 'point'); assert.strictEqual(point.x, 0, 'constructor assign x value'); assert.strictEqual(point.y, 0, 'constructor assign y value'); From 66a14cc724184ed412676c5f6df6e25b7fa8d8b6 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 23:06:21 +0200 Subject: [PATCH 19/26] revert Point UT fail in deepEquals F it --- src/parser/parsePointsAttribute.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/parser/parsePointsAttribute.ts b/src/parser/parsePointsAttribute.ts index 636f4c6ac9c..1ac59752231 100644 --- a/src/parser/parsePointsAttribute.ts +++ b/src/parser/parsePointsAttribute.ts @@ -1,7 +1,5 @@ //@ts-nocheck -import { Point } from '../point.class'; - /** * Parses "points" attribute, returning an array of values * @static @@ -19,12 +17,15 @@ export function parsePointsAttribute(points) { points = points.replace(/,/g, ' ').trim(); points = points.split(/\s+/); - const parsedPoints: Point[] = []; + let parsedPoints = [], + i, + len; - for (let i = 0; i < points.length; i += 2) { - parsedPoints.push( - new Point(parseFloat(points[i]), parseFloat(points[i + 1])) - ); + for (i = 0, len = points.length; i < len; i += 2) { + parsedPoints.push({ + x: parseFloat(points[i]), + y: parseFloat(points[i + 1]), + }); } // odd number of points is an error From 65cfcd639722f5ac910baf34b585f2d8a259b94f Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 23:07:45 +0200 Subject: [PATCH 20/26] IPoint --- src/shapes/polyline.class.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index 964bcf975cd..e8a48c7a835 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -3,7 +3,7 @@ import { config } from '../config'; import { SHARED_ATTRIBUTES } from '../parser/attributes'; import { parseAttributes } from '../parser/parseAttributes'; import { parsePointsAttribute } from '../parser/parsePointsAttribute'; -import { Point } from '../point.class'; +import { IPoint, Point } from '../point.class'; import { TClassProperties } from '../typedefs'; import { makeBoundingBoxFromPoints } from '../util/misc/boundingBoxFromPoints'; import { projectStrokeOnPoints } from '../util/misc/projectStroke'; @@ -18,7 +18,7 @@ export class Polyline extends FabricObject { * @type Array * @default */ - points: Point[]; + points: IPoint[]; /** * WARNING: Feature in progress @@ -65,7 +65,7 @@ export class Polyline extends FabricObject { * top: 100 * }); */ - constructor(points: Point[] = [], options: any = {}) { + constructor(points: IPoint[] = [], options: any = {}) { super({ points, ...options }); this.initialized = true; const bboxTL = this.setDimensions(); @@ -279,7 +279,7 @@ export class Polyline extends FabricObject { */ static fromElementGenerator< T extends { - new (points: Point[], options: any): any; + new (points: IPoint[], options: any): any; ATTRIBUTE_NAMES: string[]; } >(klass: T) { From 5681fce3bbbcb6f30cef49fd762c1ac5f6c8414d Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 23:19:58 +0200 Subject: [PATCH 21/26] refactor `fromElementGenerator` => `polyFromElement` --- src/shapes/polygon.class.ts | 10 ++++-- src/shapes/polyline.class.ts | 67 +++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/src/shapes/polygon.class.ts b/src/shapes/polygon.class.ts index f8ad577c8f0..e6762b59b9c 100644 --- a/src/shapes/polygon.class.ts +++ b/src/shapes/polygon.class.ts @@ -1,7 +1,7 @@ import { fabric } from '../../HEADER'; import { TClassProperties } from '../typedefs'; import { FabricObject } from './object.class'; -import { Polyline } from './polyline.class'; +import { polyFromElement, Polyline } from './polyline.class'; export class Polygon extends Polyline { protected isOpen() { @@ -18,7 +18,13 @@ export class Polygon extends Polyline { * @param {Function} callback callback function invoked after parsing * @param {Object} [options] Options object */ - static fromElement = Polyline.fromElementGenerator(Polygon); + static fromElement( + element: SVGElement, + callback: (poly: Polygon | null) => any, + options?: any + ) { + return polyFromElement(Polygon, element, callback, options); + } /* _FROM_SVG_END_ */ diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index e8a48c7a835..464df9ea96b 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -12,6 +12,36 @@ import { toFixed } from '../util/misc/toFixed'; import { FabricObject } from './fabricObject.class'; import { fabricObjectDefaultValues } from './object.class'; +export function polyFromElement< + T extends { + new (points: IPoint[], options: any): any; + ATTRIBUTE_NAMES: string[]; + } +>( + klass: T, + element: SVGElement, + callback: (poly: InstanceType | null) => any, + options = {} +) { + if (!element) { + return callback(null); + } + const points = parsePointsAttribute(element.getAttribute('points')), + // we omit left and top to instruct the constructor to position the object using the bbox + // eslint-disable-next-line @typescript-eslint/no-unused-vars + { left, top, ...parsedAttributes } = parseAttributes( + element, + klass.ATTRIBUTE_NAMES + ); + callback( + new klass(points || [], { + ...parsedAttributes, + ...options, + fromSVG: true, + }) + ); +} + export class Polyline extends FabricObject { /** * Points array @@ -277,39 +307,14 @@ export class Polyline extends FabricObject { * @param {Function} callback callback function invoked after parsing * @param {Object} [options] Options object */ - static fromElementGenerator< - T extends { - new (points: IPoint[], options: any): any; - ATTRIBUTE_NAMES: string[]; - } - >(klass: T) { - return function ( - element: SVGElement, - callback: (poly: InstanceType | null) => any, - options = {} - ) { - if (!element) { - return callback(null); - } - const points = parsePointsAttribute(element.getAttribute('points')), - // we omit left and top to instruct the constructor to position the object using the bbox - // eslint-disable-next-line @typescript-eslint/no-unused-vars - { left, top, ...parsedAttributes } = parseAttributes( - element, - klass.ATTRIBUTE_NAMES - ); - callback( - new klass(points || [], { - ...parsedAttributes, - ...options, - fromSVG: true, - }) - ); - }; + static fromElement( + element: SVGElement, + callback: (poly: Polyline | null) => any, + options?: any + ) { + return polyFromElement(Polyline, element, callback, options); } - static fromElement = Polyline.fromElementGenerator(Polyline); - /* _FROM_SVG_END_ */ /** From 1d18a151e03d001583dc671052afc08b5f29e12b Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 23:21:23 +0200 Subject: [PATCH 22/26] Update polyline.class.ts --- src/shapes/polyline.class.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index 464df9ea96b..eb2e9e91c95 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -62,7 +62,7 @@ export class Polyline extends FabricObject { */ exactBoundingBox: boolean; - initialized: boolean; + private initialized: boolean; /** * A list of properties that if changed trigger a recalculation of dimensions From ce8660d77267b52138efb400604923ab33bc78f1 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 23:28:49 +0200 Subject: [PATCH 23/26] Update polyline.class.ts --- src/shapes/polyline.class.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index eb2e9e91c95..ad58bb1fbd2 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -62,7 +62,7 @@ export class Polyline extends FabricObject { */ exactBoundingBox: boolean; - private initialized: boolean; + private initialized: true | undefined; /** * A list of properties that if changed trigger a recalculation of dimensions @@ -335,7 +335,6 @@ export const polylineDefaultValues: Partial> = { type: 'polyline', points: [], exactBoundingBox: false, - initialized: false, cacheProperties: fabricObjectDefaultValues.cacheProperties.concat('points'), strokeBBoxAffectingProperties: [ 'skewX', From f6eb764b4fc20c2384911d6b82cff62661544c89 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 23:35:20 +0200 Subject: [PATCH 24/26] remove default points --- src/shapes/polyline.class.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index ad58bb1fbd2..4cfa1133c52 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -333,7 +333,6 @@ export class Polyline extends FabricObject { export const polylineDefaultValues: Partial> = { type: 'polyline', - points: [], exactBoundingBox: false, cacheProperties: fabricObjectDefaultValues.cacheProperties.concat('points'), strokeBBoxAffectingProperties: [ From a3625231f93c0ea3c64739d64bdd5db1a0e490cb Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Wed, 9 Nov 2022 07:43:41 +0200 Subject: [PATCH 25/26] `setBoundingBox` instead of returning point from `setDimensions` --- src/shapes/polyline.class.ts | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index 4cfa1133c52..4dce3e006f8 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -95,18 +95,12 @@ export class Polyline extends FabricObject { * top: 100 * }); */ - constructor(points: IPoint[] = [], options: any = {}) { + constructor(points: IPoint[] = [], { left, top, ...options }: any = {}) { super({ points, ...options }); this.initialized = true; - const bboxTL = this.setDimensions(); - const origin = this.translateToGivenOrigin( - new Point(options.left ?? bboxTL.x, options.top ?? bboxTL.y), - typeof options.left === 'number' ? this.originX : 'left', - typeof options.top === 'number' ? this.originY : 'top', - this.originX, - this.originY - ); - this.setPositionByOrigin(origin, this.originX, this.originY); + this.setBoundingBox(true); + typeof left === 'number' && this.set('left', left); + typeof top === 'number' && this.set('top', top); } protected isOpen() { @@ -159,14 +153,16 @@ export class Polyline extends FabricObject { }; } - /** - * @returns {Point} top left position of the bounding box, useful for complementary positioning - */ - setDimensions(): Point { + setDimensions() { + this.setBoundingBox(); + } + + setBoundingBox(adjustPosition?: boolean) { const { left, top, width, height, pathOffset, strokeOffset } = this._calcDimensions(); this.set({ width, height, pathOffset, strokeOffset }); - return new Point(left, top); + adjustPosition && + this.setPositionByOrigin(new Point(left, top), 'left', 'top'); } /** From 859b4a9b00e63737afc9fe4987fdf618ca2e33c5 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sun, 13 Nov 2022 13:58:12 +0100 Subject: [PATCH 26/26] use string template --- src/mixins/object_origin.mixin.ts | 4 ++-- src/shapes/polyline.class.ts | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/mixins/object_origin.mixin.ts b/src/mixins/object_origin.mixin.ts index f5b12cc465f..37ac9e11afe 100644 --- a/src/mixins/object_origin.mixin.ts +++ b/src/mixins/object_origin.mixin.ts @@ -1,10 +1,10 @@ import { Point } from '../point.class'; import { transformPoint } from '../util/misc/matrix'; import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; -import { Group } from '../shapes/group.class'; +import { CommonMethods } from './shared_methods.mixin'; import { TDegree, TOriginX, TOriginY } from '../typedefs'; +import { Group } from '../shapes/group.class'; import { sizeAfterTransform } from '../util/misc/objectTransforms'; -import { CommonMethods } from './shared_methods.mixin'; const originOffset = { left: -0.5, diff --git a/src/shapes/polyline.class.ts b/src/shapes/polyline.class.ts index 4dce3e006f8..860e652d456 100644 --- a/src/shapes/polyline.class.ts +++ b/src/shapes/polyline.class.ts @@ -245,11 +245,9 @@ export class Polyline extends FabricObject { ); } return [ - '<' + this.type + ' ', + `<${this.type} `, 'COMMON_PARTS', - 'points="', - points.join(''), - '" />\n', + `points="${points.join('')}" />\n`, ]; }