fabric 7.0.0 → 7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.husky/pre-commit +1 -0
- package/CHANGELOG.md +21 -0
- package/dist/extensions/cropping_controls/croppingControls.d.ts +16 -0
- package/dist/extensions/cropping_controls/croppingControls.d.ts.map +1 -0
- package/dist/extensions/cropping_controls/croppingHandlers.d.ts +39 -0
- package/dist/extensions/cropping_controls/croppingHandlers.d.ts.map +1 -0
- package/dist/extensions/cropping_controls/enterCropMode.d.ts +7 -0
- package/dist/extensions/cropping_controls/enterCropMode.d.ts.map +1 -0
- package/dist/extensions/cropping_controls/renderCornerControl.d.ts +14 -0
- package/dist/extensions/cropping_controls/renderCornerControl.d.ts.map +1 -0
- package/dist/extensions/index.d.ts +3 -0
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/fabric.d.ts +1 -0
- package/dist/fabric.d.ts.map +1 -1
- package/dist/index.js +628 -537
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.min.mjs +1 -1
- package/dist/index.min.mjs.map +1 -1
- package/dist/index.mjs +628 -537
- package/dist/index.mjs.map +1 -1
- package/dist/index.node.cjs +628 -537
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +628 -537
- package/dist/index.node.mjs.map +1 -1
- package/dist/package.json.min.mjs +1 -1
- package/dist/package.json.mjs +1 -1
- package/dist/src/EventTypeDefs.d.ts +5 -0
- package/dist/src/EventTypeDefs.d.ts.map +1 -1
- package/dist/src/Pattern/Pattern.d.ts.map +1 -1
- package/dist/src/Pattern/Pattern.min.mjs +1 -1
- package/dist/src/Pattern/Pattern.min.mjs.map +1 -1
- package/dist/src/Pattern/Pattern.mjs +2 -1
- package/dist/src/Pattern/Pattern.mjs.map +1 -1
- package/dist/src/Shadow.d.ts +1 -1
- package/dist/src/Shadow.d.ts.map +1 -1
- package/dist/src/Shadow.min.mjs +1 -1
- package/dist/src/Shadow.min.mjs.map +1 -1
- package/dist/src/Shadow.mjs +5 -4
- package/dist/src/Shadow.mjs.map +1 -1
- package/dist/src/canvas/CanvasOptions.d.ts.map +1 -1
- package/dist/src/canvas/CanvasOptions.min.mjs.map +1 -1
- package/dist/src/canvas/CanvasOptions.mjs.map +1 -1
- package/dist/src/canvas/SelectableCanvas.d.ts +2 -0
- package/dist/src/canvas/SelectableCanvas.d.ts.map +1 -1
- package/dist/src/canvas/SelectableCanvas.min.mjs +1 -1
- package/dist/src/canvas/SelectableCanvas.min.mjs.map +1 -1
- package/dist/src/canvas/SelectableCanvas.mjs +33 -13
- package/dist/src/canvas/SelectableCanvas.mjs.map +1 -1
- package/dist/src/canvas/StaticCanvas.d.ts.map +1 -1
- package/dist/src/canvas/StaticCanvas.min.mjs +1 -1
- package/dist/src/canvas/StaticCanvas.min.mjs.map +1 -1
- package/dist/src/canvas/StaticCanvas.mjs +3 -1
- package/dist/src/canvas/StaticCanvas.mjs.map +1 -1
- package/dist/src/canvas/StaticCanvasOptions.d.ts.map +1 -1
- package/dist/src/canvas/StaticCanvasOptions.min.mjs.map +1 -1
- package/dist/src/canvas/StaticCanvasOptions.mjs.map +1 -1
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.min.mjs.map +1 -1
- package/dist/src/constants.mjs.map +1 -1
- package/dist/src/controls/Control.d.ts +22 -1
- package/dist/src/controls/Control.d.ts.map +1 -1
- package/dist/src/controls/Control.min.mjs +1 -1
- package/dist/src/controls/Control.min.mjs.map +1 -1
- package/dist/src/controls/Control.mjs +45 -1
- package/dist/src/controls/Control.mjs.map +1 -1
- package/dist/src/controls/changeWidth.d.ts +22 -0
- package/dist/src/controls/changeWidth.d.ts.map +1 -1
- package/dist/src/controls/changeWidth.min.mjs +1 -1
- package/dist/src/controls/changeWidth.min.mjs.map +1 -1
- package/dist/src/controls/changeWidth.mjs +46 -18
- package/dist/src/controls/changeWidth.mjs.map +1 -1
- package/dist/src/controls/controlRendering.d.ts.map +1 -1
- package/dist/src/controls/controlRendering.min.mjs +1 -1
- package/dist/src/controls/controlRendering.min.mjs.map +1 -1
- package/dist/src/controls/controlRendering.mjs +18 -34
- package/dist/src/controls/controlRendering.mjs.map +1 -1
- package/dist/src/controls/index.d.ts +2 -1
- package/dist/src/controls/index.d.ts.map +1 -1
- package/dist/src/controls/index.min.mjs +1 -1
- package/dist/src/controls/index.mjs +1 -1
- package/dist/src/gradient/Gradient.d.ts.map +1 -1
- package/dist/src/gradient/Gradient.min.mjs +1 -1
- package/dist/src/gradient/Gradient.min.mjs.map +1 -1
- package/dist/src/gradient/Gradient.mjs +19 -6
- package/dist/src/gradient/Gradient.mjs.map +1 -1
- package/dist/src/shapes/Circle.d.ts.map +1 -1
- package/dist/src/shapes/Circle.min.mjs +1 -1
- package/dist/src/shapes/Circle.min.mjs.map +1 -1
- package/dist/src/shapes/Circle.mjs +10 -7
- package/dist/src/shapes/Circle.mjs.map +1 -1
- package/dist/src/shapes/Ellipse.d.ts.map +1 -1
- package/dist/src/shapes/Ellipse.min.mjs +1 -1
- package/dist/src/shapes/Ellipse.min.mjs.map +1 -1
- package/dist/src/shapes/Ellipse.mjs +2 -1
- package/dist/src/shapes/Ellipse.mjs.map +1 -1
- package/dist/src/shapes/Group.d.ts.map +1 -1
- package/dist/src/shapes/Group.min.mjs +1 -1
- package/dist/src/shapes/Group.min.mjs.map +1 -1
- package/dist/src/shapes/Group.mjs +2 -1
- package/dist/src/shapes/Group.mjs.map +1 -1
- package/dist/src/shapes/IText/IText.d.ts.map +1 -1
- package/dist/src/shapes/IText/IText.min.mjs.map +1 -1
- package/dist/src/shapes/IText/IText.mjs.map +1 -1
- package/dist/src/shapes/Image.d.ts +1 -1
- package/dist/src/shapes/Image.d.ts.map +1 -1
- package/dist/src/shapes/Image.min.mjs +1 -1
- package/dist/src/shapes/Image.min.mjs.map +1 -1
- package/dist/src/shapes/Image.mjs +4 -3
- package/dist/src/shapes/Image.mjs.map +1 -1
- package/dist/src/shapes/Line.d.ts.map +1 -1
- package/dist/src/shapes/Line.min.mjs +1 -1
- package/dist/src/shapes/Line.min.mjs.map +1 -1
- package/dist/src/shapes/Line.mjs +6 -10
- package/dist/src/shapes/Line.mjs.map +1 -1
- package/dist/src/shapes/Object/FabricObjectSVGExportMixin.d.ts.map +1 -1
- package/dist/src/shapes/Object/FabricObjectSVGExportMixin.min.mjs +1 -1
- package/dist/src/shapes/Object/FabricObjectSVGExportMixin.min.mjs.map +1 -1
- package/dist/src/shapes/Object/FabricObjectSVGExportMixin.mjs +5 -4
- package/dist/src/shapes/Object/FabricObjectSVGExportMixin.mjs.map +1 -1
- package/dist/src/shapes/Object/InteractiveObject.d.ts.map +1 -1
- package/dist/src/shapes/Object/InteractiveObject.min.mjs.map +1 -1
- package/dist/src/shapes/Object/InteractiveObject.mjs.map +1 -1
- package/dist/src/shapes/Object/Object.d.ts.map +1 -1
- package/dist/src/shapes/Object/Object.min.mjs +1 -1
- package/dist/src/shapes/Object/Object.min.mjs.map +1 -1
- package/dist/src/shapes/Object/Object.mjs +3 -0
- package/dist/src/shapes/Object/Object.mjs.map +1 -1
- package/dist/src/shapes/Object/ObjectGeometry.min.mjs +1 -1
- package/dist/src/shapes/Object/ObjectGeometry.min.mjs.map +1 -1
- package/dist/src/shapes/Object/ObjectGeometry.mjs +1 -1
- package/dist/src/shapes/Object/ObjectGeometry.mjs.map +1 -1
- package/dist/src/shapes/Object/types/FabricObjectProps.d.ts.map +1 -1
- package/dist/src/shapes/Object/types/ObjectProps.d.ts.map +1 -1
- package/dist/src/shapes/Path.d.ts.map +1 -1
- package/dist/src/shapes/Path.min.mjs.map +1 -1
- package/dist/src/shapes/Path.mjs +1 -2
- package/dist/src/shapes/Path.mjs.map +1 -1
- package/dist/src/shapes/Polyline.d.ts.map +1 -1
- package/dist/src/shapes/Polyline.min.mjs +1 -1
- package/dist/src/shapes/Polyline.min.mjs.map +1 -1
- package/dist/src/shapes/Polyline.mjs +10 -6
- package/dist/src/shapes/Polyline.mjs.map +1 -1
- package/dist/src/shapes/Rect.d.ts.map +1 -1
- package/dist/src/shapes/Rect.min.mjs +1 -1
- package/dist/src/shapes/Rect.min.mjs.map +1 -1
- package/dist/src/shapes/Rect.mjs +2 -1
- package/dist/src/shapes/Rect.mjs.map +1 -1
- package/dist/src/shapes/Text/StyledText.d.ts.map +1 -1
- package/dist/src/shapes/Text/StyledText.min.mjs.map +1 -1
- package/dist/src/shapes/Text/StyledText.mjs +0 -3
- package/dist/src/shapes/Text/StyledText.mjs.map +1 -1
- package/dist/src/shapes/Text/Text.d.ts.map +1 -1
- package/dist/src/shapes/Text/Text.min.mjs.map +1 -1
- package/dist/src/shapes/Text/Text.mjs.map +1 -1
- package/dist/src/shapes/Text/TextSVGExportMixin.d.ts.map +1 -1
- package/dist/src/shapes/Text/TextSVGExportMixin.min.mjs +1 -1
- package/dist/src/shapes/Text/TextSVGExportMixin.min.mjs.map +1 -1
- package/dist/src/shapes/Text/TextSVGExportMixin.mjs +5 -6
- package/dist/src/shapes/Text/TextSVGExportMixin.mjs.map +1 -1
- package/dist/src/shapes/Textbox.d.ts.map +1 -1
- package/dist/src/shapes/Textbox.min.mjs.map +1 -1
- package/dist/src/shapes/Textbox.mjs.map +1 -1
- package/dist/src/shapes/Triangle.d.ts.map +1 -1
- package/dist/src/shapes/Triangle.min.mjs.map +1 -1
- package/dist/src/shapes/Triangle.mjs.map +1 -1
- package/dist/src/util/lang_string.d.ts +1 -1
- package/dist/src/util/lang_string.d.ts.map +1 -1
- package/dist/src/util/lang_string.min.mjs +1 -1
- package/dist/src/util/lang_string.min.mjs.map +1 -1
- package/dist/src/util/lang_string.mjs +1 -1
- package/dist/src/util/lang_string.mjs.map +1 -1
- package/dist/src/util/misc/svgParsing.d.ts.map +1 -1
- package/dist/src/util/misc/svgParsing.min.mjs +1 -1
- package/dist/src/util/misc/svgParsing.min.mjs.map +1 -1
- package/dist/src/util/misc/svgParsing.mjs +2 -1
- package/dist/src/util/misc/svgParsing.mjs.map +1 -1
- package/dist-extensions/cropping_controls/croppingControls.mjs +140 -0
- package/dist-extensions/cropping_controls/croppingControls.mjs.map +1 -0
- package/dist-extensions/cropping_controls/croppingHandlers.mjs +228 -0
- package/dist-extensions/cropping_controls/croppingHandlers.mjs.map +1 -0
- package/dist-extensions/cropping_controls/enterCropMode.mjs +38 -0
- package/dist-extensions/cropping_controls/enterCropMode.mjs.map +1 -0
- package/dist-extensions/cropping_controls/renderCornerControl.mjs +45 -0
- package/dist-extensions/cropping_controls/renderCornerControl.mjs.map +1 -0
- package/dist-extensions/extensions/cropping_controls/croppingControls.d.ts +16 -0
- package/dist-extensions/extensions/cropping_controls/croppingControls.d.ts.map +1 -0
- package/dist-extensions/extensions/cropping_controls/croppingHandlers.d.ts +39 -0
- package/dist-extensions/extensions/cropping_controls/croppingHandlers.d.ts.map +1 -0
- package/dist-extensions/extensions/cropping_controls/enterCropMode.d.ts +7 -0
- package/dist-extensions/extensions/cropping_controls/enterCropMode.d.ts.map +1 -0
- package/dist-extensions/extensions/cropping_controls/renderCornerControl.d.ts +14 -0
- package/dist-extensions/extensions/cropping_controls/renderCornerControl.d.ts.map +1 -0
- package/dist-extensions/extensions/index.d.ts +3 -0
- package/dist-extensions/extensions/index.d.ts.map +1 -1
- package/dist-extensions/fabric-extensions.min.js +1 -1
- package/dist-extensions/fabric-extensions.min.js.map +1 -1
- package/dist-extensions/fabric.d.ts +1 -0
- package/dist-extensions/fabric.d.ts.map +1 -1
- package/dist-extensions/index.mjs +3 -0
- package/dist-extensions/index.mjs.map +1 -1
- package/dist-extensions/src/EventTypeDefs.d.ts +5 -0
- package/dist-extensions/src/EventTypeDefs.d.ts.map +1 -1
- package/dist-extensions/src/Pattern/Pattern.d.ts.map +1 -1
- package/dist-extensions/src/Shadow.d.ts +1 -1
- package/dist-extensions/src/Shadow.d.ts.map +1 -1
- package/dist-extensions/src/canvas/CanvasOptions.d.ts.map +1 -1
- package/dist-extensions/src/canvas/SelectableCanvas.d.ts +2 -0
- package/dist-extensions/src/canvas/SelectableCanvas.d.ts.map +1 -1
- package/dist-extensions/src/canvas/StaticCanvas.d.ts.map +1 -1
- package/dist-extensions/src/canvas/StaticCanvasOptions.d.ts.map +1 -1
- package/dist-extensions/src/constants.d.ts +1 -0
- package/dist-extensions/src/constants.d.ts.map +1 -1
- package/dist-extensions/src/controls/Control.d.ts +22 -1
- package/dist-extensions/src/controls/Control.d.ts.map +1 -1
- package/dist-extensions/src/controls/changeWidth.d.ts +22 -0
- package/dist-extensions/src/controls/changeWidth.d.ts.map +1 -1
- package/dist-extensions/src/controls/controlRendering.d.ts.map +1 -1
- package/dist-extensions/src/controls/index.d.ts +2 -1
- package/dist-extensions/src/controls/index.d.ts.map +1 -1
- package/dist-extensions/src/gradient/Gradient.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Circle.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Ellipse.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Group.d.ts.map +1 -1
- package/dist-extensions/src/shapes/IText/IText.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Image.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Line.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Object/FabricObjectSVGExportMixin.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Object/InteractiveObject.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Object/Object.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Object/types/FabricObjectProps.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Object/types/ObjectProps.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Path.d.ts +1 -1
- package/dist-extensions/src/shapes/Path.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Polyline.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Rect.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Text/StyledText.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Text/Text.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Text/TextSVGExportMixin.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Textbox.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Triangle.d.ts.map +1 -1
- package/dist-extensions/src/util/lang_string.d.ts +1 -1
- package/dist-extensions/src/util/lang_string.d.ts.map +1 -1
- package/dist-extensions/src/util/misc/svgParsing.d.ts.map +1 -1
- package/eslint.config.mjs +2 -0
- package/extensions/cropping_controls/croppingControls.spec.ts +115 -0
- package/extensions/cropping_controls/croppingControls.ts +150 -0
- package/extensions/cropping_controls/croppingHandlers.spec.ts +579 -0
- package/extensions/cropping_controls/croppingHandlers.ts +285 -0
- package/extensions/cropping_controls/enterCropMode.ts +30 -0
- package/extensions/cropping_controls/renderCornerControl.ts +53 -0
- package/extensions/index.ts +9 -0
- package/fabric.ts +1 -0
- package/package.json +17 -8
- package/src/ClassRegistry.spec.ts +18 -19
- package/src/EventTypeDefs.ts +15 -11
- package/src/Pattern/Pattern.spec.ts +12 -0
- package/src/Pattern/Pattern.ts +3 -2
- package/src/Shadow.ts +9 -8
- package/src/brushes/PencilBrush.spec.ts +11 -11
- package/src/canvas/Canvas-dispose.spec.ts +8 -7
- package/src/canvas/Canvas.spec.ts +27 -29
- package/src/canvas/CanvasOptions.ts +2 -1
- package/src/canvas/SelectableCanvas.ts +38 -15
- package/src/canvas/StaticCanvas.spec.ts +20 -0
- package/src/canvas/StaticCanvas.ts +7 -4
- package/src/canvas/StaticCanvasOptions.ts +1 -3
- package/src/constants.ts +1 -0
- package/src/controls/Control.spec.ts +102 -0
- package/src/controls/Control.ts +71 -2
- package/src/controls/changeHeight.spec.ts +147 -0
- package/src/controls/changeWidth.ts +68 -35
- package/src/controls/controlRendering.ts +20 -48
- package/src/controls/index.ts +7 -1
- package/src/gradient/Gradient.spec.ts +101 -46
- package/src/gradient/Gradient.ts +27 -14
- package/src/shapes/Circle.spec.ts +10 -39
- package/src/shapes/Circle.ts +11 -11
- package/src/shapes/Ellipse.spec.ts +8 -37
- package/src/shapes/Ellipse.ts +7 -7
- package/src/shapes/Group.ts +3 -3
- package/src/shapes/IText/IText-click-behavior.spec.ts +36 -49
- package/src/shapes/IText/IText.ts +5 -6
- package/src/shapes/IText/ITextKeyBehavior.test.ts +0 -1
- package/src/shapes/IText/__snapshots__/ITextBehavior.test.ts.snap +6 -6
- package/src/shapes/Image.spec.ts +17 -33
- package/src/shapes/Image.ts +15 -11
- package/src/shapes/Line.spec.ts +4 -30
- package/src/shapes/Line.ts +11 -16
- package/src/shapes/Object/FabricObjectSVGExportMixin.ts +11 -4
- package/src/shapes/Object/InteractiveObject.ts +4 -4
- package/src/shapes/Object/Object.ts +6 -5
- package/src/shapes/Object/ObjectGeometry.spec.ts +15 -0
- package/src/shapes/Object/ObjectGeometry.ts +1 -1
- package/src/shapes/Object/objectSvgExport.spec.ts +112 -0
- package/src/shapes/Object/types/FabricObjectProps.ts +1 -4
- package/src/shapes/Object/types/ObjectProps.ts +1 -3
- package/src/shapes/Path.spec.ts +4 -27
- package/src/shapes/Path.ts +2 -4
- package/src/shapes/Polygon.spec.ts +4 -31
- package/src/shapes/Polyline.spec.ts +4 -31
- package/src/shapes/Polyline.ts +11 -12
- package/src/shapes/Rect.spec.ts +25 -33
- package/src/shapes/Rect.ts +7 -7
- package/src/shapes/Text/StyledText.ts +0 -3
- package/src/shapes/Text/Text.spec.ts +3 -32
- package/src/shapes/Text/Text.ts +5 -6
- package/src/shapes/Text/TextSVGExportMixin.spec.ts +9 -0
- package/src/shapes/Text/TextSVGExportMixin.ts +14 -16
- package/src/shapes/Text/__snapshots__/Text.spec.ts.snap +1 -1
- package/src/shapes/Text/__snapshots__/TextSVGExportMixin.spec.ts.snap +1 -1
- package/src/shapes/Textbox.spec.ts +5 -5
- package/src/shapes/Textbox.ts +6 -5
- package/src/shapes/Triangle.ts +4 -4
- package/src/shapes/__snapshots__/Image.spec.ts.snap +4 -4
- package/src/shapes/__snapshots__/Textbox.spec.ts.snap +5 -5
- package/src/util/lang_string.ts +3 -2
- package/src/util/misc/svgParsing.ts +2 -1
- package/tsconfig.spec.json +1 -0
- package/vitest.config.ts +12 -2
- package/vitest.extend.ts +6 -2
package/src/Shadow.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Point } from './Point';
|
|
|
6
6
|
import type { FabricObject } from './shapes/Object/FabricObject';
|
|
7
7
|
import type { TClassProperties } from './typedefs';
|
|
8
8
|
import { uid } from './util/internals/uid';
|
|
9
|
+
import { escapeXml } from './util/lang_string';
|
|
9
10
|
import { pickBy } from './util/misc/pick';
|
|
10
11
|
import { degreesToRadians } from './util/misc/radiansDegreesConversion';
|
|
11
12
|
import { toFixed } from './util/misc/toFixed';
|
|
@@ -27,7 +28,6 @@ import { rotateVector } from './util/misc/vectors';
|
|
|
27
28
|
|
|
28
29
|
(?:$|\s): This captures either the end of the line or a whitespace character. It ensures that the match ends either at the end of the string or with a whitespace character.
|
|
29
30
|
*/
|
|
30
|
-
// eslint-disable-next-line max-len
|
|
31
31
|
|
|
32
32
|
const shadowOffsetRegex = '(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?';
|
|
33
33
|
|
|
@@ -105,7 +105,7 @@ export class Shadow {
|
|
|
105
105
|
*/
|
|
106
106
|
declare nonScaling: boolean;
|
|
107
107
|
|
|
108
|
-
declare id: number;
|
|
108
|
+
declare id: number | string;
|
|
109
109
|
|
|
110
110
|
static ownDefaults = shadowDefaultValues;
|
|
111
111
|
|
|
@@ -163,6 +163,7 @@ export class Shadow {
|
|
|
163
163
|
degreesToRadians(-object.angle),
|
|
164
164
|
),
|
|
165
165
|
BLUR_BOX = 20,
|
|
166
|
+
NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS,
|
|
166
167
|
color = new Color(this.color);
|
|
167
168
|
let fBoxX = 40,
|
|
168
169
|
fBoxY = 40;
|
|
@@ -173,14 +174,14 @@ export class Shadow {
|
|
|
173
174
|
fBoxX =
|
|
174
175
|
toFixed(
|
|
175
176
|
(Math.abs(offset.x) + this.blur) / object.width,
|
|
176
|
-
|
|
177
|
+
NUM_FRACTION_DIGITS,
|
|
177
178
|
) *
|
|
178
179
|
100 +
|
|
179
180
|
BLUR_BOX;
|
|
180
181
|
fBoxY =
|
|
181
182
|
toFixed(
|
|
182
183
|
(Math.abs(offset.y) + this.blur) / object.height,
|
|
183
|
-
|
|
184
|
+
NUM_FRACTION_DIGITS,
|
|
184
185
|
) *
|
|
185
186
|
100 +
|
|
186
187
|
BLUR_BOX;
|
|
@@ -192,19 +193,19 @@ export class Shadow {
|
|
|
192
193
|
offset.y *= -1;
|
|
193
194
|
}
|
|
194
195
|
|
|
195
|
-
return `<filter id="SVGID_${this.id}" y="-${fBoxY}%" height="${
|
|
196
|
+
return `<filter id="SVGID_${escapeXml(this.id)}" y="-${fBoxY}%" height="${
|
|
196
197
|
100 + 2 * fBoxY
|
|
197
198
|
}%" x="-${fBoxX}%" width="${
|
|
198
199
|
100 + 2 * fBoxX
|
|
199
200
|
}%" >\n\t<feGaussianBlur in="SourceAlpha" stdDeviation="${toFixed(
|
|
200
201
|
this.blur ? this.blur / 2 : 0,
|
|
201
|
-
|
|
202
|
+
NUM_FRACTION_DIGITS,
|
|
202
203
|
)}"></feGaussianBlur>\n\t<feOffset dx="${toFixed(
|
|
203
204
|
offset.x,
|
|
204
|
-
|
|
205
|
+
NUM_FRACTION_DIGITS,
|
|
205
206
|
)}" dy="${toFixed(
|
|
206
207
|
offset.y,
|
|
207
|
-
|
|
208
|
+
NUM_FRACTION_DIGITS,
|
|
208
209
|
)}" result="oBlur" ></feOffset>\n\t<feFlood flood-color="${color.toRgb()}" flood-opacity="${color.getAlpha()}"/>\n\t<feComposite in2="oBlur" operator="in" />\n\t<feMerge>\n\t\t<feMergeNode></feMergeNode>\n\t\t<feMergeNode in="SourceGraphic"></feMergeNode>\n\t</feMerge>\n</filter>\n`;
|
|
209
210
|
}
|
|
210
211
|
|
|
@@ -2,9 +2,9 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
|
2
2
|
import { Canvas } from '../canvas/Canvas';
|
|
3
3
|
import { PencilBrush } from './PencilBrush';
|
|
4
4
|
import { parsePath } from '../util';
|
|
5
|
-
import type { TPointerEvent } from '../EventTypeDefs';
|
|
6
5
|
import { Path } from '../shapes/Path';
|
|
7
6
|
import { Point } from '../Point';
|
|
7
|
+
import { createPointerEvent } from '../../test/utils';
|
|
8
8
|
|
|
9
9
|
describe('PencilBrush', () => {
|
|
10
10
|
let canvas: Canvas;
|
|
@@ -55,12 +55,12 @@ describe('PencilBrush', () => {
|
|
|
55
55
|
|
|
56
56
|
it('draws a point correctly', () => {
|
|
57
57
|
const brush = new PencilBrush(canvas);
|
|
58
|
-
const e = {
|
|
59
|
-
|
|
60
|
-
...e,
|
|
58
|
+
const e = createPointerEvent({
|
|
59
|
+
target: canvas.upperCanvasEl,
|
|
61
60
|
clientX: 10,
|
|
62
61
|
clientY: 10,
|
|
63
62
|
});
|
|
63
|
+
const pointer = canvas.getScenePoint(e);
|
|
64
64
|
brush.onMouseDown(pointer, { e });
|
|
65
65
|
// @ts-expect-error -- protected
|
|
66
66
|
const pathData = brush.convertPointsToSVGPath(brush._points);
|
|
@@ -72,12 +72,12 @@ describe('PencilBrush', () => {
|
|
|
72
72
|
|
|
73
73
|
it('handles multiple coincident points', () => {
|
|
74
74
|
const brush = new PencilBrush(canvas);
|
|
75
|
-
const e = {
|
|
76
|
-
|
|
77
|
-
...e,
|
|
75
|
+
const e = createPointerEvent({
|
|
76
|
+
target: canvas.upperCanvasEl,
|
|
78
77
|
clientX: 10,
|
|
79
78
|
clientY: 10,
|
|
80
79
|
});
|
|
80
|
+
const pointer = canvas.getScenePoint(e);
|
|
81
81
|
brush.onMouseDown(pointer, { e });
|
|
82
82
|
brush.onMouseMove(pointer, { e });
|
|
83
83
|
brush.onMouseMove(pointer, { e });
|
|
@@ -95,7 +95,7 @@ describe('PencilBrush', () => {
|
|
|
95
95
|
|
|
96
96
|
it('handles multiple non-coincident points', () => {
|
|
97
97
|
const brush = new PencilBrush(canvas);
|
|
98
|
-
const e = { target: canvas.upperCanvasEl }
|
|
98
|
+
const e = createPointerEvent({ target: canvas.upperCanvasEl });
|
|
99
99
|
const pointer = canvas.getScenePoint({
|
|
100
100
|
...e,
|
|
101
101
|
clientX: 10,
|
|
@@ -129,7 +129,7 @@ describe('PencilBrush', () => {
|
|
|
129
129
|
|
|
130
130
|
it('handles points outside canvas', () => {
|
|
131
131
|
const brush = new PencilBrush(canvas);
|
|
132
|
-
const e = { target: canvas.upperCanvasEl }
|
|
132
|
+
const e = createPointerEvent({ target: canvas.upperCanvasEl });
|
|
133
133
|
const pointer = canvas.getScenePoint({
|
|
134
134
|
...e,
|
|
135
135
|
clientX: 10,
|
|
@@ -177,7 +177,7 @@ describe('PencilBrush', () => {
|
|
|
177
177
|
it('limits points to canvas size when limitedToCanvasSize is true', () => {
|
|
178
178
|
const brush = new PencilBrush(canvas);
|
|
179
179
|
brush.limitedToCanvasSize = true;
|
|
180
|
-
const e = { target: canvas.upperCanvasEl }
|
|
180
|
+
const e = createPointerEvent({ target: canvas.upperCanvasEl });
|
|
181
181
|
const pointer = canvas.getScenePoint({
|
|
182
182
|
...e,
|
|
183
183
|
clientX: 10,
|
|
@@ -237,7 +237,7 @@ describe('PencilBrush', () => {
|
|
|
237
237
|
});
|
|
238
238
|
|
|
239
239
|
const brush = new PencilBrush(canvas);
|
|
240
|
-
const e = { target: canvas.upperCanvasEl }
|
|
240
|
+
const e = createPointerEvent({ target: canvas.upperCanvasEl });
|
|
241
241
|
const pointer = canvas.getScenePoint({
|
|
242
242
|
...e,
|
|
243
243
|
clientX: 10,
|
|
@@ -195,23 +195,24 @@ describe('Canvas dispose', () => {
|
|
|
195
195
|
|
|
196
196
|
it('dispose edge case: `toCanvasElement` after dispose', async () => {
|
|
197
197
|
const canvas = new CanvasClass(undefined, { renderOnAddRemove: false });
|
|
198
|
-
const
|
|
198
|
+
const getAlphaValues = () => {
|
|
199
199
|
return canvas
|
|
200
200
|
.toCanvasElement()
|
|
201
201
|
.getContext('2d')!
|
|
202
|
-
.getImageData(
|
|
203
|
-
.data.filter((_, i) => i % 4 ===
|
|
204
|
-
.every((x) => x === colorByteVal);
|
|
202
|
+
.getImageData(10, 10, 20, 20)
|
|
203
|
+
.data.filter((_, i) => i % 4 === 3);
|
|
205
204
|
};
|
|
205
|
+
const hasOpaquePixels = () => getAlphaValues().some((x) => x === 255);
|
|
206
|
+
const isFullyTransparent = () => getAlphaValues().every((x) => x === 0);
|
|
206
207
|
canvas.add(
|
|
207
208
|
makeRect({ fill: 'red', width: 20, height: 20, top: 10, left: 10 }),
|
|
208
209
|
);
|
|
209
|
-
expect(
|
|
210
|
+
expect(hasOpaquePixels(), 'control').toBeTruthy();
|
|
210
211
|
canvas.disposed = true;
|
|
211
|
-
expect(
|
|
212
|
+
expect(hasOpaquePixels(), 'should render canvas').toBeTruthy();
|
|
212
213
|
canvas.destroyed = true;
|
|
213
214
|
expect(
|
|
214
|
-
|
|
215
|
+
isFullyTransparent(),
|
|
215
216
|
'should have disabled canvas rendering',
|
|
216
217
|
).toBeTruthy();
|
|
217
218
|
canvas.destroyed = false;
|
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
MultiSelectionStacking,
|
|
11
11
|
TPointerEvent,
|
|
12
12
|
} from '../../fabric';
|
|
13
|
+
import { createPointerEvent } from '../../test/utils';
|
|
13
14
|
import {
|
|
14
15
|
ActiveSelection,
|
|
15
16
|
Circle,
|
|
@@ -862,9 +863,7 @@ describe('Canvas', () => {
|
|
|
862
863
|
deltaX: 5,
|
|
863
864
|
deltaY: 5,
|
|
864
865
|
});
|
|
865
|
-
canvas._onMouseUp({
|
|
866
|
-
target: canvas.upperCanvasEl,
|
|
867
|
-
} as unknown as TPointerEvent);
|
|
866
|
+
canvas._onMouseUp(createPointerEvent({ target: canvas.upperCanvasEl }));
|
|
868
867
|
|
|
869
868
|
expect(fired, 'event fired for each of 3 rects').toBe(3);
|
|
870
869
|
});
|
|
@@ -885,9 +884,7 @@ describe('Canvas', () => {
|
|
|
885
884
|
deltaX: 5,
|
|
886
885
|
deltaY: 5,
|
|
887
886
|
});
|
|
888
|
-
canvas._onMouseUp({
|
|
889
|
-
target: canvas.upperCanvasEl,
|
|
890
|
-
} as unknown as TPointerEvent);
|
|
887
|
+
canvas._onMouseUp(createPointerEvent({ target: canvas.upperCanvasEl }));
|
|
891
888
|
|
|
892
889
|
expect(isFired, 'selection created fired').toBe(true);
|
|
893
890
|
expect(
|
|
@@ -917,9 +914,7 @@ describe('Canvas', () => {
|
|
|
917
914
|
deltaX: 5,
|
|
918
915
|
deltaY: 5,
|
|
919
916
|
});
|
|
920
|
-
canvas._onMouseUp({
|
|
921
|
-
target: canvas.upperCanvasEl,
|
|
922
|
-
} as unknown as TPointerEvent);
|
|
917
|
+
canvas._onMouseUp(createPointerEvent({ target: canvas.upperCanvasEl }));
|
|
923
918
|
|
|
924
919
|
expect(isFired, 'selection:created fired').toBe(true);
|
|
925
920
|
expect(canvas.getActiveObject(), 'rect1 is set as activeObject').toBe(
|
|
@@ -1115,18 +1110,22 @@ describe('Canvas', () => {
|
|
|
1115
1110
|
const rect = makeRect({ left: 0, top: 0 });
|
|
1116
1111
|
canvas.add(rect);
|
|
1117
1112
|
|
|
1118
|
-
const { target } = canvas.findTarget(
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1113
|
+
const { target } = canvas.findTarget(
|
|
1114
|
+
createPointerEvent({
|
|
1115
|
+
clientX: 5,
|
|
1116
|
+
clientY: 5,
|
|
1117
|
+
target: canvas.upperCanvasEl,
|
|
1118
|
+
}),
|
|
1119
|
+
);
|
|
1123
1120
|
expect(target, 'Should return the rect').toBe(rect);
|
|
1124
1121
|
|
|
1125
|
-
const { target: target2 } = canvas.findTarget(
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1122
|
+
const { target: target2 } = canvas.findTarget(
|
|
1123
|
+
createPointerEvent({
|
|
1124
|
+
clientX: 30,
|
|
1125
|
+
clientY: 30,
|
|
1126
|
+
target: canvas.upperCanvasEl,
|
|
1127
|
+
}),
|
|
1128
|
+
);
|
|
1130
1129
|
expect(target2, 'Should not find target').toBeUndefined();
|
|
1131
1130
|
|
|
1132
1131
|
canvas.remove(rect);
|
|
@@ -1897,16 +1896,15 @@ describe('Canvas', () => {
|
|
|
1897
1896
|
});
|
|
1898
1897
|
|
|
1899
1898
|
it('cleans up transform when discarding active object', () => {
|
|
1900
|
-
const e = {
|
|
1899
|
+
const e = createPointerEvent({
|
|
1901
1900
|
clientX: 5,
|
|
1902
1901
|
clientY: 5,
|
|
1903
|
-
which: 1,
|
|
1904
1902
|
target: canvas.upperCanvasEl,
|
|
1905
|
-
};
|
|
1903
|
+
});
|
|
1906
1904
|
const target = makeRect();
|
|
1907
1905
|
canvas.add(target);
|
|
1908
1906
|
canvas.setActiveObject(target);
|
|
1909
|
-
canvas._setupCurrentTransform(e
|
|
1907
|
+
canvas._setupCurrentTransform(e, target, true);
|
|
1910
1908
|
expect(canvas._currentTransform, 'transform should be set').toBeTruthy();
|
|
1911
1909
|
|
|
1912
1910
|
target.isMoving = true;
|
|
@@ -2221,11 +2219,11 @@ describe('Canvas', () => {
|
|
|
2221
2219
|
const rect = new Rect({ left: 100, top: 100, width: 50, height: 50 });
|
|
2222
2220
|
canvas.add(rect);
|
|
2223
2221
|
const canvasOffset = canvas.calcOffset();
|
|
2224
|
-
let eventStub = {
|
|
2222
|
+
let eventStub = createPointerEvent({
|
|
2225
2223
|
clientX: canvasOffset.left + 100,
|
|
2226
2224
|
clientY: canvasOffset.top + 100,
|
|
2227
2225
|
target: canvas.upperCanvasEl,
|
|
2228
|
-
}
|
|
2226
|
+
});
|
|
2229
2227
|
canvas.setActiveObject(rect);
|
|
2230
2228
|
const targetCorner = rect.findControl(canvas.getViewportPoint(eventStub));
|
|
2231
2229
|
rect.__corner = targetCorner ? targetCorner.key : undefined;
|
|
@@ -2237,11 +2235,11 @@ describe('Canvas', () => {
|
|
|
2237
2235
|
expect(t.originX, 'no origin change for drag').toBe(rect.originX);
|
|
2238
2236
|
expect(t.originY, 'no origin change for drag').toBe(rect.originY);
|
|
2239
2237
|
|
|
2240
|
-
eventStub = {
|
|
2238
|
+
eventStub = createPointerEvent({
|
|
2241
2239
|
clientX: canvasOffset.left + rect.oCoords.tl.corner.tl.x + 1,
|
|
2242
2240
|
clientY: canvasOffset.top + rect.oCoords.tl.corner.tl.y + 1,
|
|
2243
2241
|
target: canvas.upperCanvasEl,
|
|
2244
|
-
}
|
|
2242
|
+
});
|
|
2245
2243
|
rect.__corner = rect.findControl(canvas.getViewportPoint(eventStub))!.key;
|
|
2246
2244
|
canvas._setupCurrentTransform(eventStub, rect, false);
|
|
2247
2245
|
t = canvas._currentTransform!;
|
|
@@ -2264,12 +2262,12 @@ describe('Canvas', () => {
|
|
|
2264
2262
|
expect(t.originY, 'origin in opposite direction').toBe('bottom');
|
|
2265
2263
|
expect(t.shiftKey, 'shift was not pressed').toBe(undefined);
|
|
2266
2264
|
|
|
2267
|
-
eventStub = {
|
|
2265
|
+
eventStub = createPointerEvent({
|
|
2268
2266
|
clientX: canvasOffset.left + rect.left - 2 - rect.width / 2,
|
|
2269
2267
|
clientY: canvasOffset.top + rect.top,
|
|
2270
2268
|
target: canvas.upperCanvasEl,
|
|
2271
2269
|
shiftKey: true,
|
|
2272
|
-
}
|
|
2270
|
+
});
|
|
2273
2271
|
rect.__corner = rect.findControl(canvas.getViewportPoint(eventStub))!.key;
|
|
2274
2272
|
canvas._setupCurrentTransform(eventStub, rect, alreadySelected);
|
|
2275
2273
|
t = canvas._currentTransform!;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { dragHandler } from '../controls/drag';
|
|
2
1
|
import { getActionFromCorner } from '../controls/util';
|
|
3
2
|
import { Point } from '../Point';
|
|
4
3
|
import { FabricObject } from '../shapes/Object/FabricObject';
|
|
@@ -51,6 +50,8 @@ import type { CanvasOptions } from './CanvasOptions';
|
|
|
51
50
|
import { canvasDefaults } from './CanvasOptions';
|
|
52
51
|
import { Intersection } from '../Intersection';
|
|
53
52
|
import { isActiveSelection } from '../util/typeAssertions';
|
|
53
|
+
import { dragHandler } from '../controls';
|
|
54
|
+
import { type FabricImage } from '../shapes/Image';
|
|
54
55
|
|
|
55
56
|
export type TargetsInfo = {
|
|
56
57
|
target?: FabricObject;
|
|
@@ -564,6 +565,8 @@ export class SelectableCanvas<EventSpec extends CanvasEvents = CanvasEvents>
|
|
|
564
565
|
* Given the control clicked, determine the origin of the transform.
|
|
565
566
|
* This is bad because controls can totally have custom names
|
|
566
567
|
* should disappear before release 4.0
|
|
568
|
+
* Fabric 7.1, jan 2026 we are still using this.
|
|
569
|
+
* Needs to go.
|
|
567
570
|
* @private
|
|
568
571
|
* @deprecated
|
|
569
572
|
*/
|
|
@@ -571,15 +574,20 @@ export class SelectableCanvas<EventSpec extends CanvasEvents = CanvasEvents>
|
|
|
571
574
|
target: FabricObject,
|
|
572
575
|
controlName: string,
|
|
573
576
|
): { x: TOriginX; y: TOriginY } {
|
|
574
|
-
const origin =
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
577
|
+
const origin = controlName
|
|
578
|
+
? target.controls[controlName].getTransformAnchorPoint()
|
|
579
|
+
: {
|
|
580
|
+
x: target.originX,
|
|
581
|
+
y: target.originY,
|
|
582
|
+
};
|
|
578
583
|
|
|
579
584
|
if (!controlName) {
|
|
580
585
|
return origin;
|
|
581
586
|
}
|
|
582
587
|
|
|
588
|
+
// this part down here is deprecated.
|
|
589
|
+
// It is left to do not change the standard behavior in the middle of a major version
|
|
590
|
+
// but when possible `getTransformAnchorPoint` will be the only source of truth
|
|
583
591
|
// is a left control ?
|
|
584
592
|
if (['ml', 'tl', 'bl'].includes(controlName)) {
|
|
585
593
|
origin.x = RIGHT;
|
|
@@ -626,37 +634,52 @@ export class SelectableCanvas<EventSpec extends CanvasEvents = CanvasEvents>
|
|
|
626
634
|
origin = this._shouldCenterTransform(target, action, altKey)
|
|
627
635
|
? ({ x: CENTER, y: CENTER } as const)
|
|
628
636
|
: this._getOriginFromCorner(target, corner),
|
|
637
|
+
{
|
|
638
|
+
scaleX,
|
|
639
|
+
scaleY,
|
|
640
|
+
skewX,
|
|
641
|
+
skewY,
|
|
642
|
+
left,
|
|
643
|
+
top,
|
|
644
|
+
angle,
|
|
645
|
+
width,
|
|
646
|
+
height,
|
|
647
|
+
cropX,
|
|
648
|
+
cropY,
|
|
649
|
+
} = target as FabricImage,
|
|
629
650
|
/**
|
|
630
651
|
* relative to target's containing coordinate plane
|
|
631
652
|
* both agree on every point
|
|
632
653
|
**/
|
|
633
654
|
transform: Transform = {
|
|
634
|
-
target
|
|
655
|
+
target,
|
|
635
656
|
action,
|
|
636
657
|
actionHandler,
|
|
637
658
|
actionPerformed: false,
|
|
638
659
|
corner,
|
|
639
|
-
scaleX
|
|
640
|
-
scaleY
|
|
641
|
-
skewX
|
|
642
|
-
skewY
|
|
643
|
-
offsetX: pointer.x -
|
|
644
|
-
offsetY: pointer.y -
|
|
660
|
+
scaleX,
|
|
661
|
+
scaleY,
|
|
662
|
+
skewX,
|
|
663
|
+
skewY,
|
|
664
|
+
offsetX: pointer.x - left,
|
|
665
|
+
offsetY: pointer.y - top,
|
|
645
666
|
originX: origin.x,
|
|
646
667
|
originY: origin.y,
|
|
647
668
|
ex: pointer.x,
|
|
648
669
|
ey: pointer.y,
|
|
649
670
|
lastX: pointer.x,
|
|
650
671
|
lastY: pointer.y,
|
|
651
|
-
theta: degreesToRadians(
|
|
652
|
-
width
|
|
653
|
-
height
|
|
672
|
+
theta: degreesToRadians(angle),
|
|
673
|
+
width,
|
|
674
|
+
height,
|
|
654
675
|
shiftKey: e.shiftKey,
|
|
655
676
|
altKey,
|
|
656
677
|
original: {
|
|
657
678
|
...saveObjectTransform(target),
|
|
658
679
|
originX: origin.x,
|
|
659
680
|
originY: origin.y,
|
|
681
|
+
cropX,
|
|
682
|
+
cropY,
|
|
660
683
|
},
|
|
661
684
|
};
|
|
662
685
|
|
|
@@ -2241,6 +2241,26 @@ describe('StaticCanvas', () => {
|
|
|
2241
2241
|
// });
|
|
2242
2242
|
});
|
|
2243
2243
|
|
|
2244
|
+
describe('malicious tests', () => {
|
|
2245
|
+
it('from JSON to svg', async () => {
|
|
2246
|
+
const canvas = new StaticCanvas();
|
|
2247
|
+
const maliciousJSON = {
|
|
2248
|
+
objects: [
|
|
2249
|
+
{
|
|
2250
|
+
type: 'rect',
|
|
2251
|
+
id: '"><set onbegin="alert(1)"/>',
|
|
2252
|
+
width: 100,
|
|
2253
|
+
height: 100,
|
|
2254
|
+
fill: 'red',
|
|
2255
|
+
},
|
|
2256
|
+
],
|
|
2257
|
+
};
|
|
2258
|
+
await canvas.loadFromJSON(maliciousJSON);
|
|
2259
|
+
const svg = canvas.toSVG();
|
|
2260
|
+
expect(svg).not.toContain('onbegin="alert(1)"');
|
|
2261
|
+
});
|
|
2262
|
+
});
|
|
2263
|
+
|
|
2244
2264
|
function makeRect(options = {}) {
|
|
2245
2265
|
const defaultOptions = { width: 10, height: 10 };
|
|
2246
2266
|
return new Rect({ ...defaultOptions, ...options });
|
|
@@ -44,6 +44,7 @@ import type { StaticCanvasOptions } from './StaticCanvasOptions';
|
|
|
44
44
|
import { staticCanvasDefaults } from './StaticCanvasOptions';
|
|
45
45
|
import { log, FabricError } from '../util/internals/console';
|
|
46
46
|
import { getDevicePixelRatio } from '../env';
|
|
47
|
+
import { escapeXml } from '../util/lang_string';
|
|
47
48
|
|
|
48
49
|
/**
|
|
49
50
|
* Having both options in TCanvasSizeOptions set to true transform the call in a calcOffset
|
|
@@ -86,9 +87,9 @@ export type PatternQuality = 'fast' | 'good' | 'best' | 'nearest' | 'bilinear';
|
|
|
86
87
|
*/
|
|
87
88
|
// TODO: fix `EventSpec` inheritance https://github.com/microsoft/TypeScript/issues/26154#issuecomment-1366616260
|
|
88
89
|
export class StaticCanvas<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
91
|
+
EventSpec extends StaticCanvasEvents = StaticCanvasEvents,
|
|
92
|
+
>
|
|
92
93
|
extends createCollectionMixin(CommonMethods<CanvasEvents>)
|
|
93
94
|
implements StaticCanvasOptions
|
|
94
95
|
{
|
|
@@ -950,7 +951,9 @@ export class StaticCanvas<
|
|
|
950
951
|
this._setSVGPreamble(markup, options);
|
|
951
952
|
this._setSVGHeader(markup, options);
|
|
952
953
|
if (this.clipPath) {
|
|
953
|
-
markup.push(
|
|
954
|
+
markup.push(
|
|
955
|
+
`<g clip-path="url(#${escapeXml(this.clipPath.clipPathId ?? '')})" >\n`,
|
|
956
|
+
);
|
|
954
957
|
}
|
|
955
958
|
this._setSVGBgOverlayColor(markup, 'background');
|
|
956
959
|
this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);
|
|
@@ -113,9 +113,7 @@ export interface CanvasExportOptions {
|
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
export interface StaticCanvasOptions
|
|
116
|
-
extends CanvasDrawableOptions,
|
|
117
|
-
CanvasRenderingOptions,
|
|
118
|
-
CanvasExportOptions {
|
|
116
|
+
extends CanvasDrawableOptions, CanvasRenderingOptions, CanvasExportOptions {
|
|
119
117
|
/**
|
|
120
118
|
* Width in virtual/logical pixels of the canvas.
|
|
121
119
|
* The canvas can be larger than width if retina scaling is active
|
package/src/constants.ts
CHANGED
|
@@ -67,4 +67,106 @@ describe('Controls', () => {
|
|
|
67
67
|
Intersection.isPointInPolygon(new Point(15, 10), Object.values(coords)),
|
|
68
68
|
).toBe(true);
|
|
69
69
|
});
|
|
70
|
+
|
|
71
|
+
describe('commonRenderProps', () => {
|
|
72
|
+
const createMockContext = () =>
|
|
73
|
+
({
|
|
74
|
+
fillStyle: '',
|
|
75
|
+
strokeStyle: '',
|
|
76
|
+
translate: vi.fn(),
|
|
77
|
+
rotate: vi.fn(),
|
|
78
|
+
}) as unknown as CanvasRenderingContext2D;
|
|
79
|
+
|
|
80
|
+
test('returns default values from fabricObject', () => {
|
|
81
|
+
const control = new Control();
|
|
82
|
+
const ctx = createMockContext();
|
|
83
|
+
const fabricObject = new FabricObject({
|
|
84
|
+
cornerSize: 13,
|
|
85
|
+
cornerColor: 'blue',
|
|
86
|
+
transparentCorners: false,
|
|
87
|
+
cornerStrokeColor: 'red',
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const result = control.commonRenderProps(ctx, 10, 20, fabricObject);
|
|
91
|
+
|
|
92
|
+
expect(result).toEqual({
|
|
93
|
+
stroke: true,
|
|
94
|
+
xSize: 13,
|
|
95
|
+
ySize: 13,
|
|
96
|
+
transparentCorners: false,
|
|
97
|
+
opName: 'fill',
|
|
98
|
+
});
|
|
99
|
+
expect(ctx.fillStyle).toBe('blue');
|
|
100
|
+
expect(ctx.strokeStyle).toBe('red');
|
|
101
|
+
expect(ctx.translate).toHaveBeenCalledWith(10, 20);
|
|
102
|
+
expect(ctx.rotate).toHaveBeenCalled();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test('uses control sizeX and sizeY when set', () => {
|
|
106
|
+
const control = new Control({ sizeX: 20, sizeY: 30 });
|
|
107
|
+
const ctx = createMockContext();
|
|
108
|
+
const fabricObject = new FabricObject({ cornerSize: 13 });
|
|
109
|
+
|
|
110
|
+
const result = control.commonRenderProps(ctx, 0, 0, fabricObject);
|
|
111
|
+
|
|
112
|
+
expect(result.xSize).toBe(20);
|
|
113
|
+
expect(result.ySize).toBe(30);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('styleOverride takes precedence over fabricObject properties', () => {
|
|
117
|
+
const control = new Control();
|
|
118
|
+
const ctx = createMockContext();
|
|
119
|
+
const fabricObject = new FabricObject({
|
|
120
|
+
cornerSize: 13,
|
|
121
|
+
cornerColor: 'blue',
|
|
122
|
+
transparentCorners: false,
|
|
123
|
+
cornerStrokeColor: 'red',
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const result = control.commonRenderProps(ctx, 0, 0, fabricObject, {
|
|
127
|
+
cornerSize: 25,
|
|
128
|
+
cornerColor: 'green',
|
|
129
|
+
transparentCorners: true,
|
|
130
|
+
cornerStrokeColor: 'yellow',
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
expect(result).toEqual({
|
|
134
|
+
stroke: false,
|
|
135
|
+
xSize: 25,
|
|
136
|
+
ySize: 25,
|
|
137
|
+
transparentCorners: true,
|
|
138
|
+
opName: 'stroke',
|
|
139
|
+
});
|
|
140
|
+
expect(ctx.fillStyle).toBe('green');
|
|
141
|
+
expect(ctx.strokeStyle).toBe('yellow');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('returns stroke false when transparentCorners is true', () => {
|
|
145
|
+
const control = new Control();
|
|
146
|
+
const ctx = createMockContext();
|
|
147
|
+
const fabricObject = new FabricObject({
|
|
148
|
+
transparentCorners: true,
|
|
149
|
+
cornerStrokeColor: 'red',
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const result = control.commonRenderProps(ctx, 0, 0, fabricObject);
|
|
153
|
+
|
|
154
|
+
expect(result.stroke).toBe(false);
|
|
155
|
+
expect(result.opName).toBe('stroke');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test('returns stroke false when no cornerStrokeColor is set', () => {
|
|
159
|
+
const control = new Control();
|
|
160
|
+
const ctx = createMockContext();
|
|
161
|
+
const fabricObject = new FabricObject({
|
|
162
|
+
transparentCorners: false,
|
|
163
|
+
cornerStrokeColor: '',
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const result = control.commonRenderProps(ctx, 0, 0, fabricObject);
|
|
167
|
+
|
|
168
|
+
expect(result.stroke).toBe(false);
|
|
169
|
+
expect(result.opName).toBe('fill');
|
|
170
|
+
});
|
|
171
|
+
});
|
|
70
172
|
});
|