fabric 7.1.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 +13 -0
- package/dist/extensions/cropping_controls/croppingControls.d.ts +12 -8
- package/dist/extensions/cropping_controls/croppingControls.d.ts.map +1 -1
- package/dist/extensions/cropping_controls/croppingHandlers.d.ts +19 -1
- package/dist/extensions/cropping_controls/croppingHandlers.d.ts.map +1 -1
- package/dist/extensions/cropping_controls/enterCropMode.d.ts.map +1 -1
- package/dist/index.js +189 -160
- 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 +189 -160
- package/dist/index.mjs.map +1 -1
- package/dist/index.node.cjs +189 -160
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +189 -160
- 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 +3 -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 +6 -1
- 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/controls/Control.d.ts +9 -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 +8 -0
- package/dist/src/controls/Control.mjs.map +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/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/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.min.mjs +1 -1
- package/dist/src/shapes/Text/TextSVGExportMixin.min.mjs.map +1 -1
- package/dist/src/shapes/Text/TextSVGExportMixin.mjs +5 -5
- 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 +39 -9
- package/dist-extensions/cropping_controls/croppingControls.mjs.map +1 -1
- package/dist-extensions/cropping_controls/croppingHandlers.mjs +84 -2
- package/dist-extensions/cropping_controls/croppingHandlers.mjs.map +1 -1
- package/dist-extensions/cropping_controls/enterCropMode.mjs +7 -2
- package/dist-extensions/cropping_controls/enterCropMode.mjs.map +1 -1
- package/dist-extensions/extensions/cropping_controls/croppingControls.d.ts +12 -8
- package/dist-extensions/extensions/cropping_controls/croppingControls.d.ts.map +1 -1
- package/dist-extensions/extensions/cropping_controls/croppingHandlers.d.ts +19 -1
- package/dist-extensions/extensions/cropping_controls/croppingHandlers.d.ts.map +1 -1
- package/dist-extensions/extensions/cropping_controls/enterCropMode.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/src/EventTypeDefs.d.ts +3 -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/controls/Control.d.ts +9 -1
- package/dist-extensions/src/controls/Control.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/Text.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 +65 -27
- package/extensions/cropping_controls/croppingControls.ts +40 -8
- package/extensions/cropping_controls/croppingHandlers.spec.ts +355 -46
- package/extensions/cropping_controls/croppingHandlers.ts +123 -0
- package/extensions/cropping_controls/enterCropMode.ts +6 -2
- package/package.json +17 -8
- package/src/ClassRegistry.spec.ts +18 -19
- package/src/EventTypeDefs.ts +13 -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 +11 -4
- package/src/canvas/StaticCanvas.spec.ts +20 -0
- package/src/canvas/StaticCanvas.ts +7 -4
- package/src/canvas/StaticCanvasOptions.ts +1 -3
- package/src/controls/Control.ts +24 -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/__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/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/Text.spec.ts +3 -32
- package/src/shapes/Text/Text.ts +5 -6
- package/src/shapes/Text/TextSVGExportMixin.ts +14 -14
- package/src/shapes/Text/__snapshots__/Text.spec.ts.snap +1 -1
- package/src/shapes/Textbox.spec.ts +5 -5
- package/src/shapes/Textbox.ts +6 -5
- package/src/shapes/Triangle.ts +4 -4
- package/src/shapes/__snapshots__/Image.spec.ts.snap +4 -4
- package/src/shapes/__snapshots__/Textbox.spec.ts.snap +5 -5
- package/src/util/lang_string.ts +3 -2
- package/src/util/misc/svgParsing.ts +2 -1
- package/tsconfig.spec.json +1 -0
- package/vitest.config.ts +12 -2
- package/vitest.extend.ts +6 -2
package/dist/index.mjs
CHANGED
|
@@ -356,7 +356,7 @@ class Cache {
|
|
|
356
356
|
}
|
|
357
357
|
const cache = new Cache();
|
|
358
358
|
|
|
359
|
-
var version = "7.
|
|
359
|
+
var version = "7.2.0";
|
|
360
360
|
|
|
361
361
|
// use this syntax so babel plugin see this import here
|
|
362
362
|
const VERSION = version;
|
|
@@ -2191,6 +2191,111 @@ const staticCanvasDefaults = {
|
|
|
2191
2191
|
patternQuality: 'best'
|
|
2192
2192
|
};
|
|
2193
2193
|
|
|
2194
|
+
/**
|
|
2195
|
+
* Capitalizes a string
|
|
2196
|
+
* @param {String} string String to capitalize
|
|
2197
|
+
* @param {Boolean} [firstLetterOnly] If true only first letter is capitalized
|
|
2198
|
+
* and other letters stay untouched, if false first letter is capitalized
|
|
2199
|
+
* and other letters are converted to lowercase.
|
|
2200
|
+
* @return {String} Capitalized version of a string
|
|
2201
|
+
*/
|
|
2202
|
+
const capitalize = function (string) {
|
|
2203
|
+
let firstLetterOnly = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
2204
|
+
return `${string.charAt(0).toUpperCase()}${firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase()}`;
|
|
2205
|
+
};
|
|
2206
|
+
|
|
2207
|
+
/**
|
|
2208
|
+
* Escapes XML in a string
|
|
2209
|
+
* @param {String} string String to escape
|
|
2210
|
+
* @return {String} Escaped version of a string
|
|
2211
|
+
*/
|
|
2212
|
+
const escapeXml = stringOrNumber => stringOrNumber.toString().replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>');
|
|
2213
|
+
let segmenter;
|
|
2214
|
+
const getSegmenter = () => {
|
|
2215
|
+
if (!segmenter) {
|
|
2216
|
+
segmenter = 'Intl' in getFabricWindow() && 'Segmenter' in Intl && new Intl.Segmenter(undefined, {
|
|
2217
|
+
granularity: 'grapheme'
|
|
2218
|
+
});
|
|
2219
|
+
}
|
|
2220
|
+
return segmenter;
|
|
2221
|
+
};
|
|
2222
|
+
|
|
2223
|
+
/**
|
|
2224
|
+
* Divide a string in the user perceived single units
|
|
2225
|
+
* @param {String} textstring String to escape
|
|
2226
|
+
* @return {Array} array containing the graphemes
|
|
2227
|
+
*/
|
|
2228
|
+
const graphemeSplit = textstring => {
|
|
2229
|
+
segmenter || getSegmenter();
|
|
2230
|
+
if (segmenter) {
|
|
2231
|
+
const segments = segmenter.segment(textstring);
|
|
2232
|
+
return Array.from(segments).map(_ref => {
|
|
2233
|
+
let {
|
|
2234
|
+
segment
|
|
2235
|
+
} = _ref;
|
|
2236
|
+
return segment;
|
|
2237
|
+
});
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2240
|
+
//Fallback
|
|
2241
|
+
return graphemeSplitImpl(textstring);
|
|
2242
|
+
};
|
|
2243
|
+
const graphemeSplitImpl = textstring => {
|
|
2244
|
+
const graphemes = [];
|
|
2245
|
+
for (let i = 0, chr; i < textstring.length; i++) {
|
|
2246
|
+
if ((chr = getWholeChar(textstring, i)) === false) {
|
|
2247
|
+
continue;
|
|
2248
|
+
}
|
|
2249
|
+
graphemes.push(chr);
|
|
2250
|
+
}
|
|
2251
|
+
return graphemes;
|
|
2252
|
+
};
|
|
2253
|
+
|
|
2254
|
+
// taken from mdn in the charAt doc page.
|
|
2255
|
+
const getWholeChar = (str, i) => {
|
|
2256
|
+
const code = str.charCodeAt(i);
|
|
2257
|
+
if (isNaN(code)) {
|
|
2258
|
+
return ''; // Position not found
|
|
2259
|
+
}
|
|
2260
|
+
if (code < 0xd800 || code > 0xdfff) {
|
|
2261
|
+
return str.charAt(i);
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
// High surrogate (could change last hex to 0xDB7F to treat high private
|
|
2265
|
+
// surrogates as single characters)
|
|
2266
|
+
if (0xd800 <= code && code <= 0xdbff) {
|
|
2267
|
+
if (str.length <= i + 1) {
|
|
2268
|
+
throw 'High surrogate without following low surrogate';
|
|
2269
|
+
}
|
|
2270
|
+
const next = str.charCodeAt(i + 1);
|
|
2271
|
+
if (0xdc00 > next || next > 0xdfff) {
|
|
2272
|
+
throw 'High surrogate without following low surrogate';
|
|
2273
|
+
}
|
|
2274
|
+
return str.charAt(i) + str.charAt(i + 1);
|
|
2275
|
+
}
|
|
2276
|
+
// Low surrogate (0xDC00 <= code && code <= 0xDFFF)
|
|
2277
|
+
if (i === 0) {
|
|
2278
|
+
throw 'Low surrogate without preceding high surrogate';
|
|
2279
|
+
}
|
|
2280
|
+
const prev = str.charCodeAt(i - 1);
|
|
2281
|
+
|
|
2282
|
+
// (could change last hex to 0xDB7F to treat high private
|
|
2283
|
+
// surrogates as single characters)
|
|
2284
|
+
if (0xd800 > prev || prev > 0xdbff) {
|
|
2285
|
+
throw 'Low surrogate without preceding high surrogate';
|
|
2286
|
+
}
|
|
2287
|
+
// We can pass over low surrogates now as the second component
|
|
2288
|
+
// in a pair which we have already processed
|
|
2289
|
+
return false;
|
|
2290
|
+
};
|
|
2291
|
+
|
|
2292
|
+
var lang_string = /*#__PURE__*/Object.freeze({
|
|
2293
|
+
__proto__: null,
|
|
2294
|
+
capitalize: capitalize,
|
|
2295
|
+
escapeXml: escapeXml,
|
|
2296
|
+
graphemeSplit: graphemeSplit
|
|
2297
|
+
});
|
|
2298
|
+
|
|
2194
2299
|
/**
|
|
2195
2300
|
* Having both options in TCanvasSizeOptions set to true transform the call in a calcOffset
|
|
2196
2301
|
* Better try to restrict with types to avoid confusion.
|
|
@@ -2960,7 +3065,8 @@ class StaticCanvas extends createCollectionMixin(CommonMethods) {
|
|
|
2960
3065
|
this._setSVGPreamble(markup, options);
|
|
2961
3066
|
this._setSVGHeader(markup, options);
|
|
2962
3067
|
if (this.clipPath) {
|
|
2963
|
-
|
|
3068
|
+
var _this$clipPath$clipPa;
|
|
3069
|
+
markup.push(`<g clip-path="url(#${escapeXml((_this$clipPath$clipPa = this.clipPath.clipPathId) !== null && _this$clipPath$clipPa !== void 0 ? _this$clipPath$clipPa : '')})" >\n`);
|
|
2964
3070
|
}
|
|
2965
3071
|
this._setSVGBgOverlayColor(markup, 'background');
|
|
2966
3072
|
this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);
|
|
@@ -4587,7 +4693,7 @@ const colorPropToSVG = function (prop, value) {
|
|
|
4587
4693
|
if (!value) {
|
|
4588
4694
|
colorValue = 'none';
|
|
4589
4695
|
} else if (value.toLive) {
|
|
4590
|
-
colorValue = `url(#SVGID_${value.id})`;
|
|
4696
|
+
colorValue = `url(#SVGID_${escapeXml(value.id)})`;
|
|
4591
4697
|
} else {
|
|
4592
4698
|
const color = new Color(value),
|
|
4593
4699
|
opacity = color.getAlpha();
|
|
@@ -4640,7 +4746,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4640
4746
|
filter = skipShadow ? '' : this.getSvgFilter(),
|
|
4641
4747
|
fill = colorPropToSVG(FILL, this.fill),
|
|
4642
4748
|
stroke = colorPropToSVG(STROKE, this.stroke);
|
|
4643
|
-
return [stroke, 'stroke-width: ', strokeWidth, '; ', 'stroke-dasharray: ', strokeDashArray, '; ', 'stroke-linecap: ', strokeLineCap, '; ', 'stroke-dashoffset: ', strokeDashOffset, '; ', 'stroke-linejoin: ', strokeLineJoin, '; ', 'stroke-miterlimit: ', strokeMiterLimit, '; ', fill, 'fill-rule: ', fillRule, '; ', 'opacity: ', opacity, ';', filter, visibility].join('');
|
|
4749
|
+
return [stroke, 'stroke-width: ', strokeWidth, '; ', 'stroke-dasharray: ', strokeDashArray, '; ', 'stroke-linecap: ', strokeLineCap, '; ', 'stroke-dashoffset: ', strokeDashOffset, '; ', 'stroke-linejoin: ', strokeLineJoin, '; ', 'stroke-miterlimit: ', strokeMiterLimit, '; ', fill, 'fill-rule: ', fillRule, '; ', 'opacity: ', opacity, ';', filter, visibility].map(v => escapeXml(v)).join('');
|
|
4644
4750
|
}
|
|
4645
4751
|
|
|
4646
4752
|
/**
|
|
@@ -4648,7 +4754,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4648
4754
|
* @return {String}
|
|
4649
4755
|
*/
|
|
4650
4756
|
getSvgFilter() {
|
|
4651
|
-
return this.shadow ? `filter: url(#SVGID_${this.shadow.id});` : '';
|
|
4757
|
+
return this.shadow ? `filter: url(#SVGID_${escapeXml(this.shadow.id)});` : '';
|
|
4652
4758
|
}
|
|
4653
4759
|
|
|
4654
4760
|
/**
|
|
@@ -4656,7 +4762,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4656
4762
|
* @return {String}
|
|
4657
4763
|
*/
|
|
4658
4764
|
getSvgCommons() {
|
|
4659
|
-
return [this.id ? `id="${this.id}" ` : '', this.clipPath ? `clip-path="url(#${this.clipPath.clipPathId})" ` : ''].join('');
|
|
4765
|
+
return [this.id ? `id="${escapeXml(String(this.id))}" ` : '', this.clipPath ? `clip-path="url(#${this.clipPath.clipPathId})" ` : ''].join('');
|
|
4660
4766
|
}
|
|
4661
4767
|
|
|
4662
4768
|
/**
|
|
@@ -4769,7 +4875,7 @@ class FabricObjectSVGExportMixin {
|
|
|
4769
4875
|
return reviver ? reviver(markup.join('')) : markup.join('');
|
|
4770
4876
|
}
|
|
4771
4877
|
addPaintOrder() {
|
|
4772
|
-
return this.paintFirst !== FILL ? ` paint-order="${this.paintFirst}" ` : '';
|
|
4878
|
+
return this.paintFirst !== FILL ? ` paint-order="${escapeXml(this.paintFirst)}" ` : '';
|
|
4773
4879
|
}
|
|
4774
4880
|
}
|
|
4775
4881
|
|
|
@@ -4907,7 +5013,6 @@ const reViewBoxAttrValue = new RegExp(String.raw`^\s*(${reNum})${viewportSeparat
|
|
|
4907
5013
|
|
|
4908
5014
|
(?:$|\s): This captures either the end of the line or a whitespace character. It ensures that the match ends either at the end of the string or with a whitespace character.
|
|
4909
5015
|
*/
|
|
4910
|
-
// eslint-disable-next-line max-len
|
|
4911
5016
|
|
|
4912
5017
|
const shadowOffsetRegex = '(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?';
|
|
4913
5018
|
const reOffsetsAndBlur = new RegExp('(?:\\s|^)' + shadowOffsetRegex + shadowOffsetRegex + '(' + reNum + '?(?:px)?)?(?:\\s?|$)(?:$|\\s)');
|
|
@@ -4966,14 +5071,15 @@ class Shadow {
|
|
|
4966
5071
|
toSVG(object) {
|
|
4967
5072
|
const offset = rotateVector(new Point(this.offsetX, this.offsetY), degreesToRadians(-object.angle)),
|
|
4968
5073
|
BLUR_BOX = 20,
|
|
5074
|
+
NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS,
|
|
4969
5075
|
color = new Color(this.color);
|
|
4970
5076
|
let fBoxX = 40,
|
|
4971
5077
|
fBoxY = 40;
|
|
4972
5078
|
if (object.width && object.height) {
|
|
4973
5079
|
//http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
|
|
4974
5080
|
// we add some extra space to filter box to contain the blur ( 20 )
|
|
4975
|
-
fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width,
|
|
4976
|
-
fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height,
|
|
5081
|
+
fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;
|
|
5082
|
+
fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX;
|
|
4977
5083
|
}
|
|
4978
5084
|
if (object.flipX) {
|
|
4979
5085
|
offset.x *= -1;
|
|
@@ -4981,7 +5087,7 @@ class Shadow {
|
|
|
4981
5087
|
if (object.flipY) {
|
|
4982
5088
|
offset.y *= -1;
|
|
4983
5089
|
}
|
|
4984
|
-
return `<filter id="SVGID_${this.id}" y="-${fBoxY}%" height="${100 + 2 * fBoxY}%" x="-${fBoxX}%" width="${100 + 2 * fBoxX}%" >\n\t<feGaussianBlur in="SourceAlpha" stdDeviation="${toFixed(this.blur ? this.blur / 2 : 0,
|
|
5090
|
+
return `<filter id="SVGID_${escapeXml(this.id)}" y="-${fBoxY}%" height="${100 + 2 * fBoxY}%" x="-${fBoxX}%" width="${100 + 2 * fBoxX}%" >\n\t<feGaussianBlur in="SourceAlpha" stdDeviation="${toFixed(this.blur ? this.blur / 2 : 0, NUM_FRACTION_DIGITS)}"></feGaussianBlur>\n\t<feOffset dx="${toFixed(offset.x, NUM_FRACTION_DIGITS)}" dy="${toFixed(offset.y, NUM_FRACTION_DIGITS)}" result="oBlur" ></feOffset>\n\t<feFlood flood-color="${color.toRgb()}" flood-opacity="${color.getAlpha()}"/>\n\t<feComposite in2="oBlur" operator="in" />\n\t<feMerge>\n\t\t<feMergeNode></feMergeNode>\n\t\t<feMergeNode in="SourceGraphic"></feMergeNode>\n\t</feMerge>\n</filter>\n`;
|
|
4985
5091
|
}
|
|
4986
5092
|
|
|
4987
5093
|
/**
|
|
@@ -7132,6 +7238,9 @@ let FabricObject$1 = class FabricObject extends ObjectGeometry {
|
|
|
7132
7238
|
} else {
|
|
7133
7239
|
this._renderBackground(ctx);
|
|
7134
7240
|
}
|
|
7241
|
+
this.fire('before:render', {
|
|
7242
|
+
ctx
|
|
7243
|
+
});
|
|
7135
7244
|
this._render(ctx);
|
|
7136
7245
|
this._drawClipPath(ctx, this.clipPath, context);
|
|
7137
7246
|
this.fill = originalFill;
|
|
@@ -8422,6 +8531,14 @@ class Control {
|
|
|
8422
8531
|
_defineProperty(this, "withConnection", false);
|
|
8423
8532
|
Object.assign(this, options);
|
|
8424
8533
|
}
|
|
8534
|
+
getTransformAnchorPoint() {
|
|
8535
|
+
var _this$transformAnchor;
|
|
8536
|
+
return (// return the control transformAnchorPoint
|
|
8537
|
+
(_this$transformAnchor = this.transformAnchorPoint) !== null && _this$transformAnchor !== void 0 ? _this$transformAnchor :
|
|
8538
|
+
// otherwise will return the opposite origin of where the control is located.
|
|
8539
|
+
new Point(-this.x + 0.5, -this.y + 0.5)
|
|
8540
|
+
);
|
|
8541
|
+
}
|
|
8425
8542
|
|
|
8426
8543
|
/**
|
|
8427
8544
|
* The control actionHandler, provide one to handle action ( control being moved )
|
|
@@ -10237,111 +10354,6 @@ const cloneStyles = style => {
|
|
|
10237
10354
|
return newObj;
|
|
10238
10355
|
};
|
|
10239
10356
|
|
|
10240
|
-
/**
|
|
10241
|
-
* Capitalizes a string
|
|
10242
|
-
* @param {String} string String to capitalize
|
|
10243
|
-
* @param {Boolean} [firstLetterOnly] If true only first letter is capitalized
|
|
10244
|
-
* and other letters stay untouched, if false first letter is capitalized
|
|
10245
|
-
* and other letters are converted to lowercase.
|
|
10246
|
-
* @return {String} Capitalized version of a string
|
|
10247
|
-
*/
|
|
10248
|
-
const capitalize = function (string) {
|
|
10249
|
-
let firstLetterOnly = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
10250
|
-
return `${string.charAt(0).toUpperCase()}${firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase()}`;
|
|
10251
|
-
};
|
|
10252
|
-
|
|
10253
|
-
/**
|
|
10254
|
-
* Escapes XML in a string
|
|
10255
|
-
* @param {String} string String to escape
|
|
10256
|
-
* @return {String} Escaped version of a string
|
|
10257
|
-
*/
|
|
10258
|
-
const escapeXml = string => string.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>');
|
|
10259
|
-
let segmenter;
|
|
10260
|
-
const getSegmenter = () => {
|
|
10261
|
-
if (!segmenter) {
|
|
10262
|
-
segmenter = 'Intl' in getFabricWindow() && 'Segmenter' in Intl && new Intl.Segmenter(undefined, {
|
|
10263
|
-
granularity: 'grapheme'
|
|
10264
|
-
});
|
|
10265
|
-
}
|
|
10266
|
-
return segmenter;
|
|
10267
|
-
};
|
|
10268
|
-
|
|
10269
|
-
/**
|
|
10270
|
-
* Divide a string in the user perceived single units
|
|
10271
|
-
* @param {String} textstring String to escape
|
|
10272
|
-
* @return {Array} array containing the graphemes
|
|
10273
|
-
*/
|
|
10274
|
-
const graphemeSplit = textstring => {
|
|
10275
|
-
segmenter || getSegmenter();
|
|
10276
|
-
if (segmenter) {
|
|
10277
|
-
const segments = segmenter.segment(textstring);
|
|
10278
|
-
return Array.from(segments).map(_ref => {
|
|
10279
|
-
let {
|
|
10280
|
-
segment
|
|
10281
|
-
} = _ref;
|
|
10282
|
-
return segment;
|
|
10283
|
-
});
|
|
10284
|
-
}
|
|
10285
|
-
|
|
10286
|
-
//Fallback
|
|
10287
|
-
return graphemeSplitImpl(textstring);
|
|
10288
|
-
};
|
|
10289
|
-
const graphemeSplitImpl = textstring => {
|
|
10290
|
-
const graphemes = [];
|
|
10291
|
-
for (let i = 0, chr; i < textstring.length; i++) {
|
|
10292
|
-
if ((chr = getWholeChar(textstring, i)) === false) {
|
|
10293
|
-
continue;
|
|
10294
|
-
}
|
|
10295
|
-
graphemes.push(chr);
|
|
10296
|
-
}
|
|
10297
|
-
return graphemes;
|
|
10298
|
-
};
|
|
10299
|
-
|
|
10300
|
-
// taken from mdn in the charAt doc page.
|
|
10301
|
-
const getWholeChar = (str, i) => {
|
|
10302
|
-
const code = str.charCodeAt(i);
|
|
10303
|
-
if (isNaN(code)) {
|
|
10304
|
-
return ''; // Position not found
|
|
10305
|
-
}
|
|
10306
|
-
if (code < 0xd800 || code > 0xdfff) {
|
|
10307
|
-
return str.charAt(i);
|
|
10308
|
-
}
|
|
10309
|
-
|
|
10310
|
-
// High surrogate (could change last hex to 0xDB7F to treat high private
|
|
10311
|
-
// surrogates as single characters)
|
|
10312
|
-
if (0xd800 <= code && code <= 0xdbff) {
|
|
10313
|
-
if (str.length <= i + 1) {
|
|
10314
|
-
throw 'High surrogate without following low surrogate';
|
|
10315
|
-
}
|
|
10316
|
-
const next = str.charCodeAt(i + 1);
|
|
10317
|
-
if (0xdc00 > next || next > 0xdfff) {
|
|
10318
|
-
throw 'High surrogate without following low surrogate';
|
|
10319
|
-
}
|
|
10320
|
-
return str.charAt(i) + str.charAt(i + 1);
|
|
10321
|
-
}
|
|
10322
|
-
// Low surrogate (0xDC00 <= code && code <= 0xDFFF)
|
|
10323
|
-
if (i === 0) {
|
|
10324
|
-
throw 'Low surrogate without preceding high surrogate';
|
|
10325
|
-
}
|
|
10326
|
-
const prev = str.charCodeAt(i - 1);
|
|
10327
|
-
|
|
10328
|
-
// (could change last hex to 0xDB7F to treat high private
|
|
10329
|
-
// surrogates as single characters)
|
|
10330
|
-
if (0xd800 > prev || prev > 0xdbff) {
|
|
10331
|
-
throw 'Low surrogate without preceding high surrogate';
|
|
10332
|
-
}
|
|
10333
|
-
// We can pass over low surrogates now as the second component
|
|
10334
|
-
// in a pair which we have already processed
|
|
10335
|
-
return false;
|
|
10336
|
-
};
|
|
10337
|
-
|
|
10338
|
-
var lang_string = /*#__PURE__*/Object.freeze({
|
|
10339
|
-
__proto__: null,
|
|
10340
|
-
capitalize: capitalize,
|
|
10341
|
-
escapeXml: escapeXml,
|
|
10342
|
-
graphemeSplit: graphemeSplit
|
|
10343
|
-
});
|
|
10344
|
-
|
|
10345
10357
|
/**
|
|
10346
10358
|
* @param {Object} prevStyle first style to compare
|
|
10347
10359
|
* @param {Object} thisStyle second style to compare
|
|
@@ -10925,7 +10937,7 @@ class Rect extends FabricObject {
|
|
|
10925
10937
|
rx,
|
|
10926
10938
|
ry
|
|
10927
10939
|
} = this;
|
|
10928
|
-
return ['<rect ', 'COMMON_PARTS', `x="${-width / 2}" y="${-height / 2}" rx="${rx}" ry="${ry}" width="${width}" height="${height}" />\n`];
|
|
10940
|
+
return ['<rect ', 'COMMON_PARTS', `x="${-width / 2}" y="${-height / 2}" rx="${escapeXml(rx)}" ry="${escapeXml(ry)}" width="${escapeXml(width)}" height="${escapeXml(height)}" />\n`];
|
|
10929
10941
|
}
|
|
10930
10942
|
|
|
10931
10943
|
/**
|
|
@@ -11890,7 +11902,7 @@ class Group extends createCollectionMixin(FabricObject) {
|
|
|
11890
11902
|
* @return {String}
|
|
11891
11903
|
*/
|
|
11892
11904
|
getSvgStyles() {
|
|
11893
|
-
const opacity = typeof this.opacity !== 'undefined' && this.opacity !== 1 ? `opacity: ${this.opacity};` : '',
|
|
11905
|
+
const opacity = typeof this.opacity !== 'undefined' && this.opacity !== 1 ? `opacity: ${escapeXml(this.opacity)};` : '',
|
|
11894
11906
|
visibility = this.visible ? '' : ' visibility: hidden;';
|
|
11895
11907
|
return [opacity, this.getSvgFilter(), visibility].join('');
|
|
11896
11908
|
}
|
|
@@ -13844,11 +13856,13 @@ class SelectableCanvas extends StaticCanvas {
|
|
|
13844
13856
|
* Given the control clicked, determine the origin of the transform.
|
|
13845
13857
|
* This is bad because controls can totally have custom names
|
|
13846
13858
|
* should disappear before release 4.0
|
|
13859
|
+
* Fabric 7.1, jan 2026 we are still using this.
|
|
13860
|
+
* Needs to go.
|
|
13847
13861
|
* @private
|
|
13848
13862
|
* @deprecated
|
|
13849
13863
|
*/
|
|
13850
13864
|
_getOriginFromCorner(target, controlName) {
|
|
13851
|
-
const origin = {
|
|
13865
|
+
const origin = controlName ? target.controls[controlName].getTransformAnchorPoint() : {
|
|
13852
13866
|
x: target.originX,
|
|
13853
13867
|
y: target.originY
|
|
13854
13868
|
};
|
|
@@ -13856,6 +13870,9 @@ class SelectableCanvas extends StaticCanvas {
|
|
|
13856
13870
|
return origin;
|
|
13857
13871
|
}
|
|
13858
13872
|
|
|
13873
|
+
// this part down here is deprecated.
|
|
13874
|
+
// It is left to do not change the standard behavior in the middle of a major version
|
|
13875
|
+
// but when possible `getTransformAnchorPoint` will be the only source of truth
|
|
13859
13876
|
// is a left control ?
|
|
13860
13877
|
if (['ml', 'tl', 'bl'].includes(controlName)) {
|
|
13861
13878
|
origin.x = RIGHT;
|
|
@@ -16353,7 +16370,8 @@ class Gradient {
|
|
|
16353
16370
|
}
|
|
16354
16371
|
transform[4] -= offsetX;
|
|
16355
16372
|
transform[5] -= offsetY;
|
|
16356
|
-
const commonAttributes = [`id="SVGID_${this.id}"`, `gradientUnits="${gradientUnits}"`, `gradientTransform="${preTransform ? preTransform + ' ' : ''}${matrixToSVG(transform)}"`, ''].join(' ');
|
|
16373
|
+
const commonAttributes = [`id="SVGID_${escapeXml(String(this.id))}"`, `gradientUnits="${gradientUnits}"`, `gradientTransform="${preTransform ? preTransform + ' ' : ''}${matrixToSVG(transform)}"`, ''].join(' ');
|
|
16374
|
+
const sanitizeCoord = value => parseFloat(String(value));
|
|
16357
16375
|
if (this.type === 'linear') {
|
|
16358
16376
|
const {
|
|
16359
16377
|
x1,
|
|
@@ -16361,7 +16379,11 @@ class Gradient {
|
|
|
16361
16379
|
x2,
|
|
16362
16380
|
y2
|
|
16363
16381
|
} = this.coords;
|
|
16364
|
-
|
|
16382
|
+
const sx1 = sanitizeCoord(x1);
|
|
16383
|
+
const sy1 = sanitizeCoord(y1);
|
|
16384
|
+
const sx2 = sanitizeCoord(x2);
|
|
16385
|
+
const sy2 = sanitizeCoord(y2);
|
|
16386
|
+
markup.push('<linearGradient ', commonAttributes, ' x1="', sx1, '" y1="', sy1, '" x2="', sx2, '" y2="', sy2, '">\n');
|
|
16365
16387
|
} else if (this.type === 'radial') {
|
|
16366
16388
|
const {
|
|
16367
16389
|
x1,
|
|
@@ -16371,9 +16393,15 @@ class Gradient {
|
|
|
16371
16393
|
r1,
|
|
16372
16394
|
r2
|
|
16373
16395
|
} = this.coords;
|
|
16374
|
-
const
|
|
16396
|
+
const sx1 = sanitizeCoord(x1);
|
|
16397
|
+
const sy1 = sanitizeCoord(y1);
|
|
16398
|
+
const sx2 = sanitizeCoord(x2);
|
|
16399
|
+
const sy2 = sanitizeCoord(y2);
|
|
16400
|
+
const sr1 = sanitizeCoord(r1);
|
|
16401
|
+
const sr2 = sanitizeCoord(r2);
|
|
16402
|
+
const needsSwap = sr1 > sr2;
|
|
16375
16403
|
// svg radial gradient has just 1 radius. the biggest.
|
|
16376
|
-
markup.push('<radialGradient ', commonAttributes, ' cx="', needsSwap ?
|
|
16404
|
+
markup.push('<radialGradient ', commonAttributes, ' cx="', needsSwap ? sx1 : sx2, '" cy="', needsSwap ? sy1 : sy2, '" r="', needsSwap ? sr1 : sr2, '" fx="', needsSwap ? sx2 : sx1, '" fy="', needsSwap ? sy2 : sy1, '">\n');
|
|
16377
16405
|
if (needsSwap) {
|
|
16378
16406
|
// svg goes from internal to external radius. if radius are inverted, swap color stops.
|
|
16379
16407
|
colorStops.reverse(); // mutates array
|
|
@@ -16381,16 +16409,17 @@ class Gradient {
|
|
|
16381
16409
|
colorStop.offset = 1 - colorStop.offset;
|
|
16382
16410
|
});
|
|
16383
16411
|
}
|
|
16384
|
-
const minRadius = Math.min(
|
|
16412
|
+
const minRadius = Math.min(sr1, sr2);
|
|
16385
16413
|
if (minRadius > 0) {
|
|
16386
16414
|
// i have to shift all colorStops and add new one in 0.
|
|
16387
|
-
const maxRadius = Math.max(
|
|
16415
|
+
const maxRadius = Math.max(sr1, sr2),
|
|
16388
16416
|
percentageShift = minRadius / maxRadius;
|
|
16389
16417
|
colorStops.forEach(colorStop => {
|
|
16390
16418
|
colorStop.offset += percentageShift * (1 - colorStop.offset);
|
|
16391
16419
|
});
|
|
16392
16420
|
}
|
|
16393
16421
|
}
|
|
16422
|
+
// todo make a malicious script tag injection test with color and also apply a fix with escapeXml
|
|
16394
16423
|
colorStops.forEach(_ref => {
|
|
16395
16424
|
let {
|
|
16396
16425
|
color,
|
|
@@ -16706,7 +16735,7 @@ class Pattern {
|
|
|
16706
16735
|
patternOffsetY = ifNaN(this.offsetY / height, 0),
|
|
16707
16736
|
patternWidth = repeat === 'repeat-y' || repeat === 'no-repeat' ? 1 + Math.abs(patternOffsetX || 0) : ifNaN(patternSource.width / width, 0),
|
|
16708
16737
|
patternHeight = repeat === 'repeat-x' || repeat === 'no-repeat' ? 1 + Math.abs(patternOffsetY || 0) : ifNaN(patternSource.height / height, 0);
|
|
16709
|
-
return [`<pattern id="SVGID_${id}" x="${patternOffsetX}" y="${patternOffsetY}" width="${patternWidth}" height="${patternHeight}">`, `<image x="0" y="0" width="${patternSource.width}" height="${patternSource.height}" xlink:href="${this.sourceToString()}"></image>`, `</pattern>`, ''].join('\n');
|
|
16738
|
+
return [`<pattern id="SVGID_${escapeXml(id)}" x="${patternOffsetX}" y="${patternOffsetY}" width="${patternWidth}" height="${patternHeight}">`, `<image x="0" y="0" width="${patternSource.width}" height="${patternSource.height}" xlink:href="${escapeXml(this.sourceToString())}"></image>`, `</pattern>`, ''].join('\n');
|
|
16710
16739
|
}
|
|
16711
16740
|
/* _TO_SVG_END_ */
|
|
16712
16741
|
|
|
@@ -16988,8 +17017,7 @@ class Path extends FabricObject {
|
|
|
16988
17017
|
* of the instance
|
|
16989
17018
|
*/
|
|
16990
17019
|
_toSVG() {
|
|
16991
|
-
|
|
16992
|
-
return ['<path ', 'COMMON_PARTS', `d="${path}" stroke-linecap="round" />\n`];
|
|
17020
|
+
return ['<path ', 'COMMON_PARTS', `d="${joinPath(this.path, config.NUM_FRACTION_DIGITS)}" stroke-linecap="round" />\n`];
|
|
16993
17021
|
}
|
|
16994
17022
|
|
|
16995
17023
|
/**
|
|
@@ -17540,15 +17568,17 @@ class Circle extends FabricObject {
|
|
|
17540
17568
|
* of the instance
|
|
17541
17569
|
*/
|
|
17542
17570
|
_toSVG() {
|
|
17543
|
-
const
|
|
17571
|
+
const {
|
|
17572
|
+
radius,
|
|
17573
|
+
startAngle,
|
|
17574
|
+
endAngle
|
|
17575
|
+
} = this;
|
|
17576
|
+
const angle = (endAngle - startAngle) % 360;
|
|
17544
17577
|
if (angle === 0) {
|
|
17545
|
-
return ['<circle ', 'COMMON_PARTS', 'cx="0" cy="0" ', 'r="', `${
|
|
17578
|
+
return ['<circle ', 'COMMON_PARTS', 'cx="0" cy="0" ', 'r="', `${escapeXml(radius)}`, '" />\n'];
|
|
17546
17579
|
} else {
|
|
17547
|
-
const
|
|
17548
|
-
|
|
17549
|
-
} = this;
|
|
17550
|
-
const start = degreesToRadians(this.startAngle),
|
|
17551
|
-
end = degreesToRadians(this.endAngle),
|
|
17580
|
+
const start = degreesToRadians(startAngle),
|
|
17581
|
+
end = degreesToRadians(endAngle),
|
|
17552
17582
|
startX = cos(start) * radius,
|
|
17553
17583
|
startY = sin(start) * radius,
|
|
17554
17584
|
endX = cos(end) * radius,
|
|
@@ -18120,17 +18150,13 @@ class Line extends FabricObject {
|
|
|
18120
18150
|
width,
|
|
18121
18151
|
height
|
|
18122
18152
|
} = this;
|
|
18123
|
-
const xMult = _x1 <= _x2 ? -
|
|
18124
|
-
yMult = _y1 <= _y2 ? -
|
|
18125
|
-
x1 = xMult * width / 2,
|
|
18126
|
-
y1 = yMult * height / 2,
|
|
18127
|
-
x2 = xMult * -width / 2,
|
|
18128
|
-
y2 = yMult * -height / 2;
|
|
18153
|
+
const xMult = _x1 <= _x2 ? -0.5 : 0.5,
|
|
18154
|
+
yMult = _y1 <= _y2 ? -0.5 : 0.5;
|
|
18129
18155
|
return {
|
|
18130
|
-
x1,
|
|
18131
|
-
x2,
|
|
18132
|
-
y1,
|
|
18133
|
-
y2
|
|
18156
|
+
x1: xMult * width,
|
|
18157
|
+
x2: xMult * -width,
|
|
18158
|
+
y1: yMult * height,
|
|
18159
|
+
y2: yMult * -height
|
|
18134
18160
|
};
|
|
18135
18161
|
}
|
|
18136
18162
|
|
|
@@ -18348,7 +18374,7 @@ class Ellipse extends FabricObject {
|
|
|
18348
18374
|
* of the instance
|
|
18349
18375
|
*/
|
|
18350
18376
|
_toSVG() {
|
|
18351
|
-
return ['<ellipse ', 'COMMON_PARTS', `cx="0" cy="0" rx="${this.rx}" ry="${this.ry}" />\n`];
|
|
18377
|
+
return ['<ellipse ', 'COMMON_PARTS', `cx="0" cy="0" rx="${escapeXml(this.rx)}" ry="${escapeXml(this.ry)}" />\n`];
|
|
18352
18378
|
}
|
|
18353
18379
|
|
|
18354
18380
|
/**
|
|
@@ -18666,14 +18692,17 @@ class Polyline extends FabricObject {
|
|
|
18666
18692
|
* of the instance
|
|
18667
18693
|
*/
|
|
18668
18694
|
_toSVG() {
|
|
18669
|
-
const
|
|
18670
|
-
diffX = this.pathOffset.x,
|
|
18695
|
+
const diffX = this.pathOffset.x,
|
|
18671
18696
|
diffY = this.pathOffset.y,
|
|
18672
18697
|
NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS;
|
|
18673
|
-
|
|
18674
|
-
|
|
18675
|
-
|
|
18676
|
-
|
|
18698
|
+
const points = this.points.map(_ref2 => {
|
|
18699
|
+
let {
|
|
18700
|
+
x,
|
|
18701
|
+
y
|
|
18702
|
+
} = _ref2;
|
|
18703
|
+
return `${toFixed(x - diffX, NUM_FRACTION_DIGITS)},${toFixed(y - diffY, NUM_FRACTION_DIGITS)}`;
|
|
18704
|
+
}).join(' ');
|
|
18705
|
+
return [`<${escapeXml(this.constructor.type).toLowerCase()} `, 'COMMON_PARTS', `points="${points}" />\n`];
|
|
18677
18706
|
}
|
|
18678
18707
|
|
|
18679
18708
|
/**
|
|
@@ -19097,7 +19126,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
19097
19126
|
} = _ref;
|
|
19098
19127
|
const noShadow = true,
|
|
19099
19128
|
textDecoration = this.getSvgTextDecoration(this);
|
|
19100
|
-
return [textBgRects.join(''), '\t\t<text xml:space="preserve" ', `font-family="${this.fontFamily.replace(dblQuoteRegex, "'")}" `, `font-size="${this.fontSize}" `, this.fontStyle ? `font-style="${this.fontStyle}" ` : '', this.fontWeight ? `font-weight="${this.fontWeight}" ` : '', textDecoration ? `text-decoration="${textDecoration}" ` : '', this.direction === 'rtl' ? `direction="
|
|
19129
|
+
return [textBgRects.join(''), '\t\t<text xml:space="preserve" ', `font-family="${escapeXml(this.fontFamily.replace(dblQuoteRegex, "'"))}" `, `font-size="${escapeXml(this.fontSize)}" `, this.fontStyle ? `font-style="${escapeXml(this.fontStyle)}" ` : '', this.fontWeight ? `font-weight="${escapeXml(this.fontWeight)}" ` : '', textDecoration ? `text-decoration="${textDecoration}" ` : '', this.direction === 'rtl' ? `direction="rtl" ` : '', 'style="', this.getSvgStyles(noShadow), '"', this.addPaintOrder(), ' >', textSpans.join(''), '</text>\n'];
|
|
19101
19130
|
}
|
|
19102
19131
|
|
|
19103
19132
|
/**
|
|
@@ -19113,7 +19142,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
19113
19142
|
lineOffset;
|
|
19114
19143
|
|
|
19115
19144
|
// bounding-box background
|
|
19116
|
-
this.backgroundColor && textBgRects.push(
|
|
19145
|
+
this.backgroundColor && textBgRects.push(createSVGInlineRect(this.backgroundColor, -this.width / 2, -this.height / 2, this.width, this.height));
|
|
19117
19146
|
|
|
19118
19147
|
// text and text-background
|
|
19119
19148
|
for (let i = 0, len = this._textLines.length; i < len; i++) {
|
|
@@ -19221,7 +19250,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
19221
19250
|
} = this.__charBounds[i][j];
|
|
19222
19251
|
currentColor = this.getValueOfPropertyAt(i, j, 'textBackgroundColor');
|
|
19223
19252
|
if (currentColor !== lastColor) {
|
|
19224
|
-
lastColor && textBgRects.push(
|
|
19253
|
+
lastColor && textBgRects.push(createSVGInlineRect(lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine));
|
|
19225
19254
|
boxStart = left;
|
|
19226
19255
|
boxWidth = width;
|
|
19227
19256
|
lastColor = currentColor;
|
|
@@ -19229,7 +19258,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
19229
19258
|
boxWidth += kernedWidth;
|
|
19230
19259
|
}
|
|
19231
19260
|
}
|
|
19232
|
-
currentColor && textBgRects.push(
|
|
19261
|
+
currentColor && textBgRects.push(createSVGInlineRect(lastColor, leftOffset + boxStart, textTopOffset, boxWidth, heightOfLine));
|
|
19233
19262
|
}
|
|
19234
19263
|
|
|
19235
19264
|
/**
|
|
@@ -19267,7 +19296,7 @@ class TextSVGExportMixin extends FabricObjectSVGExportMixin {
|
|
|
19267
19296
|
linethrough: linethrough !== null && linethrough !== void 0 ? linethrough : this.linethrough
|
|
19268
19297
|
});
|
|
19269
19298
|
const thickness = textDecorationThickness || this.textDecorationThickness;
|
|
19270
|
-
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) : '', useWhiteSpace ? 'white-space: pre; ' : ''].join('');
|
|
19299
|
+
return [stroke ? colorPropToSVG(STROKE, stroke) : '', strokeWidth ? `stroke-width: ${escapeXml(strokeWidth)}; ` : '', fontFamily ? `font-family: ${!fontFamily.includes("'") && !fontFamily.includes('"') ? `'${escapeXml(fontFamily)}'` : escapeXml(fontFamily)}; ` : '', fontSize ? `font-size: ${escapeXml(fontSize)}px; ` : '', fontStyle ? `font-style: ${escapeXml(fontStyle)}; ` : '', fontWeight ? `font-weight: ${escapeXml(fontWeight)}; ` : '', textDecoration ? `text-decoration: ${textDecoration}; text-decoration-thickness: ${toFixed(thickness * this.getObjectScaling().y / 10, config.NUM_FRACTION_DIGITS)}%; ` : '', fill ? colorPropToSVG(FILL, fill) : '', useWhiteSpace ? 'white-space: pre; ' : ''].join('');
|
|
19271
19300
|
}
|
|
19272
19301
|
|
|
19273
19302
|
/**
|
|
@@ -24831,13 +24860,13 @@ class FabricImage extends FabricObject {
|
|
|
24831
24860
|
}
|
|
24832
24861
|
if (this.hasCrop()) {
|
|
24833
24862
|
const clipPathId = uid();
|
|
24834
|
-
svgString.push('<clipPath id="imageCrop_' + clipPathId + '">\n', '\t<rect x="' + x + '" y="' + y + '" width="' + this.width + '" height="' + this.height + '" />\n', '</clipPath>\n');
|
|
24863
|
+
svgString.push('<clipPath id="imageCrop_' + clipPathId + '">\n', '\t<rect x="' + x + '" y="' + y + '" width="' + escapeXml(this.width) + '" height="' + escapeXml(this.height) + '" />\n', '</clipPath>\n');
|
|
24835
24864
|
clipPath = ' clip-path="url(#imageCrop_' + clipPathId + ')" ';
|
|
24836
24865
|
}
|
|
24837
24866
|
if (!this.imageSmoothing) {
|
|
24838
24867
|
imageRendering = ' image-rendering="optimizeSpeed"';
|
|
24839
24868
|
}
|
|
24840
|
-
imageMarkup.push('\t<image ', 'COMMON_PARTS', `xlink:href="${this.
|
|
24869
|
+
imageMarkup.push('\t<image ', 'COMMON_PARTS', `xlink:href="${escapeXml(this.getSrc(true))}" x="${x - this.cropX}" y="${y - this.cropY
|
|
24841
24870
|
// we're essentially moving origin of transformation from top/left corner to the center of the shape
|
|
24842
24871
|
// by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left
|
|
24843
24872
|
// so that object's center aligns with container's left/top
|
|
@@ -24845,7 +24874,7 @@ class FabricImage extends FabricObject {
|
|
|
24845
24874
|
if (this.stroke || this.strokeDashArray) {
|
|
24846
24875
|
const origFill = this.fill;
|
|
24847
24876
|
this.fill = null;
|
|
24848
|
-
strokeSvg = [`\t<rect x="${x}" y="${y}" width="${this.width}" height="${this.height}" style="${this.getSvgStyles()}" />\n`];
|
|
24877
|
+
strokeSvg = [`\t<rect x="${x}" y="${y}" width="${escapeXml(this.width)}" height="${escapeXml(this.height)}" style="${this.getSvgStyles()}" />\n`];
|
|
24849
24878
|
this.fill = origFill;
|
|
24850
24879
|
}
|
|
24851
24880
|
if (this.paintFirst !== FILL) {
|