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/dist/index.mjs
CHANGED
|
@@ -356,7 +356,7 @@ class Cache {
|
|
|
356
356
|
}
|
|
357
357
|
const cache = new Cache();
|
|
358
358
|
|
|
359
|
-
var version = "7.
|
|
359
|
+
var version = "7.2.0";
|
|
360
360
|
|
|
361
361
|
// use this syntax so babel plugin see this import here
|
|
362
362
|
const VERSION = version;
|
|
@@ -2191,6 +2191,111 @@ const staticCanvasDefaults = {
|
|
|
2191
2191
|
patternQuality: 'best'
|
|
2192
2192
|
};
|
|
2193
2193
|
|
|
2194
|
+
/**
|
|
2195
|
+
* Capitalizes a string
|
|
2196
|
+
* @param {String} string String to capitalize
|
|
2197
|
+
* @param {Boolean} [firstLetterOnly] If true only first letter is capitalized
|
|
2198
|
+
* and other letters stay untouched, if false first letter is capitalized
|
|
2199
|
+
* and other letters are converted to lowercase.
|
|
2200
|
+
* @return {String} Capitalized version of a string
|
|
2201
|
+
*/
|
|
2202
|
+
const capitalize = function (string) {
|
|
2203
|
+
let firstLetterOnly = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
2204
|
+
return `${string.charAt(0).toUpperCase()}${firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase()}`;
|
|
2205
|
+
};
|
|
2206
|
+
|
|
2207
|
+
/**
|
|
2208
|
+
* Escapes XML in a string
|
|
2209
|
+
* @param {String} string String to escape
|
|
2210
|
+
* @return {String} Escaped version of a string
|
|
2211
|
+
*/
|
|
2212
|
+
const escapeXml = stringOrNumber => stringOrNumber.toString().replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>');
|
|
2213
|
+
let segmenter;
|
|
2214
|
+
const getSegmenter = () => {
|
|
2215
|
+
if (!segmenter) {
|
|
2216
|
+
segmenter = 'Intl' in getFabricWindow() && 'Segmenter' in Intl && new Intl.Segmenter(undefined, {
|
|
2217
|
+
granularity: 'grapheme'
|
|
2218
|
+
});
|
|
2219
|
+
}
|
|
2220
|
+
return segmenter;
|
|
2221
|
+
};
|
|
2222
|
+
|
|
2223
|
+
/**
|
|
2224
|
+
* Divide a string in the user perceived single units
|
|
2225
|
+
* @param {String} textstring String to escape
|
|
2226
|
+
* @return {Array} array containing the graphemes
|
|
2227
|
+
*/
|
|
2228
|
+
const graphemeSplit = textstring => {
|
|
2229
|
+
segmenter || getSegmenter();
|
|
2230
|
+
if (segmenter) {
|
|
2231
|
+
const segments = segmenter.segment(textstring);
|
|
2232
|
+
return Array.from(segments).map(_ref => {
|
|
2233
|
+
let {
|
|
2234
|
+
segment
|
|
2235
|
+
} = _ref;
|
|
2236
|
+
return segment;
|
|
2237
|
+
});
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2240
|
+
//Fallback
|
|
2241
|
+
return graphemeSplitImpl(textstring);
|
|
2242
|
+
};
|
|
2243
|
+
const graphemeSplitImpl = textstring => {
|
|
2244
|
+
const graphemes = [];
|
|
2245
|
+
for (let i = 0, chr; i < textstring.length; i++) {
|
|
2246
|
+
if ((chr = getWholeChar(textstring, i)) === false) {
|
|
2247
|
+
continue;
|
|
2248
|
+
}
|
|
2249
|
+
graphemes.push(chr);
|
|
2250
|
+
}
|
|
2251
|
+
return graphemes;
|
|
2252
|
+
};
|
|
2253
|
+
|
|
2254
|
+
// taken from mdn in the charAt doc page.
|
|
2255
|
+
const getWholeChar = (str, i) => {
|
|
2256
|
+
const code = str.charCodeAt(i);
|
|
2257
|
+
if (isNaN(code)) {
|
|
2258
|
+
return ''; // Position not found
|
|
2259
|
+
}
|
|
2260
|
+
if (code < 0xd800 || code > 0xdfff) {
|
|
2261
|
+
return str.charAt(i);
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
// High surrogate (could change last hex to 0xDB7F to treat high private
|
|
2265
|
+
// surrogates as single characters)
|
|
2266
|
+
if (0xd800 <= code && code <= 0xdbff) {
|
|
2267
|
+
if (str.length <= i + 1) {
|
|
2268
|
+
throw 'High surrogate without following low surrogate';
|
|
2269
|
+
}
|
|
2270
|
+
const next = str.charCodeAt(i + 1);
|
|
2271
|
+
if (0xdc00 > next || next > 0xdfff) {
|
|
2272
|
+
throw 'High surrogate without following low surrogate';
|
|
2273
|
+
}
|
|
2274
|
+
return str.charAt(i) + str.charAt(i + 1);
|
|
2275
|
+
}
|
|
2276
|
+
// Low surrogate (0xDC00 <= code && code <= 0xDFFF)
|
|
2277
|
+
if (i === 0) {
|
|
2278
|
+
throw 'Low surrogate without preceding high surrogate';
|
|
2279
|
+
}
|
|
2280
|
+
const prev = str.charCodeAt(i - 1);
|
|
2281
|
+
|
|
2282
|
+
// (could change last hex to 0xDB7F to treat high private
|
|
2283
|
+
// surrogates as single characters)
|
|
2284
|
+
if (0xd800 > prev || prev > 0xdbff) {
|
|
2285
|
+
throw 'Low surrogate without preceding high surrogate';
|
|
2286
|
+
}
|
|
2287
|
+
// We can pass over low surrogates now as the second component
|
|
2288
|
+
// in a pair which we have already processed
|
|
2289
|
+
return false;
|
|
2290
|
+
};
|
|
2291
|
+
|
|
2292
|
+
var lang_string = /*#__PURE__*/Object.freeze({
|
|
2293
|
+
__proto__: null,
|
|
2294
|
+
capitalize: capitalize,
|
|
2295
|
+
escapeXml: escapeXml,
|
|
2296
|
+
graphemeSplit: graphemeSplit
|
|
2297
|
+
});
|
|
2298
|
+
|
|
2194
2299
|
/**
|
|
2195
2300
|
* Having both options in TCanvasSizeOptions set to true transform the call in a calcOffset
|
|
2196
2301
|
* Better try to restrict with types to avoid confusion.
|
|
@@ -2960,7 +3065,8 @@ class StaticCanvas extends createCollectionMixin(CommonMethods) {
|
|
|
2960
3065
|
this._setSVGPreamble(markup, options);
|
|
2961
3066
|
this._setSVGHeader(markup, options);
|
|
2962
3067
|
if (this.clipPath) {
|
|
2963
|
-
|
|
3068
|
+
var _this$clipPath$clipPa;
|
|
3069
|
+
markup.push(`<g clip-path="url(#${escapeXml((_this$clipPath$clipPa = this.clipPath.clipPathId) !== null && _this$clipPath$clipPa !== void 0 ? _this$clipPath$clipPa : '')})" >\n`);
|
|
2964
3070
|
}
|
|
2965
3071
|
this._setSVGBgOverlayColor(markup, 'background');
|
|
2966
3072
|
this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);
|
|
@@ -3639,20 +3745,6 @@ const sendObjectToPlane = (object, from, to) => {
|
|
|
3639
3745
|
return t;
|
|
3640
3746
|
};
|
|
3641
3747
|
|
|
3642
|
-
const fireEvent = (eventName, options) => {
|
|
3643
|
-
var _target$canvas;
|
|
3644
|
-
const {
|
|
3645
|
-
transform: {
|
|
3646
|
-
target
|
|
3647
|
-
}
|
|
3648
|
-
} = options;
|
|
3649
|
-
(_target$canvas = target.canvas) === null || _target$canvas === void 0 || _target$canvas.fire(`object:${eventName}`, {
|
|
3650
|
-
...options,
|
|
3651
|
-
target
|
|
3652
|
-
});
|
|
3653
|
-
target.fire(eventName, options);
|
|
3654
|
-
};
|
|
3655
|
-
|
|
3656
3748
|
const originOffset = {
|
|
3657
3749
|
left: -0.5,
|
|
3658
3750
|
top: -0.5,
|
|
@@ -3855,33 +3947,6 @@ function getLocalPoint(_ref, originX, originY, x, y) {
|
|
|
3855
3947
|
return localPoint;
|
|
3856
3948
|
}
|
|
3857
3949
|
|
|
3858
|
-
/**
|
|
3859
|
-
* Action handler
|
|
3860
|
-
* @private
|
|
3861
|
-
* @param {Event} eventData javascript event that is doing the transform
|
|
3862
|
-
* @param {Object} transform javascript object containing a series of information around the current transform
|
|
3863
|
-
* @param {number} x current mouse x position, canvas normalized
|
|
3864
|
-
* @param {number} y current mouse y position, canvas normalized
|
|
3865
|
-
* @return {Boolean} true if the translation occurred
|
|
3866
|
-
*/
|
|
3867
|
-
const dragHandler = (eventData, transform, x, y) => {
|
|
3868
|
-
const {
|
|
3869
|
-
target,
|
|
3870
|
-
offsetX,
|
|
3871
|
-
offsetY
|
|
3872
|
-
} = transform,
|
|
3873
|
-
newLeft = x - offsetX,
|
|
3874
|
-
newTop = y - offsetY,
|
|
3875
|
-
moveX = !isLocked(target, 'lockMovementX') && target.left !== newLeft,
|
|
3876
|
-
moveY = !isLocked(target, 'lockMovementY') && target.top !== newTop;
|
|
3877
|
-
moveX && target.set(LEFT, newLeft);
|
|
3878
|
-
moveY && target.set(TOP, newTop);
|
|
3879
|
-
if (moveX || moveY) {
|
|
3880
|
-
fireEvent(MOVING, commonEventInfo(eventData, transform, x, y));
|
|
3881
|
-
}
|
|
3882
|
-
return moveX || moveY;
|
|
3883
|
-
};
|
|
3884
|
-
|
|
3885
3950
|
const normalizeWs = value => value.replace(/\s+/g, ' ');
|
|
3886
3951
|
|
|
3887
3952
|
/**
|
|
@@ -4628,7 +4693,7 @@ const colorPropToSVG = function (prop, value) {
|
|
|
4628
4693
|
if (!value) {
|
|
4629
4694
|
colorValue = 'none';
|
|
4630
4695
|
} else if (value.toLive) {
|
|
4631
|
-
colorValue = `url(#SVGID_${value.id})`;
|
|
4696
|
+
colorValue = `url(#SVGID_${escapeXml(value.id)})`;
|
|
4632
4697
|
} else {
|
|
4633
4698
|
const color = new Color(value),
|
|
4634
4699
|
opacity = color.getAlpha();
|
|
@@ -4681,7 +4746,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4681
4746
|
filter = skipShadow ? '' : this.getSvgFilter(),
|
|
4682
4747
|
fill = colorPropToSVG(FILL, this.fill),
|
|
4683
4748
|
stroke = colorPropToSVG(STROKE, this.stroke);
|
|
4684
|
-
return [stroke, 'stroke-width: ', strokeWidth, '; ', 'stroke-dasharray: ', strokeDashArray, '; ', 'stroke-linecap: ', strokeLineCap, '; ', 'stroke-dashoffset: ', strokeDashOffset, '; ', 'stroke-linejoin: ', strokeLineJoin, '; ', 'stroke-miterlimit: ', strokeMiterLimit, '; ', fill, 'fill-rule: ', fillRule, '; ', 'opacity: ', opacity, ';', filter, visibility].join('');
|
|
4749
|
+
return [stroke, 'stroke-width: ', strokeWidth, '; ', 'stroke-dasharray: ', strokeDashArray, '; ', 'stroke-linecap: ', strokeLineCap, '; ', 'stroke-dashoffset: ', strokeDashOffset, '; ', 'stroke-linejoin: ', strokeLineJoin, '; ', 'stroke-miterlimit: ', strokeMiterLimit, '; ', fill, 'fill-rule: ', fillRule, '; ', 'opacity: ', opacity, ';', filter, visibility].map(v => escapeXml(v)).join('');
|
|
4685
4750
|
}
|
|
4686
4751
|
|
|
4687
4752
|
/**
|
|
@@ -4689,7 +4754,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4689
4754
|
* @return {String}
|
|
4690
4755
|
*/
|
|
4691
4756
|
getSvgFilter() {
|
|
4692
|
-
return this.shadow ? `filter: url(#SVGID_${this.shadow.id});` : '';
|
|
4757
|
+
return this.shadow ? `filter: url(#SVGID_${escapeXml(this.shadow.id)});` : '';
|
|
4693
4758
|
}
|
|
4694
4759
|
|
|
4695
4760
|
/**
|
|
@@ -4697,7 +4762,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4697
4762
|
* @return {String}
|
|
4698
4763
|
*/
|
|
4699
4764
|
getSvgCommons() {
|
|
4700
|
-
return [this.id ? `id="${this.id}" ` : '', this.clipPath ? `clip-path="url(#${this.clipPath.clipPathId})" ` : ''].join('');
|
|
4765
|
+
return [this.id ? `id="${escapeXml(String(this.id))}" ` : '', this.clipPath ? `clip-path="url(#${this.clipPath.clipPathId})" ` : ''].join('');
|
|
4701
4766
|
}
|
|
4702
4767
|
|
|
4703
4768
|
/**
|
|
@@ -4810,7 +4875,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4810
4875
|
return reviver ? reviver(markup.join('')) : markup.join('');
|
|
4811
4876
|
}
|
|
4812
4877
|
addPaintOrder() {
|
|
4813
|
-
return this.paintFirst !== FILL ? ` paint-order="${this.paintFirst}" ` : '';
|
|
4878
|
+
return this.paintFirst !== FILL ? ` paint-order="${escapeXml(this.paintFirst)}" ` : '';
|
|
4814
4879
|
}
|
|
4815
4880
|
}
|
|
4816
4881
|
|
|
@@ -4948,7 +5013,6 @@ const reViewBoxAttrValue = new RegExp(String.raw`^\s*(${reNum})${viewportSeparat
|
|
|
4948
5013
|
|
|
4949
5014
|
(?:$|\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.
|
|
4950
5015
|
*/
|
|
4951
|
-
// eslint-disable-next-line max-len
|
|
4952
5016
|
|
|
4953
5017
|
const shadowOffsetRegex = '(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?';
|
|
4954
5018
|
const reOffsetsAndBlur = new RegExp('(?:\\s|^)' + shadowOffsetRegex + shadowOffsetRegex + '(' + reNum + '?(?:px)?)?(?:\\s?|$)(?:$|\\s)');
|
|
@@ -5007,14 +5071,15 @@ class Shadow {
|
|
|
5007
5071
|
toSVG(object) {
|
|
5008
5072
|
const offset = rotateVector(new Point(this.offsetX, this.offsetY), degreesToRadians(-object.angle)),
|
|
5009
5073
|
BLUR_BOX = 20,
|
|
5074
|
+
NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS,
|
|
5010
5075
|
color = new Color(this.color);
|
|
5011
5076
|
let fBoxX = 40,
|
|
5012
5077
|
fBoxY = 40;
|
|
5013
5078
|
if (object.width && object.height) {
|
|
5014
5079
|
//http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
|
|
5015
5080
|
// we add some extra space to filter box to contain the blur ( 20 )
|
|
5016
|
-
fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width,
|
|
5017
|
-
fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height,
|
|
5081
|
+
fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;
|
|
5082
|
+
fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;
|
|
5018
5083
|
}
|
|
5019
5084
|
if (object.flipX) {
|
|
5020
5085
|
offset.x *= -1;
|
|
@@ -5022,7 +5087,7 @@ class Shadow {
|
|
|
5022
5087
|
if (object.flipY) {
|
|
5023
5088
|
offset.y *= -1;
|
|
5024
5089
|
}
|
|
5025
|
-
return `<filter id="SVGID_${this.id}" y="-${fBoxY}%" height="${100 + 2 * fBoxY}%" x="-${fBoxX}%" width="${100 + 2 * fBoxX}%" >\n\t<feGaussianBlur in="SourceAlpha" stdDeviation="${toFixed(this.blur ? this.blur / 2 : 0,
|
|
5090
|
+
return `<filter id="SVGID_${escapeXml(this.id)}" y="-${fBoxY}%" height="${100 + 2 * fBoxY}%" x="-${fBoxX}%" width="${100 + 2 * fBoxX}%" >\n\t<feGaussianBlur in="SourceAlpha" stdDeviation="${toFixed(this.blur ? this.blur / 2 : 0, NUM_FRACTION_DIGITS)}"></feGaussianBlur>\n\t<feOffset dx="${toFixed(offset.x, NUM_FRACTION_DIGITS)}" dy="${toFixed(offset.y, NUM_FRACTION_DIGITS)}" 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`;
|
|
5026
5091
|
}
|
|
5027
5092
|
|
|
5028
5093
|
/**
|
|
@@ -6432,7 +6497,7 @@ class ObjectGeometry extends CommonMethods {
|
|
|
6432
6497
|
calcOwnMatrix() {
|
|
6433
6498
|
const key = this.transformMatrixKey(true),
|
|
6434
6499
|
cache = this.ownMatrixCache;
|
|
6435
|
-
if (cache && cache.key === key) {
|
|
6500
|
+
if (cache && cache.key.every((x, i) => x === key[i])) {
|
|
6436
6501
|
return cache.value;
|
|
6437
6502
|
}
|
|
6438
6503
|
const center = this.getRelativeCenterPoint(),
|
|
@@ -7173,6 +7238,9 @@ let FabricObject$1 = class FabricObject extends ObjectGeometry {
|
|
|
7173
7238
|
} else {
|
|
7174
7239
|
this._renderBackground(ctx);
|
|
7175
7240
|
}
|
|
7241
|
+
this.fire('before:render', {
|
|
7242
|
+
ctx
|
|
7243
|
+
});
|
|
7176
7244
|
this._render(ctx);
|
|
7177
7245
|
this._drawClipPath(ctx, this.clipPath, context);
|
|
7178
7246
|
this.fill = originalFill;
|
|
@@ -8173,6 +8241,20 @@ _defineProperty(FabricObject$1, "customProperties", []);
|
|
|
8173
8241
|
classRegistry.setClass(FabricObject$1);
|
|
8174
8242
|
classRegistry.setClass(FabricObject$1, 'object');
|
|
8175
8243
|
|
|
8244
|
+
const fireEvent = (eventName, options) => {
|
|
8245
|
+
var _target$canvas;
|
|
8246
|
+
const {
|
|
8247
|
+
transform: {
|
|
8248
|
+
target
|
|
8249
|
+
}
|
|
8250
|
+
} = options;
|
|
8251
|
+
(_target$canvas = target.canvas) === null || _target$canvas === void 0 || _target$canvas.fire(`object:${eventName}`, {
|
|
8252
|
+
...options,
|
|
8253
|
+
target
|
|
8254
|
+
});
|
|
8255
|
+
target.fire(eventName, options);
|
|
8256
|
+
};
|
|
8257
|
+
|
|
8176
8258
|
/**
|
|
8177
8259
|
* Wrap an action handler with firing an event if the action is performed
|
|
8178
8260
|
* @param {TModificationEvents} eventName the event we want to fire
|
|
@@ -8215,34 +8297,62 @@ function wrapWithFixedAnchor(actionHandler) {
|
|
|
8215
8297
|
};
|
|
8216
8298
|
}
|
|
8217
8299
|
|
|
8218
|
-
|
|
8219
|
-
* Action handler to change object's width
|
|
8220
|
-
* Needs to be wrapped with `wrapWithFixedAnchor` to be effective
|
|
8221
|
-
* @param {Event} eventData javascript event that is doing the transform
|
|
8222
|
-
* @param {Object} transform javascript object containing a series of information around the current transform
|
|
8223
|
-
* @param {number} x current mouse x position, canvas normalized
|
|
8224
|
-
* @param {number} y current mouse y position, canvas normalized
|
|
8225
|
-
* @return {Boolean} true if some change happened
|
|
8226
|
-
*/
|
|
8227
|
-
const changeObjectWidth = (eventData, transform, x, y) => {
|
|
8300
|
+
const changeObjectDimensionGen = (dimension, origin, xorY, scale) => (eventData, transform, x, y) => {
|
|
8228
8301
|
const localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y);
|
|
8302
|
+
const localPointValue = localPoint[xorY];
|
|
8229
8303
|
// make sure the control changes width ONLY from it's side of target
|
|
8230
|
-
|
|
8304
|
+
const originValue = resolveOrigin(transform[origin]);
|
|
8305
|
+
if (originValue === 0 || originValue > 0 && localPointValue < 0 || originValue < 0 && localPointValue > 0) {
|
|
8231
8306
|
const {
|
|
8232
8307
|
target
|
|
8233
8308
|
} = transform,
|
|
8234
|
-
strokePadding = target.strokeWidth / (target.strokeUniform ? target
|
|
8309
|
+
strokePadding = target.strokeWidth / (target.strokeUniform ? target[scale] : 1),
|
|
8235
8310
|
multiplier = isTransformCentered(transform) ? 2 : 1,
|
|
8236
|
-
oldWidth = target
|
|
8237
|
-
newWidth = Math.abs(
|
|
8238
|
-
target.set(
|
|
8311
|
+
oldWidth = target[dimension],
|
|
8312
|
+
newWidth = Math.abs(localPointValue * multiplier / target[scale]) - strokePadding;
|
|
8313
|
+
target.set(dimension, Math.max(newWidth, 1));
|
|
8239
8314
|
// check against actual target width in case `newWidth` was rejected
|
|
8240
|
-
return oldWidth !== target
|
|
8315
|
+
return oldWidth !== target[dimension];
|
|
8241
8316
|
}
|
|
8242
8317
|
return false;
|
|
8243
8318
|
};
|
|
8319
|
+
|
|
8320
|
+
/**
|
|
8321
|
+
* Action handler to change object's width
|
|
8322
|
+
* Needs to be wrapped with `wrapWithFixedAnchor` to be effective
|
|
8323
|
+
* You want to use this only if you are building a new control handler and you want
|
|
8324
|
+
* to reuse some logic. use "changeWidth" if you are looking to just use a control for width
|
|
8325
|
+
* @param {Event} eventData javascript event that is doing the transform
|
|
8326
|
+
* @param {Object} transform javascript object containing a series of information around the current transform
|
|
8327
|
+
* @param {number} x current mouse x position, canvas normalized
|
|
8328
|
+
* @param {number} y current mouse y position, canvas normalized
|
|
8329
|
+
* @return {Boolean} true if some change happened
|
|
8330
|
+
*/
|
|
8331
|
+
const changeObjectWidth = changeObjectDimensionGen('width', 'originX', 'x', 'scaleX');
|
|
8332
|
+
|
|
8333
|
+
/**
|
|
8334
|
+
* Action handler to change object's height
|
|
8335
|
+
* Needs to be wrapped with `wrapWithFixedAnchor` to be effective
|
|
8336
|
+
* You want to use this only if you are building a new control handler and you want
|
|
8337
|
+
* to reuse some logic. use "changeHeight" if you are looking to just use a control for height
|
|
8338
|
+
* @param {Event} eventData javascript event that is doing the transform
|
|
8339
|
+
* @param {Object} transform javascript object containing a series of information around the current transform
|
|
8340
|
+
* @param {number} x current mouse x position, canvas normalized
|
|
8341
|
+
* @param {number} y current mouse y position, canvas normalized
|
|
8342
|
+
* @return {Boolean} true if some change happened
|
|
8343
|
+
*/
|
|
8344
|
+
const changeObjectHeight = changeObjectDimensionGen('height', 'originY', 'y', 'scaleY');
|
|
8345
|
+
|
|
8346
|
+
/**
|
|
8347
|
+
* Control handler for changing width
|
|
8348
|
+
*/
|
|
8244
8349
|
const changeWidth = wrapWithFireEvent(RESIZING, wrapWithFixedAnchor(changeObjectWidth));
|
|
8245
8350
|
|
|
8351
|
+
/**
|
|
8352
|
+
* Control handler for changing height
|
|
8353
|
+
*/
|
|
8354
|
+
const changeHeight = wrapWithFireEvent(RESIZING, wrapWithFixedAnchor(changeObjectHeight));
|
|
8355
|
+
|
|
8246
8356
|
/**
|
|
8247
8357
|
* Render a round control, as per fabric features.
|
|
8248
8358
|
* This function is written to respect object properties like transparentCorners, cornerSize
|
|
@@ -8255,33 +8365,24 @@ const changeWidth = wrapWithFireEvent(RESIZING, wrapWithFixedAnchor(changeObject
|
|
|
8255
8365
|
* @param {FabricObject} fabricObject the fabric object for which we are rendering controls
|
|
8256
8366
|
*/
|
|
8257
8367
|
function renderCircleControl(ctx, left, top, styleOverride, fabricObject) {
|
|
8258
|
-
styleOverride = styleOverride || {};
|
|
8259
|
-
const xSize = this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize,
|
|
8260
|
-
ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize,
|
|
8261
|
-
transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ? styleOverride.transparentCorners : fabricObject.transparentCorners,
|
|
8262
|
-
methodName = transparentCorners ? STROKE : FILL,
|
|
8263
|
-
stroke = !transparentCorners && (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor);
|
|
8264
|
-
let myLeft = left,
|
|
8265
|
-
myTop = top,
|
|
8266
|
-
size;
|
|
8267
8368
|
ctx.save();
|
|
8268
|
-
|
|
8269
|
-
|
|
8369
|
+
const {
|
|
8370
|
+
stroke,
|
|
8371
|
+
xSize,
|
|
8372
|
+
ySize,
|
|
8373
|
+
opName
|
|
8374
|
+
} = this.commonRenderProps(ctx, left, top, fabricObject, styleOverride);
|
|
8375
|
+
let size = xSize;
|
|
8270
8376
|
// TODO: use proper ellipse code.
|
|
8271
8377
|
if (xSize > ySize) {
|
|
8272
|
-
size = xSize;
|
|
8273
8378
|
ctx.scale(1.0, ySize / xSize);
|
|
8274
|
-
myTop = top * xSize / ySize;
|
|
8275
8379
|
} else if (ySize > xSize) {
|
|
8276
8380
|
size = ySize;
|
|
8277
8381
|
ctx.scale(xSize / ySize, 1.0);
|
|
8278
|
-
myLeft = left * ySize / xSize;
|
|
8279
|
-
} else {
|
|
8280
|
-
size = xSize;
|
|
8281
8382
|
}
|
|
8282
8383
|
ctx.beginPath();
|
|
8283
|
-
ctx.arc(
|
|
8284
|
-
ctx[
|
|
8384
|
+
ctx.arc(0, 0, size / 2, 0, twoMathPi, false);
|
|
8385
|
+
ctx[opName]();
|
|
8285
8386
|
if (stroke) {
|
|
8286
8387
|
ctx.stroke();
|
|
8287
8388
|
}
|
|
@@ -8300,25 +8401,19 @@ function renderCircleControl(ctx, left, top, styleOverride, fabricObject) {
|
|
|
8300
8401
|
* @param {FabricObject} fabricObject the fabric object for which we are rendering controls
|
|
8301
8402
|
*/
|
|
8302
8403
|
function renderSquareControl(ctx, left, top, styleOverride, fabricObject) {
|
|
8303
|
-
|
|
8304
|
-
const
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8404
|
+
ctx.save();
|
|
8405
|
+
const {
|
|
8406
|
+
stroke,
|
|
8407
|
+
xSize,
|
|
8408
|
+
ySize,
|
|
8409
|
+
opName
|
|
8410
|
+
} = this.commonRenderProps(ctx, left, top, fabricObject, styleOverride),
|
|
8309
8411
|
xSizeBy2 = xSize / 2,
|
|
8310
8412
|
ySizeBy2 = ySize / 2;
|
|
8311
|
-
ctx.save();
|
|
8312
|
-
ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor || '';
|
|
8313
|
-
ctx.strokeStyle = styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor || '';
|
|
8314
|
-
ctx.translate(left, top);
|
|
8315
|
-
// angle is relative to canvas plane
|
|
8316
|
-
const angle = fabricObject.getTotalAngle();
|
|
8317
|
-
ctx.rotate(degreesToRadians(angle));
|
|
8318
8413
|
// this does not work, and fixed with ( && ) does not make sense.
|
|
8319
8414
|
// to have real transparent corners we need the controls on upperCanvas
|
|
8320
8415
|
// transparentCorners || ctx.clearRect(-xSizeBy2, -ySizeBy2, xSize, ySize);
|
|
8321
|
-
ctx[`${
|
|
8416
|
+
ctx[`${opName}Rect`](-xSizeBy2, -ySizeBy2, xSize, ySize);
|
|
8322
8417
|
if (stroke) {
|
|
8323
8418
|
ctx.strokeRect(-xSizeBy2, -ySizeBy2, xSize, ySize);
|
|
8324
8419
|
}
|
|
@@ -8436,6 +8531,14 @@ class Control {
|
|
|
8436
8531
|
_defineProperty(this, "withConnection", false);
|
|
8437
8532
|
Object.assign(this, options);
|
|
8438
8533
|
}
|
|
8534
|
+
getTransformAnchorPoint() {
|
|
8535
|
+
var _this$transformAnchor;
|
|
8536
|
+
return (// return the control transformAnchorPoint
|
|
8537
|
+
(_this$transformAnchor = this.transformAnchorPoint) !== null && _this$transformAnchor !== void 0 ? _this$transformAnchor :
|
|
8538
|
+
// otherwise will return the opposite origin of where the control is located.
|
|
8539
|
+
new Point(-this.x + 0.5, -this.y + 0.5)
|
|
8540
|
+
);
|
|
8541
|
+
}
|
|
8439
8542
|
|
|
8440
8543
|
/**
|
|
8441
8544
|
* The control actionHandler, provide one to handle action ( control being moved )
|
|
@@ -8578,6 +8681,41 @@ class Control {
|
|
|
8578
8681
|
};
|
|
8579
8682
|
}
|
|
8580
8683
|
|
|
8684
|
+
/**
|
|
8685
|
+
* This is an helper method to prepare the canvas to render a control
|
|
8686
|
+
* It detectes common control properties and sets the correct fill and
|
|
8687
|
+
* stroke styles on the context. It does not execute translations or
|
|
8688
|
+
* rotations since different controls need differnt combination of these.
|
|
8689
|
+
*/
|
|
8690
|
+
commonRenderProps(ctx, left, top, fabricObject) {
|
|
8691
|
+
let styleOverride = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
8692
|
+
const {
|
|
8693
|
+
cornerSize,
|
|
8694
|
+
cornerColor,
|
|
8695
|
+
transparentCorners,
|
|
8696
|
+
cornerStrokeColor
|
|
8697
|
+
} = styleOverride,
|
|
8698
|
+
sizeFromProps = cornerSize || fabricObject.cornerSize,
|
|
8699
|
+
xSize = this.sizeX || sizeFromProps,
|
|
8700
|
+
ySize = this.sizeY || sizeFromProps,
|
|
8701
|
+
transparent = typeof transparentCorners !== 'undefined' ? transparentCorners : fabricObject.transparentCorners,
|
|
8702
|
+
opName = transparent ? STROKE : FILL,
|
|
8703
|
+
strokeColor = cornerStrokeColor || fabricObject.cornerStrokeColor,
|
|
8704
|
+
stroke = !transparent && !!strokeColor;
|
|
8705
|
+
ctx.fillStyle = cornerColor || fabricObject.cornerColor || '';
|
|
8706
|
+
ctx.strokeStyle = strokeColor || '';
|
|
8707
|
+
ctx.translate(left, top);
|
|
8708
|
+
// angle is relative to canvas plane
|
|
8709
|
+
ctx.rotate(degreesToRadians(fabricObject.getTotalAngle()));
|
|
8710
|
+
return {
|
|
8711
|
+
stroke,
|
|
8712
|
+
xSize,
|
|
8713
|
+
ySize,
|
|
8714
|
+
transparentCorners: transparent,
|
|
8715
|
+
opName
|
|
8716
|
+
};
|
|
8717
|
+
}
|
|
8718
|
+
|
|
8581
8719
|
/**
|
|
8582
8720
|
* Render function for the control.
|
|
8583
8721
|
* When this function runs the context is unscaled. unrotate. Just retina scaled.
|
|
@@ -10217,136 +10355,31 @@ const cloneStyles = style => {
|
|
|
10217
10355
|
};
|
|
10218
10356
|
|
|
10219
10357
|
/**
|
|
10220
|
-
*
|
|
10221
|
-
* @param {
|
|
10222
|
-
* @param {
|
|
10223
|
-
*
|
|
10224
|
-
* and other letters are converted to lowercase.
|
|
10225
|
-
* @return {String} Capitalized version of a string
|
|
10358
|
+
* @param {Object} prevStyle first style to compare
|
|
10359
|
+
* @param {Object} thisStyle second style to compare
|
|
10360
|
+
* @param {boolean} forTextSpans whether to check overline, underline, and line-through properties
|
|
10361
|
+
* @return {boolean} true if the style changed
|
|
10226
10362
|
*/
|
|
10227
|
-
const
|
|
10228
|
-
let
|
|
10229
|
-
return
|
|
10363
|
+
const hasStyleChanged = function (prevStyle, thisStyle) {
|
|
10364
|
+
let forTextSpans = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
10365
|
+
return prevStyle.fill !== thisStyle.fill || prevStyle.stroke !== thisStyle.stroke || prevStyle.strokeWidth !== thisStyle.strokeWidth || prevStyle.fontSize !== thisStyle.fontSize || prevStyle.fontFamily !== thisStyle.fontFamily || prevStyle.fontWeight !== thisStyle.fontWeight || prevStyle.fontStyle !== thisStyle.fontStyle || prevStyle.textDecorationThickness !== thisStyle.textDecorationThickness || prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor || prevStyle.deltaY !== thisStyle.deltaY || forTextSpans && (prevStyle.overline !== thisStyle.overline || prevStyle.underline !== thisStyle.underline || prevStyle.linethrough !== thisStyle.linethrough);
|
|
10230
10366
|
};
|
|
10231
10367
|
|
|
10232
10368
|
/**
|
|
10233
|
-
*
|
|
10234
|
-
*
|
|
10235
|
-
*
|
|
10369
|
+
* Returns the array form of a text object's inline styles property with styles grouped in ranges
|
|
10370
|
+
* rather than per character. This format is less verbose, and is better suited for storage
|
|
10371
|
+
* so it is used in serialization (not during runtime).
|
|
10372
|
+
* @param {object} styles per character styles for a text object
|
|
10373
|
+
* @param {String} text the text string that the styles are applied to
|
|
10374
|
+
* @return {{start: number, end: number, style: object}[]}
|
|
10236
10375
|
*/
|
|
10237
|
-
const
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10241
|
-
|
|
10242
|
-
|
|
10243
|
-
|
|
10244
|
-
}
|
|
10245
|
-
return segmenter;
|
|
10246
|
-
};
|
|
10247
|
-
|
|
10248
|
-
/**
|
|
10249
|
-
* Divide a string in the user perceived single units
|
|
10250
|
-
* @param {String} textstring String to escape
|
|
10251
|
-
* @return {Array} array containing the graphemes
|
|
10252
|
-
*/
|
|
10253
|
-
const graphemeSplit = textstring => {
|
|
10254
|
-
segmenter || getSegmenter();
|
|
10255
|
-
if (segmenter) {
|
|
10256
|
-
const segments = segmenter.segment(textstring);
|
|
10257
|
-
return Array.from(segments).map(_ref => {
|
|
10258
|
-
let {
|
|
10259
|
-
segment
|
|
10260
|
-
} = _ref;
|
|
10261
|
-
return segment;
|
|
10262
|
-
});
|
|
10263
|
-
}
|
|
10264
|
-
|
|
10265
|
-
//Fallback
|
|
10266
|
-
return graphemeSplitImpl(textstring);
|
|
10267
|
-
};
|
|
10268
|
-
const graphemeSplitImpl = textstring => {
|
|
10269
|
-
const graphemes = [];
|
|
10270
|
-
for (let i = 0, chr; i < textstring.length; i++) {
|
|
10271
|
-
if ((chr = getWholeChar(textstring, i)) === false) {
|
|
10272
|
-
continue;
|
|
10273
|
-
}
|
|
10274
|
-
graphemes.push(chr);
|
|
10275
|
-
}
|
|
10276
|
-
return graphemes;
|
|
10277
|
-
};
|
|
10278
|
-
|
|
10279
|
-
// taken from mdn in the charAt doc page.
|
|
10280
|
-
const getWholeChar = (str, i) => {
|
|
10281
|
-
const code = str.charCodeAt(i);
|
|
10282
|
-
if (isNaN(code)) {
|
|
10283
|
-
return ''; // Position not found
|
|
10284
|
-
}
|
|
10285
|
-
if (code < 0xd800 || code > 0xdfff) {
|
|
10286
|
-
return str.charAt(i);
|
|
10287
|
-
}
|
|
10288
|
-
|
|
10289
|
-
// High surrogate (could change last hex to 0xDB7F to treat high private
|
|
10290
|
-
// surrogates as single characters)
|
|
10291
|
-
if (0xd800 <= code && code <= 0xdbff) {
|
|
10292
|
-
if (str.length <= i + 1) {
|
|
10293
|
-
throw 'High surrogate without following low surrogate';
|
|
10294
|
-
}
|
|
10295
|
-
const next = str.charCodeAt(i + 1);
|
|
10296
|
-
if (0xdc00 > next || next > 0xdfff) {
|
|
10297
|
-
throw 'High surrogate without following low surrogate';
|
|
10298
|
-
}
|
|
10299
|
-
return str.charAt(i) + str.charAt(i + 1);
|
|
10300
|
-
}
|
|
10301
|
-
// Low surrogate (0xDC00 <= code && code <= 0xDFFF)
|
|
10302
|
-
if (i === 0) {
|
|
10303
|
-
throw 'Low surrogate without preceding high surrogate';
|
|
10304
|
-
}
|
|
10305
|
-
const prev = str.charCodeAt(i - 1);
|
|
10306
|
-
|
|
10307
|
-
// (could change last hex to 0xDB7F to treat high private
|
|
10308
|
-
// surrogates as single characters)
|
|
10309
|
-
if (0xd800 > prev || prev > 0xdbff) {
|
|
10310
|
-
throw 'Low surrogate without preceding high surrogate';
|
|
10311
|
-
}
|
|
10312
|
-
// We can pass over low surrogates now as the second component
|
|
10313
|
-
// in a pair which we have already processed
|
|
10314
|
-
return false;
|
|
10315
|
-
};
|
|
10316
|
-
|
|
10317
|
-
var lang_string = /*#__PURE__*/Object.freeze({
|
|
10318
|
-
__proto__: null,
|
|
10319
|
-
capitalize: capitalize,
|
|
10320
|
-
escapeXml: escapeXml,
|
|
10321
|
-
graphemeSplit: graphemeSplit
|
|
10322
|
-
});
|
|
10323
|
-
|
|
10324
|
-
/**
|
|
10325
|
-
* @param {Object} prevStyle first style to compare
|
|
10326
|
-
* @param {Object} thisStyle second style to compare
|
|
10327
|
-
* @param {boolean} forTextSpans whether to check overline, underline, and line-through properties
|
|
10328
|
-
* @return {boolean} true if the style changed
|
|
10329
|
-
*/
|
|
10330
|
-
const hasStyleChanged = function (prevStyle, thisStyle) {
|
|
10331
|
-
let forTextSpans = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
10332
|
-
return prevStyle.fill !== thisStyle.fill || prevStyle.stroke !== thisStyle.stroke || prevStyle.strokeWidth !== thisStyle.strokeWidth || prevStyle.fontSize !== thisStyle.fontSize || prevStyle.fontFamily !== thisStyle.fontFamily || prevStyle.fontWeight !== thisStyle.fontWeight || prevStyle.fontStyle !== thisStyle.fontStyle || prevStyle.textDecorationThickness !== thisStyle.textDecorationThickness || prevStyle.textBackgroundColor !== thisStyle.textBackgroundColor || prevStyle.deltaY !== thisStyle.deltaY || forTextSpans && (prevStyle.overline !== thisStyle.overline || prevStyle.underline !== thisStyle.underline || prevStyle.linethrough !== thisStyle.linethrough);
|
|
10333
|
-
};
|
|
10334
|
-
|
|
10335
|
-
/**
|
|
10336
|
-
* Returns the array form of a text object's inline styles property with styles grouped in ranges
|
|
10337
|
-
* rather than per character. This format is less verbose, and is better suited for storage
|
|
10338
|
-
* so it is used in serialization (not during runtime).
|
|
10339
|
-
* @param {object} styles per character styles for a text object
|
|
10340
|
-
* @param {String} text the text string that the styles are applied to
|
|
10341
|
-
* @return {{start: number, end: number, style: object}[]}
|
|
10342
|
-
*/
|
|
10343
|
-
const stylesToArray = (styles, text) => {
|
|
10344
|
-
const textLines = text.split('\n'),
|
|
10345
|
-
stylesArray = [];
|
|
10346
|
-
let charIndex = -1,
|
|
10347
|
-
prevStyle = {};
|
|
10348
|
-
// clone style structure to prevent mutation
|
|
10349
|
-
styles = cloneStyles(styles);
|
|
10376
|
+
const stylesToArray = (styles, text) => {
|
|
10377
|
+
const textLines = text.split('\n'),
|
|
10378
|
+
stylesArray = [];
|
|
10379
|
+
let charIndex = -1,
|
|
10380
|
+
prevStyle = {};
|
|
10381
|
+
// clone style structure to prevent mutation
|
|
10382
|
+
styles = cloneStyles(styles);
|
|
10350
10383
|
|
|
10351
10384
|
//loop through each textLine
|
|
10352
10385
|
for (let i = 0; i < textLines.length; i++) {
|
|
@@ -10904,7 +10937,7 @@ class Rect extends FabricObject {
|
|
|
10904
10937
|
rx,
|
|
10905
10938
|
ry
|
|
10906
10939
|
} = this;
|
|
10907
|
-
return ['<rect ', 'COMMON_PARTS', `x="${-width / 2}" y="${-height / 2}" rx="${rx}" ry="${ry}" width="${width}" height="${height}" />\n`];
|
|
10940
|
+
return ['<rect ', 'COMMON_PARTS', `x="${-width / 2}" y="${-height / 2}" rx="${escapeXml(rx)}" ry="${escapeXml(ry)}" width="${escapeXml(width)}" height="${escapeXml(height)}" />\n`];
|
|
10908
10941
|
}
|
|
10909
10942
|
|
|
10910
10943
|
/**
|
|
@@ -11869,7 +11902,7 @@ class Group extends createCollectionMixin(FabricObject) {
|
|
|
11869
11902
|
* @return {String}
|
|
11870
11903
|
*/
|
|
11871
11904
|
getSvgStyles() {
|
|
11872
|
-
const opacity = typeof this.opacity !== 'undefined' && this.opacity !== 1 ? `opacity: ${this.opacity};` : '',
|
|
11905
|
+
const opacity = typeof this.opacity !== 'undefined' && this.opacity !== 1 ? `opacity: ${escapeXml(this.opacity)};` : '',
|
|
11873
11906
|
visibility = this.visible ? '' : ' visibility: hidden;';
|
|
11874
11907
|
return [opacity, this.getSvgFilter(), visibility].join('');
|
|
11875
11908
|
}
|
|
@@ -13171,6 +13204,288 @@ const canvasDefaults = {
|
|
|
13171
13204
|
preserveObjectStacking: true
|
|
13172
13205
|
};
|
|
13173
13206
|
|
|
13207
|
+
/**
|
|
13208
|
+
* Action handler
|
|
13209
|
+
* @private
|
|
13210
|
+
* @param {Event} eventData javascript event that is doing the transform
|
|
13211
|
+
* @param {Object} transform javascript object containing a series of information around the current transform
|
|
13212
|
+
* @param {number} x current mouse x position, canvas normalized
|
|
13213
|
+
* @param {number} y current mouse y position, canvas normalized
|
|
13214
|
+
* @return {Boolean} true if the translation occurred
|
|
13215
|
+
*/
|
|
13216
|
+
const dragHandler = (eventData, transform, x, y) => {
|
|
13217
|
+
const {
|
|
13218
|
+
target,
|
|
13219
|
+
offsetX,
|
|
13220
|
+
offsetY
|
|
13221
|
+
} = transform,
|
|
13222
|
+
newLeft = x - offsetX,
|
|
13223
|
+
newTop = y - offsetY,
|
|
13224
|
+
moveX = !isLocked(target, 'lockMovementX') && target.left !== newLeft,
|
|
13225
|
+
moveY = !isLocked(target, 'lockMovementY') && target.top !== newTop;
|
|
13226
|
+
moveX && target.set(LEFT, newLeft);
|
|
13227
|
+
moveY && target.set(TOP, newTop);
|
|
13228
|
+
if (moveX || moveY) {
|
|
13229
|
+
fireEvent(MOVING, commonEventInfo(eventData, transform, x, y));
|
|
13230
|
+
}
|
|
13231
|
+
return moveX || moveY;
|
|
13232
|
+
};
|
|
13233
|
+
|
|
13234
|
+
const ACTION_NAME$1 = MODIFY_POLY;
|
|
13235
|
+
/**
|
|
13236
|
+
* This function locates the controls.
|
|
13237
|
+
* It'll be used both for drawing and for interaction.
|
|
13238
|
+
*/
|
|
13239
|
+
const createPolyPositionHandler = pointIndex => {
|
|
13240
|
+
return function (dim, finalMatrix, polyObject) {
|
|
13241
|
+
const {
|
|
13242
|
+
points,
|
|
13243
|
+
pathOffset
|
|
13244
|
+
} = polyObject;
|
|
13245
|
+
return new Point(points[pointIndex]).subtract(pathOffset).transform(multiplyTransformMatrices(polyObject.getViewportTransform(), polyObject.calcTransformMatrix()));
|
|
13246
|
+
};
|
|
13247
|
+
};
|
|
13248
|
+
|
|
13249
|
+
/**
|
|
13250
|
+
* This function defines what the control does.
|
|
13251
|
+
* It'll be called on every mouse move after a control has been clicked and is being dragged.
|
|
13252
|
+
* The function receives as argument the mouse event, the current transform object
|
|
13253
|
+
* and the current position in canvas coordinate `transform.target` is a reference to the
|
|
13254
|
+
* current object being transformed.
|
|
13255
|
+
*/
|
|
13256
|
+
const polyActionHandler = (eventData, transform, x, y) => {
|
|
13257
|
+
const {
|
|
13258
|
+
target,
|
|
13259
|
+
pointIndex
|
|
13260
|
+
} = transform;
|
|
13261
|
+
const poly = target;
|
|
13262
|
+
const mouseLocalPosition = sendPointToPlane(new Point(x, y), undefined, poly.calcOwnMatrix());
|
|
13263
|
+
poly.points[pointIndex] = mouseLocalPosition.add(poly.pathOffset);
|
|
13264
|
+
poly.setDimensions();
|
|
13265
|
+
poly.set('dirty', true);
|
|
13266
|
+
return true;
|
|
13267
|
+
};
|
|
13268
|
+
|
|
13269
|
+
/**
|
|
13270
|
+
* Keep the polygon in the same position when we change its `width`/`height`/`top`/`left`.
|
|
13271
|
+
*/
|
|
13272
|
+
const factoryPolyActionHandler = (pointIndex, fn) => {
|
|
13273
|
+
return function (eventData, transform, x, y) {
|
|
13274
|
+
const poly = transform.target,
|
|
13275
|
+
anchorPoint = new Point(poly.points[(pointIndex > 0 ? pointIndex : poly.points.length) - 1]),
|
|
13276
|
+
anchorPointInParentPlane = anchorPoint.subtract(poly.pathOffset).transform(poly.calcOwnMatrix()),
|
|
13277
|
+
actionPerformed = fn(eventData, {
|
|
13278
|
+
...transform,
|
|
13279
|
+
pointIndex
|
|
13280
|
+
}, x, y);
|
|
13281
|
+
const newAnchorPointInParentPlane = anchorPoint.subtract(poly.pathOffset).transform(poly.calcOwnMatrix());
|
|
13282
|
+
const diff = newAnchorPointInParentPlane.subtract(anchorPointInParentPlane);
|
|
13283
|
+
poly.left -= diff.x;
|
|
13284
|
+
poly.top -= diff.y;
|
|
13285
|
+
return actionPerformed;
|
|
13286
|
+
};
|
|
13287
|
+
};
|
|
13288
|
+
const createPolyActionHandler = pointIndex => wrapWithFireEvent(ACTION_NAME$1, factoryPolyActionHandler(pointIndex, polyActionHandler));
|
|
13289
|
+
function createPolyControls(arg0) {
|
|
13290
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
13291
|
+
const controls = {};
|
|
13292
|
+
for (let idx = 0; idx < (typeof arg0 === 'number' ? arg0 : arg0.points.length); idx++) {
|
|
13293
|
+
controls[`p${idx}`] = new Control({
|
|
13294
|
+
actionName: ACTION_NAME$1,
|
|
13295
|
+
positionHandler: createPolyPositionHandler(idx),
|
|
13296
|
+
actionHandler: createPolyActionHandler(idx),
|
|
13297
|
+
...options
|
|
13298
|
+
});
|
|
13299
|
+
}
|
|
13300
|
+
return controls;
|
|
13301
|
+
}
|
|
13302
|
+
|
|
13303
|
+
const ACTION_NAME = 'modifyPath';
|
|
13304
|
+
const calcPathPointPosition = (pathObject, commandIndex, pointIndex) => {
|
|
13305
|
+
const {
|
|
13306
|
+
path,
|
|
13307
|
+
pathOffset
|
|
13308
|
+
} = pathObject;
|
|
13309
|
+
const command = path[commandIndex];
|
|
13310
|
+
return new Point(command[pointIndex] - pathOffset.x, command[pointIndex + 1] - pathOffset.y).transform(multiplyTransformMatrices(pathObject.getViewportTransform(), pathObject.calcTransformMatrix()));
|
|
13311
|
+
};
|
|
13312
|
+
const movePathPoint = (pathObject, x, y, commandIndex, pointIndex) => {
|
|
13313
|
+
const {
|
|
13314
|
+
path,
|
|
13315
|
+
pathOffset
|
|
13316
|
+
} = pathObject;
|
|
13317
|
+
const anchorCommand = path[(commandIndex > 0 ? commandIndex : path.length) - 1];
|
|
13318
|
+
const anchorPoint = new Point(anchorCommand[pointIndex], anchorCommand[pointIndex + 1]);
|
|
13319
|
+
const anchorPointInParentPlane = anchorPoint.subtract(pathOffset).transform(pathObject.calcOwnMatrix());
|
|
13320
|
+
const mouseLocalPosition = sendPointToPlane(new Point(x, y), undefined, pathObject.calcOwnMatrix());
|
|
13321
|
+
path[commandIndex][pointIndex] = mouseLocalPosition.x + pathOffset.x;
|
|
13322
|
+
path[commandIndex][pointIndex + 1] = mouseLocalPosition.y + pathOffset.y;
|
|
13323
|
+
pathObject.setDimensions();
|
|
13324
|
+
const newAnchorPointInParentPlane = anchorPoint.subtract(pathObject.pathOffset).transform(pathObject.calcOwnMatrix());
|
|
13325
|
+
const diff = newAnchorPointInParentPlane.subtract(anchorPointInParentPlane);
|
|
13326
|
+
pathObject.left -= diff.x;
|
|
13327
|
+
pathObject.top -= diff.y;
|
|
13328
|
+
pathObject.set('dirty', true);
|
|
13329
|
+
return true;
|
|
13330
|
+
};
|
|
13331
|
+
|
|
13332
|
+
/**
|
|
13333
|
+
* This function locates the controls.
|
|
13334
|
+
* It'll be used both for drawing and for interaction.
|
|
13335
|
+
*/
|
|
13336
|
+
function pathPositionHandler(dim, finalMatrix, pathObject) {
|
|
13337
|
+
const {
|
|
13338
|
+
commandIndex,
|
|
13339
|
+
pointIndex
|
|
13340
|
+
} = this;
|
|
13341
|
+
return calcPathPointPosition(pathObject, commandIndex, pointIndex);
|
|
13342
|
+
}
|
|
13343
|
+
|
|
13344
|
+
/**
|
|
13345
|
+
* This function defines what the control does.
|
|
13346
|
+
* It'll be called on every mouse move after a control has been clicked and is being dragged.
|
|
13347
|
+
* The function receives as argument the mouse event, the current transform object
|
|
13348
|
+
* and the current position in canvas coordinate `transform.target` is a reference to the
|
|
13349
|
+
* current object being transformed.
|
|
13350
|
+
*/
|
|
13351
|
+
function pathActionHandler(eventData, transform, x, y) {
|
|
13352
|
+
const {
|
|
13353
|
+
target
|
|
13354
|
+
} = transform;
|
|
13355
|
+
const {
|
|
13356
|
+
commandIndex,
|
|
13357
|
+
pointIndex
|
|
13358
|
+
} = this;
|
|
13359
|
+
const actionPerformed = movePathPoint(target, x, y, commandIndex, pointIndex);
|
|
13360
|
+
{
|
|
13361
|
+
fireEvent(this.actionName, {
|
|
13362
|
+
...commonEventInfo(eventData, transform, x, y),
|
|
13363
|
+
commandIndex,
|
|
13364
|
+
pointIndex
|
|
13365
|
+
});
|
|
13366
|
+
}
|
|
13367
|
+
return actionPerformed;
|
|
13368
|
+
}
|
|
13369
|
+
const indexFromPrevCommand = previousCommandType => previousCommandType === 'C' ? 5 : previousCommandType === 'Q' ? 3 : 1;
|
|
13370
|
+
class PathPointControl extends Control {
|
|
13371
|
+
constructor(options) {
|
|
13372
|
+
super(options);
|
|
13373
|
+
}
|
|
13374
|
+
render(ctx, left, top, styleOverride, fabricObject) {
|
|
13375
|
+
const overrides = {
|
|
13376
|
+
...styleOverride,
|
|
13377
|
+
cornerColor: this.controlFill,
|
|
13378
|
+
cornerStrokeColor: this.controlStroke,
|
|
13379
|
+
transparentCorners: !this.controlFill
|
|
13380
|
+
};
|
|
13381
|
+
super.render(ctx, left, top, overrides, fabricObject);
|
|
13382
|
+
}
|
|
13383
|
+
}
|
|
13384
|
+
class PathControlPointControl extends PathPointControl {
|
|
13385
|
+
constructor(options) {
|
|
13386
|
+
super(options);
|
|
13387
|
+
}
|
|
13388
|
+
render(ctx, left, top, styleOverride, fabricObject) {
|
|
13389
|
+
const {
|
|
13390
|
+
path
|
|
13391
|
+
} = fabricObject;
|
|
13392
|
+
const {
|
|
13393
|
+
commandIndex,
|
|
13394
|
+
pointIndex,
|
|
13395
|
+
connectToCommandIndex,
|
|
13396
|
+
connectToPointIndex
|
|
13397
|
+
} = this;
|
|
13398
|
+
ctx.save();
|
|
13399
|
+
ctx.strokeStyle = this.controlStroke;
|
|
13400
|
+
if (this.connectionDashArray) {
|
|
13401
|
+
ctx.setLineDash(this.connectionDashArray);
|
|
13402
|
+
}
|
|
13403
|
+
const [commandType] = path[commandIndex];
|
|
13404
|
+
const point = calcPathPointPosition(fabricObject, connectToCommandIndex, connectToPointIndex);
|
|
13405
|
+
if (commandType === 'Q') {
|
|
13406
|
+
// one control point connects to 2 points
|
|
13407
|
+
const point2 = calcPathPointPosition(fabricObject, commandIndex, pointIndex + 2);
|
|
13408
|
+
ctx.moveTo(point2.x, point2.y);
|
|
13409
|
+
ctx.lineTo(left, top);
|
|
13410
|
+
} else {
|
|
13411
|
+
ctx.moveTo(left, top);
|
|
13412
|
+
}
|
|
13413
|
+
ctx.lineTo(point.x, point.y);
|
|
13414
|
+
ctx.stroke();
|
|
13415
|
+
ctx.restore();
|
|
13416
|
+
super.render(ctx, left, top, styleOverride, fabricObject);
|
|
13417
|
+
}
|
|
13418
|
+
}
|
|
13419
|
+
const createControl = (commandIndexPos, pointIndexPos, isControlPoint, options, connectToCommandIndex, connectToPointIndex) => new (isControlPoint ? PathControlPointControl : PathPointControl)({
|
|
13420
|
+
commandIndex: commandIndexPos,
|
|
13421
|
+
pointIndex: pointIndexPos,
|
|
13422
|
+
actionName: ACTION_NAME,
|
|
13423
|
+
positionHandler: pathPositionHandler,
|
|
13424
|
+
actionHandler: pathActionHandler,
|
|
13425
|
+
connectToCommandIndex,
|
|
13426
|
+
connectToPointIndex,
|
|
13427
|
+
...options,
|
|
13428
|
+
...(isControlPoint ? options.controlPointStyle : options.pointStyle)
|
|
13429
|
+
});
|
|
13430
|
+
function createPathControls(path) {
|
|
13431
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
13432
|
+
const controls = {};
|
|
13433
|
+
let previousCommandType = 'M';
|
|
13434
|
+
path.path.forEach((command, commandIndex) => {
|
|
13435
|
+
const commandType = command[0];
|
|
13436
|
+
if (commandType !== 'Z') {
|
|
13437
|
+
controls[`c_${commandIndex}_${commandType}`] = createControl(commandIndex, command.length - 2, false, options);
|
|
13438
|
+
}
|
|
13439
|
+
switch (commandType) {
|
|
13440
|
+
case 'C':
|
|
13441
|
+
controls[`c_${commandIndex}_C_CP_1`] = createControl(commandIndex, 1, true, options, commandIndex - 1, indexFromPrevCommand(previousCommandType));
|
|
13442
|
+
controls[`c_${commandIndex}_C_CP_2`] = createControl(commandIndex, 3, true, options, commandIndex, 5);
|
|
13443
|
+
break;
|
|
13444
|
+
case 'Q':
|
|
13445
|
+
controls[`c_${commandIndex}_Q_CP_1`] = createControl(commandIndex, 1, true, options, commandIndex, 3);
|
|
13446
|
+
break;
|
|
13447
|
+
}
|
|
13448
|
+
previousCommandType = commandType;
|
|
13449
|
+
});
|
|
13450
|
+
return controls;
|
|
13451
|
+
}
|
|
13452
|
+
|
|
13453
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
13454
|
+
__proto__: null,
|
|
13455
|
+
changeHeight: changeHeight,
|
|
13456
|
+
changeObjectHeight: changeObjectHeight,
|
|
13457
|
+
changeObjectWidth: changeObjectWidth,
|
|
13458
|
+
changeWidth: changeWidth,
|
|
13459
|
+
createObjectDefaultControls: createObjectDefaultControls,
|
|
13460
|
+
createPathControls: createPathControls,
|
|
13461
|
+
createPolyActionHandler: createPolyActionHandler,
|
|
13462
|
+
createPolyControls: createPolyControls,
|
|
13463
|
+
createPolyPositionHandler: createPolyPositionHandler,
|
|
13464
|
+
createResizeControls: createResizeControls,
|
|
13465
|
+
createTextboxDefaultControls: createTextboxDefaultControls,
|
|
13466
|
+
dragHandler: dragHandler,
|
|
13467
|
+
factoryPolyActionHandler: factoryPolyActionHandler,
|
|
13468
|
+
getLocalPoint: getLocalPoint,
|
|
13469
|
+
polyActionHandler: polyActionHandler,
|
|
13470
|
+
renderCircleControl: renderCircleControl,
|
|
13471
|
+
renderSquareControl: renderSquareControl,
|
|
13472
|
+
rotationStyleHandler: rotationStyleHandler,
|
|
13473
|
+
rotationWithSnapping: rotationWithSnapping,
|
|
13474
|
+
scaleCursorStyleHandler: scaleCursorStyleHandler,
|
|
13475
|
+
scaleOrSkewActionName: scaleOrSkewActionName,
|
|
13476
|
+
scaleSkewCursorStyleHandler: scaleSkewCursorStyleHandler,
|
|
13477
|
+
scalingEqually: scalingEqually,
|
|
13478
|
+
scalingX: scalingX,
|
|
13479
|
+
scalingXOrSkewingY: scalingXOrSkewingY,
|
|
13480
|
+
scalingY: scalingY,
|
|
13481
|
+
scalingYOrSkewingX: scalingYOrSkewingX,
|
|
13482
|
+
skewCursorStyleHandler: skewCursorStyleHandler,
|
|
13483
|
+
skewHandlerX: skewHandlerX,
|
|
13484
|
+
skewHandlerY: skewHandlerY,
|
|
13485
|
+
wrapWithFireEvent: wrapWithFireEvent,
|
|
13486
|
+
wrapWithFixedAnchor: wrapWithFixedAnchor
|
|
13487
|
+
});
|
|
13488
|
+
|
|
13174
13489
|
/**
|
|
13175
13490
|
* Canvas class
|
|
13176
13491
|
* @class Canvas
|
|
@@ -13541,11 +13856,13 @@ class SelectableCanvas extends StaticCanvas {
|
|
|
13541
13856
|
* Given the control clicked, determine the origin of the transform.
|
|
13542
13857
|
* This is bad because controls can totally have custom names
|
|
13543
13858
|
* should disappear before release 4.0
|
|
13859
|
+
* Fabric 7.1, jan 2026 we are still using this.
|
|
13860
|
+
* Needs to go.
|
|
13544
13861
|
* @private
|
|
13545
13862
|
* @deprecated
|
|
13546
13863
|
*/
|
|
13547
13864
|
_getOriginFromCorner(target, controlName) {
|
|
13548
|
-
const origin = {
|
|
13865
|
+
const origin = controlName ? target.controls[controlName].getTransformAnchorPoint() : {
|
|
13549
13866
|
x: target.originX,
|
|
13550
13867
|
y: target.originY
|
|
13551
13868
|
};
|
|
@@ -13553,6 +13870,9 @@ class SelectableCanvas extends StaticCanvas {
|
|
|
13553
13870
|
return origin;
|
|
13554
13871
|
}
|
|
13555
13872
|
|
|
13873
|
+
// this part down here is deprecated.
|
|
13874
|
+
// It is left to do not change the standard behavior in the middle of a major version
|
|
13875
|
+
// but when possible `getTransformAnchorPoint` will be the only source of truth
|
|
13556
13876
|
// is a left control ?
|
|
13557
13877
|
if (['ml', 'tl', 'bl'].includes(controlName)) {
|
|
13558
13878
|
origin.x = RIGHT;
|
|
@@ -13592,37 +13912,52 @@ class SelectableCanvas extends StaticCanvas {
|
|
|
13592
13912
|
x: CENTER,
|
|
13593
13913
|
y: CENTER
|
|
13594
13914
|
} : this._getOriginFromCorner(target, corner),
|
|
13915
|
+
{
|
|
13916
|
+
scaleX,
|
|
13917
|
+
scaleY,
|
|
13918
|
+
skewX,
|
|
13919
|
+
skewY,
|
|
13920
|
+
left,
|
|
13921
|
+
top,
|
|
13922
|
+
angle,
|
|
13923
|
+
width,
|
|
13924
|
+
height,
|
|
13925
|
+
cropX,
|
|
13926
|
+
cropY
|
|
13927
|
+
} = target,
|
|
13595
13928
|
/**
|
|
13596
13929
|
* relative to target's containing coordinate plane
|
|
13597
13930
|
* both agree on every point
|
|
13598
13931
|
**/
|
|
13599
13932
|
transform = {
|
|
13600
|
-
target
|
|
13933
|
+
target,
|
|
13601
13934
|
action,
|
|
13602
13935
|
actionHandler,
|
|
13603
13936
|
actionPerformed: false,
|
|
13604
13937
|
corner,
|
|
13605
|
-
scaleX
|
|
13606
|
-
scaleY
|
|
13607
|
-
skewX
|
|
13608
|
-
skewY
|
|
13609
|
-
offsetX: pointer.x -
|
|
13610
|
-
offsetY: pointer.y -
|
|
13938
|
+
scaleX,
|
|
13939
|
+
scaleY,
|
|
13940
|
+
skewX,
|
|
13941
|
+
skewY,
|
|
13942
|
+
offsetX: pointer.x - left,
|
|
13943
|
+
offsetY: pointer.y - top,
|
|
13611
13944
|
originX: origin.x,
|
|
13612
13945
|
originY: origin.y,
|
|
13613
13946
|
ex: pointer.x,
|
|
13614
13947
|
ey: pointer.y,
|
|
13615
13948
|
lastX: pointer.x,
|
|
13616
13949
|
lastY: pointer.y,
|
|
13617
|
-
theta: degreesToRadians(
|
|
13618
|
-
width
|
|
13619
|
-
height
|
|
13950
|
+
theta: degreesToRadians(angle),
|
|
13951
|
+
width,
|
|
13952
|
+
height,
|
|
13620
13953
|
shiftKey: e.shiftKey,
|
|
13621
13954
|
altKey,
|
|
13622
13955
|
original: {
|
|
13623
13956
|
...saveObjectTransform(target),
|
|
13624
13957
|
originX: origin.x,
|
|
13625
|
-
originY: origin.y
|
|
13958
|
+
originY: origin.y,
|
|
13959
|
+
cropX,
|
|
13960
|
+
cropY
|
|
13626
13961
|
}
|
|
13627
13962
|
};
|
|
13628
13963
|
this._currentTransform = transform;
|
|
@@ -16035,7 +16370,8 @@ class Gradient {
|
|
|
16035
16370
|
}
|
|
16036
16371
|
transform[4] -= offsetX;
|
|
16037
16372
|
transform[5] -= offsetY;
|
|
16038
|
-
const commonAttributes = [`id="SVGID_${this.id}"`, `gradientUnits="${gradientUnits}"`, `gradientTransform="${preTransform ? preTransform + ' ' : ''}${matrixToSVG(transform)}"`, ''].join(' ');
|
|
16373
|
+
const commonAttributes = [`id="SVGID_${escapeXml(String(this.id))}"`, `gradientUnits="${gradientUnits}"`, `gradientTransform="${preTransform ? preTransform + ' ' : ''}${matrixToSVG(transform)}"`, ''].join(' ');
|
|
16374
|
+
const sanitizeCoord = value => parseFloat(String(value));
|
|
16039
16375
|
if (this.type === 'linear') {
|
|
16040
16376
|
const {
|
|
16041
16377
|
x1,
|
|
@@ -16043,7 +16379,11 @@ class Gradient {
|
|
|
16043
16379
|
x2,
|
|
16044
16380
|
y2
|
|
16045
16381
|
} = this.coords;
|
|
16046
|
-
|
|
16382
|
+
const sx1 = sanitizeCoord(x1);
|
|
16383
|
+
const sy1 = sanitizeCoord(y1);
|
|
16384
|
+
const sx2 = sanitizeCoord(x2);
|
|
16385
|
+
const sy2 = sanitizeCoord(y2);
|
|
16386
|
+
markup.push('<linearGradient ', commonAttributes, ' x1="', sx1, '" y1="', sy1, '" x2="', sx2, '" y2="', sy2, '">\n');
|
|
16047
16387
|
} else if (this.type === 'radial') {
|
|
16048
16388
|
const {
|
|
16049
16389
|
x1,
|
|
@@ -16053,9 +16393,15 @@ class Gradient {
|
|
|
16053
16393
|
r1,
|
|
16054
16394
|
r2
|
|
16055
16395
|
} = this.coords;
|
|
16056
|
-
const
|
|
16396
|
+
const sx1 = sanitizeCoord(x1);
|
|
16397
|
+
const sy1 = sanitizeCoord(y1);
|
|
16398
|
+
const sx2 = sanitizeCoord(x2);
|
|
16399
|
+
const sy2 = sanitizeCoord(y2);
|
|
16400
|
+
const sr1 = sanitizeCoord(r1);
|
|
16401
|
+
const sr2 = sanitizeCoord(r2);
|
|
16402
|
+
const needsSwap = sr1 > sr2;
|
|
16057
16403
|
// svg radial gradient has just 1 radius. the biggest.
|
|
16058
|
-
markup.push('<radialGradient ', commonAttributes, ' cx="', needsSwap ?
|
|
16404
|
+
markup.push('<radialGradient ', commonAttributes, ' cx="', needsSwap ? sx1 : sx2, '" cy="', needsSwap ? sy1 : sy2, '" r="', needsSwap ? sr1 : sr2, '" fx="', needsSwap ? sx2 : sx1, '" fy="', needsSwap ? sy2 : sy1, '">\n');
|
|
16059
16405
|
if (needsSwap) {
|
|
16060
16406
|
// svg goes from internal to external radius. if radius are inverted, swap color stops.
|
|
16061
16407
|
colorStops.reverse(); // mutates array
|
|
@@ -16063,16 +16409,17 @@ class Gradient {
|
|
|
16063
16409
|
colorStop.offset = 1 - colorStop.offset;
|
|
16064
16410
|
});
|
|
16065
16411
|
}
|
|
16066
|
-
const minRadius = Math.min(
|
|
16412
|
+
const minRadius = Math.min(sr1, sr2);
|
|
16067
16413
|
if (minRadius > 0) {
|
|
16068
16414
|
// i have to shift all colorStops and add new one in 0.
|
|
16069
|
-
const maxRadius = Math.max(
|
|
16415
|
+
const maxRadius = Math.max(sr1, sr2),
|
|
16070
16416
|
percentageShift = minRadius / maxRadius;
|
|
16071
16417
|
colorStops.forEach(colorStop => {
|
|
16072
16418
|
colorStop.offset += percentageShift * (1 - colorStop.offset);
|
|
16073
16419
|
});
|
|
16074
16420
|
}
|
|
16075
16421
|
}
|
|
16422
|
+
// todo make a malicious script tag injection test with color and also apply a fix with escapeXml
|
|
16076
16423
|
colorStops.forEach(_ref => {
|
|
16077
16424
|
let {
|
|
16078
16425
|
color,
|
|
@@ -16388,7 +16735,7 @@ class Pattern {
|
|
|
16388
16735
|
patternOffsetY = ifNaN(this.offsetY / height, 0),
|
|
16389
16736
|
patternWidth = repeat === 'repeat-y' || repeat === 'no-repeat' ? 1 + Math.abs(patternOffsetX || 0) : ifNaN(patternSource.width / width, 0),
|
|
16390
16737
|
patternHeight = repeat === 'repeat-x' || repeat === 'no-repeat' ? 1 + Math.abs(patternOffsetY || 0) : ifNaN(patternSource.height / height, 0);
|
|
16391
|
-
return [`<pattern id="SVGID_${id}" x="${patternOffsetX}" y="${patternOffsetY}" width="${patternWidth}" height="${patternHeight}">`, `<image x="0" y="0" width="${patternSource.width}" height="${patternSource.height}" xlink:href="${this.sourceToString()}"></image>`, `</pattern>`, ''].join('\n');
|
|
16738
|
+
return [`<pattern id="SVGID_${escapeXml(id)}" x="${patternOffsetX}" y="${patternOffsetY}" width="${patternWidth}" height="${patternHeight}">`, `<image x="0" y="0" width="${patternSource.width}" height="${patternSource.height}" xlink:href="${escapeXml(this.sourceToString())}"></image>`, `</pattern>`, ''].join('\n');
|
|
16392
16739
|
}
|
|
16393
16740
|
/* _TO_SVG_END_ */
|
|
16394
16741
|
|
|
@@ -16670,8 +17017,7 @@ class Path extends FabricObject {
|
|
|
16670
17017
|
* of the instance
|
|
16671
17018
|
*/
|
|
16672
17019
|
_toSVG() {
|
|
16673
|
-
|
|
16674
|
-
return ['<path ', 'COMMON_PARTS', `d="${path}" stroke-linecap="round" />\n`];
|
|
17020
|
+
return ['<path ', 'COMMON_PARTS', `d="${joinPath(this.path, config.NUM_FRACTION_DIGITS)}" stroke-linecap="round" />\n`];
|
|
16675
17021
|
}
|
|
16676
17022
|
|
|
16677
17023
|
/**
|
|
@@ -17222,15 +17568,17 @@ class Circle extends FabricObject {
|
|
|
17222
17568
|
* of the instance
|
|
17223
17569
|
*/
|
|
17224
17570
|
_toSVG() {
|
|
17225
|
-
const
|
|
17571
|
+
const {
|
|
17572
|
+
radius,
|
|
17573
|
+
startAngle,
|
|
17574
|
+
endAngle
|
|
17575
|
+
} = this;
|
|
17576
|
+
const angle = (endAngle - startAngle) % 360;
|
|
17226
17577
|
if (angle === 0) {
|
|
17227
|
-
return ['<circle ', 'COMMON_PARTS', 'cx="0" cy="0" ', 'r="', `${
|
|
17578
|
+
return ['<circle ', 'COMMON_PARTS', 'cx="0" cy="0" ', 'r="', `${escapeXml(radius)}`, '" />\n'];
|
|
17228
17579
|
} else {
|
|
17229
|
-
const
|
|
17230
|
-
|
|
17231
|
-
} = this;
|
|
17232
|
-
const start = degreesToRadians(this.startAngle),
|
|
17233
|
-
end = degreesToRadians(this.endAngle),
|
|
17580
|
+
const start = degreesToRadians(startAngle),
|
|
17581
|
+
end = degreesToRadians(endAngle),
|
|
17234
17582
|
startX = cos(start) * radius,
|
|
17235
17583
|
startY = sin(start) * radius,
|
|
17236
17584
|
endX = cos(end) * radius,
|
|
@@ -17802,17 +18150,13 @@ class Line extends FabricObject {
|
|
|
17802
18150
|
width,
|
|
17803
18151
|
height
|
|
17804
18152
|
} = this;
|
|
17805
|
-
const xMult = _x1 <= _x2 ? -
|
|
17806
|
-
yMult = _y1 <= _y2 ? -
|
|
17807
|
-
x1 = xMult * width / 2,
|
|
17808
|
-
y1 = yMult * height / 2,
|
|
17809
|
-
x2 = xMult * -width / 2,
|
|
17810
|
-
y2 = yMult * -height / 2;
|
|
18153
|
+
const xMult = _x1 <= _x2 ? -0.5 : 0.5,
|
|
18154
|
+
yMult = _y1 <= _y2 ? -0.5 : 0.5;
|
|
17811
18155
|
return {
|
|
17812
|
-
x1,
|
|
17813
|
-
x2,
|
|
17814
|
-
y1,
|
|
17815
|
-
y2
|
|
18156
|
+
x1: xMult * width,
|
|
18157
|
+
x2: xMult * -width,
|
|
18158
|
+
y1: yMult * height,
|
|
18159
|
+
y2: yMult * -height
|
|
17816
18160
|
};
|
|
17817
18161
|
}
|
|
17818
18162
|
|
|
@@ -18030,7 +18374,7 @@ class Ellipse extends FabricObject {
|
|
|
18030
18374
|
* of the instance
|
|
18031
18375
|
*/
|
|
18032
18376
|
_toSVG() {
|
|
18033
|
-
return ['<ellipse ', 'COMMON_PARTS', `cx="0" cy="0" rx="${this.rx}" ry="${this.ry}" />\n`];
|
|
18377
|
+
return ['<ellipse ', 'COMMON_PARTS', `cx="0" cy="0" rx="${escapeXml(this.rx)}" ry="${escapeXml(this.ry)}" />\n`];
|
|
18034
18378
|
}
|
|
18035
18379
|
|
|
18036
18380
|
/**
|
|
@@ -18348,14 +18692,17 @@ class Polyline extends FabricObject {
|
|
|
18348
18692
|
* of the instance
|
|
18349
18693
|
*/
|
|
18350
18694
|
_toSVG() {
|
|
18351
|
-
const
|
|
18352
|
-
diffX = this.pathOffset.x,
|
|
18695
|
+
const diffX = this.pathOffset.x,
|
|
18353
18696
|
diffY = this.pathOffset.y,
|
|
18354
18697
|
NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS;
|
|
18355
|
-
|
|
18356
|
-
|
|
18357
|
-
|
|
18358
|
-
|
|
18698
|
+
const points = this.points.map(_ref2 => {
|
|
18699
|
+
let {
|
|
18700
|
+
x,
|
|
18701
|
+
y
|
|
18702
|
+
} = _ref2;
|
|
18703
|
+
return `${toFixed(x - diffX, NUM_FRACTION_DIGITS)},${toFixed(y - diffY, NUM_FRACTION_DIGITS)}`;
|
|
18704
|
+
}).join(' ');
|
|
18705
|
+
return [`<${escapeXml(this.constructor.type).toLowerCase()} `, 'COMMON_PARTS', `points="${points}" />\n`];
|
|
18359
18706
|
}
|
|
18360
18707
|
|
|
18361
18708
|
/**
|
|
@@ -18478,7 +18825,6 @@ class StyledText extends FabricObject {
|
|
|
18478
18825
|
};
|
|
18479
18826
|
for (const p1 in obj) {
|
|
18480
18827
|
for (const p2 in obj[p1]) {
|
|
18481
|
-
// eslint-disable-next-line no-unused-vars
|
|
18482
18828
|
for (const p3 in obj[p1][p2]) {
|
|
18483
18829
|
return false;
|
|
18484
18830
|
}
|
|
@@ -18504,9 +18850,7 @@ class StyledText extends FabricObject {
|
|
|
18504
18850
|
const obj = typeof lineIndex === 'undefined' ? this.styles : {
|
|
18505
18851
|
0: this.styles[lineIndex]
|
|
18506
18852
|
};
|
|
18507
|
-
// eslint-disable-next-line
|
|
18508
18853
|
for (const p1 in obj) {
|
|
18509
|
-
// eslint-disable-next-line
|
|
18510
18854
|
for (const p2 in obj[p1]) {
|
|
18511
18855
|
if (typeof obj[p1][p2][property] !== 'undefined') {
|
|
18512
18856
|
return true;
|
|
@@ -18782,7 +19126,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
18782
19126
|
} = _ref;
|
|
18783
19127
|
const noShadow = true,
|
|
18784
19128
|
textDecoration = this.getSvgTextDecoration(this);
|
|
18785
|
-
return [textBgRects.join(''), '\t\t<text xml:space="preserve" ', `font-family="${this.fontFamily.replace(dblQuoteRegex, "'")}" `, `font-size="${this.fontSize}" `, this.fontStyle ? `font-style="${this.fontStyle}" ` : '', this.fontWeight ? `font-weight="${this.fontWeight}" ` : '', textDecoration ? `text-decoration="${textDecoration}" ` : '', this.direction === 'rtl' ? `direction="
|
|
19129
|
+
return [textBgRects.join(''), '\t\t<text xml:space="preserve" ', `font-family="${escapeXml(this.fontFamily.replace(dblQuoteRegex, "'"))}" `, `font-size="${escapeXml(this.fontSize)}" `, this.fontStyle ? `font-style="${escapeXml(this.fontStyle)}" ` : '', this.fontWeight ? `font-weight="${escapeXml(this.fontWeight)}" ` : '', textDecoration ? `text-decoration="${textDecoration}" ` : '', this.direction === 'rtl' ? `direction="rtl" ` : '', 'style="', this.getSvgStyles(noShadow), '"', this.addPaintOrder(), ' >', textSpans.join(''), '</text>\n'];
|
|
18786
19130
|
}
|
|
18787
19131
|
|
|
18788
19132
|
/**
|
|
@@ -18798,7 +19142,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
18798
19142
|
lineOffset;
|
|
18799
19143
|
|
|
18800
19144
|
// bounding-box background
|
|
18801
|
-
this.backgroundColor && textBgRects.push(
|
|
19145
|
+
this.backgroundColor && textBgRects.push(createSVGInlineRect(this.backgroundColor, -this.width / 2, -this.height / 2, this.width, this.height));
|
|
18802
19146
|
|
|
18803
19147
|
// text and text-background
|
|
18804
19148
|
for (let i = 0, len = this._textLines.length; i < len; i++) {
|
|
@@ -18906,7 +19250,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
18906
19250
|
} = this.__charBounds[i][j];
|
|
18907
19251
|
currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');
|
|
18908
19252
|
if (currentColor !== lastColor) {
|
|
18909
|
-
lastColor && textBgRects.push(
|
|
19253
|
+
lastColor && textBgRects.push(createSVGInlineRect(lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine));
|
|
18910
19254
|
boxStart = left;
|
|
18911
19255
|
boxWidth = width;
|
|
18912
19256
|
lastColor = currentColor;
|
|
@@ -18914,7 +19258,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
18914
19258
|
boxWidth += kernedWidth;
|
|
18915
19259
|
}
|
|
18916
19260
|
}
|
|
18917
|
-
currentColor && textBgRects.push(
|
|
19261
|
+
currentColor && textBgRects.push(createSVGInlineRect(lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine));
|
|
18918
19262
|
}
|
|
18919
19263
|
|
|
18920
19264
|
/**
|
|
@@ -18941,7 +19285,6 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
18941
19285
|
fontSize,
|
|
18942
19286
|
fontStyle,
|
|
18943
19287
|
fontWeight,
|
|
18944
|
-
deltaY,
|
|
18945
19288
|
textDecorationThickness,
|
|
18946
19289
|
linethrough,
|
|
18947
19290
|
overline,
|
|
@@ -18953,7 +19296,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
18953
19296
|
linethrough: linethrough !== null && linethrough !== void 0 ? linethrough : this.linethrough
|
|
18954
19297
|
});
|
|
18955
19298
|
const thickness = textDecorationThickness || this.textDecorationThickness;
|
|
18956
|
-
return [stroke ? colorPropToSVG(STROKE, stroke) : '', strokeWidth ? `stroke-width: ${strokeWidth}; ` : '', fontFamily ? `font-family: ${!fontFamily.includes("'") && !fontFamily.includes('"') ? `'${fontFamily}'` : fontFamily}; ` : '', fontSize ? `font-size: ${fontSize}px; ` : '', fontStyle ? `font-style: ${fontStyle}; ` : '', fontWeight ? `font-weight: ${fontWeight}; ` : '', textDecoration ? `text-decoration: ${textDecoration}; text-decoration-thickness: ${toFixed(thickness * this.getObjectScaling().y / 10, config.NUM_FRACTION_DIGITS)}%; ` : '', fill ? colorPropToSVG(FILL, fill) : '',
|
|
19299
|
+
return [stroke ? colorPropToSVG(STROKE, stroke) : '', strokeWidth ? `stroke-width: ${escapeXml(strokeWidth)}; ` : '', fontFamily ? `font-family: ${!fontFamily.includes("'") && !fontFamily.includes('"') ? `'${escapeXml(fontFamily)}'` : escapeXml(fontFamily)}; ` : '', fontSize ? `font-size: ${escapeXml(fontSize)}px; ` : '', fontStyle ? `font-style: ${escapeXml(fontStyle)}; ` : '', fontWeight ? `font-weight: ${escapeXml(fontWeight)}; ` : '', textDecoration ? `text-decoration: ${textDecoration}; text-decoration-thickness: ${toFixed(thickness * this.getObjectScaling().y / 10, config.NUM_FRACTION_DIGITS)}%; ` : '', fill ? colorPropToSVG(FILL, fill) : '', useWhiteSpace ? 'white-space: pre; ' : ''].join('');
|
|
18957
19300
|
}
|
|
18958
19301
|
|
|
18959
19302
|
/**
|
|
@@ -24517,13 +24860,13 @@ class FabricImage extends FabricObject {
|
|
|
24517
24860
|
}
|
|
24518
24861
|
if (this.hasCrop()) {
|
|
24519
24862
|
const clipPathId = uid();
|
|
24520
|
-
svgString.push('<clipPath id="imageCrop_' + clipPathId + '">\n', '\t<rect x="' + x + '" y="' + y + '" width="' + this.width + '" height="' + this.height + '" />\n', '</clipPath>\n');
|
|
24863
|
+
svgString.push('<clipPath id="imageCrop_' + clipPathId + '">\n', '\t<rect x="' + x + '" y="' + y + '" width="' + escapeXml(this.width) + '" height="' + escapeXml(this.height) + '" />\n', '</clipPath>\n');
|
|
24521
24864
|
clipPath = ' clip-path="url(#imageCrop_' + clipPathId + ')" ';
|
|
24522
24865
|
}
|
|
24523
24866
|
if (!this.imageSmoothing) {
|
|
24524
24867
|
imageRendering = ' image-rendering="optimizeSpeed"';
|
|
24525
24868
|
}
|
|
24526
|
-
imageMarkup.push('\t<image ', 'COMMON_PARTS', `xlink:href="${this.
|
|
24869
|
+
imageMarkup.push('\t<image ', 'COMMON_PARTS', `xlink:href="${escapeXml(this.getSrc(true))}" x="${x - this.cropX}" y="${y - this.cropY
|
|
24527
24870
|
// we're essentially moving origin of transformation from top/left corner to the center of the shape
|
|
24528
24871
|
// by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left
|
|
24529
24872
|
// so that object's center aligns with container's left/top
|
|
@@ -24531,7 +24874,7 @@ class FabricImage extends FabricObject {
|
|
|
24531
24874
|
if (this.stroke || this.strokeDashArray) {
|
|
24532
24875
|
const origFill = this.fill;
|
|
24533
24876
|
this.fill = null;
|
|
24534
|
-
strokeSvg = [`\t<rect x="${x}" y="${y}" width="${this.width}" height="${this.height}" style="${this.getSvgStyles()}" />\n`];
|
|
24877
|
+
strokeSvg = [`\t<rect x="${x}" y="${y}" width="${escapeXml(this.width)}" height="${escapeXml(this.height)}" style="${this.getSvgStyles()}" />\n`];
|
|
24535
24878
|
this.fill = origFill;
|
|
24536
24879
|
}
|
|
24537
24880
|
if (this.paintFirst !== FILL) {
|
|
@@ -25514,258 +25857,6 @@ function loadSVGFromURL(url, reviver) {
|
|
|
25514
25857
|
});
|
|
25515
25858
|
}
|
|
25516
25859
|
|
|
25517
|
-
const ACTION_NAME$1 = MODIFY_POLY;
|
|
25518
|
-
/**
|
|
25519
|
-
* This function locates the controls.
|
|
25520
|
-
* It'll be used both for drawing and for interaction.
|
|
25521
|
-
*/
|
|
25522
|
-
const createPolyPositionHandler = pointIndex => {
|
|
25523
|
-
return function (dim, finalMatrix, polyObject) {
|
|
25524
|
-
const {
|
|
25525
|
-
points,
|
|
25526
|
-
pathOffset
|
|
25527
|
-
} = polyObject;
|
|
25528
|
-
return new Point(points[pointIndex]).subtract(pathOffset).transform(multiplyTransformMatrices(polyObject.getViewportTransform(), polyObject.calcTransformMatrix()));
|
|
25529
|
-
};
|
|
25530
|
-
};
|
|
25531
|
-
|
|
25532
|
-
/**
|
|
25533
|
-
* This function defines what the control does.
|
|
25534
|
-
* It'll be called on every mouse move after a control has been clicked and is being dragged.
|
|
25535
|
-
* The function receives as argument the mouse event, the current transform object
|
|
25536
|
-
* and the current position in canvas coordinate `transform.target` is a reference to the
|
|
25537
|
-
* current object being transformed.
|
|
25538
|
-
*/
|
|
25539
|
-
const polyActionHandler = (eventData, transform, x, y) => {
|
|
25540
|
-
const {
|
|
25541
|
-
target,
|
|
25542
|
-
pointIndex
|
|
25543
|
-
} = transform;
|
|
25544
|
-
const poly = target;
|
|
25545
|
-
const mouseLocalPosition = sendPointToPlane(new Point(x, y), undefined, poly.calcOwnMatrix());
|
|
25546
|
-
poly.points[pointIndex] = mouseLocalPosition.add(poly.pathOffset);
|
|
25547
|
-
poly.setDimensions();
|
|
25548
|
-
poly.set('dirty', true);
|
|
25549
|
-
return true;
|
|
25550
|
-
};
|
|
25551
|
-
|
|
25552
|
-
/**
|
|
25553
|
-
* Keep the polygon in the same position when we change its `width`/`height`/`top`/`left`.
|
|
25554
|
-
*/
|
|
25555
|
-
const factoryPolyActionHandler = (pointIndex, fn) => {
|
|
25556
|
-
return function (eventData, transform, x, y) {
|
|
25557
|
-
const poly = transform.target,
|
|
25558
|
-
anchorPoint = new Point(poly.points[(pointIndex > 0 ? pointIndex : poly.points.length) - 1]),
|
|
25559
|
-
anchorPointInParentPlane = anchorPoint.subtract(poly.pathOffset).transform(poly.calcOwnMatrix()),
|
|
25560
|
-
actionPerformed = fn(eventData, {
|
|
25561
|
-
...transform,
|
|
25562
|
-
pointIndex
|
|
25563
|
-
}, x, y);
|
|
25564
|
-
const newAnchorPointInParentPlane = anchorPoint.subtract(poly.pathOffset).transform(poly.calcOwnMatrix());
|
|
25565
|
-
const diff = newAnchorPointInParentPlane.subtract(anchorPointInParentPlane);
|
|
25566
|
-
poly.left -= diff.x;
|
|
25567
|
-
poly.top -= diff.y;
|
|
25568
|
-
return actionPerformed;
|
|
25569
|
-
};
|
|
25570
|
-
};
|
|
25571
|
-
const createPolyActionHandler = pointIndex => wrapWithFireEvent(ACTION_NAME$1, factoryPolyActionHandler(pointIndex, polyActionHandler));
|
|
25572
|
-
function createPolyControls(arg0) {
|
|
25573
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
25574
|
-
const controls = {};
|
|
25575
|
-
for (let idx = 0; idx < (typeof arg0 === 'number' ? arg0 : arg0.points.length); idx++) {
|
|
25576
|
-
controls[`p${idx}`] = new Control({
|
|
25577
|
-
actionName: ACTION_NAME$1,
|
|
25578
|
-
positionHandler: createPolyPositionHandler(idx),
|
|
25579
|
-
actionHandler: createPolyActionHandler(idx),
|
|
25580
|
-
...options
|
|
25581
|
-
});
|
|
25582
|
-
}
|
|
25583
|
-
return controls;
|
|
25584
|
-
}
|
|
25585
|
-
|
|
25586
|
-
const ACTION_NAME = 'modifyPath';
|
|
25587
|
-
const calcPathPointPosition = (pathObject, commandIndex, pointIndex) => {
|
|
25588
|
-
const {
|
|
25589
|
-
path,
|
|
25590
|
-
pathOffset
|
|
25591
|
-
} = pathObject;
|
|
25592
|
-
const command = path[commandIndex];
|
|
25593
|
-
return new Point(command[pointIndex] - pathOffset.x, command[pointIndex + 1] - pathOffset.y).transform(multiplyTransformMatrices(pathObject.getViewportTransform(), pathObject.calcTransformMatrix()));
|
|
25594
|
-
};
|
|
25595
|
-
const movePathPoint = (pathObject, x, y, commandIndex, pointIndex) => {
|
|
25596
|
-
const {
|
|
25597
|
-
path,
|
|
25598
|
-
pathOffset
|
|
25599
|
-
} = pathObject;
|
|
25600
|
-
const anchorCommand = path[(commandIndex > 0 ? commandIndex : path.length) - 1];
|
|
25601
|
-
const anchorPoint = new Point(anchorCommand[pointIndex], anchorCommand[pointIndex + 1]);
|
|
25602
|
-
const anchorPointInParentPlane = anchorPoint.subtract(pathOffset).transform(pathObject.calcOwnMatrix());
|
|
25603
|
-
const mouseLocalPosition = sendPointToPlane(new Point(x, y), undefined, pathObject.calcOwnMatrix());
|
|
25604
|
-
path[commandIndex][pointIndex] = mouseLocalPosition.x + pathOffset.x;
|
|
25605
|
-
path[commandIndex][pointIndex + 1] = mouseLocalPosition.y + pathOffset.y;
|
|
25606
|
-
pathObject.setDimensions();
|
|
25607
|
-
const newAnchorPointInParentPlane = anchorPoint.subtract(pathObject.pathOffset).transform(pathObject.calcOwnMatrix());
|
|
25608
|
-
const diff = newAnchorPointInParentPlane.subtract(anchorPointInParentPlane);
|
|
25609
|
-
pathObject.left -= diff.x;
|
|
25610
|
-
pathObject.top -= diff.y;
|
|
25611
|
-
pathObject.set('dirty', true);
|
|
25612
|
-
return true;
|
|
25613
|
-
};
|
|
25614
|
-
|
|
25615
|
-
/**
|
|
25616
|
-
* This function locates the controls.
|
|
25617
|
-
* It'll be used both for drawing and for interaction.
|
|
25618
|
-
*/
|
|
25619
|
-
function pathPositionHandler(dim, finalMatrix, pathObject) {
|
|
25620
|
-
const {
|
|
25621
|
-
commandIndex,
|
|
25622
|
-
pointIndex
|
|
25623
|
-
} = this;
|
|
25624
|
-
return calcPathPointPosition(pathObject, commandIndex, pointIndex);
|
|
25625
|
-
}
|
|
25626
|
-
|
|
25627
|
-
/**
|
|
25628
|
-
* This function defines what the control does.
|
|
25629
|
-
* It'll be called on every mouse move after a control has been clicked and is being dragged.
|
|
25630
|
-
* The function receives as argument the mouse event, the current transform object
|
|
25631
|
-
* and the current position in canvas coordinate `transform.target` is a reference to the
|
|
25632
|
-
* current object being transformed.
|
|
25633
|
-
*/
|
|
25634
|
-
function pathActionHandler(eventData, transform, x, y) {
|
|
25635
|
-
const {
|
|
25636
|
-
target
|
|
25637
|
-
} = transform;
|
|
25638
|
-
const {
|
|
25639
|
-
commandIndex,
|
|
25640
|
-
pointIndex
|
|
25641
|
-
} = this;
|
|
25642
|
-
const actionPerformed = movePathPoint(target, x, y, commandIndex, pointIndex);
|
|
25643
|
-
{
|
|
25644
|
-
fireEvent(this.actionName, {
|
|
25645
|
-
...commonEventInfo(eventData, transform, x, y),
|
|
25646
|
-
commandIndex,
|
|
25647
|
-
pointIndex
|
|
25648
|
-
});
|
|
25649
|
-
}
|
|
25650
|
-
return actionPerformed;
|
|
25651
|
-
}
|
|
25652
|
-
const indexFromPrevCommand = previousCommandType => previousCommandType === 'C' ? 5 : previousCommandType === 'Q' ? 3 : 1;
|
|
25653
|
-
class PathPointControl extends Control {
|
|
25654
|
-
constructor(options) {
|
|
25655
|
-
super(options);
|
|
25656
|
-
}
|
|
25657
|
-
render(ctx, left, top, styleOverride, fabricObject) {
|
|
25658
|
-
const overrides = {
|
|
25659
|
-
...styleOverride,
|
|
25660
|
-
cornerColor: this.controlFill,
|
|
25661
|
-
cornerStrokeColor: this.controlStroke,
|
|
25662
|
-
transparentCorners: !this.controlFill
|
|
25663
|
-
};
|
|
25664
|
-
super.render(ctx, left, top, overrides, fabricObject);
|
|
25665
|
-
}
|
|
25666
|
-
}
|
|
25667
|
-
class PathControlPointControl extends PathPointControl {
|
|
25668
|
-
constructor(options) {
|
|
25669
|
-
super(options);
|
|
25670
|
-
}
|
|
25671
|
-
render(ctx, left, top, styleOverride, fabricObject) {
|
|
25672
|
-
const {
|
|
25673
|
-
path
|
|
25674
|
-
} = fabricObject;
|
|
25675
|
-
const {
|
|
25676
|
-
commandIndex,
|
|
25677
|
-
pointIndex,
|
|
25678
|
-
connectToCommandIndex,
|
|
25679
|
-
connectToPointIndex
|
|
25680
|
-
} = this;
|
|
25681
|
-
ctx.save();
|
|
25682
|
-
ctx.strokeStyle = this.controlStroke;
|
|
25683
|
-
if (this.connectionDashArray) {
|
|
25684
|
-
ctx.setLineDash(this.connectionDashArray);
|
|
25685
|
-
}
|
|
25686
|
-
const [commandType] = path[commandIndex];
|
|
25687
|
-
const point = calcPathPointPosition(fabricObject, connectToCommandIndex, connectToPointIndex);
|
|
25688
|
-
if (commandType === 'Q') {
|
|
25689
|
-
// one control point connects to 2 points
|
|
25690
|
-
const point2 = calcPathPointPosition(fabricObject, commandIndex, pointIndex + 2);
|
|
25691
|
-
ctx.moveTo(point2.x, point2.y);
|
|
25692
|
-
ctx.lineTo(left, top);
|
|
25693
|
-
} else {
|
|
25694
|
-
ctx.moveTo(left, top);
|
|
25695
|
-
}
|
|
25696
|
-
ctx.lineTo(point.x, point.y);
|
|
25697
|
-
ctx.stroke();
|
|
25698
|
-
ctx.restore();
|
|
25699
|
-
super.render(ctx, left, top, styleOverride, fabricObject);
|
|
25700
|
-
}
|
|
25701
|
-
}
|
|
25702
|
-
const createControl = (commandIndexPos, pointIndexPos, isControlPoint, options, connectToCommandIndex, connectToPointIndex) => new (isControlPoint ? PathControlPointControl : PathPointControl)({
|
|
25703
|
-
commandIndex: commandIndexPos,
|
|
25704
|
-
pointIndex: pointIndexPos,
|
|
25705
|
-
actionName: ACTION_NAME,
|
|
25706
|
-
positionHandler: pathPositionHandler,
|
|
25707
|
-
actionHandler: pathActionHandler,
|
|
25708
|
-
connectToCommandIndex,
|
|
25709
|
-
connectToPointIndex,
|
|
25710
|
-
...options,
|
|
25711
|
-
...(isControlPoint ? options.controlPointStyle : options.pointStyle)
|
|
25712
|
-
});
|
|
25713
|
-
function createPathControls(path) {
|
|
25714
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
25715
|
-
const controls = {};
|
|
25716
|
-
let previousCommandType = 'M';
|
|
25717
|
-
path.path.forEach((command, commandIndex) => {
|
|
25718
|
-
const commandType = command[0];
|
|
25719
|
-
if (commandType !== 'Z') {
|
|
25720
|
-
controls[`c_${commandIndex}_${commandType}`] = createControl(commandIndex, command.length - 2, false, options);
|
|
25721
|
-
}
|
|
25722
|
-
switch (commandType) {
|
|
25723
|
-
case 'C':
|
|
25724
|
-
controls[`c_${commandIndex}_C_CP_1`] = createControl(commandIndex, 1, true, options, commandIndex - 1, indexFromPrevCommand(previousCommandType));
|
|
25725
|
-
controls[`c_${commandIndex}_C_CP_2`] = createControl(commandIndex, 3, true, options, commandIndex, 5);
|
|
25726
|
-
break;
|
|
25727
|
-
case 'Q':
|
|
25728
|
-
controls[`c_${commandIndex}_Q_CP_1`] = createControl(commandIndex, 1, true, options, commandIndex, 3);
|
|
25729
|
-
break;
|
|
25730
|
-
}
|
|
25731
|
-
previousCommandType = commandType;
|
|
25732
|
-
});
|
|
25733
|
-
return controls;
|
|
25734
|
-
}
|
|
25735
|
-
|
|
25736
|
-
var index = /*#__PURE__*/Object.freeze({
|
|
25737
|
-
__proto__: null,
|
|
25738
|
-
changeWidth: changeWidth,
|
|
25739
|
-
createObjectDefaultControls: createObjectDefaultControls,
|
|
25740
|
-
createPathControls: createPathControls,
|
|
25741
|
-
createPolyActionHandler: createPolyActionHandler,
|
|
25742
|
-
createPolyControls: createPolyControls,
|
|
25743
|
-
createPolyPositionHandler: createPolyPositionHandler,
|
|
25744
|
-
createResizeControls: createResizeControls,
|
|
25745
|
-
createTextboxDefaultControls: createTextboxDefaultControls,
|
|
25746
|
-
dragHandler: dragHandler,
|
|
25747
|
-
factoryPolyActionHandler: factoryPolyActionHandler,
|
|
25748
|
-
getLocalPoint: getLocalPoint,
|
|
25749
|
-
polyActionHandler: polyActionHandler,
|
|
25750
|
-
renderCircleControl: renderCircleControl,
|
|
25751
|
-
renderSquareControl: renderSquareControl,
|
|
25752
|
-
rotationStyleHandler: rotationStyleHandler,
|
|
25753
|
-
rotationWithSnapping: rotationWithSnapping,
|
|
25754
|
-
scaleCursorStyleHandler: scaleCursorStyleHandler,
|
|
25755
|
-
scaleOrSkewActionName: scaleOrSkewActionName,
|
|
25756
|
-
scaleSkewCursorStyleHandler: scaleSkewCursorStyleHandler,
|
|
25757
|
-
scalingEqually: scalingEqually,
|
|
25758
|
-
scalingX: scalingX,
|
|
25759
|
-
scalingXOrSkewingY: scalingXOrSkewingY,
|
|
25760
|
-
scalingY: scalingY,
|
|
25761
|
-
scalingYOrSkewingX: scalingYOrSkewingX,
|
|
25762
|
-
skewCursorStyleHandler: skewCursorStyleHandler,
|
|
25763
|
-
skewHandlerX: skewHandlerX,
|
|
25764
|
-
skewHandlerY: skewHandlerY,
|
|
25765
|
-
wrapWithFireEvent: wrapWithFireEvent,
|
|
25766
|
-
wrapWithFixedAnchor: wrapWithFixedAnchor
|
|
25767
|
-
});
|
|
25768
|
-
|
|
25769
25860
|
const isWebGLPipelineState = options => {
|
|
25770
25861
|
return options.webgl !== undefined;
|
|
25771
25862
|
};
|