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.node.cjs
CHANGED
|
@@ -414,7 +414,7 @@ class Cache {
|
|
|
414
414
|
}
|
|
415
415
|
const cache = new Cache();
|
|
416
416
|
|
|
417
|
-
var version = "7.
|
|
417
|
+
var version = "7.2.0";
|
|
418
418
|
|
|
419
419
|
// use this syntax so babel plugin see this import here
|
|
420
420
|
const VERSION = version;
|
|
@@ -2249,6 +2249,111 @@ const staticCanvasDefaults = {
|
|
|
2249
2249
|
patternQuality: 'best'
|
|
2250
2250
|
};
|
|
2251
2251
|
|
|
2252
|
+
/**
|
|
2253
|
+
* Capitalizes a string
|
|
2254
|
+
* @param {String} string String to capitalize
|
|
2255
|
+
* @param {Boolean} [firstLetterOnly] If true only first letter is capitalized
|
|
2256
|
+
* and other letters stay untouched, if false first letter is capitalized
|
|
2257
|
+
* and other letters are converted to lowercase.
|
|
2258
|
+
* @return {String} Capitalized version of a string
|
|
2259
|
+
*/
|
|
2260
|
+
const capitalize = function (string) {
|
|
2261
|
+
let firstLetterOnly = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
2262
|
+
return `${string.charAt(0).toUpperCase()}${firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase()}`;
|
|
2263
|
+
};
|
|
2264
|
+
|
|
2265
|
+
/**
|
|
2266
|
+
* Escapes XML in a string
|
|
2267
|
+
* @param {String} string String to escape
|
|
2268
|
+
* @return {String} Escaped version of a string
|
|
2269
|
+
*/
|
|
2270
|
+
const escapeXml = stringOrNumber => stringOrNumber.toString().replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>');
|
|
2271
|
+
let segmenter;
|
|
2272
|
+
const getSegmenter = () => {
|
|
2273
|
+
if (!segmenter) {
|
|
2274
|
+
segmenter = 'Intl' in getFabricWindow() && 'Segmenter' in Intl && new Intl.Segmenter(undefined, {
|
|
2275
|
+
granularity: 'grapheme'
|
|
2276
|
+
});
|
|
2277
|
+
}
|
|
2278
|
+
return segmenter;
|
|
2279
|
+
};
|
|
2280
|
+
|
|
2281
|
+
/**
|
|
2282
|
+
* Divide a string in the user perceived single units
|
|
2283
|
+
* @param {String} textstring String to escape
|
|
2284
|
+
* @return {Array} array containing the graphemes
|
|
2285
|
+
*/
|
|
2286
|
+
const graphemeSplit = textstring => {
|
|
2287
|
+
segmenter || getSegmenter();
|
|
2288
|
+
if (segmenter) {
|
|
2289
|
+
const segments = segmenter.segment(textstring);
|
|
2290
|
+
return Array.from(segments).map(_ref => {
|
|
2291
|
+
let {
|
|
2292
|
+
segment
|
|
2293
|
+
} = _ref;
|
|
2294
|
+
return segment;
|
|
2295
|
+
});
|
|
2296
|
+
}
|
|
2297
|
+
|
|
2298
|
+
//Fallback
|
|
2299
|
+
return graphemeSplitImpl(textstring);
|
|
2300
|
+
};
|
|
2301
|
+
const graphemeSplitImpl = textstring => {
|
|
2302
|
+
const graphemes = [];
|
|
2303
|
+
for (let i = 0, chr; i < textstring.length; i++) {
|
|
2304
|
+
if ((chr = getWholeChar(textstring, i)) === false) {
|
|
2305
|
+
continue;
|
|
2306
|
+
}
|
|
2307
|
+
graphemes.push(chr);
|
|
2308
|
+
}
|
|
2309
|
+
return graphemes;
|
|
2310
|
+
};
|
|
2311
|
+
|
|
2312
|
+
// taken from mdn in the charAt doc page.
|
|
2313
|
+
const getWholeChar = (str, i) => {
|
|
2314
|
+
const code = str.charCodeAt(i);
|
|
2315
|
+
if (isNaN(code)) {
|
|
2316
|
+
return ''; // Position not found
|
|
2317
|
+
}
|
|
2318
|
+
if (code < 0xd800 || code > 0xdfff) {
|
|
2319
|
+
return str.charAt(i);
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
// High surrogate (could change last hex to 0xDB7F to treat high private
|
|
2323
|
+
// surrogates as single characters)
|
|
2324
|
+
if (0xd800 <= code && code <= 0xdbff) {
|
|
2325
|
+
if (str.length <= i + 1) {
|
|
2326
|
+
throw 'High surrogate without following low surrogate';
|
|
2327
|
+
}
|
|
2328
|
+
const next = str.charCodeAt(i + 1);
|
|
2329
|
+
if (0xdc00 > next || next > 0xdfff) {
|
|
2330
|
+
throw 'High surrogate without following low surrogate';
|
|
2331
|
+
}
|
|
2332
|
+
return str.charAt(i) + str.charAt(i + 1);
|
|
2333
|
+
}
|
|
2334
|
+
// Low surrogate (0xDC00 <= code && code <= 0xDFFF)
|
|
2335
|
+
if (i === 0) {
|
|
2336
|
+
throw 'Low surrogate without preceding high surrogate';
|
|
2337
|
+
}
|
|
2338
|
+
const prev = str.charCodeAt(i - 1);
|
|
2339
|
+
|
|
2340
|
+
// (could change last hex to 0xDB7F to treat high private
|
|
2341
|
+
// surrogates as single characters)
|
|
2342
|
+
if (0xd800 > prev || prev > 0xdbff) {
|
|
2343
|
+
throw 'Low surrogate without preceding high surrogate';
|
|
2344
|
+
}
|
|
2345
|
+
// We can pass over low surrogates now as the second component
|
|
2346
|
+
// in a pair which we have already processed
|
|
2347
|
+
return false;
|
|
2348
|
+
};
|
|
2349
|
+
|
|
2350
|
+
var lang_string = /*#__PURE__*/Object.freeze({
|
|
2351
|
+
__proto__: null,
|
|
2352
|
+
capitalize: capitalize,
|
|
2353
|
+
escapeXml: escapeXml,
|
|
2354
|
+
graphemeSplit: graphemeSplit
|
|
2355
|
+
});
|
|
2356
|
+
|
|
2252
2357
|
/**
|
|
2253
2358
|
* Having both options in TCanvasSizeOptions set to true transform the call in a calcOffset
|
|
2254
2359
|
* Better try to restrict with types to avoid confusion.
|
|
@@ -3018,7 +3123,8 @@ let StaticCanvas$1 = class StaticCanvas extends createCollectionMixin(CommonMeth
|
|
|
3018
3123
|
this._setSVGPreamble(markup, options);
|
|
3019
3124
|
this._setSVGHeader(markup, options);
|
|
3020
3125
|
if (this.clipPath) {
|
|
3021
|
-
|
|
3126
|
+
var _this$clipPath$clipPa;
|
|
3127
|
+
markup.push(`<g clip-path="url(#${escapeXml((_this$clipPath$clipPa = this.clipPath.clipPathId) !== null && _this$clipPath$clipPa !== void 0 ? _this$clipPath$clipPa : '')})" >\n`);
|
|
3022
3128
|
}
|
|
3023
3129
|
this._setSVGBgOverlayColor(markup, 'background');
|
|
3024
3130
|
this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);
|
|
@@ -3697,20 +3803,6 @@ const sendObjectToPlane = (object, from, to) => {
|
|
|
3697
3803
|
return t;
|
|
3698
3804
|
};
|
|
3699
3805
|
|
|
3700
|
-
const fireEvent = (eventName, options) => {
|
|
3701
|
-
var _target$canvas;
|
|
3702
|
-
const {
|
|
3703
|
-
transform: {
|
|
3704
|
-
target
|
|
3705
|
-
}
|
|
3706
|
-
} = options;
|
|
3707
|
-
(_target$canvas = target.canvas) === null || _target$canvas === void 0 || _target$canvas.fire(`object:${eventName}`, {
|
|
3708
|
-
...options,
|
|
3709
|
-
target
|
|
3710
|
-
});
|
|
3711
|
-
target.fire(eventName, options);
|
|
3712
|
-
};
|
|
3713
|
-
|
|
3714
3806
|
const originOffset = {
|
|
3715
3807
|
left: -0.5,
|
|
3716
3808
|
top: -0.5,
|
|
@@ -3913,33 +4005,6 @@ function getLocalPoint(_ref, originX, originY, x, y) {
|
|
|
3913
4005
|
return localPoint;
|
|
3914
4006
|
}
|
|
3915
4007
|
|
|
3916
|
-
/**
|
|
3917
|
-
* Action handler
|
|
3918
|
-
* @private
|
|
3919
|
-
* @param {Event} eventData javascript event that is doing the transform
|
|
3920
|
-
* @param {Object} transform javascript object containing a series of information around the current transform
|
|
3921
|
-
* @param {number} x current mouse x position, canvas normalized
|
|
3922
|
-
* @param {number} y current mouse y position, canvas normalized
|
|
3923
|
-
* @return {Boolean} true if the translation occurred
|
|
3924
|
-
*/
|
|
3925
|
-
const dragHandler = (eventData, transform, x, y) => {
|
|
3926
|
-
const {
|
|
3927
|
-
target,
|
|
3928
|
-
offsetX,
|
|
3929
|
-
offsetY
|
|
3930
|
-
} = transform,
|
|
3931
|
-
newLeft = x - offsetX,
|
|
3932
|
-
newTop = y - offsetY,
|
|
3933
|
-
moveX = !isLocked(target, 'lockMovementX') && target.left !== newLeft,
|
|
3934
|
-
moveY = !isLocked(target, 'lockMovementY') && target.top !== newTop;
|
|
3935
|
-
moveX && target.set(LEFT, newLeft);
|
|
3936
|
-
moveY && target.set(TOP, newTop);
|
|
3937
|
-
if (moveX || moveY) {
|
|
3938
|
-
fireEvent(MOVING, commonEventInfo(eventData, transform, x, y));
|
|
3939
|
-
}
|
|
3940
|
-
return moveX || moveY;
|
|
3941
|
-
};
|
|
3942
|
-
|
|
3943
4008
|
const normalizeWs = value => value.replace(/\s+/g, ' ');
|
|
3944
4009
|
|
|
3945
4010
|
/**
|
|
@@ -4686,7 +4751,7 @@ const colorPropToSVG = function (prop, value) {
|
|
|
4686
4751
|
if (!value) {
|
|
4687
4752
|
colorValue = 'none';
|
|
4688
4753
|
} else if (value.toLive) {
|
|
4689
|
-
colorValue = `url(#SVGID_${value.id})`;
|
|
4754
|
+
colorValue = `url(#SVGID_${escapeXml(value.id)})`;
|
|
4690
4755
|
} else {
|
|
4691
4756
|
const color = new Color(value),
|
|
4692
4757
|
opacity = color.getAlpha();
|
|
@@ -4739,7 +4804,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4739
4804
|
filter = skipShadow ? '' : this.getSvgFilter(),
|
|
4740
4805
|
fill = colorPropToSVG(FILL, this.fill),
|
|
4741
4806
|
stroke = colorPropToSVG(STROKE, this.stroke);
|
|
4742
|
-
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('');
|
|
4807
|
+
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('');
|
|
4743
4808
|
}
|
|
4744
4809
|
|
|
4745
4810
|
/**
|
|
@@ -4747,7 +4812,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4747
4812
|
* @return {String}
|
|
4748
4813
|
*/
|
|
4749
4814
|
getSvgFilter() {
|
|
4750
|
-
return this.shadow ? `filter: url(#SVGID_${this.shadow.id});` : '';
|
|
4815
|
+
return this.shadow ? `filter: url(#SVGID_${escapeXml(this.shadow.id)});` : '';
|
|
4751
4816
|
}
|
|
4752
4817
|
|
|
4753
4818
|
/**
|
|
@@ -4755,7 +4820,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4755
4820
|
* @return {String}
|
|
4756
4821
|
*/
|
|
4757
4822
|
getSvgCommons() {
|
|
4758
|
-
return [this.id ? `id="${this.id}" ` : '', this.clipPath ? `clip-path="url(#${this.clipPath.clipPathId})" ` : ''].join('');
|
|
4823
|
+
return [this.id ? `id="${escapeXml(String(this.id))}" ` : '', this.clipPath ? `clip-path="url(#${this.clipPath.clipPathId})" ` : ''].join('');
|
|
4759
4824
|
}
|
|
4760
4825
|
|
|
4761
4826
|
/**
|
|
@@ -4868,7 +4933,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4868
4933
|
return reviver ? reviver(markup.join('')) : markup.join('');
|
|
4869
4934
|
}
|
|
4870
4935
|
addPaintOrder() {
|
|
4871
|
-
return this.paintFirst !== FILL ? ` paint-order="${this.paintFirst}" ` : '';
|
|
4936
|
+
return this.paintFirst !== FILL ? ` paint-order="${escapeXml(this.paintFirst)}" ` : '';
|
|
4872
4937
|
}
|
|
4873
4938
|
}
|
|
4874
4939
|
|
|
@@ -5006,7 +5071,6 @@ const reViewBoxAttrValue = new RegExp(String.raw`^\s*(${reNum})${viewportSeparat
|
|
|
5006
5071
|
|
|
5007
5072
|
(?:$|\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.
|
|
5008
5073
|
*/
|
|
5009
|
-
// eslint-disable-next-line max-len
|
|
5010
5074
|
|
|
5011
5075
|
const shadowOffsetRegex = '(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?';
|
|
5012
5076
|
const reOffsetsAndBlur = new RegExp('(?:\\s|^)' + shadowOffsetRegex + shadowOffsetRegex + '(' + reNum + '?(?:px)?)?(?:\\s?|$)(?:$|\\s)');
|
|
@@ -5065,14 +5129,15 @@ class Shadow {
|
|
|
5065
5129
|
toSVG(object) {
|
|
5066
5130
|
const offset = rotateVector(new Point(this.offsetX, this.offsetY), degreesToRadians(-object.angle)),
|
|
5067
5131
|
BLUR_BOX = 20,
|
|
5132
|
+
NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS,
|
|
5068
5133
|
color = new Color(this.color);
|
|
5069
5134
|
let fBoxX = 40,
|
|
5070
5135
|
fBoxY = 40;
|
|
5071
5136
|
if (object.width && object.height) {
|
|
5072
5137
|
//http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
|
|
5073
5138
|
// we add some extra space to filter box to contain the blur ( 20 )
|
|
5074
|
-
fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width,
|
|
5075
|
-
fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height,
|
|
5139
|
+
fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;
|
|
5140
|
+
fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;
|
|
5076
5141
|
}
|
|
5077
5142
|
if (object.flipX) {
|
|
5078
5143
|
offset.x *= -1;
|
|
@@ -5080,7 +5145,7 @@ class Shadow {
|
|
|
5080
5145
|
if (object.flipY) {
|
|
5081
5146
|
offset.y *= -1;
|
|
5082
5147
|
}
|
|
5083
|
-
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,
|
|
5148
|
+
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`;
|
|
5084
5149
|
}
|
|
5085
5150
|
|
|
5086
5151
|
/**
|
|
@@ -6490,7 +6555,7 @@ class ObjectGeometry extends CommonMethods {
|
|
|
6490
6555
|
calcOwnMatrix() {
|
|
6491
6556
|
const key = this.transformMatrixKey(true),
|
|
6492
6557
|
cache = this.ownMatrixCache;
|
|
6493
|
-
if (cache && cache.key === key) {
|
|
6558
|
+
if (cache && cache.key.every((x, i) => x === key[i])) {
|
|
6494
6559
|
return cache.value;
|
|
6495
6560
|
}
|
|
6496
6561
|
const center = this.getRelativeCenterPoint(),
|
|
@@ -7231,6 +7296,9 @@ let FabricObject$1 = class FabricObject extends ObjectGeometry {
|
|
|
7231
7296
|
} else {
|
|
7232
7297
|
this._renderBackground(ctx);
|
|
7233
7298
|
}
|
|
7299
|
+
this.fire('before:render', {
|
|
7300
|
+
ctx
|
|
7301
|
+
});
|
|
7234
7302
|
this._render(ctx);
|
|
7235
7303
|
this._drawClipPath(ctx, this.clipPath, context);
|
|
7236
7304
|
this.fill = originalFill;
|
|
@@ -8231,6 +8299,20 @@ _defineProperty(FabricObject$1, "customProperties", []);
|
|
|
8231
8299
|
classRegistry.setClass(FabricObject$1);
|
|
8232
8300
|
classRegistry.setClass(FabricObject$1, 'object');
|
|
8233
8301
|
|
|
8302
|
+
const fireEvent = (eventName, options) => {
|
|
8303
|
+
var _target$canvas;
|
|
8304
|
+
const {
|
|
8305
|
+
transform: {
|
|
8306
|
+
target
|
|
8307
|
+
}
|
|
8308
|
+
} = options;
|
|
8309
|
+
(_target$canvas = target.canvas) === null || _target$canvas === void 0 || _target$canvas.fire(`object:${eventName}`, {
|
|
8310
|
+
...options,
|
|
8311
|
+
target
|
|
8312
|
+
});
|
|
8313
|
+
target.fire(eventName, options);
|
|
8314
|
+
};
|
|
8315
|
+
|
|
8234
8316
|
/**
|
|
8235
8317
|
* Wrap an action handler with firing an event if the action is performed
|
|
8236
8318
|
* @param {TModificationEvents} eventName the event we want to fire
|
|
@@ -8273,34 +8355,62 @@ function wrapWithFixedAnchor(actionHandler) {
|
|
|
8273
8355
|
};
|
|
8274
8356
|
}
|
|
8275
8357
|
|
|
8276
|
-
|
|
8277
|
-
* Action handler to change object's width
|
|
8278
|
-
* Needs to be wrapped with `wrapWithFixedAnchor` to be effective
|
|
8279
|
-
* @param {Event} eventData javascript event that is doing the transform
|
|
8280
|
-
* @param {Object} transform javascript object containing a series of information around the current transform
|
|
8281
|
-
* @param {number} x current mouse x position, canvas normalized
|
|
8282
|
-
* @param {number} y current mouse y position, canvas normalized
|
|
8283
|
-
* @return {Boolean} true if some change happened
|
|
8284
|
-
*/
|
|
8285
|
-
const changeObjectWidth = (eventData, transform, x, y) => {
|
|
8358
|
+
const changeObjectDimensionGen = (dimension, origin, xorY, scale) => (eventData, transform, x, y) => {
|
|
8286
8359
|
const localPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y);
|
|
8360
|
+
const localPointValue = localPoint[xorY];
|
|
8287
8361
|
// make sure the control changes width ONLY from it's side of target
|
|
8288
|
-
|
|
8362
|
+
const originValue = resolveOrigin(transform[origin]);
|
|
8363
|
+
if (originValue === 0 || originValue > 0 && localPointValue < 0 || originValue < 0 && localPointValue > 0) {
|
|
8289
8364
|
const {
|
|
8290
8365
|
target
|
|
8291
8366
|
} = transform,
|
|
8292
|
-
strokePadding = target.strokeWidth / (target.strokeUniform ? target
|
|
8367
|
+
strokePadding = target.strokeWidth / (target.strokeUniform ? target[scale] : 1),
|
|
8293
8368
|
multiplier = isTransformCentered(transform) ? 2 : 1,
|
|
8294
|
-
oldWidth = target
|
|
8295
|
-
newWidth = Math.abs(
|
|
8296
|
-
target.set(
|
|
8369
|
+
oldWidth = target[dimension],
|
|
8370
|
+
newWidth = Math.abs(localPointValue * multiplier / target[scale]) - strokePadding;
|
|
8371
|
+
target.set(dimension, Math.max(newWidth, 1));
|
|
8297
8372
|
// check against actual target width in case `newWidth` was rejected
|
|
8298
|
-
return oldWidth !== target
|
|
8373
|
+
return oldWidth !== target[dimension];
|
|
8299
8374
|
}
|
|
8300
8375
|
return false;
|
|
8301
8376
|
};
|
|
8377
|
+
|
|
8378
|
+
/**
|
|
8379
|
+
* Action handler to change object's width
|
|
8380
|
+
* Needs to be wrapped with `wrapWithFixedAnchor` to be effective
|
|
8381
|
+
* You want to use this only if you are building a new control handler and you want
|
|
8382
|
+
* to reuse some logic. use "changeWidth" if you are looking to just use a control for width
|
|
8383
|
+
* @param {Event} eventData javascript event that is doing the transform
|
|
8384
|
+
* @param {Object} transform javascript object containing a series of information around the current transform
|
|
8385
|
+
* @param {number} x current mouse x position, canvas normalized
|
|
8386
|
+
* @param {number} y current mouse y position, canvas normalized
|
|
8387
|
+
* @return {Boolean} true if some change happened
|
|
8388
|
+
*/
|
|
8389
|
+
const changeObjectWidth = changeObjectDimensionGen('width', 'originX', 'x', 'scaleX');
|
|
8390
|
+
|
|
8391
|
+
/**
|
|
8392
|
+
* Action handler to change object's height
|
|
8393
|
+
* Needs to be wrapped with `wrapWithFixedAnchor` to be effective
|
|
8394
|
+
* You want to use this only if you are building a new control handler and you want
|
|
8395
|
+
* to reuse some logic. use "changeHeight" if you are looking to just use a control for height
|
|
8396
|
+
* @param {Event} eventData javascript event that is doing the transform
|
|
8397
|
+
* @param {Object} transform javascript object containing a series of information around the current transform
|
|
8398
|
+
* @param {number} x current mouse x position, canvas normalized
|
|
8399
|
+
* @param {number} y current mouse y position, canvas normalized
|
|
8400
|
+
* @return {Boolean} true if some change happened
|
|
8401
|
+
*/
|
|
8402
|
+
const changeObjectHeight = changeObjectDimensionGen('height', 'originY', 'y', 'scaleY');
|
|
8403
|
+
|
|
8404
|
+
/**
|
|
8405
|
+
* Control handler for changing width
|
|
8406
|
+
*/
|
|
8302
8407
|
const changeWidth = wrapWithFireEvent(RESIZING, wrapWithFixedAnchor(changeObjectWidth));
|
|
8303
8408
|
|
|
8409
|
+
/**
|
|
8410
|
+
* Control handler for changing height
|
|
8411
|
+
*/
|
|
8412
|
+
const changeHeight = wrapWithFireEvent(RESIZING, wrapWithFixedAnchor(changeObjectHeight));
|
|
8413
|
+
|
|
8304
8414
|
/**
|
|
8305
8415
|
* Render a round control, as per fabric features.
|
|
8306
8416
|
* This function is written to respect object properties like transparentCorners, cornerSize
|
|
@@ -8313,33 +8423,24 @@ const changeWidth = wrapWithFireEvent(RESIZING, wrapWithFixedAnchor(changeObject
|
|
|
8313
8423
|
* @param {FabricObject} fabricObject the fabric object for which we are rendering controls
|
|
8314
8424
|
*/
|
|
8315
8425
|
function renderCircleControl(ctx, left, top, styleOverride, fabricObject) {
|
|
8316
|
-
styleOverride = styleOverride || {};
|
|
8317
|
-
const xSize = this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize,
|
|
8318
|
-
ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize,
|
|
8319
|
-
transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ? styleOverride.transparentCorners : fabricObject.transparentCorners,
|
|
8320
|
-
methodName = transparentCorners ? STROKE : FILL,
|
|
8321
|
-
stroke = !transparentCorners && (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor);
|
|
8322
|
-
let myLeft = left,
|
|
8323
|
-
myTop = top,
|
|
8324
|
-
size;
|
|
8325
8426
|
ctx.save();
|
|
8326
|
-
|
|
8327
|
-
|
|
8427
|
+
const {
|
|
8428
|
+
stroke,
|
|
8429
|
+
xSize,
|
|
8430
|
+
ySize,
|
|
8431
|
+
opName
|
|
8432
|
+
} = this.commonRenderProps(ctx, left, top, fabricObject, styleOverride);
|
|
8433
|
+
let size = xSize;
|
|
8328
8434
|
// TODO: use proper ellipse code.
|
|
8329
8435
|
if (xSize > ySize) {
|
|
8330
|
-
size = xSize;
|
|
8331
8436
|
ctx.scale(1.0, ySize / xSize);
|
|
8332
|
-
myTop = top * xSize / ySize;
|
|
8333
8437
|
} else if (ySize > xSize) {
|
|
8334
8438
|
size = ySize;
|
|
8335
8439
|
ctx.scale(xSize / ySize, 1.0);
|
|
8336
|
-
myLeft = left * ySize / xSize;
|
|
8337
|
-
} else {
|
|
8338
|
-
size = xSize;
|
|
8339
8440
|
}
|
|
8340
8441
|
ctx.beginPath();
|
|
8341
|
-
ctx.arc(
|
|
8342
|
-
ctx[
|
|
8442
|
+
ctx.arc(0, 0, size / 2, 0, twoMathPi, false);
|
|
8443
|
+
ctx[opName]();
|
|
8343
8444
|
if (stroke) {
|
|
8344
8445
|
ctx.stroke();
|
|
8345
8446
|
}
|
|
@@ -8358,25 +8459,19 @@ function renderCircleControl(ctx, left, top, styleOverride, fabricObject) {
|
|
|
8358
8459
|
* @param {FabricObject} fabricObject the fabric object for which we are rendering controls
|
|
8359
8460
|
*/
|
|
8360
8461
|
function renderSquareControl(ctx, left, top, styleOverride, fabricObject) {
|
|
8361
|
-
|
|
8362
|
-
const
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
|
|
8462
|
+
ctx.save();
|
|
8463
|
+
const {
|
|
8464
|
+
stroke,
|
|
8465
|
+
xSize,
|
|
8466
|
+
ySize,
|
|
8467
|
+
opName
|
|
8468
|
+
} = this.commonRenderProps(ctx, left, top, fabricObject, styleOverride),
|
|
8367
8469
|
xSizeBy2 = xSize / 2,
|
|
8368
8470
|
ySizeBy2 = ySize / 2;
|
|
8369
|
-
ctx.save();
|
|
8370
|
-
ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor || '';
|
|
8371
|
-
ctx.strokeStyle = styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor || '';
|
|
8372
|
-
ctx.translate(left, top);
|
|
8373
|
-
// angle is relative to canvas plane
|
|
8374
|
-
const angle = fabricObject.getTotalAngle();
|
|
8375
|
-
ctx.rotate(degreesToRadians(angle));
|
|
8376
8471
|
// this does not work, and fixed with ( && ) does not make sense.
|
|
8377
8472
|
// to have real transparent corners we need the controls on upperCanvas
|
|
8378
8473
|
// transparentCorners || ctx.clearRect(-xSizeBy2, -ySizeBy2, xSize, ySize);
|
|
8379
|
-
ctx[`${
|
|
8474
|
+
ctx[`${opName}Rect`](-xSizeBy2, -ySizeBy2, xSize, ySize);
|
|
8380
8475
|
if (stroke) {
|
|
8381
8476
|
ctx.strokeRect(-xSizeBy2, -ySizeBy2, xSize, ySize);
|
|
8382
8477
|
}
|
|
@@ -8494,6 +8589,14 @@ class Control {
|
|
|
8494
8589
|
_defineProperty(this, "withConnection", false);
|
|
8495
8590
|
Object.assign(this, options);
|
|
8496
8591
|
}
|
|
8592
|
+
getTransformAnchorPoint() {
|
|
8593
|
+
var _this$transformAnchor;
|
|
8594
|
+
return (// return the control transformAnchorPoint
|
|
8595
|
+
(_this$transformAnchor = this.transformAnchorPoint) !== null && _this$transformAnchor !== void 0 ? _this$transformAnchor :
|
|
8596
|
+
// otherwise will return the opposite origin of where the control is located.
|
|
8597
|
+
new Point(-this.x + 0.5, -this.y + 0.5)
|
|
8598
|
+
);
|
|
8599
|
+
}
|
|
8497
8600
|
|
|
8498
8601
|
/**
|
|
8499
8602
|
* The control actionHandler, provide one to handle action ( control being moved )
|
|
@@ -8636,6 +8739,41 @@ class Control {
|
|
|
8636
8739
|
};
|
|
8637
8740
|
}
|
|
8638
8741
|
|
|
8742
|
+
/**
|
|
8743
|
+
* This is an helper method to prepare the canvas to render a control
|
|
8744
|
+
* It detectes common control properties and sets the correct fill and
|
|
8745
|
+
* stroke styles on the context. It does not execute translations or
|
|
8746
|
+
* rotations since different controls need differnt combination of these.
|
|
8747
|
+
*/
|
|
8748
|
+
commonRenderProps(ctx, left, top, fabricObject) {
|
|
8749
|
+
let styleOverride = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
8750
|
+
const {
|
|
8751
|
+
cornerSize,
|
|
8752
|
+
cornerColor,
|
|
8753
|
+
transparentCorners,
|
|
8754
|
+
cornerStrokeColor
|
|
8755
|
+
} = styleOverride,
|
|
8756
|
+
sizeFromProps = cornerSize || fabricObject.cornerSize,
|
|
8757
|
+
xSize = this.sizeX || sizeFromProps,
|
|
8758
|
+
ySize = this.sizeY || sizeFromProps,
|
|
8759
|
+
transparent = typeof transparentCorners !== 'undefined' ? transparentCorners : fabricObject.transparentCorners,
|
|
8760
|
+
opName = transparent ? STROKE : FILL,
|
|
8761
|
+
strokeColor = cornerStrokeColor || fabricObject.cornerStrokeColor,
|
|
8762
|
+
stroke = !transparent && !!strokeColor;
|
|
8763
|
+
ctx.fillStyle = cornerColor || fabricObject.cornerColor || '';
|
|
8764
|
+
ctx.strokeStyle = strokeColor || '';
|
|
8765
|
+
ctx.translate(left, top);
|
|
8766
|
+
// angle is relative to canvas plane
|
|
8767
|
+
ctx.rotate(degreesToRadians(fabricObject.getTotalAngle()));
|
|
8768
|
+
return {
|
|
8769
|
+
stroke,
|
|
8770
|
+
xSize,
|
|
8771
|
+
ySize,
|
|
8772
|
+
transparentCorners: transparent,
|
|
8773
|
+
opName
|
|
8774
|
+
};
|
|
8775
|
+
}
|
|
8776
|
+
|
|
8639
8777
|
/**
|
|
8640
8778
|
* Render function for the control.
|
|
8641
8779
|
* When this function runs the context is unscaled. unrotate. Just retina scaled.
|
|
@@ -10275,136 +10413,31 @@ const cloneStyles = style => {
|
|
|
10275
10413
|
};
|
|
10276
10414
|
|
|
10277
10415
|
/**
|
|
10278
|
-
*
|
|
10279
|
-
* @param {
|
|
10280
|
-
* @param {
|
|
10281
|
-
*
|
|
10282
|
-
* and other letters are converted to lowercase.
|
|
10283
|
-
* @return {String} Capitalized version of a string
|
|
10416
|
+
* @param {Object} prevStyle first style to compare
|
|
10417
|
+
* @param {Object} thisStyle second style to compare
|
|
10418
|
+
* @param {boolean} forTextSpans whether to check overline, underline, and line-through properties
|
|
10419
|
+
* @return {boolean} true if the style changed
|
|
10284
10420
|
*/
|
|
10285
|
-
const
|
|
10286
|
-
let
|
|
10287
|
-
return
|
|
10421
|
+
const hasStyleChanged = function (prevStyle, thisStyle) {
|
|
10422
|
+
let forTextSpans = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
10423
|
+
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);
|
|
10288
10424
|
};
|
|
10289
10425
|
|
|
10290
10426
|
/**
|
|
10291
|
-
*
|
|
10292
|
-
*
|
|
10293
|
-
*
|
|
10427
|
+
* Returns the array form of a text object's inline styles property with styles grouped in ranges
|
|
10428
|
+
* rather than per character. This format is less verbose, and is better suited for storage
|
|
10429
|
+
* so it is used in serialization (not during runtime).
|
|
10430
|
+
* @param {object} styles per character styles for a text object
|
|
10431
|
+
* @param {String} text the text string that the styles are applied to
|
|
10432
|
+
* @return {{start: number, end: number, style: object}[]}
|
|
10294
10433
|
*/
|
|
10295
|
-
const
|
|
10296
|
-
|
|
10297
|
-
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
}
|
|
10303
|
-
return segmenter;
|
|
10304
|
-
};
|
|
10305
|
-
|
|
10306
|
-
/**
|
|
10307
|
-
* Divide a string in the user perceived single units
|
|
10308
|
-
* @param {String} textstring String to escape
|
|
10309
|
-
* @return {Array} array containing the graphemes
|
|
10310
|
-
*/
|
|
10311
|
-
const graphemeSplit = textstring => {
|
|
10312
|
-
segmenter || getSegmenter();
|
|
10313
|
-
if (segmenter) {
|
|
10314
|
-
const segments = segmenter.segment(textstring);
|
|
10315
|
-
return Array.from(segments).map(_ref => {
|
|
10316
|
-
let {
|
|
10317
|
-
segment
|
|
10318
|
-
} = _ref;
|
|
10319
|
-
return segment;
|
|
10320
|
-
});
|
|
10321
|
-
}
|
|
10322
|
-
|
|
10323
|
-
//Fallback
|
|
10324
|
-
return graphemeSplitImpl(textstring);
|
|
10325
|
-
};
|
|
10326
|
-
const graphemeSplitImpl = textstring => {
|
|
10327
|
-
const graphemes = [];
|
|
10328
|
-
for (let i = 0, chr; i < textstring.length; i++) {
|
|
10329
|
-
if ((chr = getWholeChar(textstring, i)) === false) {
|
|
10330
|
-
continue;
|
|
10331
|
-
}
|
|
10332
|
-
graphemes.push(chr);
|
|
10333
|
-
}
|
|
10334
|
-
return graphemes;
|
|
10335
|
-
};
|
|
10336
|
-
|
|
10337
|
-
// taken from mdn in the charAt doc page.
|
|
10338
|
-
const getWholeChar = (str, i) => {
|
|
10339
|
-
const code = str.charCodeAt(i);
|
|
10340
|
-
if (isNaN(code)) {
|
|
10341
|
-
return ''; // Position not found
|
|
10342
|
-
}
|
|
10343
|
-
if (code < 0xd800 || code > 0xdfff) {
|
|
10344
|
-
return str.charAt(i);
|
|
10345
|
-
}
|
|
10346
|
-
|
|
10347
|
-
// High surrogate (could change last hex to 0xDB7F to treat high private
|
|
10348
|
-
// surrogates as single characters)
|
|
10349
|
-
if (0xd800 <= code && code <= 0xdbff) {
|
|
10350
|
-
if (str.length <= i + 1) {
|
|
10351
|
-
throw 'High surrogate without following low surrogate';
|
|
10352
|
-
}
|
|
10353
|
-
const next = str.charCodeAt(i + 1);
|
|
10354
|
-
if (0xdc00 > next || next > 0xdfff) {
|
|
10355
|
-
throw 'High surrogate without following low surrogate';
|
|
10356
|
-
}
|
|
10357
|
-
return str.charAt(i) + str.charAt(i + 1);
|
|
10358
|
-
}
|
|
10359
|
-
// Low surrogate (0xDC00 <= code && code <= 0xDFFF)
|
|
10360
|
-
if (i === 0) {
|
|
10361
|
-
throw 'Low surrogate without preceding high surrogate';
|
|
10362
|
-
}
|
|
10363
|
-
const prev = str.charCodeAt(i - 1);
|
|
10364
|
-
|
|
10365
|
-
// (could change last hex to 0xDB7F to treat high private
|
|
10366
|
-
// surrogates as single characters)
|
|
10367
|
-
if (0xd800 > prev || prev > 0xdbff) {
|
|
10368
|
-
throw 'Low surrogate without preceding high surrogate';
|
|
10369
|
-
}
|
|
10370
|
-
// We can pass over low surrogates now as the second component
|
|
10371
|
-
// in a pair which we have already processed
|
|
10372
|
-
return false;
|
|
10373
|
-
};
|
|
10374
|
-
|
|
10375
|
-
var lang_string = /*#__PURE__*/Object.freeze({
|
|
10376
|
-
__proto__: null,
|
|
10377
|
-
capitalize: capitalize,
|
|
10378
|
-
escapeXml: escapeXml,
|
|
10379
|
-
graphemeSplit: graphemeSplit
|
|
10380
|
-
});
|
|
10381
|
-
|
|
10382
|
-
/**
|
|
10383
|
-
* @param {Object} prevStyle first style to compare
|
|
10384
|
-
* @param {Object} thisStyle second style to compare
|
|
10385
|
-
* @param {boolean} forTextSpans whether to check overline, underline, and line-through properties
|
|
10386
|
-
* @return {boolean} true if the style changed
|
|
10387
|
-
*/
|
|
10388
|
-
const hasStyleChanged = function (prevStyle, thisStyle) {
|
|
10389
|
-
let forTextSpans = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
10390
|
-
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);
|
|
10391
|
-
};
|
|
10392
|
-
|
|
10393
|
-
/**
|
|
10394
|
-
* Returns the array form of a text object's inline styles property with styles grouped in ranges
|
|
10395
|
-
* rather than per character. This format is less verbose, and is better suited for storage
|
|
10396
|
-
* so it is used in serialization (not during runtime).
|
|
10397
|
-
* @param {object} styles per character styles for a text object
|
|
10398
|
-
* @param {String} text the text string that the styles are applied to
|
|
10399
|
-
* @return {{start: number, end: number, style: object}[]}
|
|
10400
|
-
*/
|
|
10401
|
-
const stylesToArray = (styles, text) => {
|
|
10402
|
-
const textLines = text.split('\n'),
|
|
10403
|
-
stylesArray = [];
|
|
10404
|
-
let charIndex = -1,
|
|
10405
|
-
prevStyle = {};
|
|
10406
|
-
// clone style structure to prevent mutation
|
|
10407
|
-
styles = cloneStyles(styles);
|
|
10434
|
+
const stylesToArray = (styles, text) => {
|
|
10435
|
+
const textLines = text.split('\n'),
|
|
10436
|
+
stylesArray = [];
|
|
10437
|
+
let charIndex = -1,
|
|
10438
|
+
prevStyle = {};
|
|
10439
|
+
// clone style structure to prevent mutation
|
|
10440
|
+
styles = cloneStyles(styles);
|
|
10408
10441
|
|
|
10409
10442
|
//loop through each textLine
|
|
10410
10443
|
for (let i = 0; i < textLines.length; i++) {
|
|
@@ -10962,7 +10995,7 @@ class Rect extends FabricObject {
|
|
|
10962
10995
|
rx,
|
|
10963
10996
|
ry
|
|
10964
10997
|
} = this;
|
|
10965
|
-
return ['<rect ', 'COMMON_PARTS', `x="${-width / 2}" y="${-height / 2}" rx="${rx}" ry="${ry}" width="${width}" height="${height}" />\n`];
|
|
10998
|
+
return ['<rect ', 'COMMON_PARTS', `x="${-width / 2}" y="${-height / 2}" rx="${escapeXml(rx)}" ry="${escapeXml(ry)}" width="${escapeXml(width)}" height="${escapeXml(height)}" />\n`];
|
|
10966
10999
|
}
|
|
10967
11000
|
|
|
10968
11001
|
/**
|
|
@@ -11927,7 +11960,7 @@ class Group extends createCollectionMixin(FabricObject) {
|
|
|
11927
11960
|
* @return {String}
|
|
11928
11961
|
*/
|
|
11929
11962
|
getSvgStyles() {
|
|
11930
|
-
const opacity = typeof this.opacity !== 'undefined' && this.opacity !== 1 ? `opacity: ${this.opacity};` : '',
|
|
11963
|
+
const opacity = typeof this.opacity !== 'undefined' && this.opacity !== 1 ? `opacity: ${escapeXml(this.opacity)};` : '',
|
|
11931
11964
|
visibility = this.visible ? '' : ' visibility: hidden;';
|
|
11932
11965
|
return [opacity, this.getSvgFilter(), visibility].join('');
|
|
11933
11966
|
}
|
|
@@ -13229,6 +13262,288 @@ const canvasDefaults = {
|
|
|
13229
13262
|
preserveObjectStacking: true
|
|
13230
13263
|
};
|
|
13231
13264
|
|
|
13265
|
+
/**
|
|
13266
|
+
* Action handler
|
|
13267
|
+
* @private
|
|
13268
|
+
* @param {Event} eventData javascript event that is doing the transform
|
|
13269
|
+
* @param {Object} transform javascript object containing a series of information around the current transform
|
|
13270
|
+
* @param {number} x current mouse x position, canvas normalized
|
|
13271
|
+
* @param {number} y current mouse y position, canvas normalized
|
|
13272
|
+
* @return {Boolean} true if the translation occurred
|
|
13273
|
+
*/
|
|
13274
|
+
const dragHandler = (eventData, transform, x, y) => {
|
|
13275
|
+
const {
|
|
13276
|
+
target,
|
|
13277
|
+
offsetX,
|
|
13278
|
+
offsetY
|
|
13279
|
+
} = transform,
|
|
13280
|
+
newLeft = x - offsetX,
|
|
13281
|
+
newTop = y - offsetY,
|
|
13282
|
+
moveX = !isLocked(target, 'lockMovementX') && target.left !== newLeft,
|
|
13283
|
+
moveY = !isLocked(target, 'lockMovementY') && target.top !== newTop;
|
|
13284
|
+
moveX && target.set(LEFT, newLeft);
|
|
13285
|
+
moveY && target.set(TOP, newTop);
|
|
13286
|
+
if (moveX || moveY) {
|
|
13287
|
+
fireEvent(MOVING, commonEventInfo(eventData, transform, x, y));
|
|
13288
|
+
}
|
|
13289
|
+
return moveX || moveY;
|
|
13290
|
+
};
|
|
13291
|
+
|
|
13292
|
+
const ACTION_NAME$1 = MODIFY_POLY;
|
|
13293
|
+
/**
|
|
13294
|
+
* This function locates the controls.
|
|
13295
|
+
* It'll be used both for drawing and for interaction.
|
|
13296
|
+
*/
|
|
13297
|
+
const createPolyPositionHandler = pointIndex => {
|
|
13298
|
+
return function (dim, finalMatrix, polyObject) {
|
|
13299
|
+
const {
|
|
13300
|
+
points,
|
|
13301
|
+
pathOffset
|
|
13302
|
+
} = polyObject;
|
|
13303
|
+
return new Point(points[pointIndex]).subtract(pathOffset).transform(multiplyTransformMatrices(polyObject.getViewportTransform(), polyObject.calcTransformMatrix()));
|
|
13304
|
+
};
|
|
13305
|
+
};
|
|
13306
|
+
|
|
13307
|
+
/**
|
|
13308
|
+
* This function defines what the control does.
|
|
13309
|
+
* It'll be called on every mouse move after a control has been clicked and is being dragged.
|
|
13310
|
+
* The function receives as argument the mouse event, the current transform object
|
|
13311
|
+
* and the current position in canvas coordinate `transform.target` is a reference to the
|
|
13312
|
+
* current object being transformed.
|
|
13313
|
+
*/
|
|
13314
|
+
const polyActionHandler = (eventData, transform, x, y) => {
|
|
13315
|
+
const {
|
|
13316
|
+
target,
|
|
13317
|
+
pointIndex
|
|
13318
|
+
} = transform;
|
|
13319
|
+
const poly = target;
|
|
13320
|
+
const mouseLocalPosition = sendPointToPlane(new Point(x, y), undefined, poly.calcOwnMatrix());
|
|
13321
|
+
poly.points[pointIndex] = mouseLocalPosition.add(poly.pathOffset);
|
|
13322
|
+
poly.setDimensions();
|
|
13323
|
+
poly.set('dirty', true);
|
|
13324
|
+
return true;
|
|
13325
|
+
};
|
|
13326
|
+
|
|
13327
|
+
/**
|
|
13328
|
+
* Keep the polygon in the same position when we change its `width`/`height`/`top`/`left`.
|
|
13329
|
+
*/
|
|
13330
|
+
const factoryPolyActionHandler = (pointIndex, fn) => {
|
|
13331
|
+
return function (eventData, transform, x, y) {
|
|
13332
|
+
const poly = transform.target,
|
|
13333
|
+
anchorPoint = new Point(poly.points[(pointIndex > 0 ? pointIndex : poly.points.length) - 1]),
|
|
13334
|
+
anchorPointInParentPlane = anchorPoint.subtract(poly.pathOffset).transform(poly.calcOwnMatrix()),
|
|
13335
|
+
actionPerformed = fn(eventData, {
|
|
13336
|
+
...transform,
|
|
13337
|
+
pointIndex
|
|
13338
|
+
}, x, y);
|
|
13339
|
+
const newAnchorPointInParentPlane = anchorPoint.subtract(poly.pathOffset).transform(poly.calcOwnMatrix());
|
|
13340
|
+
const diff = newAnchorPointInParentPlane.subtract(anchorPointInParentPlane);
|
|
13341
|
+
poly.left -= diff.x;
|
|
13342
|
+
poly.top -= diff.y;
|
|
13343
|
+
return actionPerformed;
|
|
13344
|
+
};
|
|
13345
|
+
};
|
|
13346
|
+
const createPolyActionHandler = pointIndex => wrapWithFireEvent(ACTION_NAME$1, factoryPolyActionHandler(pointIndex, polyActionHandler));
|
|
13347
|
+
function createPolyControls(arg0) {
|
|
13348
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
13349
|
+
const controls = {};
|
|
13350
|
+
for (let idx = 0; idx < (typeof arg0 === 'number' ? arg0 : arg0.points.length); idx++) {
|
|
13351
|
+
controls[`p${idx}`] = new Control({
|
|
13352
|
+
actionName: ACTION_NAME$1,
|
|
13353
|
+
positionHandler: createPolyPositionHandler(idx),
|
|
13354
|
+
actionHandler: createPolyActionHandler(idx),
|
|
13355
|
+
...options
|
|
13356
|
+
});
|
|
13357
|
+
}
|
|
13358
|
+
return controls;
|
|
13359
|
+
}
|
|
13360
|
+
|
|
13361
|
+
const ACTION_NAME = 'modifyPath';
|
|
13362
|
+
const calcPathPointPosition = (pathObject, commandIndex, pointIndex) => {
|
|
13363
|
+
const {
|
|
13364
|
+
path,
|
|
13365
|
+
pathOffset
|
|
13366
|
+
} = pathObject;
|
|
13367
|
+
const command = path[commandIndex];
|
|
13368
|
+
return new Point(command[pointIndex] - pathOffset.x, command[pointIndex + 1] - pathOffset.y).transform(multiplyTransformMatrices(pathObject.getViewportTransform(), pathObject.calcTransformMatrix()));
|
|
13369
|
+
};
|
|
13370
|
+
const movePathPoint = (pathObject, x, y, commandIndex, pointIndex) => {
|
|
13371
|
+
const {
|
|
13372
|
+
path,
|
|
13373
|
+
pathOffset
|
|
13374
|
+
} = pathObject;
|
|
13375
|
+
const anchorCommand = path[(commandIndex > 0 ? commandIndex : path.length) - 1];
|
|
13376
|
+
const anchorPoint = new Point(anchorCommand[pointIndex], anchorCommand[pointIndex + 1]);
|
|
13377
|
+
const anchorPointInParentPlane = anchorPoint.subtract(pathOffset).transform(pathObject.calcOwnMatrix());
|
|
13378
|
+
const mouseLocalPosition = sendPointToPlane(new Point(x, y), undefined, pathObject.calcOwnMatrix());
|
|
13379
|
+
path[commandIndex][pointIndex] = mouseLocalPosition.x + pathOffset.x;
|
|
13380
|
+
path[commandIndex][pointIndex + 1] = mouseLocalPosition.y + pathOffset.y;
|
|
13381
|
+
pathObject.setDimensions();
|
|
13382
|
+
const newAnchorPointInParentPlane = anchorPoint.subtract(pathObject.pathOffset).transform(pathObject.calcOwnMatrix());
|
|
13383
|
+
const diff = newAnchorPointInParentPlane.subtract(anchorPointInParentPlane);
|
|
13384
|
+
pathObject.left -= diff.x;
|
|
13385
|
+
pathObject.top -= diff.y;
|
|
13386
|
+
pathObject.set('dirty', true);
|
|
13387
|
+
return true;
|
|
13388
|
+
};
|
|
13389
|
+
|
|
13390
|
+
/**
|
|
13391
|
+
* This function locates the controls.
|
|
13392
|
+
* It'll be used both for drawing and for interaction.
|
|
13393
|
+
*/
|
|
13394
|
+
function pathPositionHandler(dim, finalMatrix, pathObject) {
|
|
13395
|
+
const {
|
|
13396
|
+
commandIndex,
|
|
13397
|
+
pointIndex
|
|
13398
|
+
} = this;
|
|
13399
|
+
return calcPathPointPosition(pathObject, commandIndex, pointIndex);
|
|
13400
|
+
}
|
|
13401
|
+
|
|
13402
|
+
/**
|
|
13403
|
+
* This function defines what the control does.
|
|
13404
|
+
* It'll be called on every mouse move after a control has been clicked and is being dragged.
|
|
13405
|
+
* The function receives as argument the mouse event, the current transform object
|
|
13406
|
+
* and the current position in canvas coordinate `transform.target` is a reference to the
|
|
13407
|
+
* current object being transformed.
|
|
13408
|
+
*/
|
|
13409
|
+
function pathActionHandler(eventData, transform, x, y) {
|
|
13410
|
+
const {
|
|
13411
|
+
target
|
|
13412
|
+
} = transform;
|
|
13413
|
+
const {
|
|
13414
|
+
commandIndex,
|
|
13415
|
+
pointIndex
|
|
13416
|
+
} = this;
|
|
13417
|
+
const actionPerformed = movePathPoint(target, x, y, commandIndex, pointIndex);
|
|
13418
|
+
{
|
|
13419
|
+
fireEvent(this.actionName, {
|
|
13420
|
+
...commonEventInfo(eventData, transform, x, y),
|
|
13421
|
+
commandIndex,
|
|
13422
|
+
pointIndex
|
|
13423
|
+
});
|
|
13424
|
+
}
|
|
13425
|
+
return actionPerformed;
|
|
13426
|
+
}
|
|
13427
|
+
const indexFromPrevCommand = previousCommandType => previousCommandType === 'C' ? 5 : previousCommandType === 'Q' ? 3 : 1;
|
|
13428
|
+
class PathPointControl extends Control {
|
|
13429
|
+
constructor(options) {
|
|
13430
|
+
super(options);
|
|
13431
|
+
}
|
|
13432
|
+
render(ctx, left, top, styleOverride, fabricObject) {
|
|
13433
|
+
const overrides = {
|
|
13434
|
+
...styleOverride,
|
|
13435
|
+
cornerColor: this.controlFill,
|
|
13436
|
+
cornerStrokeColor: this.controlStroke,
|
|
13437
|
+
transparentCorners: !this.controlFill
|
|
13438
|
+
};
|
|
13439
|
+
super.render(ctx, left, top, overrides, fabricObject);
|
|
13440
|
+
}
|
|
13441
|
+
}
|
|
13442
|
+
class PathControlPointControl extends PathPointControl {
|
|
13443
|
+
constructor(options) {
|
|
13444
|
+
super(options);
|
|
13445
|
+
}
|
|
13446
|
+
render(ctx, left, top, styleOverride, fabricObject) {
|
|
13447
|
+
const {
|
|
13448
|
+
path
|
|
13449
|
+
} = fabricObject;
|
|
13450
|
+
const {
|
|
13451
|
+
commandIndex,
|
|
13452
|
+
pointIndex,
|
|
13453
|
+
connectToCommandIndex,
|
|
13454
|
+
connectToPointIndex
|
|
13455
|
+
} = this;
|
|
13456
|
+
ctx.save();
|
|
13457
|
+
ctx.strokeStyle = this.controlStroke;
|
|
13458
|
+
if (this.connectionDashArray) {
|
|
13459
|
+
ctx.setLineDash(this.connectionDashArray);
|
|
13460
|
+
}
|
|
13461
|
+
const [commandType] = path[commandIndex];
|
|
13462
|
+
const point = calcPathPointPosition(fabricObject, connectToCommandIndex, connectToPointIndex);
|
|
13463
|
+
if (commandType === 'Q') {
|
|
13464
|
+
// one control point connects to 2 points
|
|
13465
|
+
const point2 = calcPathPointPosition(fabricObject, commandIndex, pointIndex + 2);
|
|
13466
|
+
ctx.moveTo(point2.x, point2.y);
|
|
13467
|
+
ctx.lineTo(left, top);
|
|
13468
|
+
} else {
|
|
13469
|
+
ctx.moveTo(left, top);
|
|
13470
|
+
}
|
|
13471
|
+
ctx.lineTo(point.x, point.y);
|
|
13472
|
+
ctx.stroke();
|
|
13473
|
+
ctx.restore();
|
|
13474
|
+
super.render(ctx, left, top, styleOverride, fabricObject);
|
|
13475
|
+
}
|
|
13476
|
+
}
|
|
13477
|
+
const createControl = (commandIndexPos, pointIndexPos, isControlPoint, options, connectToCommandIndex, connectToPointIndex) => new (isControlPoint ? PathControlPointControl : PathPointControl)({
|
|
13478
|
+
commandIndex: commandIndexPos,
|
|
13479
|
+
pointIndex: pointIndexPos,
|
|
13480
|
+
actionName: ACTION_NAME,
|
|
13481
|
+
positionHandler: pathPositionHandler,
|
|
13482
|
+
actionHandler: pathActionHandler,
|
|
13483
|
+
connectToCommandIndex,
|
|
13484
|
+
connectToPointIndex,
|
|
13485
|
+
...options,
|
|
13486
|
+
...(isControlPoint ? options.controlPointStyle : options.pointStyle)
|
|
13487
|
+
});
|
|
13488
|
+
function createPathControls(path) {
|
|
13489
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
13490
|
+
const controls = {};
|
|
13491
|
+
let previousCommandType = 'M';
|
|
13492
|
+
path.path.forEach((command, commandIndex) => {
|
|
13493
|
+
const commandType = command[0];
|
|
13494
|
+
if (commandType !== 'Z') {
|
|
13495
|
+
controls[`c_${commandIndex}_${commandType}`] = createControl(commandIndex, command.length - 2, false, options);
|
|
13496
|
+
}
|
|
13497
|
+
switch (commandType) {
|
|
13498
|
+
case 'C':
|
|
13499
|
+
controls[`c_${commandIndex}_C_CP_1`] = createControl(commandIndex, 1, true, options, commandIndex - 1, indexFromPrevCommand(previousCommandType));
|
|
13500
|
+
controls[`c_${commandIndex}_C_CP_2`] = createControl(commandIndex, 3, true, options, commandIndex, 5);
|
|
13501
|
+
break;
|
|
13502
|
+
case 'Q':
|
|
13503
|
+
controls[`c_${commandIndex}_Q_CP_1`] = createControl(commandIndex, 1, true, options, commandIndex, 3);
|
|
13504
|
+
break;
|
|
13505
|
+
}
|
|
13506
|
+
previousCommandType = commandType;
|
|
13507
|
+
});
|
|
13508
|
+
return controls;
|
|
13509
|
+
}
|
|
13510
|
+
|
|
13511
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
13512
|
+
__proto__: null,
|
|
13513
|
+
changeHeight: changeHeight,
|
|
13514
|
+
changeObjectHeight: changeObjectHeight,
|
|
13515
|
+
changeObjectWidth: changeObjectWidth,
|
|
13516
|
+
changeWidth: changeWidth,
|
|
13517
|
+
createObjectDefaultControls: createObjectDefaultControls,
|
|
13518
|
+
createPathControls: createPathControls,
|
|
13519
|
+
createPolyActionHandler: createPolyActionHandler,
|
|
13520
|
+
createPolyControls: createPolyControls,
|
|
13521
|
+
createPolyPositionHandler: createPolyPositionHandler,
|
|
13522
|
+
createResizeControls: createResizeControls,
|
|
13523
|
+
createTextboxDefaultControls: createTextboxDefaultControls,
|
|
13524
|
+
dragHandler: dragHandler,
|
|
13525
|
+
factoryPolyActionHandler: factoryPolyActionHandler,
|
|
13526
|
+
getLocalPoint: getLocalPoint,
|
|
13527
|
+
polyActionHandler: polyActionHandler,
|
|
13528
|
+
renderCircleControl: renderCircleControl,
|
|
13529
|
+
renderSquareControl: renderSquareControl,
|
|
13530
|
+
rotationStyleHandler: rotationStyleHandler,
|
|
13531
|
+
rotationWithSnapping: rotationWithSnapping,
|
|
13532
|
+
scaleCursorStyleHandler: scaleCursorStyleHandler,
|
|
13533
|
+
scaleOrSkewActionName: scaleOrSkewActionName,
|
|
13534
|
+
scaleSkewCursorStyleHandler: scaleSkewCursorStyleHandler,
|
|
13535
|
+
scalingEqually: scalingEqually,
|
|
13536
|
+
scalingX: scalingX,
|
|
13537
|
+
scalingXOrSkewingY: scalingXOrSkewingY,
|
|
13538
|
+
scalingY: scalingY,
|
|
13539
|
+
scalingYOrSkewingX: scalingYOrSkewingX,
|
|
13540
|
+
skewCursorStyleHandler: skewCursorStyleHandler,
|
|
13541
|
+
skewHandlerX: skewHandlerX,
|
|
13542
|
+
skewHandlerY: skewHandlerY,
|
|
13543
|
+
wrapWithFireEvent: wrapWithFireEvent,
|
|
13544
|
+
wrapWithFixedAnchor: wrapWithFixedAnchor
|
|
13545
|
+
});
|
|
13546
|
+
|
|
13232
13547
|
/**
|
|
13233
13548
|
* Canvas class
|
|
13234
13549
|
* @class Canvas
|
|
@@ -13599,11 +13914,13 @@ class SelectableCanvas extends StaticCanvas$1 {
|
|
|
13599
13914
|
* Given the control clicked, determine the origin of the transform.
|
|
13600
13915
|
* This is bad because controls can totally have custom names
|
|
13601
13916
|
* should disappear before release 4.0
|
|
13917
|
+
* Fabric 7.1, jan 2026 we are still using this.
|
|
13918
|
+
* Needs to go.
|
|
13602
13919
|
* @private
|
|
13603
13920
|
* @deprecated
|
|
13604
13921
|
*/
|
|
13605
13922
|
_getOriginFromCorner(target, controlName) {
|
|
13606
|
-
const origin = {
|
|
13923
|
+
const origin = controlName ? target.controls[controlName].getTransformAnchorPoint() : {
|
|
13607
13924
|
x: target.originX,
|
|
13608
13925
|
y: target.originY
|
|
13609
13926
|
};
|
|
@@ -13611,6 +13928,9 @@ class SelectableCanvas extends StaticCanvas$1 {
|
|
|
13611
13928
|
return origin;
|
|
13612
13929
|
}
|
|
13613
13930
|
|
|
13931
|
+
// this part down here is deprecated.
|
|
13932
|
+
// It is left to do not change the standard behavior in the middle of a major version
|
|
13933
|
+
// but when possible `getTransformAnchorPoint` will be the only source of truth
|
|
13614
13934
|
// is a left control ?
|
|
13615
13935
|
if (['ml', 'tl', 'bl'].includes(controlName)) {
|
|
13616
13936
|
origin.x = RIGHT;
|
|
@@ -13650,37 +13970,52 @@ class SelectableCanvas extends StaticCanvas$1 {
|
|
|
13650
13970
|
x: CENTER,
|
|
13651
13971
|
y: CENTER
|
|
13652
13972
|
} : this._getOriginFromCorner(target, corner),
|
|
13973
|
+
{
|
|
13974
|
+
scaleX,
|
|
13975
|
+
scaleY,
|
|
13976
|
+
skewX,
|
|
13977
|
+
skewY,
|
|
13978
|
+
left,
|
|
13979
|
+
top,
|
|
13980
|
+
angle,
|
|
13981
|
+
width,
|
|
13982
|
+
height,
|
|
13983
|
+
cropX,
|
|
13984
|
+
cropY
|
|
13985
|
+
} = target,
|
|
13653
13986
|
/**
|
|
13654
13987
|
* relative to target's containing coordinate plane
|
|
13655
13988
|
* both agree on every point
|
|
13656
13989
|
**/
|
|
13657
13990
|
transform = {
|
|
13658
|
-
target
|
|
13991
|
+
target,
|
|
13659
13992
|
action,
|
|
13660
13993
|
actionHandler,
|
|
13661
13994
|
actionPerformed: false,
|
|
13662
13995
|
corner,
|
|
13663
|
-
scaleX
|
|
13664
|
-
scaleY
|
|
13665
|
-
skewX
|
|
13666
|
-
skewY
|
|
13667
|
-
offsetX: pointer.x -
|
|
13668
|
-
offsetY: pointer.y -
|
|
13996
|
+
scaleX,
|
|
13997
|
+
scaleY,
|
|
13998
|
+
skewX,
|
|
13999
|
+
skewY,
|
|
14000
|
+
offsetX: pointer.x - left,
|
|
14001
|
+
offsetY: pointer.y - top,
|
|
13669
14002
|
originX: origin.x,
|
|
13670
14003
|
originY: origin.y,
|
|
13671
14004
|
ex: pointer.x,
|
|
13672
14005
|
ey: pointer.y,
|
|
13673
14006
|
lastX: pointer.x,
|
|
13674
14007
|
lastY: pointer.y,
|
|
13675
|
-
theta: degreesToRadians(
|
|
13676
|
-
width
|
|
13677
|
-
height
|
|
14008
|
+
theta: degreesToRadians(angle),
|
|
14009
|
+
width,
|
|
14010
|
+
height,
|
|
13678
14011
|
shiftKey: e.shiftKey,
|
|
13679
14012
|
altKey,
|
|
13680
14013
|
original: {
|
|
13681
14014
|
...saveObjectTransform(target),
|
|
13682
14015
|
originX: origin.x,
|
|
13683
|
-
originY: origin.y
|
|
14016
|
+
originY: origin.y,
|
|
14017
|
+
cropX,
|
|
14018
|
+
cropY
|
|
13684
14019
|
}
|
|
13685
14020
|
};
|
|
13686
14021
|
this._currentTransform = transform;
|
|
@@ -16093,7 +16428,8 @@ class Gradient {
|
|
|
16093
16428
|
}
|
|
16094
16429
|
transform[4] -= offsetX;
|
|
16095
16430
|
transform[5] -= offsetY;
|
|
16096
|
-
const commonAttributes = [`id="SVGID_${this.id}"`, `gradientUnits="${gradientUnits}"`, `gradientTransform="${preTransform ? preTransform + ' ' : ''}${matrixToSVG(transform)}"`, ''].join(' ');
|
|
16431
|
+
const commonAttributes = [`id="SVGID_${escapeXml(String(this.id))}"`, `gradientUnits="${gradientUnits}"`, `gradientTransform="${preTransform ? preTransform + ' ' : ''}${matrixToSVG(transform)}"`, ''].join(' ');
|
|
16432
|
+
const sanitizeCoord = value => parseFloat(String(value));
|
|
16097
16433
|
if (this.type === 'linear') {
|
|
16098
16434
|
const {
|
|
16099
16435
|
x1,
|
|
@@ -16101,7 +16437,11 @@ class Gradient {
|
|
|
16101
16437
|
x2,
|
|
16102
16438
|
y2
|
|
16103
16439
|
} = this.coords;
|
|
16104
|
-
|
|
16440
|
+
const sx1 = sanitizeCoord(x1);
|
|
16441
|
+
const sy1 = sanitizeCoord(y1);
|
|
16442
|
+
const sx2 = sanitizeCoord(x2);
|
|
16443
|
+
const sy2 = sanitizeCoord(y2);
|
|
16444
|
+
markup.push('<linearGradient ', commonAttributes, ' x1="', sx1, '" y1="', sy1, '" x2="', sx2, '" y2="', sy2, '">\n');
|
|
16105
16445
|
} else if (this.type === 'radial') {
|
|
16106
16446
|
const {
|
|
16107
16447
|
x1,
|
|
@@ -16111,9 +16451,15 @@ class Gradient {
|
|
|
16111
16451
|
r1,
|
|
16112
16452
|
r2
|
|
16113
16453
|
} = this.coords;
|
|
16114
|
-
const
|
|
16454
|
+
const sx1 = sanitizeCoord(x1);
|
|
16455
|
+
const sy1 = sanitizeCoord(y1);
|
|
16456
|
+
const sx2 = sanitizeCoord(x2);
|
|
16457
|
+
const sy2 = sanitizeCoord(y2);
|
|
16458
|
+
const sr1 = sanitizeCoord(r1);
|
|
16459
|
+
const sr2 = sanitizeCoord(r2);
|
|
16460
|
+
const needsSwap = sr1 > sr2;
|
|
16115
16461
|
// svg radial gradient has just 1 radius. the biggest.
|
|
16116
|
-
markup.push('<radialGradient ', commonAttributes, ' cx="', needsSwap ?
|
|
16462
|
+
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');
|
|
16117
16463
|
if (needsSwap) {
|
|
16118
16464
|
// svg goes from internal to external radius. if radius are inverted, swap color stops.
|
|
16119
16465
|
colorStops.reverse(); // mutates array
|
|
@@ -16121,16 +16467,17 @@ class Gradient {
|
|
|
16121
16467
|
colorStop.offset = 1 - colorStop.offset;
|
|
16122
16468
|
});
|
|
16123
16469
|
}
|
|
16124
|
-
const minRadius = Math.min(
|
|
16470
|
+
const minRadius = Math.min(sr1, sr2);
|
|
16125
16471
|
if (minRadius > 0) {
|
|
16126
16472
|
// i have to shift all colorStops and add new one in 0.
|
|
16127
|
-
const maxRadius = Math.max(
|
|
16473
|
+
const maxRadius = Math.max(sr1, sr2),
|
|
16128
16474
|
percentageShift = minRadius / maxRadius;
|
|
16129
16475
|
colorStops.forEach(colorStop => {
|
|
16130
16476
|
colorStop.offset += percentageShift * (1 - colorStop.offset);
|
|
16131
16477
|
});
|
|
16132
16478
|
}
|
|
16133
16479
|
}
|
|
16480
|
+
// todo make a malicious script tag injection test with color and also apply a fix with escapeXml
|
|
16134
16481
|
colorStops.forEach(_ref => {
|
|
16135
16482
|
let {
|
|
16136
16483
|
color,
|
|
@@ -16446,7 +16793,7 @@ class Pattern {
|
|
|
16446
16793
|
patternOffsetY = ifNaN(this.offsetY / height, 0),
|
|
16447
16794
|
patternWidth = repeat === 'repeat-y' || repeat === 'no-repeat' ? 1 + Math.abs(patternOffsetX || 0) : ifNaN(patternSource.width / width, 0),
|
|
16448
16795
|
patternHeight = repeat === 'repeat-x' || repeat === 'no-repeat' ? 1 + Math.abs(patternOffsetY || 0) : ifNaN(patternSource.height / height, 0);
|
|
16449
|
-
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');
|
|
16796
|
+
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');
|
|
16450
16797
|
}
|
|
16451
16798
|
/* _TO_SVG_END_ */
|
|
16452
16799
|
|
|
@@ -16728,8 +17075,7 @@ class Path extends FabricObject {
|
|
|
16728
17075
|
* of the instance
|
|
16729
17076
|
*/
|
|
16730
17077
|
_toSVG() {
|
|
16731
|
-
|
|
16732
|
-
return ['<path ', 'COMMON_PARTS', `d="${path}" stroke-linecap="round" />\n`];
|
|
17078
|
+
return ['<path ', 'COMMON_PARTS', `d="${joinPath(this.path, config.NUM_FRACTION_DIGITS)}" stroke-linecap="round" />\n`];
|
|
16733
17079
|
}
|
|
16734
17080
|
|
|
16735
17081
|
/**
|
|
@@ -17280,15 +17626,17 @@ class Circle extends FabricObject {
|
|
|
17280
17626
|
* of the instance
|
|
17281
17627
|
*/
|
|
17282
17628
|
_toSVG() {
|
|
17283
|
-
const
|
|
17629
|
+
const {
|
|
17630
|
+
radius,
|
|
17631
|
+
startAngle,
|
|
17632
|
+
endAngle
|
|
17633
|
+
} = this;
|
|
17634
|
+
const angle = (endAngle - startAngle) % 360;
|
|
17284
17635
|
if (angle === 0) {
|
|
17285
|
-
return ['<circle ', 'COMMON_PARTS', 'cx="0" cy="0" ', 'r="', `${
|
|
17636
|
+
return ['<circle ', 'COMMON_PARTS', 'cx="0" cy="0" ', 'r="', `${escapeXml(radius)}`, '" />\n'];
|
|
17286
17637
|
} else {
|
|
17287
|
-
const
|
|
17288
|
-
|
|
17289
|
-
} = this;
|
|
17290
|
-
const start = degreesToRadians(this.startAngle),
|
|
17291
|
-
end = degreesToRadians(this.endAngle),
|
|
17638
|
+
const start = degreesToRadians(startAngle),
|
|
17639
|
+
end = degreesToRadians(endAngle),
|
|
17292
17640
|
startX = cos(start) * radius,
|
|
17293
17641
|
startY = sin(start) * radius,
|
|
17294
17642
|
endX = cos(end) * radius,
|
|
@@ -17860,17 +18208,13 @@ class Line extends FabricObject {
|
|
|
17860
18208
|
width,
|
|
17861
18209
|
height
|
|
17862
18210
|
} = this;
|
|
17863
|
-
const xMult = _x1 <= _x2 ? -
|
|
17864
|
-
yMult = _y1 <= _y2 ? -
|
|
17865
|
-
x1 = xMult * width / 2,
|
|
17866
|
-
y1 = yMult * height / 2,
|
|
17867
|
-
x2 = xMult * -width / 2,
|
|
17868
|
-
y2 = yMult * -height / 2;
|
|
18211
|
+
const xMult = _x1 <= _x2 ? -0.5 : 0.5,
|
|
18212
|
+
yMult = _y1 <= _y2 ? -0.5 : 0.5;
|
|
17869
18213
|
return {
|
|
17870
|
-
x1,
|
|
17871
|
-
x2,
|
|
17872
|
-
y1,
|
|
17873
|
-
y2
|
|
18214
|
+
x1: xMult * width,
|
|
18215
|
+
x2: xMult * -width,
|
|
18216
|
+
y1: yMult * height,
|
|
18217
|
+
y2: yMult * -height
|
|
17874
18218
|
};
|
|
17875
18219
|
}
|
|
17876
18220
|
|
|
@@ -18088,7 +18432,7 @@ class Ellipse extends FabricObject {
|
|
|
18088
18432
|
* of the instance
|
|
18089
18433
|
*/
|
|
18090
18434
|
_toSVG() {
|
|
18091
|
-
return ['<ellipse ', 'COMMON_PARTS', `cx="0" cy="0" rx="${this.rx}" ry="${this.ry}" />\n`];
|
|
18435
|
+
return ['<ellipse ', 'COMMON_PARTS', `cx="0" cy="0" rx="${escapeXml(this.rx)}" ry="${escapeXml(this.ry)}" />\n`];
|
|
18092
18436
|
}
|
|
18093
18437
|
|
|
18094
18438
|
/**
|
|
@@ -18406,14 +18750,17 @@ class Polyline extends FabricObject {
|
|
|
18406
18750
|
* of the instance
|
|
18407
18751
|
*/
|
|
18408
18752
|
_toSVG() {
|
|
18409
|
-
const
|
|
18410
|
-
diffX = this.pathOffset.x,
|
|
18753
|
+
const diffX = this.pathOffset.x,
|
|
18411
18754
|
diffY = this.pathOffset.y,
|
|
18412
18755
|
NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS;
|
|
18413
|
-
|
|
18414
|
-
|
|
18415
|
-
|
|
18416
|
-
|
|
18756
|
+
const points = this.points.map(_ref2 => {
|
|
18757
|
+
let {
|
|
18758
|
+
x,
|
|
18759
|
+
y
|
|
18760
|
+
} = _ref2;
|
|
18761
|
+
return `${toFixed(x - diffX, NUM_FRACTION_DIGITS)},${toFixed(y - diffY, NUM_FRACTION_DIGITS)}`;
|
|
18762
|
+
}).join(' ');
|
|
18763
|
+
return [`<${escapeXml(this.constructor.type).toLowerCase()} `, 'COMMON_PARTS', `points="${points}" />\n`];
|
|
18417
18764
|
}
|
|
18418
18765
|
|
|
18419
18766
|
/**
|
|
@@ -18536,7 +18883,6 @@ class StyledText extends FabricObject {
|
|
|
18536
18883
|
};
|
|
18537
18884
|
for (const p1 in obj) {
|
|
18538
18885
|
for (const p2 in obj[p1]) {
|
|
18539
|
-
// eslint-disable-next-line no-unused-vars
|
|
18540
18886
|
for (const p3 in obj[p1][p2]) {
|
|
18541
18887
|
return false;
|
|
18542
18888
|
}
|
|
@@ -18562,9 +18908,7 @@ class StyledText extends FabricObject {
|
|
|
18562
18908
|
const obj = typeof lineIndex === 'undefined' ? this.styles : {
|
|
18563
18909
|
0: this.styles[lineIndex]
|
|
18564
18910
|
};
|
|
18565
|
-
// eslint-disable-next-line
|
|
18566
18911
|
for (const p1 in obj) {
|
|
18567
|
-
// eslint-disable-next-line
|
|
18568
18912
|
for (const p2 in obj[p1]) {
|
|
18569
18913
|
if (typeof obj[p1][p2][property] !== 'undefined') {
|
|
18570
18914
|
return true;
|
|
@@ -18840,7 +19184,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
18840
19184
|
} = _ref;
|
|
18841
19185
|
const noShadow = true,
|
|
18842
19186
|
textDecoration = this.getSvgTextDecoration(this);
|
|
18843
|
-
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="
|
|
19187
|
+
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'];
|
|
18844
19188
|
}
|
|
18845
19189
|
|
|
18846
19190
|
/**
|
|
@@ -18856,7 +19200,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
18856
19200
|
lineOffset;
|
|
18857
19201
|
|
|
18858
19202
|
// bounding-box background
|
|
18859
|
-
this.backgroundColor && textBgRects.push(
|
|
19203
|
+
this.backgroundColor && textBgRects.push(createSVGInlineRect(this.backgroundColor, -this.width / 2, -this.height / 2, this.width, this.height));
|
|
18860
19204
|
|
|
18861
19205
|
// text and text-background
|
|
18862
19206
|
for (let i = 0, len = this._textLines.length; i < len; i++) {
|
|
@@ -18964,7 +19308,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
18964
19308
|
} = this.__charBounds[i][j];
|
|
18965
19309
|
currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');
|
|
18966
19310
|
if (currentColor !== lastColor) {
|
|
18967
|
-
lastColor && textBgRects.push(
|
|
19311
|
+
lastColor && textBgRects.push(createSVGInlineRect(lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine));
|
|
18968
19312
|
boxStart = left;
|
|
18969
19313
|
boxWidth = width;
|
|
18970
19314
|
lastColor = currentColor;
|
|
@@ -18972,7 +19316,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
18972
19316
|
boxWidth += kernedWidth;
|
|
18973
19317
|
}
|
|
18974
19318
|
}
|
|
18975
|
-
currentColor && textBgRects.push(
|
|
19319
|
+
currentColor && textBgRects.push(createSVGInlineRect(lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine));
|
|
18976
19320
|
}
|
|
18977
19321
|
|
|
18978
19322
|
/**
|
|
@@ -18999,7 +19343,6 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
18999
19343
|
fontSize,
|
|
19000
19344
|
fontStyle,
|
|
19001
19345
|
fontWeight,
|
|
19002
|
-
deltaY,
|
|
19003
19346
|
textDecorationThickness,
|
|
19004
19347
|
linethrough,
|
|
19005
19348
|
overline,
|
|
@@ -19011,7 +19354,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
19011
19354
|
linethrough: linethrough !== null && linethrough !== void 0 ? linethrough : this.linethrough
|
|
19012
19355
|
});
|
|
19013
19356
|
const thickness = textDecorationThickness || this.textDecorationThickness;
|
|
19014
|
-
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) : '',
|
|
19357
|
+
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('');
|
|
19015
19358
|
}
|
|
19016
19359
|
|
|
19017
19360
|
/**
|
|
@@ -24575,13 +24918,13 @@ class FabricImage extends FabricObject {
|
|
|
24575
24918
|
}
|
|
24576
24919
|
if (this.hasCrop()) {
|
|
24577
24920
|
const clipPathId = uid();
|
|
24578
|
-
svgString.push('<clipPath id="imageCrop_' + clipPathId + '">\n', '\t<rect x="' + x + '" y="' + y + '" width="' + this.width + '" height="' + this.height + '" />\n', '</clipPath>\n');
|
|
24921
|
+
svgString.push('<clipPath id="imageCrop_' + clipPathId + '">\n', '\t<rect x="' + x + '" y="' + y + '" width="' + escapeXml(this.width) + '" height="' + escapeXml(this.height) + '" />\n', '</clipPath>\n');
|
|
24579
24922
|
clipPath = ' clip-path="url(#imageCrop_' + clipPathId + ')" ';
|
|
24580
24923
|
}
|
|
24581
24924
|
if (!this.imageSmoothing) {
|
|
24582
24925
|
imageRendering = ' image-rendering="optimizeSpeed"';
|
|
24583
24926
|
}
|
|
24584
|
-
imageMarkup.push('\t<image ', 'COMMON_PARTS', `xlink:href="${this.
|
|
24927
|
+
imageMarkup.push('\t<image ', 'COMMON_PARTS', `xlink:href="${escapeXml(this.getSrc(true))}" x="${x - this.cropX}" y="${y - this.cropY
|
|
24585
24928
|
// we're essentially moving origin of transformation from top/left corner to the center of the shape
|
|
24586
24929
|
// by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left
|
|
24587
24930
|
// so that object's center aligns with container's left/top
|
|
@@ -24589,7 +24932,7 @@ class FabricImage extends FabricObject {
|
|
|
24589
24932
|
if (this.stroke || this.strokeDashArray) {
|
|
24590
24933
|
const origFill = this.fill;
|
|
24591
24934
|
this.fill = null;
|
|
24592
|
-
strokeSvg = [`\t<rect x="${x}" y="${y}" width="${this.width}" height="${this.height}" style="${this.getSvgStyles()}" />\n`];
|
|
24935
|
+
strokeSvg = [`\t<rect x="${x}" y="${y}" width="${escapeXml(this.width)}" height="${escapeXml(this.height)}" style="${this.getSvgStyles()}" />\n`];
|
|
24593
24936
|
this.fill = origFill;
|
|
24594
24937
|
}
|
|
24595
24938
|
if (this.paintFirst !== FILL) {
|
|
@@ -25572,258 +25915,6 @@ function loadSVGFromURL(url, reviver) {
|
|
|
25572
25915
|
});
|
|
25573
25916
|
}
|
|
25574
25917
|
|
|
25575
|
-
const ACTION_NAME$1 = MODIFY_POLY;
|
|
25576
|
-
/**
|
|
25577
|
-
* This function locates the controls.
|
|
25578
|
-
* It'll be used both for drawing and for interaction.
|
|
25579
|
-
*/
|
|
25580
|
-
const createPolyPositionHandler = pointIndex => {
|
|
25581
|
-
return function (dim, finalMatrix, polyObject) {
|
|
25582
|
-
const {
|
|
25583
|
-
points,
|
|
25584
|
-
pathOffset
|
|
25585
|
-
} = polyObject;
|
|
25586
|
-
return new Point(points[pointIndex]).subtract(pathOffset).transform(multiplyTransformMatrices(polyObject.getViewportTransform(), polyObject.calcTransformMatrix()));
|
|
25587
|
-
};
|
|
25588
|
-
};
|
|
25589
|
-
|
|
25590
|
-
/**
|
|
25591
|
-
* This function defines what the control does.
|
|
25592
|
-
* It'll be called on every mouse move after a control has been clicked and is being dragged.
|
|
25593
|
-
* The function receives as argument the mouse event, the current transform object
|
|
25594
|
-
* and the current position in canvas coordinate `transform.target` is a reference to the
|
|
25595
|
-
* current object being transformed.
|
|
25596
|
-
*/
|
|
25597
|
-
const polyActionHandler = (eventData, transform, x, y) => {
|
|
25598
|
-
const {
|
|
25599
|
-
target,
|
|
25600
|
-
pointIndex
|
|
25601
|
-
} = transform;
|
|
25602
|
-
const poly = target;
|
|
25603
|
-
const mouseLocalPosition = sendPointToPlane(new Point(x, y), undefined, poly.calcOwnMatrix());
|
|
25604
|
-
poly.points[pointIndex] = mouseLocalPosition.add(poly.pathOffset);
|
|
25605
|
-
poly.setDimensions();
|
|
25606
|
-
poly.set('dirty', true);
|
|
25607
|
-
return true;
|
|
25608
|
-
};
|
|
25609
|
-
|
|
25610
|
-
/**
|
|
25611
|
-
* Keep the polygon in the same position when we change its `width`/`height`/`top`/`left`.
|
|
25612
|
-
*/
|
|
25613
|
-
const factoryPolyActionHandler = (pointIndex, fn) => {
|
|
25614
|
-
return function (eventData, transform, x, y) {
|
|
25615
|
-
const poly = transform.target,
|
|
25616
|
-
anchorPoint = new Point(poly.points[(pointIndex > 0 ? pointIndex : poly.points.length) - 1]),
|
|
25617
|
-
anchorPointInParentPlane = anchorPoint.subtract(poly.pathOffset).transform(poly.calcOwnMatrix()),
|
|
25618
|
-
actionPerformed = fn(eventData, {
|
|
25619
|
-
...transform,
|
|
25620
|
-
pointIndex
|
|
25621
|
-
}, x, y);
|
|
25622
|
-
const newAnchorPointInParentPlane = anchorPoint.subtract(poly.pathOffset).transform(poly.calcOwnMatrix());
|
|
25623
|
-
const diff = newAnchorPointInParentPlane.subtract(anchorPointInParentPlane);
|
|
25624
|
-
poly.left -= diff.x;
|
|
25625
|
-
poly.top -= diff.y;
|
|
25626
|
-
return actionPerformed;
|
|
25627
|
-
};
|
|
25628
|
-
};
|
|
25629
|
-
const createPolyActionHandler = pointIndex => wrapWithFireEvent(ACTION_NAME$1, factoryPolyActionHandler(pointIndex, polyActionHandler));
|
|
25630
|
-
function createPolyControls(arg0) {
|
|
25631
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
25632
|
-
const controls = {};
|
|
25633
|
-
for (let idx = 0; idx < (typeof arg0 === 'number' ? arg0 : arg0.points.length); idx++) {
|
|
25634
|
-
controls[`p${idx}`] = new Control({
|
|
25635
|
-
actionName: ACTION_NAME$1,
|
|
25636
|
-
positionHandler: createPolyPositionHandler(idx),
|
|
25637
|
-
actionHandler: createPolyActionHandler(idx),
|
|
25638
|
-
...options
|
|
25639
|
-
});
|
|
25640
|
-
}
|
|
25641
|
-
return controls;
|
|
25642
|
-
}
|
|
25643
|
-
|
|
25644
|
-
const ACTION_NAME = 'modifyPath';
|
|
25645
|
-
const calcPathPointPosition = (pathObject, commandIndex, pointIndex) => {
|
|
25646
|
-
const {
|
|
25647
|
-
path,
|
|
25648
|
-
pathOffset
|
|
25649
|
-
} = pathObject;
|
|
25650
|
-
const command = path[commandIndex];
|
|
25651
|
-
return new Point(command[pointIndex] - pathOffset.x, command[pointIndex + 1] - pathOffset.y).transform(multiplyTransformMatrices(pathObject.getViewportTransform(), pathObject.calcTransformMatrix()));
|
|
25652
|
-
};
|
|
25653
|
-
const movePathPoint = (pathObject, x, y, commandIndex, pointIndex) => {
|
|
25654
|
-
const {
|
|
25655
|
-
path,
|
|
25656
|
-
pathOffset
|
|
25657
|
-
} = pathObject;
|
|
25658
|
-
const anchorCommand = path[(commandIndex > 0 ? commandIndex : path.length) - 1];
|
|
25659
|
-
const anchorPoint = new Point(anchorCommand[pointIndex], anchorCommand[pointIndex + 1]);
|
|
25660
|
-
const anchorPointInParentPlane = anchorPoint.subtract(pathOffset).transform(pathObject.calcOwnMatrix());
|
|
25661
|
-
const mouseLocalPosition = sendPointToPlane(new Point(x, y), undefined, pathObject.calcOwnMatrix());
|
|
25662
|
-
path[commandIndex][pointIndex] = mouseLocalPosition.x + pathOffset.x;
|
|
25663
|
-
path[commandIndex][pointIndex + 1] = mouseLocalPosition.y + pathOffset.y;
|
|
25664
|
-
pathObject.setDimensions();
|
|
25665
|
-
const newAnchorPointInParentPlane = anchorPoint.subtract(pathObject.pathOffset).transform(pathObject.calcOwnMatrix());
|
|
25666
|
-
const diff = newAnchorPointInParentPlane.subtract(anchorPointInParentPlane);
|
|
25667
|
-
pathObject.left -= diff.x;
|
|
25668
|
-
pathObject.top -= diff.y;
|
|
25669
|
-
pathObject.set('dirty', true);
|
|
25670
|
-
return true;
|
|
25671
|
-
};
|
|
25672
|
-
|
|
25673
|
-
/**
|
|
25674
|
-
* This function locates the controls.
|
|
25675
|
-
* It'll be used both for drawing and for interaction.
|
|
25676
|
-
*/
|
|
25677
|
-
function pathPositionHandler(dim, finalMatrix, pathObject) {
|
|
25678
|
-
const {
|
|
25679
|
-
commandIndex,
|
|
25680
|
-
pointIndex
|
|
25681
|
-
} = this;
|
|
25682
|
-
return calcPathPointPosition(pathObject, commandIndex, pointIndex);
|
|
25683
|
-
}
|
|
25684
|
-
|
|
25685
|
-
/**
|
|
25686
|
-
* This function defines what the control does.
|
|
25687
|
-
* It'll be called on every mouse move after a control has been clicked and is being dragged.
|
|
25688
|
-
* The function receives as argument the mouse event, the current transform object
|
|
25689
|
-
* and the current position in canvas coordinate `transform.target` is a reference to the
|
|
25690
|
-
* current object being transformed.
|
|
25691
|
-
*/
|
|
25692
|
-
function pathActionHandler(eventData, transform, x, y) {
|
|
25693
|
-
const {
|
|
25694
|
-
target
|
|
25695
|
-
} = transform;
|
|
25696
|
-
const {
|
|
25697
|
-
commandIndex,
|
|
25698
|
-
pointIndex
|
|
25699
|
-
} = this;
|
|
25700
|
-
const actionPerformed = movePathPoint(target, x, y, commandIndex, pointIndex);
|
|
25701
|
-
{
|
|
25702
|
-
fireEvent(this.actionName, {
|
|
25703
|
-
...commonEventInfo(eventData, transform, x, y),
|
|
25704
|
-
commandIndex,
|
|
25705
|
-
pointIndex
|
|
25706
|
-
});
|
|
25707
|
-
}
|
|
25708
|
-
return actionPerformed;
|
|
25709
|
-
}
|
|
25710
|
-
const indexFromPrevCommand = previousCommandType => previousCommandType === 'C' ? 5 : previousCommandType === 'Q' ? 3 : 1;
|
|
25711
|
-
class PathPointControl extends Control {
|
|
25712
|
-
constructor(options) {
|
|
25713
|
-
super(options);
|
|
25714
|
-
}
|
|
25715
|
-
render(ctx, left, top, styleOverride, fabricObject) {
|
|
25716
|
-
const overrides = {
|
|
25717
|
-
...styleOverride,
|
|
25718
|
-
cornerColor: this.controlFill,
|
|
25719
|
-
cornerStrokeColor: this.controlStroke,
|
|
25720
|
-
transparentCorners: !this.controlFill
|
|
25721
|
-
};
|
|
25722
|
-
super.render(ctx, left, top, overrides, fabricObject);
|
|
25723
|
-
}
|
|
25724
|
-
}
|
|
25725
|
-
class PathControlPointControl extends PathPointControl {
|
|
25726
|
-
constructor(options) {
|
|
25727
|
-
super(options);
|
|
25728
|
-
}
|
|
25729
|
-
render(ctx, left, top, styleOverride, fabricObject) {
|
|
25730
|
-
const {
|
|
25731
|
-
path
|
|
25732
|
-
} = fabricObject;
|
|
25733
|
-
const {
|
|
25734
|
-
commandIndex,
|
|
25735
|
-
pointIndex,
|
|
25736
|
-
connectToCommandIndex,
|
|
25737
|
-
connectToPointIndex
|
|
25738
|
-
} = this;
|
|
25739
|
-
ctx.save();
|
|
25740
|
-
ctx.strokeStyle = this.controlStroke;
|
|
25741
|
-
if (this.connectionDashArray) {
|
|
25742
|
-
ctx.setLineDash(this.connectionDashArray);
|
|
25743
|
-
}
|
|
25744
|
-
const [commandType] = path[commandIndex];
|
|
25745
|
-
const point = calcPathPointPosition(fabricObject, connectToCommandIndex, connectToPointIndex);
|
|
25746
|
-
if (commandType === 'Q') {
|
|
25747
|
-
// one control point connects to 2 points
|
|
25748
|
-
const point2 = calcPathPointPosition(fabricObject, commandIndex, pointIndex + 2);
|
|
25749
|
-
ctx.moveTo(point2.x, point2.y);
|
|
25750
|
-
ctx.lineTo(left, top);
|
|
25751
|
-
} else {
|
|
25752
|
-
ctx.moveTo(left, top);
|
|
25753
|
-
}
|
|
25754
|
-
ctx.lineTo(point.x, point.y);
|
|
25755
|
-
ctx.stroke();
|
|
25756
|
-
ctx.restore();
|
|
25757
|
-
super.render(ctx, left, top, styleOverride, fabricObject);
|
|
25758
|
-
}
|
|
25759
|
-
}
|
|
25760
|
-
const createControl = (commandIndexPos, pointIndexPos, isControlPoint, options, connectToCommandIndex, connectToPointIndex) => new (isControlPoint ? PathControlPointControl : PathPointControl)({
|
|
25761
|
-
commandIndex: commandIndexPos,
|
|
25762
|
-
pointIndex: pointIndexPos,
|
|
25763
|
-
actionName: ACTION_NAME,
|
|
25764
|
-
positionHandler: pathPositionHandler,
|
|
25765
|
-
actionHandler: pathActionHandler,
|
|
25766
|
-
connectToCommandIndex,
|
|
25767
|
-
connectToPointIndex,
|
|
25768
|
-
...options,
|
|
25769
|
-
...(isControlPoint ? options.controlPointStyle : options.pointStyle)
|
|
25770
|
-
});
|
|
25771
|
-
function createPathControls(path) {
|
|
25772
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
25773
|
-
const controls = {};
|
|
25774
|
-
let previousCommandType = 'M';
|
|
25775
|
-
path.path.forEach((command, commandIndex) => {
|
|
25776
|
-
const commandType = command[0];
|
|
25777
|
-
if (commandType !== 'Z') {
|
|
25778
|
-
controls[`c_${commandIndex}_${commandType}`] = createControl(commandIndex, command.length - 2, false, options);
|
|
25779
|
-
}
|
|
25780
|
-
switch (commandType) {
|
|
25781
|
-
case 'C':
|
|
25782
|
-
controls[`c_${commandIndex}_C_CP_1`] = createControl(commandIndex, 1, true, options, commandIndex - 1, indexFromPrevCommand(previousCommandType));
|
|
25783
|
-
controls[`c_${commandIndex}_C_CP_2`] = createControl(commandIndex, 3, true, options, commandIndex, 5);
|
|
25784
|
-
break;
|
|
25785
|
-
case 'Q':
|
|
25786
|
-
controls[`c_${commandIndex}_Q_CP_1`] = createControl(commandIndex, 1, true, options, commandIndex, 3);
|
|
25787
|
-
break;
|
|
25788
|
-
}
|
|
25789
|
-
previousCommandType = commandType;
|
|
25790
|
-
});
|
|
25791
|
-
return controls;
|
|
25792
|
-
}
|
|
25793
|
-
|
|
25794
|
-
var index = /*#__PURE__*/Object.freeze({
|
|
25795
|
-
__proto__: null,
|
|
25796
|
-
changeWidth: changeWidth,
|
|
25797
|
-
createObjectDefaultControls: createObjectDefaultControls,
|
|
25798
|
-
createPathControls: createPathControls,
|
|
25799
|
-
createPolyActionHandler: createPolyActionHandler,
|
|
25800
|
-
createPolyControls: createPolyControls,
|
|
25801
|
-
createPolyPositionHandler: createPolyPositionHandler,
|
|
25802
|
-
createResizeControls: createResizeControls,
|
|
25803
|
-
createTextboxDefaultControls: createTextboxDefaultControls,
|
|
25804
|
-
dragHandler: dragHandler,
|
|
25805
|
-
factoryPolyActionHandler: factoryPolyActionHandler,
|
|
25806
|
-
getLocalPoint: getLocalPoint,
|
|
25807
|
-
polyActionHandler: polyActionHandler,
|
|
25808
|
-
renderCircleControl: renderCircleControl,
|
|
25809
|
-
renderSquareControl: renderSquareControl,
|
|
25810
|
-
rotationStyleHandler: rotationStyleHandler,
|
|
25811
|
-
rotationWithSnapping: rotationWithSnapping,
|
|
25812
|
-
scaleCursorStyleHandler: scaleCursorStyleHandler,
|
|
25813
|
-
scaleOrSkewActionName: scaleOrSkewActionName,
|
|
25814
|
-
scaleSkewCursorStyleHandler: scaleSkewCursorStyleHandler,
|
|
25815
|
-
scalingEqually: scalingEqually,
|
|
25816
|
-
scalingX: scalingX,
|
|
25817
|
-
scalingXOrSkewingY: scalingXOrSkewingY,
|
|
25818
|
-
scalingY: scalingY,
|
|
25819
|
-
scalingYOrSkewingX: scalingYOrSkewingX,
|
|
25820
|
-
skewCursorStyleHandler: skewCursorStyleHandler,
|
|
25821
|
-
skewHandlerX: skewHandlerX,
|
|
25822
|
-
skewHandlerY: skewHandlerY,
|
|
25823
|
-
wrapWithFireEvent: wrapWithFireEvent,
|
|
25824
|
-
wrapWithFixedAnchor: wrapWithFixedAnchor
|
|
25825
|
-
});
|
|
25826
|
-
|
|
25827
25918
|
const isWebGLPipelineState = options => {
|
|
25828
25919
|
return options.webgl !== undefined;
|
|
25829
25920
|
};
|